]> git.proxmox.com Git - systemd.git/commitdiff
Merge tag 'upstream/229'
authorMartin Pitt <martin.pitt@ubuntu.com>
Thu, 11 Feb 2016 16:57:20 +0000 (17:57 +0100)
committerMartin Pitt <martin.pitt@ubuntu.com>
Thu, 11 Feb 2016 16:57:20 +0000 (17:57 +0100)
Upstream version 229

1231 files changed:
.dir-locals.el
.editorconfig [new file with mode: 0644]
.gitignore
.vimrc
CODING_STYLE
CONTRIBUTING.md [new file with mode: 0644]
Makefile-man.am
Makefile.am
NEWS
README
README.md
TODO
catalog/systemd.catalog
catalog/systemd.hu.catalog [new file with mode: 0644]
catalog/systemd.ru.catalog
coccinelle/xsprintf.cocci [new file with mode: 0644]
configure.ac
hwdb/20-OUI.hwdb
hwdb/20-bluetooth-vendor-product.hwdb
hwdb/20-pci-vendor-model.hwdb
hwdb/20-usb-vendor-model.hwdb
hwdb/60-evdev.hwdb
hwdb/60-keyboard.hwdb
hwdb/70-mouse.hwdb
hwdb/70-pointingstick.hwdb
m4/attributes.m4
man/.gitignore
man/busctl.xml
man/custom-html.xsl
man/dnssec-trust-anchors.d.xml [new file with mode: 0644]
man/file-hierarchy.xml
man/hostname.xml
man/hostnamectl.xml
man/journal-remote.conf.xml
man/journalctl.xml
man/kernel-command-line.xml
man/logind.conf.xml
man/machine-id.xml
man/machinectl.xml
man/nss-myhostname.xml
man/resolved.conf.xml
man/sd-bus.xml [new file with mode: 0644]
man/sd-daemon.xml
man/sd-event.xml [new file with mode: 0644]
man/sd-journal.xml
man/sd_bus_creds_get_pid.xml
man/sd_bus_creds_new_from_pid.xml
man/sd_bus_new.xml
man/sd_event_add_child.xml
man/sd_event_add_defer.xml
man/sd_event_add_io.xml [new file with mode: 0644]
man/sd_event_add_signal.xml
man/sd_event_add_time.xml
man/sd_event_exit.xml [new file with mode: 0644]
man/sd_event_get_fd.xml
man/sd_event_new.xml
man/sd_event_now.xml [new file with mode: 0644]
man/sd_event_run.xml
man/sd_event_set_name.xml [deleted file]
man/sd_event_set_watchdog.xml [new file with mode: 0644]
man/sd_event_source_get_event.xml [new file with mode: 0644]
man/sd_event_source_get_pending.xml [new file with mode: 0644]
man/sd_event_source_set_description.xml [new file with mode: 0644]
man/sd_event_source_set_enabled.xml [new file with mode: 0644]
man/sd_event_source_set_prepare.xml [new file with mode: 0644]
man/sd_event_source_set_priority.xml [new file with mode: 0644]
man/sd_event_source_set_userdata.xml [new file with mode: 0644]
man/sd_event_source_unref.xml [new file with mode: 0644]
man/sd_event_wait.xml
man/sd_journal_enumerate_fields.xml [new file with mode: 0644]
man/sd_journal_has_runtime_files.xml [new file with mode: 0644]
man/sd_journal_query_unique.xml
man/sd_login_monitor_new.xml
man/sd_notify.xml
man/sd_seat_get_active.xml
man/sd_watchdog_enabled.xml
man/systemctl.xml
man/systemd-activate.xml
man/systemd-ask-password.xml
man/systemd-detect-virt.xml
man/systemd-escape.xml
man/systemd-journal-gatewayd.service.xml
man/systemd-journal-remote.xml
man/systemd-journald.service.xml
man/systemd-nspawn.xml
man/systemd-path.xml
man/systemd-resolve.xml [new file with mode: 0644]
man/systemd-resolved.service.xml
man/systemd-system.conf.xml
man/systemd.exec.xml
man/systemd.generator.xml
man/systemd.mount.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.nspawn.xml
man/systemd.resource-control.xml
man/systemd.service.xml
man/systemd.socket.xml
man/systemd.special.xml
man/systemd.time.xml
man/systemd.timer.xml
man/systemd.unit.xml
man/systemd.xml
man/sysusers.d.xml
man/timesyncd.conf.xml
man/tmpfiles.d.xml
man/udev_device_new_from_syspath.xml
po/el.po
po/es.po
po/hu.po
po/it.po
po/pt_BR.po
po/ru.po
po/sv.po
po/uk.po
po/zh_TW.po
shell-completion/bash/journalctl
shell-completion/bash/loginctl
shell-completion/bash/machinectl
shell-completion/bash/systemctl.in
shell-completion/bash/systemd-nspawn
shell-completion/zsh/_busctl
shell-completion/zsh/_journalctl
shell-completion/zsh/_machinectl
shell-completion/zsh/_systemctl.in
shell-completion/zsh/_systemd
src/ac-power/ac-power.c
src/activate/activate.c
src/analyze/analyze-verify.c
src/analyze/analyze-verify.h
src/analyze/analyze.c
src/ask-password/ask-password.c
src/backlight/backlight.c
src/basic/af-list.c
src/basic/af-list.h
src/basic/alloc-util.c
src/basic/alloc-util.h
src/basic/arphrd-list.c
src/basic/arphrd-list.h
src/basic/async.c
src/basic/async.h
src/basic/audit-util.c
src/basic/audit-util.h
src/basic/barrier.c
src/basic/barrier.h
src/basic/bitmap.c
src/basic/bitmap.h
src/basic/blkid-util.h
src/basic/btrfs-ctree.h
src/basic/btrfs-util.c
src/basic/btrfs-util.h
src/basic/build.h
src/basic/bus-label.c
src/basic/bus-label.h
src/basic/c-rbtree.c [new file with mode: 0644]
src/basic/c-rbtree.h [new file with mode: 0644]
src/basic/calendarspec.c
src/basic/calendarspec.h
src/basic/cap-list.c
src/basic/cap-list.h
src/basic/capability-util.c
src/basic/capability-util.h
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/chattr-util.c
src/basic/chattr-util.h
src/basic/clock-util.c
src/basic/clock-util.h
src/basic/conf-files.c
src/basic/conf-files.h
src/basic/copy.c
src/basic/copy.h
src/basic/cpu-set-util.c
src/basic/cpu-set-util.h
src/basic/def.h
src/basic/device-nodes.c
src/basic/device-nodes.h
src/basic/dirent-util.c
src/basic/dirent-util.h
src/basic/env-util.c
src/basic/env-util.h
src/basic/errno-list.c
src/basic/errno-list.h
src/basic/escape.c
src/basic/escape.h
src/basic/ether-addr-util.c
src/basic/ether-addr-util.h
src/basic/exit-status.c
src/basic/exit-status.h
src/basic/extract-word.c
src/basic/extract-word.h
src/basic/fd-util.c
src/basic/fd-util.h
src/basic/fdset.c
src/basic/fdset.h
src/basic/fileio-label.c
src/basic/fileio-label.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/glob-util.c
src/basic/glob-util.h
src/basic/gunicode.c
src/basic/gunicode.h
src/basic/hash-funcs.c [new file with mode: 0644]
src/basic/hash-funcs.h [new file with mode: 0644]
src/basic/hashmap.c
src/basic/hashmap.h
src/basic/hexdecoct.c
src/basic/hexdecoct.h
src/basic/hostname-util.c
src/basic/hostname-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/io-util.c
src/basic/io-util.h
src/basic/ioprio.h
src/basic/json.c
src/basic/json.h
src/basic/label.c
src/basic/label.h
src/basic/list.h
src/basic/locale-util.c
src/basic/locale-util.h
src/basic/lockfile-util.c
src/basic/lockfile-util.h
src/basic/log.c
src/basic/log.h
src/basic/login-util.c
src/basic/login-util.h
src/basic/macro.h
src/basic/memfd-util.c
src/basic/memfd-util.h
src/basic/mempool.c
src/basic/mempool.h
src/basic/missing.h
src/basic/mkdir-label.c
src/basic/mkdir.c
src/basic/mkdir.h
src/basic/mount-util.c
src/basic/mount-util.h
src/basic/nss-util.h [new file with mode: 0644]
src/basic/ordered-set.c [new file with mode: 0644]
src/basic/ordered-set.h
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/path-util.c
src/basic/path-util.h
src/basic/prioq.c
src/basic/prioq.h
src/basic/proc-cmdline.c
src/basic/proc-cmdline.h
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/random-util.h
src/basic/ratelimit.c
src/basic/ratelimit.h
src/basic/refcnt.h
src/basic/replace-var.c
src/basic/replace-var.h
src/basic/rlimit-util.c
src/basic/rlimit-util.h
src/basic/rm-rf.c
src/basic/rm-rf.h
src/basic/selinux-util.c
src/basic/selinux-util.h
src/basic/set.h
src/basic/sigbus.c
src/basic/sigbus.h
src/basic/signal-util.c
src/basic/signal-util.h
src/basic/siphash24.c
src/basic/siphash24.h
src/basic/smack-util.c
src/basic/smack-util.h
src/basic/socket-label.c
src/basic/socket-util.c
src/basic/socket-util.h
src/basic/special.h
src/basic/stat-util.c
src/basic/stat-util.h
src/basic/stdio-util.h
src/basic/strbuf.c
src/basic/strbuf.h
src/basic/string-table.c
src/basic/string-table.h
src/basic/string-util.c
src/basic/string-util.h
src/basic/strv.c
src/basic/strv.h
src/basic/strxcpyx.c
src/basic/strxcpyx.h
src/basic/syslog-util.c
src/basic/syslog-util.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/time-util.c
src/basic/time-util.h
src/basic/umask-util.h
src/basic/unaligned.h
src/basic/unit-name.c
src/basic/unit-name.h
src/basic/user-util.c
src/basic/user-util.h
src/basic/utf8.c
src/basic/utf8.h
src/basic/util.c
src/basic/util.h
src/basic/verbs.c
src/basic/verbs.h
src/basic/virt.c
src/basic/virt.h
src/basic/web-util.c
src/basic/web-util.h
src/basic/xattr-util.c
src/basic/xattr-util.h
src/basic/xml.c
src/basic/xml.h
src/binfmt/binfmt.c
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/console.c
src/boot/efi/console.h
src/boot/efi/disk.c
src/boot/efi/disk.h
src/boot/efi/graphics.c
src/boot/efi/graphics.h
src/boot/efi/linux.c
src/boot/efi/linux.h
src/boot/efi/pefile.c
src/boot/efi/pefile.h
src/boot/efi/splash.c
src/boot/efi/splash.h
src/boot/efi/stub.c
src/boot/efi/util.c
src/boot/efi/util.h
src/bootchart/bootchart.c
src/bootchart/bootchart.h
src/bootchart/store.c
src/bootchart/store.h
src/bootchart/svg.c
src/bootchart/svg.h
src/bus-proxyd/bus-proxyd.c
src/bus-proxyd/bus-xml-policy.c
src/bus-proxyd/bus-xml-policy.h
src/bus-proxyd/driver.c
src/bus-proxyd/driver.h
src/bus-proxyd/proxy.c
src/bus-proxyd/proxy.h
src/bus-proxyd/stdio-bridge.c
src/bus-proxyd/synthesize.c
src/bus-proxyd/synthesize.h
src/bus-proxyd/test-bus-xml-policy.c
src/cgls/cgls.c
src/cgroups-agent/cgroups-agent.c
src/cgtop/cgtop.c
src/core/audit-fd.c
src/core/audit-fd.h
src/core/automount.c
src/core/automount.h
src/core/bus-endpoint.h
src/core/bus-policy.h
src/core/busname.c
src/core/busname.h
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-automount.c
src/core/dbus-automount.h
src/core/dbus-busname.c
src/core/dbus-busname.h
src/core/dbus-cgroup.c
src/core/dbus-cgroup.h
src/core/dbus-device.c
src/core/dbus-device.h
src/core/dbus-execute.c
src/core/dbus-execute.h
src/core/dbus-job.c
src/core/dbus-job.h
src/core/dbus-kill.c
src/core/dbus-kill.h
src/core/dbus-manager.c
src/core/dbus-manager.h
src/core/dbus-mount.c
src/core/dbus-mount.h
src/core/dbus-path.c
src/core/dbus-path.h
src/core/dbus-scope.c
src/core/dbus-scope.h
src/core/dbus-service.c
src/core/dbus-service.h
src/core/dbus-slice.c
src/core/dbus-slice.h
src/core/dbus-socket.c
src/core/dbus-socket.h
src/core/dbus-swap.c
src/core/dbus-swap.h
src/core/dbus-target.c
src/core/dbus-target.h
src/core/dbus-timer.c
src/core/dbus-timer.h
src/core/dbus-unit.c
src/core/dbus-unit.h
src/core/dbus.c
src/core/dbus.h
src/core/device.c
src/core/device.h
src/core/execute.c
src/core/execute.h
src/core/failure-action.c
src/core/failure-action.h
src/core/hostname-setup.c
src/core/hostname-setup.h
src/core/ima-setup.c
src/core/ima-setup.h
src/core/job.c
src/core/job.h
src/core/kill.c
src/core/kill.h
src/core/killall.c
src/core/killall.h
src/core/kmod-setup.c
src/core/kmod-setup.h
src/core/load-dropin.c
src/core/load-dropin.h
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/core/locale-setup.c
src/core/locale-setup.h
src/core/loopback-setup.c
src/core/loopback-setup.h
src/core/machine-id-setup.c
src/core/machine-id-setup.h
src/core/macros.systemd.in
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/mount-setup.c
src/core/mount-setup.h
src/core/mount.c
src/core/mount.h
src/core/namespace.c
src/core/namespace.h
src/core/path.c
src/core/path.h
src/core/scope.c
src/core/scope.h
src/core/selinux-access.c
src/core/selinux-access.h
src/core/selinux-setup.c
src/core/selinux-setup.h
src/core/service.c
src/core/service.h
src/core/show-status.c
src/core/show-status.h
src/core/shutdown.c
src/core/slice.c
src/core/slice.h
src/core/smack-setup.c
src/core/smack-setup.h
src/core/socket.c
src/core/socket.h
src/core/swap.c
src/core/swap.h
src/core/target.c
src/core/target.h
src/core/timer.c
src/core/timer.h
src/core/transaction.c
src/core/transaction.h
src/core/triggers.systemd.in
src/core/umount.c
src/core/umount.h
src/core/unit-printf.c
src/core/unit-printf.h
src/core/unit.c
src/core/unit.h
src/coredump/Makefile [new symlink]
src/coredump/coredump-vacuum.c [new file with mode: 0644]
src/coredump/coredump-vacuum.h [new file with mode: 0644]
src/coredump/coredump.c [new file with mode: 0644]
src/coredump/coredump.conf [new file with mode: 0644]
src/coredump/coredumpctl.c [new file with mode: 0644]
src/coredump/stacktrace.c [new file with mode: 0644]
src/coredump/stacktrace.h [new file with mode: 0644]
src/coredump/test-coredump-vacuum.c [new file with mode: 0644]
src/cryptsetup/cryptsetup-generator.c
src/cryptsetup/cryptsetup.c
src/dbus1-generator/dbus1-generator.c
src/debug-generator/debug-generator.c
src/delta/delta.c
src/detect-virt/detect-virt.c
src/escape/escape.c
src/firstboot/firstboot.c
src/fsck/fsck.c
src/fstab-generator/fstab-generator.c
src/getty-generator/getty-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/hibernate-resume/hibernate-resume-generator.c
src/hibernate-resume/hibernate-resume.c
src/hostname/hostnamectl.c
src/hostname/hostnamed.c
src/hwdb/hwdb.c
src/import/aufs-util.c
src/import/aufs-util.h
src/import/curl-util.c
src/import/curl-util.h
src/import/export-raw.c
src/import/export-raw.h
src/import/export-tar.c
src/import/export-tar.h
src/import/export.c
src/import/import-common.c
src/import/import-common.h
src/import/import-compress.c
src/import/import-compress.h
src/import/import-raw.c
src/import/import-raw.h
src/import/import-tar.c
src/import/import-tar.h
src/import/import.c
src/import/importd.c
src/import/org.freedesktop.import1.conf
src/import/pull-common.c
src/import/pull-common.h
src/import/pull-dkr.c [deleted file]
src/import/pull-dkr.h [deleted file]
src/import/pull-job.c
src/import/pull-job.h
src/import/pull-raw.c
src/import/pull-raw.h
src/import/pull-tar.c
src/import/pull-tar.h
src/import/pull.c
src/import/qcow2-util.c
src/import/qcow2-util.h
src/import/test-qcow2.c
src/initctl/initctl.c
src/journal-remote/journal-gatewayd.c
src/journal-remote/journal-remote-parse.c
src/journal-remote/journal-remote-parse.h
src/journal-remote/journal-remote-write.c
src/journal-remote/journal-remote-write.h
src/journal-remote/journal-remote.c
src/journal-remote/journal-remote.conf.in
src/journal-remote/journal-remote.h
src/journal-remote/journal-upload-journal.c
src/journal-remote/journal-upload.c
src/journal-remote/journal-upload.h
src/journal-remote/microhttpd-util.c
src/journal-remote/microhttpd-util.h
src/journal/audit-type.c
src/journal/audit-type.h
src/journal/cat.c
src/journal/catalog.c
src/journal/catalog.h
src/journal/compress.c
src/journal/compress.h
src/journal/coredump-vacuum.c [deleted file]
src/journal/coredump-vacuum.h [deleted file]
src/journal/coredump.c [deleted file]
src/journal/coredump.conf [deleted file]
src/journal/coredumpctl.c [deleted file]
src/journal/fsprg.c
src/journal/fsprg.h
src/journal/journal-authenticate.c
src/journal/journal-authenticate.h
src/journal/journal-def.h
src/journal/journal-file.c
src/journal/journal-file.h
src/journal/journal-internal.h
src/journal/journal-qrcode.c
src/journal/journal-qrcode.h
src/journal/journal-send.c
src/journal/journal-vacuum.c
src/journal/journal-vacuum.h
src/journal/journal-verify.c
src/journal/journal-verify.h
src/journal/journalctl.c
src/journal/journald-audit.c
src/journal/journald-audit.h
src/journal/journald-console.c
src/journal/journald-console.h
src/journal/journald-kmsg.c
src/journal/journald-kmsg.h
src/journal/journald-native.c
src/journal/journald-native.h
src/journal/journald-rate-limit.c
src/journal/journald-rate-limit.h
src/journal/journald-server.c
src/journal/journald-server.h
src/journal/journald-stream.c
src/journal/journald-stream.h
src/journal/journald-syslog.c
src/journal/journald-syslog.h
src/journal/journald-wall.c
src/journal/journald-wall.h
src/journal/journald.c
src/journal/lookup3.h
src/journal/mmap-cache.c
src/journal/mmap-cache.h
src/journal/sd-journal.c
src/journal/stacktrace.c [deleted file]
src/journal/stacktrace.h [deleted file]
src/journal/test-audit-type.c
src/journal/test-catalog.c
src/journal/test-compress-benchmark.c
src/journal/test-compress.c
src/journal/test-coredump-vacuum.c [deleted file]
src/journal/test-journal-enum.c
src/journal/test-journal-flush.c
src/journal/test-journal-init.c
src/journal/test-journal-interleaving.c
src/journal/test-journal-match.c
src/journal/test-journal-send.c
src/journal/test-journal-stream.c
src/journal/test-journal-syslog.c
src/journal/test-journal-verify.c
src/journal/test-journal.c
src/journal/test-mmap-cache.c
src/libsystemd-network/arp-util.h
src/libsystemd-network/dhcp-identifier.c
src/libsystemd-network/dhcp-identifier.h
src/libsystemd-network/dhcp-internal.h
src/libsystemd-network/dhcp-lease-internal.h
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-packet.c
src/libsystemd-network/dhcp-protocol.h
src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/dhcp6-internal.h
src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/dhcp6-protocol.h
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/icmp6-util.h
src/libsystemd-network/lldp-internal.c
src/libsystemd-network/lldp-internal.h
src/libsystemd-network/lldp-network.c
src/libsystemd-network/lldp-network.h
src/libsystemd-network/lldp-port.c
src/libsystemd-network/lldp-port.h
src/libsystemd-network/lldp-tlv.c
src/libsystemd-network/lldp-tlv.h
src/libsystemd-network/lldp-util.h [deleted file]
src/libsystemd-network/lldp.h
src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
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-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/libsystemd-network/sd-ipv4acd.c
src/libsystemd-network/sd-ipv4ll.c
src/libsystemd-network/sd-lldp.c
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/test-acd.c
src/libsystemd-network/test-dhcp-client.c
src/libsystemd-network/test-dhcp-option.c
src/libsystemd-network/test-dhcp-server.c
src/libsystemd-network/test-dhcp6-client.c
src/libsystemd-network/test-ipv4ll-manual.c
src/libsystemd-network/test-ipv4ll.c
src/libsystemd-network/test-lldp.c
src/libsystemd-network/test-ndisc-rs.c
src/libsystemd/libsystemd.sym
src/libsystemd/sd-bus/bus-bloom.c
src/libsystemd/sd-bus/bus-bloom.h
src/libsystemd/sd-bus/bus-common-errors.c
src/libsystemd/sd-bus/bus-common-errors.h
src/libsystemd/sd-bus/bus-container.c
src/libsystemd/sd-bus/bus-container.h
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-control.h
src/libsystemd/sd-bus/bus-convenience.c
src/libsystemd/sd-bus/bus-creds.c
src/libsystemd/sd-bus/bus-creds.h
src/libsystemd/sd-bus/bus-dump.c
src/libsystemd/sd-bus/bus-dump.h
src/libsystemd/sd-bus/bus-error.c
src/libsystemd/sd-bus/bus-error.h
src/libsystemd/sd-bus/bus-gvariant.c
src/libsystemd/sd-bus/bus-gvariant.h
src/libsystemd/sd-bus/bus-internal.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-introspect.c
src/libsystemd/sd-bus/bus-introspect.h
src/libsystemd/sd-bus/bus-kernel.c
src/libsystemd/sd-bus/bus-kernel.h
src/libsystemd/sd-bus/bus-match.c
src/libsystemd/sd-bus/bus-match.h
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-objects.h
src/libsystemd/sd-bus/bus-protocol.h
src/libsystemd/sd-bus/bus-signature.c
src/libsystemd/sd-bus/bus-signature.h
src/libsystemd/sd-bus/bus-slot.c
src/libsystemd/sd-bus/bus-slot.h
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/bus-socket.h
src/libsystemd/sd-bus/bus-track.c
src/libsystemd/sd-bus/bus-track.h
src/libsystemd/sd-bus/bus-type.c
src/libsystemd/sd-bus/bus-type.h
src/libsystemd/sd-bus/busctl-introspect.c
src/libsystemd/sd-bus/busctl-introspect.h
src/libsystemd/sd-bus/busctl.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-benchmark.c
src/libsystemd/sd-bus/test-bus-chat.c
src/libsystemd/sd-bus/test-bus-cleanup.c
src/libsystemd/sd-bus/test-bus-creds.c
src/libsystemd/sd-bus/test-bus-error.c
src/libsystemd/sd-bus/test-bus-gvariant.c
src/libsystemd/sd-bus/test-bus-introspect.c
src/libsystemd/sd-bus/test-bus-kernel-bloom.c
src/libsystemd/sd-bus/test-bus-kernel.c
src/libsystemd/sd-bus/test-bus-marshal.c
src/libsystemd/sd-bus/test-bus-match.c
src/libsystemd/sd-bus/test-bus-objects.c
src/libsystemd/sd-bus/test-bus-proxy.c
src/libsystemd/sd-bus/test-bus-server.c
src/libsystemd/sd-bus/test-bus-signature.c
src/libsystemd/sd-bus/test-bus-zero-copy.c
src/libsystemd/sd-daemon/sd-daemon.c
src/libsystemd/sd-device/device-enumerator-private.h
src/libsystemd/sd-device/device-enumerator.c
src/libsystemd/sd-device/device-private.c
src/libsystemd/sd-device/device-private.h
src/libsystemd/sd-device/device-util.h
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-event/event-util.h [deleted file]
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-event/test-event.c
src/libsystemd/sd-hwdb/hwdb-util.h
src/libsystemd/sd-hwdb/sd-hwdb.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/local-addresses.c
src/libsystemd/sd-netlink/local-addresses.h
src/libsystemd/sd-netlink/netlink-internal.h
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-socket.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/libsystemd/sd-netlink/sd-netlink.c
src/libsystemd/sd-netlink/test-local-addresses.c
src/libsystemd/sd-netlink/test-netlink.c
src/libsystemd/sd-network/network-util.c
src/libsystemd/sd-network/network-util.h
src/libsystemd/sd-network/sd-network.c
src/libsystemd/sd-resolve/resolve-util.h [deleted file]
src/libsystemd/sd-resolve/sd-resolve.c
src/libsystemd/sd-resolve/test-resolve.c
src/libsystemd/sd-utf8/sd-utf8.c
src/libudev/libudev-device-private.c
src/libudev/libudev-enumerate.c
src/libudev/libudev-hwdb.c
src/libudev/libudev-private.h
src/locale/localectl.c
src/locale/localed.c
src/login/inhibit.c
src/login/loginctl.c
src/login/logind-acl.c
src/login/logind-acl.h
src/login/logind-action.c
src/login/logind-action.h
src/login/logind-button.c
src/login/logind-button.h
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-device.c
src/login/logind-device.h
src/login/logind-inhibit.c
src/login/logind-inhibit.h
src/login/logind-seat-dbus.c
src/login/logind-seat.c
src/login/logind-seat.h
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-user-dbus.c
src/login/logind-user.c
src/login/logind-user.h
src/login/logind-utmp.c
src/login/logind.c
src/login/logind.conf
src/login/logind.h
src/login/pam_systemd.c
src/login/sysfs-show.c
src/login/sysfs-show.h
src/login/test-inhibit.c
src/login/test-login-shared.c
src/machine-id-setup/machine-id-setup-main.c
src/machine/image-dbus.c
src/machine/image-dbus.h
src/machine/machine-dbus.c
src/machine/machine-dbus.h
src/machine/machine.c
src/machine/machine.h
src/machine/machinectl.c
src/machine/machined-dbus.c
src/machine/machined.c
src/machine/machined.h
src/modules-load/modules-load.c
src/network/networkctl.c
src/network/networkd-address-pool.c
src/network/networkd-address-pool.h
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-fdb.c
src/network/networkd-fdb.h
src/network/networkd-ipv4ll.c
src/network/networkd-link-bus.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager-bus.c
src/network/networkd-manager.c
src/network/networkd-ndisc.c
src/network/networkd-netdev-bond.c
src/network/networkd-netdev-bond.h
src/network/networkd-netdev-bridge.c
src/network/networkd-netdev-bridge.h
src/network/networkd-netdev-dummy.c
src/network/networkd-netdev-dummy.h
src/network/networkd-netdev-gperf.gperf
src/network/networkd-netdev-ipvlan.c
src/network/networkd-netdev-ipvlan.h
src/network/networkd-netdev-macvlan.c
src/network/networkd-netdev-macvlan.h
src/network/networkd-netdev-tunnel.c
src/network/networkd-netdev-tunnel.h
src/network/networkd-netdev-tuntap.c
src/network/networkd-netdev-tuntap.h
src/network/networkd-netdev-veth.c
src/network/networkd-netdev-veth.h
src/network/networkd-netdev-vlan.c
src/network/networkd-netdev-vlan.h
src/network/networkd-netdev-vxlan.c
src/network/networkd-netdev-vxlan.h
src/network/networkd-netdev.c
src/network/networkd-netdev.h
src/network/networkd-network-bus.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-util.c
src/network/networkd-util.h
src/network/networkd-wait-online-link.c
src/network/networkd-wait-online-link.h
src/network/networkd-wait-online-manager.c
src/network/networkd-wait-online.h
src/network/networkd.c
src/network/networkd.h
src/network/test-network.c
src/notify/notify.c
src/nspawn/nspawn-cgroup.c
src/nspawn/nspawn-cgroup.h
src/nspawn/nspawn-expose-ports.c
src/nspawn/nspawn-expose-ports.h
src/nspawn/nspawn-gperf.gperf
src/nspawn/nspawn-mount.c
src/nspawn/nspawn-mount.h
src/nspawn/nspawn-network.c
src/nspawn/nspawn-network.h
src/nspawn/nspawn-register.c
src/nspawn/nspawn-register.h
src/nspawn/nspawn-settings.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn-setuid.c
src/nspawn/nspawn-setuid.h
src/nspawn/nspawn-stub-pid1.c [new file with mode: 0644]
src/nspawn/nspawn-stub-pid1.h [new file with mode: 0644]
src/nspawn/nspawn.c
src/nss-myhostname/nss-myhostname.c
src/nss-mymachines/nss-mymachines.c
src/nss-resolve/nss-resolve.c
src/path/path.c
src/quotacheck/quotacheck.c
src/random-seed/random-seed.c
src/rc-local-generator/rc-local-generator.c
src/remount-fs/remount-fs.c
src/reply-password/reply-password.c
src/resolve-host/Makefile [deleted symlink]
src/resolve-host/resolve-host.c [deleted file]
src/resolve/RFCs [new file with mode: 0644]
src/resolve/dns-type.c
src/resolve/dns-type.h
src/resolve/resolve-tool.c [new file with mode: 0644]
src/resolve/resolved-bus.c
src/resolve/resolved-bus.h
src/resolve/resolved-conf.c
src/resolve/resolved-conf.h
src/resolve/resolved-def.h
src/resolve/resolved-dns-answer.c
src/resolve/resolved-dns-answer.h
src/resolve/resolved-dns-cache.c
src/resolve/resolved-dns-cache.h
src/resolve/resolved-dns-dnssec.c [new file with mode: 0644]
src/resolve/resolved-dns-dnssec.h [new file with mode: 0644]
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-query.c
src/resolve/resolved-dns-query.h
src/resolve/resolved-dns-question.c
src/resolve/resolved-dns-question.h
src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-scope.h
src/resolve/resolved-dns-search-domain.c [new file with mode: 0644]
src/resolve/resolved-dns-search-domain.h [new file with mode: 0644]
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-dns-stream.c
src/resolve/resolved-dns-stream.h
src/resolve/resolved-dns-synthesize.c [new file with mode: 0644]
src/resolve/resolved-dns-synthesize.h [new file with mode: 0644]
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-transaction.h
src/resolve/resolved-dns-trust-anchor.c [new file with mode: 0644]
src/resolve/resolved-dns-trust-anchor.h [new file with mode: 0644]
src/resolve/resolved-dns-zone.c
src/resolve/resolved-dns-zone.h
src/resolve/resolved-etc-hosts.c [new file with mode: 0644]
src/resolve/resolved-etc-hosts.h [new file with mode: 0644]
src/resolve/resolved-gperf.gperf
src/resolve/resolved-link-bus.c [new file with mode: 0644]
src/resolve/resolved-link-bus.h [new file with mode: 0644]
src/resolve/resolved-link.c
src/resolve/resolved-link.h
src/resolve/resolved-llmnr.c
src/resolve/resolved-llmnr.h
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/resolve/resolved-mdns.c [new file with mode: 0644]
src/resolve/resolved-mdns.h [new file with mode: 0644]
src/resolve/resolved-resolv-conf.c [new file with mode: 0644]
src/resolve/resolved-resolv-conf.h [new file with mode: 0644]
src/resolve/resolved.c
src/resolve/resolved.conf.in
src/resolve/test-dnssec-complex.c [new file with mode: 0644]
src/resolve/test-dnssec.c [new file with mode: 0644]
src/resolve/test-resolve-tables.c [new file with mode: 0644]
src/rfkill/rfkill.c
src/run/run.c
src/shared/acl-util.c
src/shared/acl-util.h
src/shared/acpi-fpdt.c
src/shared/acpi-fpdt.h
src/shared/apparmor-util.c
src/shared/apparmor-util.h
src/shared/architecture.c
src/shared/architecture.h
src/shared/ask-password-api.c
src/shared/ask-password-api.h
src/shared/base-filesystem.c
src/shared/base-filesystem.h
src/shared/boot-timestamps.c
src/shared/boot-timestamps.h
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/cgroup-show.c
src/shared/cgroup-show.h
src/shared/clean-ipc.c
src/shared/clean-ipc.h
src/shared/condition.c
src/shared/condition.h
src/shared/conf-parser.c
src/shared/conf-parser.h
src/shared/dev-setup.c
src/shared/dev-setup.h
src/shared/dns-domain.c
src/shared/dns-domain.h
src/shared/dropin.c
src/shared/dropin.h
src/shared/efivars.c
src/shared/efivars.h
src/shared/firewall-util.c
src/shared/firewall-util.h
src/shared/fstab-util.c
src/shared/fstab-util.h
src/shared/generator.c
src/shared/generator.h
src/shared/gpt.h
src/shared/ima-util.c
src/shared/ima-util.h
src/shared/import-util.c
src/shared/import-util.h
src/shared/install-printf.c
src/shared/install-printf.h
src/shared/install.c
src/shared/install.h
src/shared/logs-show.c
src/shared/logs-show.h
src/shared/machine-image.c
src/shared/machine-image.h
src/shared/machine-pool.c
src/shared/machine-pool.h
src/shared/nss-util.h [deleted file]
src/shared/output-mode.h
src/shared/pager.c
src/shared/pager.h
src/shared/path-lookup.c
src/shared/path-lookup.h
src/shared/ptyfwd.c
src/shared/ptyfwd.h
src/shared/resolve-util.c [new file with mode: 0644]
src/shared/resolve-util.h [new file with mode: 0644]
src/shared/seccomp-util.c
src/shared/seccomp-util.h
src/shared/sleep-config.c
src/shared/sleep-config.h
src/shared/spawn-ask-password-agent.c
src/shared/spawn-ask-password-agent.h
src/shared/spawn-polkit-agent.c
src/shared/spawn-polkit-agent.h
src/shared/specifier.c
src/shared/specifier.h
src/shared/switch-root.c
src/shared/switch-root.h
src/shared/sysctl-util.c
src/shared/sysctl-util.h
src/shared/test-tables.h
src/shared/udev-util.h
src/shared/uid-range.c
src/shared/uid-range.h
src/shared/utmp-wtmp.c
src/shared/utmp-wtmp.h
src/shared/watchdog.c
src/shared/watchdog.h
src/sleep/sleep.c
src/socket-proxy/socket-proxyd.c
src/sysctl/sysctl.c
src/system-update-generator/system-update-generator.c
src/systemctl/systemctl.c
src/systemd/_sd-common.h
src/systemd/sd-bus-protocol.h
src/systemd/sd-bus-vtable.h
src/systemd/sd-bus.h
src/systemd/sd-daemon.h
src/systemd/sd-device.h
src/systemd/sd-dhcp-client.h
src/systemd/sd-dhcp-lease.h
src/systemd/sd-dhcp-server.h
src/systemd/sd-dhcp6-client.h
src/systemd/sd-dhcp6-lease.h
src/systemd/sd-event.h
src/systemd/sd-hwdb.h
src/systemd/sd-id128.h
src/systemd/sd-ipv4acd.h
src/systemd/sd-ipv4ll.h
src/systemd/sd-journal.h
src/systemd/sd-lldp.h
src/systemd/sd-login.h
src/systemd/sd-messages.h
src/systemd/sd-ndisc.h
src/systemd/sd-netlink.h
src/systemd/sd-network.h
src/systemd/sd-path.h
src/systemd/sd-resolve.h
src/systemd/sd-utf8.h
src/sysusers/sysusers.c
src/sysv-generator/sysv-generator.c
src/test/test-acl-util.c [new file with mode: 0644]
src/test/test-architecture.c
src/test/test-ask-password-api.c [new file with mode: 0644]
src/test/test-barrier.c
src/test/test-boot-timestamps.c
src/test/test-btrfs.c
src/test/test-calendarspec.c
src/test/test-cap-list.c
src/test/test-capability.c
src/test/test-cgroup-mask.c
src/test/test-cgroup-util.c
src/test/test-cgroup.c
src/test/test-condition.c
src/test/test-conf-files.c
src/test/test-daemon.c
src/test/test-date.c
src/test/test-device-nodes.c
src/test/test-dns-domain.c
src/test/test-ellipsize.c
src/test/test-engine.c
src/test/test-env-replace.c
src/test/test-execute.c
src/test/test-extract-word.c
src/test/test-fileio.c
src/test/test-firewall-util.c
src/test/test-fstab-util.c
src/test/test-helper.h
src/test/test-hostname-util.c
src/test/test-hostname.c
src/test/test-id128.c
src/test/test-install-root.c
src/test/test-install.c
src/test/test-ipcrm.c
src/test/test-job-type.c
src/test/test-json.c
src/test/test-libudev.c
src/test/test-log.c
src/test/test-loopback.c
src/test/test-namespace.c
src/test/test-netlink-manual.c
src/test/test-ns.c
src/test/test-parse-util.c
src/test/test-path-lookup.c
src/test/test-path-util.c
src/test/test-path.c
src/test/test-prioq.c
src/test/test-rbtree.c [new file with mode: 0644]
src/test/test-replace-var.c
src/test/test-rlimit-util.c [new file with mode: 0644]
src/test/test-sched-prio.c
src/test/test-sigbus.c
src/test/test-signal-util.c [new file with mode: 0644]
src/test/test-siphash24.c
src/test/test-sleep.c
src/test/test-strbuf.c
src/test/test-string-util.c
src/test/test-strip-tab-ansi.c
src/test/test-strv.c
src/test/test-strxcpyx.c
src/test/test-time.c
src/test/test-tmpfiles.c
src/test/test-uid-range.c
src/test/test-unit-file.c
src/test/test-unit-name.c
src/test/test-user-util.c
src/test/test-utf8.c
src/test/test-util.c
src/test/test-watchdog.c
src/test/test-xml.c
src/timedate/timedatectl.c
src/timedate/timedated.c
src/timesync/timesyncd-conf.c
src/timesync/timesyncd-conf.h
src/timesync/timesyncd-manager.c
src/timesync/timesyncd-manager.h
src/timesync/timesyncd-server.c
src/timesync/timesyncd-server.h
src/timesync/timesyncd.c
src/tmpfiles/tmpfiles.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/udev/collect/collect.c
src/udev/net/ethtool-util.c
src/udev/net/ethtool-util.h
src/udev/net/link-config.c
src/udev/net/link-config.h
src/udev/scsi_id/scsi.h
src/udev/scsi_id/scsi_serial.c
src/udev/udev-builtin-blkid.c
src/udev/udev-builtin-input_id.c
src/udev/udev-builtin-net_id.c
src/udev/udev-builtin-net_setup_link.c
src/udev/udev-builtin-path_id.c
src/udev/udev-event.c
src/udev/udev-node.c
src/udev/udev-watch.c
src/udev/udevadm-hwdb.c
src/udev/udevadm.c
src/udev/udevd.c
src/update-done/update-done.c
src/update-utmp/update-utmp.c
src/user-sessions/user-sessions.c
src/vconsole/vconsole-setup.c
sysctl.d/50-coredump.conf.in
sysusers.d/.gitignore
sysusers.d/basic.conf.in
sysusers.d/systemd-remote.conf [deleted file]
sysusers.d/systemd-remote.conf.m4 [new file with mode: 0644]
sysusers.d/systemd.conf.m4
test/README.testsuite
test/TEST-01-BASIC/test.sh
test/TEST-02-CRYPTSETUP/test.sh
test/TEST-03-JOBS/test-jobs.sh
test/TEST-03-JOBS/test.sh
test/TEST-04-JOURNAL/Makefile [new symlink]
test/TEST-04-JOURNAL/test-journal.sh [new file with mode: 0755]
test/TEST-04-JOURNAL/test.sh [new file with mode: 0755]
test/TEST-05-RLIMITS/Makefile [new symlink]
test/TEST-05-RLIMITS/test-rlimits.sh [new file with mode: 0755]
test/TEST-05-RLIMITS/test.sh [new file with mode: 0755]
test/TEST-06-SELINUX/Makefile [new file with mode: 0644]
test/TEST-06-SELINUX/systemd_test.if [new file with mode: 0644]
test/TEST-06-SELINUX/systemd_test.te [new file with mode: 0644]
test/TEST-06-SELINUX/test-selinux-checks.sh [new file with mode: 0755]
test/TEST-06-SELINUX/test.sh [new file with mode: 0755]
test/TEST-07-ISSUE-1981/Makefile [new symlink]
test/TEST-07-ISSUE-1981/test-segfault.sh [new file with mode: 0755]
test/TEST-07-ISSUE-1981/test.sh [new file with mode: 0755]
test/networkd-test.py [new file with mode: 0755]
test/sys.tar.xz
test/sysv-generator-test.py
test/test-execute/exec-capabilityambientset-merge.service [new file with mode: 0644]
test/test-execute/exec-capabilityambientset.service [new file with mode: 0644]
test/test-functions
test/udev-test.pl
tmpfiles.d/legacy.conf
tmpfiles.d/systemd-remote.conf
tmpfiles.d/systemd.conf.m4
tools/make-directive-index.py
units/.gitignore
units/basic.target
units/console-shell.service.m4.in
units/dev-mqueue.mount
units/emergency.service.in
units/kmod-static-nodes.service.in
units/rescue.service.in
units/sys-fs-fuse-connections.mount
units/systemd-coredump.socket [new file with mode: 0644]
units/systemd-coredump@.service.in [new file with mode: 0644]
units/systemd-journal-gatewayd.service.in
units/systemd-journal-gatewayd.socket
units/systemd-journal-remote.service.in
units/systemd-journal-upload.service.in
units/user@.service.m4.in

index 9d9f8cd178c96e16ded975a09045d09e0d5b2f19..3e1b2d76c070c5f36504eae6fd5d37c815ef6cdd 100644 (file)
@@ -2,6 +2,22 @@
 ; A list of (major-mode . ((var1 . value1) (var2 . value2)))
 ; Mode can be nil, which gives default values.
 
+; Note that we set a line width of 119 for .c and XML files, but for everything
+; else (such as journal catalog files, unit files, README files) we stick to a
+; more conservative 79 characters.
+
+; NOTE: If you update this file make sure to update .vimrc and .editorconfig,
+; too.
+
 ((nil . ((indent-tabs-mode . nil)
-         (tab-width . 8)))
-)
+         (tab-width . 8)
+         (fill-column . 79)))
+ (c-mode . ((fill-column . 119)
+            (c-basic-offset . 8)
+            (eval . (c-set-offset 'substatement-open 0))
+            (eval . (c-set-offset 'statement-case-open 0))
+            (eval . (c-set-offset 'case-label 0))
+            (eval . (c-set-offset 'arglist-intro '++))
+            (eval . (c-set-offset 'arglist-close 0))))
+ (nxml-mode . ((nxml-child-indent . 2)
+               (fill-column . 119))))
diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..e98007c
--- /dev/null
@@ -0,0 +1,20 @@
+# EditorConfig configuration for systemd
+# http://EditorConfig.org
+
+# NOTE: If you update this file make sure to update .dir-locals.el and .vimrc,
+# too.
+
+# Top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file, utf-8 charset
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+# Match config files, set indent to spaces with width of eight
+[*.{c,h}]
+indent_style = space
+indent_size = 8
index b0abc0d4e99e3bab18117e1286d73eccb594508a..586b3796b1b894b003749f71295b2d0a0999e262 100644 (file)
@@ -1,6 +1,5 @@
 *.a
 *.cache
-*.html
 *.la
 *.lo
 *.log
 /systemd-remount-api-vfs
 /systemd-remount-fs
 /systemd-reply-password
-/systemd-resolve-host
+/systemd-resolve
 /systemd-resolved
 /systemd-rfkill
 /systemd-run
 /systemd-vconsole-setup
 /tags
 /test-acd
+/test-acl-util
 /test-af-list
 /test-architecture
 /test-arphrd-list
+/test-ask-password-api
 /test-async
 /test-audit-type
 /test-barrier
 /test-daemon
 /test-date
 /test-device-nodes
+/test-dnssec-complex
 /test-dhcp-client
 /test-dhcp-option
 /test-dhcp-server
 /test-dhcp6-client
 /test-dns-domain
+/test-dnssec
 /test-efi-disk.img
 /test-ellipsize
 /test-engine
 /test-pty
 /test-qcow2
 /test-ratelimit
+/test-rbtree
 /test-replace-var
 /test-resolve
+/test-resolve-tables
 /test-ring
+/test-rlimit-util
 /test-sched-prio
 /test-set
 /test-sigbus
+/test-signal-util
 /test-siphash24
 /test-sleep
 /test-socket-util
diff --git a/.vimrc b/.vimrc
index b802c908f268d686c31b7fc6f5e7d0375b27abfe..7b436bd3776950d12af3163a24be516c4e2a8047 100644 (file)
--- a/.vimrc
+++ b/.vimrc
@@ -1,5 +1,20 @@
 " 'set exrc' in ~/.vimrc will read .vimrc from the current directory
+" Warning: Enabling exrc is dangerous! You can do nearly everything from a
+" vimrc configuration file, including write operations and shell execution.
+" You should consider setting 'set secure' as well, which is highly
+" recommended!
+
+" Note that we set a line width of 119 for .c and XML files, but for everything
+" else (such as journal catalog files, unit files, README files) we stick to a
+" more conservative 79 characters.
+
+" NOTE: If you update this file make sure to update .dir-locals.el and
+" .editorconfig, too.
+
 set tabstop=8
 set shiftwidth=8
 set expandtab
 set makeprg=GCC_COLORS=\ make
+set tw=79
+au FileType xml set tw=119
+au FileType c set tw=119
index 00643032032b4a6259ee24494ebcce2142e6a61a..46e366898e7ee5ddeac6882ef9fa51c081de7cd0 100644 (file)
@@ -7,7 +7,7 @@
 
 - Don't break code lines too eagerly. We do *not* force line breaks at
   80ch, all of today's screens should be much larger than that. But
-  then again, don't overdo it, ~140ch should be enough really.
+  then again, don't overdo it, ~119ch should be enough really.
 
 - Variables and functions *must* be static, unless they have a
   prototype, and are supposed to be exported.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..18081cb
--- /dev/null
@@ -0,0 +1,37 @@
+# Contributing
+
+We welcome contributions from everyone. However, please follow the following guidelines when posting a GitHub Pull
+Request or filing a GitHub Issue on the systemd project:
+
+## 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 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.
+
+## Posting Pull Requests
+
+* Make sure to post PRs only relative to a very recent git master.
+* Follow our [Coding Style](https://raw.githubusercontent.com/systemd/systemd/master/CODING_STYLE) when contributing
+  code. This is a requirement for all code we merge.
+* Make sure to run "make check" locally, before posting your PR. We use a CI system, meaning we don't even look at your
+  PR, if the build and tests don't pass.
+* If you need to update the code in an existing PR, please consider opening a new PR (mentioning in it which old PR it
+  replaces) and closing the old PR. This is much preferable over force-pushing a new patch set into the PR's branch, as
+  commit comments aren't lost that way. That said, we don't follow this rule ourselves quite often, hence this is
+  really just a say as we say, not say as we do...
+
+## Final Words
+
+We'd like to apologize in advance if we are not able to process and reply to your issue or PR right-away. We have a lot
+of work to do, but we are trying our best!
+
+Thank you very much for your contributions!
index c792c8932499feee2c6c5ecb1bb885abc8f73e53..28b5fb6adb937b2eedaf7cd31a73123cd7ae6711 100644 (file)
@@ -25,7 +25,9 @@ MANPAGES += \
        man/machine-info.5 \
        man/os-release.5 \
        man/sd-bus-errors.3 \
+       man/sd-bus.3 \
        man/sd-daemon.3 \
+       man/sd-event.3 \
        man/sd-id128.3 \
        man/sd-journal.3 \
        man/sd_booted.3 \
@@ -47,18 +49,30 @@ MANPAGES += \
        man/sd_bus_request_name.3 \
        man/sd_event_add_child.3 \
        man/sd_event_add_defer.3 \
+       man/sd_event_add_io.3 \
        man/sd_event_add_signal.3 \
        man/sd_event_add_time.3 \
+       man/sd_event_exit.3 \
        man/sd_event_get_fd.3 \
        man/sd_event_new.3 \
+       man/sd_event_now.3 \
        man/sd_event_run.3 \
-       man/sd_event_set_name.3 \
+       man/sd_event_set_watchdog.3 \
+       man/sd_event_source_get_event.3 \
+       man/sd_event_source_get_pending.3 \
+       man/sd_event_source_set_description.3 \
+       man/sd_event_source_set_enabled.3 \
+       man/sd_event_source_set_prepare.3 \
+       man/sd_event_source_set_priority.3 \
+       man/sd_event_source_set_userdata.3 \
+       man/sd_event_source_unref.3 \
        man/sd_event_wait.3 \
        man/sd_id128_get_machine.3 \
        man/sd_id128_randomize.3 \
        man/sd_id128_to_string.3 \
        man/sd_is_fifo.3 \
        man/sd_journal_add_match.3 \
+       man/sd_journal_enumerate_fields.3 \
        man/sd_journal_get_catalog.3 \
        man/sd_journal_get_cursor.3 \
        man/sd_journal_get_cutoff_realtime_usec.3 \
@@ -66,6 +80,7 @@ MANPAGES += \
        man/sd_journal_get_fd.3 \
        man/sd_journal_get_realtime_usec.3 \
        man/sd_journal_get_usage.3 \
+       man/sd_journal_has_runtime_files.3 \
        man/sd_journal_next.3 \
        man/sd_journal_open.3 \
        man/sd_journal_print.3 \
@@ -108,6 +123,7 @@ 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-proxyd.8 \
@@ -199,6 +215,19 @@ MANPAGES_ALIAS += \
        man/SD_DEBUG.3 \
        man/SD_EMERG.3 \
        man/SD_ERR.3 \
+       man/SD_EVENT_ARMED.3 \
+       man/SD_EVENT_EXITING.3 \
+       man/SD_EVENT_FINISHED.3 \
+       man/SD_EVENT_INITIAL.3 \
+       man/SD_EVENT_OFF.3 \
+       man/SD_EVENT_ON.3 \
+       man/SD_EVENT_ONESHOT.3 \
+       man/SD_EVENT_PENDING.3 \
+       man/SD_EVENT_PREPARING.3 \
+       man/SD_EVENT_PRIORITY_IDLE.3 \
+       man/SD_EVENT_PRIORITY_IMPORTANT.3 \
+       man/SD_EVENT_PRIORITY_NORMAL.3 \
+       man/SD_EVENT_RUNNING.3 \
        man/SD_ID128_CONST_STR.3 \
        man/SD_ID128_FORMAT_STR.3 \
        man/SD_ID128_FORMAT_VAL.3 \
@@ -209,6 +238,7 @@ MANPAGES_ALIAS += \
        man/SD_JOURNAL_FOREACH.3 \
        man/SD_JOURNAL_FOREACH_BACKWARDS.3 \
        man/SD_JOURNAL_FOREACH_DATA.3 \
+       man/SD_JOURNAL_FOREACH_FIELD.3 \
        man/SD_JOURNAL_FOREACH_UNIQUE.3 \
        man/SD_JOURNAL_INVALIDATE.3 \
        man/SD_JOURNAL_LOCAL_ONLY.3 \
@@ -260,6 +290,7 @@ MANPAGES_ALIAS += \
        man/sd_bus_creds_has_permitted_cap.3 \
        man/sd_bus_creds_ref.3 \
        man/sd_bus_creds_unref.3 \
+       man/sd_bus_creds_unrefp.3 \
        man/sd_bus_default_system.3 \
        man/sd_bus_default_user.3 \
        man/sd_bus_error_copy.3 \
@@ -295,22 +326,45 @@ MANPAGES_ALIAS += \
        man/sd_bus_ref.3 \
        man/sd_bus_release_name.3 \
        man/sd_bus_unref.3 \
+       man/sd_bus_unrefp.3 \
+       man/sd_event.3 \
        man/sd_event_add_exit.3 \
        man/sd_event_add_post.3 \
+       man/sd_event_child_handler_t.3 \
        man/sd_event_default.3 \
        man/sd_event_dispatch.3 \
-       man/sd_event_get_name.3 \
+       man/sd_event_get_exit_code.3 \
+       man/sd_event_get_state.3 \
+       man/sd_event_get_tid.3 \
+       man/sd_event_get_watchdog.3 \
+       man/sd_event_handler_t.3 \
+       man/sd_event_io_handler_t.3 \
        man/sd_event_loop.3 \
        man/sd_event_prepare.3 \
        man/sd_event_ref.3 \
+       man/sd_event_signal_handler_t.3 \
+       man/sd_event_source.3 \
        man/sd_event_source_get_child_pid.3 \
+       man/sd_event_source_get_description.3 \
+       man/sd_event_source_get_enabled.3 \
+       man/sd_event_source_get_io_events.3 \
+       man/sd_event_source_get_io_fd.3 \
+       man/sd_event_source_get_io_revents.3 \
+       man/sd_event_source_get_priority.3 \
        man/sd_event_source_get_signal.3 \
        man/sd_event_source_get_time.3 \
        man/sd_event_source_get_time_accuracy.3 \
        man/sd_event_source_get_time_clock.3 \
+       man/sd_event_source_get_userdata.3 \
+       man/sd_event_source_ref.3 \
+       man/sd_event_source_set_io_events.3 \
+       man/sd_event_source_set_io_fd.3 \
        man/sd_event_source_set_time.3 \
        man/sd_event_source_set_time_accuracy.3 \
+       man/sd_event_source_unrefp.3 \
+       man/sd_event_time_handler_t.3 \
        man/sd_event_unref.3 \
+       man/sd_event_unrefp.3 \
        man/sd_id128_equal.3 \
        man/sd_id128_from_string.3 \
        man/sd_id128_get_boot.3 \
@@ -333,6 +387,7 @@ MANPAGES_ALIAS += \
        man/sd_journal_get_events.3 \
        man/sd_journal_get_monotonic_usec.3 \
        man/sd_journal_get_timeout.3 \
+       man/sd_journal_has_persistent_files.3 \
        man/sd_journal_next_skip.3 \
        man/sd_journal_open_container.3 \
        man/sd_journal_open_directory.3 \
@@ -344,6 +399,7 @@ MANPAGES_ALIAS += \
        man/sd_journal_process.3 \
        man/sd_journal_reliable_fd.3 \
        man/sd_journal_restart_data.3 \
+       man/sd_journal_restart_fields.3 \
        man/sd_journal_restart_unique.3 \
        man/sd_journal_seek_cursor.3 \
        man/sd_journal_seek_monotonic_usec.3 \
@@ -489,6 +545,19 @@ man/SD_CRIT.3: man/sd-daemon.3
 man/SD_DEBUG.3: man/sd-daemon.3
 man/SD_EMERG.3: man/sd-daemon.3
 man/SD_ERR.3: man/sd-daemon.3
+man/SD_EVENT_ARMED.3: man/sd_event_wait.3
+man/SD_EVENT_EXITING.3: man/sd_event_wait.3
+man/SD_EVENT_FINISHED.3: man/sd_event_wait.3
+man/SD_EVENT_INITIAL.3: man/sd_event_wait.3
+man/SD_EVENT_OFF.3: man/sd_event_source_set_enabled.3
+man/SD_EVENT_ON.3: man/sd_event_source_set_enabled.3
+man/SD_EVENT_ONESHOT.3: man/sd_event_source_set_enabled.3
+man/SD_EVENT_PENDING.3: man/sd_event_wait.3
+man/SD_EVENT_PREPARING.3: man/sd_event_wait.3
+man/SD_EVENT_PRIORITY_IDLE.3: man/sd_event_source_set_priority.3
+man/SD_EVENT_PRIORITY_IMPORTANT.3: man/sd_event_source_set_priority.3
+man/SD_EVENT_PRIORITY_NORMAL.3: man/sd_event_source_set_priority.3
+man/SD_EVENT_RUNNING.3: man/sd_event_wait.3
 man/SD_ID128_CONST_STR.3: man/sd-id128.3
 man/SD_ID128_FORMAT_STR.3: man/sd-id128.3
 man/SD_ID128_FORMAT_VAL.3: man/sd-id128.3
@@ -499,6 +568,7 @@ man/SD_JOURNAL_CURRENT_USER.3: man/sd_journal_open.3
 man/SD_JOURNAL_FOREACH.3: man/sd_journal_next.3
 man/SD_JOURNAL_FOREACH_BACKWARDS.3: man/sd_journal_next.3
 man/SD_JOURNAL_FOREACH_DATA.3: man/sd_journal_get_data.3
+man/SD_JOURNAL_FOREACH_FIELD.3: man/sd_journal_enumerate_fields.3
 man/SD_JOURNAL_FOREACH_UNIQUE.3: man/sd_journal_query_unique.3
 man/SD_JOURNAL_INVALIDATE.3: man/sd_journal_get_fd.3
 man/SD_JOURNAL_LOCAL_ONLY.3: man/sd_journal_open.3
@@ -550,6 +620,7 @@ man/sd_bus_creds_has_inheritable_cap.3: man/sd_bus_creds_get_pid.3
 man/sd_bus_creds_has_permitted_cap.3: man/sd_bus_creds_get_pid.3
 man/sd_bus_creds_ref.3: man/sd_bus_creds_new_from_pid.3
 man/sd_bus_creds_unref.3: man/sd_bus_creds_new_from_pid.3
+man/sd_bus_creds_unrefp.3: man/sd_bus_creds_new_from_pid.3
 man/sd_bus_default_system.3: man/sd_bus_default.3
 man/sd_bus_default_user.3: man/sd_bus_default.3
 man/sd_bus_error_copy.3: man/sd_bus_error.3
@@ -585,22 +656,45 @@ man/sd_bus_path_encode_many.3: man/sd_bus_path_encode.3
 man/sd_bus_ref.3: man/sd_bus_new.3
 man/sd_bus_release_name.3: man/sd_bus_request_name.3
 man/sd_bus_unref.3: man/sd_bus_new.3
+man/sd_bus_unrefp.3: man/sd_bus_new.3
+man/sd_event.3: man/sd_event_new.3
 man/sd_event_add_exit.3: man/sd_event_add_defer.3
 man/sd_event_add_post.3: man/sd_event_add_defer.3
+man/sd_event_child_handler_t.3: man/sd_event_add_child.3
 man/sd_event_default.3: man/sd_event_new.3
 man/sd_event_dispatch.3: man/sd_event_wait.3
-man/sd_event_get_name.3: man/sd_event_set_name.3
+man/sd_event_get_exit_code.3: man/sd_event_exit.3
+man/sd_event_get_state.3: man/sd_event_wait.3
+man/sd_event_get_tid.3: man/sd_event_new.3
+man/sd_event_get_watchdog.3: man/sd_event_set_watchdog.3
+man/sd_event_handler_t.3: man/sd_event_add_defer.3
+man/sd_event_io_handler_t.3: man/sd_event_add_io.3
 man/sd_event_loop.3: man/sd_event_run.3
 man/sd_event_prepare.3: man/sd_event_wait.3
 man/sd_event_ref.3: man/sd_event_new.3
+man/sd_event_signal_handler_t.3: man/sd_event_add_signal.3
+man/sd_event_source.3: man/sd_event_add_io.3
 man/sd_event_source_get_child_pid.3: man/sd_event_add_child.3
+man/sd_event_source_get_description.3: man/sd_event_source_set_description.3
+man/sd_event_source_get_enabled.3: man/sd_event_source_set_enabled.3
+man/sd_event_source_get_io_events.3: man/sd_event_add_io.3
+man/sd_event_source_get_io_fd.3: man/sd_event_add_io.3
+man/sd_event_source_get_io_revents.3: man/sd_event_add_io.3
+man/sd_event_source_get_priority.3: man/sd_event_source_set_priority.3
 man/sd_event_source_get_signal.3: man/sd_event_add_signal.3
 man/sd_event_source_get_time.3: man/sd_event_add_time.3
 man/sd_event_source_get_time_accuracy.3: man/sd_event_add_time.3
 man/sd_event_source_get_time_clock.3: man/sd_event_add_time.3
+man/sd_event_source_get_userdata.3: man/sd_event_source_set_userdata.3
+man/sd_event_source_ref.3: man/sd_event_source_unref.3
+man/sd_event_source_set_io_events.3: man/sd_event_add_io.3
+man/sd_event_source_set_io_fd.3: man/sd_event_add_io.3
 man/sd_event_source_set_time.3: man/sd_event_add_time.3
 man/sd_event_source_set_time_accuracy.3: man/sd_event_add_time.3
+man/sd_event_source_unrefp.3: man/sd_event_source_unref.3
+man/sd_event_time_handler_t.3: man/sd_event_add_time.3
 man/sd_event_unref.3: man/sd_event_new.3
+man/sd_event_unrefp.3: man/sd_event_new.3
 man/sd_id128_equal.3: man/sd-id128.3
 man/sd_id128_from_string.3: man/sd_id128_to_string.3
 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3
@@ -623,6 +717,7 @@ man/sd_journal_get_data_threshold.3: man/sd_journal_get_data.3
 man/sd_journal_get_events.3: man/sd_journal_get_fd.3
 man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3
 man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3
+man/sd_journal_has_persistent_files.3: man/sd_journal_has_runtime_files.3
 man/sd_journal_next_skip.3: man/sd_journal_next.3
 man/sd_journal_open_container.3: man/sd_journal_open.3
 man/sd_journal_open_directory.3: man/sd_journal_open.3
@@ -634,6 +729,7 @@ man/sd_journal_printv.3: man/sd_journal_print.3
 man/sd_journal_process.3: man/sd_journal_get_fd.3
 man/sd_journal_reliable_fd.3: man/sd_journal_get_fd.3
 man/sd_journal_restart_data.3: man/sd_journal_get_data.3
+man/sd_journal_restart_fields.3: man/sd_journal_enumerate_fields.3
 man/sd_journal_restart_unique.3: man/sd_journal_query_unique.3
 man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3
 man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3
@@ -857,6 +953,45 @@ man/SD_EMERG.html: man/sd-daemon.html
 man/SD_ERR.html: man/sd-daemon.html
        $(html-alias)
 
+man/SD_EVENT_ARMED.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_EXITING.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_FINISHED.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_INITIAL.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_OFF.html: man/sd_event_source_set_enabled.html
+       $(html-alias)
+
+man/SD_EVENT_ON.html: man/sd_event_source_set_enabled.html
+       $(html-alias)
+
+man/SD_EVENT_ONESHOT.html: man/sd_event_source_set_enabled.html
+       $(html-alias)
+
+man/SD_EVENT_PENDING.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_PREPARING.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/SD_EVENT_PRIORITY_IDLE.html: man/sd_event_source_set_priority.html
+       $(html-alias)
+
+man/SD_EVENT_PRIORITY_IMPORTANT.html: man/sd_event_source_set_priority.html
+       $(html-alias)
+
+man/SD_EVENT_PRIORITY_NORMAL.html: man/sd_event_source_set_priority.html
+       $(html-alias)
+
+man/SD_EVENT_RUNNING.html: man/sd_event_wait.html
+       $(html-alias)
+
 man/SD_ID128_CONST_STR.html: man/sd-id128.html
        $(html-alias)
 
@@ -887,6 +1022,9 @@ man/SD_JOURNAL_FOREACH_BACKWARDS.html: man/sd_journal_next.html
 man/SD_JOURNAL_FOREACH_DATA.html: man/sd_journal_get_data.html
        $(html-alias)
 
+man/SD_JOURNAL_FOREACH_FIELD.html: man/sd_journal_enumerate_fields.html
+       $(html-alias)
+
 man/SD_JOURNAL_FOREACH_UNIQUE.html: man/sd_journal_query_unique.html
        $(html-alias)
 
@@ -1040,6 +1178,9 @@ man/sd_bus_creds_ref.html: man/sd_bus_creds_new_from_pid.html
 man/sd_bus_creds_unref.html: man/sd_bus_creds_new_from_pid.html
        $(html-alias)
 
+man/sd_bus_creds_unrefp.html: man/sd_bus_creds_new_from_pid.html
+       $(html-alias)
+
 man/sd_bus_default_system.html: man/sd_bus_default.html
        $(html-alias)
 
@@ -1145,19 +1286,43 @@ man/sd_bus_release_name.html: man/sd_bus_request_name.html
 man/sd_bus_unref.html: man/sd_bus_new.html
        $(html-alias)
 
+man/sd_bus_unrefp.html: man/sd_bus_new.html
+       $(html-alias)
+
+man/sd_event.html: man/sd_event_new.html
+       $(html-alias)
+
 man/sd_event_add_exit.html: man/sd_event_add_defer.html
        $(html-alias)
 
 man/sd_event_add_post.html: man/sd_event_add_defer.html
        $(html-alias)
 
+man/sd_event_child_handler_t.html: man/sd_event_add_child.html
+       $(html-alias)
+
 man/sd_event_default.html: man/sd_event_new.html
        $(html-alias)
 
 man/sd_event_dispatch.html: man/sd_event_wait.html
        $(html-alias)
 
-man/sd_event_get_name.html: man/sd_event_set_name.html
+man/sd_event_get_exit_code.html: man/sd_event_exit.html
+       $(html-alias)
+
+man/sd_event_get_state.html: man/sd_event_wait.html
+       $(html-alias)
+
+man/sd_event_get_tid.html: man/sd_event_new.html
+       $(html-alias)
+
+man/sd_event_get_watchdog.html: man/sd_event_set_watchdog.html
+       $(html-alias)
+
+man/sd_event_handler_t.html: man/sd_event_add_defer.html
+       $(html-alias)
+
+man/sd_event_io_handler_t.html: man/sd_event_add_io.html
        $(html-alias)
 
 man/sd_event_loop.html: man/sd_event_run.html
@@ -1169,9 +1334,33 @@ man/sd_event_prepare.html: man/sd_event_wait.html
 man/sd_event_ref.html: man/sd_event_new.html
        $(html-alias)
 
+man/sd_event_signal_handler_t.html: man/sd_event_add_signal.html
+       $(html-alias)
+
+man/sd_event_source.html: man/sd_event_add_io.html
+       $(html-alias)
+
 man/sd_event_source_get_child_pid.html: man/sd_event_add_child.html
        $(html-alias)
 
+man/sd_event_source_get_description.html: man/sd_event_source_set_description.html
+       $(html-alias)
+
+man/sd_event_source_get_enabled.html: man/sd_event_source_set_enabled.html
+       $(html-alias)
+
+man/sd_event_source_get_io_events.html: man/sd_event_add_io.html
+       $(html-alias)
+
+man/sd_event_source_get_io_fd.html: man/sd_event_add_io.html
+       $(html-alias)
+
+man/sd_event_source_get_io_revents.html: man/sd_event_add_io.html
+       $(html-alias)
+
+man/sd_event_source_get_priority.html: man/sd_event_source_set_priority.html
+       $(html-alias)
+
 man/sd_event_source_get_signal.html: man/sd_event_add_signal.html
        $(html-alias)
 
@@ -1184,15 +1373,36 @@ man/sd_event_source_get_time_accuracy.html: man/sd_event_add_time.html
 man/sd_event_source_get_time_clock.html: man/sd_event_add_time.html
        $(html-alias)
 
+man/sd_event_source_get_userdata.html: man/sd_event_source_set_userdata.html
+       $(html-alias)
+
+man/sd_event_source_ref.html: man/sd_event_source_unref.html
+       $(html-alias)
+
+man/sd_event_source_set_io_events.html: man/sd_event_add_io.html
+       $(html-alias)
+
+man/sd_event_source_set_io_fd.html: man/sd_event_add_io.html
+       $(html-alias)
+
 man/sd_event_source_set_time.html: man/sd_event_add_time.html
        $(html-alias)
 
 man/sd_event_source_set_time_accuracy.html: man/sd_event_add_time.html
        $(html-alias)
 
+man/sd_event_source_unrefp.html: man/sd_event_source_unref.html
+       $(html-alias)
+
+man/sd_event_time_handler_t.html: man/sd_event_add_time.html
+       $(html-alias)
+
 man/sd_event_unref.html: man/sd_event_new.html
        $(html-alias)
 
+man/sd_event_unrefp.html: man/sd_event_new.html
+       $(html-alias)
+
 man/sd_id128_equal.html: man/sd-id128.html
        $(html-alias)
 
@@ -1259,6 +1469,9 @@ man/sd_journal_get_monotonic_usec.html: man/sd_journal_get_realtime_usec.html
 man/sd_journal_get_timeout.html: man/sd_journal_get_fd.html
        $(html-alias)
 
+man/sd_journal_has_persistent_files.html: man/sd_journal_has_runtime_files.html
+       $(html-alias)
+
 man/sd_journal_next_skip.html: man/sd_journal_next.html
        $(html-alias)
 
@@ -1292,6 +1505,9 @@ man/sd_journal_reliable_fd.html: man/sd_journal_get_fd.html
 man/sd_journal_restart_data.html: man/sd_journal_get_data.html
        $(html-alias)
 
+man/sd_journal_restart_fields.html: man/sd_journal_enumerate_fields.html
+       $(html-alias)
+
 man/sd_journal_restart_unique.html: man/sd_journal_query_unique.html
        $(html-alias)
 
@@ -1793,16 +2009,21 @@ endif
 
 if ENABLE_RESOLVED
 MANPAGES += \
+       man/dnssec-trust-anchors.d.5 \
        man/nss-resolve.8 \
        man/resolved.conf.5 \
        man/systemd-resolved.service.8
 MANPAGES_ALIAS += \
        man/libnss_resolve.so.2.8 \
        man/resolved.conf.d.5 \
-       man/systemd-resolved.8
+       man/systemd-resolved.8 \
+       man/systemd.negative.5 \
+       man/systemd.positive.5
 man/libnss_resolve.so.2.8: man/nss-resolve.8
 man/resolved.conf.d.5: man/resolved.conf.5
 man/systemd-resolved.8: man/systemd-resolved.service.8
+man/systemd.negative.5: man/dnssec-trust-anchors.d.5
+man/systemd.positive.5: man/dnssec-trust-anchors.d.5
 man/libnss_resolve.so.2.html: man/nss-resolve.html
        $(html-alias)
 
@@ -1812,6 +2033,12 @@ man/resolved.conf.d.html: man/resolved.conf.html
 man/systemd-resolved.html: man/systemd-resolved.service.html
        $(html-alias)
 
+man/systemd.negative.html: man/dnssec-trust-anchors.d.html
+       $(html-alias)
+
+man/systemd.positive.html: man/dnssec-trust-anchors.d.html
+       $(html-alias)
+
 endif
 
 if ENABLE_RFKILL
@@ -1961,6 +2188,7 @@ MANPAGES_ALIAS += \
        man/sd_login_monitor_get_fd.3 \
        man/sd_login_monitor_get_timeout.3 \
        man/sd_login_monitor_unref.3 \
+       man/sd_login_monitor_unrefp.3 \
        man/sd_peer_get_cgroup.3 \
        man/sd_peer_get_machine_name.3 \
        man/sd_peer_get_owner_uid.3 \
@@ -2007,6 +2235,7 @@ man/sd_login_monitor_get_events.3: man/sd_login_monitor_new.3
 man/sd_login_monitor_get_fd.3: man/sd_login_monitor_new.3
 man/sd_login_monitor_get_timeout.3: man/sd_login_monitor_new.3
 man/sd_login_monitor_unref.3: man/sd_login_monitor_new.3
+man/sd_login_monitor_unrefp.3: man/sd_login_monitor_new.3
 man/sd_peer_get_cgroup.3: man/sd_pid_get_session.3
 man/sd_peer_get_machine_name.3: man/sd_pid_get_session.3
 man/sd_peer_get_owner_uid.3: man/sd_pid_get_session.3
@@ -2071,6 +2300,9 @@ man/sd_login_monitor_get_timeout.html: man/sd_login_monitor_new.html
 man/sd_login_monitor_unref.html: man/sd_login_monitor_new.html
        $(html-alias)
 
+man/sd_login_monitor_unrefp.html: man/sd_login_monitor_new.html
+       $(html-alias)
+
 man/sd_peer_get_cgroup.html: man/sd_pid_get_session.html
        $(html-alias)
 
@@ -2232,6 +2464,7 @@ EXTRA_DIST += \
        man/coredumpctl.xml \
        man/crypttab.xml \
        man/daemon.xml \
+       man/dnssec-trust-anchors.d.xml \
        man/file-hierarchy.xml \
        man/halt.xml \
        man/hostname.xml \
@@ -2263,7 +2496,9 @@ EXTRA_DIST += \
        man/resolved.conf.xml \
        man/runlevel.xml \
        man/sd-bus-errors.xml \
+       man/sd-bus.xml \
        man/sd-daemon.xml \
+       man/sd-event.xml \
        man/sd-id128.xml \
        man/sd-journal.xml \
        man/sd-login.xml \
@@ -2286,12 +2521,23 @@ EXTRA_DIST += \
        man/sd_bus_request_name.xml \
        man/sd_event_add_child.xml \
        man/sd_event_add_defer.xml \
+       man/sd_event_add_io.xml \
        man/sd_event_add_signal.xml \
        man/sd_event_add_time.xml \
+       man/sd_event_exit.xml \
        man/sd_event_get_fd.xml \
        man/sd_event_new.xml \
+       man/sd_event_now.xml \
        man/sd_event_run.xml \
-       man/sd_event_set_name.xml \
+       man/sd_event_set_watchdog.xml \
+       man/sd_event_source_get_event.xml \
+       man/sd_event_source_get_pending.xml \
+       man/sd_event_source_set_description.xml \
+       man/sd_event_source_set_enabled.xml \
+       man/sd_event_source_set_prepare.xml \
+       man/sd_event_source_set_priority.xml \
+       man/sd_event_source_set_userdata.xml \
+       man/sd_event_source_unref.xml \
        man/sd_event_wait.xml \
        man/sd_get_seats.xml \
        man/sd_id128_get_machine.xml \
@@ -2299,6 +2545,7 @@ EXTRA_DIST += \
        man/sd_id128_to_string.xml \
        man/sd_is_fifo.xml \
        man/sd_journal_add_match.xml \
+       man/sd_journal_enumerate_fields.xml \
        man/sd_journal_get_catalog.xml \
        man/sd_journal_get_cursor.xml \
        man/sd_journal_get_cutoff_realtime_usec.xml \
@@ -2306,6 +2553,7 @@ EXTRA_DIST += \
        man/sd_journal_get_fd.xml \
        man/sd_journal_get_realtime_usec.xml \
        man/sd_journal_get_usage.xml \
+       man/sd_journal_has_runtime_files.xml \
        man/sd_journal_next.xml \
        man/sd_journal_open.xml \
        man/sd_journal_print.xml \
@@ -2375,6 +2623,7 @@ EXTRA_DIST += \
        man/systemd-quotacheck.service.xml \
        man/systemd-random-seed.service.xml \
        man/systemd-remount-fs.service.xml \
+       man/systemd-resolve.xml \
        man/systemd-resolved.service.xml \
        man/systemd-rfkill.service.xml \
        man/systemd-run.xml \
index 437905ce045ab3a59f826f913e0b310927e56642..3b7cc1e33e8e3bb5d49301c2b9563766656d7cba 100644 (file)
@@ -42,9 +42,9 @@ LIBUDEV_CURRENT=7
 LIBUDEV_REVISION=4
 LIBUDEV_AGE=6
 
-LIBSYSTEMD_CURRENT=13
+LIBSYSTEMD_CURRENT=14
 LIBSYSTEMD_REVISION=0
-LIBSYSTEMD_AGE=13
+LIBSYSTEMD_AGE=14
 
 # The following four libraries only exist for compatibility reasons,
 # their version info should not be bumped anymore
@@ -147,6 +147,7 @@ tests=
 manual_tests =
 TEST_EXTENSIONS = .py
 PY_LOG_COMPILER = $(PYTHON)
+DISABLE_HARD_ERRORS = yes
 if ENABLE_TESTS
 noinst_PROGRAMS = $(manual_tests) $(tests)
 TESTS = $(tests)
@@ -154,6 +155,14 @@ else
 noinst_PROGRAMS =
 TESTS =
 endif
+if ENABLE_BASH_COMPLETION
+dist_bashcompletion_DATA = $(dist_bashcompletion_data)
+nodist_bashcompletion_DATA = $(nodist_bashcompletion_data)
+endif
+if ENABLE_ZSH_COMPLETION
+dist_zshcompletion_DATA = $(dist_zshcompletion_data)
+nodist_zshcompletion_DATA = $(nodist_zshcompletion_data)
+endif
 udevlibexec_PROGRAMS =
 gperf_gperf_sources =
 
@@ -164,6 +173,8 @@ m4_files = $(filter %.m4,$(EXTRA_DIST) $(in_files:.m4.in=.m4))
 CLEANFILES = $(BUILT_SOURCES) \
        $(pkgconfigdata_DATA) \
        $(pkgconfiglib_DATA) \
+       $(nodist_bashcompletion_data) \
+       $(nodist_zshcompletion_data) \
        $(in_files:.in=) $(in_in_files:.in.in=) \
        $(m4_files:.m4=)
 
@@ -415,8 +426,7 @@ systemgenerator_PROGRAMS = \
        systemd-system-update-generator \
        systemd-debug-generator
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA = \
+dist_bashcompletion_data = \
        shell-completion/bash/busctl \
        shell-completion/bash/journalctl \
        shell-completion/bash/systemd-analyze \
@@ -426,16 +436,15 @@ dist_bashcompletion_DATA = \
        shell-completion/bash/systemd-delta \
        shell-completion/bash/systemd-detect-virt \
        shell-completion/bash/systemd-nspawn \
+       shell-completion/bash/systemd-path \
        shell-completion/bash/systemd-run \
        shell-completion/bash/udevadm \
        shell-completion/bash/kernel-install
 
-nodist_bashcompletion_DATA = \
+nodist_bashcompletion_data = \
        shell-completion/bash/systemctl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA = \
+dist_zshcompletion_data = \
        shell-completion/zsh/_busctl \
        shell-completion/zsh/_journalctl \
        shell-completion/zsh/_udevadm \
@@ -449,18 +458,13 @@ dist_zshcompletion_DATA = \
        shell-completion/zsh/_systemd-delta \
        shell-completion/zsh/_systemd
 
-nodist_zshcompletion_DATA = \
+nodist_zshcompletion_data = \
        shell-completion/zsh/_systemctl
-endif
 
 EXTRA_DIST += \
        shell-completion/bash/systemctl.in \
        shell-completion/zsh/_systemctl.in
 
-CLEANFILES += \
-       $(nodist_bashcompletion_DATA) \
-       $(nodist_zshcompletion_DATA)
-
 dist_sysctl_DATA = \
        sysctl.d/50-default.conf
 
@@ -660,6 +664,7 @@ EXTRA_DIST += \
        README.md \
        autogen.sh \
        .dir-locals.el \
+       .editorconfig \
        .vimrc \
        .ycm_extra_conf.py \
        .travis.yml \
@@ -691,29 +696,27 @@ man_MANS = \
 
 noinst_DATA += \
        $(HTML_FILES) \
-       $(HTML_ALIAS)
+       $(HTML_ALIAS) \
+       docs/html/man
+endif
 
 CLEANFILES += \
        $(man_MANS) \
        $(HTML_FILES) \
-       $(HTML_ALIAS)
+       $(HTML_ALIAS) \
+       docs/html/man
 
 docs/html/man:
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_LN)$(LN_S) -f ../../man $@
 
-noinst_DATA += \
-       docs/html/man
-
-CLEANFILES += \
-       docs/html/man
-
-if HAVE_PYTHON
 man/index.html: man/systemd.index.html
        $(AM_V_LN)$(LN_S) -f systemd.index.html $@
 
+if HAVE_PYTHON
 noinst_DATA += \
        man/index.html
+endif
 
 CLEANFILES += \
        man/index.html
@@ -742,16 +745,10 @@ CLEANFILES += \
        man/systemd.index.xml \
        man/systemd.directives.xml
 
-EXTRA_DIST += \
-       tools/make-man-rules.py
-
-endif
-
-endif
-
 EXTRA_DIST += \
        $(filter-out man/systemd.directives.xml man/systemd.index.xml,$(XML_FILES)) \
        tools/make-man-index.py \
+       tools/make-man-rules.py \
        tools/make-directive-index.py \
        tools/xml_helper.py \
        man/glib-event-glue.c
@@ -764,6 +761,8 @@ libbasic_la_SOURCES = \
        src/basic/missing.h \
        src/basic/capability-util.c \
        src/basic/capability-util.h \
+       src/basic/c-rbtree.c \
+       src/basic/c-rbtree.h \
        src/basic/conf-files.c \
        src/basic/conf-files.h \
        src/basic/stdio-util.h \
@@ -837,10 +836,13 @@ libbasic_la_SOURCES = \
        src/basic/mempool.h \
        src/basic/hashmap.c \
        src/basic/hashmap.h \
+       src/basic/hash-funcs.c \
+       src/basic/hash-funcs.h \
        src/basic/siphash24.c \
        src/basic/siphash24.h \
        src/basic/set.h \
        src/basic/ordered-set.h \
+       src/basic/ordered-set.c \
        src/basic/bitmap.c \
        src/basic/bitmap.h \
        src/basic/fdset.c \
@@ -945,7 +947,8 @@ libbasic_la_SOURCES = \
        src/basic/copy.h \
        src/basic/alloc-util.h \
        src/basic/alloc-util.c \
-       src/basic/formats-util.h
+       src/basic/formats-util.h \
+       src/basic/nss-util.h
 
 nodist_libbasic_la_SOURCES = \
        src/basic/errno-from-name.h \
@@ -1005,7 +1008,6 @@ libshared_la_SOURCES = \
        src/shared/base-filesystem.h \
        src/shared/uid-range.c \
        src/shared/uid-range.h \
-       src/shared/nss-util.h \
        src/shared/install.c \
        src/shared/install.h \
        src/shared/install-printf.c \
@@ -1050,7 +1052,9 @@ libshared_la_SOURCES = \
        src/shared/machine-image.c \
        src/shared/machine-image.h \
        src/shared/machine-pool.c \
-       src/shared/machine-pool.h
+       src/shared/machine-pool.h \
+       src/shared/resolve-util.c \
+       src/shared/resolve-util.h
 
 if HAVE_UTMP
 libshared_la_SOURCES += \
@@ -1416,7 +1420,8 @@ manual_tests += \
        test-ipcrm \
        test-btrfs \
        test-acd \
-       test-ipv4ll-manual
+       test-ipv4ll-manual \
+       test-ask-password-api
 
 if HAVE_LIBIPTC
 manual_tests += \
@@ -1491,11 +1496,20 @@ tests += \
        test-copy \
        test-cap-list \
        test-sigbus \
+       test-rbtree \
        test-verbs \
        test-af-list \
        test-arphrd-list \
        test-dns-domain \
-       test-install-root
+       test-resolve-tables \
+       test-install-root \
+       test-rlimit-util \
+       test-signal-util
+
+if HAVE_ACL
+tests += \
+       test-acl-util
+endif
 
 EXTRA_DIST += \
        test/a.service \
@@ -1652,6 +1666,17 @@ test_dns_domain_LDADD = \
        libsystemd-network.la \
        libshared.la
 
+test_resolve_tables_SOURCES = \
+       src/resolve/test-resolve-tables.c \
+       src/shared/test-tables.h \
+       src/resolve/dns-type.c \
+       src/resolve/dns-type.h \
+       src/resolve/dns_type-from-name.h \
+       src/resolve/dns_type-to-name.h
+
+test_resolve_tables_LDADD = \
+       libshared.la
+
 if ENABLE_EFI
 manual_tests += \
        test-boot-timestamp
@@ -1721,6 +1746,12 @@ test_sigbus_SOURCES = \
 test_sigbus_LDADD = \
        libshared.la
 
+test_rbtree_SOURCES = \
+       src/test/test-rbtree.c
+
+test_rbtree_LDADD = \
+       libshared.la
+
 test_condition_SOURCES = \
        src/test/test-condition.c
 
@@ -1844,9 +1875,33 @@ test_install_root_SOURCES = \
 test_install_root_LDADD = \
        libshared.la
 
+test_acl_util_SOURCES = \
+       src/test/test-acl-util.c
+
+test_acl_util_LDADD = \
+       libshared.la
+
 test_namespace_LDADD = \
        libcore.la
 
+test_rlimit_util_SOURCES = \
+       src/test/test-rlimit-util.c
+
+test_rlimit_util_LDADD = \
+       libshared.la
+
+test_ask_password_api_SOURCES = \
+       src/test/test-ask-password-api.c
+
+test_ask_password_api_LDADD = \
+       libshared.la
+
+test_signal_util_SOURCES = \
+       src/test/test-signal-util.c
+
+test_signal_util_LDADD = \
+       libshared.la
+
 BUILT_SOURCES += \
        src/test/test-hashmap-ordered.c
 
@@ -2343,10 +2398,8 @@ SYSINIT_TARGET_WANTS += \
        systemd-tmpfiles-setup-dev.service \
        systemd-tmpfiles-setup.service
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_systemd-tmpfiles
-endif
 
 TIMERS_TARGET_WANTS += \
        systemd-tmpfiles-clean.timer
@@ -2384,6 +2437,11 @@ nodist_sysusers_DATA = \
        sysusers.d/systemd.conf \
        sysusers.d/basic.conf
 
+if HAVE_REMOTE
+nodist_sysusers_DATA += \
+       sysusers.d/systemd-remote.conf
+endif
+
 INSTALL_DIRS += \
        $(sysusersdir)
 endif
@@ -2391,6 +2449,7 @@ endif
 EXTRA_DIST += \
        units/systemd-sysusers.service.in \
        sysusers.d/systemd.conf.m4 \
+       sysusers.d/systemd-remote.conf.m4 \
        sysusers.d/basic.conf.in
 
 # ------------------------------------------------------------------------------
@@ -2568,16 +2627,12 @@ bootctl_LDADD = \
 bin_PROGRAMS += \
        bootctl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/bootctl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_bootctl
 endif
-endif
 
 # ------------------------------------------------------------------------------
 if HAVE_GNUEFI
@@ -2658,14 +2713,13 @@ systemd_boot_sources = \
 
 EXTRA_DIST += $(systemd_boot_sources) $(systemd_boot_headers)
 
-if ENABLE_EFI
-if HAVE_GNUEFI
 systemd_boot_objects = $(addprefix $(top_builddir)/,$(systemd_boot_sources:.c=.o))
 systemd_boot_solib = $(top_builddir)/src/boot/efi/systemd_boot.so
 systemd_boot = systemd-boot$(EFI_MACHINE_TYPE_NAME).efi
 
+if ENABLE_EFI
+if HAVE_GNUEFI
 bootlib_DATA = $(systemd_boot)
-CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot)
 
 $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(systemd_boot_headers))
        @$(MKDIR_P) $(top_builddir)/src/boot/efi/
@@ -2682,6 +2736,8 @@ $(systemd_boot): $(systemd_boot_solib)
 endif
 endif
 
+CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot)
+
 # ------------------------------------------------------------------------------
 stub_headers = \
        src/boot/efi/util.h \
@@ -2705,14 +2761,13 @@ EXTRA_DIST += \
        $(stub_headers) \
        test/splash.bmp
 
-if ENABLE_EFI
-if HAVE_GNUEFI
 stub_objects = $(addprefix $(top_builddir)/,$(stub_sources:.c=.o))
 stub_solib = $(top_builddir)/src/boot/efi/stub.so
 stub = linux$(EFI_MACHINE_TYPE_NAME).efi.stub
 
+if ENABLE_EFI
+if HAVE_GNUEFI
 bootlib_DATA += $(stub)
-CLEANFILES += $(stub_objects) $(stub_solib) $(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/
@@ -2726,6 +2781,11 @@ $(stub_solib): $(stub_objects)
 $(stub): $(stub_solib)
        $(AM_V_GEN)$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \
          -j .dynsym -j .rel -j .rela -j .reloc $(EFI_FORMAT) $< $@
+endif
+endif
+
+CLEANFILES += $(stub_objects) $(stub_solib) $(stub)
+
 
 # ------------------------------------------------------------------------------
 CLEANFILES += test-efi-disk.img
@@ -2735,8 +2795,6 @@ test-efi-disk.img: $(systemd_boot) $(stub) test/test-efi-create-disk.sh
 
 test-efi: test-efi-disk.img
        $(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-efi-disk.img
-endif
-endif
 
 EXTRA_DIST += test/test-efi-create-disk.sh
 
@@ -2885,6 +2943,8 @@ systemd_nspawn_SOURCES = \
        src/nspawn/nspawn-register.h \
        src/nspawn/nspawn-setuid.c \
        src/nspawn/nspawn-setuid.h \
+       src/nspawn/nspawn-stub-pid1.c \
+       src/nspawn/nspawn-stub-pid1.h \
        src/core/mount-setup.c \
        src/core/mount-setup.h \
        src/core/loopback-setup.c \
@@ -3039,7 +3099,6 @@ libsystemd_internal_la_SOURCES = \
        src/libsystemd/sd-bus/bus-dump.h \
        src/libsystemd/sd-utf8/sd-utf8.c \
        src/libsystemd/sd-event/sd-event.c \
-       src/libsystemd/sd-event/event-util.h \
        src/libsystemd/sd-netlink/sd-netlink.c \
        src/libsystemd/sd-netlink/netlink-internal.h \
        src/libsystemd/sd-netlink/netlink-message.c \
@@ -3068,8 +3127,7 @@ libsystemd_internal_la_SOURCES = \
        src/libsystemd/sd-device/sd-device.c \
        src/libsystemd/sd-device/device-private.c \
        src/libsystemd/sd-device/device-private.h \
-       src/libsystemd/sd-resolve/sd-resolve.c \
-       src/libsystemd/sd-resolve/resolve-util.h
+       src/libsystemd/sd-resolve/sd-resolve.c
 
 libsystemd_internal_la_LIBADD = \
        libbasic.la \
@@ -3351,7 +3409,6 @@ libsystemd_network_la_SOURCES = \
        src/libsystemd-network/lldp-port.c \
        src/libsystemd-network/lldp-internal.h \
        src/libsystemd-network/lldp-internal.c \
-       src/libsystemd-network/lldp-util.h \
        src/libsystemd-network/sd-lldp.c
 
 libsystemd_network_la_LIBADD = \
@@ -3712,6 +3769,7 @@ EXTRA_DIST += \
        hwdb/sdio.ids
 
 # ------------------------------------------------------------------------------
+if ENABLE_TESTS
 TESTS += \
        test/udev-test.pl
 
@@ -3724,6 +3782,7 @@ TESTS += \
        test/sysv-generator-test.py
 endif
 endif
+endif
 
 manual_tests += \
        test-libudev \
@@ -3743,8 +3802,10 @@ test_udev_LDADD = \
        $(BLKID_LIBS) \
        $(KMOD_LIBS)
 
+if ENABLE_TESTS
 check_DATA += \
        test/sys
+endif
 
 # packed sysfs test tree
 test/sys:
@@ -3898,11 +3959,6 @@ systemd_journal_remote_CFLAGS = \
 systemd_journal_remote_LDADD += \
        $(MICROHTTPD_LIBS)
 
-if ENABLE_SYSUSERS
-dist_sysusers_DATA += \
-       sysusers.d/systemd-remote.conf
-endif
-
 if ENABLE_TMPFILES
 dist_tmpfiles_DATA += \
        tmpfiles.d/systemd-remote.conf
@@ -3972,7 +4028,8 @@ journalctl_SOURCES = \
        src/journal/journalctl.c
 
 journalctl_LDADD = \
-       libshared.la
+       libshared.la \
+       libudev-core.la
 
 if HAVE_QRENCODE
 journalctl_SOURCES += \
@@ -4340,30 +4397,39 @@ systemd_socket_proxyd_LDADD = \
 # ------------------------------------------------------------------------------
 if ENABLE_COREDUMP
 systemd_coredump_SOURCES = \
-       src/journal/coredump.c \
-       src/journal/coredump-vacuum.c \
-       src/journal/coredump-vacuum.h
+       src/coredump/coredump.c \
+       src/coredump/coredump-vacuum.c \
+       src/coredump/coredump-vacuum.h
 
 systemd_coredump_LDADD = \
        libshared.la
 
 if HAVE_ELFUTILS
 systemd_coredump_SOURCES += \
-       src/journal/stacktrace.c \
-       src/journal/stacktrace.h
+       src/coredump/stacktrace.c \
+       src/coredump/stacktrace.h
 
 systemd_coredump_LDADD += \
        $(ELFUTILS_LIBS)
 endif
 
+nodist_systemunit_DATA += \
+       units/systemd-coredump@.service
+
+dist_systemunit_DATA += \
+       units/systemd-coredump.socket
+
+SOCKETS_TARGET_WANTS += \
+       systemd-coredump.socket
+
 rootlibexec_PROGRAMS += \
        systemd-coredump
 
 dist_pkgsysconf_DATA += \
-       src/journal/coredump.conf
+       src/coredump/coredump.conf
 
 coredumpctl_SOURCES = \
-       src/journal/coredumpctl.c
+       src/coredump/coredumpctl.c
 
 coredumpctl_LDADD = \
        libshared.la
@@ -4375,22 +4441,18 @@ manual_tests += \
        test-coredump-vacuum
 
 test_coredump_vacuum_SOURCES = \
-       src/journal/test-coredump-vacuum.c  \
-       src/journal/coredump-vacuum.c \
-       src/journal/coredump-vacuum.h
+       src/coredump/test-coredump-vacuum.c  \
+       src/coredump/coredump-vacuum.c \
+       src/coredump/coredump-vacuum.h
 
 test_coredump_vacuum_LDADD = \
        libshared.la
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/coredumpctl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_coredumpctl
-endif
 
 nodist_sysctl_DATA = \
        sysctl.d/50-coredump.conf
@@ -4400,7 +4462,8 @@ CLEANFILES += \
 endif
 
 EXTRA_DIST += \
-       sysctl.d/50-coredump.conf.in
+       sysctl.d/50-coredump.conf.in \
+       units/systemd-coredump@.service.in
 
 # ------------------------------------------------------------------------------
 if ENABLE_BINFMT
@@ -4641,16 +4704,12 @@ hostnamectl_LDADD = \
 bin_PROGRAMS += \
        hostnamectl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/hostnamectl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_hostnamectl
 endif
-endif
 
 polkitpolicy_in_files += \
        src/hostname/org.freedesktop.hostname1.policy.in
@@ -4715,16 +4774,12 @@ localectl_LDADD = \
 bin_PROGRAMS += \
        localectl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/localectl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_localectl
 endif
-endif
 
 .PHONY: update-kbd-model-map
 
@@ -4775,16 +4830,12 @@ timedatectl_LDADD = \
 bin_PROGRAMS += \
        timedatectl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/timedatectl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_timedatectl
 endif
-endif
 
 polkitpolicy_in_files += \
        src/timedate/org.freedesktop.timedate1.policy.in
@@ -4806,9 +4857,6 @@ systemd_timesyncd_SOURCES = \
 nodist_systemd_timesyncd_SOURCES = \
        src/timesync/timesyncd-gperf.c
 
-gperf_gperf_sources += \
-       src/timesync/timesyncd-gperf.gperf
-
 systemd_timesyncd_LDADD = \
        libsystemd-network.la \
        libshared.la
@@ -4822,15 +4870,17 @@ nodist_systemunit_DATA += \
 GENERAL_ALIASES += \
        $(systemunitdir)/systemd-timesyncd.service $(pkgsysconfdir)/system/sysinit.target.wants/systemd-timesyncd.service
 
-EXTRA_DIST += \
-       units/systemd-timesyncd.service.in
-
 nodist_pkgsysconf_DATA += \
        src/timesync/timesyncd.conf
 
+endif
+
+gperf_gperf_sources += \
+       src/timesync/timesyncd-gperf.gperf
+
 EXTRA_DIST += \
+       units/systemd-timesyncd.service.in \
        src/timesync/timesyncd.conf.in
-endif
 
 # ------------------------------------------------------------------------------
 if HAVE_MYHOSTNAME
@@ -4848,7 +4898,7 @@ libnss_myhostname_la_LDFLAGS = \
        -Wl,--version-script=$(top_srcdir)/src/nss-myhostname/nss-myhostname.sym
 
 libnss_myhostname_la_LIBADD = \
-       libshared.la
+       libsystemd-internal.la
 
 lib_LTLIBRARIES += \
        libnss_myhostname.la
@@ -4890,11 +4940,6 @@ machinectl_LDADD = \
 rootbin_PROGRAMS += \
        machinectl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
-       shell-completion/bash/machinectl
-endif
-
 test_machine_tables_SOURCES = \
        src/machine/test-machine-tables.c
 
@@ -4922,11 +4967,12 @@ dist_dbuspolicy_DATA += \
 polkitpolicy_files += \
        src/machine/org.freedesktop.machine1.policy
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_bashcompletion_data += \
+       shell-completion/bash/machinectl
+
+dist_zshcompletion_data += \
        shell-completion/zsh/_machinectl \
        shell-completion/zsh/_sd_machines
-endif
 
 SYSTEM_UNIT_ALIASES += \
        systemd-machined.service dbus-org.freedesktop.machine1.service
@@ -4948,7 +4994,7 @@ libnss_mymachines_la_LDFLAGS = \
        -Wl,--version-script=$(top_srcdir)/src/nss-mymachines/nss-mymachines.sym
 
 libnss_mymachines_la_LIBADD = \
-       libshared.la
+       libsystemd-internal.la
 
 lib_LTLIBRARIES += \
        libnss_mymachines.la
@@ -4994,8 +5040,6 @@ systemd_pull_SOURCES = \
        src/import/pull-raw.h \
        src/import/pull-tar.c \
        src/import/pull-tar.h \
-       src/import/pull-dkr.c \
-       src/import/pull-dkr.h \
        src/import/pull-job.c \
        src/import/pull-job.h \
        src/import/pull-common.c \
@@ -5126,24 +5170,30 @@ polkitpolicy_in_files += \
        src/import/org.freedesktop.import1.policy.in
 
 EXTRA_DIST += \
-       units/systemd-importd.service.in \
-       src/resolve/resolved.conf.in
+       units/systemd-importd.service.in
 
 
 # ------------------------------------------------------------------------------
 if ENABLE_RESOLVED
+
 systemd_resolved_SOURCES = \
        src/resolve/resolved.c \
        src/resolve/resolved-manager.c \
        src/resolve/resolved-manager.h \
        src/resolve/resolved-conf.c \
        src/resolve/resolved-conf.h \
+       src/resolve/resolved-resolv-conf.c \
+       src/resolve/resolved-resolv-conf.h \
        src/resolve/resolved-bus.c \
        src/resolve/resolved-bus.h \
        src/resolve/resolved-link.h \
        src/resolve/resolved-link.c \
+       src/resolve/resolved-link-bus.c \
+       src/resolve/resolved-link-bus.h \
        src/resolve/resolved-llmnr.h \
        src/resolve/resolved-llmnr.c \
+       src/resolve/resolved-mdns.h \
+       src/resolve/resolved-mdns.c \
        src/resolve/resolved-def.h \
        src/resolve/resolved-dns-rr.h \
        src/resolve/resolved-dns-rr.c \
@@ -5155,18 +5205,28 @@ systemd_resolved_SOURCES = \
        src/resolve/resolved-dns-packet.c \
        src/resolve/resolved-dns-query.h \
        src/resolve/resolved-dns-query.c \
+       src/resolve/resolved-dns-synthesize.h \
+       src/resolve/resolved-dns-synthesize.c \
        src/resolve/resolved-dns-transaction.h \
        src/resolve/resolved-dns-transaction.c \
        src/resolve/resolved-dns-scope.h \
        src/resolve/resolved-dns-scope.c \
        src/resolve/resolved-dns-server.h \
        src/resolve/resolved-dns-server.c \
+       src/resolve/resolved-dns-search-domain.h \
+       src/resolve/resolved-dns-search-domain.c \
        src/resolve/resolved-dns-cache.h \
        src/resolve/resolved-dns-cache.c \
        src/resolve/resolved-dns-zone.h \
        src/resolve/resolved-dns-zone.c \
        src/resolve/resolved-dns-stream.h \
        src/resolve/resolved-dns-stream.c \
+       src/resolve/resolved-dns-dnssec.h \
+       src/resolve/resolved-dns-dnssec.c \
+       src/resolve/resolved-dns-trust-anchor.h \
+       src/resolve/resolved-dns-trust-anchor.c \
+       src/resolve/resolved-etc-hosts.h \
+       src/resolve/resolved-etc-hosts.c \
        src/resolve/dns-type.c \
        src/resolve/dns-type.h
 
@@ -5175,12 +5235,6 @@ nodist_systemd_resolved_SOURCES = \
        src/resolve/dns_type-to-name.h \
        src/resolve/resolved-gperf.c
 
-gperf_gperf_sources += \
-       src/resolve/resolved-gperf.gperf
-
-gperf_txt_sources += \
-       src/resolve/dns_type-list.txt
-
 systemd_resolved_LDADD = \
        libsystemd-network.la \
        libshared.la
@@ -5212,9 +5266,6 @@ GENERAL_ALIASES += \
 nodist_pkgsysconf_DATA += \
        src/resolve/resolved.conf
 
-tests += \
-       test-dns-domain
-
 libnss_resolve_la_SOURCES = \
        src/nss-resolve/nss-resolve.sym \
        src/nss-resolve/nss-resolve.c
@@ -5229,14 +5280,16 @@ libnss_resolve_la_LDFLAGS = \
        -Wl,--version-script=$(top_srcdir)/src/nss-resolve/nss-resolve.sym
 
 libnss_resolve_la_LIBADD = \
-       libshared.la \
+       libsystemd-internal.la \
         -ldl
 
 lib_LTLIBRARIES += \
        libnss_resolve.la
 
-systemd_resolve_host_SOURCES = \
-       src/resolve-host/resolve-host.c \
+systemd_resolve_SOURCES = \
+       src/resolve/resolve-tool.c \
+       src/resolve/resolved-dns-dnssec.c \
+       src/resolve/resolved-dns-dnssec.h \
        src/resolve/resolved-dns-packet.c \
        src/resolve/resolved-dns-packet.h \
        src/resolve/resolved-dns-rr.c \
@@ -5248,20 +5301,60 @@ systemd_resolve_host_SOURCES = \
        src/resolve/dns-type.c \
        src/resolve/dns-type.h
 
-nodist_systemd_resolve_host_SOURCES = \
+nodist_systemd_resolve_SOURCES = \
        src/resolve/dns_type-from-name.h \
        src/resolve/dns_type-to-name.h
 
-systemd_resolve_host_LDADD = \
+systemd_resolve_LDADD = \
        libshared.la
 
-rootlibexec_PROGRAMS += \
-       systemd-resolve-host
+bin_PROGRAMS += \
+       systemd-resolve
+
+tests += \
+       test-dns-domain \
+       test-dnssec
+
+manual_tests += \
+       test-dnssec-complex
+
+test_dnssec_SOURCES = \
+       src/resolve/test-dnssec.c \
+       src/resolve/resolved-dns-packet.c \
+       src/resolve/resolved-dns-packet.h \
+       src/resolve/resolved-dns-rr.c \
+       src/resolve/resolved-dns-rr.h \
+       src/resolve/resolved-dns-answer.c \
+       src/resolve/resolved-dns-answer.h \
+       src/resolve/resolved-dns-question.c \
+       src/resolve/resolved-dns-question.h \
+       src/resolve/resolved-dns-dnssec.c \
+       src/resolve/resolved-dns-dnssec.h \
+       src/resolve/dns-type.c \
+       src/resolve/dns-type.h
+
+test_dnssec_LDADD = \
+       libshared.la
+
+test_dnssec_complex_SOURCES = \
+       src/resolve/test-dnssec-complex.c \
+       src/resolve/dns-type.c \
+       src/resolve/dns-type.h
+
+test_dnssec_complex_LDADD = \
+       libshared.la
 
 endif
 
+gperf_txt_sources += \
+       src/resolve/dns_type-list.txt
+
+gperf_gperf_sources += \
+       src/resolve/resolved-gperf.gperf
+
 EXTRA_DIST += \
-       units/systemd-resolved.service.m4.in
+       units/systemd-resolved.service.m4.in \
+       src/resolve/resolved.conf.in
 
 # ------------------------------------------------------------------------------
 if ENABLE_NETWORKD
@@ -5369,6 +5462,9 @@ networkctl_LDADD = \
        libshared.la \
        libsystemd-network.la
 
+dist_bashcompletion_data += \
+       shell-completion/bash/networkctl
+
 test_network_SOURCES = \
        src/network/test-network.c
 
@@ -5424,14 +5520,16 @@ SYSTEM_UNIT_ALIASES += \
 BUSNAMES_TARGET_WANTS += \
        org.freedesktop.network1.busname
 
+endif
+
 gperf_gperf_sources += \
        src/network/networkd-network-gperf.gperf \
        src/network/networkd-netdev-gperf.gperf
-endif
 
 EXTRA_DIST += \
        units/systemd-networkd.service.m4.in \
-       units/systemd-networkd-wait-online.service.in
+       units/systemd-networkd-wait-online.service.in \
+       test/networkd-test.py
 
 # ------------------------------------------------------------------------------
 if ENABLE_LOGIND
@@ -5495,16 +5593,12 @@ loginctl_LDADD = \
 rootbin_PROGRAMS += \
        loginctl
 
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA += \
+dist_bashcompletion_data += \
        shell-completion/bash/loginctl
-endif
 
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA += \
+dist_zshcompletion_data += \
        shell-completion/zsh/_loginctl \
        shell-completion/zsh/_systemd-inhibit
-endif
 
 systemd_inhibit_SOURCES = \
        src/login/inhibit.c
@@ -5669,6 +5763,20 @@ EXTRA_DIST += \
        test/TEST-03-JOBS/Makefile \
        test/TEST-03-JOBS/test-jobs.sh \
        test/TEST-03-JOBS/test.sh \
+       test/TEST-04-JOURNAL/Makefile \
+       test/TEST-04-JOURNAL/test-journal.sh \
+       test/TEST-04-JOURNAL/test.sh \
+       test/TEST-05-RLIMITS/Makefile \
+       test/TEST-05-RLIMITS/test-rlimits.sh \
+       test/TEST-05-RLIMITS/test.sh \
+       test/TEST-06-SELINUX/Makefile \
+       test/TEST-06-SELINUX/test-selinux-checks.sh \
+       test/TEST-06-SELINUX/test.sh \
+       test/TEST-06-SELINUX/systemd_test.te \
+       test/TEST-06-SELINUX/systemd_test.if \
+       test/TEST-07-ISSUE-1981/Makefile \
+       test/TEST-07-ISSUE-1981/test-segfault.sh \
+       test/TEST-07-ISSUE-1981/test.sh \
        test/test-functions
 
 EXTRA_DIST += \
@@ -5904,24 +6012,24 @@ src/%.c: src/%.gperf
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_GPERF)$(GPERF) < $< > $@
 
-src/%: src/%.m4
+src/%: src/%.m4 $(top_builddir)/config.status
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
 
-sysusers.d/%: sysusers.d/%.m4
+sysusers.d/%: sysusers.d/%.m4 $(top_builddir)/config.status
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
 
-tmpfiles.d/%: tmpfiles.d/%.m4
+tmpfiles.d/%: tmpfiles.d/%.m4 $(top_builddir)/config.status
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
 
 
-units/%: units/%.m4
+units/%: units/%.m4 $(top_builddir)/config.status
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_SYSTEM=1 < $< > $@
 
-units/user/%: units/user/%.m4
+units/user/%: units/user/%.m4 $(top_builddir)/config.status
        $(AM_V_at)$(MKDIR_P) $(dir $@)
        $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_USER=1 < $< > $@
 
@@ -5936,7 +6044,6 @@ EXTRA_DIST += \
        $(polkitpolicy_in_in_files)
 
 # ------------------------------------------------------------------------------
-if ENABLE_MANPAGES
 man/custom-entities.ent: configure.ac
        $(AM_V_GEN)$(MKDIR_P) $(dir $@)
        $(AM_V_GEN)(echo '<?xml version="1.0" encoding="utf-8" ?>' && \
@@ -5956,11 +6063,12 @@ XSLTPROC_FLAGS = \
        --stringparam systemd.version $(VERSION) \
        --path '$(builddir)/man:$(srcdir)/man'
 
+XSLT = $(if $(XSLTPROC), $(XSLTPROC), xsltproc)
 XSLTPROC_PROCESS_MAN = \
-       $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $<
+       $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $<
 
 XSLTPROC_PROCESS_HTML = \
-       $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-html.xsl $<
+       $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-html.xsl $<
 
 man/%.1: man/%.xml man/custom-man.xsl man/custom-entities.ent
        $(XSLTPROC_PROCESS_MAN)
@@ -5984,8 +6092,6 @@ define html-alias
        $(AM_V_LN)$(LN_S) -f $(notdir $<) $@
 endef
 
-endif
-
 EXTRA_DIST += \
        man/custom-html.xsl \
        man/custom-man.xsl
@@ -6159,21 +6265,7 @@ DISTCHECK_CONFIGURE_FLAGS += \
        --disable-split-usr
 endif
 
-#
-# Require python when making dist
-#
-.PHONY: dist-check-python dist-check-compat-libs dist-check-help
-dist-check-python:
-if !HAVE_PYTHON
-       @echo "*** python and python-lxml module must be installed and enabled in order to make dist"
-       @false
-endif
-
-dist-check-compat-libs:
-if !ENABLE_COMPAT_LIBS
-       @echo "*** compat-libs must be enabled in order to make dist"
-       @false
-endif
+.PHONY: dist-check-help
 
 dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS)
        for i in $(abspath $^); do                                             \
@@ -6183,8 +6275,6 @@ dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS)
                exit 1;                                                        \
             fi; done
 
-dist: dist-check-python dist-check-compat-libs
-
 .PHONY: hwdb-update
 hwdb-update:
        ( cd $(top_srcdir)/hwdb && \
@@ -6212,14 +6302,6 @@ www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd
 doc-sync: all
        rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/
 
-.PHONY: gardel
-gardel:
-       scp man/*.html gardel:public/systemd-man/
-
-.PHONY: lennart-fedora
-lennart-fedora:
-       cp -v systemd-$(VERSION).tar.xz /home/lennart/git.fedora/systemd/
-
 .PHONY: install-tree
 install-tree: all
        rm -rf $(abs_srcdir)/install-tree
@@ -6227,14 +6309,14 @@ install-tree: all
        tree $(abs_srcdir)/install-tree
 
 # Let's run all tests of the test suite, but under valgrind. Let's
-# exclude the one perl script we have in there
+# exclude perl/python/shell scripts we have in there
 .PHONY: valgrind-tests
 valgrind-tests: $(TESTS)
-       $(AM_V_GEN)for f in $(filter-out %.pl, $^); do \
+       $(AM_V_GEN)for f in $(filter-out %.pl %.py, $^); do \
                if file $$f | grep -q shell; then \
                echo -e "$${x}Skipping non-binary $$f"; else \
                echo -e "$${x}Running $$f"; \
-               libtool --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \
+               $(LIBTOOL) --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \
                x="\n\n"; \
        done
 
diff --git a/NEWS b/NEWS
index 006aef5e1e542c21b98c62e5227cd1aaa11db703..e7f6bb45933e839d21acabd5345ee3fb800498b3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,224 @@
 systemd System and Service Manager
 
+CHANGES WITH 229:
+
+        * The systemd-resolved DNS resolver service has gained a substantial
+          set of new features, most prominently it may now act as a DNSSEC
+          validating stub resolver. DNSSEC mode is currently turned off by
+          default, but it is expected that this is turned on by default in one
+          of the next releases. For now, we invite everybody to test the DNSSEC
+          logic by setting DNSSEC=allow-downgrade in
+          /etc/systemd/resolved.conf. The service also gained a full set of
+          D-Bus interfaces, including calls to configure DNS and DNSSEC
+          settings per link (for consumption by external network management
+          software). systemd-resolved (and systemd-networkd along with it) now
+          know to distinguish between "search" and "routing" domains. The
+          former are used to qualify single-label names, the latter are purely
+          used for routing lookups within certain domains to specific
+          links. resolved will now also synthesize RRs for all entries from
+          /etc/hosts.
+
+        * The systemd-resolve tool (which is a client utility for
+          systemd-resolved, and previously experimental) has been improved
+          considerably and is now fully supported and documented. Hence it has
+          moved from /usr/lib/systemd to /usr/bin.
+
+        * /dev/disk/by-path/ symlink support has been (re-)added for virtio
+          devices.
+
+        * The coredump collection logic has been reworked: when a coredump is
+          collected it is now written to disk, compressed and processed
+          (including stacktrace extraction) from a new instantiated service
+          systemd-coredump@.service, instead of directly from the
+          /proc/sys/kernel/core_pattern hook we provide. This is beneficial as
+          processing large coredumps can take up a substantial amount of
+          resources and time, and this previously happened entirely outside of
+          systemd's service supervision. With the new logic the core_pattern
+          hook only does minimal metadata collection before passing off control
+          to the new instantiated service, which is configured with a time
+          limit, a nice level and other settings to minimize negative impact on
+          the rest of the system. Also note that the new logic will honour the
+          RLIMIT_CORE setting of the crashed process, which now allows users
+          and processes to turn off coredumping for their processes by setting
+          this limit.
+
+        * The RLIMIT_CORE resource limit now defaults to "unlimited" for PID 1
+          and all forked processes by default. Previously, PID 1 would leave
+          the setting at "0" for all processes, as set by the kernel. Note that
+          the resource limit traditionally has no effect on the generated
+          coredumps on the system if the /proc/sys/kernel/core_pattern hook
+          logic is used. Since the limit is now honoured (see above) its
+          default has been changed so that the coredumping logic is enabled by
+          default for all processes, while allowing specific opt-out.
+
+        * When the stacktrace is extracted from processes of system users, this
+          is now done as "systemd-coredump" user, in order to sandbox this
+          potentially security sensitive parsing operation. (Note that when
+          processing coredumps of normal users this is done under the user ID
+          of process that crashed, as before.) Packagers should take notice
+          that it is now necessary to create the "systemd-coredump" system user
+          and group at package installation time.
+
+        * The systemd-activate socket activation testing tool gained support
+          for SOCK_DGRAM and SOCK_SEQPACKET sockets using the new --datagram
+          and --seqpacket switches. It also has been extended to support both
+          new-style and inetd-style file descriptor passing. Use the new
+          --inetd switch to request inetd-style file descriptor passing.
+
+        * Most systemd tools now honor a new $SYSTEMD_COLORS environment
+          variable, which takes a boolean value. If set to false, ANSI color
+          output is disabled in the tools even when run on a terminal that
+          supports it.
+
+        * The VXLAN support in networkd now supports two new settings
+          DestinationPort= and PortRange=.
+
+        * A new systemd.machine_id= kernel command line switch has been added,
+          that may be used to set the machine ID in /etc/machine-id if it is
+          not initialized yet. This command line option has no effect if the
+          file is already initialized.
+
+        * systemd-nspawn gained a new --as-pid2 switch that invokes any
+          specified command line as PID 2 rather than PID 1 in the
+          container. In this mode PID 1 will be a minimal stub init process
+          that implements the special POSIX and Linux semantics of PID 1
+          regarding signal and child process management. Note that this stub
+          init process is implemented in nspawn itself and requires no support
+          from the container image. This new logic is useful to support running
+          arbitrary command lines in the container, as normal processes are
+          generally not prepared to run as PID 1.
+
+        * systemd-nspawn gained a new --chdir= switch for setting the current
+          working directory for the process started in the container.
+
+        * "journalctl /dev/sda" will now output all kernel log messages from
+          the specified device, in addition to all devices that are parents of
+          it. This should make log output about devices pretty useful, as long
+          as kernel drivers attach enough metadata to the log messages. (The
+          usual SATA drivers do.)
+
+        * The sd-journal API gained two new calls
+          sd_journal_has_runtime_files() and sd_journal_has_persistent_files()
+          that report whether log data from /run or /var has been found.
+
+        * journalctl gained a new switch "--fields" that prints all journal
+          record field names currently in use in the journal.  This is backed
+          by two new sd-journal API calls sd_journal_enumerate_fields() and
+          sd_journal_restart_fields().
+
+        * Most configurable timeouts in systemd now expect an argument of
+          "infinity" to turn them off, instead of "0" as before. The semantics
+          from now on is that a timeout of "0" means "now", and "infinity"
+          means "never". To maintain backwards compatibility, "0" continues to
+          turn off previously existing timeout settings.
+
+        * "systemctl reload-or-try-restart" has been renamed to "systemctl
+          try-reload-or-restart" to clarify what it actually does: the "try"
+          logic applies to both reloading and restarting, not just restarting.
+          The old name continues to be accepted for compatibility.
+
+        * On boot-up, when PID 1 detects that the system clock is behind the
+          release date of the systemd version in use, the clock is now set
+          to the latter. Previously, this was already done in timesyncd, in order
+          to avoid running with clocks set to the various clock epochs such as
+          1902, 1938 or 1970. With this change the logic is now done in PID 1
+          in addition to timesyncd during early boot-up, so that it is enforced
+          before the first process is spawned by systemd. Note that the logic
+          in timesyncd remains, as it is more comprehensive and ensures
+          montonic clocks by maintaining a persistant timestamp file in
+          /var. Since /var is generally not available in earliest boot or the
+          initrd, this part of the logic remains in timesyncd, and is not done
+          by PID 1.
+
+        * Support for tweaking details in net_cls.class_id through the
+          NetClass= configuration directive has been removed, as the kernel
+          people have decided to deprecate that controller in cgroup v2.
+          Userspace tools such as nftables are moving over to setting rules
+          that are specific to the full cgroup path of a task, which obsoletes
+          these controllers anyway. The NetClass= directive is kept around for
+          legacy compatibility reasons. For a more in-depth description of the
+          kernel change, please refer to the respective upstream commit:
+
+            https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bd1060a1d671
+
+        * A new service setting RuntimeMaxSec= has been added that may be used
+          to specify a maximum runtime for a service. If the timeout is hit, the
+          service is terminated and put into a failure state.
+
+        * A new service setting AmbientCapabilities= has been added. It allows
+          configuration of additional Linux process capabilities that are
+          passed to the activated processes. This is only available on very
+          recent kernels.
+
+        * The process resource limit settings in service units may now be used
+          to configure hard and soft limits individually.
+
+        * The various libsystemd APIs such as sd-bus or sd-event now publicly
+          expose support for gcc's __attribute__((cleanup())) C
+          extension. Specifically, for many object destructor functions
+          alternative versions whose names are suffixed with "p" have been
+          added, which take a pointer to a pointer to the object to destroy,
+          instead of just a pointer to the object itself. This is useful because
+          these destructor functions may be used directly as parameters to the
+          cleanup construct. Internally, systemd has been a heavy user of the
+          GCC extension since a long time, and with this change similar support
+          is now available to consumers of the library outside of systemd. Note
+          that by using this extension in your sources compatibility with old
+          and strictly ANSI compatible C compilers is lost. However, any gcc or
+          LLVM version of recent years have supported this extension.
+
+        * Timer units gained support for a new setting RandomizedDelaySec= that
+          allows configuring some additional randomized delay to the configured
+          time. This is useful to spread out timer events to avoid load peaks in
+          clusters or larger setups.
+
+        * Calendar time specifications now support sub-second accuracy.
+
+        * Socket units now support listening on SCTP and UDP-lite protocol
+          sockets.
+
+        * The sd-event API now comes with a full set of man pages.
+
+        * Older versions of systemd contained experimental support for
+          compressing journal files and coredumps with the LZ4 compressor that
+          was not compatible with the lz4 binary (due to API limitations of the
+          lz4 library). This support has been removed; only support for files
+          compatible with the lz4 binary remains. This LZ4 logic is now
+          officially supported and no longer considered experimental.
+
+        * The dkr image import logic has been removed again from importd. dkr's
+          micro-services focus doesn't fit into the machine image focus of
+          importd, and quickly got out of date with the upstream dkr API.
+
+        * Creation of the /run/lock/lockdev/ directory was dropped from
+          tmpfiles.d/legacy.conf. Better locking mechanisms like flock() have
+          been available for many years. If you still need this, you need to
+          create your own tmpfiles.d config file with:
+
+                  d /run/lock/lockdev 0775 root lock -
+
+        Contributions from: Abdo Roig-Maranges, Alban Crequy, Aleksander
+        Adamowski, Alexander Kuleshov, Andreas Pokorny, Andrei Borzenkov,
+        Andrew Wilcox, Arthur Clement, Beniamino Galvani, Casey Schaufler,
+        Chris Atkinson, Chris Mayo, Christian Hesse, Damjan Georgievski, Dan
+        Dedrick, Daniele Medri, Daniel J Walsh, Daniel Korostil, Daniel Mack,
+        David Herrmann, Dimitri John Ledkov, Dominik Hannen, Douglas Christman,
+        Evgeny Vereshchagin, Filipe Brandenburger, Franck Bui, Gabor Kelemen,
+        Harald Hoyer, Hayden Walles, Helmut Grohne, Henrik Kaare Poulsen,
+        Hristo Venev, Hui Wang, Indrajit Raychaudhuri, Ismo Puustinen, Jakub
+        Wilk, Jan Alexander Steffens (heftig), Jan Engelhardt, Jan Synacek,
+        Joost Bremmer, Jorgen Schaefer, Karel Zak, Klearchos Chaloulos,
+        lc85446, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel
+        Holtmann, Martin Pitt, Michael Biebl, Michael Olbrich, Michael Scherer,
+        Michał Górny, Michal Sekletar, Nicolas Cornu, Nicolas Iooss, Nils
+        Carlson, nmartensen, nnz1024, Patrick Ohly, Peter Hutterer, Phillip Sz,
+        Ronny Chevalier, Samu Kallio, Shawn Landden, Stef Walter, Susant
+        Sahani, Sylvain Plantefève, Tadej Janež, Thomas Hindoe Paaboel
+        Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito
+        Caputo, WaLyong Cho, Yu Watanabe, Zbigniew Jędrzejewski-Szmek
+
+        -- Berlin, 2016-02-11
+
 CHANGES WITH 228:
 
         * A number of properties previously only settable in unit
@@ -88,6 +307,14 @@ CHANGES WITH 228:
           from PID1's environment block into the environment block of
           the service.
 
+        * Timer units gained support for a new RemainAfterElapse=
+          setting which takes a boolean argument. It defaults on on,
+          exposing behaviour unchanged to previous releases. If set to
+          off, timer units are unloaded after they elapsed if they
+          cannot elapse again. This is particularly useful for
+          transient timer units, which shall not stay around longer
+          than until they first elapse.
+
         * systemd will now bump the net.unix.max_dgram_qlen to 512 by
           default now (the kernel default is 16). This is beneficial
           for avoiding blocking on AF_UNIX/SOCK_DGRAM sockets since it
diff --git a/README b/README
index bc7068a66da294cd150d5e02cdcc971a6a9284ea..0a2c0df47d3a0aa75e0e3d7ebc88d15eb8fffdbb 100644 (file)
--- a/README
+++ b/README
@@ -15,7 +15,6 @@ GITWEB:
 
 MAILING LIST:
         http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-        http://lists.freedesktop.org/mailman/listinfo/systemd-commits
 
 IRC:
         #systemd on irc.freenode.org
@@ -204,6 +203,9 @@ USERS AND GROUPS:
         Similarly, the kdbus dbus1 proxy daemon requires the
         "systemd-bus-proxy" system user and group to exist.
 
+        Similarly, the coredump support requires the
+        "systemd-coredump" system user and group to exist.
+
 NSS:
         systemd ships with three NSS modules:
 
@@ -237,10 +239,6 @@ SYSV INIT.D SCRIPTS:
         needs to look like, and provide an implementation at the marked places.
 
 WARNINGS:
-        systemd will freeze execution during boot if /etc/mtab exists
-        but is not a symlink to /proc/mounts. Please ensure that
-        /etc/mtab is a proper symlink.
-
         systemd will warn you during boot if /usr is on a different
         file system than /. While in systemd itself very little will
         break if /usr is on a separate partition, many of its
@@ -267,3 +265,8 @@ WARNINGS:
         servers if not specified otherwise at configure time. You
         really should not ship an OS or device with this default
         setting. See DISTRO_PORTING for details.
+
+ENGINEERING AND CONSULTING SERVICES:
+        Kinvolk (https://kinvolk.io) offers professional engineering
+        and consulting services for systemd. Please contact Chris Kühl
+        <chris@kinvolk.io> for more information.
index 5abe2073c29f0a43f8f21c868ed72a44be3137e7..dcd14ba94fb5dcfbc66bef9b33f96022a2ed4937 100644 (file)
--- a/README.md
+++ b/README.md
@@ -5,5 +5,14 @@
 
 ## Details
 
- * General information about systemd can be found in the [systemd Wiki](http://www.freedesktop.org/wiki/Software/systemd)
- * Information about build requirements are provided in the [README file](../master/README)
+General information about systemd can be found in the [systemd Wiki](http://www.freedesktop.org/wiki/Software/systemd).
+
+Information about build requirements are provided in the [README file](../master/README).
+
+Consult our [NEWS file](../master/NEWS) for information about what's new in the most recent systemd versions.
+
+Please see our [Contribution Guidelines](../master/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
+
+When preparing patches for systemd, please follow our [Coding Style Guidelines](../master/CODING_STYLE).
+
+If you are looking for support, please contact our [mailing list](http://lists.freedesktop.org/mailman/listinfo/systemd-devel) or join our [IRC channel](irc://irc.freenode.org/%23systemd).
diff --git a/TODO b/TODO
index 10a20758bab4df800d751fe1e3da06fb656a1c52..7437938bf0e12bba82fe9c2f62c0cf3c001a56d0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -33,6 +33,19 @@ Janitorial Clean-ups:
 
 Features:
 
+* delay activation of logind until somebody logs in, or when /dev/tty0 pulls it
+  in or lingering is on (so that containers don't bother with it until PAM is used). also exit-on-idle
+
+* cache sd_event_now() result from before the first iteration...
+
+* remove Capabilities=, after all AmbientCapabilities= and CapabilityBoundingSet= should be enough.
+
+* support for the new copy_file_range() syscall
+
+* add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction
+
+* Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC?
+
 * PID1: find a way how we can reload unit file configuration for
   specific units only, without reloading the whole of systemd
 
@@ -58,8 +71,6 @@ Features:
 
 * consider throwing a warning if a service declares it wants to be "Before=" a .device unit.
 
-* "systemctl edit" should know a mode to create a new unit file
-
 * there's probably something wrong with having user mounts below /sys,
   as we have for debugfs. for exmaple, src/core/mount.c handles mounts
   prefixed with /sys generally special.
@@ -67,12 +78,8 @@ Features:
 
 * man: document that unless you use StandardError=null the shell >/dev/stderr won't work in shell scripts in services
 
-* "systemctl daemon-reload" should result in /etc/systemd/system.conf being reloaded by systemd
-
 * install: include generator dirs in unit file search paths
 
-* invent a better systemd-run scheme for naming scopes, that works with remoting
-
 * rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring
   to unicode chars, to make things more expressive.
 
@@ -103,7 +110,7 @@ Features:
 
 * Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
 
-* core/cgroup: support net_cls modules, and support automatically allocating class ids, then add support for making firewall changes depending on it, to implement a per-service firewall
+* implement a per-service firewall based on net_cls
 
 * Port various tools to make use of verbs.[ch], where applicable
 
@@ -155,8 +162,6 @@ Features:
 
 * maybe provide an API to allow migration of foreign PIDs into existing scopes.
 
-* maybe support a new very "soft" reboot mode, that simply kills all processes, disassembles everything, flushes /run and sysvipc, and then reexecs systemd again
-
 * man: maybe use the word "inspect" rather than "introspect"?
 
 * systemctl: if some operation fails, show log output?
@@ -166,9 +171,9 @@ Features:
 - use equvalent of cat() to insert existing config as a comment, prepended with #.
   Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc.
 
-* exponential backoff in timesyncd and resolved when we cannot reach a server
+* exponential backoff in timesyncd when we cannot reach a server
 
-* timesyncd + resolved: add ugly bus calls to set NTP and DNS servers per-interface, for usage by NM
+* timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM
 
 * extract_many_words() should probably be used by a lot of code that
   currently uses FOREACH_WORD and friends. For example, most conf
@@ -183,23 +188,16 @@ Features:
   (throughout the codebase, not only PID1)
 
 * resolved:
-  - put networkd events and rtnl events at a higher priority, so that
-    we always process them before we process client requests
-  - DNSSEC
-        - add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)?
-  - DNS
-        - search paths
   - mDNS/DNS-SD
+        - service registration
+        - service/domain/types browsing
         - avahi compat
   - DNS-SD service registration from socket units
-  - edns0
-  - dname: Not necessary for plain DNS as synthesized cname is handed out instead if we do not
-           announce dname support. However, for DNSSEC it is necessary as the synthesized cname
-           will not be signed.
-  - cname on PTR (?)
   - resolved should optionally register additional per-interface LLMNR
     names, so that for the container case we can establish the same name
     (maybe "host") for referencing the server, everywhere.
+  - enable DNSSEC by default
+  - allow clients to request DNSSEC for a single lookup even if DNSSEC is off (?)
 
 * refcounting in sd-resolve is borked
 
@@ -213,8 +211,6 @@ Features:
 
 * generator that automatically discovers btrfs subvolumes, identifies their purpose based on some xattr on them.
 
-* timer units: actually add extra delays to timer units with high AccuracySec values, don't start them already when we are awake...
-
 * a way for container managers to turn off getty starting via $container_headless= or so...
 
 * figure out a nice way how we can let the admin know what child/sibling unit causes cgroup membership for a specific unit
@@ -339,10 +335,6 @@ Features:
   - generate a failure of a default event loop is executed out-of-thread
   - maybe add support for inotify events
 
-* in the final killing spree, detect processes from the root directory, and
-  complain loudly if they have argv[0][0] == '@' set.
-  https://bugzilla.redhat.com/show_bug.cgi?id=961044
-
 * investigate endianness issues of UUID vs. GUID
 
 * dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we
@@ -491,10 +483,6 @@ Features:
   - journal-or-kmsg is currently broken? See reverted
     commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8.
   - man: document that corrupted journal files is nothing to act on
-  - systemd-journal-upload (or a new, related tool): allow pushing out
-    journal messages onto the network in BSD syslog protocol,
-    continuously. Default to some link-local IP mcast group, to make this
-    useful as a one-stop debugging tool.
   - rework journald sigbus stuff to use mutex
   - Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our
     services that run under their own user ids, and use User= (but only
@@ -609,8 +597,6 @@ Features:
     removed or added to an existing machine
   - "machinectl migrate" or similar to copy a container from or to a
     difference host, via ssh
-  - man: document how update dkr images works with machinectl
-    http://lists.freedesktop.org/archives/systemd-devel/2015-February/028630.html
   - introduce systemd-nspawn-ephemeral@.service, and hook it into
     "machinectl start" with a new --ephemeral switch
   - "machinectl status" should also show internal logs of the container in
@@ -623,8 +609,6 @@ Features:
     shell in it, and marks it read-only after use
 
 * importd:
-  - dkr: support tarsum checksum verification, if it becomes reality one day...
-  - dkr: convert json bits to nspawn configuration
   - generate a nice warning if mkfs.btrfs is missing
 
 * cryptsetup:
@@ -661,10 +645,6 @@ Features:
 * coredump:
   - save coredump in Windows/Mozilla minidump format
   - move PID 1 segfaults to /var/lib/systemd/coredump?
-  - make the handler check /proc/$PID/rlimits for RLIMIT_CORE,
-    and supress coredump if turned off. Then change RLIMIT_CORE to
-    infinity by default for all services. This then allows per-service
-    control of coredumping.
 
 * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
 
@@ -736,7 +716,6 @@ Features:
   - Support --test based on current system state
   - If we show an error about a unit (such as not showing up) and it has no Description string, then show a description string generated form the reverse of unit_name_mangle().
   - after deserializing sockets in socket.c we should reapply sockopts and things
-  - make timer units go away after they elapsed
   - drop PID 1 reloading, only do reexecing (difficult: Reload()
     currently is properly synchronous, Reexec() is weird, because we
     cannot delay the response properly until we are back, so instead of
index 4488c835a8169f25cb4a3a0cc884883669451eb8..077f182a5a7ad78ed9d7d334d188b06501192d54 100644 (file)
@@ -38,6 +38,21 @@ Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 The system journal process has shut down and closed all currently
 active journal files.
 
+-- ec387f577b844b8fa948f33cad9a75e6
+Subject: Disk space used by the journal
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+@JOURNAL_NAME@ (@JOURNAL_PATH@) is currently using @CURRENT_USE_PRETTY@.
+Maximum allowed usage is set to @MAX_USE_PRETTY@.
+Leaving at least @DISK_KEEP_FREE_PRETTY@ free (of currently available @DISK_AVAILABLE_PRETTY@ of disk space).
+Enforced usage limit is thus @LIMIT_PRETTY@, of which @AVAILABLE_PRETTY@ are still available.
+
+The limits controlling how much disk space is used by the journal may
+be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=,
+RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in
+/etc/systemd/journald.conf. See journald.conf(5) for details.
+
 -- a596d6fe7bfa4994828e72309e95d61e
 Subject: Messages from a service have been suppressed
 Defined-By: systemd
@@ -278,3 +293,42 @@ Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 
 The virtual machine @NAME@ with its leader PID @LEADER@ has been
 shut down.
+
+-- 36db2dfa5a9045e1bd4af5f93e1cf057
+Subject: DNSSEC mode has been turned off, as server doesn't support it
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8) resolved.conf(5)
+
+The resolver service (systemd-resolved.service) has detected that the
+configured DNS server does not support DNSSEC, and DNSSEC validation has been
+turned off as result.
+
+This event will take place if DNSSEC=allow-downgrade is configured in
+resolved.conf and the configured DNS server is incompatible with DNSSEC. Note
+that using this mode permits DNSSEC downgrade attacks, as an attacker might be
+able turn off DNSSEC validation on the system by inserting DNS replies in the
+communication channel that result in a downgrade like this.
+
+This event might be indication that the DNS server is indeed incompatible with
+DNSSEC or that an attacker has successfully managed to stage such a downgrade
+attack.
+
+-- 1675d7f172174098b1108bf8c7dc8f5d
+Subject: DNSSEC validation failed
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8)
+
+A DNS query or resource record set failed DNSSEC validation. This is usually
+indication that the communication channel used was tampered with.
+
+-- 4d4408cfd0d144859184d1e65d7c8a65
+Subject: A DNSSEC trust anchor has been revoked
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8)
+
+A DNSSEC trust anchor has been revoked. A new trust anchor has to be
+configured, or the operating system needs to be updated, to provide an updated
+DNSSEC trust anchor.
diff --git a/catalog/systemd.hu.catalog b/catalog/systemd.hu.catalog
new file mode 100644 (file)
index 0000000..30d7691
--- /dev/null
@@ -0,0 +1,262 @@
+#  This file is part of systemd.
+#
+#  Copyright 2012 Lennart Poettering
+#  Copyright 2016 Gabor Kelemen
+#
+#  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/>.
+
+# Message catalog for systemd's own messages
+
+# The catalog format is documented on
+# http://www.freedesktop.org/wiki/Software/systemd/catalog
+
+# For an explanation why we do all this, see https://xkcd.com/1024/
+
+-- f77379a8490b408bbe5f6940505a777b
+Subject: A napló elindult
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszernapló folyamat elindult, megnyitotta írásra a naplófájlokat,
+és most készen áll kérések feldolgozására.
+
+-- d93fb3c9c24d451a97cea615ce59c00b
+Subject: A napló leállt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszernapló folyamat leállt, és bezárt minden jelenleg aktív naplófájlt.
+
+-- a596d6fe7bfa4994828e72309e95d61e
+Subject: Egy szolgáltatás üzenetei elnémítva
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:journald.conf(5)
+
+Egy szolgáltatás túl sok üzenetet naplózott adott idő alatt. A 
+szolgáltatástól származó üzenetek eldobásra kerültek.
+
+Ne feledje, hogy csak a kérdéses szolgáltatás üzenetei kerültek eldobásra,
+ más szolgáltatások üzeneteit ez nem befolyásolja. 
+
+Az üzenetek eldobását vezérlő korlátok az /etc/systemd/journald.conf
+RateLimitInterval= és RateLimitBurst= beállításaival adhatók meg.
+Részletekért lásd a journald.conf(5) man oldalt.
+
+-- e9bf28e6e834481bb6f48f548ad13606
+Subject: Naplóüzenetek vesztek el
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Kernelüzenetek vesztek el, mert a naplózó rendszer nem tudta elég gyorsan
+feldolgozni azokat.
+
+-- fc2e22bc6ee647b6b90729ab34a250b1
+Subject: Egy folyamat összeomlott: @COREDUMP_PID@ (@COREDUMP_COMM@)
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:core(5)
+
+Ez a folyamat: @COREDUMP_PID@ (@COREDUMP_COMM@) összeomlott, és core fájlt
+ írt ki.
+
+Ez általában programozási hibát jelez az összeomló programban, és 
+a szállítója felé kell bejelenteni.
+
+-- 8d45620c1a4348dbb17410da57c60c66
+Subject: Új munkamenet (@SESSION_ID@) létrehozva, felhasználója: @USER_ID@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+Létrejött egy új munkamenet @SESSION_ID@ azonosítóval ezen felhasználóhoz:
+@USER_ID@.
+
+A munkamenet vezető folyamata: @LEADER@.
+
+-- 3354939424b4456d9802ca8333ed424a
+Subject: Munkamenet (@SESSION_ID@) befejezve
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+A következő azonosítójú munkamenet befejeződött: @SESSION_ID@.
+
+-- fcbefc5da23d428093f97c82a9290f7b
+Subject: Elérhető egy új munkaállomás: @SEAT_ID@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+Beállításra kerül és használható egy új munkaállomás: @SEAT_ID@.
+
+-- e7852bfe46784ed0accde04bc864c2d5
+Subject: A munkaállomás eltávolítva: @SEAT_ID@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+A munkaállomás el lett távolítva, és már nem érhető el: @SEAT_ID@
+
+-- c7a787079b354eaaa9e77b371893cd27
+Subject: Időmódosítás
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszeróra beállítva @REALTIME@ ezredmásodpercre 1970. január 1. után.
+
+-- 45f82f4aef7a4bbf942ce861d1f20990
+Subject: Időzóna-módosítás erre: @TIMEZONE@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszer időzónája módosítva lett erre: @TIMEZONE@.
+
+-- b07a249cd024414a82dd00cd181378ff
+Subject: A rendszer indítása kész
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszerindításkor szükséges indításhoz sorba állított összes 
+rendszerszolgáltatás elindult. Ne feledje, hogy ez nem jelenti, hogy a 
+gép üresjáratban van, mivel egyes szolgáltatások még az indítás 
+befejezésével lehetnek elfoglalva.
+
+A kernel indítása @KERNEL_USEC@ ezredmásodpercet igényelt.
+
+A kiinduló RAM lemez indítása @INITRD_USEC@ ezredmásodpercet igényelt.
+
+A felhasználói programok indítása @USERSPACE_USEC@ ezredmásodpercet igényelt.
+
+-- 6bbd95ee977941e497c48be27c254128
+Subject: A rendszer „@SLEEP@” alvási állapotba lépett
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszer belépett ebbe az alvási állapotba: @SLEEP@.
+
+-- 8811e6df2a8e40f58a94cea26f8ebf14
+Subject: A rendszer „@SLEEP@” alvási állapotból kilépett
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A rendszer kilépett ebből az alvási állapotból: @SLEEP@.
+
+-- 98268866d1d54a499c4e98921d93bc40
+Subject: Rendszer leállítása kezdeményezve
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A systemd leállítása kezdeményezve. A leállítás megkezdődött, minden
+rendszerszolgáltatás befejeződik, minden fájlrendszer leválasztásra kerül.
+
+-- 7d4958e842da4a758f6c1cdc7b36dcc5
+Subject: A(z) @UNIT@ egység indítása megkezdődött
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység megkezdte az indulást.
+
+-- 39f53479d3a045ac8e11786248231fbf
+Subject: A(z) @UNIT@ egység befejezte az indulást
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység befejezte az indulást
+
+Az indítás eredménye: @RESULT@.
+
+-- de5b426a63be47a7b6ac3eaac82e2f6f
+Subject: A(z) @UNIT@ egység megkezdte a leállást
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység megkezdte a leállást.
+
+-- 9d1aaa27d60140bd96365438aad20286
+Subject: A(z) @UNIT@ egység befejezte a leállást
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység befejezte a leállást.
+
+-- be02cf6855d2428ba40df7e9d022f03d
+Subject: A(z) @UNIT@ egység hibát jelzett
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység hibát jelzett.
+
+Az eredmény: @RESULT@.
+
+-- d34d037fff1847e6ae669a370e694725
+Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység megkezdte a beállításainak újratöltését.
+
+-- 7b05ebc668384222baa8881179cfda54
+Subject: A(z) @UNIT@ egység befejezte a beállításainak újratöltését
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @UNIT@ egység befejezte a beállításainak újratöltését.
+
+Az eredmény: @RESULT@.
+
+-- 641257651c1b4ec9a8624d7a40a9e1e7
+Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A folyamat végrehajtása sikertelen volt, és hibát jelzett: @EXECUTABLE@.
+
+A folyamat által visszaadott hibaszám: @ERRNO@.
+
+-- 0027229ca0644181a76c4e92458afa2e
+Subject: Legalább egy üzenet nem továbbítható a rendszernaplónak
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Legalább egy üzenet nem volt továbbítható a journald-vel párhuzamosan futó
+syslog szolgáltatásnak. Ez általában azt jelenti, hogy a syslog
+megvalósítás nem volt képes lépést tartani a sorba állított
+üzenetek sebességével.
+
+-- 1dee0369c7fc4736b7099b38ecb46ee7
+Subject: A csatolási pont nem üres
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A csatolási pontként megadott @WHERE@ könyvtár (második mező az /etc/fstab
+fájlban, vagy a Where= sor a systemd egységfájlban) nem üres. Ez nem
+akadályozza meg a csatolást, de a könyvtárban már meglévő fájlok
+elérhetetlenné válnak. A fájlok láthatóvá tételéhez csatolja
+az azokat tartalmazó fájlrendszert egy másodlagos helyre. 
+
+-- 24d8d4452573402496068381a6312df2
+Subject: Egy virtuális gép vagy konténer elindult
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) elindult, és 
+használatra kész.
+
+-- 58432bd3bace477cb514b56381b8a758
+Subject: Egy virtuális gép vagy konténer befejeződött
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) leállt.
index 03eea04c9f5a1a72e13eb61d998c6b20c6960a7e..eedbb8aa9c44bcb7d8ced2d896610fe65a518d3e 100644 (file)
@@ -1,7 +1,7 @@
 #  This file is part of systemd.
 #
 #  Copyright 2012 Lennart Poettering
-#  Copyright 2013 Sergey Ptashnick
+#  Copyright 2013-2016 Sergey Ptashnick
 #
 #  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
@@ -43,6 +43,25 @@ Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 Процесс, отвечающий за журналирование системных событий, завершил работу и
 закрыл все свои файлы.
 
+# Subject: Disk space used by the journal
+-- ec387f577b844b8fa948f33cad9a75e6
+Subject: Место на диске, занятое журналом
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+@JOURNAL_NAME@ (@JOURNAL_PATH@) сейчас занимает @CURRENT_USE_PRETTY@.
+Максимальный разрешенный размер составляет @MAX_USE_PRETTY@.
+Оставляем свободными как минимум @DISK_KEEP_FREE_PRETTY@ (сейчас на диске 
+свободно @DISK_AVAILABLE_PRETTY@).
+Таким образом, предел использования составляет @LIMIT_PRETTY@, из которых
+@AVAILABLE_PRETTY@ пока свободно.
+
+Ограничения на размер журнала настраиваются при помощи параметров
+SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, 
+RuntimeKeepFree=, RuntimeMaxFileSize= в файле /etc/systemd/journald.conf.
+Более подробные сведения вы можете получить на справочной странице 
+journald.conf(5).
+
 # Subject: Messages from a service have been suppressed
 -- a596d6fe7bfa4994828e72309e95d61e
 Subject: Часть сообщений от службы пропущена
@@ -292,3 +311,44 @@ Defined-By: systemd
 Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
 
 Виртуальная машина @NAME@ (идентификатор главного процесса: @LEADER@) выключена.
+
+# Subject: DNSSEC mode has been turned off, as server doesn't support it
+-- 36db2dfa5a9045e1bd4af5f93e1cf057
+Subject: Механизм DNSSEC был отключен, так как DNS-сервер его не поддерживает
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8) resolved.conf(5)
+
+Служба разрешения имен хостов (systemd-resolved.service) определила, что
+указанный в настойках DNS-сервер не поддерживает технологию DNSSEC, и 
+автоматически отключила DNSSEC-проверки.
+
+Данное событие возникает, если в файле resolved.conf указан параметр
+DNSSEC=allow-downgrade, и вышестоящий DNS-сервер не поддерживает DNSSEC.
+Обратите внимание, что режим allow-downgrade допускает возможность атаки
+"DNSSEC downgrade", в ходе которой атакующий хакер блокирует проверки DNSSEC
+путем отправки ложных сообщений от имени DNS-сервера.
+
+Возникновение данного события может свидетельствовать как о том, что ваш 
+DNS-сервер не поддерживает DNSSEC, так и о том, что некий хакер успешно провел
+против вас атаку, направленную на блокировку DNSSEC-проверок.
+
+# Subject: DNSSEC validation failed
+-- 1675d7f172174098b1108bf8c7dc8f5d
+Subject: Проверка DNSSEC провалена
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8)
+
+DNS-запрос или отдельная ресурсная запись не прошла проверку DNSSEC.
+Как правило, это свидетельствует о постороннем вмешательстве в канал связи.
+
+# Subject: A DNSSEC trust anchor has been revoked
+-- 4d4408cfd0d144859184d1e65d7c8a65
+Subject: Открытый ключ DNSSEC был отозван
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:systemd-resolved.service(8)
+
+Открытый ключ (trust ahcnor) DNSSEC был отозван. Необходимо настроить новый 
+открытый ключ, либо обновить систему, чтобы получить обновленный открытый ключ.
diff --git a/coccinelle/xsprintf.cocci b/coccinelle/xsprintf.cocci
new file mode 100644 (file)
index 0000000..401216a
--- /dev/null
@@ -0,0 +1,6 @@
+@@
+expression e, fmt;
+expression list vaargs;
+@@
+- snprintf(e, sizeof(e), fmt, vaargs);
++ xsprintf(e, fmt, vaargs);
index ec30ff12ae32a61327b8d92a9b18124c6fab86e9..5fd73c59f15a22166b64f1606d143dc32d34fada 100644 (file)
@@ -20,7 +20,7 @@
 AC_PREREQ([2.64])
 
 AC_INIT([systemd],
-        [228],
+        [229],
         [http://github.com/systemd/systemd/issues],
         [systemd],
         [http://www.freedesktop.org/wiki/Software/systemd])
@@ -297,7 +297,8 @@ AC_SUBST(CAP_LIBS)
 
 AC_CHECK_FUNCS([memfd_create])
 AC_CHECK_FUNCS([__secure_getenv secure_getenv])
-AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, renameat2, kcmp, keyctl, key_serial_t, LO_FLAGS_PARTSCAN],
+AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, renameat2,
+                kcmp, keyctl, key_serial_t, char16_t, char32_t, LO_FLAGS_PARTSCAN],
                [], [], [[
 #include <sys/types.h>
 #include <unistd.h>
@@ -555,7 +556,7 @@ AM_CONDITIONAL(HAVE_ZLIB, [test "$have_zlib" = "yes"])
 
 # ------------------------------------------------------------------------------
 have_bzip2=no
-AC_ARG_ENABLE(bzip2, AS_HELP_STRING([--enable-bzip2], [Disable optional BZIP2 support]))
+AC_ARG_ENABLE(bzip2, AS_HELP_STRING([--enable-bzip2], [Enable optional BZIP2 support]))
 AS_IF([test "x$enable_bzip2" != "xno"], [
         AC_CHECK_HEADERS(bzlib.h,
                 [AC_DEFINE(HAVE_BZIP2, 1, [Define if BZIP2 is available])
@@ -668,11 +669,14 @@ AC_ARG_ENABLE([smack], AS_HELP_STRING([--disable-smack],[Disable optional SMACK
                 esac],
                 [have_smack=auto])
 
-if test "x${have_smack}" = xauto; then
+if test "x${have_smack}" != xno; then
+        AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
         M4_DEFINES="$M4_DEFINES -DHAVE_SMACK"
         have_smack=yes
 fi
 
+AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"])
+
 have_smack_run_label=no
 AC_ARG_WITH(smack-run-label,
 AS_HELP_STRING([--with-smack-run-label=STRING],
@@ -690,12 +694,6 @@ AS_HELP_STRING([--with-smack-default-process-label=STRING],
         [AC_DEFINE_UNQUOTED(SMACK_DEFAULT_PROCESS_LABEL, ["$withval"], [Default SMACK label for executed processes])],
         [])
 
-if test "x${have_smack}" = xyes ; then
-        AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
-fi
-
-AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"])
-
 # ------------------------------------------------------------------------------
 AC_ARG_ENABLE([gcrypt],
         AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
@@ -708,7 +706,7 @@ AC_ARG_ENABLE([gcrypt],
 
 if test "x${have_gcrypt}" != xno ; then
         m4_define([AM_PATH_LIBGCRYPT_FAIL],
-                [{ test "x$have_gcrypt" != xyes || AC_MSG_ERROR([*** GCRYPT headers not found.]); }]
+                [{ test "x$have_gcrypt" != xyes || AC_MSG_ERROR([*** GCRYPT/GPG-ERROR headers not found.]); }]
         )
         m4_ifdef([AM_PATH_LIBGCRYPT], [AM_PATH_LIBGCRYPT(
                         [1.4.5],
@@ -723,12 +721,22 @@ if test "x${have_gcrypt}" != xno ; then
                 [AM_PATH_LIBGCRYPT_FAIL]
         )
 
-        if test "x$have_gcrypt" = xyes ; then
-                GCRYPT_LIBS="$LIBGCRYPT_LIBS"
-                GCRYPT_CFLAGS="$LIBGCRYPT_CFLAGS"
+        have_gpg_error=no
+        m4_ifdef([AM_PATH_GPG_ERROR], [AM_PATH_GPG_ERROR(
+                        [1.12],
+                        [have_gpg_error=yes],
+                        [AM_PATH_LIBGCRYPT_FAIL]
+                )],
+                [AM_PATH_LIBGCRYPT_FAIL]
+        )
+
+        if test "x$have_gcrypt" = xyes -a "x$have_gpg_error" = xyes ; then
+                GCRYPT_LIBS="$LIBGCRYPT_LIBS $GPG_ERROR_LIBS"
+                GCRYPT_CFLAGS="$LIBGCRYPT_CFLAGS $GPG_ERROR_CFLAGS"
                 AC_DEFINE(HAVE_GCRYPT, 1, [GCRYPT available])
         else
                 have_gcrypt=no
+                have_gpg_error=no
         fi
 else
         GCRYPT_LIBS=
@@ -838,18 +846,6 @@ if test "x$enable_qrencode" != "xno"; then
 fi
 AM_CONDITIONAL(HAVE_QRENCODE, [test "$have_qrencode" = "yes"])
 
-# ------------------------------------------------------------------------------
-have_microhttpd=no
-AC_ARG_ENABLE(microhttpd, AS_HELP_STRING([--disable-microhttpd], [disable microhttpd support]))
-if test "x$enable_microhttpd" != "xno"; then
-        PKG_CHECK_MODULES(MICROHTTPD, [libmicrohttpd >= 0.9.33],
-                [AC_DEFINE(HAVE_MICROHTTPD, 1, [Define if microhttpd is available]) have_microhttpd=yes], have_microhttpd=no)
-        if test "x$have_microhttpd" = xno -a "x$enable_microhttpd" = xyes; then
-                AC_MSG_ERROR([*** microhttpd support requested but libraries not found])
-        fi
-fi
-AM_CONDITIONAL(HAVE_MICROHTTPD, [test "$have_microhttpd" = "yes"])
-
 # ------------------------------------------------------------------------------
 have_gnutls=no
 AC_ARG_ENABLE(gnutls, AS_HELP_STRING([--disable-gnutls], [disable gnutls support]))
@@ -862,18 +858,39 @@ if test "x$enable_gnutls" != "xno"; then
 fi
 AM_CONDITIONAL(HAVE_GNUTLS, [test "$have_gnutls" = "yes"])
 
+# ------------------------------------------------------------------------------
+have_microhttpd=no
+AC_ARG_ENABLE(microhttpd, AS_HELP_STRING([--disable-microhttpd], [disable microhttpd support]))
+if test "x$enable_microhttpd" != "xno"; then
+        PKG_CHECK_MODULES(MICROHTTPD, [libmicrohttpd >= 0.9.33],
+                [AC_DEFINE(HAVE_MICROHTTPD, 1, [Define if microhttpd is available])
+                 have_microhttpd=yes
+                 M4_DEFINES="$M4_DEFINES -DHAVE_MICROHTTPD"],
+                [have_microhttpd=no])
+        if test "x$have_microhttpd" = xno -a "x$enable_microhttpd" = xyes; then
+                AC_MSG_ERROR([*** microhttpd support requested but libraries not found])
+        fi
+fi
+AM_CONDITIONAL(HAVE_MICROHTTPD, [test "$have_microhttpd" = "yes"])
+
 # ------------------------------------------------------------------------------
 have_libcurl=no
 AC_ARG_ENABLE(libcurl, AS_HELP_STRING([--disable-libcurl], [disable libcurl support]))
 if test "x$enable_libcurl" != "xno"; then
         PKG_CHECK_MODULES(LIBCURL, [libcurl],
-                [AC_DEFINE(HAVE_LIBCURL, 1, [Define if libcurl is available]) have_libcurl=yes], have_libcurl=no)
+                [AC_DEFINE(HAVE_LIBCURL, 1, [Define if libcurl is available])
+                 have_libcurl=yes
+                 M4_DEFINES="$M4_DEFINES -DHAVE_LIBCURL"],
+                [have_libcurl=no])
         if test "x$have_libcurl" = xno -a "x$enable_libcurl" = xyes; then
                 AC_MSG_ERROR([*** libcurl support requested but libraries not found])
         fi
 fi
 AM_CONDITIONAL(HAVE_LIBCURL, [test "$have_libcurl" = "yes"])
 
+# ------------------------------------------------------------------------------
+AM_CONDITIONAL(HAVE_REMOTE, [test "$have_microhttpd" = "yes" -o "$have_libcurl" = "yes"])
+
 # ------------------------------------------------------------------------------
 have_libidn=no
 AC_ARG_ENABLE(libidn, AS_HELP_STRING([--disable-libidn], [Disable optional LIBIDN support]))
@@ -1089,6 +1106,7 @@ have_coredump=no
 AC_ARG_ENABLE(coredump, AS_HELP_STRING([--disable-coredump], [disable coredump hook]))
 if test "x$enable_coredump" != "xno"; then
         have_coredump=yes
+        M4_DEFINES="$M4_DEFINES -DENABLE_COREDUMP"
 fi
 AM_CONDITIONAL(ENABLE_COREDUMP, [test "$have_coredump" = "yes"])
 
@@ -1159,7 +1177,7 @@ AC_SUBST([EFI_ARCH])
 AC_SUBST([EFI_MACHINE_TYPE_NAME])
 
 have_gnuefi=no
-AC_ARG_ENABLE(gnuefi, AS_HELP_STRING([--enable-gnuefi], [Disable optional gnuefi support]))
+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_DEFINE(HAVE_GNUEFI, 1, [Define if gnuefi is available])
@@ -1285,9 +1303,9 @@ AM_CONDITIONAL(ENABLE_HWDB, [test x$enable_hwdb = xyes])
 # ------------------------------------------------------------------------------
 have_manpages=no
 AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages]))
+AC_PATH_PROG([XSLTPROC], [xsltproc])
 AS_IF([test "x$enable_manpages" != xno], [
        have_manpages=yes
-       AC_PATH_PROG([XSLTPROC], [xsltproc])
        AS_IF([test -z "$XSLTPROC"],
              AC_MSG_ERROR([*** xsltproc is required for man pages]))
 ])
@@ -1421,14 +1439,6 @@ AC_ARG_ENABLE([split-usr],
                 enable_split_usr=no
         ])])
 
-AC_ARG_WITH([dkr-index-url],
-        [AS_HELP_STRING([--dkr-index-url=URL], [Specify the default index URL to use for image downloads])],
-        [DEFAULT_DKR_INDEX_URL="\"$withval\""],
-        [DEFAULT_DKR_INDEX_URL="NULL"])
-
-AC_DEFINE_UNQUOTED(DEFAULT_DKR_INDEX_URL, [$DEFAULT_DKR_INDEX_URL], [Default index URL to use for image downloads])
-AC_SUBST(DEFAULT_DKR_INDEX_URL)
-
 AS_IF([test "x${enable_split_usr}" = "xyes"], [
         AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr])
 ])
@@ -1597,7 +1607,6 @@ AC_MSG_RESULT([
         Maximum System UID:      ${SYSTEM_UID_MAX}
         Maximum System GID:      ${SYSTEM_GID_MAX}
         Certificate root:        ${CERTIFICATEROOT}
-        Default dkr Index        ${DEFAULT_DKR_INDEX_URL}
 
         CFLAGS:                  ${OUR_CFLAGS} ${CFLAGS}
         CPPFLAGS:                ${OUR_CPPFLAGS} ${CPPFLAGS}
index 62e77714c4c8c54cf28ce008c0f7c5912871955d..80f18907142a5dc8b5184fbb0e8993d78dd1790c 100644 (file)
@@ -629,9 +629,6 @@ OUI:001BC508C*
 OUI:001BC5090*
  ID_OUI_FROM_DATABASE=Seven Solutions S.L
 
-OUI:001BC5087*
- ID_OUI_FROM_DATABASE=Onnet Technologies And Innovations
-
 OUI:001BC507D*
  ID_OUI_FROM_DATABASE=Greatcom AG
 
@@ -779,6 +776,78 @@ OUI:70B3D5A6F*
 OUI:70B3D5929*
  ID_OUI_FROM_DATABASE=OutSys
 
+OUI:70B3D5120*
+ ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH
+
+OUI:70B3D523E*
+ ID_OUI_FROM_DATABASE=Tornado Modular Systems
+
+OUI:70B3D5EA2*
+ ID_OUI_FROM_DATABASE=Transportal Solutions Ltd
+
+OUI:70B3D545D*
+ ID_OUI_FROM_DATABASE=Sensapex Oy
+
+OUI:70B3D58B0*
+ ID_OUI_FROM_DATABASE=IES S.r.l.
+
+OUI:70B3D5FB6*
+ ID_OUI_FROM_DATABASE=KRONOTECH SRL
+
+OUI:70B3D5EB7*
+ ID_OUI_FROM_DATABASE=Skreens
+
+OUI:70B3D538F*
+ ID_OUI_FROM_DATABASE=Sorynorydotcom Inc
+
+OUI:70B3D57E9*
+ ID_OUI_FROM_DATABASE=Mecsel Oy
+
+OUI:70B3D506C*
+ ID_OUI_FROM_DATABASE=AppTek
+
+OUI:70B3D5818*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5895*
+ ID_OUI_FROM_DATABASE=Integrated Control Corp.
+
+OUI:70B3D5232*
+ ID_OUI_FROM_DATABASE=UCONSYS
+
+OUI:70B3D501A*
+ ID_OUI_FROM_DATABASE=Cubro Acronet GesmbH
+
+OUI:70B3D537B*
+ ID_OUI_FROM_DATABASE=Power Ltd.
+
+OUI:70B3D5FCC*
+ ID_OUI_FROM_DATABASE=DIgSILENT GmbH
+
+OUI:70B3D5FD8*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
+OUI:70B3D576B*
+ ID_OUI_FROM_DATABASE=EMPELOR GmbH
+
+OUI:70B3D50B8*
+ ID_OUI_FROM_DATABASE=Lucas-Nülle GmbH
+
+OUI:70B3D5FEB*
+ ID_OUI_FROM_DATABASE=Les distributions Multi-Secure incorporee
+
+OUI:70B3D5658*
+ ID_OUI_FROM_DATABASE=emperor brands
+
+OUI:70B3D53A9*
+ ID_OUI_FROM_DATABASE=Vivalnk
+
+OUI:001BC5087*
+ ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC
+
+OUI:70B3D5720*
+ ID_OUI_FROM_DATABASE=Private
+
 OUI:70B3D5D60*
  ID_OUI_FROM_DATABASE=Flintab AB
 
@@ -1130,9 +1199,6 @@ OUI:70B3D5DE7*
 OUI:70B3D51F4*
  ID_OUI_FROM_DATABASE=Hangzhou Woosiyuan Communication Co.,Ltd.
 
-OUI:70B3D5B7E*
- ID_OUI_FROM_DATABASE=Elbit Systems of America - FMF Operations
-
 OUI:70B3D5092*
  ID_OUI_FROM_DATABASE=inomed Medizintechnik GmbH
 
@@ -1472,6 +1538,102 @@ OUI:70B3D5384*
 OUI:70B3D5893*
  ID_OUI_FROM_DATABASE=Cubitech
 
+OUI:70B3D509E*
+ ID_OUI_FROM_DATABASE=MobiPromo
+
+OUI:70B3D549E*
+ ID_OUI_FROM_DATABASE=CAPTEMP, Lda
+
+OUI:70B3D54B6*
+ ID_OUI_FROM_DATABASE=VEILUX INC.
+
+OUI:70B3D57CF*
+ ID_OUI_FROM_DATABASE=ORCA Technologies, LLC
+
+OUI:70B3D55A3*
+ ID_OUI_FROM_DATABASE=CT Company
+
+OUI:70B3D580A*
+ ID_OUI_FROM_DATABASE=SENSING LABS
+
+OUI:70B3D5E45*
+ ID_OUI_FROM_DATABASE=Momentum Data Systems
+
+OUI:70B3D5059*
+ ID_OUI_FROM_DATABASE=Pro-Digital Projetos Eletronicos Ltda
+
+OUI:70B3D5091*
+ ID_OUI_FROM_DATABASE=PROFITT Ltd
+
+OUI:70B3D5647*
+ ID_OUI_FROM_DATABASE=KZTA
+
+OUI:70B3D56DF*
+ ID_OUI_FROM_DATABASE=Mango DSP, Inc.
+
+OUI:70B3D5CBE*
+ ID_OUI_FROM_DATABASE=Ensura Solutions BV
+
+OUI:70B3D5CAC*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D58B9*
+ ID_OUI_FROM_DATABASE=Toptech Systems, Inc.
+
+OUI:70B3D574E*
+ ID_OUI_FROM_DATABASE=PushCorp, Inc.
+
+OUI:70B3D5FD2*
+ ID_OUI_FROM_DATABASE=DALIAN  LEVEAR ELECTRIC  CO., LTD
+
+OUI:70B3D5F08*
+ ID_OUI_FROM_DATABASE=Szabo Software & Engineering UK Ltd
+
+OUI:70B3D56A1*
+ ID_OUI_FROM_DATABASE=GLIAL TECHNOLOGY
+
+OUI:70B3D5955*
+ ID_OUI_FROM_DATABASE=Dynacard Co., Ltd.
+
+OUI:70B3D512B*
+ ID_OUI_FROM_DATABASE=RIC Electronics
+
+OUI:70B3D517E*
+ ID_OUI_FROM_DATABASE=OCULI VISION
+
+OUI:70B3D5046*
+ ID_OUI_FROM_DATABASE=Shenzhen Rihuida Electronics Co,. Ltd
+
+OUI:70B3D5268*
+ ID_OUI_FROM_DATABASE=Cardinal Scale Mfg Co
+
+OUI:70B3D5B7E*
+ ID_OUI_FROM_DATABASE=Elbit Systems of America - Fort Worth Operations
+
+OUI:70B3D5DB5*
+ ID_OUI_FROM_DATABASE=Xiamen Point Circle Technologh Co,ltd
+
+OUI:70B3D5429*
+ ID_OUI_FROM_DATABASE=Redco Audio Inc
+
+OUI:70B3D52E7*
+ ID_OUI_FROM_DATABASE=Atos spa
+
+OUI:70B3D5766*
+ ID_OUI_FROM_DATABASE=Tirasoft Nederland
+
+OUI:70B3D517D*
+ ID_OUI_FROM_DATABASE=Entech Electronics
+
+OUI:70B3D599A*
+ ID_OUI_FROM_DATABASE=KEVIC. inc,
+
+OUI:70B3D502A*
+ ID_OUI_FROM_DATABASE=BAE Systems Surface Ships Limited
+
+OUI:70B3D5DE2*
+ ID_OUI_FROM_DATABASE=ACD Elekronik GmbH
+
 OUI:70B3D5FFF*
  ID_OUI_FROM_DATABASE=Private
 
@@ -1961,9 +2123,6 @@ OUI:70B3D5AC8*
 OUI:70B3D5F2A*
  ID_OUI_FROM_DATABASE=WIBOND Informationssysteme GmbH
 
-OUI:70B3D5C24*
- ID_OUI_FROM_DATABASE=Elbit Systems of America
-
 OUI:70B3D52A5*
  ID_OUI_FROM_DATABASE=Taitotekniikka
 
@@ -2141,6 +2300,93 @@ OUI:70B3D55D1*
 OUI:70B3D5A2E*
  ID_OUI_FROM_DATABASE=Kokam Co., Ltd
 
+OUI:70B3D58A6*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5FB5*
+ ID_OUI_FROM_DATABASE=Orange Tree Technologies Ltd
+
+OUI:70B3D5E02*
+ ID_OUI_FROM_DATABASE=YEHL & JORDAN LLC
+
+OUI:70B3D5F56*
+ ID_OUI_FROM_DATABASE=VirtualHere Pty. Ltd.
+
+OUI:70B3D58BE*
+ ID_OUI_FROM_DATABASE=Connoiseur Electronics Private Limited
+
+OUI:70B3D526B*
+ ID_OUI_FROM_DATABASE=Sorama BV
+
+OUI:70B3D52FA*
+ ID_OUI_FROM_DATABASE=Toray Medical Co.,Ltd
+
+OUI:70B3D5975*
+ ID_OUI_FROM_DATABASE=Coester Automação Ltda
+
+OUI:70B3D513C*
+ ID_OUI_FROM_DATABASE=Detec Systems Ltd
+
+OUI:70B3D5455*
+ ID_OUI_FROM_DATABASE=Heartlandmicropayments
+
+OUI:70B3D5070*
+ ID_OUI_FROM_DATABASE=Lumiplan Duhamel
+
+OUI:70B3D58D8*
+ ID_OUI_FROM_DATABASE=VNG Corporation
+
+OUI:70B3D5392*
+ ID_OUI_FROM_DATABASE=Contec DTx
+
+OUI:70B3D514D*
+ ID_OUI_FROM_DATABASE=2-Observe
+
+OUI:70B3D5A9F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D59CB*
+ ID_OUI_FROM_DATABASE=Alligator Communications
+
+OUI:70B3D5B67*
+ ID_OUI_FROM_DATABASE=RedWave Labs Ltd
+
+OUI:70B3D5B93*
+ ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL
+
+OUI:70B3D5B89*
+ ID_OUI_FROM_DATABASE=IDA
+
+OUI:70B3D57E2*
+ ID_OUI_FROM_DATABASE=Depro Électronique inc
+
+OUI:70B3D5772*
+ ID_OUI_FROM_DATABASE=enModus
+
+OUI:70B3D53C5*
+ ID_OUI_FROM_DATABASE=P4Q ELECTRONICS, S.L.
+
+OUI:70B3D5FE2*
+ ID_OUI_FROM_DATABASE=Galileo Tıp Teknolojileri San. ve Tic. A.S.
+
+OUI:70B3D5C24*
+ ID_OUI_FROM_DATABASE=Elbit Systems of America - Fort Worth Operations
+
+OUI:70B3D5AC6*
+ ID_OUI_FROM_DATABASE=SMTC Corporation
+
+OUI:70B3D5028*
+ ID_OUI_FROM_DATABASE=AT-Automation Technology GmbH
+
+OUI:70B3D50B9*
+ ID_OUI_FROM_DATABASE=Easy Digital Concept
+
+OUI:70B3D5CF2*
+ ID_OUI_FROM_DATABASE=tinnos
+
+OUI:70B3D59E0*
+ ID_OUI_FROM_DATABASE=ES Industrial Systems Co., Ltd.
+
 OUI:70B3D566B*
  ID_OUI_FROM_DATABASE=Innitive B.V.
 
@@ -2555,9 +2801,6 @@ OUI:70B3D5710*
 OUI:70B3D5A0B*
  ID_OUI_FROM_DATABASE=ambiHome GmbH
 
-OUI:70B3D58B1*
- ID_OUI_FROM_DATABASE=M-Tech Innovations Ltd
-
 OUI:70B3D5204*
  ID_OUI_FROM_DATABASE=TWC
 
@@ -2762,6 +3005,111 @@ OUI:70B3D5B05*
 OUI:70B3D5847*
  ID_OUI_FROM_DATABASE=Ai-Lynx
 
+OUI:70B3D5148*
+ ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L.
+
+OUI:70B3D5BFE*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:70B3D5261*
+ ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+
+OUI:70B3D5618*
+ ID_OUI_FROM_DATABASE=Motec Pty Ltd
+
+OUI:70B3D5892*
+ ID_OUI_FROM_DATABASE=ABB
+
+OUI:70B3D59BA*
+ ID_OUI_FROM_DATABASE=ATIM Radiocommunication
+
+OUI:70B3D54C4*
+ ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies
+
+OUI:70B3D59B3*
+ ID_OUI_FROM_DATABASE=K&J Schmittschneider AG
+
+OUI:70B3D5747*
+ ID_OUI_FROM_DATABASE=Eva Automation
+
+OUI:70B3D53F4*
+ ID_OUI_FROM_DATABASE=Wincode Technology Co., Ltd.
+
+OUI:70B3D56E6*
+ ID_OUI_FROM_DATABASE=Eleven Engineering Incorporated
+
+OUI:70B3D5E39*
+ ID_OUI_FROM_DATABASE=Thinnect, Inc,
+
+OUI:70B3D5216*
+ ID_OUI_FROM_DATABASE=FLEXTRONICS
+
+OUI:70B3D50FE*
+ ID_OUI_FROM_DATABASE=Vocality International Ltd
+
+OUI:70B3D54B7*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:70B3D555C*
+ ID_OUI_FROM_DATABASE=Saratoga Speed, Inc.
+
+OUI:70B3D5428*
+ ID_OUI_FROM_DATABASE=Presentation Switchers, Inc.
+
+OUI:70B3D5C32*
+ ID_OUI_FROM_DATABASE=INFRASAFE/ ADVANTOR SYSTEMS
+
+OUI:70B3D5592*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5F1A*
+ ID_OUI_FROM_DATABASE=Sator Controls s.r.o.
+
+OUI:70B3D505A*
+ ID_OUI_FROM_DATABASE=Uni Control System Sp. z o. o.
+
+OUI:70B3D59EF*
+ ID_OUI_FROM_DATABASE=Cottonwood Creek Technologies, Inc.
+
+OUI:70B3D59EB*
+ ID_OUI_FROM_DATABASE=Preston Industries dba PolyScience
+
+OUI:70B3D5A3B*
+ ID_OUI_FROM_DATABASE=Grace Design/Lunatec LLC
+
+OUI:70B3D57A0*
+ ID_OUI_FROM_DATABASE=Reactec Ltd
+
+OUI:70B3D529B*
+ ID_OUI_FROM_DATABASE=DermaLumics S.L.
+
+OUI:70B3D5202*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
+OUI:70B3D5259*
+ ID_OUI_FROM_DATABASE=Zebra Elektronik A.S.
+
+OUI:70B3D5FBE*
+ ID_OUI_FROM_DATABASE=Hanbat National University
+
+OUI:70B3D5FE4*
+ ID_OUI_FROM_DATABASE=CARE PVT LTD
+
+OUI:70B3D58B1*
+ ID_OUI_FROM_DATABASE=M-Tech Innovations Limited
+
+OUI:70B3D5D34*
+ ID_OUI_FROM_DATABASE=G-PHILOS CO.,LTD
+
+OUI:70B3D5528*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:70B3D5B81*
+ ID_OUI_FROM_DATABASE=Instro Precision Limited
+
+OUI:70B3D5479*
+ ID_OUI_FROM_DATABASE=LINEAGE POWER PVT. LTD.
+
 OUI:70B3D58AB*
  ID_OUI_FROM_DATABASE=EMAC, Inc.
 
@@ -3239,9 +3587,6 @@ OUI:70B3D5918*
 OUI:70B3D5308*
  ID_OUI_FROM_DATABASE=DSD MICROTECHNOLOGY,INC.
 
-OUI:70B3D5184*
- ID_OUI_FROM_DATABASE=XV360 Optical Information Systems Ltd.
-
 OUI:70B3D56D3*
  ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
 
@@ -3392,6 +3737,105 @@ OUI:70B3D5297*
 OUI:70B3D5942*
  ID_OUI_FROM_DATABASE=TruTeq Devices (Pty) Ltd
 
+OUI:70B3D5F7B*
+ ID_OUI_FROM_DATABASE=KST technology
+
+OUI:70B3D5B99*
+ ID_OUI_FROM_DATABASE=DomoSafety S.A.
+
+OUI:70B3D5D51*
+ ID_OUI_FROM_DATABASE=Azcom Technology S.r.l.
+
+OUI:70B3D5BA1*
+ ID_OUI_FROM_DATABASE=Cathwell AS
+
+OUI:70B3D5286*
+ ID_OUI_FROM_DATABASE=Pedax Danmark
+
+OUI:70B3D51A9*
+ ID_OUI_FROM_DATABASE=OCEANIX INC.
+
+OUI:70B3D5733*
+ ID_OUI_FROM_DATABASE=SA Instrumentation Limited
+
+OUI:70B3D5652*
+ ID_OUI_FROM_DATABASE=Robert Bosch, LLC
+
+OUI:70B3D5F65*
+ ID_OUI_FROM_DATABASE=MARKUS LABS
+
+OUI:70B3D5F2E*
+ ID_OUI_FROM_DATABASE=Shanghai JCY Technology Company
+
+OUI:70B3D57F8*
+ ID_OUI_FROM_DATABASE=Solvera Lynx d.d.
+
+OUI:70B3D55BE*
+ ID_OUI_FROM_DATABASE=CASWA
+
+OUI:70B3D5F55*
+ ID_OUI_FROM_DATABASE=Kohler Mira Ltd
+
+OUI:70B3D57ED*
+ ID_OUI_FROM_DATABASE=The Things Network Foundation
+
+OUI:70B3D5A9D*
+ ID_OUI_FROM_DATABASE=VITEC MULTIMEDIA
+
+OUI:70B3D51A8*
+ ID_OUI_FROM_DATABASE=STC Rainbow Ltd.
+
+OUI:70B3D53CA*
+ ID_OUI_FROM_DATABASE=TTI Ltd
+
+OUI:70B3D5E1C*
+ ID_OUI_FROM_DATABASE=Xcenter AS
+
+OUI:70B3D5184*
+ ID_OUI_FROM_DATABASE=XV360 Optical Information Systems Ltd.
+
+OUI:70B3D5B5C*
+ ID_OUI_FROM_DATABASE=Prozess Technologie
+
+OUI:70B3D5AF4*
+ ID_OUI_FROM_DATABASE=TATTILE SRL
+
+OUI:70B3D5531*
+ ID_OUI_FROM_DATABASE=ATEME
+
+OUI:70B3D5BA7*
+ ID_OUI_FROM_DATABASE=Digital Yacht Ltd
+
+OUI:70B3D51C7*
+ ID_OUI_FROM_DATABASE=Hoshin Electronics Co., Ltd.
+
+OUI:70B3D528B*
+ ID_OUI_FROM_DATABASE=Arnouse Digital Devices, Corp.
+
+OUI:70B3D5D94*
+ ID_OUI_FROM_DATABASE=Dewetron GmbH
+
+OUI:70B3D5974*
+ ID_OUI_FROM_DATABASE=Jireh Industries Ltd.
+
+OUI:70B3D5544*
+ ID_OUI_FROM_DATABASE=Silicon Safe Ltd
+
+OUI:70B3D5EE1*
+ ID_OUI_FROM_DATABASE=allora Factory BVBA
+
+OUI:70B3D5389*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D5640*
+ ID_OUI_FROM_DATABASE=Electronic Equipment Company Pvt. Ltd.
+
+OUI:70B3D5D65*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D53C3*
+ ID_OUI_FROM_DATABASE=AIMCO
+
 OUI:1C8776D*
  ID_OUI_FROM_DATABASE=Qivivo
 
@@ -3851,6 +4295,75 @@ OUI:1C8774E*
 OUI:78CA834*
  ID_OUI_FROM_DATABASE=Pinhole (Beijing) Technology Co., Ltd.
 
+OUI:78CA83E*
+ ID_OUI_FROM_DATABASE=Konecranes
+
+OUI:38B8EBB*
+ ID_OUI_FROM_DATABASE=ExaScaler Inc.
+
+OUI:38FDFEC*
+ ID_OUI_FROM_DATABASE=New Garden Co., Ltd.
+
+OUI:38FDFE5*
+ ID_OUI_FROM_DATABASE=CaptiveAire Systems Inc.
+
+OUI:5CF2867*
+ ID_OUI_FROM_DATABASE=Access IS
+
+OUI:5CF286C*
+ ID_OUI_FROM_DATABASE=Sunpet Industries Limited
+
+OUI:5CF2862*
+ ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD.
+
+OUI:5CF2866*
+ ID_OUI_FROM_DATABASE=VPInstruments
+
+OUI:5CF286A*
+ ID_OUI_FROM_DATABASE=Unfors Raysafe AB
+
+OUI:7C477C5*
+ ID_OUI_FROM_DATABASE=Midwest Microwave Solutions
+
+OUI:5CF286E*
+ ID_OUI_FROM_DATABASE=Daisen Electronic Industrial Co., Ltd.
+
+OUI:7C477C1*
+ ID_OUI_FROM_DATABASE=Photosynth Inc.
+
+OUI:986D35A*
+ ID_OUI_FROM_DATABASE=iWave Japan, Inc.
+
+OUI:986D357*
+ ID_OUI_FROM_DATABASE=Zhejiang Hanshow Technology Co., Ltd.
+
+OUI:50FF99C*
+ ID_OUI_FROM_DATABASE=Goetting KG
+
+OUI:50FF995*
+ ID_OUI_FROM_DATABASE=Garrison Technology
+
+OUI:50FF997*
+ ID_OUI_FROM_DATABASE=Honeywell International
+
+OUI:50FF99B*
+ ID_OUI_FROM_DATABASE=Sichuan Dowlab Electronics Technology Co. Ltd
+
+OUI:E0B6F55*
+ ID_OUI_FROM_DATABASE=Shenzhen Civicom Technology Co.,Limited
+
+OUI:E0B6F50*
+ ID_OUI_FROM_DATABASE=BeSTAR Corporation
+
+OUI:E0B6F57*
+ ID_OUI_FROM_DATABASE=Shenzhen Xrinda Technology Ltd
+
+OUI:E0B6F5B*
+ ID_OUI_FROM_DATABASE=Moog Crossbow
+
+OUI:E0B6F5C*
+ ID_OUI_FROM_DATABASE=funktel GmbH
+
 OUI:1C8776C*
  ID_OUI_FROM_DATABASE=Strone Technology
 
@@ -4301,6 +4814,84 @@ OUI:78CA839*
 OUI:78CA83C*
  ID_OUI_FROM_DATABASE=Elanview Technology Co.,Ltd
 
+OUI:38B8EB8*
+ ID_OUI_FROM_DATABASE=CeeNex Inc
+
+OUI:38B8EBD*
+ ID_OUI_FROM_DATABASE=Yellowbrick Data, Inc.
+
+OUI:38B8EB6*
+ ID_OUI_FROM_DATABASE=MATRIXSTREAM TECHNOLOGIES, INC.
+
+OUI:38B8EB2*
+ ID_OUI_FROM_DATABASE=barox Kommunikation GmbH
+
+OUI:38B8EBC*
+ ID_OUI_FROM_DATABASE=Ajax Systems Inc
+
+OUI:38B8EBE*
+ ID_OUI_FROM_DATABASE=Wyres SAS
+
+OUI:38FDFE1*
+ ID_OUI_FROM_DATABASE=WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD
+
+OUI:38FDFEE*
+ ID_OUI_FROM_DATABASE=iSmart electronic technology co.,LTD
+
+OUI:38FDFE8*
+ ID_OUI_FROM_DATABASE=Indra Navia AS
+
+OUI:5CF2864*
+ ID_OUI_FROM_DATABASE=CHIPSEN Co.,Ltd.
+
+OUI:5CF2868*
+ ID_OUI_FROM_DATABASE=SHENZHEN HIVT TECHNOLOGY CO.,LTD
+
+OUI:7C477C9*
+ ID_OUI_FROM_DATABASE=DaLian Cheering Tech Co.,Ltd
+
+OUI:7C477C0*
+ ID_OUI_FROM_DATABASE=BungBungame Inc
+
+OUI:7C477C4*
+ ID_OUI_FROM_DATABASE=RLC Electronics Systems
+
+OUI:7C477CE*
+ ID_OUI_FROM_DATABASE=I-Convergence.com
+
+OUI:986D35D*
+ ID_OUI_FROM_DATABASE=Praesideo B.V.
+
+OUI:986D358*
+ ID_OUI_FROM_DATABASE=Beijing 3CAVI Tech Co.,Ltd
+
+OUI:986D350*
+ ID_OUI_FROM_DATABASE=Shenzhen MALATA Mobile Communication Co.,LTD
+
+OUI:986D354*
+ ID_OUI_FROM_DATABASE=blossom communications corp.
+
+OUI:50FF998*
+ ID_OUI_FROM_DATABASE=Dolphin Concepts Limited
+
+OUI:50FF99D*
+ ID_OUI_FROM_DATABASE=Shenzhen Haipengxin Electronic Co., Ltd.
+
+OUI:50FF993*
+ ID_OUI_FROM_DATABASE=Yongjing Shanghai Electronic Science and Technology
+
+OUI:50FF992*
+ ID_OUI_FROM_DATABASE=SHENZHEN KINGVT ELECTRONICS CO.,LTD
+
+OUI:E0B6F5A*
+ ID_OUI_FROM_DATABASE=Folksam AB
+
+OUI:E0B6F54*
+ ID_OUI_FROM_DATABASE=Agora
+
+OUI:E0B6F5E*
+ ID_OUI_FROM_DATABASE=Advatek Lighting Pty Ltd
+
 OUI:1C87790*
  ID_OUI_FROM_DATABASE=Wurm GmbH & Co. KG Elektronische Systeme
 
@@ -4811,6 +5402,66 @@ OUI:78CA831*
 OUI:78CA837*
  ID_OUI_FROM_DATABASE=Beijing CarePulse Electronic Technology
 
+OUI:78CA83D*
+ ID_OUI_FROM_DATABASE=Hubei Boyuan Zhijia Network Media Co. Ltd.
+
+OUI:38B8EB3*
+ ID_OUI_FROM_DATABASE=Aina Wireless Inc
+
+OUI:38FDFE3*
+ ID_OUI_FROM_DATABASE=Siemens AG, PG IE R&D
+
+OUI:38FDFED*
+ ID_OUI_FROM_DATABASE=FUBA Automotive Electronics GmbH
+
+OUI:38FDFE7*
+ ID_OUI_FROM_DATABASE=Rademacher Geraete-Elektronik GmbH
+
+OUI:38FDFE0*
+ ID_OUI_FROM_DATABASE=Edge I&D Co., Ltd.
+
+OUI:5CF286B*
+ ID_OUI_FROM_DATABASE=Itron UK Limited
+
+OUI:7C477C2*
+ ID_OUI_FROM_DATABASE=POWERLAND LIMITED
+
+OUI:5CF286D*
+ ID_OUI_FROM_DATABASE=BrightSky, LLC
+
+OUI:7C477CB*
+ ID_OUI_FROM_DATABASE=Hangzhou Yiyitaidi Information Technology Co., Ltd.
+
+OUI:7C477C3*
+ ID_OUI_FROM_DATABASE=EyeLock LLC
+
+OUI:986D351*
+ ID_OUI_FROM_DATABASE=Shenzhen cositea electronics technology co.,LTD
+
+OUI:986D35C*
+ ID_OUI_FROM_DATABASE=my-PV GmbH
+
+OUI:986D35E*
+ ID_OUI_FROM_DATABASE=BAYCOM OPTO-ELECTRONICS TECHNOLGY CO., LTD.
+
+OUI:50FF994*
+ ID_OUI_FROM_DATABASE=IPC Global
+
+OUI:50FF996*
+ ID_OUI_FROM_DATABASE=LEGEND WINNER LIMITED
+
+OUI:50FF99A*
+ ID_OUI_FROM_DATABASE=metraTec GmbH
+
+OUI:50FF99E*
+ ID_OUI_FROM_DATABASE=Informa LLC
+
+OUI:E0B6F5D*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
+OUI:E0B6F53*
+ ID_OUI_FROM_DATABASE=Huizhou GISUN Industrial CO. LTD
+
 OUI:1C8776B*
  ID_OUI_FROM_DATABASE=Hekatron Vertriebs GmbH
 
@@ -5105,9 +5756,6 @@ OUI:28FD804*
 OUI:2C265FB*
  ID_OUI_FROM_DATABASE=Rexgen Inc.
 
-OUI:2C265FC*
- ID_OUI_FROM_DATABASE=AATON DIGITAL
-
 OUI:2C265F6*
  ID_OUI_FROM_DATABASE=Appostar Technology Co. Ltd
 
@@ -5342,6 +5990,75 @@ OUI:78CA83B*
 OUI:78CA835*
  ID_OUI_FROM_DATABASE=Huatune Technology (Shanghai) Co., Ltd.
 
+OUI:38B8EB0*
+ ID_OUI_FROM_DATABASE=Bumjin C&L Co., Ltd.
+
+OUI:38B8EB5*
+ ID_OUI_FROM_DATABASE=Dojo-Labs Ltd
+
+OUI:38B8EB1*
+ ID_OUI_FROM_DATABASE=1.A Connect GmbH
+
+OUI:38B8EBA*
+ ID_OUI_FROM_DATABASE=SECAD SA
+
+OUI:38B8EB7*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:38FDFE6*
+ ID_OUI_FROM_DATABASE=Inspero Inc
+
+OUI:38FDFE2*
+ ID_OUI_FROM_DATABASE=B.U.G.SST,Inc
+
+OUI:5CF2869*
+ ID_OUI_FROM_DATABASE=Shenzhen VST Automotive Electronics Co., LTD
+
+OUI:7C477C7*
+ ID_OUI_FROM_DATABASE=BlueSmart Technology Corporation
+
+OUI:7C477CA*
+ ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc.
+
+OUI:7C477CC*
+ ID_OUI_FROM_DATABASE=annapurnalabs
+
+OUI:986D356*
+ ID_OUI_FROM_DATABASE=Vitronic Dr.-Ing. Stein Bildverarbeitungssysteme GmbH
+
+OUI:7C477C8*
+ ID_OUI_FROM_DATABASE=Shenzhen Eunicum Electric Co.,Ltd.
+
+OUI:986D35B*
+ ID_OUI_FROM_DATABASE=INTECH
+
+OUI:986D352*
+ ID_OUI_FROM_DATABASE=SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD.
+
+OUI:50FF990*
+ ID_OUI_FROM_DATABASE=Simicon
+
+OUI:50FF991*
+ ID_OUI_FROM_DATABASE=Coyote Sytem
+
+OUI:50FF999*
+ ID_OUI_FROM_DATABASE=Sea Eagle Optoelectronic Information Technology(Tianjin)co,Ltd
+
+OUI:E0B6F58*
+ ID_OUI_FROM_DATABASE=Yuneec International(China)Co.,Ltd
+
+OUI:E0B6F52*
+ ID_OUI_FROM_DATABASE=Shanghai- British Information Technology Co., Ltd
+
+OUI:E0B6F56*
+ ID_OUI_FROM_DATABASE=POMCube Inc.
+
+OUI:2C265FC*
+ ID_OUI_FROM_DATABASE=AATON DIGITAL
+
+OUI:6891D05*
+ ID_OUI_FROM_DATABASE=NIPK Electron Co.
+
 OUI:1C87740*
  ID_OUI_FROM_DATABASE=Philips Personal Health Solutions
 
@@ -5801,6 +6518,57 @@ OUI:1C8774A*
 OUI:78CA830*
  ID_OUI_FROM_DATABASE=DAINCUBE
 
+OUI:38B8EB4*
+ ID_OUI_FROM_DATABASE=UMLOGICS
+
+OUI:38B8EB9*
+ ID_OUI_FROM_DATABASE=NHS Sistemas de Energia
+
+OUI:38FDFEA*
+ ID_OUI_FROM_DATABASE=Management Service Corporation
+
+OUI:38FDFEB*
+ ID_OUI_FROM_DATABASE=Swedish Adrenaline AB
+
+OUI:38FDFE4*
+ ID_OUI_FROM_DATABASE=New Telecom Solutions LLC
+
+OUI:38FDFE9*
+ ID_OUI_FROM_DATABASE=OOO Group of Industrial Technologies
+
+OUI:5CF2860*
+ ID_OUI_FROM_DATABASE=Hangzhou Signwei Electronics Technology Co., Ltd
+
+OUI:5CF2863*
+ ID_OUI_FROM_DATABASE=beijing your wonderful control system technology co.,ltd
+
+OUI:5CF2865*
+ ID_OUI_FROM_DATABASE=EUROIMMUN Medizinische Labordiagnostika AG
+
+OUI:5CF2861*
+ ID_OUI_FROM_DATABASE=iSon Tech
+
+OUI:7C477C6*
+ ID_OUI_FROM_DATABASE=Zerosystem LTD.Co
+
+OUI:7C477CD*
+ ID_OUI_FROM_DATABASE=Speedifi Inc
+
+OUI:986D353*
+ ID_OUI_FROM_DATABASE=DH Mechatronic AG
+
+OUI:986D359*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:986D355*
+ ID_OUI_FROM_DATABASE=PDAHL
+
+OUI:E0B6F59*
+ ID_OUI_FROM_DATABASE=Motiveprime Consumer Electronics Pvt Ltd
+
+OUI:E0B6F51*
+ ID_OUI_FROM_DATABASE=START TODAY CO.,LTD.
+
 OUI:E043DB*
  ID_OUI_FROM_DATABASE=Shenzhen ViewAt Technology Co.,Ltd.
 
@@ -7121,9 +7889,6 @@ OUI:741F4A*
 OUI:88CBA5*
  ID_OUI_FROM_DATABASE=Suzhou Torchstar Intelligent Technology Co.,Ltd
 
-OUI:A47B2C*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:184F32*
  ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
 
@@ -7184,9 +7949,6 @@ OUI:F85B9C*
 OUI:7CA237*
  ID_OUI_FROM_DATABASE=King Slide Technology CO., LTD.
 
-OUI:B0E2E5*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:300EE3*
  ID_OUI_FROM_DATABASE=Aquantia Corporation
 
@@ -7214,9 +7976,6 @@ OUI:D4522A*
 OUI:B0ECE1*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:AC9B0A*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
 OUI:407FE0*
  ID_OUI_FROM_DATABASE=Glory Star Technics (ShenZhen) Limited
 
@@ -7355,9 +8114,6 @@ OUI:3077CB*
 OUI:88C9D0*
  ID_OUI_FROM_DATABASE=LG Electronics
 
-OUI:BC6B4D*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:3428F0*
  ID_OUI_FROM_DATABASE=ATN International Limited
 
@@ -7550,9 +8306,6 @@ OUI:3C46D8*
 OUI:6C0273*
  ID_OUI_FROM_DATABASE=Shenzhen Jin Yun Video Equipment Co., Ltd.
 
-OUI:600292*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:2CFAA2*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent
 
@@ -7616,9 +8369,6 @@ OUI:D8E56D*
 OUI:3CCD5A*
  ID_OUI_FROM_DATABASE=Technische Alternative GmbH
 
-OUI:B0754D*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:604826*
  ID_OUI_FROM_DATABASE=Newbridge Technologies Int. Ltd.
 
@@ -7667,9 +8417,6 @@ OUI:6C2C06*
 OUI:54EE75*
  ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
 
-OUI:202564*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:60812B*
  ID_OUI_FROM_DATABASE=Custom Control Concepts
 
@@ -7679,9 +8426,6 @@ OUI:F86601*
 OUI:FC4AE9*
  ID_OUI_FROM_DATABASE=Castlenet Technology Inc.
 
-OUI:BC8D0E*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:34E42A*
  ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc.
 
@@ -7865,9 +8609,6 @@ OUI:30D6C9*
 OUI:107BEF*
  ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
 
-OUI:84262B*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:8CCDA2*
  ID_OUI_FROM_DATABASE=ACTP, Inc.
 
@@ -7889,9 +8630,6 @@ OUI:98FF6A*
 OUI:AC6BAC*
  ID_OUI_FROM_DATABASE=Jenny Science AG
 
-OUI:0C54A5*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:707C18*
  ID_OUI_FROM_DATABASE=ADATA Technology Co., Ltd
 
@@ -7919,9 +8657,6 @@ OUI:2C3731*
 OUI:041A04*
  ID_OUI_FROM_DATABASE=WaveIP
 
-OUI:94E98C*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:50206B*
  ID_OUI_FROM_DATABASE=Emerson Climate Technologies Transportation Solutions
 
@@ -7997,9 +8732,6 @@ OUI:A0E453*
 OUI:404A18*
  ID_OUI_FROM_DATABASE=Addrek Smart Solutions
 
-OUI:E48184*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:C4C0AE*
  ID_OUI_FROM_DATABASE=MIDORI ELECTRONIC CO., LTD.
 
@@ -8222,9 +8954,6 @@ OUI:ACE42E*
 OUI:08EF3B*
  ID_OUI_FROM_DATABASE=MCS Logic Inc.
 
-OUI:98B039*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:806C8B*
  ID_OUI_FROM_DATABASE=KAESER KOMPRESSOREN AG
 
@@ -8243,9 +8972,6 @@ OUI:C47F51*
 OUI:E8D4E0*
  ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd.
 
-OUI:54BEF7*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:3889DC*
  ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V.
 
@@ -10073,9 +10799,6 @@ OUI:4491DB*
 OUI:14D76E*
  ID_OUI_FROM_DATABASE=CONCH ELECTRONIC Co.,Ltd
 
-OUI:1078D2*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
-
 OUI:CC6B98*
  ID_OUI_FROM_DATABASE=Minetec Wireless Technologies
 
@@ -10367,9 +11090,6 @@ OUI:5CE286*
 OUI:2CCD27*
  ID_OUI_FROM_DATABASE=Precor Inc
 
-OUI:AC44F2*
- ID_OUI_FROM_DATABASE=Revolabs Inc
-
 OUI:6C5E7A*
  ID_OUI_FROM_DATABASE=Ubiquitous Internet Telecom Co., Ltd
 
@@ -10823,9 +11543,6 @@ OUI:002471*
 OUI:002473*
  ID_OUI_FROM_DATABASE=3COM EUROPE LTD
 
-OUI:002465*
- ID_OUI_FROM_DATABASE=Elentec
-
 OUI:002460*
  ID_OUI_FROM_DATABASE=Giaval Science Development Co. Ltd.
 
@@ -11495,9 +12212,6 @@ OUI:001F2C*
 OUI:001F26*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001F1F*
- ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
-
 OUI:001F1A*
  ID_OUI_FROM_DATABASE=Prominvest
 
@@ -11528,9 +12242,6 @@ OUI:001E95*
 OUI:001E96*
  ID_OUI_FROM_DATABASE=Sepura Plc
 
-OUI:001E90*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co
-
 OUI:001E8B*
  ID_OUI_FROM_DATABASE=Infra Access Korea Co., Ltd.
 
@@ -11633,9 +12344,6 @@ OUI:001F13*
 OUI:001F0F*
  ID_OUI_FROM_DATABASE=Select Engineered Systems
 
-OUI:001F09*
- ID_OUI_FROM_DATABASE=JASTEC CO., LTD.
-
 OUI:001EFD*
  ID_OUI_FROM_DATABASE=Microbit 2.0 AB
 
@@ -11819,9 +12527,6 @@ OUI:001E39*
 OUI:001E34*
  ID_OUI_FROM_DATABASE=CryptoMetrics
 
-OUI:001E33*
- ID_OUI_FROM_DATABASE=Inventec Corporation
-
 OUI:001E2D*
  ID_OUI_FROM_DATABASE=STIM
 
@@ -11891,9 +12596,6 @@ OUI:001CE3*
 OUI:001CDC*
  ID_OUI_FROM_DATABASE=Custom Computer Services, Inc.
 
-OUI:001CD7*
- ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
-
 OUI:001CD0*
  ID_OUI_FROM_DATABASE=Circleone Co.,Ltd.
 
@@ -12191,9 +12893,6 @@ OUI:001A2E*
 OUI:001A33*
  ID_OUI_FROM_DATABASE=ASI Communications, Inc.
 
-OUI:001A29*
- ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics, Inc
-
 OUI:001A1D*
  ID_OUI_FROM_DATABASE=PChome Online Inc.
 
@@ -12626,12 +13325,6 @@ OUI:001717*
 OUI:00170B*
  ID_OUI_FROM_DATABASE=Contela, Inc.
 
-OUI:001706*
- ID_OUI_FROM_DATABASE=Techfaith Wireless Communication Technology Limited.
-
-OUI:0016FA*
- ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
-
 OUI:0016FF*
  ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp
 
@@ -12776,9 +13469,6 @@ OUI:0016EE*
 OUI:0016E7*
  ID_OUI_FROM_DATABASE=Dynamix Promotions Limited
 
-OUI:0016EC*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
 OUI:0016DB*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
 
@@ -13262,9 +13952,6 @@ OUI:001459*
 OUI:001454*
  ID_OUI_FROM_DATABASE=Symwave
 
-OUI:00144F*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:001443*
  ID_OUI_FROM_DATABASE=Consultronics Europe Ltd
 
@@ -13406,9 +14093,6 @@ OUI:001199*
 OUI:00118F*
  ID_OUI_FROM_DATABASE=EUTECH INSTRUMENTS PTE. LTD.
 
-OUI:001188*
- ID_OUI_FROM_DATABASE=Enterasys
-
 OUI:001183*
  ID_OUI_FROM_DATABASE=Datalogic ADC, Inc.
 
@@ -13769,9 +14453,6 @@ OUI:000D8D*
 OUI:000D8E*
  ID_OUI_FROM_DATABASE=Koden Electronics Co., Ltd.
 
-OUI:000D87*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
 OUI:000D84*
  ID_OUI_FROM_DATABASE=Makus Inc.
 
@@ -14303,9 +14984,6 @@ OUI:000AEB*
 OUI:000AE4*
  ID_OUI_FROM_DATABASE=Wistron Corp.
 
-OUI:000AE6*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
 OUI:000A0E*
  ID_OUI_FROM_DATABASE=Invivo Research Inc.
 
@@ -16352,9 +17030,6 @@ OUI:0090B9*
 OUI:00901A*
  ID_OUI_FROM_DATABASE=UNISPHERE SOLUTIONS
 
-OUI:0090AE*
- ID_OUI_FROM_DATABASE=ITALTEL S.p.A.
-
 OUI:009082*
  ID_OUI_FROM_DATABASE=FORCE INSTITUTE
 
@@ -16472,9 +17147,6 @@ OUI:001074*
 OUI:001057*
  ID_OUI_FROM_DATABASE=Rebel.com, Inc.
 
-OUI:0010E0*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:0010BC*
  ID_OUI_FROM_DATABASE=Aastra Telecom
 
@@ -16784,9 +17456,6 @@ OUI:00A052*
 OUI:00A0EA*
  ID_OUI_FROM_DATABASE=ETHERCOM CORP.
 
-OUI:00A0B8*
- ID_OUI_FROM_DATABASE=SYMBIOS LOGIC INC.
-
 OUI:00A02E*
  ID_OUI_FROM_DATABASE=BRAND COMMUNICATIONS, LTD.
 
@@ -18161,9 +18830,6 @@ OUI:001577*
 OUI:ACE010*
  ID_OUI_FROM_DATABASE=Liteon Technology Corporation
 
-OUI:000BA2*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
 OUI:EC086B*
  ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
@@ -18176,12 +18842,6 @@ OUI:00192C*
 OUI:2421AB*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:001FA7*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
-OUI:A8E3EE*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
 OUI:6C23B9*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -18200,12 +18860,6 @@ OUI:303926*
 OUI:00EB2D*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:709E29*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:FC0FE6*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
 OUI:B00594*
  ID_OUI_FROM_DATABASE=Liteon Technology Corporation
 
@@ -18236,9 +18890,6 @@ OUI:E86D52*
 OUI:0015D0*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:001315*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
 OUI:0013A9*
  ID_OUI_FROM_DATABASE=Sony Corporation
 
@@ -18359,27 +19010,6 @@ OUI:0010E7*
 OUI:5C9656*
  ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
 
-OUI:0881F4*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:A8D0E5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:648788*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:28C0DA*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:80711F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:00239C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001DB5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:7C4CA5*
  ID_OUI_FROM_DATABASE=BSkyB Ltd
 
@@ -18548,29 +19178,35 @@ OUI:001DBC*
 OUI:001F32*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
-OUI:D8FB5E*
- ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
-
 OUI:544408*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:0017B0*
+OUI:D8FB5E*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
+OUI:1886AC*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001BEE*
+OUI:0021FE*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:1886AC*
+OUI:001DFD*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:0021FE*
+OUI:001EA3*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
 OUI:002266*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:DCB3B4*
- ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd.
+OUI:0017B0*
+ ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+
+OUI:001BEE*
+ ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+
+OUI:002548*
+ ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
 OUI:C8D10B*
  ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -18581,36 +19217,381 @@ OUI:C8979F*
 OUI:F4F5A5*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:3CC243*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:DCB3B4*
+ ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd.
 
-OUI:0015A0*
+OUI:001D98*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001A16*
+OUI:00119F*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:0022FC*
+OUI:0015A0*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:002548*
+OUI:001A16*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001DFD*
+OUI:0022FC*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001EA3*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:3CC243*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:001D98*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:18A6F7*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:00119F*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:246968*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
 OUI:8CA2FD*
  ID_OUI_FROM_DATABASE=Starry, Inc.
 
+OUI:14BB6E*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:AC61EA*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:38B54D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:90A62F*
+ ID_OUI_FROM_DATABASE=NAVER
+
+OUI:9476B7*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:8C1ABF*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:B47443*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:30CBF8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:000BA2*
+ ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
+
+OUI:F4ED5F*
+ ID_OUI_FROM_DATABASE=SHENZHEN KTC TECHNOLOGY GROUP
+
+OUI:2C4D79*
+ ID_OUI_FROM_DATABASE=GoerTek Inc.
+
+OUI:40D357*
+ ID_OUI_FROM_DATABASE=Ison Technology Co., Ltd.
+
+OUI:A4F1E8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:F03404*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
+OUI:AC9B0A*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:FC0FE6*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:709E29*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:00351A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:9CD48B*
+ ID_OUI_FROM_DATABASE=Innolux Technology Europe BV
+
+OUI:00A0B8*
+ ID_OUI_FROM_DATABASE=NetApp
+
+OUI:DCE838*
+ ID_OUI_FROM_DATABASE=CK Telecom (Shenzhen) Limited
+
+OUI:545AA6*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:BC8D0E*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:E48184*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:94E98C*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:84262B*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:98B039*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:A47B2C*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:BC6B4D*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:B0754D*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:00CCFC*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:2C9662*
+ ID_OUI_FROM_DATABASE=Invenit BV
+
+OUI:DC2DCB*
+ ID_OUI_FROM_DATABASE=Beijing Unis HengYue Technology Co., Ltd.
+
+OUI:3810D5*
+ ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
+
+OUI:44AAF5*
+ ID_OUI_FROM_DATABASE=Pace plc
+
+OUI:1C5F2B*
+ ID_OUI_FROM_DATABASE=D-Link International
+
+OUI:D8803C*
+ ID_OUI_FROM_DATABASE=Anhui Huami Information Technology Company Limited
+
+OUI:A8E3EE*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:001FA7*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:001315*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:703C03*
+ ID_OUI_FROM_DATABASE=RadiAnt Co.,Ltd
+
+OUI:F0D2F1*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:583277*
+ ID_OUI_FROM_DATABASE=Reliance Communications LLC
+
+OUI:CCD3E2*
+ ID_OUI_FROM_DATABASE=Jiangsu Yinhe  Electronics Co.,Ltd.
+
+OUI:182195*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:A88195*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:88ADD2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:008E73*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:B805AB*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:9C52F8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:900325*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:DC094C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:DCEE06*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:AC44F2*
+ ID_OUI_FROM_DATABASE=YAMAHA CORPORATION
+
+OUI:508965*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+
+OUI:808C97*
+ ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+
+OUI:30B49E*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:349971*
+ ID_OUI_FROM_DATABASE=Quanta Storage Inc.
+
+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)
+
+OUI:5CC7D7*
+ ID_OUI_FROM_DATABASE=AZROAD TECHNOLOGY COMPANY LIMITED
+
+OUI:A0043E*
+ ID_OUI_FROM_DATABASE=Parker Hannifin Manufacturing Germany GmbH & Co. KG
+
+OUI:001706*
+ ID_OUI_FROM_DATABASE=Techfaithwireless Communication Technology Limited.
+
+OUI:30F6B9*
+ ID_OUI_FROM_DATABASE=Ecocentric Energy
+
+OUI:1C3ADE*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:004268*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00BD82*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
+OUI:603ECA*
+ ID_OUI_FROM_DATABASE=Cambridge Medical Robotics Ltd
+
+OUI:E4A1E6*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+
+OUI:54489C*
+ ID_OUI_FROM_DATABASE=CDOUBLES ELECTRONICS CO. LTD.
+
+OUI:54BEF7*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:0C54A5*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:202564*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:600292*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:84002D*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:8019FE*
+ ID_OUI_FROM_DATABASE=JianLing Technology CO., LTD
+
+OUI:58605F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:001188*
+ ID_OUI_FROM_DATABASE=Enterasys
+
+OUI:1078D2*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:001E90*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:002465*
+ ID_OUI_FROM_DATABASE=Elentec
+
+OUI:001CD7*
+ ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
+
+OUI:0016EC*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:000D87*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:000AE6*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:945089*
+ ID_OUI_FROM_DATABASE=SimonsVoss Technologies GmbH
+
+OUI:001F1F*
+ ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
+
+OUI:0016FA*
+ ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
+
+OUI:003A7D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:844076*
+ ID_OUI_FROM_DATABASE=Drivenets
+
+OUI:E80959*
+ ID_OUI_FROM_DATABASE=Guoguang Electric Co.,Ltd
+
+OUI:00144F*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:541379*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:0010E0*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:0090AE*
+ ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I
+
+OUI:001E33*
+ ID_OUI_FROM_DATABASE=INVENTEC Corporation
+
+OUI:001A29*
+ ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota
+
+OUI:001F09*
+ ID_OUI_FROM_DATABASE=Jastec
+
+OUI:D0A4B1*
+ ID_OUI_FROM_DATABASE=Sonifex Ltd.
+
+OUI:001DB5*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:00239C*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:80711F*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:28F366*
+ ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD
+
+OUI:D44165*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
+
+OUI:8828B3*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:C4F081*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:801382*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:341290*
+ ID_OUI_FROM_DATABASE=Treeview Co.,Ltd.
+
+OUI:BCAD28*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
+
+OUI:3CB6B7*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:28C0DA*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:648788*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:A8D0E5*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0881F4*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
 OUI:0C6F9C*
  ID_OUI_FROM_DATABASE=Shaw Communications Inc.
 
@@ -19733,9 +20714,6 @@ OUI:B88687*
 OUI:68F956*
  ID_OUI_FROM_DATABASE=Objetivos y Servicio de Valor Añadido
 
-OUI:C07CD1*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:58B633*
  ID_OUI_FROM_DATABASE=Ruckus Wireless
 
@@ -19841,9 +20819,6 @@ OUI:D468BA*
 OUI:A47B85*
  ID_OUI_FROM_DATABASE=ULTIMEDIA Co Ltd,
 
-OUI:A8D828*
- ID_OUI_FROM_DATABASE=Bayer HealthCare
-
 OUI:CC37AB*
  ID_OUI_FROM_DATABASE=Edgecore Networks Corportation
 
@@ -19868,9 +20843,6 @@ OUI:E89120*
 OUI:546172*
  ID_OUI_FROM_DATABASE=ZODIAC AEROSPACE SAS
 
-OUI:AC620D*
- ID_OUI_FROM_DATABASE=Jabil Circuit (Wuxi) Co. LTD
-
 OUI:54CD10*
  ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd.
 
@@ -20078,9 +21050,6 @@ OUI:EC74BA*
 OUI:683C7D*
  ID_OUI_FROM_DATABASE=Magic Intelligence Technology Limited
 
-OUI:18A3E8*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:60128B*
  ID_OUI_FROM_DATABASE=CANON INC.
 
@@ -20393,9 +21362,6 @@ OUI:B0D59D*
 OUI:C4913A*
  ID_OUI_FROM_DATABASE=Shenzhen Sanland Electronic Co., ltd.
 
-OUI:60B617*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:A46032*
  ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
 
@@ -21197,9 +22163,6 @@ OUI:A01C05*
 OUI:F80DEA*
  ID_OUI_FROM_DATABASE=ZyCast Technology Inc.
 
-OUI:7C0507*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:1800DB*
  ID_OUI_FROM_DATABASE=Fitbit Inc.
 
@@ -21302,9 +22265,6 @@ OUI:D40FB2*
 OUI:74FE48*
  ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD.
 
-OUI:7054D2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:D0B498*
  ID_OUI_FROM_DATABASE=Robert Bosch LLC Automotive Electronics
 
@@ -21563,9 +22523,6 @@ OUI:803FD6*
 OUI:645FFF*
  ID_OUI_FROM_DATABASE=Nicolet Neuro
 
-OUI:741E93*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:2829D9*
  ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd
 
@@ -21758,9 +22715,6 @@ OUI:5C4A26*
 OUI:289EDF*
  ID_OUI_FROM_DATABASE=Danfoss Turbocor Compressors, Inc
 
-OUI:E840F2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:50053D*
  ID_OUI_FROM_DATABASE=CyWee Group Ltd
 
@@ -21815,9 +22769,6 @@ OUI:045C06*
 OUI:504A5E*
  ID_OUI_FROM_DATABASE=Masimo Corporation
 
-OUI:4CC94F*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:38BF33*
  ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications
 
@@ -21890,9 +22841,6 @@ OUI:BC1401*
 OUI:68D925*
  ID_OUI_FROM_DATABASE=ProSys Development Services
 
-OUI:2C2D48*
- ID_OUI_FROM_DATABASE=bct electronic GesmbH
-
 OUI:B41DEF*
  ID_OUI_FROM_DATABASE=Internet Laboratories, Inc.
 
@@ -22136,9 +23084,6 @@ OUI:7C4B78*
 OUI:28D1AF*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:3482DE*
- ID_OUI_FROM_DATABASE=Kayo Technology, Inc.
-
 OUI:68BC0C*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -22211,9 +23156,6 @@ OUI:0041B4*
 OUI:0007AB*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:48F7F1*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:D453AF*
  ID_OUI_FROM_DATABASE=VIGO System S.A.
 
@@ -22547,9 +23489,6 @@ OUI:408BF6*
 OUI:447E95*
  ID_OUI_FROM_DATABASE=Alpha and Omega, Inc
 
-OUI:50C971*
- ID_OUI_FROM_DATABASE=GN Netcom A/S
-
 OUI:E8B748*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -23324,9 +24263,6 @@ OUI:9CCD82*
 OUI:C8AACC*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:008CFA*
- ID_OUI_FROM_DATABASE=Inventec Corporation
-
 OUI:003D41*
  ID_OUI_FROM_DATABASE=Hatteland Computer AS
 
@@ -23627,9 +24563,6 @@ OUI:0025B7*
 OUI:0025B0*
  ID_OUI_FROM_DATABASE=Schmartz Inc
 
-OUI:002552*
- ID_OUI_FROM_DATABASE=VXI CORPORATION
-
 OUI:002546*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -23915,9 +24848,6 @@ OUI:0023A5*
 OUI:0022B6*
  ID_OUI_FROM_DATABASE=Superflow Technologies Group
 
-OUI:0022B1*
- ID_OUI_FROM_DATABASE=Elbit Systems
-
 OUI:0022A3*
  ID_OUI_FROM_DATABASE=California Eastern Laboratories
 
@@ -24446,9 +25376,6 @@ OUI:001E9E*
 OUI:001E99*
  ID_OUI_FROM_DATABASE=Vantanol Industrial Corporation
 
-OUI:001F45*
- ID_OUI_FROM_DATABASE=Enterasys
-
 OUI:001F36*
  ID_OUI_FROM_DATABASE=Bellwin Information Co. Ltd.,
 
@@ -24644,9 +25571,6 @@ OUI:001D88*
 OUI:001D7E*
  ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
 
-OUI:001D82*
- ID_OUI_FROM_DATABASE=GN A/S (GN Netcom A/S)
-
 OUI:001D7D*
  ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
 
@@ -25565,9 +26489,6 @@ OUI:001633*
 OUI:00162C*
  ID_OUI_FROM_DATABASE=Xanboo
 
-OUI:001625*
- ID_OUI_FROM_DATABASE=Impinj, Inc.
-
 OUI:001627*
  ID_OUI_FROM_DATABASE=embedded-logic DESIGN AND MORE GmbH
 
@@ -26048,9 +26969,6 @@ OUI:00131E*
 OUI:001323*
  ID_OUI_FROM_DATABASE=Cap Co., Ltd.
 
-OUI:001317*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
 OUI:00130B*
  ID_OUI_FROM_DATABASE=Mextal B.V.
 
@@ -27014,9 +27932,6 @@ OUI:000CB5*
 OUI:000CBC*
  ID_OUI_FROM_DATABASE=Iscutum
 
-OUI:000CC1*
- ID_OUI_FROM_DATABASE=Cooper Industries Inc.
-
 OUI:000CA3*
  ID_OUI_FROM_DATABASE=Rancho Technology, Inc.
 
@@ -27470,9 +28385,6 @@ OUI:0008CA*
 OUI:0008BF*
  ID_OUI_FROM_DATABASE=Aptus Elektronik AB
 
-OUI:0008B9*
- ID_OUI_FROM_DATABASE=KAON MEDIA Co., Ltd.
-
 OUI:0008B3*
  ID_OUI_FROM_DATABASE=Fastwel
 
@@ -27812,9 +28724,6 @@ OUI:000659*
 OUI:000658*
  ID_OUI_FROM_DATABASE=Helmut Fischer GmbH Institut für Elektronik und Messtechnik
 
-OUI:00065F*
- ID_OUI_FROM_DATABASE=ECI Telecom - NGTS Ltd.
-
 OUI:000646*
  ID_OUI_FROM_DATABASE=ShenZhen XunBao Network Technology Co Ltd
 
@@ -29030,9 +29939,6 @@ OUI:0050F1*
 OUI:00501B*
  ID_OUI_FROM_DATABASE=ABL CANADA, INC.
 
-OUI:005058*
- ID_OUI_FROM_DATABASE=VegaStream Group Limted
-
 OUI:005036*
  ID_OUI_FROM_DATABASE=NETCAM, LTD.
 
@@ -29072,9 +29978,6 @@ OUI:009042*
 OUI:009051*
  ID_OUI_FROM_DATABASE=ULTIMATE TECHNOLOGY CORP.
 
-OUI:0090F9*
- ID_OUI_FROM_DATABASE=LEITCH
-
 OUI:0090FF*
  ID_OUI_FROM_DATABASE=TELLUS TECHNOLOGY INC.
 
@@ -29117,9 +30020,6 @@ OUI:009013*
 OUI:0090CC*
  ID_OUI_FROM_DATABASE=Planex Communications
 
-OUI:0090FA*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
 OUI:009004*
  ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
 
@@ -29393,9 +30293,6 @@ OUI:00E0C6*
 OUI:00E06D*
  ID_OUI_FROM_DATABASE=COMPUWARE CORPORATION
 
-OUI:00E0E6*
- ID_OUI_FROM_DATABASE=INCAA DATACOM B.V.
-
 OUI:00E074*
  ID_OUI_FROM_DATABASE=TIERNAN COMMUNICATIONS, INC.
 
@@ -29726,9 +30623,6 @@ OUI:00A000*
 OUI:00A07B*
  ID_OUI_FROM_DATABASE=DAWN COMPUTER INCORPORATION
 
-OUI:00A0DE*
- ID_OUI_FROM_DATABASE=YAMAHA CORPORATION
-
 OUI:00A05C*
  ID_OUI_FROM_DATABASE=INVENTORY CONVERSION, INC./
 
@@ -29783,9 +30677,6 @@ OUI:00C019*
 OUI:00A062*
  ID_OUI_FROM_DATABASE=AES PRODATA
 
-OUI:00A0F4*
- ID_OUI_FROM_DATABASE=GE
-
 OUI:00A008*
  ID_OUI_FROM_DATABASE=NETCORP
 
@@ -30353,9 +31244,6 @@ OUI:0080F6*
 OUI:00001F*
  ID_OUI_FROM_DATABASE=Telco Systems, Inc.
 
-OUI:0000B4*
- ID_OUI_FROM_DATABASE=EDIMAX COMPUTER COMPANY
-
 OUI:000058*
  ID_OUI_FROM_DATABASE=RACORE COMPUTER PRODUCTS INC.
 
@@ -30887,12 +31775,6 @@ OUI:948815*
 OUI:3010B3*
  ID_OUI_FROM_DATABASE=Liteon Technology Corporation
 
-OUI:00005F*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
-OUI:0008F6*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
 OUI:001802*
  ID_OUI_FROM_DATABASE=Alpha Networks Inc.
 
@@ -31094,42 +31976,9 @@ OUI:00264D*
 OUI:74A528*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:3C8AB0*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:4C9614*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:88E0F3*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:2C2172*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:7819F7*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:5C5EAB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:009069*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:B0C69A*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:88A25E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001BC0*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:30A220*
  ID_OUI_FROM_DATABASE=ARG Telecom
 
-OUI:F4B52F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:783E53*
  ID_OUI_FROM_DATABASE=BSkyB Ltd
 
@@ -31337,6 +32186,378 @@ OUI:0025D0*
 OUI:001FDE*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
+OUI:907282*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:006CFD*
+ ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
+
+OUI:1C234F*
+ ID_OUI_FROM_DATABASE=EDMI  Europe Ltd
+
+OUI:A444D1*
+ ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited
+
+OUI:1C9E46*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:005058*
+ ID_OUI_FROM_DATABASE=Sangoma Technologies
+
+OUI:3482DE*
+ ID_OUI_FROM_DATABASE=Kiio Inc
+
+OUI:0008F6*
+ ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
+
+OUI:00005F*
+ ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
+
+OUI:A0C589*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:74BFB7*
+ ID_OUI_FROM_DATABASE=Nusoft Corporation
+
+OUI:50DA00*
+ ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+
+OUI:9C2A83*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:E45D75*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:3CBEE1*
+ ID_OUI_FROM_DATABASE=NIKON CORPORATION
+
+OUI:047E4A*
+ ID_OUI_FROM_DATABASE=moobox CO., Ltd.
+
+OUI:104FA8*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:F01B6C*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:E0C767*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:2C09CB*
+ ID_OUI_FROM_DATABASE=COBS AB
+
+OUI:60ACC8*
+ ID_OUI_FROM_DATABASE=KunTeng Inc.
+
+OUI:0404EA*
+ ID_OUI_FROM_DATABASE=Valens Semiconductor Ltd.
+
+OUI:800DD7*
+ ID_OUI_FROM_DATABASE=Latticework, Inc
+
+OUI:402E28*
+ ID_OUI_FROM_DATABASE=MiXTelematics
+
+OUI:18C501*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:546D52*
+ ID_OUI_FROM_DATABASE=TOPVIEW OPTRONICS CORP.
+
+OUI:CCB3AB*
+ ID_OUI_FROM_DATABASE=shenzhen Biocare Bio-Medical Equipment Co.,Ltd.
+
+OUI:4CC94F*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:48F7F1*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:E4B318*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:00C88B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:A85EE4*
+ ID_OUI_FROM_DATABASE=12Sided Technology, LLC
+
+OUI:000CC1*
+ ID_OUI_FROM_DATABASE=Eaton Corporation
+
+OUI:0090F9*
+ ID_OUI_FROM_DATABASE=Imagine Communications
+
+OUI:04C103*
+ ID_OUI_FROM_DATABASE=Clover Network, Inc.
+
+OUI:F877B8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:1C553A*
+ ID_OUI_FROM_DATABASE=QianGua Corp.
+
+OUI:E4A7A0*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:E4FAED*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:789682*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:F02745*
+ ID_OUI_FROM_DATABASE=F-Secure Corporation
+
+OUI:54D0B4*
+ ID_OUI_FROM_DATABASE=Xiamen Four-Faith Communication Technology Co.,Ltd
+
+OUI:D017C2*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
+OUI:10DA43*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:001625*
+ ID_OUI_FROM_DATABASE=Impinj, Inc.
+
+OUI:1CEA1B*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:DC1AC5*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:60EE5C*
+ ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+
+OUI:BC60A7*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:58D67A*
+ ID_OUI_FROM_DATABASE=TCPlink
+
+OUI:00A0DE*
+ ID_OUI_FROM_DATABASE=YAMAHA CORPORATION
+
+OUI:081F71*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:2C2D48*
+ ID_OUI_FROM_DATABASE=bct electronic GesmbH
+
+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:F0C77F*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:00A0F4*
+ ID_OUI_FROM_DATABASE=GE
+
+OUI:00CAE5*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:4883C7*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:7050AF*
+ ID_OUI_FROM_DATABASE=BSkyB Ltd
+
+OUI:F4EF9E*
+ ID_OUI_FROM_DATABASE=SGSG SCIENCE & TECHNOLOGY CO. LTD
+
+OUI:DC9C9F*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
+OUI:0CBF3F*
+ ID_OUI_FROM_DATABASE=Shenzhen Lencotion Technology Co.,Ltd
+
+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
+
+OUI:703A0E*
+ ID_OUI_FROM_DATABASE=Aruba Networks
+
+OUI:7054D2*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:7C0507*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:C07CD1*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:94DBDA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:384C4F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E4A8B6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:244C07*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E840F2*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:F0D1B8*
+ ID_OUI_FROM_DATABASE=LEDVANCE
+
+OUI:60B387*
+ ID_OUI_FROM_DATABASE=Synergics Technologies GmbH
+
+OUI:7085C2*
+ ID_OUI_FROM_DATABASE=ASRock Incorporation
+
+OUI:C825E1*
+ ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd
+
+OUI:0022B1*
+ ID_OUI_FROM_DATABASE=Elbit Systems Ltd.
+
+OUI:0000B4*
+ ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
+
+OUI:00065F*
+ ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
+
+OUI:001F45*
+ ID_OUI_FROM_DATABASE=Enterasys
+
+OUI:0090FA*
+ ID_OUI_FROM_DATABASE=Emulex Corporation
+
+OUI:50C971*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:001D82*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:001317*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:749781*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:B4B15A*
+ ID_OUI_FROM_DATABASE=Siemens AG Energy Management Division
+
+OUI:A86BAD*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:D80F99*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:A8D828*
+ ID_OUI_FROM_DATABASE=Ascensia Diabetes Care
+
+OUI:FCBC9C*
+ ID_OUI_FROM_DATABASE=Vimar Spa
+
+OUI:149ECF*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:AC620D*
+ ID_OUI_FROM_DATABASE=Jabil Circuit(Wuxi) Co.,Ltd
+
+OUI:008CFA*
+ ID_OUI_FROM_DATABASE=INVENTEC Corporation
+
+OUI:0008B9*
+ ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+
+OUI:C83F26*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
+OUI:00E0E6*
+ ID_OUI_FROM_DATABASE=INCAA Computers
+
+OUI:5C5EAB*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:7819F7*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:2C2172*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:88E0F3*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:4C9614*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:3C8AB0*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:B0C69A*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:009069*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:204E71*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:F4B52F*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:88A25E*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:001BC0*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:F49EEF*
+ ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+
+OUI:F4911E*
+ ID_OUI_FROM_DATABASE=ZHUHAI EWPE INFORMATION TECHNOLOGY INC
+
+OUI:94FE22*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:F823B2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:DCD916*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:002552*
+ ID_OUI_FROM_DATABASE=VXi Corporation
+
+OUI:341FE4*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:006CBC*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:DC3752*
+ ID_OUI_FROM_DATABASE=GE
+
+OUI:F08261*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:D084B0*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
 OUI:5846E1*
  ID_OUI_FROM_DATABASE=Baxter International Inc
 
@@ -31361,41 +32582,26 @@ OUI:B4EED4*
 OUI:D08CB5*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:001831*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:0023D4*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:3C2DB7*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:40984E*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:3C7DB1*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:505663*
- ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:0030C5*
+ ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC.
 
-OUI:B0B448*
- ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:00FEC8*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:F08261*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:BC5436*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:D084B0*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:0CC731*
+ ID_OUI_FROM_DATABASE=Currant, Inc.
 
-OUI:00FEC8*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00142F*
+ ID_OUI_FROM_DATABASE=Savvius
 
-OUI:0030C5*
- ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC.
+OUI:70CA4D*
+ ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd.
 
-OUI:EC2280*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:DCC0EB*
+ ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE
 
 OUI:047863*
  ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd.
@@ -31406,33 +32612,24 @@ OUI:24BA13*
 OUI:24DA11*
  ID_OUI_FROM_DATABASE=NO NDA Inc
 
-OUI:70CA4D*
- ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd.
+OUI:BCD1D3*
+ ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
 
-OUI:DCC0EB*
- ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE
+OUI:BC4434*
+ ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
 
-OUI:001735*
- ID_OUI_FROM_DATABASE=Intel Wireless Network Group
+OUI:0041D2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:9CDFB1*
- ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD
+OUI:4CFB45*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:5CF938*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A4BA76*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
 OUI:3871DE*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:BC5436*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:0CC731*
- ID_OUI_FROM_DATABASE=Currant, Inc.
-
-OUI:00142F*
- ID_OUI_FROM_DATABASE=Savvius
-
 OUI:2CDDA3*
  ID_OUI_FROM_DATABASE=Point Grey Research Inc.
 
@@ -31451,23 +32648,23 @@ OUI:F4F5E8*
 OUI:F88FCA*
  ID_OUI_FROM_DATABASE=Google, Inc.
 
-OUI:BCD1D3*
- ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:14D64D*
+ ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:BC4434*
- ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:C8BE19*
+ ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:0041D2*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:BCF685*
+ ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:4CFB45*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:CCB255*
+ ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:A4BA76*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:84C9B2*
+ ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:003676*
- ID_OUI_FROM_DATABASE=Pace plc
+OUI:EC2280*
+ ID_OUI_FROM_DATABASE=D-Link International
 
 OUI:78E3B5*
  ID_OUI_FROM_DATABASE=Hewlett Packard
@@ -31481,47 +32678,41 @@ OUI:68B599*
 OUI:0C47C9*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
 
-OUI:0017E6*
+OUI:001831*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:0017E8*
+OUI:0023D4*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:9059AF*
+OUI:3C2DB7*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:E0C79D*
+OUI:40984E*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:14D64D*
- ID_OUI_FROM_DATABASE=D-Link International
-
-OUI:C8BE19*
- ID_OUI_FROM_DATABASE=D-Link International
-
-OUI:BCF685*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:3C7DB1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:CCB255*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:505663*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:84C9B2*
- ID_OUI_FROM_DATABASE=D-Link International
+OUI:B0B448*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:DCD321*
- ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:0017E6*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:CC4EEC*
- ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:0017E8*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:88C255*
+OUI:9059AF*
  ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:DC330D*
- ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd
+OUI:E0C79D*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:0080E1*
- ID_OUI_FROM_DATABASE=STMicroelectronics SRL
+OUI:003676*
+ ID_OUI_FROM_DATABASE=Pace plc
 
 OUI:58DC6D*
  ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc.
@@ -31565,18 +32756,6 @@ OUI:08EA44*
 OUI:78F882*
  ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
 
-OUI:8851FB*
- ID_OUI_FROM_DATABASE=Hewlett Packard
-
-OUI:AC162D*
- ID_OUI_FROM_DATABASE=Hewlett Packard
-
-OUI:A0B3CC*
- ID_OUI_FROM_DATABASE=Hewlett Packard
-
-OUI:E4115B*
- ID_OUI_FROM_DATABASE=Hewlett Packard
-
 OUI:C8CBB8*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
@@ -31598,8 +32777,29 @@ OUI:D48564*
 OUI:3C4A92*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
-OUI:780AC7*
- ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd.
+OUI:0080E1*
+ ID_OUI_FROM_DATABASE=STMicroelectronics SRL
+
+OUI:2C6E85*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:00D0B7*
+ ID_OUI_FROM_DATABASE=Intel Corporation
+
+OUI:0015D1*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:001DD3*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:001735*
+ ID_OUI_FROM_DATABASE=Intel Wireless Network Group
+
+OUI:9CDFB1*
+ ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD
+
+OUI:5CF938*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
 OUI:001D73*
  ID_OUI_FROM_DATABASE=BUFFALO.INC
@@ -31625,21 +32825,6 @@ OUI:001B78*
 OUI:001E0B*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
-OUI:2C6E85*
- ID_OUI_FROM_DATABASE=Intel Corporate
-
-OUI:00D0B7*
- ID_OUI_FROM_DATABASE=Intel Corporation
-
-OUI:0015D1*
- 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:0002B3*
  ID_OUI_FROM_DATABASE=Intel Corporation
 
@@ -31658,6 +32843,9 @@ OUI:9049FA*
 OUI:C8348E*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
+OUI:780AC7*
+ ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd.
+
 OUI:00508B*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
@@ -31676,8 +32864,17 @@ OUI:A0481C*
 OUI:A01D48*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
-OUI:001DD3*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:8851FB*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:AC162D*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:A0B3CC*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:E4115B*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
 
 OUI:E8892C*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -31694,41 +32891,29 @@ OUI:8C09F4*
 OUI:3CDFA9*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:94B2CC*
- ID_OUI_FROM_DATABASE=PIONEER CORPORATION
-
-OUI:887F03*
- ID_OUI_FROM_DATABASE=Comper Technology Investment Limited
-
-OUI:E06066*
- ID_OUI_FROM_DATABASE=Sercomm Corporation
-
-OUI:0019E0*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
-OUI:0023CD*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:C005C2*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:002719*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:6455B1*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:40169F*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:DCD321*
+ ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
 
-OUI:940C6D*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:CC4EEC*
+ ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
 
-OUI:74EA3A*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:88C255*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:90F652*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:DC330D*
+ ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd
 
-OUI:10FEED*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:94B2CC*
+ ID_OUI_FROM_DATABASE=PIONEER CORPORATION
 
-OUI:C46E1F*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:887F03*
+ ID_OUI_FROM_DATABASE=Comper Technology Investment Limited
 
 OUI:50FA84*
  ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
@@ -31757,26 +32942,11 @@ OUI:1C994C*
 OUI:F02765*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
-OUI:507224*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:D4970B*
- ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
-
-OUI:F48B32*
- ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
-
-OUI:20A783*
- ID_OUI_FROM_DATABASE=miControl GmbH
-
-OUI:005053*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:00500F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:88308A*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
-OUI:048A15*
- ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:44A7CF*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
 OUI:44322A*
  ID_OUI_FROM_DATABASE=Avaya Inc
@@ -31808,11 +32978,77 @@ OUI:200BC7*
 OUI:104780*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:88308A*
- ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:30D17E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:44A7CF*
- ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:9C28EF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E06066*
+ ID_OUI_FROM_DATABASE=Sercomm Corporation
+
+OUI:0019E0*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:0023CD*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:002719*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:40169F*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:940C6D*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:74EA3A*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:90F652*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:10FEED*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:C46E1F*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:68A0F6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:5CF96A*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:B43052*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:88CEFA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:582AF7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:F48E92*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:40CBA8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:087A4C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:D46E5C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:2469A5*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:C8D15E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:F83DFF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
 OUI:0013E0*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
@@ -31874,41 +33110,29 @@ OUI:88E3AB*
 OUI:00664B*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:68A0F6*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:5CF96A*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:B43052*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:88CEFA*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:582AF7*
+OUI:7C6097*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:F48E92*
+OUI:60DE44*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:40CBA8*
+OUI:3400A3*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:087A4C*
+OUI:643E8C*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:D46E5C*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0012D1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:2469A5*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:70FF76*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:C8D15E*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:B4994C*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
-OUI:F83DFF*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:507224*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
 OUI:308730*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -31934,86 +33158,26 @@ OUI:A4251B*
 OUI:6CA849*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:30D17E*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:9C28EF*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:7C6097*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:60DE44*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:3400A3*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:643E8C*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
-OUI:0012D1*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:70FF76*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:B4994C*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:00C610*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:70DEE2*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:182032*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:6CC26B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:1040F3*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:FC253F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:183451*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:C0847A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:64200C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:74E1B6*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:0C771A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:00F4B9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:048A15*
+ ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:C8334B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:D4970B*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
 
-OUI:B8F6B1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F48B32*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
 
-OUI:C09F42*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:20A783*
+ ID_OUI_FROM_DATABASE=miControl GmbH
 
-OUI:189EFC*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:005053*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:6C3E6D*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:00500F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:0016FE*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
+OUI:0050A2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:0498F3*
  ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
@@ -32045,39 +33209,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
-
-OUI:78BAF9*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:0016B6*
- ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-
-OUI:0018F8*
- ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
-
-OUI:00252E*
- ID_OUI_FROM_DATABASE=Cisco SPVTG
-
-OUI:A4A24A*
- ID_OUI_FROM_DATABASE=Cisco SPVTG
-
-OUI:602AD0*
- ID_OUI_FROM_DATABASE=Cisco SPVTG
-
-OUI:001BFB*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
-
-OUI:00E08F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
 OUI:203A07*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -32117,41 +33248,38 @@ OUI:500604*
 OUI:70105C*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:7CFADF*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C067AF*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:101C0C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:001124*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:64E950*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001D4F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:B0AA77*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001E52*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:78BAF9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001F5B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0016B6*
+ ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
 
-OUI:001FF3*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0018F8*
+ ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
 
-OUI:0021E9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:00252E*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
 
-OUI:00236C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A4A24A*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
 
-OUI:002500*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:602AD0*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
 
-OUI:60FB42*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:001BFB*
+ ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
 
-OUI:14DAE9*
- ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:0016FE*
+ ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
 
 OUI:3C08F6*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -32174,6 +33302,45 @@ OUI:346288*
 OUI:881DFC*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
+OUI:000389*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:0CE0E4*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:7CFADF*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:101C0C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:001124*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:001D4F*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:001E52*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:001F5B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:001FF3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:0021E9*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:00236C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:002500*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:60FB42*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
 OUI:F81EDF*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -32201,10 +33368,31 @@ OUI:A4D1D2*
 OUI:406C8F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:C067AF*
+OUI:00C610*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:70DEE2*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:0050F0*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:64E950*
+OUI:00905F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00902B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00100B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00100D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001014*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00E08F*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:189C5D*
@@ -32222,105 +33410,93 @@ OUI:002618*
 OUI:00248C*
  ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
 
-OUI:0050A2*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:0050F0*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:00905F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:00902B*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:14DAE9*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
 
-OUI:00100B*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:182032*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:00100D*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:6CC26B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:001014*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:1040F3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:649ABE*
+OUI:FC253F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:94E96A*
+OUI:183451*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:AC293A*
+OUI:C0847A*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:10417F*
+OUI:64200C*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:7014A6*
+OUI:74E1B6*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:A8667F*
+OUI:0C771A*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:D02598*
+OUI:00F4B9*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:CC29F5*
+OUI:C8334B*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:802994*
- ID_OUI_FROM_DATABASE=Technicolor CH USA
+OUI:B8F6B1*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:6C709F*
+OUI:C09F42*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:0C3E9F*
+OUI:189EFC*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:34E2FD*
+OUI:6C3E6D*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:609217*
+OUI:8C2DAA*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:8863DF*
+OUI:444C0C*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:80E650*
+OUI:84FCFE*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:006171*
+OUI:E48B7F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:90FD61*
+OUI:94E96A*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:5C97F3*
+OUI:AC293A*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:6C4008*
+OUI:10417F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:24A074*
+OUI:7014A6*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:F02475*
+OUI:A8667F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:20A2E4*
+OUI:D02598*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:5CF5DA*
+OUI:CC29F5*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
+OUI:802994*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA
+
 OUI:D4B8FF*
  ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd
 
-OUI:28E14C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
-OUI:54E43A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
-
 OUI:C8E0EB*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -32348,62 +33524,68 @@ OUI:B03495*
 OUI:848E0C*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:8C2DAA*
+OUI:6C709F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:444C0C*
+OUI:0C3E9F*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:84FCFE*
+OUI:34E2FD*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:E48B7F*
+OUI:609217*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:5C969D*
+OUI:8863DF*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:A8FAD8*
+OUI:80E650*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:949426*
+OUI:006171*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:E0F5C6*
+OUI:90FD61*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:AC6462*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:5C97F3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:C08488*
- ID_OUI_FROM_DATABASE=Finis Inc
+OUI:6C4008*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:68E8EB*
- ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd
+OUI:24A074*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:20C3A4*
- ID_OUI_FROM_DATABASE=RetailNext
+OUI:F02475*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:780541*
- ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd
+OUI:20A2E4*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:C02DEE*
- ID_OUI_FROM_DATABASE=Cuff
+OUI:5CF5DA*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:54A3FA*
- ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd
+OUI:649ABE*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:30F772*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:5C969D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:9023EC*
- ID_OUI_FROM_DATABASE=Availink, Inc.
+OUI:A8FAD8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:7467F7*
- ID_OUI_FROM_DATABASE=Zebra Technologoes
+OUI:949426*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:3891D5*
- ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:E0F5C6*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:28E14C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:54E43A*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
 
 OUI:90DFFB*
  ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS
@@ -32414,8 +33596,11 @@ OUI:3C831E*
 OUI:381C23*
  ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD
 
-OUI:E03676*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:AC6462*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:C08488*
+ ID_OUI_FROM_DATABASE=Finis Inc
 
 OUI:8C99E6*
  ID_OUI_FROM_DATABASE=TCT Mobile Limited
@@ -32429,11 +33614,26 @@ OUI:243184*
 OUI:24DA9B*
  ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
 
-OUI:3052CB*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:7467F7*
+ ID_OUI_FROM_DATABASE=Zebra Technologoes
 
-OUI:DCFE07*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+OUI:3891D5*
+ ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+
+OUI:68E8EB*
+ ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd
+
+OUI:20C3A4*
+ ID_OUI_FROM_DATABASE=RetailNext
+
+OUI:B844D9*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:DC2B2A*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:8C10D4*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
 OUI:B8B2EB*
  ID_OUI_FROM_DATABASE=Googol Technology (HK) Limited
@@ -32444,23 +33644,17 @@ OUI:C40049*
 OUI:50A9DE*
  ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD
 
-OUI:54AB3A*
- ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
-
-OUI:8809AF*
- ID_OUI_FROM_DATABASE=Masimo Corp.
-
-OUI:E8DED6*
- ID_OUI_FROM_DATABASE=Intrising Networks, Inc.
+OUI:C02DEE*
+ ID_OUI_FROM_DATABASE=Cuff
 
-OUI:B844D9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:54A3FA*
+ ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd
 
-OUI:DC2B2A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:30F772*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
 
-OUI:8C10D4*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:9023EC*
+ ID_OUI_FROM_DATABASE=Availink, Inc.
 
 OUI:203D66*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -32471,11 +33665,26 @@ OUI:B83A9D*
 OUI:089B4B*
  ID_OUI_FROM_DATABASE=iKuai Networks
 
+OUI:780541*
+ ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd
+
 OUI:3C7873*
  ID_OUI_FROM_DATABASE=Airsonics
 
-OUI:BC5FF6*
- ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+OUI:3052CB*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:54AB3A*
+ ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
+
+OUI:8809AF*
+ ID_OUI_FROM_DATABASE=Masimo Corp.
+
+OUI:E8DED6*
+ ID_OUI_FROM_DATABASE=Intrising Networks, Inc.
+
+OUI:E03676*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
 OUI:C8F9C8*
  ID_OUI_FROM_DATABASE=NewSharp Technology(SuZhou)Co,Ltd
@@ -32489,6 +33698,21 @@ OUI:A8741D*
 OUI:F4C613*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
 
+OUI:D404CD*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:EC0133*
+ ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC.
+
+OUI:90D8F3*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:D84710*
+ ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
+
+OUI:444CA8*
+ ID_OUI_FROM_DATABASE=Arista Networks
+
 OUI:A4C138*
  ID_OUI_FROM_DATABASE=Telink Semiconductor (Taipei) Co. Ltd.
 
@@ -32501,11 +33725,8 @@ OUI:48E244*
 OUI:D8EFCD*
  ID_OUI_FROM_DATABASE=Nokia
 
-OUI:D404CD*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:EC0133*
- ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC.
+OUI:BC5FF6*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
 
 OUI:1C56FE*
  ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
@@ -32534,39 +33755,9 @@ OUI:94F278*
 OUI:E8BDD1*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:3481F4*
- ID_OUI_FROM_DATABASE=SST Taiwan Ltd.
-
-OUI:F4B8A7*
- ID_OUI_FROM_DATABASE=zte corporation
-
-OUI:58F102*
- ID_OUI_FROM_DATABASE=BLU Products Inc.
-
-OUI:B869C2*
- ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
-
-OUI:2CC548*
- ID_OUI_FROM_DATABASE=IAdea Corporation
-
-OUI:84DBFC*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:307CB2*
  ID_OUI_FROM_DATABASE=ANOV FRANCE
 
-OUI:90D8F3*
- ID_OUI_FROM_DATABASE=zte corporation
-
-OUI:D84710*
- ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
-
-OUI:444CA8*
- ID_OUI_FROM_DATABASE=Arista Networks
-
-OUI:FCE33C*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
-
 OUI:BC6A2F*
  ID_OUI_FROM_DATABASE=Henge Docks LLC
 
@@ -32579,32 +33770,29 @@ OUI:48066A*
 OUI:1CF03E*
  ID_OUI_FROM_DATABASE=Wearhaus Inc.
 
-OUI:DCDB70*
- ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH
-
-OUI:C47D46*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:BCF811*
+ ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd
 
-OUI:68EDA4*
- ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd
+OUI:A8827F*
+ ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd
 
-OUI:B899B0*
- ID_OUI_FROM_DATABASE=Cohere Technologies
+OUI:609C9F*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
 
-OUI:2CC5D3*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:249EAB*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:80C5E6*
- ID_OUI_FROM_DATABASE=Microsoft Corporation
+OUI:DC56E6*
+ ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD
 
-OUI:D85DEF*
- ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH
+OUI:5CA178*
+ ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk)
 
-OUI:10DF8B*
- ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd
+OUI:A0B437*
+ ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSEMS
 
-OUI:00A784*
- ID_OUI_FROM_DATABASE=ITX security
+OUI:B89ACD*
+ ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD
 
 OUI:800184*
  ID_OUI_FROM_DATABASE=HTC Corporation
@@ -32621,47 +33809,53 @@ OUI:C02567*
 OUI:B46D35*
  ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd
 
-OUI:B89ACD*
- ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD
+OUI:FCE33C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:241C04*
- ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD.
+OUI:68EDA4*
+ ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd
 
-OUI:F8CFC5*
- ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:B899B0*
+ ID_OUI_FROM_DATABASE=Cohere Technologies
 
-OUI:BCF811*
- ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd
+OUI:2CC5D3*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
 
-OUI:A8827F*
- ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd
+OUI:80C5E6*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
 
-OUI:609C9F*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+OUI:D85DEF*
+ ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH
 
-OUI:900A39*
- ID_OUI_FROM_DATABASE=Wiio, Inc.
+OUI:10DF8B*
+ ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd
 
-OUI:C4693E*
- ID_OUI_FROM_DATABASE=Turbulence Design Inc.
+OUI:00A784*
+ ID_OUI_FROM_DATABASE=ITX security
 
-OUI:1C8341*
- ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd
+OUI:3481F4*
+ ID_OUI_FROM_DATABASE=SST Taiwan Ltd.
 
-OUI:4011DC*
- ID_OUI_FROM_DATABASE=Sonance
+OUI:F4B8A7*
+ ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:249EAB*
- ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:58F102*
+ ID_OUI_FROM_DATABASE=BLU Products Inc.
 
-OUI:DC56E6*
- ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD
+OUI:B869C2*
+ ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
 
-OUI:5CA178*
- ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk)
+OUI:2CC548*
+ ID_OUI_FROM_DATABASE=IAdea Corporation
 
-OUI:A0B437*
- ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSEMS
+OUI:84DBFC*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:DCDB70*
+ ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH
+
+OUI:C47D46*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
 
 OUI:702A7D*
  ID_OUI_FROM_DATABASE=EpSpot AB
@@ -32672,12 +33866,30 @@ OUI:B8B3DC*
 OUI:347A60*
  ID_OUI_FROM_DATABASE=Pace plc
 
+OUI:C4EA1D*
+ ID_OUI_FROM_DATABASE=Technicolor
+
+OUI:900A39*
+ ID_OUI_FROM_DATABASE=Wiio, Inc.
+
+OUI:C4693E*
+ ID_OUI_FROM_DATABASE=Turbulence Design Inc.
+
+OUI:1C8341*
+ ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd
+
 OUI:6C1E70*
  ID_OUI_FROM_DATABASE=Guangzhou YBDS IT Co.,Ltd
 
 OUI:C8E130*
  ID_OUI_FROM_DATABASE=Milkyway Group Ltd
 
+OUI:20E407*
+ ID_OUI_FROM_DATABASE=Spark srl
+
+OUI:887384*
+ ID_OUI_FROM_DATABASE=Toshiba
+
 OUI:8833BE*
  ID_OUI_FROM_DATABASE=Ivenix, Inc.
 
@@ -32690,23 +33902,8 @@ OUI:144146*
 OUI:F41563*
  ID_OUI_FROM_DATABASE=F5 Networks, Inc.
 
-OUI:C4EA1D*
- ID_OUI_FROM_DATABASE=Technicolor
-
-OUI:20E407*
- ID_OUI_FROM_DATABASE=Spark srl
-
-OUI:887384*
- ID_OUI_FROM_DATABASE=Toshiba
-
-OUI:584704*
- ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd
-
-OUI:1C14B3*
- ID_OUI_FROM_DATABASE=Pinyon Technologies
-
-OUI:A0E4CB*
- ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+OUI:4011DC*
+ ID_OUI_FROM_DATABASE=Sonance
 
 OUI:749CE3*
  ID_OUI_FROM_DATABASE=Art2Wave Canada Inc.
@@ -32723,9 +33920,6 @@ OUI:7CC709*
 OUI:3C8C40*
  ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
 
-OUI:0071C2*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:D45556*
  ID_OUI_FROM_DATABASE=Fiber Mountain Inc.
 
@@ -32747,6 +33941,9 @@ OUI:08D34B*
 OUI:C808E9*
  ID_OUI_FROM_DATABASE=LG Electronics
 
+OUI:589B0B*
+ ID_OUI_FROM_DATABASE=Shineway Technologies, Inc.
+
 OUI:78ACBF*
  ID_OUI_FROM_DATABASE=Igneous Systems
 
@@ -32762,6 +33959,12 @@ OUI:844BB7*
 OUI:148F21*
  ID_OUI_FROM_DATABASE=Garmin International
 
+OUI:1C7D22*
+ ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd.
+
+OUI:ACD1B8*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
 OUI:3C6A9D*
  ID_OUI_FROM_DATABASE=Dexatek Technology LTD.
 
@@ -32771,20 +33974,17 @@ OUI:14893E*
 OUI:60F189*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
-OUI:74A34A*
- ID_OUI_FROM_DATABASE=ZIMI CORPORATION
-
-OUI:98F5A9*
- ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD.
+OUI:241C04*
+ ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD.
 
-OUI:D89341*
- ID_OUI_FROM_DATABASE=General Electric Global Research
+OUI:F8CFC5*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
 
-OUI:F4645D*
- ID_OUI_FROM_DATABASE=Toshiba
+OUI:7C11CD*
+ ID_OUI_FROM_DATABASE=QianTang Technology
 
-OUI:30D587*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:0492EE*
+ ID_OUI_FROM_DATABASE=iway AG
 
 OUI:B04519*
  ID_OUI_FROM_DATABASE=TCT mobile ltd
@@ -32801,8 +34001,23 @@ OUI:2C337A*
 OUI:844464*
  ID_OUI_FROM_DATABASE=ServerU Inc
 
-OUI:589B0B*
- ID_OUI_FROM_DATABASE=Shineway Technologies, Inc.
+OUI:78312B*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+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
+
+OUI:F4645D*
+ ID_OUI_FROM_DATABASE=Toshiba
+
+OUI:30D587*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:A48CDB*
  ID_OUI_FROM_DATABASE=Lenovo
@@ -32813,35 +34028,20 @@ OUI:4062B6*
 OUI:3C2C94*
  ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd)
 
-OUI:78312B*
- ID_OUI_FROM_DATABASE=zte corporation
-
-OUI:C035C5*
- ID_OUI_FROM_DATABASE=Prosoft Systems LTD
-
-OUI:F8B2F3*
- ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD
-
-OUI:1C7D22*
- ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd.
-
-OUI:ACD1B8*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
-
-OUI:7C11CD*
- ID_OUI_FROM_DATABASE=QianTang Technology
-
-OUI:0492EE*
- ID_OUI_FROM_DATABASE=iway AG
-
 OUI:48A9D2*
  ID_OUI_FROM_DATABASE=Wistron Neweb Corp.
 
 OUI:F02A23*
  ID_OUI_FROM_DATABASE=Creative Next Design
 
-OUI:8C9109*
- ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd.
+OUI:584704*
+ ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd
+
+OUI:1C14B3*
+ ID_OUI_FROM_DATABASE=Pinyon Technologies
+
+OUI:A0E4CB*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
 
 OUI:307350*
  ID_OUI_FROM_DATABASE=Inpeco SA
@@ -32861,26 +34061,8 @@ OUI:3C1E13*
 OUI:B4A828*
  ID_OUI_FROM_DATABASE=Shenzhen Concox Information Technology Co., Ltd
 
-OUI:A41242*
- ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
-
-OUI:404EEB*
- ID_OUI_FROM_DATABASE=Higher Way Electronic Co., Ltd.
-
-OUI:50BD5F*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
-OUI:147590*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
-OUI:ECB907*
- ID_OUI_FROM_DATABASE=CloudGenix Inc
-
-OUI:5CF9F0*
- ID_OUI_FROM_DATABASE=Atomos Engineering P/L
-
-OUI:F409D8*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
+OUI:50F43C*
+ ID_OUI_FROM_DATABASE=Leeo Inc
 
 OUI:FCDBB3*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
@@ -32906,8 +34088,8 @@ OUI:C0EEFB*
 OUI:E00DB9*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:108A1B*
- ID_OUI_FROM_DATABASE=RAONIX Inc.
+OUI:A41242*
+ ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
 
 OUI:8CF813*
  ID_OUI_FROM_DATABASE=ORANGE POLSKA
@@ -32927,29 +34109,8 @@ OUI:C401CE*
 OUI:D01242*
  ID_OUI_FROM_DATABASE=BIOS Corporation
 
-OUI:50F43C*
- ID_OUI_FROM_DATABASE=Leeo Inc
-
-OUI:B43934*
- ID_OUI_FROM_DATABASE=Pen Generations, Inc.
-
-OUI:C03896*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
-
-OUI:DCC622*
- ID_OUI_FROM_DATABASE=BUHEUNG SYSTEM
-
-OUI:5C2BF5*
- ID_OUI_FROM_DATABASE=Vivint
-
-OUI:6C0B84*
- ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd.
-
-OUI:D062A0*
- ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd.
-
-OUI:CC10A3*
- ID_OUI_FROM_DATABASE=Beijing Nan Bao Technology Co., Ltd.
+OUI:6CBFB5*
+ ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd
 
 OUI:2CA30E*
  ID_OUI_FROM_DATABASE=POWER DRAGON DEVELOPMENT LIMITED
@@ -32975,8 +34136,50 @@ OUI:CC3080*
 OUI:F82441*
  ID_OUI_FROM_DATABASE=Yeelink
 
-OUI:6CBFB5*
- ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd
+OUI:108A1B*
+ ID_OUI_FROM_DATABASE=RAONIX Inc.
+
+OUI:94B40F*
+ ID_OUI_FROM_DATABASE=Aruba Networks
+
+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.
+
+OUI:CC3F1D*
+ ID_OUI_FROM_DATABASE=Intesis Software SL
+
+OUI:902181*
+ ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd
+
+OUI:D062A0*
+ ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd.
+
+OUI:CC10A3*
+ ID_OUI_FROM_DATABASE=Beijing Nan Bao Technology Co., Ltd.
+
+OUI:B43934*
+ ID_OUI_FROM_DATABASE=Pen Generations, Inc.
+
+OUI:C03896*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:DCC622*
+ ID_OUI_FROM_DATABASE=BUHEUNG SYSTEM
+
+OUI:5C2BF5*
+ ID_OUI_FROM_DATABASE=Vivint
+
+OUI:6C0B84*
+ ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd.
+
+OUI:600417*
+ ID_OUI_FROM_DATABASE=POSBANK CO.,LTD
 
 OUI:489D18*
  ID_OUI_FROM_DATABASE=Flashbay Limited
@@ -32996,26 +34199,17 @@ OUI:E4C62B*
 OUI:80F8EB*
  ID_OUI_FROM_DATABASE=RayTight
 
-OUI:94B40F*
- ID_OUI_FROM_DATABASE=Aruba Networks
-
-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.
+OUI:F409D8*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
 
-OUI:CC3F1D*
- ID_OUI_FROM_DATABASE=Intesis Software SL
+OUI:C035C5*
+ ID_OUI_FROM_DATABASE=Prosoft Systems LTD
 
-OUI:902181*
- ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd
+OUI:F8B2F3*
+ ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD
 
-OUI:600417*
- ID_OUI_FROM_DATABASE=POSBANK CO.,LTD
+OUI:8C9109*
+ ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd.
 
 OUI:A44AD3*
  ID_OUI_FROM_DATABASE=ST Electronics(Shanghai) Co.,Ltd
@@ -33044,23 +34238,11 @@ OUI:907EBA*
 OUI:488244*
  ID_OUI_FROM_DATABASE=Life Fitness / Div. of Brunswick
 
-OUI:A8F7E0*
- ID_OUI_FROM_DATABASE=PLANET Technology Corporation
-
-OUI:2C5BE1*
- ID_OUI_FROM_DATABASE=Centripetal Networks, Inc
-
-OUI:D87EB1*
- ID_OUI_FROM_DATABASE=x.o.ware, inc.
-
-OUI:4045DA*
- ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd.
-
-OUI:98BE94*
- ID_OUI_FROM_DATABASE=IBM
+OUI:D85DFB*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:D4B43E*
- ID_OUI_FROM_DATABASE=Messcomp Datentechnik GmbH
+OUI:7CC4EF*
+ ID_OUI_FROM_DATABASE=Devialet
 
 OUI:A8E539*
  ID_OUI_FROM_DATABASE=Moimstone Co.,Ltd
@@ -33071,21 +34253,27 @@ OUI:98F170*
 OUI:04C991*
  ID_OUI_FROM_DATABASE=Phistek INC.
 
+OUI:404EEB*
+ ID_OUI_FROM_DATABASE=Higher Way Electronic Co., Ltd.
+
+OUI:50BD5F*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:147590*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:ECB907*
+ ID_OUI_FROM_DATABASE=CloudGenix Inc
+
+OUI:5CF9F0*
+ ID_OUI_FROM_DATABASE=Atomos Engineering P/L
+
 OUI:581F67*
  ID_OUI_FROM_DATABASE=Open-m technology limited
 
 OUI:BC25F0*
  ID_OUI_FROM_DATABASE=3D Display Technologies Co., Ltd.
 
-OUI:7CE524*
- ID_OUI_FROM_DATABASE=Quirky, Inc.
-
-OUI:D85DFB*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:7CC4EF*
- ID_OUI_FROM_DATABASE=Devialet
-
 OUI:94AEE3*
  ID_OUI_FROM_DATABASE=Belden Hirschmann Industries (Suzhou) Ltd.
 
@@ -33098,15 +34286,6 @@ OUI:705B2E*
 OUI:0C8C8F*
  ID_OUI_FROM_DATABASE=Kamo Technology Limited
 
-OUI:F4FD2B*
- ID_OUI_FROM_DATABASE=ZOYI Company
-
-OUI:FCAA14*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
-
-OUI:50FEF2*
- ID_OUI_FROM_DATABASE=Sify Technologies Ltd
-
 OUI:3CD9CE*
  ID_OUI_FROM_DATABASE=Eclipse WiFi
 
@@ -33128,6 +34307,27 @@ OUI:ECD9D1*
 OUI:748F4D*
  ID_OUI_FROM_DATABASE=MEN Mikro Elektronik GmbH
 
+OUI:F4FD2B*
+ ID_OUI_FROM_DATABASE=ZOYI Company
+
+OUI:FCAA14*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
+OUI:50FEF2*
+ ID_OUI_FROM_DATABASE=Sify Technologies Ltd
+
+OUI:7CE524*
+ ID_OUI_FROM_DATABASE=Quirky, Inc.
+
+OUI:7CD30A*
+ ID_OUI_FROM_DATABASE=INVENTEC Corporation
+
+OUI:3481C4*
+ ID_OUI_FROM_DATABASE=AVM GmbH
+
+OUI:885BDD*
+ ID_OUI_FROM_DATABASE=Aerohive Networks Inc.
+
 OUI:A47E39*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -33140,17 +34340,23 @@ OUI:ACA9A0*
 OUI:A8A668*
  ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:60E327*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:A8F7E0*
+ ID_OUI_FROM_DATABASE=PLANET Technology Corporation
 
-OUI:E4D332*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:2C5BE1*
+ ID_OUI_FROM_DATABASE=Centripetal Networks, Inc
 
-OUI:A0DA92*
- ID_OUI_FROM_DATABASE=Nanjing Glarun Atten Technology Co. Ltd.
+OUI:D87EB1*
+ ID_OUI_FROM_DATABASE=x.o.ware, inc.
 
-OUI:6828BA*
- ID_OUI_FROM_DATABASE=Dejai
+OUI:4045DA*
+ ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd.
+
+OUI:98BE94*
+ ID_OUI_FROM_DATABASE=IBM
+
+OUI:D4B43E*
+ ID_OUI_FROM_DATABASE=Messcomp Datentechnik GmbH
 
 OUI:48D18E*
  ID_OUI_FROM_DATABASE=Metis Communication Co.,Ltd
@@ -33158,18 +34364,6 @@ OUI:48D18E*
 OUI:A49F85*
  ID_OUI_FROM_DATABASE=Lyve Minds, Inc
 
-OUI:7CD30A*
- ID_OUI_FROM_DATABASE=INVENTEC Corporation
-
-OUI:3481C4*
- ID_OUI_FROM_DATABASE=AVM GmbH
-
-OUI:885BDD*
- ID_OUI_FROM_DATABASE=Aerohive Networks Inc.
-
-OUI:085700*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
 OUI:888914*
  ID_OUI_FROM_DATABASE=All Components Incorporated
 
@@ -33182,8 +34376,8 @@ OUI:A06518*
 OUI:748F1B*
  ID_OUI_FROM_DATABASE=MasterImage 3D
 
-OUI:F03A4B*
- ID_OUI_FROM_DATABASE=Bloombase, Inc.
+OUI:684898*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:E4121D*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -33248,17 +34442,20 @@ OUI:50B695*
 OUI:B48547*
  ID_OUI_FROM_DATABASE=Amptown System Company GmbH
 
-OUI:3C25D7*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:085700*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:1889DF*
- ID_OUI_FROM_DATABASE=CerebrEX Inc.
+OUI:60E327*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:30A8DB*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+OUI:E4D332*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:CC9F35*
- ID_OUI_FROM_DATABASE=Transbit Sp. z o.o.
+OUI:A0DA92*
+ ID_OUI_FROM_DATABASE=Nanjing Glarun Atten Technology Co. Ltd.
+
+OUI:6828BA*
+ ID_OUI_FROM_DATABASE=Dejai
 
 OUI:407875*
  ID_OUI_FROM_DATABASE=IMBEL - Industria de Material Belico do Brasil
@@ -33290,23 +34487,29 @@ OUI:88E8F8*
 OUI:2C073C*
  ID_OUI_FROM_DATABASE=DEVLINE LIMITED
 
-OUI:7CE4AA*
- ID_OUI_FROM_DATABASE=Private
+OUI:F015A0*
+ ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd.
 
-OUI:1820A6*
- ID_OUI_FROM_DATABASE=Sage Co., Ltd.
+OUI:ECF72B*
+ ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD.
 
-OUI:BCF61C*
- ID_OUI_FROM_DATABASE=Geomodeling Wuxi Technology Co. Ltd.
+OUI:D8B6D6*
+ ID_OUI_FROM_DATABASE=Blu Tether Limited
 
-OUI:083F3E*
- ID_OUI_FROM_DATABASE=WSH GmbH
+OUI:847207*
+ ID_OUI_FROM_DATABASE=I&C Technology
 
-OUI:6C09D6*
- ID_OUI_FROM_DATABASE=Digiquest Electronics LTD
+OUI:3C25D7*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:684898*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:1889DF*
+ ID_OUI_FROM_DATABASE=CerebrEX Inc.
+
+OUI:30A8DB*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
+OUI:CC9F35*
+ ID_OUI_FROM_DATABASE=Transbit Sp. z o.o.
 
 OUI:8C569D*
  ID_OUI_FROM_DATABASE=Imaging Solutions Group
@@ -33329,11 +34532,26 @@ OUI:4CE1BB*
 OUI:8CDE99*
  ID_OUI_FROM_DATABASE=Comlab Inc.
 
-OUI:1088CE*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:085AE0*
+ ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd.
 
-OUI:FCF647*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:7CE4AA*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:1820A6*
+ ID_OUI_FROM_DATABASE=Sage Co., Ltd.
+
+OUI:BCF61C*
+ ID_OUI_FROM_DATABASE=Geomodeling Wuxi Technology Co. Ltd.
+
+OUI:083F3E*
+ ID_OUI_FROM_DATABASE=WSH GmbH
+
+OUI:6C09D6*
+ ID_OUI_FROM_DATABASE=Digiquest Electronics LTD
+
+OUI:F03A4B*
+ ID_OUI_FROM_DATABASE=Bloombase, Inc.
 
 OUI:2C9AA4*
  ID_OUI_FROM_DATABASE=NGI SpA
@@ -33347,35 +34565,47 @@ OUI:283B96*
 OUI:80D433*
  ID_OUI_FROM_DATABASE=LzLabs GmbH
 
-OUI:085AE0*
- ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd.
+OUI:687CC8*
+ ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L.
 
-OUI:BCEE7B*
- ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:38BF2F*
+ ID_OUI_FROM_DATABASE=Espec Corp.
 
-OUI:8C3AE3*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:182012*
+ ID_OUI_FROM_DATABASE=Aztech Associates Inc.
 
-OUI:FC09D8*
- ID_OUI_FROM_DATABASE=ACTEON Group
+OUI:34BE00*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:0C1262*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:343111*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:687CC8*
- ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L.
+OUI:0CBD51*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
 
-OUI:F015A0*
- ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd.
+OUI:C0F991*
+ ID_OUI_FROM_DATABASE=GME Standard Communications P/L
 
-OUI:ECF72B*
- ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD.
+OUI:14EDA5*
+ ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme
 
-OUI:D8B6D6*
- ID_OUI_FROM_DATABASE=Blu Tether Limited
+OUI:E056F4*
+ ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc.
 
-OUI:847207*
- ID_OUI_FROM_DATABASE=I&C Technology
+OUI:B8C1A2*
+ ID_OUI_FROM_DATABASE=Dragon Path Technologies Co., Limited
+
+OUI:50ED78*
+ ID_OUI_FROM_DATABASE=Changzhou Yongse Infotech Co.,Ltd
+
+OUI:8CB7F7*
+ ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd
+
+OUI:085240*
+ ID_OUI_FROM_DATABASE=EbV Elektronikbau- und Vertriebs GmbH
+
+OUI:80F25E*
+ ID_OUI_FROM_DATABASE=Kyynel
 
 OUI:94DF4E*
  ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
@@ -33383,9 +34613,6 @@ OUI:94DF4E*
 OUI:E0AEB2*
  ID_OUI_FROM_DATABASE=Bender GmbH &amp; Co.KG
 
-OUI:BC9889*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:2C553C*
  ID_OUI_FROM_DATABASE=Gainspeed, Inc.
 
@@ -33404,21 +34631,6 @@ OUI:2464EF*
 OUI:50B888*
  ID_OUI_FROM_DATABASE=wi2be Tecnologia S/A
 
-OUI:B8C1A2*
- ID_OUI_FROM_DATABASE=Dragon Path Technologies Co., Limited
-
-OUI:50ED78*
- ID_OUI_FROM_DATABASE=Changzhou Yongse Infotech Co.,Ltd
-
-OUI:8CB7F7*
- ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd
-
-OUI:085240*
- ID_OUI_FROM_DATABASE=EbV Elektronikbau- und Vertriebs GmbH
-
-OUI:80F25E*
- ID_OUI_FROM_DATABASE=Kyynel
-
 OUI:844F03*
  ID_OUI_FROM_DATABASE=Ablelink Electronics Ltd
 
@@ -33452,62 +34664,11 @@ 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.
-
-OUI:182012*
- ID_OUI_FROM_DATABASE=Aztech Associates Inc.
-
-OUI:34BE00*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:343111*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:0CBD51*
- ID_OUI_FROM_DATABASE=TCT Mobile Limited
-
-OUI:C0F991*
- ID_OUI_FROM_DATABASE=GME Standard Communications P/L
-
-OUI:14EDA5*
- ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme
-
-OUI:E056F4*
- ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc.
-
-OUI:385AA8*
- ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co.
-
-OUI:FC3FAB*
- ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd
-
-OUI:F8FF5F*
- ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd
-
-OUI:DCC422*
- ID_OUI_FROM_DATABASE=Systembase Limited
-
-OUI:F4BD7C*
- ID_OUI_FROM_DATABASE=Chengdu jinshi communication Co., LTD
-
-OUI:C8F36B*
- ID_OUI_FROM_DATABASE=Yamato Scale Co.,Ltd.
-
-OUI:6C90B1*
- ID_OUI_FROM_DATABASE=SanLogic Inc
-
-OUI:845C93*
- ID_OUI_FROM_DATABASE=Chabrier Services
-
-OUI:D44C9C*
- ID_OUI_FROM_DATABASE=Shenzhen YOOBAO Technology Co.Ltd
+OUI:1C63B7*
+ ID_OUI_FROM_DATABASE=OpenProducts 237 AB
 
-OUI:A88D7B*
- ID_OUI_FROM_DATABASE=SunDroid Global limited.
+OUI:A0A23C*
+ ID_OUI_FROM_DATABASE=GPMS
 
 OUI:A03B1B*
  ID_OUI_FROM_DATABASE=Inspire Tech
@@ -33530,7 +34691,31 @@ OUI:6C4B7F*
 OUI:0CCB8D*
  ID_OUI_FROM_DATABASE=ASCO Numatics GmbH
 
-OUI:2847AA*
+OUI:FC019E*
+ ID_OUI_FROM_DATABASE=VIEVU
+
+OUI:34AA8B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:F45F69*
+ ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company
+
+OUI:F4A294*
+ ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED
+
+OUI:2CCD69*
+ ID_OUI_FROM_DATABASE=Aqavi.com
+
+OUI:947C3E*
+ ID_OUI_FROM_DATABASE=Polewall Norge AS
+
+OUI:385AA8*
+ ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co.
+
+OUI:FC3FAB*
+ ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd
+
+OUI:2847AA*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
 OUI:682DDC*
@@ -33539,11 +34724,14 @@ OUI:682DDC*
 OUI:FCB0C4*
  ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd
 
-OUI:1C63B7*
- ID_OUI_FROM_DATABASE=OpenProducts 237 AB
+OUI:9CBB98*
+ ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD
 
-OUI:A0A23C*
- ID_OUI_FROM_DATABASE=GPMS
+OUI:345C40*
+ ID_OUI_FROM_DATABASE=Cargt Holdings LLC
+
+OUI:34885D*
+ ID_OUI_FROM_DATABASE=Logitech Far East
 
 OUI:708D09*
  ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -33557,17 +34745,8 @@ OUI:38B74D*
 OUI:A0E5E9*
  ID_OUI_FROM_DATABASE=enimai Inc
 
-OUI:9CBB98*
- ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD
-
-OUI:345C40*
- ID_OUI_FROM_DATABASE=Cargt Holdings LLC
-
-OUI:34885D*
- ID_OUI_FROM_DATABASE=Logitech Far East
-
-OUI:B462AD*
- ID_OUI_FROM_DATABASE=raytest GmbH
+OUI:A88D7B*
+ ID_OUI_FROM_DATABASE=SunDroid Global limited.
 
 OUI:6064A1*
  ID_OUI_FROM_DATABASE=RADiflow Ltd.
@@ -33587,23 +34766,20 @@ OUI:FC1BFF*
 OUI:AC5036*
  ID_OUI_FROM_DATABASE=Pi-Coral Inc
 
-OUI:FC019E*
- ID_OUI_FROM_DATABASE=VIEVU
-
-OUI:34AA8B*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:BCEE7B*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
 
-OUI:F45F69*
- ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company
+OUI:8C3AE3*
+ ID_OUI_FROM_DATABASE=LG Electronics
 
-OUI:F4A294*
- ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED
+OUI:FC09D8*
+ ID_OUI_FROM_DATABASE=ACTEON Group
 
-OUI:2CCD69*
- ID_OUI_FROM_DATABASE=Aqavi.com
+OUI:0C1262*
+ ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:947C3E*
- ID_OUI_FROM_DATABASE=Polewall Norge AS
+OUI:A875E2*
+ ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
 
 OUI:E0D1E6*
  ID_OUI_FROM_DATABASE=Aliph dba Jawbone
@@ -33629,17 +34805,35 @@ OUI:306112*
 OUI:A0C6EC*
  ID_OUI_FROM_DATABASE=ShenZhen ANYK Technology Co.,LTD
 
-OUI:C80258*
- ID_OUI_FROM_DATABASE=ITW GSE ApS
+OUI:6405BE*
+ ID_OUI_FROM_DATABASE=NEW LIGHT LED
 
-OUI:1001CA*
- ID_OUI_FROM_DATABASE=Ashley Butterworth
+OUI:F8FF5F*
+ ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd
 
-OUI:246AAB*
- ID_OUI_FROM_DATABASE=IT-IS International
+OUI:DCC422*
+ ID_OUI_FROM_DATABASE=Systembase Limited
 
-OUI:28F532*
- ID_OUI_FROM_DATABASE=ADD-Engineering BV
+OUI:F4BD7C*
+ ID_OUI_FROM_DATABASE=Chengdu jinshi communication Co., LTD
+
+OUI:C8F36B*
+ ID_OUI_FROM_DATABASE=Yamato Scale Co.,Ltd.
+
+OUI:6C90B1*
+ ID_OUI_FROM_DATABASE=SanLogic Inc
+
+OUI:845C93*
+ ID_OUI_FROM_DATABASE=Chabrier Services
+
+OUI:D44C9C*
+ ID_OUI_FROM_DATABASE=Shenzhen YOOBAO Technology Co.Ltd
+
+OUI:68E166*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:60FEF9*
+ ID_OUI_FROM_DATABASE=Thomas & Betts
 
 OUI:FC4BBC*
  ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd.
@@ -33677,29 +34871,35 @@ OUI:E8519D*
 OUI:00B78D*
  ID_OUI_FROM_DATABASE=Nanjing Shining Electric Automation Co., Ltd
 
-OUI:68E166*
- ID_OUI_FROM_DATABASE=Private
+OUI:882364*
+ ID_OUI_FROM_DATABASE=Watchnet DVR Inc
 
-OUI:60FEF9*
- ID_OUI_FROM_DATABASE=Thomas & Betts
+OUI:A05B21*
+ ID_OUI_FROM_DATABASE=ENVINET GmbH
 
-OUI:78FE41*
- ID_OUI_FROM_DATABASE=Socus networks
+OUI:50B8A2*
+ ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
 
-OUI:083571*
- ID_OUI_FROM_DATABASE=CASwell INC.
+OUI:A41566*
+ ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
 
-OUI:DCF755*
- ID_OUI_FROM_DATABASE=SITRONIK
+OUI:B04C05*
+ ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH
 
-OUI:E42D02*
- ID_OUI_FROM_DATABASE=TCT Mobile Limited
+OUI:A0EC80*
+ ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:ACCA8E*
- ID_OUI_FROM_DATABASE=ODA Technologies
+OUI:9046B7*
+ ID_OUI_FROM_DATABASE=Vadaro Pte Ltd
 
-OUI:6405BE*
- ID_OUI_FROM_DATABASE=NEW LIGHT LED
+OUI:1C08C1*
+ ID_OUI_FROM_DATABASE=Lg Innotek
+
+OUI:201D03*
+ ID_OUI_FROM_DATABASE=Elatec GmbH
+
+OUI:C06C6D*
+ ID_OUI_FROM_DATABASE=MagneMotion, Inc.
 
 OUI:E03E4A*
  ID_OUI_FROM_DATABASE=Cavanagh Group International
@@ -33725,35 +34925,32 @@ OUI:1C86AD*
 OUI:28D93E*
  ID_OUI_FROM_DATABASE=Telecor Inc.
 
-OUI:882364*
- ID_OUI_FROM_DATABASE=Watchnet DVR Inc
-
-OUI:A05B21*
- ID_OUI_FROM_DATABASE=ENVINET GmbH
+OUI:C80258*
+ ID_OUI_FROM_DATABASE=ITW GSE ApS
 
-OUI:50B8A2*
- ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
+OUI:1001CA*
+ ID_OUI_FROM_DATABASE=Ashley Butterworth
 
-OUI:A41566*
- ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
+OUI:246AAB*
+ ID_OUI_FROM_DATABASE=IT-IS International
 
-OUI:B04C05*
- ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH
+OUI:28F532*
+ ID_OUI_FROM_DATABASE=ADD-Engineering BV
 
-OUI:A0EC80*
- ID_OUI_FROM_DATABASE=zte corporation
+OUI:78FE41*
+ ID_OUI_FROM_DATABASE=Socus networks
 
-OUI:9046B7*
- ID_OUI_FROM_DATABASE=Vadaro Pte Ltd
+OUI:083571*
+ ID_OUI_FROM_DATABASE=CASwell INC.
 
-OUI:1C08C1*
- ID_OUI_FROM_DATABASE=Lg Innotek
+OUI:DCF755*
+ ID_OUI_FROM_DATABASE=SITRONIK
 
-OUI:201D03*
- ID_OUI_FROM_DATABASE=Elatec GmbH
+OUI:E42D02*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
 
-OUI:C06C6D*
- ID_OUI_FROM_DATABASE=MagneMotion, Inc.
+OUI:ACCA8E*
+ ID_OUI_FROM_DATABASE=ODA Technologies
 
 OUI:74CA25*
  ID_OUI_FROM_DATABASE=Calxeda, Inc.
@@ -33764,42 +34961,6 @@ OUI:181EB0*
 OUI:CCBD35*
  ID_OUI_FROM_DATABASE=Steinel GmbH
 
-OUI:788DF7*
- ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
-
-OUI:6CECA1*
- ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD.
-
-OUI:D862DB*
- ID_OUI_FROM_DATABASE=Eno Inc.
-
-OUI:68DB67*
- ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd
-
-OUI:BC261D*
- ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY
-
-OUI:888964*
- ID_OUI_FROM_DATABASE=GSI Electronics Inc.
-
-OUI:4C82CF*
- ID_OUI_FROM_DATABASE=Echostar Technologies
-
-OUI:9CA577*
- ID_OUI_FROM_DATABASE=Osorno Enterprises Inc.
-
-OUI:C0C3B6*
- ID_OUI_FROM_DATABASE=Automatic Systems
-
-OUI:A8294C*
- ID_OUI_FROM_DATABASE=Precision Optical Transceivers, Inc.
-
-OUI:D0EB03*
- ID_OUI_FROM_DATABASE=Zhehua technology limited
-
-OUI:A0861D*
- ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd
-
 OUI:9498A2*
  ID_OUI_FROM_DATABASE=Shanghai LISTEN TECH.LTD
 
@@ -33818,89 +34979,89 @@ OUI:D82916*
 OUI:6472D8*
  ID_OUI_FROM_DATABASE=GooWi Technology Co.,Limited
 
-OUI:84ACA4*
- ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd
+OUI:3C081E*
+ ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd
 
-OUI:3C6FF7*
- ID_OUI_FROM_DATABASE=EnTek Systems, Inc.
+OUI:7CA15D*
+ ID_OUI_FROM_DATABASE=GN ReSound A/S
 
-OUI:B838CA*
- ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD
+OUI:B4DD15*
+ ID_OUI_FROM_DATABASE=ControlThings Oy Ab
 
-OUI:380FE4*
- ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy
+OUI:F8FEA8*
+ ID_OUI_FROM_DATABASE=Technico Japan Corporation
 
-OUI:847A88*
- ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:A8154D*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:0808C2*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:D05099*
+ ID_OUI_FROM_DATABASE=ASRock Incorporation
 
-OUI:5461EA*
- ID_OUI_FROM_DATABASE=Zaplox AB
+OUI:78A106*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:78324F*
- ID_OUI_FROM_DATABASE=Millennium Group, Inc.
+OUI:A49EDB*
+ ID_OUI_FROM_DATABASE=AutoCrib, Inc.
 
-OUI:F05DC8*
- ID_OUI_FROM_DATABASE=Duracell Powermat
+OUI:282CB2*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:48F925*
- ID_OUI_FROM_DATABASE=Maestronic
+OUI:D43A65*
+ ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd.
 
-OUI:C0885B*
- ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
+OUI:D0EB03*
+ ID_OUI_FROM_DATABASE=Zhehua technology limited
 
-OUI:64C667*
- ID_OUI_FROM_DATABASE=Barnes&Noble
+OUI:A0861D*
+ ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd
 
-OUI:C47DCC*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:888964*
+ ID_OUI_FROM_DATABASE=GSI Electronics Inc.
 
-OUI:64535D*
- ID_OUI_FROM_DATABASE=Frauscher Sensortechnik
+OUI:4C82CF*
+ ID_OUI_FROM_DATABASE=Echostar Technologies
 
-OUI:105F06*
- ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+OUI:9CA577*
+ ID_OUI_FROM_DATABASE=Osorno Enterprises Inc.
 
-OUI:841715*
- ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd.
+OUI:C0C3B6*
+ ID_OUI_FROM_DATABASE=Automatic Systems
 
-OUI:087999*
- ID_OUI_FROM_DATABASE=AIM GmbH
+OUI:A8294C*
+ ID_OUI_FROM_DATABASE=Precision Optical Transceivers, Inc.
 
-OUI:84C2E4*
- ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd.
+OUI:3C86A8*
+ ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD
 
-OUI:C0B8B1*
- ID_OUI_FROM_DATABASE=BitBox Ltd
+OUI:FCDD55*
+ ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd
 
-OUI:0C722C*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:CC0DEC*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
 
-OUI:B01408*
- ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO.
+OUI:68B094*
+ ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD
 
-OUI:F8FEA8*
- ID_OUI_FROM_DATABASE=Technico Japan Corporation
+OUI:40E730*
+ ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc.
 
-OUI:A8154D*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:F05DC8*
+ ID_OUI_FROM_DATABASE=Duracell Powermat
 
-OUI:D05099*
- ID_OUI_FROM_DATABASE=ASRock Incorporation
+OUI:6C8686*
+ ID_OUI_FROM_DATABASE=Technonia
 
-OUI:78A106*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:4432C8*
+ ID_OUI_FROM_DATABASE=Technicolor USA Inc.
 
-OUI:A49EDB*
- ID_OUI_FROM_DATABASE=AutoCrib, Inc.
+OUI:78521A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:282CB2*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:68DB67*
+ ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd
 
-OUI:D43A65*
- ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd.
+OUI:BC261D*
+ ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY
 
 OUI:10B9FE*
  ID_OUI_FROM_DATABASE=Lika srl
@@ -33923,41 +35084,47 @@ OUI:30CDA7*
 OUI:104D77*
  ID_OUI_FROM_DATABASE=Innovative Computer Engineering
 
-OUI:3C081E*
- ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd
+OUI:788DF7*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
 
-OUI:7CA15D*
- ID_OUI_FROM_DATABASE=GN ReSound A/S
+OUI:6CECA1*
+ ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD.
 
-OUI:B4DD15*
- ID_OUI_FROM_DATABASE=ControlThings Oy Ab
+OUI:D862DB*
+ ID_OUI_FROM_DATABASE=Eno Inc.
 
-OUI:3C86A8*
- ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD
+OUI:A8D236*
+ ID_OUI_FROM_DATABASE=Lightware Visual Engineering
 
-OUI:FCDD55*
- ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd
+OUI:48F925*
+ ID_OUI_FROM_DATABASE=Maestronic
 
-OUI:CC0DEC*
- ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:C0885B*
+ ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
 
-OUI:68B094*
- ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD
+OUI:64C667*
+ ID_OUI_FROM_DATABASE=Barnes&Noble
 
-OUI:40E730*
- ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc.
+OUI:C47DCC*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Inc
 
-OUI:A8D236*
- ID_OUI_FROM_DATABASE=Lightware Visual Engineering
+OUI:64535D*
+ ID_OUI_FROM_DATABASE=Frauscher Sensortechnik
 
-OUI:6C8686*
- ID_OUI_FROM_DATABASE=Technonia
+OUI:105F06*
+ ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
 
-OUI:4432C8*
- ID_OUI_FROM_DATABASE=Technicolor USA Inc.
+OUI:00B56D*
+ ID_OUI_FROM_DATABASE=David Electronics Co., LTD.
 
-OUI:78521A*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:B461FF*
+ ID_OUI_FROM_DATABASE=Lumigon A/S
+
+OUI:9038DF*
+ ID_OUI_FROM_DATABASE=Changzhou Tiannengbo System Co. Ltd.
+
+OUI:CC593E*
+ ID_OUI_FROM_DATABASE=TOUMAZ LTD
 
 OUI:84E714*
  ID_OUI_FROM_DATABASE=Liang Herng Enterprise,Co.Ltd.
@@ -33965,15 +35132,6 @@ OUI:84E714*
 OUI:303D08*
  ID_OUI_FROM_DATABASE=GLINTT TES S.A.
 
-OUI:9C541C*
- ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd
-
-OUI:90187C*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
-
-OUI:FC1F19*
- ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD.
-
 OUI:E496AE*
  ID_OUI_FROM_DATABASE=ALTOGRAPHICS Inc.
 
@@ -34004,66 +35162,6 @@ OUI:ECB541*
 OUI:D40057*
  ID_OUI_FROM_DATABASE=MC Technologies GmbH
 
-OUI:48B8DE*
- ID_OUI_FROM_DATABASE=HOMEWINS TECHNOLOGY CO.,LTD.
-
-OUI:20D5BF*
- ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd
-
-OUI:6CD032*
- ID_OUI_FROM_DATABASE=LG Electronics
-
-OUI:1065CF*
- ID_OUI_FROM_DATABASE=IQSIM
-
-OUI:B877C3*
- ID_OUI_FROM_DATABASE=Decagon Devices, Inc.
-
-OUI:849DC5*
- ID_OUI_FROM_DATABASE=Centera Photonics Inc.
-
-OUI:580943*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:547FA8*
- ID_OUI_FROM_DATABASE=TELCO systems, s.r.o.
-
-OUI:5474E6*
- ID_OUI_FROM_DATABASE=Webtech Wireless
-
-OUI:AC5D10*
- ID_OUI_FROM_DATABASE=Pace Americas
-
-OUI:88F490*
- ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd
-
-OUI:E8A364*
- ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio
-
-OUI:D0D6CC*
- ID_OUI_FROM_DATABASE=Wintop
-
-OUI:101D51*
- ID_OUI_FROM_DATABASE=ON-Q LLC dba ON-Q Mesh Networks
-
-OUI:34C99D*
- ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD.
-
-OUI:8C4AEE*
- ID_OUI_FROM_DATABASE=GIGA TMS INC
-
-OUI:F46DE2*
- ID_OUI_FROM_DATABASE=zte corporation
-
-OUI:04F8C2*
- ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc.
-
-OUI:0C93FB*
- ID_OUI_FROM_DATABASE=BNS Solutions
-
-OUI:38B5BD*
- ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger
-
 OUI:B85AF7*
  ID_OUI_FROM_DATABASE=Ouya, Inc
 
@@ -34082,17 +35180,11 @@ OUI:F0219D*
 OUI:F8D7BF*
  ID_OUI_FROM_DATABASE=REV Ritter GmbH
 
-OUI:00B56D*
- ID_OUI_FROM_DATABASE=David Electronics Co., LTD.
-
-OUI:B461FF*
- ID_OUI_FROM_DATABASE=Lumigon A/S
-
-OUI:9038DF*
- ID_OUI_FROM_DATABASE=Changzhou Tiannengbo System Co. Ltd.
+OUI:AC5D10*
+ ID_OUI_FROM_DATABASE=Pace Americas
 
-OUI:CC593E*
- ID_OUI_FROM_DATABASE=TOUMAZ LTD
+OUI:88F490*
+ ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd
 
 OUI:AC8D14*
  ID_OUI_FROM_DATABASE=Smartrove Inc
@@ -34118,119 +35210,104 @@ OUI:38192F*
 OUI:141BF0*
  ID_OUI_FROM_DATABASE=Intellimedia Systems Ltd
 
-OUI:E45614*
- ID_OUI_FROM_DATABASE=Suttle Apparatus
+OUI:101D51*
+ ID_OUI_FROM_DATABASE=ON-Q LLC dba ON-Q Mesh Networks
 
-OUI:842BBC*
- ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH
+OUI:34C99D*
+ ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD.
 
-OUI:E856D6*
- ID_OUI_FROM_DATABASE=NCTech Ltd
+OUI:8C4AEE*
+ ID_OUI_FROM_DATABASE=GIGA TMS INC
 
-OUI:4088E0*
- ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch
+OUI:F46DE2*
+ ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:1CF4CA*
- ID_OUI_FROM_DATABASE=Private
+OUI:B838CA*
+ ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD
 
-OUI:F490EA*
- ID_OUI_FROM_DATABASE=Deciso B.V.
+OUI:380FE4*
+ ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy
 
-OUI:942197*
- ID_OUI_FROM_DATABASE=Stalmart Technology Limited
+OUI:847A88*
+ ID_OUI_FROM_DATABASE=HTC Corporation
 
-OUI:AC9403*
- ID_OUI_FROM_DATABASE=Envision Peripherals Inc
+OUI:0808C2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:A865B2*
- ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED
+OUI:5461EA*
+ ID_OUI_FROM_DATABASE=Zaplox AB
 
-OUI:60B982*
- ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A.
+OUI:78324F*
+ ID_OUI_FROM_DATABASE=Millennium Group, Inc.
 
-OUI:B46238*
- ID_OUI_FROM_DATABASE=Exablox
+OUI:38B5BD*
+ ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger
 
-OUI:40704A*
- ID_OUI_FROM_DATABASE=Power Idea Technology Limited
-
-OUI:A40BED*
- ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd
-
-OUI:0CD996*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:D82DE1*
- ID_OUI_FROM_DATABASE=Tricascade Inc.
-
-OUI:C438D3*
- ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD
-
-OUI:547398*
- ID_OUI_FROM_DATABASE=Toyo Electronics Corporation
+OUI:841715*
+ ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd.
 
-OUI:4C72B9*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+OUI:087999*
+ ID_OUI_FROM_DATABASE=AIM GmbH
 
-OUI:E0AAB0*
- ID_OUI_FROM_DATABASE=GENERAL VISION ELECTRONICS CO. LTD.
+OUI:84C2E4*
+ ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd.
 
-OUI:68B43A*
- ID_OUI_FROM_DATABASE=WaterFurnace International, Inc.
+OUI:C0B8B1*
+ ID_OUI_FROM_DATABASE=BitBox Ltd
 
-OUI:543968*
- ID_OUI_FROM_DATABASE=Edgewater Networks Inc
+OUI:0C722C*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:C041F6*
- ID_OUI_FROM_DATABASE=LG Electronics Inc
+OUI:B01408*
+ ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO.
 
-OUI:985E1B*
- ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd.
+OUI:84ACA4*
+ ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd
 
-OUI:B8B7D7*
- ID_OUI_FROM_DATABASE=2GIG Technologies
+OUI:3C6FF7*
+ ID_OUI_FROM_DATABASE=EnTek Systems, Inc.
 
-OUI:1048B1*
- ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited
+OUI:48B8DE*
+ ID_OUI_FROM_DATABASE=HOMEWINS TECHNOLOGY CO.,LTD.
 
-OUI:005D03*
- ID_OUI_FROM_DATABASE=Xilinx, Inc
+OUI:20D5BF*
+ ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd
 
-OUI:24EE3A*
- ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd
+OUI:6CD032*
+ ID_OUI_FROM_DATABASE=LG Electronics
 
-OUI:F82285*
- ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD.
+OUI:1065CF*
+ ID_OUI_FROM_DATABASE=IQSIM
 
-OUI:8482F4*
- ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd
+OUI:B877C3*
+ ID_OUI_FROM_DATABASE=Decagon Devices, Inc.
 
-OUI:0CC47E*
- ID_OUI_FROM_DATABASE=EUCAST Co., Ltd.
+OUI:849DC5*
+ ID_OUI_FROM_DATABASE=Centera Photonics Inc.
 
-OUI:CCE798*
- ID_OUI_FROM_DATABASE=My Social Stuff
+OUI:580943*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:50724D*
- ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH
+OUI:547FA8*
+ ID_OUI_FROM_DATABASE=TELCO systems, s.r.o.
 
-OUI:B898B0*
- ID_OUI_FROM_DATABASE=Atlona Inc.
+OUI:5474E6*
+ ID_OUI_FROM_DATABASE=Webtech Wireless
 
-OUI:1C66AA*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:E8A364*
+ ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio
 
-OUI:2C625A*
- ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd
+OUI:D0D6CC*
+ ID_OUI_FROM_DATABASE=Wintop
 
-OUI:2074CF*
- ID_OUI_FROM_DATABASE=Shenzhen Voxtech Co.,Ltd
+OUI:FC1F19*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD.
 
-OUI:ACBD0B*
- ID_OUI_FROM_DATABASE=IMAC CO.,LTD
+OUI:9C541C*
+ ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd
 
-OUI:D8D27C*
- ID_OUI_FROM_DATABASE=JEMA ENERGY, SA
+OUI:90187C*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
 
 OUI:10F3DB*
  ID_OUI_FROM_DATABASE=Gridco Systems, Inc.
@@ -34250,12 +35327,45 @@ OUI:FCD6BD*
 OUI:044A50*
  ID_OUI_FROM_DATABASE=Ramaxel Technology (Shenzhen) limited company
 
-OUI:E42F26*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:A4466B*
  ID_OUI_FROM_DATABASE=EOC Technology
 
+OUI:7C386C*
+ ID_OUI_FROM_DATABASE=Real Time Logic
+
+OUI:D8AF3B*
+ ID_OUI_FROM_DATABASE=Hangzhou Bigbright Integrated communications system Co.,Ltd
+
+OUI:78D34F*
+ ID_OUI_FROM_DATABASE=Pace-O-Matic, Inc.
+
+OUI:D857EF*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
+
+OUI:647657*
+ ID_OUI_FROM_DATABASE=Innovative Security Designs
+
+OUI:60455E*
+ ID_OUI_FROM_DATABASE=Liptel s.r.o.
+
+OUI:944A09*
+ ID_OUI_FROM_DATABASE=BitWise Controls
+
+OUI:E8102E*
+ ID_OUI_FROM_DATABASE=Really Simple Software, Inc
+
+OUI:D48CB5*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:24A43C*
+ ID_OUI_FROM_DATABASE=Ubiquiti Networks, INC
+
+OUI:D41E35*
+ ID_OUI_FROM_DATABASE=TOHO Electronics INC.
+
+OUI:700BC0*
+ ID_OUI_FROM_DATABASE=Dewav Technology Company
+
 OUI:3CF392*
  ID_OUI_FROM_DATABASE=Virtualtek. Co. Ltd
 
@@ -34268,20 +35378,23 @@ OUI:149FE8*
 OUI:70B599*
  ID_OUI_FROM_DATABASE=Embedded Technologies s.r.o.
 
-OUI:EC4C4D*
- ID_OUI_FROM_DATABASE=ZAO NPK RoTeK
+OUI:547398*
+ ID_OUI_FROM_DATABASE=Toyo Electronics Corporation
 
-OUI:E8D483*
- ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH
+OUI:E0AAB0*
+ ID_OUI_FROM_DATABASE=GENERAL VISION ELECTRONICS CO. LTD.
 
-OUI:089E01*
- ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
+OUI:68B43A*
+ ID_OUI_FROM_DATABASE=WaterFurnace International, Inc.
 
-OUI:ACD9D6*
- ID_OUI_FROM_DATABASE=tci GmbH
+OUI:543968*
+ ID_OUI_FROM_DATABASE=Edgewater Networks Inc
 
-OUI:7493A4*
- ID_OUI_FROM_DATABASE=Zebra Technologies Corp.
+OUI:C041F6*
+ ID_OUI_FROM_DATABASE=LG Electronics Inc
+
+OUI:985E1B*
+ ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd.
 
 OUI:9C0DAC*
  ID_OUI_FROM_DATABASE=Tymphany HK Limited
@@ -34289,38 +35402,41 @@ OUI:9C0DAC*
 OUI:8CD3A2*
  ID_OUI_FROM_DATABASE=VisSim AS
 
-OUI:647657*
- ID_OUI_FROM_DATABASE=Innovative Security Designs
-
-OUI:60455E*
- ID_OUI_FROM_DATABASE=Liptel s.r.o.
+OUI:24EE3A*
+ ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd
 
-OUI:944A09*
- ID_OUI_FROM_DATABASE=BitWise Controls
+OUI:F82285*
+ ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD.
 
-OUI:E8102E*
- ID_OUI_FROM_DATABASE=Really Simple Software, Inc
+OUI:8482F4*
+ ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd
 
-OUI:D48CB5*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0CC47E*
+ ID_OUI_FROM_DATABASE=EUCAST Co., Ltd.
 
-OUI:24A43C*
- ID_OUI_FROM_DATABASE=Ubiquiti Networks, INC
+OUI:CCE798*
+ ID_OUI_FROM_DATABASE=My Social Stuff
 
-OUI:D41E35*
- ID_OUI_FROM_DATABASE=TOHO Electronics INC.
+OUI:50724D*
+ ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH
 
-OUI:700BC0*
- ID_OUI_FROM_DATABASE=Dewav Technology Company
+OUI:B898B0*
+ ID_OUI_FROM_DATABASE=Atlona Inc.
 
-OUI:58C38B*
+OUI:1C66AA*
  ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:2CD444*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:2C625A*
+ ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd
 
-OUI:EC1A59*
- ID_OUI_FROM_DATABASE=Belkin International Inc.
+OUI:2074CF*
+ ID_OUI_FROM_DATABASE=Shenzhen Voxtech Co.,Ltd
+
+OUI:ACBD0B*
+ ID_OUI_FROM_DATABASE=IMAC CO.,LTD
+
+OUI:D8D27C*
+ ID_OUI_FROM_DATABASE=JEMA ENERGY, SA
 
 OUI:60CBFB*
  ID_OUI_FROM_DATABASE=AirScape Inc.
@@ -34340,107 +35456,116 @@ OUI:407074*
 OUI:58BFEA*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:7C386C*
- ID_OUI_FROM_DATABASE=Real Time Logic
+OUI:E856D6*
+ ID_OUI_FROM_DATABASE=NCTech Ltd
 
-OUI:D8AF3B*
- ID_OUI_FROM_DATABASE=Hangzhou Bigbright Integrated communications system Co.,Ltd
+OUI:4088E0*
+ ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch
 
-OUI:78D34F*
- ID_OUI_FROM_DATABASE=Pace-O-Matic, Inc.
+OUI:1CF4CA*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:D857EF*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:EC4C4D*
+ ID_OUI_FROM_DATABASE=ZAO NPK RoTeK
 
-OUI:784405*
- ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD.
+OUI:E8D483*
+ ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH
 
-OUI:C03F2A*
- ID_OUI_FROM_DATABASE=Biscotti, Inc.
+OUI:089E01*
+ ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
 
-OUI:5001BB*
+OUI:ACD9D6*
+ ID_OUI_FROM_DATABASE=tci GmbH
+
+OUI:7493A4*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Corp.
+
+OUI:58C38B*
  ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:F0FDA0*
- ID_OUI_FROM_DATABASE=Acurix Networks LP
+OUI:2CD444*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
 
-OUI:44B382*
- ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology
+OUI:EC1A59*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
 
-OUI:344B3D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:04F8C2*
+ ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc.
 
-OUI:D80DE3*
- ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS
+OUI:0C93FB*
+ ID_OUI_FROM_DATABASE=BNS Solutions
 
-OUI:1CE165*
- ID_OUI_FROM_DATABASE=Marshal Corporation
+OUI:E45614*
+ ID_OUI_FROM_DATABASE=Suttle Apparatus
 
-OUI:0CC0C0*
- ID_OUI_FROM_DATABASE=MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO
+OUI:784405*
+ ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD.
 
-OUI:AC40EA*
- ID_OUI_FROM_DATABASE=C&T Solution Inc.
+OUI:C03F2A*
+ ID_OUI_FROM_DATABASE=Biscotti, Inc.
 
-OUI:BC8B55*
- ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic
+OUI:5001BB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:D8EB97*
- ID_OUI_FROM_DATABASE=TRENDnet, Inc.
+OUI:A40BED*
+ ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd
 
-OUI:202598*
- ID_OUI_FROM_DATABASE=Teleview
+OUI:0CD996*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:844915*
- ID_OUI_FROM_DATABASE=vArmour Networks, Inc.
+OUI:D82DE1*
+ ID_OUI_FROM_DATABASE=Tricascade Inc.
 
-OUI:A04CC1*
- ID_OUI_FROM_DATABASE=Helixtech Corp.
+OUI:C438D3*
+ ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD
 
-OUI:1CB243*
- ID_OUI_FROM_DATABASE=TDC A/S
+OUI:842BBC*
+ ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH
 
-OUI:1C51B5*
- ID_OUI_FROM_DATABASE=Techaya LTD
+OUI:B8B7D7*
+ ID_OUI_FROM_DATABASE=2GIG Technologies
 
-OUI:80DB31*
- ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd.
+OUI:1048B1*
+ ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited
 
-OUI:AC0142*
- ID_OUI_FROM_DATABASE=Uriel Technologies SIA
+OUI:005D03*
+ ID_OUI_FROM_DATABASE=Xilinx, Inc
 
-OUI:A007B6*
- ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc.
+OUI:20FABB*
+ ID_OUI_FROM_DATABASE=Cambridge Executive Limited
 
-OUI:542A9C*
- ID_OUI_FROM_DATABASE=LSY Defense, LLC.
+OUI:1C0B52*
+ ID_OUI_FROM_DATABASE=EPICOM S.A
 
-OUI:D487D8*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:747E2D*
+ ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD.
 
-OUI:F89955*
- ID_OUI_FROM_DATABASE=Fortress Technology Inc
+OUI:E80C75*
+ ID_OUI_FROM_DATABASE=Syncbak, Inc.
 
-OUI:B827EB*
- ID_OUI_FROM_DATABASE=Raspberry Pi Foundation
+OUI:BC8B55*
+ ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic
 
-OUI:E88DF5*
- ID_OUI_FROM_DATABASE=ZNYX Networks, Inc.
+OUI:D8EB97*
+ ID_OUI_FROM_DATABASE=TRENDnet, Inc.
 
-OUI:48EA63*
- ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd.
+OUI:202598*
+ ID_OUI_FROM_DATABASE=Teleview
 
-OUI:0CE5D3*
- ID_OUI_FROM_DATABASE=DH electronics GmbH
+OUI:44B382*
+ ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology
 
-OUI:C47130*
- ID_OUI_FROM_DATABASE=Fon Technology S.L.
+OUI:D80DE3*
+ ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS
 
-OUI:90CF7D*
- ID_OUI_FROM_DATABASE=Qingdao Hisense Electric Co.,Ltd.
+OUI:1CE165*
+ ID_OUI_FROM_DATABASE=Marshal Corporation
 
-OUI:48D7FF*
- ID_OUI_FROM_DATABASE=BLANKOM Antennentechnik GmbH
+OUI:0CC0C0*
+ ID_OUI_FROM_DATABASE=MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO
+
+OUI:AC40EA*
+ ID_OUI_FROM_DATABASE=C&T Solution Inc.
 
 OUI:F47F35*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -34466,35 +35591,20 @@ OUI:5C0A5B*
 OUI:6CA96F*
  ID_OUI_FROM_DATABASE=TransPacket AS
 
-OUI:48ED80*
- ID_OUI_FROM_DATABASE=daesung eltec
-
-OUI:A086EC*
- ID_OUI_FROM_DATABASE=SAEHAN HITEC Co., Ltd
-
-OUI:BC4B79*
- ID_OUI_FROM_DATABASE=SensingTek
-
-OUI:2818FD*
- ID_OUI_FROM_DATABASE=Aditya Infotech Ltd.
-
-OUI:9003B7*
- ID_OUI_FROM_DATABASE=PARROT
-
-OUI:E42C56*
- ID_OUI_FROM_DATABASE=Lilee Systems, Ltd.
+OUI:AC0142*
+ ID_OUI_FROM_DATABASE=Uriel Technologies SIA
 
-OUI:50008C*
- ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited
+OUI:A007B6*
+ ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc.
 
-OUI:DCA8CF*
- ID_OUI_FROM_DATABASE=New Spin Golf, LLC.
+OUI:542A9C*
+ ID_OUI_FROM_DATABASE=LSY Defense, LLC.
 
-OUI:34BA9A*
- ID_OUI_FROM_DATABASE=Asiatelco Technologies Co.
+OUI:D487D8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:642DB7*
- ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS
+OUI:F89955*
+ ID_OUI_FROM_DATABASE=Fortress Technology Inc
 
 OUI:008DDA*
  ID_OUI_FROM_DATABASE=Link One Co., Ltd.
@@ -34520,53 +35630,29 @@ OUI:F48E09*
 OUI:882012*
  ID_OUI_FROM_DATABASE=LMI Technologies
 
-OUI:D443A8*
- ID_OUI_FROM_DATABASE=Changzhou Haojie Electric Co., Ltd.
-
-OUI:BCB852*
- ID_OUI_FROM_DATABASE=Cybera, Inc.
-
-OUI:70D6B6*
- ID_OUI_FROM_DATABASE=Metrum Technologies
-
-OUI:28D576*
- ID_OUI_FROM_DATABASE=Premier Wireless, Inc.
-
-OUI:6CE907*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
-OUI:94DF58*
- ID_OUI_FROM_DATABASE=IJ Electron CO.,Ltd.
-
-OUI:8C0CA3*
- ID_OUI_FROM_DATABASE=Amper
-
-OUI:28940F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:5CEB4E*
- ID_OUI_FROM_DATABASE=R. STAHL HMI Systems GmbH
+OUI:800A06*
+ ID_OUI_FROM_DATABASE=COMTEC co.,ltd
 
-OUI:B8DAF7*
- ID_OUI_FROM_DATABASE=Advanced Photonics, Inc.
+OUI:B827EB*
+ ID_OUI_FROM_DATABASE=Raspberry Pi Foundation
 
-OUI:2C36A0*
- ID_OUI_FROM_DATABASE=Capisco Limited
+OUI:E88DF5*
+ ID_OUI_FROM_DATABASE=ZNYX Networks, Inc.
 
-OUI:800A06*
- ID_OUI_FROM_DATABASE=COMTEC co.,ltd
+OUI:48EA63*
+ ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd.
 
-OUI:20FABB*
- ID_OUI_FROM_DATABASE=Cambridge Executive Limited
+OUI:0CE5D3*
+ ID_OUI_FROM_DATABASE=DH electronics GmbH
 
-OUI:1C0B52*
- ID_OUI_FROM_DATABASE=EPICOM S.A
+OUI:C47130*
+ ID_OUI_FROM_DATABASE=Fon Technology S.L.
 
-OUI:747E2D*
- ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD.
+OUI:90CF7D*
+ ID_OUI_FROM_DATABASE=Qingdao Hisense Electric Co.,Ltd.
 
-OUI:E80C75*
- ID_OUI_FROM_DATABASE=Syncbak, Inc.
+OUI:48D7FF*
+ ID_OUI_FROM_DATABASE=BLANKOM Antennentechnik GmbH
 
 OUI:18D66A*
  ID_OUI_FROM_DATABASE=Inmarsat
@@ -34574,26 +35660,29 @@ OUI:18D66A*
 OUI:C85645*
  ID_OUI_FROM_DATABASE=Intermas France
 
-OUI:8C604F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F490EA*
+ ID_OUI_FROM_DATABASE=Deciso B.V.
 
-OUI:74FF7D*
- ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC
+OUI:942197*
+ ID_OUI_FROM_DATABASE=Stalmart Technology Limited
 
-OUI:380A94*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:AC9403*
+ ID_OUI_FROM_DATABASE=Envision Peripherals Inc
 
-OUI:2CC260*
- ID_OUI_FROM_DATABASE=Ravello Systems
+OUI:A865B2*
+ ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED
 
-OUI:30B216*
- ID_OUI_FROM_DATABASE=Hytec Geraetebau GmbH
+OUI:60B982*
+ ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A.
 
-OUI:34FC6F*
- ID_OUI_FROM_DATABASE=ALCEA
+OUI:B46238*
+ ID_OUI_FROM_DATABASE=Exablox
 
-OUI:C0B357*
- ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd.
+OUI:40704A*
+ ID_OUI_FROM_DATABASE=Power Idea Technology Limited
+
+OUI:F0FDA0*
+ ID_OUI_FROM_DATABASE=Acurix Networks LP
 
 OUI:D8BF4C*
  ID_OUI_FROM_DATABASE=Victory Concept Electronics Limited
@@ -34613,149 +35702,182 @@ OUI:BC125E*
 OUI:C80718*
  ID_OUI_FROM_DATABASE=TDSi
 
-OUI:B4944E*
- ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd.
+OUI:48ED80*
+ ID_OUI_FROM_DATABASE=daesung eltec
 
-OUI:345B11*
- ID_OUI_FROM_DATABASE=EVI HEAT AB
+OUI:A086EC*
+ ID_OUI_FROM_DATABASE=SAEHAN HITEC Co., Ltd
 
-OUI:988BAD*
- ID_OUI_FROM_DATABASE=Corintech Ltd.
+OUI:BC4B79*
+ ID_OUI_FROM_DATABASE=SensingTek
 
-OUI:4050E0*
- ID_OUI_FROM_DATABASE=Milton Security Group LLC
+OUI:2818FD*
+ ID_OUI_FROM_DATABASE=Aditya Infotech Ltd.
 
-OUI:C87CBC*
- ID_OUI_FROM_DATABASE=Valink Co., Ltd.
+OUI:9003B7*
+ ID_OUI_FROM_DATABASE=PARROT
 
-OUI:409FC7*
- ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd.
+OUI:844915*
+ ID_OUI_FROM_DATABASE=vArmour Networks, Inc.
 
-OUI:D4E33F*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
+OUI:A04CC1*
+ ID_OUI_FROM_DATABASE=Helixtech Corp.
 
-OUI:C87D77*
- ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd
+OUI:1CB243*
+ ID_OUI_FROM_DATABASE=TDC A/S
 
-OUI:A078BA*
- ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
+OUI:1C51B5*
+ ID_OUI_FROM_DATABASE=Techaya LTD
 
-OUI:D4507A*
- ID_OUI_FROM_DATABASE=CEIVA Logic, Inc
+OUI:80DB31*
+ ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd.
 
-OUI:184617*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:8C604F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:9CC7D1*
- ID_OUI_FROM_DATABASE=SHARP Corporation
+OUI:74FF7D*
+ ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC
 
-OUI:AC9CE4*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+OUI:380A94*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:00B9F6*
- ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd
+OUI:2CC260*
+ ID_OUI_FROM_DATABASE=Ravello Systems
 
-OUI:9C5C8D*
- ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS  LTDA
+OUI:30B216*
+ ID_OUI_FROM_DATABASE=Hytec Geraetebau GmbH
 
-OUI:E01E07*
- ID_OUI_FROM_DATABASE=Anite Telecoms  US. Inc
+OUI:34FC6F*
+ ID_OUI_FROM_DATABASE=ALCEA
 
-OUI:B06CBF*
- ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH
+OUI:C0B357*
+ ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd.
 
-OUI:20AA4B*
- ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
+OUI:642DB7*
+ ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS
 
-OUI:080D84*
- ID_OUI_FROM_DATABASE=GECO, Inc.
+OUI:A898C6*
+ ID_OUI_FROM_DATABASE=Shinbo Co., Ltd.
 
-OUI:88E712*
- ID_OUI_FROM_DATABASE=Whirlpool Corporation
+OUI:006BA0*
+ ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD
 
-OUI:644BF0*
- ID_OUI_FROM_DATABASE=CalDigit, Inc
+OUI:502690*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
 
-OUI:2838CF*
- ID_OUI_FROM_DATABASE=Gen2wave
+OUI:B4211D*
+ ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd
 
-OUI:50FC30*
- ID_OUI_FROM_DATABASE=Treehouse Labs
+OUI:E039D7*
+ ID_OUI_FROM_DATABASE=Plexxi, Inc.
 
-OUI:70704C*
- ID_OUI_FROM_DATABASE=Purple Communications, Inc
+OUI:FC946C*
+ ID_OUI_FROM_DATABASE=UBIVELOX
 
-OUI:F47ACC*
- ID_OUI_FROM_DATABASE=SolidFire, Inc.
+OUI:B4944E*
+ ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd.
 
-OUI:24BC82*
- ID_OUI_FROM_DATABASE=Dali Wireless, Inc.
+OUI:345B11*
+ ID_OUI_FROM_DATABASE=EVI HEAT AB
 
-OUI:F80CF3*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:988BAD*
+ ID_OUI_FROM_DATABASE=Corintech Ltd.
 
-OUI:64C5AA*
- ID_OUI_FROM_DATABASE=South African Broadcasting Corporation
+OUI:4050E0*
+ ID_OUI_FROM_DATABASE=Milton Security Group LLC
 
-OUI:64ED62*
- ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd
+OUI:E42C56*
+ ID_OUI_FROM_DATABASE=Lilee Systems, Ltd.
 
-OUI:C4237A*
- ID_OUI_FROM_DATABASE=WhizNets Inc.
+OUI:50008C*
+ ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited
 
-OUI:8430E5*
- ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC
+OUI:DCA8CF*
+ ID_OUI_FROM_DATABASE=New Spin Golf, LLC.
 
-OUI:2C002C*
- ID_OUI_FROM_DATABASE=UNOWHY
+OUI:34BA9A*
+ ID_OUI_FROM_DATABASE=Asiatelco Technologies Co.
 
-OUI:0481AE*
- ID_OUI_FROM_DATABASE=Clack Corporation
+OUI:D443A8*
+ ID_OUI_FROM_DATABASE=Changzhou Haojie Electric Co., Ltd.
 
-OUI:C09132*
- ID_OUI_FROM_DATABASE=Patriot Memory
+OUI:BCB852*
+ ID_OUI_FROM_DATABASE=Cybera, Inc.
 
-OUI:A898C6*
- ID_OUI_FROM_DATABASE=Shinbo Co., Ltd.
+OUI:70D6B6*
+ ID_OUI_FROM_DATABASE=Metrum Technologies
 
-OUI:006BA0*
- ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD
+OUI:28D576*
+ ID_OUI_FROM_DATABASE=Premier Wireless, Inc.
 
-OUI:502690*
- ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:C87CBC*
+ ID_OUI_FROM_DATABASE=Valink Co., Ltd.
 
-OUI:B4211D*
- ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd
+OUI:409FC7*
+ ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd.
 
-OUI:E039D7*
- ID_OUI_FROM_DATABASE=Plexxi, Inc.
+OUI:C87D77*
+ ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd
 
-OUI:FC946C*
- ID_OUI_FROM_DATABASE=UBIVELOX
+OUI:A078BA*
+ ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
 
-OUI:38DE60*
- ID_OUI_FROM_DATABASE=Mohlenhoff GmbH
+OUI:20BBC6*
+ ID_OUI_FROM_DATABASE=Jabil Circuit Hungary Ltd.
 
-OUI:2839E7*
- ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd.
+OUI:2C9717*
+ ID_OUI_FROM_DATABASE=I.C.Y. B.V.
 
-OUI:28D997*
- ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd.
+OUI:64E84F*
+ ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd
 
-OUI:886B76*
- ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD
+OUI:6CE907*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:A0CF5B*
+OUI:94DF58*
+ ID_OUI_FROM_DATABASE=IJ Electron CO.,Ltd.
+
+OUI:8C0CA3*
+ ID_OUI_FROM_DATABASE=Amper
+
+OUI:28940F*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:18C451*
- ID_OUI_FROM_DATABASE=Tucson Embedded Systems
+OUI:5CEB4E*
+ ID_OUI_FROM_DATABASE=R. STAHL HMI Systems GmbH
 
-OUI:582EFE*
- ID_OUI_FROM_DATABASE=Lighting Science Group
+OUI:B8DAF7*
+ ID_OUI_FROM_DATABASE=Advanced Photonics, Inc.
 
-OUI:D826B9*
- ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S &T Co., Ltd.
+OUI:2C36A0*
+ ID_OUI_FROM_DATABASE=Capisco Limited
+
+OUI:B06CBF*
+ ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH
+
+OUI:20AA4B*
+ ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
+
+OUI:080D84*
+ ID_OUI_FROM_DATABASE=GECO, Inc.
+
+OUI:88E712*
+ ID_OUI_FROM_DATABASE=Whirlpool Corporation
+
+OUI:644BF0*
+ ID_OUI_FROM_DATABASE=CalDigit, Inc
+
+OUI:2838CF*
+ ID_OUI_FROM_DATABASE=Gen2wave
+
+OUI:50FC30*
+ ID_OUI_FROM_DATABASE=Treehouse Labs
+
+OUI:70704C*
+ ID_OUI_FROM_DATABASE=Purple Communications, Inc
+
+OUI:F47ACC*
+ ID_OUI_FROM_DATABASE=SolidFire, Inc.
 
 OUI:F8D3A9*
  ID_OUI_FROM_DATABASE=AXAN Networks
@@ -34775,15 +35897,6 @@ OUI:CCA374*
 OUI:50F61A*
  ID_OUI_FROM_DATABASE=Kunshan JADE Technologies co., Ltd.
 
-OUI:20BBC6*
- ID_OUI_FROM_DATABASE=Jabil Circuit Hungary Ltd.
-
-OUI:2C9717*
- ID_OUI_FROM_DATABASE=I.C.Y. B.V.
-
-OUI:64E84F*
- ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd
-
 OUI:941D1C*
  ID_OUI_FROM_DATABASE=TLab West Systems AB
 
@@ -34799,6 +35912,27 @@ OUI:7C6B52*
 OUI:48C1AC*
  ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
 
+OUI:D826B9*
+ ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S &T Co., Ltd.
+
+OUI:24BC82*
+ ID_OUI_FROM_DATABASE=Dali Wireless, Inc.
+
+OUI:F80CF3*
+ ID_OUI_FROM_DATABASE=LG Electronics
+
+OUI:64C5AA*
+ ID_OUI_FROM_DATABASE=South African Broadcasting Corporation
+
+OUI:64ED62*
+ ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd
+
+OUI:C4237A*
+ ID_OUI_FROM_DATABASE=WhizNets Inc.
+
+OUI:8430E5*
+ ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC
+
 OUI:046D42*
  ID_OUI_FROM_DATABASE=Bryston Ltd.
 
@@ -34814,14 +35948,14 @@ OUI:644D70*
 OUI:807693*
  ID_OUI_FROM_DATABASE=Newag SA
 
-OUI:FC1794*
- ID_OUI_FROM_DATABASE=InterCreative Co., Ltd
+OUI:2C002C*
+ ID_OUI_FROM_DATABASE=UNOWHY
 
-OUI:181420*
- ID_OUI_FROM_DATABASE=TEB SAS
+OUI:0481AE*
+ ID_OUI_FROM_DATABASE=Clack Corporation
 
-OUI:D03110*
- ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd
+OUI:C09132*
+ ID_OUI_FROM_DATABASE=Patriot Memory
 
 OUI:AC81F3*
  ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -34838,20 +35972,17 @@ OUI:80971B*
 OUI:1071F9*
  ID_OUI_FROM_DATABASE=Cloud Telecomputers, LLC
 
-OUI:C47B2F*
- ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd.
-
-OUI:18F650*
- ID_OUI_FROM_DATABASE=Multimedia Pacific Limited
+OUI:B8B42E*
+ ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen
 
-OUI:704AAE*
- ID_OUI_FROM_DATABASE=Xstream Flow (Pty) Ltd
+OUI:A84041*
+ ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited
 
-OUI:9C934E*
- ID_OUI_FROM_DATABASE=Xerox Corporation
+OUI:DCF05D*
+ ID_OUI_FROM_DATABASE=Letta Teknoloji
 
-OUI:3C26D5*
- ID_OUI_FROM_DATABASE=Sotera Wireless
+OUI:D05A0F*
+ ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD
 
 OUI:FC2E2D*
  ID_OUI_FROM_DATABASE=Lorom Industrial Co.LTD.
@@ -34865,56 +35996,53 @@ OUI:B4C799*
 OUI:70B921*
  ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
 
-OUI:948FEE*
- ID_OUI_FROM_DATABASE=Hughes Telematics, Inc.
-
-OUI:E8C320*
- ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
+OUI:C47B2F*
+ ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd.
 
-OUI:D8973B*
- ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
+OUI:18F650*
+ ID_OUI_FROM_DATABASE=Multimedia Pacific Limited
 
-OUI:008D4E*
- ID_OUI_FROM_DATABASE=CJSC NII STT
+OUI:38DE60*
+ ID_OUI_FROM_DATABASE=Mohlenhoff GmbH
 
-OUI:10C586*
- ID_OUI_FROM_DATABASE=BIO SOUND LAB CO., LTD.
+OUI:2839E7*
+ ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd.
 
-OUI:E8BA70*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:28D997*
+ ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd.
 
-OUI:6473E2*
- ID_OUI_FROM_DATABASE=Arbiter Systems, Inc.
+OUI:886B76*
+ ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD
 
-OUI:00A1DE*
- ID_OUI_FROM_DATABASE=ShenZhen ShiHua Technology CO.,LTD
+OUI:A0CF5B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:04E1C8*
- ID_OUI_FROM_DATABASE=IMS Soluções em Energia Ltda.
+OUI:18C451*
+ ID_OUI_FROM_DATABASE=Tucson Embedded Systems
 
-OUI:E4DD79*
- ID_OUI_FROM_DATABASE=En-Vision America, Inc.
+OUI:582EFE*
+ ID_OUI_FROM_DATABASE=Lighting Science Group
 
-OUI:60190C*
- ID_OUI_FROM_DATABASE=RRAMAC
+OUI:D4507A*
+ ID_OUI_FROM_DATABASE=CEIVA Logic, Inc
 
-OUI:34A709*
- ID_OUI_FROM_DATABASE=Trevil srl
+OUI:184617*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:F80332*
- ID_OUI_FROM_DATABASE=Khomp
+OUI:9CC7D1*
+ ID_OUI_FROM_DATABASE=SHARP Corporation
 
-OUI:C40F09*
- ID_OUI_FROM_DATABASE=Hermes electronic GmbH
+OUI:AC9CE4*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
 
-OUI:908D1D*
- ID_OUI_FROM_DATABASE=GH Technologies
+OUI:00B9F6*
+ ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd
 
-OUI:CCB55A*
- ID_OUI_FROM_DATABASE=Fraunhofer ITWM
+OUI:9C5C8D*
+ ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS  LTDA
 
-OUI:587521*
- ID_OUI_FROM_DATABASE=CJSC RTSoft
+OUI:E01E07*
+ ID_OUI_FROM_DATABASE=Anite Telecoms  US. Inc
 
 OUI:64D989*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -34928,6 +36056,9 @@ OUI:24DAB6*
 OUI:B8F5E7*
  ID_OUI_FROM_DATABASE=WayTools, LLC
 
+OUI:980C82*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
+
 OUI:148A70*
  ID_OUI_FROM_DATABASE=ADS GmbH
 
@@ -34943,20 +36074,26 @@ OUI:644346*
 OUI:FCE892*
  ID_OUI_FROM_DATABASE=Hangzhou Lancable Technology Co.,Ltd
 
-OUI:B8B42E*
- ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen
+OUI:FC1794*
+ ID_OUI_FROM_DATABASE=InterCreative Co., Ltd
 
-OUI:A84041*
- ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited
+OUI:181420*
+ ID_OUI_FROM_DATABASE=TEB SAS
 
-OUI:686E23*
- ID_OUI_FROM_DATABASE=Wi3 Inc.
+OUI:D03110*
+ ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd
 
-OUI:DCF05D*
- ID_OUI_FROM_DATABASE=Letta Teknoloji
+OUI:48C862*
+ ID_OUI_FROM_DATABASE=Simo Wireless,Inc.
 
-OUI:D05A0F*
- ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD
+OUI:3C26D5*
+ ID_OUI_FROM_DATABASE=Sotera Wireless
+
+OUI:704AAE*
+ ID_OUI_FROM_DATABASE=Xstream Flow (Pty) Ltd
+
+OUI:9C934E*
+ ID_OUI_FROM_DATABASE=Xerox Corporation
 
 OUI:9439E5*
  ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -34973,18 +36110,6 @@ OUI:9C7BD2*
 OUI:900D66*
  ID_OUI_FROM_DATABASE=Digimore Electronics Co., Ltd
 
-OUI:980C82*
- ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
-
-OUI:48C862*
- ID_OUI_FROM_DATABASE=Simo Wireless,Inc.
-
-OUI:0CF3EE*
- ID_OUI_FROM_DATABASE=EM Microelectronic
-
-OUI:F0C27C*
- ID_OUI_FROM_DATABASE=Mianyang Netop Telecom Equipment Co.,Ltd.
-
 OUI:BC35E5*
  ID_OUI_FROM_DATABASE=Hydro Systems Company
 
@@ -35003,6 +36128,18 @@ OUI:A433D1*
 OUI:84DE3D*
  ID_OUI_FROM_DATABASE=Crystal Vision Ltd
 
+OUI:F87B8C*
+ ID_OUI_FROM_DATABASE=Amped Wireless
+
+OUI:44D2CA*
+ ID_OUI_FROM_DATABASE=Anvia TV Oy
+
+OUI:4C1A3A*
+ ID_OUI_FROM_DATABASE=PRIMA Research And Production Enterprise Ltd.
+
+OUI:AC0613*
+ ID_OUI_FROM_DATABASE=Senselogix Ltd
+
 OUI:B4AA4D*
  ID_OUI_FROM_DATABASE=Ensequence, Inc.
 
@@ -35024,9 +36161,6 @@ OUI:3891FB*
 OUI:50FAAB*
  ID_OUI_FROM_DATABASE=L-tek d.o.o.
 
-OUI:547F54*
- ID_OUI_FROM_DATABASE=INGENICO
-
 OUI:A8E018*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
@@ -35048,53 +36182,44 @@ OUI:50E549*
 OUI:A8FCB7*
  ID_OUI_FROM_DATABASE=Consolidated Resource Imaging
 
-OUI:F87B8C*
- ID_OUI_FROM_DATABASE=Amped Wireless
-
-OUI:44D2CA*
- ID_OUI_FROM_DATABASE=Anvia TV Oy
-
-OUI:4C1A3A*
- ID_OUI_FROM_DATABASE=PRIMA Research And Production Enterprise Ltd.
-
-OUI:AC0613*
- ID_OUI_FROM_DATABASE=Senselogix Ltd
+OUI:6400F1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:CCF67A*
- ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
+OUI:04C5A4*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:200A5E*
- ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing co.,LTD
+OUI:E4DD79*
+ ID_OUI_FROM_DATABASE=En-Vision America, Inc.
 
-OUI:747818*
- ID_OUI_FROM_DATABASE=ServiceAssure
+OUI:60190C*
+ ID_OUI_FROM_DATABASE=RRAMAC
 
-OUI:00BB8E*
- ID_OUI_FROM_DATABASE=HME Co., Ltd.
+OUI:34A709*
+ ID_OUI_FROM_DATABASE=Trevil srl
 
-OUI:C0A26D*
- ID_OUI_FROM_DATABASE=Abbott Point of Care
+OUI:F80332*
+ ID_OUI_FROM_DATABASE=Khomp
 
-OUI:205B2A*
- ID_OUI_FROM_DATABASE=Private
+OUI:C40F09*
+ ID_OUI_FROM_DATABASE=Hermes electronic GmbH
 
-OUI:18B430*
- ID_OUI_FROM_DATABASE=Nest Labs Inc.
+OUI:908D1D*
+ ID_OUI_FROM_DATABASE=GH Technologies
 
-OUI:F8769B*
- ID_OUI_FROM_DATABASE=Neopis Co., Ltd.
+OUI:CCB55A*
+ ID_OUI_FROM_DATABASE=Fraunhofer ITWM
 
-OUI:08E672*
- ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD.
+OUI:587521*
+ ID_OUI_FROM_DATABASE=CJSC RTSoft
 
-OUI:C89CDC*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
+OUI:948FEE*
+ ID_OUI_FROM_DATABASE=Hughes Telematics, Inc.
 
-OUI:58E476*
- ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD
+OUI:E8C320*
+ ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
 
-OUI:B435F7*
- ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd.
+OUI:D8973B*
+ ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
 
 OUI:0C6E4F*
  ID_OUI_FROM_DATABASE=PrimeVOLT Co., Ltd.
@@ -35114,6 +36239,33 @@ OUI:CC5D4E*
 OUI:D0EB9E*
  ID_OUI_FROM_DATABASE=Seowoo Inc.
 
+OUI:BC99BC*
+ ID_OUI_FROM_DATABASE=FonSee Technology Inc.
+
+OUI:986022*
+ ID_OUI_FROM_DATABASE=EMW Co., Ltd.
+
+OUI:80B32A*
+ ID_OUI_FROM_DATABASE=Alstom Grid
+
+OUI:803457*
+ ID_OUI_FROM_DATABASE=OT Systems Limited
+
+OUI:B83D4E*
+ ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch
+
+OUI:3CA72B*
+ ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
+
+OUI:EC55F9*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:F4D9FB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
+
+OUI:584C19*
+ ID_OUI_FROM_DATABASE=Chongqing Guohong Technology Development Company Limited
+
 OUI:8C5FDF*
  ID_OUI_FROM_DATABASE=Beijing Railway Signal Factory
 
@@ -35150,6 +36302,30 @@ OUI:7C6C39*
 OUI:9C5D95*
  ID_OUI_FROM_DATABASE=VTC Electronics Corp.
 
+OUI:0CF3EE*
+ ID_OUI_FROM_DATABASE=EM Microelectronic
+
+OUI:F0C27C*
+ ID_OUI_FROM_DATABASE=Mianyang Netop Telecom Equipment Co.,Ltd.
+
+OUI:008D4E*
+ ID_OUI_FROM_DATABASE=CJSC NII STT
+
+OUI:10C586*
+ ID_OUI_FROM_DATABASE=BIO SOUND LAB CO., LTD.
+
+OUI:E8BA70*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:6473E2*
+ ID_OUI_FROM_DATABASE=Arbiter Systems, Inc.
+
+OUI:00A1DE*
+ ID_OUI_FROM_DATABASE=ShenZhen ShiHua Technology CO.,LTD
+
+OUI:04E1C8*
+ ID_OUI_FROM_DATABASE=IMS Soluções em Energia Ltda.
+
 OUI:DC05ED*
  ID_OUI_FROM_DATABASE=Nabtesco  Corporation
 
@@ -35162,71 +36338,71 @@ OUI:94E848*
 OUI:AC5E8C*
  ID_OUI_FROM_DATABASE=Utillink
 
+OUI:CCF3A5*
+ ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc
+
+OUI:C4242E*
+ ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc
+
 OUI:549B12*
  ID_OUI_FROM_DATABASE=Samsung Electronics
 
 OUI:CC7EE7*
  ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
 
-OUI:BC99BC*
- ID_OUI_FROM_DATABASE=FonSee Technology Inc.
+OUI:58E476*
+ ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD
 
-OUI:986022*
- ID_OUI_FROM_DATABASE=EMW Co., Ltd.
+OUI:B435F7*
+ ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd.
 
-OUI:80B32A*
- ID_OUI_FROM_DATABASE=Alstom Grid
+OUI:346F92*
+ ID_OUI_FROM_DATABASE=White Rodgers Division
 
-OUI:803457*
- ID_OUI_FROM_DATABASE=OT Systems Limited
+OUI:8CDB25*
+ ID_OUI_FROM_DATABASE=ESG Solutions
 
-OUI:B83D4E*
- ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch
+OUI:641A22*
+ ID_OUI_FROM_DATABASE=Heliospectra AB
 
-OUI:CCF3A5*
- ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc
+OUI:BC20BA*
+ ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd
 
-OUI:143E60*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
+OUI:249442*
+ ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
 
-OUI:C4242E*
- ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc
-
-OUI:6400F1*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:04C5A4*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:E0F379*
+ ID_OUI_FROM_DATABASE=Vaddio
 
-OUI:3CA72B*
- ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
+OUI:B09AE2*
+ ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH
 
-OUI:EC55F9*
- ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:E441E6*
+ ID_OUI_FROM_DATABASE=Ottec Technology GmbH
 
-OUI:F4D9FB*
- ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
+OUI:10E2D5*
+ ID_OUI_FROM_DATABASE=Qi Hardware Inc.
 
-OUI:584C19*
- ID_OUI_FROM_DATABASE=Chongqing Guohong Technology Development Company Limited
+OUI:7CDA84*
+ ID_OUI_FROM_DATABASE=Dongnian Networks Inc.
 
-OUI:D0A311*
- ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH
+OUI:A036FA*
+ ID_OUI_FROM_DATABASE=Ettus Research LLC
 
-OUI:3C5A37*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:EC836C*
+ ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
 
-OUI:10A13B*
- ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
+OUI:BC71C1*
+ ID_OUI_FROM_DATABASE=XTrillion, Inc.
 
-OUI:F4E142*
- ID_OUI_FROM_DATABASE=Delta Elektronika BV
+OUI:0C469D*
+ ID_OUI_FROM_DATABASE=MS Sedco
 
-OUI:F00248*
- ID_OUI_FROM_DATABASE=SmarteBuilding
+OUI:E0E8E8*
+ ID_OUI_FROM_DATABASE=Olive Telecommunication Pvt. Ltd
 
-OUI:2CDD0C*
- ID_OUI_FROM_DATABASE=Discovergy GmbH
+OUI:0C3C65*
+ ID_OUI_FROM_DATABASE=Dome Imaging Inc
 
 OUI:40B2C8*
  ID_OUI_FROM_DATABASE=Nortel Networks
@@ -35252,68 +36428,26 @@ OUI:088DC8*
 OUI:D491AF*
  ID_OUI_FROM_DATABASE=Electroacustica General Iberica, S.A.
 
-OUI:1CDF0F*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:34DF2A*
- ID_OUI_FROM_DATABASE=Fujikon Industrial Co.,Limited
-
-OUI:C88447*
- ID_OUI_FROM_DATABASE=Beautiful Enterprise Co., Ltd
-
-OUI:C88B47*
- ID_OUI_FROM_DATABASE=Nolangroup S.P.A con Socio Unico
-
-OUI:24BA30*
- ID_OUI_FROM_DATABASE=Technical Consumer Products, Inc.
-
-OUI:74D675*
- ID_OUI_FROM_DATABASE=WYMA Tecnologia
-
-OUI:D01CBB*
- ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd.
-
-OUI:9481A4*
- ID_OUI_FROM_DATABASE=Azuray Technologies
-
-OUI:BCE09D*
- ID_OUI_FROM_DATABASE=Eoslink
-
-OUI:346F92*
- ID_OUI_FROM_DATABASE=White Rodgers Division
-
-OUI:8CDB25*
- ID_OUI_FROM_DATABASE=ESG Solutions
-
-OUI:641A22*
- ID_OUI_FROM_DATABASE=Heliospectra AB
-
-OUI:30142D*
- ID_OUI_FROM_DATABASE=Piciorgros GmbH
-
-OUI:E441E6*
- ID_OUI_FROM_DATABASE=Ottec Technology GmbH
-
-OUI:10E2D5*
- ID_OUI_FROM_DATABASE=Qi Hardware Inc.
+OUI:CCF67A*
+ ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
 
-OUI:7CDA84*
- ID_OUI_FROM_DATABASE=Dongnian Networks Inc.
+OUI:00BB8E*
+ ID_OUI_FROM_DATABASE=HME Co., Ltd.
 
-OUI:A036FA*
- ID_OUI_FROM_DATABASE=Ettus Research LLC
+OUI:C0A26D*
+ ID_OUI_FROM_DATABASE=Abbott Point of Care
 
-OUI:EC836C*
- ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
+OUI:205B2A*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:C0C520*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:18B430*
+ ID_OUI_FROM_DATABASE=Nest Labs Inc.
 
-OUI:6083B2*
- ID_OUI_FROM_DATABASE=GkWare e.K.
+OUI:F8769B*
+ ID_OUI_FROM_DATABASE=Neopis Co., Ltd.
 
-OUI:80D019*
- ID_OUI_FROM_DATABASE=Embed, Inc
+OUI:08E672*
+ ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD.
 
 OUI:D41296*
  ID_OUI_FROM_DATABASE=Anobit Technologies Ltd.
@@ -35333,17 +36467,17 @@ OUI:649B24*
 OUI:0475F5*
  ID_OUI_FROM_DATABASE=CSST
 
-OUI:BC20BA*
- ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd
+OUI:10A13B*
+ ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
 
-OUI:249442*
- ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
+OUI:F4E142*
+ ID_OUI_FROM_DATABASE=Delta Elektronika BV
 
-OUI:E0F379*
- ID_OUI_FROM_DATABASE=Vaddio
+OUI:F00248*
+ ID_OUI_FROM_DATABASE=SmarteBuilding
 
-OUI:B09AE2*
- ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH
+OUI:2CDD0C*
+ ID_OUI_FROM_DATABASE=Discovergy GmbH
 
 OUI:CCD811*
  ID_OUI_FROM_DATABASE=Aiconn Technology Corporation
@@ -35363,8 +36497,14 @@ OUI:44599F*
 OUI:3C2F3A*
  ID_OUI_FROM_DATABASE=SFORZATO Corp.
 
-OUI:EC9233*
- ID_OUI_FROM_DATABASE=Eddyfi NDT Inc
+OUI:C0C520*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:6083B2*
+ ID_OUI_FROM_DATABASE=GkWare e.K.
+
+OUI:80D019*
+ ID_OUI_FROM_DATABASE=Embed, Inc
 
 OUI:ECE90B*
  ID_OUI_FROM_DATABASE=SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH
@@ -35393,17 +36533,8 @@ OUI:6C33A9*
 OUI:08B7EC*
  ID_OUI_FROM_DATABASE=Wireless Seismic
 
-OUI:BC71C1*
- ID_OUI_FROM_DATABASE=XTrillion, Inc.
-
-OUI:0C469D*
- ID_OUI_FROM_DATABASE=MS Sedco
-
-OUI:E0E8E8*
- ID_OUI_FROM_DATABASE=Olive Telecommunication Pvt. Ltd
-
-OUI:0C3C65*
- ID_OUI_FROM_DATABASE=Dome Imaging Inc
+OUI:30142D*
+ ID_OUI_FROM_DATABASE=Piciorgros GmbH
 
 OUI:942053*
  ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -35420,32 +36551,23 @@ OUI:2CB0DF*
 OUI:5CF3FC*
  ID_OUI_FROM_DATABASE=IBM Corp
 
-OUI:D43D67*
- ID_OUI_FROM_DATABASE=Carma Industries Inc.
-
-OUI:00BD27*
- ID_OUI_FROM_DATABASE=Exar Corp.
+OUI:D01CBB*
+ ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd.
 
-OUI:C8A729*
- ID_OUI_FROM_DATABASE=SYStronics Co., Ltd.
+OUI:9481A4*
+ ID_OUI_FROM_DATABASE=Azuray Technologies
 
-OUI:6C9CE9*
- ID_OUI_FROM_DATABASE=Nimble Storage
+OUI:BCE09D*
+ ID_OUI_FROM_DATABASE=Eoslink
 
-OUI:700258*
- ID_OUI_FROM_DATABASE=01DB-METRAVIB
+OUI:D0A311*
+ ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH
 
-OUI:D4E8B2*
+OUI:3C5A37*
  ID_OUI_FROM_DATABASE=Samsung Electronics
 
-OUI:20FDF1*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD
-
-OUI:389592*
- ID_OUI_FROM_DATABASE=Beijing Tendyron Corporation
-
-OUI:705EAA*
- ID_OUI_FROM_DATABASE=Action Target, Inc.
+OUI:EC9233*
+ ID_OUI_FROM_DATABASE=Eddyfi NDT Inc
 
 OUI:0C8D98*
  ID_OUI_FROM_DATABASE=TOP EIGHT IND CORP
@@ -35453,17 +36575,11 @@ OUI:0C8D98*
 OUI:30493B*
  ID_OUI_FROM_DATABASE=Nanjing Z-Com Wireless Co.,Ltd
 
-OUI:68DB96*
- ID_OUI_FROM_DATABASE=OPWILL Technologies CO .,LTD
-
-OUI:00F860*
- ID_OUI_FROM_DATABASE=PT. Panggung Electric Citrabuana
-
-OUI:FCEDB9*
- ID_OUI_FROM_DATABASE=Arrayent
+OUI:785712*
+ ID_OUI_FROM_DATABASE=Mobile Integration Workgroup
 
-OUI:44ED57*
- ID_OUI_FROM_DATABASE=Longicorn, inc.
+OUI:380A0A*
+ ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company
 
 OUI:38521A*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent 7705
@@ -35477,11 +36593,20 @@ OUI:641E81*
 OUI:88ACC1*
  ID_OUI_FROM_DATABASE=Generiton Co., Ltd.
 
-OUI:785712*
- ID_OUI_FROM_DATABASE=Mobile Integration Workgroup
+OUI:700258*
+ ID_OUI_FROM_DATABASE=01DB-METRAVIB
 
-OUI:380A0A*
- ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company
+OUI:D4E8B2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
+
+OUI:20FDF1*
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
+
+OUI:389592*
+ ID_OUI_FROM_DATABASE=Beijing Tendyron Corporation
+
+OUI:705EAA*
+ ID_OUI_FROM_DATABASE=Action Target, Inc.
 
 OUI:141BBD*
  ID_OUI_FROM_DATABASE=Volex Inc.
@@ -35513,47 +36638,65 @@ OUI:988EDD*
 OUI:98FC11*
  ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
 
-OUI:180C77*
- ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC
-
-OUI:ACA016*
+OUI:A40CC3*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:78E400*
+OUI:34E0D7*
+ ID_OUI_FROM_DATABASE=DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD
+
+OUI:40520D*
+ ID_OUI_FROM_DATABASE=Pico Technology
+
+OUI:8C7CB5*
  ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
 
-OUI:E4AD7D*
- ID_OUI_FROM_DATABASE=SCL Elements
+OUI:543131*
+ ID_OUI_FROM_DATABASE=Raster Vision Ltd
 
-OUI:40D40E*
- ID_OUI_FROM_DATABASE=Biodata Ltd
+OUI:90E0F0*
+ ID_OUI_FROM_DATABASE=IEEE 1722a Working Group
 
-OUI:7C051E*
- ID_OUI_FROM_DATABASE=RAFAEL LTD.
+OUI:1C6F65*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
 
-OUI:58570D*
- ID_OUI_FROM_DATABASE=Danfoss Solar Inverters
+OUI:F0AD4E*
+ ID_OUI_FROM_DATABASE=Globalscale Technologies, Inc.
 
-OUI:E47CF9*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD
+OUI:903D5A*
+ ID_OUI_FROM_DATABASE=Shenzhen Wision Technology Holding Limited
 
-OUI:0C826A*
- ID_OUI_FROM_DATABASE=Wuhan Huagong Genuine Optics Technology Co., Ltd
+OUI:609AA4*
+ ID_OUI_FROM_DATABASE=GVI SECURITY INC.
 
-OUI:5C0E8B*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:F0ED1E*
+ ID_OUI_FROM_DATABASE=Bilkon Bilgisayar Kontrollu Cih. Im.Ltd.
 
-OUI:38C7BA*
- ID_OUI_FROM_DATABASE=CS Services Co.,Ltd.
+OUI:206A8A*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd.
 
-OUI:70D57E*
- ID_OUI_FROM_DATABASE=Scalar Corporation
+OUI:F80F41*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan) Corporation
 
-OUI:7866AE*
- ID_OUI_FROM_DATABASE=ZTEC Instruments, Inc.
+OUI:1CDF0F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:24AF4A*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD
+OUI:34DF2A*
+ ID_OUI_FROM_DATABASE=Fujikon Industrial Co.,Limited
+
+OUI:C88447*
+ ID_OUI_FROM_DATABASE=Beautiful Enterprise Co., Ltd
+
+OUI:C88B47*
+ ID_OUI_FROM_DATABASE=Nolangroup S.P.A con Socio Unico
+
+OUI:24BA30*
+ ID_OUI_FROM_DATABASE=Technical Consumer Products, Inc.
+
+OUI:74D675*
+ ID_OUI_FROM_DATABASE=WYMA Tecnologia
+
+OUI:D43D67*
+ ID_OUI_FROM_DATABASE=Carma Industries Inc.
 
 OUI:78818F*
  ID_OUI_FROM_DATABASE=Server Racks Australia Pty Ltd
@@ -35579,75 +36722,15 @@ OUI:68E41F*
 OUI:84F64C*
  ID_OUI_FROM_DATABASE=Cross Point BV
 
-OUI:206A8A*
- ID_OUI_FROM_DATABASE=Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd.
-
-OUI:F80F41*
- ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan) Corporation
-
-OUI:90513F*
- ID_OUI_FROM_DATABASE=Elettronica Santerno SpA
-
-OUI:7CA29B*
- ID_OUI_FROM_DATABASE=D.SignT GmbH & Co. KG
-
-OUI:34AAEE*
- ID_OUI_FROM_DATABASE=Mikrovisatos Servisas UAB
+OUI:180C77*
+ ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC
 
-OUI:A40CC3*
+OUI:ACA016*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:34E0D7*
- ID_OUI_FROM_DATABASE=DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD
-
-OUI:40520D*
- ID_OUI_FROM_DATABASE=Pico Technology
-
-OUI:8C7CB5*
+OUI:78E400*
  ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
 
-OUI:543131*
- ID_OUI_FROM_DATABASE=Raster Vision Ltd
-
-OUI:90E0F0*
- ID_OUI_FROM_DATABASE=IEEE 1722a Working Group
-
-OUI:1C6F65*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
-
-OUI:F0AD4E*
- ID_OUI_FROM_DATABASE=Globalscale Technologies, Inc.
-
-OUI:903D5A*
- ID_OUI_FROM_DATABASE=Shenzhen Wision Technology Holding Limited
-
-OUI:609AA4*
- ID_OUI_FROM_DATABASE=GVI SECURITY INC.
-
-OUI:F0ED1E*
- ID_OUI_FROM_DATABASE=Bilkon Bilgisayar Kontrollu Cih. Im.Ltd.
-
-OUI:24A937*
- ID_OUI_FROM_DATABASE=PURE Storage
-
-OUI:348302*
- ID_OUI_FROM_DATABASE=iFORCOM Co., Ltd
-
-OUI:949C55*
- ID_OUI_FROM_DATABASE=Alta Data Technologies
-
-OUI:389F83*
- ID_OUI_FROM_DATABASE=OTN Systems N.V.
-
-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.
-
 OUI:905446*
  ID_OUI_FROM_DATABASE=TES ELECTRONIC SOLUTIONS
 
@@ -35666,11 +36749,41 @@ OUI:A4BE61*
 OUI:E06290*
  ID_OUI_FROM_DATABASE=Jinan Jovision Science & Technology Co., Ltd.
 
-OUI:A01859*
- ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd
+OUI:68DB96*
+ ID_OUI_FROM_DATABASE=OPWILL Technologies CO .,LTD
 
-OUI:042234*
- ID_OUI_FROM_DATABASE=Wireless Standard Extensions
+OUI:00F860*
+ ID_OUI_FROM_DATABASE=PT. Panggung Electric Citrabuana
+
+OUI:FCEDB9*
+ ID_OUI_FROM_DATABASE=Arrayent
+
+OUI:44ED57*
+ ID_OUI_FROM_DATABASE=Longicorn, inc.
+
+OUI:90513F*
+ ID_OUI_FROM_DATABASE=Elettronica Santerno SpA
+
+OUI:7CA29B*
+ ID_OUI_FROM_DATABASE=D.SignT GmbH & Co. KG
+
+OUI:34AAEE*
+ ID_OUI_FROM_DATABASE=Mikrovisatos Servisas UAB
+
+OUI:7866AE*
+ ID_OUI_FROM_DATABASE=ZTEC Instruments, Inc.
+
+OUI:24AF4A*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD
+
+OUI:00BD27*
+ ID_OUI_FROM_DATABASE=Exar Corp.
+
+OUI:C8A729*
+ ID_OUI_FROM_DATABASE=SYStronics Co., Ltd.
+
+OUI:6C9CE9*
+ ID_OUI_FROM_DATABASE=Nimble Storage
 
 OUI:7812B8*
  ID_OUI_FROM_DATABASE=ORANTEK LIMITED
@@ -35702,6 +36815,72 @@ OUI:CC69B0*
 OUI:2872C5*
  ID_OUI_FROM_DATABASE=Smartmatic Corp
 
+OUI:E4AD7D*
+ ID_OUI_FROM_DATABASE=SCL Elements
+
+OUI:40D40E*
+ ID_OUI_FROM_DATABASE=Biodata Ltd
+
+OUI:7C051E*
+ ID_OUI_FROM_DATABASE=RAFAEL LTD.
+
+OUI:58570D*
+ ID_OUI_FROM_DATABASE=Danfoss Solar Inverters
+
+OUI:E47CF9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD
+
+OUI:0C826A*
+ ID_OUI_FROM_DATABASE=Wuhan Huagong Genuine Optics Technology Co., Ltd
+
+OUI:5C0E8B*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+
+OUI:38C7BA*
+ ID_OUI_FROM_DATABASE=CS Services Co.,Ltd.
+
+OUI:70D57E*
+ ID_OUI_FROM_DATABASE=Scalar Corporation
+
+OUI:24A937*
+ ID_OUI_FROM_DATABASE=PURE Storage
+
+OUI:348302*
+ ID_OUI_FROM_DATABASE=iFORCOM Co., Ltd
+
+OUI:949C55*
+ ID_OUI_FROM_DATABASE=Alta Data Technologies
+
+OUI:70D5E7*
+ ID_OUI_FROM_DATABASE=Wellcore Corporation
+
+OUI:3CF72A*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:FCE192*
+ ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd
+
+OUI:F8912A*
+ ID_OUI_FROM_DATABASE=GLP German Light Products GmbH
+
+OUI:E02630*
+ ID_OUI_FROM_DATABASE=Intrigue Technologies, Inc.
+
+OUI:8C9236*
+ ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd.
+
+OUI:F445ED*
+ ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd.
+
+OUI:6C32DE*
+ ID_OUI_FROM_DATABASE=Indieon Technologies Pvt. Ltd.
+
+OUI:FCCF62*
+ ID_OUI_FROM_DATABASE=IBM Corp
+
+OUI:D8E72B*
+ ID_OUI_FROM_DATABASE=NetScout Systems, Inc.
+
 OUI:B8A3E0*
  ID_OUI_FROM_DATABASE=BenRui Technology Co.,Ltd
 
@@ -35729,17 +36908,23 @@ OUI:506313*
 OUI:A8995C*
  ID_OUI_FROM_DATABASE=aizo ag
 
-OUI:F445ED*
- ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd.
+OUI:4012E4*
+ ID_OUI_FROM_DATABASE=Compass-EOS
 
-OUI:6C32DE*
- ID_OUI_FROM_DATABASE=Indieon Technologies Pvt. Ltd.
+OUI:F8DC7A*
+ ID_OUI_FROM_DATABASE=Variscite LTD
 
-OUI:FCCF62*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:EC4476*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:D8E72B*
- ID_OUI_FROM_DATABASE=NetScout Systems, Inc.
+OUI:9CEBE8*
+ ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd
+
+OUI:A01859*
+ ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd
+
+OUI:042234*
+ ID_OUI_FROM_DATABASE=Wireless Standard Extensions
 
 OUI:B09074*
  ID_OUI_FROM_DATABASE=Fulan Electronics Limited
@@ -35759,35 +36944,29 @@ OUI:8C736E*
 OUI:30EFD1*
  ID_OUI_FROM_DATABASE=Alstom Strongwish (Shenzhen) Co., Ltd.
 
-OUI:C835B8*
- ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K
+OUI:7C2CF3*
+ ID_OUI_FROM_DATABASE=Secure Electrans Ltd
 
-OUI:243C20*
- ID_OUI_FROM_DATABASE=Dynamode Group
+OUI:304174*
+ ID_OUI_FROM_DATABASE=ALTEC LANSING LLC
 
-OUI:70D5E7*
- ID_OUI_FROM_DATABASE=Wellcore Corporation
+OUI:7830E1*
+ ID_OUI_FROM_DATABASE=UltraClenz, LLC
 
-OUI:3CF72A*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:FCFBFB*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:FCE192*
- ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd
+OUI:1C129D*
+ ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB
 
-OUI:F8912A*
- ID_OUI_FROM_DATABASE=GLP German Light Products GmbH
+OUI:B40832*
+ ID_OUI_FROM_DATABASE=TC Communications
 
-OUI:E02630*
- ID_OUI_FROM_DATABASE=Intrigue Technologies, Inc.
-
-OUI:8C9236*
- ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd.
-
-OUI:4012E4*
- ID_OUI_FROM_DATABASE=Compass-EOS
+OUI:B42CBE*
+ ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited
 
-OUI:F8DC7A*
- ID_OUI_FROM_DATABASE=Variscite LTD
+OUI:F47626*
+ ID_OUI_FROM_DATABASE=Viltechmeda UAB
 
 OUI:003A9C*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -35807,17 +36986,50 @@ OUI:0494A1*
 OUI:2C3427*
  ID_OUI_FROM_DATABASE=ERCO & GENER
 
-OUI:B42CBE*
- ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited
+OUI:389F83*
+ ID_OUI_FROM_DATABASE=OTN Systems N.V.
 
-OUI:F47626*
- ID_OUI_FROM_DATABASE=Viltechmeda UAB
+OUI:8C541D*
+ ID_OUI_FROM_DATABASE=LGE
 
-OUI:EC4476*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:601283*
+ ID_OUI_FROM_DATABASE=Soluciones Tecnologicas para la Salud y el Bienestar SA
 
-OUI:9CEBE8*
- ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd
+OUI:003A9D*
+ ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
+
+OUI:C835B8*
+ ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K
+
+OUI:243C20*
+ ID_OUI_FROM_DATABASE=Dynamode Group
+
+OUI:E09153*
+ ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+
+OUI:CC0080*
+ ID_OUI_FROM_DATABASE=BETTINI SRL
+
+OUI:644BC3*
+ ID_OUI_FROM_DATABASE=Shanghai WOASiS Telecommunications Ltd., Co.
+
+OUI:0CE709*
+ ID_OUI_FROM_DATABASE=Fox Crypto B.V.
+
+OUI:002720*
+ ID_OUI_FROM_DATABASE=NEW-SOL COM
+
+OUI:00271C*
+ ID_OUI_FROM_DATABASE=MERCURY CORPORATION
+
+OUI:002712*
+ ID_OUI_FROM_DATABASE=MaxVision LLC
+
+OUI:00270F*
+ ID_OUI_FROM_DATABASE=Envisionnovation Inc
+
+OUI:002703*
+ ID_OUI_FROM_DATABASE=Testech Electronics Pte Ltd
 
 OUI:88ED1C*
  ID_OUI_FROM_DATABASE=Cudo Communication Co., Ltd.
@@ -35846,47 +37058,68 @@ OUI:C87E75*
 OUI:889821*
  ID_OUI_FROM_DATABASE=TERAON
 
-OUI:CC5076*
- ID_OUI_FROM_DATABASE=Ocom Communications, Inc.
+OUI:0026FD*
+ ID_OUI_FROM_DATABASE=Interactive Intelligence
 
-OUI:705812*
- ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
+OUI:0026F6*
+ ID_OUI_FROM_DATABASE=Military Communication Institute
 
-OUI:7C2CF3*
- ID_OUI_FROM_DATABASE=Secure Electrans Ltd
+OUI:0026F0*
+ ID_OUI_FROM_DATABASE=cTrixs International GmbH.
 
-OUI:304174*
- ID_OUI_FROM_DATABASE=ALTEC LANSING LLC
+OUI:0026EA*
+ ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd.
 
-OUI:7830E1*
- ID_OUI_FROM_DATABASE=UltraClenz, LLC
+OUI:0026E3*
+ ID_OUI_FROM_DATABASE=DTI
 
-OUI:FCFBFB*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0026DD*
+ ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd.
 
-OUI:1C129D*
- ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB
+OUI:0026DE*
+ ID_OUI_FROM_DATABASE=FDI MATELEC
 
-OUI:B40832*
- ID_OUI_FROM_DATABASE=TC Communications
+OUI:0026D7*
+ ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd.
 
-OUI:002720*
- ID_OUI_FROM_DATABASE=NEW-SOL COM
+OUI:0026D1*
+ ID_OUI_FROM_DATABASE=S Squared Innovations Inc.
 
-OUI:00271C*
- ID_OUI_FROM_DATABASE=MERCURY CORPORATION
+OUI:54B620*
+ ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd.
 
-OUI:002712*
- ID_OUI_FROM_DATABASE=MaxVision LLC
+OUI:C4AAA1*
+ ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o.
 
-OUI:00270F*
- ID_OUI_FROM_DATABASE=Envisionnovation Inc
+OUI:78C40E*
+ ID_OUI_FROM_DATABASE=H&D Wireless
 
-OUI:0026D7*
- ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd.
+OUI:9C5B96*
+ ID_OUI_FROM_DATABASE=NMR Corporation
 
-OUI:0026D1*
- ID_OUI_FROM_DATABASE=S Squared Innovations Inc.
+OUI:E4FFDD*
+ ID_OUI_FROM_DATABASE=ELECTRON INDIA
+
+OUI:6C8CDB*
+ ID_OUI_FROM_DATABASE=Otus Technologies Ltd
+
+OUI:B4417A*
+ ID_OUI_FROM_DATABASE=ShenZhen Gongjin Electronics Co.,Ltd
+
+OUI:401597*
+ ID_OUI_FROM_DATABASE=Protect America, Inc.
+
+OUI:F852DF*
+ ID_OUI_FROM_DATABASE=VNL Europe AB
+
+OUI:1CF061*
+ ID_OUI_FROM_DATABASE=SCAPS GmbH
+
+OUI:A893E6*
+ ID_OUI_FROM_DATABASE=JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD
+
+OUI:7825AD*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD.
 
 OUI:0026CB*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -35912,30 +37145,6 @@ OUI:0026A8*
 OUI:0026A7*
  ID_OUI_FROM_DATABASE=CONNECT SRL
 
-OUI:0026A1*
- ID_OUI_FROM_DATABASE=Megger
-
-OUI:0026A2*
- ID_OUI_FROM_DATABASE=Instrumentation Technology Systems
-
-OUI:00269B*
- ID_OUI_FROM_DATABASE=SOKRAT Ltd.
-
-OUI:002695*
- ID_OUI_FROM_DATABASE=ZT Group Int'l Inc
-
-OUI:00268F*
- ID_OUI_FROM_DATABASE=MTA SpA
-
-OUI:6C8CDB*
- ID_OUI_FROM_DATABASE=Otus Technologies Ltd
-
-OUI:B4417A*
- ID_OUI_FROM_DATABASE=ShenZhen Gongjin Electronics Co.,Ltd
-
-OUI:401597*
- ID_OUI_FROM_DATABASE=Protect America, Inc.
-
 OUI:60391F*
  ID_OUI_FROM_DATABASE=ABB Ltd
 
@@ -35960,72 +37169,126 @@ OUI:10BAA5*
 OUI:586ED6*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:E09153*
- ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+OUI:CC5076*
+ ID_OUI_FROM_DATABASE=Ocom Communications, Inc.
 
-OUI:CC0080*
- ID_OUI_FROM_DATABASE=BETTINI SRL
+OUI:705812*
+ ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
 
-OUI:644BC3*
- ID_OUI_FROM_DATABASE=Shanghai WOASiS Telecommunications Ltd., Co.
+OUI:002648*
+ ID_OUI_FROM_DATABASE=Emitech Corp.
 
-OUI:0CE709*
- ID_OUI_FROM_DATABASE=Fox Crypto B.V.
+OUI:002644*
+ ID_OUI_FROM_DATABASE=Thomson Telecom Belgium
 
-OUI:002703*
- ID_OUI_FROM_DATABASE=Testech Electronics Pte Ltd
+OUI:00263E*
+ ID_OUI_FROM_DATABASE=Trapeze Networks
 
-OUI:0026FD*
- ID_OUI_FROM_DATABASE=Interactive Intelligence
+OUI:002638*
+ ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd.
 
-OUI:0026F6*
- ID_OUI_FROM_DATABASE=Military Communication Institute
+OUI:00263D*
+ ID_OUI_FROM_DATABASE=MIA Corporation
 
-OUI:0026F0*
- ID_OUI_FROM_DATABASE=cTrixs International GmbH.
+OUI:002631*
+ ID_OUI_FROM_DATABASE=COMMTACT LTD
 
-OUI:0026EA*
- ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd.
+OUI:00262B*
+ ID_OUI_FROM_DATABASE=Wongs Electronics Co. Ltd.
 
-OUI:0026E3*
- ID_OUI_FROM_DATABASE=DTI
+OUI:002625*
+ ID_OUI_FROM_DATABASE=MediaSputnik
 
-OUI:0026DD*
- ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd.
+OUI:00261E*
+ ID_OUI_FROM_DATABASE=QINGBANG ELEC(SZ) CO., LTD
 
-OUI:0026DE*
- ID_OUI_FROM_DATABASE=FDI MATELEC
+OUI:002619*
+ ID_OUI_FROM_DATABASE=FRC
 
-OUI:7825AD*
- ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD.
+OUI:0025BA*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD
 
-OUI:54B620*
- ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd.
+OUI:0025B5*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:C4AAA1*
- ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o.
+OUI:0025AE*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
 
-OUI:78C40E*
- ID_OUI_FROM_DATABASE=H&D Wireless
+OUI:0025A8*
+ ID_OUI_FROM_DATABASE=Kontron (BeiJing) Technology Co.,Ltd
 
-OUI:9C5B96*
- ID_OUI_FROM_DATABASE=NMR Corporation
+OUI:0025A7*
+ ID_OUI_FROM_DATABASE=Comverge, Inc.
 
-OUI:E4FFDD*
- ID_OUI_FROM_DATABASE=ELECTRON INDIA
+OUI:0025A2*
+ ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L.
 
-OUI:F852DF*
- ID_OUI_FROM_DATABASE=VNL Europe AB
+OUI:002596*
+ ID_OUI_FROM_DATABASE=GIGAVISION srl
 
-OUI:1CF061*
- ID_OUI_FROM_DATABASE=SCAPS GmbH
+OUI:00259B*
+ ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd
 
-OUI:A893E6*
- ID_OUI_FROM_DATABASE=JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD
+OUI:002595*
+ ID_OUI_FROM_DATABASE=Northwest Signal Supply, Inc
+
+OUI:002542*
+ ID_OUI_FROM_DATABASE=Pittasoft
+
+OUI:002530*
+ ID_OUI_FROM_DATABASE=Aetas Systems Inc.
+
+OUI:002529*
+ ID_OUI_FROM_DATABASE=COMELIT GROUP S.P.A
+
+OUI:002522*
+ ID_OUI_FROM_DATABASE=ASRock Incorporation
+
+OUI:00251D*
+ ID_OUI_FROM_DATABASE=DSA Encore, LLC
+
+OUI:002518*
+ ID_OUI_FROM_DATABASE=Power PLUS Communications AG
+
+OUI:002513*
+ ID_OUI_FROM_DATABASE=CXP DIGITAL BV
+
+OUI:0026A1*
+ ID_OUI_FROM_DATABASE=Megger
+
+OUI:0026A2*
+ ID_OUI_FROM_DATABASE=Instrumentation Technology Systems
+
+OUI:00269B*
+ ID_OUI_FROM_DATABASE=SOKRAT Ltd.
+
+OUI:002695*
+ ID_OUI_FROM_DATABASE=ZT Group Int'l Inc
+
+OUI:00268F*
+ ID_OUI_FROM_DATABASE=MTA SpA
 
 OUI:00267C*
  ID_OUI_FROM_DATABASE=Metz-Werke GmbH & Co KG
 
+OUI:00255C*
+ ID_OUI_FROM_DATABASE=NEC Corporation
+
+OUI:002550*
+ ID_OUI_FROM_DATABASE=Riverbed Technology
+
+OUI:002555*
+ ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd
+
+OUI:00254F*
+ ID_OUI_FROM_DATABASE=ELETTROLAB Srl
+
+OUI:002549*
+ ID_OUI_FROM_DATABASE=Jeorich Tech. Co.,Ltd.
+
+OUI:002538*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division
+
 OUI:002676*
  ID_OUI_FROM_DATABASE=COMMidt AS
 
@@ -36041,6 +37304,21 @@ OUI:002663*
 OUI:00265D*
  ID_OUI_FROM_DATABASE=Samsung Electronics
 
+OUI:00264F*
+ ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH
+
+OUI:0025E0*
+ ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd
+
+OUI:0025DA*
+ ID_OUI_FROM_DATABASE=Secura Key
+
+OUI:0025D9*
+ ID_OUI_FROM_DATABASE=DataFab Systems Inc.
+
+OUI:0025D4*
+ ID_OUI_FROM_DATABASE=Fortress Technologies
+
 OUI:0025CD*
  ID_OUI_FROM_DATABASE=Skylane Optics
 
@@ -36053,33 +37331,6 @@ OUI:0025C7*
 OUI:0025C1*
  ID_OUI_FROM_DATABASE=Nawoo Korea Corp.
 
-OUI:0025BA*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD
-
-OUI:0025B5*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:0025AE*
- ID_OUI_FROM_DATABASE=Microsoft Corporation
-
-OUI:0025A8*
- ID_OUI_FROM_DATABASE=Kontron (BeiJing) Technology Co.,Ltd
-
-OUI:0025A7*
- ID_OUI_FROM_DATABASE=Comverge, Inc.
-
-OUI:00262B*
- ID_OUI_FROM_DATABASE=Wongs Electronics Co. Ltd.
-
-OUI:002625*
- ID_OUI_FROM_DATABASE=MediaSputnik
-
-OUI:00261E*
- ID_OUI_FROM_DATABASE=QINGBANG ELEC(SZ) CO., LTD
-
-OUI:002619*
- ID_OUI_FROM_DATABASE=FRC
-
 OUI:002612*
  ID_OUI_FROM_DATABASE=Space Exploration Technologies
 
@@ -36098,17 +37349,17 @@ OUI:002606*
 OUI:0025F9*
  ID_OUI_FROM_DATABASE=GMK electronic design GmbH
 
-OUI:0025A2*
- ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L.
+OUI:0025F5*
+ ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd
 
-OUI:002596*
- ID_OUI_FROM_DATABASE=GIGAVISION srl
+OUI:0025F0*
+ ID_OUI_FROM_DATABASE=Suga Electronics Limited
 
-OUI:00259B*
- ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd
+OUI:0025EA*
+ ID_OUI_FROM_DATABASE=Iphion BV
 
-OUI:002595*
- ID_OUI_FROM_DATABASE=Northwest Signal Supply, Inc
+OUI:0025E4*
+ ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC
 
 OUI:00258F*
  ID_OUI_FROM_DATABASE=Trident Microsystems, Inc.
@@ -36125,56 +37376,86 @@ OUI:00257B*
 OUI:002574*
  ID_OUI_FROM_DATABASE=KUNIMI MEDIA DEVICE Co., Ltd.
 
-OUI:00264F*
- ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH
+OUI:00256F*
+ ID_OUI_FROM_DATABASE=Dantherm Power
 
-OUI:002648*
- ID_OUI_FROM_DATABASE=Emitech Corp.
+OUI:002562*
+ ID_OUI_FROM_DATABASE=interbro Co. Ltd.
 
-OUI:002644*
- ID_OUI_FROM_DATABASE=Thomson Telecom Belgium
+OUI:002561*
+ ID_OUI_FROM_DATABASE=ProCurve Networking by HP
 
-OUI:00263E*
- ID_OUI_FROM_DATABASE=Trapeze Networks
+OUI:0023F7*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:002638*
- ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd.
+OUI:0023FD*
+ ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH
 
-OUI:00263D*
- ID_OUI_FROM_DATABASE=MIA Corporation
+OUI:0023F6*
+ ID_OUI_FROM_DATABASE=Softwell Technology Co., Ltd.
 
-OUI:002631*
- ID_OUI_FROM_DATABASE=COMMTACT LTD
+OUI:0023EC*
+ ID_OUI_FROM_DATABASE=Algorithmix GmbH
 
-OUI:00256F*
- ID_OUI_FROM_DATABASE=Dantherm Power
+OUI:0023E7*
+ ID_OUI_FROM_DATABASE=Hinke A/S
 
-OUI:002562*
- ID_OUI_FROM_DATABASE=interbro Co. Ltd.
+OUI:0023E0*
+ ID_OUI_FROM_DATABASE=INO Therapeutics LLC
 
-OUI:002561*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:0024C2*
+ ID_OUI_FROM_DATABASE=Asumo Co.,Ltd.
 
-OUI:00255C*
- ID_OUI_FROM_DATABASE=NEC Corporation
+OUI:0024BC*
+ ID_OUI_FROM_DATABASE=HuRob Co.,Ltd
 
-OUI:002550*
- ID_OUI_FROM_DATABASE=Riverbed Technology
+OUI:0024B7*
+ ID_OUI_FROM_DATABASE=GridPoint, Inc.
 
-OUI:002555*
- ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd
+OUI:0024AB*
+ ID_OUI_FROM_DATABASE=A7 Engineering, Inc.
 
-OUI:00254F*
- ID_OUI_FROM_DATABASE=ELETTROLAB Srl
+OUI:0024A6*
+ ID_OUI_FROM_DATABASE=TELESTAR DIGITAL GmbH
 
-OUI:002518*
- ID_OUI_FROM_DATABASE=Power PLUS Communications AG
+OUI:00249A*
+ ID_OUI_FROM_DATABASE=Beijing Zhongchuang Telecommunication Test Co., Ltd.
 
-OUI:002511*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
+OUI:00249F*
+ ID_OUI_FROM_DATABASE=RIM Testing Services
 
-OUI:002513*
- ID_OUI_FROM_DATABASE=CXP DIGITAL BV
+OUI:00246D*
+ ID_OUI_FROM_DATABASE=Weinzierl Engineering GmbH
+
+OUI:002474*
+ ID_OUI_FROM_DATABASE=Autronica Fire And Securirty
+
+OUI:002468*
+ ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd
+
+OUI:002466*
+ ID_OUI_FROM_DATABASE=Unitron nv
+
+OUI:002461*
+ ID_OUI_FROM_DATABASE=Shin Wang Tech.
+
+OUI:00245C*
+ ID_OUI_FROM_DATABASE=Design-Com Technologies Pty. Ltd.
+
+OUI:00244F*
+ ID_OUI_FROM_DATABASE=Asantron Technologies Ltd.
+
+OUI:002454*
+ ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
+
+OUI:002448*
+ ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc
+
+OUI:00244A*
+ ID_OUI_FROM_DATABASE=Voyant International
+
+OUI:002449*
+ ID_OUI_FROM_DATABASE=Shen Zhen Lite Star Electronics Technology Co., Ltd
 
 OUI:00250C*
  ID_OUI_FROM_DATABASE=Enertrac
@@ -36188,9 +37469,6 @@ OUI:0024F9*
 OUI:0024F2*
  ID_OUI_FROM_DATABASE=Uniphone Telecommunication Co., Ltd.
 
-OUI:0024F4*
- ID_OUI_FROM_DATABASE=Kaminario Technologies Ltd.
-
 OUI:0024ED*
  ID_OUI_FROM_DATABASE=YT Elec. Co,.Ltd.
 
@@ -36206,50 +37484,26 @@ OUI:0024DF*
 OUI:0024DA*
  ID_OUI_FROM_DATABASE=Innovar Systems Limited
 
-OUI:002549*
- ID_OUI_FROM_DATABASE=Jeorich Tech. Co.,Ltd.
-
-OUI:002538*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division
-
-OUI:002542*
- ID_OUI_FROM_DATABASE=Pittasoft
-
-OUI:002530*
- ID_OUI_FROM_DATABASE=Aetas Systems Inc.
-
-OUI:002529*
- ID_OUI_FROM_DATABASE=COMELIT GROUP S.P.A
-
-OUI:002522*
- ID_OUI_FROM_DATABASE=ASRock Incorporation
-
-OUI:00251D*
- ID_OUI_FROM_DATABASE=DSA Encore, LLC
-
-OUI:0025F5*
- ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd
-
-OUI:0025F0*
- ID_OUI_FROM_DATABASE=Suga Electronics Limited
+OUI:0024CE*
+ ID_OUI_FROM_DATABASE=Exeltech Inc
 
-OUI:0025EA*
- ID_OUI_FROM_DATABASE=Iphion BV
+OUI:0024D3*
+ ID_OUI_FROM_DATABASE=QUALICA Inc.
 
-OUI:0025E4*
- ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC
+OUI:0024C7*
+ ID_OUI_FROM_DATABASE=Mobilarm Ltd
 
-OUI:0025E0*
- ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd
+OUI:002429*
+ ID_OUI_FROM_DATABASE=MK MASTER INC.
 
-OUI:0025DA*
- ID_OUI_FROM_DATABASE=Secura Key
+OUI:00241C*
+ ID_OUI_FROM_DATABASE=FuGang Electronic (DG) Co.,Ltd
 
-OUI:0025D9*
- ID_OUI_FROM_DATABASE=DataFab Systems Inc.
+OUI:002428*
+ ID_OUI_FROM_DATABASE=EnergyICT
 
-OUI:0025D4*
- ID_OUI_FROM_DATABASE=Fortress Technologies
+OUI:002416*
+ ID_OUI_FROM_DATABASE=Any Use
 
 OUI:002410*
  ID_OUI_FROM_DATABASE=NUETEQ Technology,Inc.
@@ -36257,66 +37511,6 @@ OUI:002410*
 OUI:002409*
  ID_OUI_FROM_DATABASE=The Toro Company
 
-OUI:0023F7*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:0023FD*
- ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH
-
-OUI:0023F6*
- ID_OUI_FROM_DATABASE=Softwell Technology Co., Ltd.
-
-OUI:0023EC*
- ID_OUI_FROM_DATABASE=Algorithmix GmbH
-
-OUI:0023E7*
- ID_OUI_FROM_DATABASE=Hinke A/S
-
-OUI:002387*
- ID_OUI_FROM_DATABASE=ThinkFlood, Inc.
-
-OUI:002381*
- ID_OUI_FROM_DATABASE=Lengda Technology(Xiamen) Co.,Ltd.
-
-OUI:002382*
- ID_OUI_FROM_DATABASE=Lih Rong Electronic Enterprise Co., Ltd.
-
-OUI:00237B*
- ID_OUI_FROM_DATABASE=WHDI LLC
-
-OUI:002372*
- ID_OUI_FROM_DATABASE=MORE STAR INDUSTRIAL GROUP LIMITED
-
-OUI:0024CE*
- ID_OUI_FROM_DATABASE=Exeltech Inc
-
-OUI:0024D3*
- ID_OUI_FROM_DATABASE=QUALICA Inc.
-
-OUI:0024C7*
- ID_OUI_FROM_DATABASE=Mobilarm Ltd
-
-OUI:0024C2*
- ID_OUI_FROM_DATABASE=Asumo Co.,Ltd.
-
-OUI:0024BC*
- ID_OUI_FROM_DATABASE=HuRob Co.,Ltd
-
-OUI:0024B7*
- ID_OUI_FROM_DATABASE=GridPoint, Inc.
-
-OUI:0024AB*
- ID_OUI_FROM_DATABASE=A7 Engineering, Inc.
-
-OUI:0024A6*
- ID_OUI_FROM_DATABASE=TELESTAR DIGITAL GmbH
-
-OUI:00249A*
- ID_OUI_FROM_DATABASE=Beijing Zhongchuang Telecommunication Test Co., Ltd.
-
-OUI:00249F*
- ID_OUI_FROM_DATABASE=RIM Testing Services
-
 OUI:002487*
  ID_OUI_FROM_DATABASE=Blackboard Inc.
 
@@ -36329,17 +37523,8 @@ OUI:002485*
 OUI:002480*
  ID_OUI_FROM_DATABASE=Meteocontrol GmbH
 
-OUI:002454*
- ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
-
-OUI:002448*
- ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc
-
-OUI:00244A*
- ID_OUI_FROM_DATABASE=Voyant International
-
-OUI:002449*
- ID_OUI_FROM_DATABASE=Shen Zhen Lite Star Electronics Technology Co., Ltd
+OUI:002479*
+ ID_OUI_FROM_DATABASE=Optec Displays, Inc.
 
 OUI:002443*
  ID_OUI_FROM_DATABASE=Nortel Networks
@@ -36347,29 +37532,20 @@ OUI:002443*
 OUI:002439*
  ID_OUI_FROM_DATABASE=Digital Barriers Advanced Technologies
 
-OUI:002479*
- ID_OUI_FROM_DATABASE=Optec Displays, Inc.
-
-OUI:00246D*
- ID_OUI_FROM_DATABASE=Weinzierl Engineering GmbH
-
-OUI:002474*
- ID_OUI_FROM_DATABASE=Autronica Fire And Securirty
-
-OUI:002468*
- ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd
+OUI:002432*
+ ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD
 
-OUI:002466*
- ID_OUI_FROM_DATABASE=Unitron nv
+OUI:0023DA*
+ ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH
 
-OUI:002461*
- ID_OUI_FROM_DATABASE=Shin Wang Tech.
+OUI:0023C8*
+ ID_OUI_FROM_DATABASE=TEAM-R
 
-OUI:00245C*
- ID_OUI_FROM_DATABASE=Design-Com Technologies Pty. Ltd.
+OUI:0023C7*
+ ID_OUI_FROM_DATABASE=AVSystem
 
-OUI:00244F*
- ID_OUI_FROM_DATABASE=Asantron Technologies Ltd.
+OUI:0023C1*
+ ID_OUI_FROM_DATABASE=Securitas Direct AB
 
 OUI:0023BB*
  ID_OUI_FROM_DATABASE=Schmitt Industries
@@ -36380,71 +37556,44 @@ OUI:0023BA*
 OUI:0023B5*
  ID_OUI_FROM_DATABASE=ORTANA LTD
 
-OUI:0023A8*
- ID_OUI_FROM_DATABASE=Marshall Electronics
-
-OUI:00239B*
- ID_OUI_FROM_DATABASE=Elster Solutions, LLC
-
-OUI:002396*
- ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION
-
-OUI:002391*
- ID_OUI_FROM_DATABASE=Maxian
-
-OUI:00238C*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:002432*
- ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD
-
-OUI:002429*
- ID_OUI_FROM_DATABASE=MK MASTER INC.
-
-OUI:00241C*
- ID_OUI_FROM_DATABASE=FuGang Electronic (DG) Co.,Ltd
-
-OUI:002428*
- ID_OUI_FROM_DATABASE=EnergyICT
-
-OUI:002416*
- ID_OUI_FROM_DATABASE=Any Use
+OUI:002381*
+ ID_OUI_FROM_DATABASE=Lengda Technology(Xiamen) Co.,Ltd.
 
-OUI:0023E0*
- ID_OUI_FROM_DATABASE=INO Therapeutics LLC
+OUI:002382*
+ ID_OUI_FROM_DATABASE=Lih Rong Electronic Enterprise Co., Ltd.
 
-OUI:0023DA*
- ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH
+OUI:00237B*
+ ID_OUI_FROM_DATABASE=WHDI LLC
 
-OUI:0023C8*
- ID_OUI_FROM_DATABASE=TEAM-R
+OUI:002372*
+ ID_OUI_FROM_DATABASE=MORE STAR INDUSTRIAL GROUP LIMITED
 
-OUI:0023C7*
- ID_OUI_FROM_DATABASE=AVSystem
+OUI:002366*
+ ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd.
 
-OUI:0023C1*
- ID_OUI_FROM_DATABASE=Securitas Direct AB
+OUI:00236B*
+ ID_OUI_FROM_DATABASE=Xembedded, Inc.
 
-OUI:0021DC*
- ID_OUI_FROM_DATABASE=TECNOALARM S.r.l.
+OUI:002359*
+ ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited
 
-OUI:0021E2*
- ID_OUI_FROM_DATABASE=Creative Electronic GmbH
+OUI:00235F*
+ ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH
 
-OUI:0021D6*
- ID_OUI_FROM_DATABASE=LXI Consortium
+OUI:002353*
+ ID_OUI_FROM_DATABASE=F E T Elettronica snc
 
-OUI:0021CF*
- ID_OUI_FROM_DATABASE=The Crypto Group
+OUI:002347*
+ ID_OUI_FROM_DATABASE=ProCurve Networking by HP
 
-OUI:0021C9*
- ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited
+OUI:00234C*
+ ID_OUI_FROM_DATABASE=KTC AB
 
-OUI:0021CA*
- ID_OUI_FROM_DATABASE=ART System Co., Ltd.
+OUI:00233A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:0021C3*
- ID_OUI_FROM_DATABASE=CORNELL Communications, Inc.
+OUI:002339*
+ ID_OUI_FROM_DATABASE=Samsung Electronics
 
 OUI:002334*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -36473,71 +37622,68 @@ OUI:002317*
 OUI:002310*
  ID_OUI_FROM_DATABASE=LNC Technology Co., Ltd.
 
-OUI:002273*
- ID_OUI_FROM_DATABASE=Techway
-
-OUI:002274*
- ID_OUI_FROM_DATABASE=FamilyPhone AB
+OUI:002304*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:00226F*
- ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd.
+OUI:002236*
+ ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O.
 
-OUI:00226A*
- ID_OUI_FROM_DATABASE=Honeywell
+OUI:002230*
+ ID_OUI_FROM_DATABASE=FutureLogic Inc.
 
-OUI:002260*
- ID_OUI_FROM_DATABASE=AFREEY Inc.
+OUI:002229*
+ ID_OUI_FROM_DATABASE=Compumedics Ltd
 
-OUI:00225B*
- ID_OUI_FROM_DATABASE=Teradici Corporation
+OUI:00221D*
+ ID_OUI_FROM_DATABASE=Freegene Technology LTD
 
-OUI:002256*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:002224*
+ ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd.
 
-OUI:002255*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:002223*
+ ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc.
 
-OUI:00224D*
- ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP.
+OUI:002216*
+ ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION
 
-OUI:002252*
- ID_OUI_FROM_DATABASE=ZOLL Lifecor Corporation
+OUI:002217*
+ ID_OUI_FROM_DATABASE=Neat Electronics
 
-OUI:002246*
- ID_OUI_FROM_DATABASE=Evoc Intelligent Technology Co.,Ltd.
+OUI:002211*
+ ID_OUI_FROM_DATABASE=Rohati Systems
 
-OUI:002366*
- ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd.
+OUI:00220A*
+ ID_OUI_FROM_DATABASE=OnLive, Inc
 
-OUI:00236B*
- ID_OUI_FROM_DATABASE=Xembedded, Inc.
+OUI:002295*
+ ID_OUI_FROM_DATABASE=SGM Technology for lighting spa
 
-OUI:002359*
- ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited
+OUI:00228E*
+ ID_OUI_FROM_DATABASE=TV-NUMERIC
 
-OUI:00235F*
- ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH
+OUI:002289*
+ ID_OUI_FROM_DATABASE=Optosecurity Inc.
 
-OUI:002353*
- ID_OUI_FROM_DATABASE=F E T Elettronica snc
+OUI:002282*
+ ID_OUI_FROM_DATABASE=8086 Consultancy
 
-OUI:002347*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:00227C*
+ ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd
 
-OUI:00234C*
- ID_OUI_FROM_DATABASE=KTC AB
+OUI:002279*
+ ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd.
 
-OUI:002340*
- ID_OUI_FROM_DATABASE=MiX Telematics
+OUI:002273*
+ ID_OUI_FROM_DATABASE=Techway
 
-OUI:00233A*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:002274*
+ ID_OUI_FROM_DATABASE=FamilyPhone AB
 
-OUI:002339*
- ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:00226F*
+ ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd.
 
-OUI:002304*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00226A*
+ ID_OUI_FROM_DATABASE=Honeywell
 
 OUI:0022F3*
  ID_OUI_FROM_DATABASE=SHARP Corporation
@@ -36557,110 +37703,125 @@ OUI:0022E2*
 OUI:0022DB*
  ID_OUI_FROM_DATABASE=Translogic Corporation
 
-OUI:0022A1*
- ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd.
+OUI:0022CF*
+ ID_OUI_FROM_DATABASE=PLANEX Communications INC
 
-OUI:00229B*
- ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc.
+OUI:0022D4*
+ ID_OUI_FROM_DATABASE=ComWorth Co., Ltd.
 
-OUI:00229C*
- ID_OUI_FROM_DATABASE=Verismo Networks Inc
+OUI:0022CA*
+ ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd.
 
-OUI:002295*
- ID_OUI_FROM_DATABASE=SGM Technology for lighting spa
+OUI:0022C5*
+ ID_OUI_FROM_DATABASE=INFORSON Co,Ltd.
 
-OUI:00228E*
- ID_OUI_FROM_DATABASE=TV-NUMERIC
+OUI:002260*
+ ID_OUI_FROM_DATABASE=AFREEY Inc.
 
-OUI:002289*
- ID_OUI_FROM_DATABASE=Optosecurity Inc.
+OUI:00225B*
+ ID_OUI_FROM_DATABASE=Teradici Corporation
 
-OUI:002282*
- ID_OUI_FROM_DATABASE=8086 Consultancy
+OUI:002256*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:00227C*
- ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd
+OUI:002255*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:002279*
- ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd.
+OUI:00224D*
+ ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP.
+
+OUI:002252*
+ ID_OUI_FROM_DATABASE=ZOLL Lifecor Corporation
+
+OUI:002246*
+ ID_OUI_FROM_DATABASE=Evoc Intelligent Technology Co.,Ltd.
 
 OUI:00223C*
  ID_OUI_FROM_DATABASE=RATIO Entwicklungen GmbH
 
-OUI:002236*
- ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O.
+OUI:0022C0*
+ ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd
 
-OUI:002230*
- ID_OUI_FROM_DATABASE=FutureLogic Inc.
+OUI:0022BB*
+ ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG
 
-OUI:002229*
- ID_OUI_FROM_DATABASE=Compumedics Ltd
+OUI:0022AE*
+ ID_OUI_FROM_DATABASE=Mattel Inc.
 
-OUI:00221D*
- ID_OUI_FROM_DATABASE=Freegene Technology LTD
+OUI:0022AD*
+ ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC.
 
-OUI:002224*
- ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd.
+OUI:0022A8*
+ ID_OUI_FROM_DATABASE=Ouman Oy
 
-OUI:002223*
- ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc.
+OUI:0022A1*
+ ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd.
 
-OUI:002216*
- ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION
+OUI:00229B*
+ ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc.
 
-OUI:002217*
- ID_OUI_FROM_DATABASE=Neat Electronics
+OUI:00229C*
+ ID_OUI_FROM_DATABASE=Verismo Networks Inc
 
-OUI:002211*
- ID_OUI_FROM_DATABASE=Rohati Systems
+OUI:0023A8*
+ ID_OUI_FROM_DATABASE=Marshall Electronics
 
-OUI:00220A*
- ID_OUI_FROM_DATABASE=OnLive, Inc
+OUI:00239B*
+ ID_OUI_FROM_DATABASE=Elster Solutions, LLC
 
-OUI:002204*
- ID_OUI_FROM_DATABASE=KORATEK
+OUI:002396*
+ ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION
 
-OUI:0021FF*
- ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA
+OUI:002391*
+ ID_OUI_FROM_DATABASE=Maxian
 
-OUI:0021FB*
- ID_OUI_FROM_DATABASE=LG Electronics
+OUI:00238C*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:0021F5*
- ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc.
+OUI:002387*
+ ID_OUI_FROM_DATABASE=ThinkFlood, Inc.
 
-OUI:0021EF*
- ID_OUI_FROM_DATABASE=Kapsys
+OUI:0021D6*
+ ID_OUI_FROM_DATABASE=LXI Consortium
 
-OUI:0021EE*
- ID_OUI_FROM_DATABASE=Full Spectrum Inc.
+OUI:0021CF*
+ ID_OUI_FROM_DATABASE=The Crypto Group
 
-OUI:0022CF*
- ID_OUI_FROM_DATABASE=PLANEX Communications INC
+OUI:0021C9*
+ ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited
 
-OUI:0022D4*
- ID_OUI_FROM_DATABASE=ComWorth Co., Ltd.
+OUI:0021CA*
+ ID_OUI_FROM_DATABASE=ART System Co., Ltd.
 
-OUI:0022CA*
- ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd.
+OUI:0021C3*
+ ID_OUI_FROM_DATABASE=CORNELL Communications, Inc.
 
-OUI:0022C5*
- ID_OUI_FROM_DATABASE=INFORSON Co,Ltd.
+OUI:0021BC*
+ ID_OUI_FROM_DATABASE=ZALA COMPUTER
 
-OUI:0022C0*
- ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd
+OUI:0021B7*
+ ID_OUI_FROM_DATABASE=Lexmark International Inc.
 
-OUI:0022BB*
- ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG
+OUI:002152*
+ ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited
 
-OUI:0022AE*
- ID_OUI_FROM_DATABASE=Mattel Inc.
+OUI:002157*
+ ID_OUI_FROM_DATABASE=National Datacast, Inc.
 
-OUI:0022AD*
- ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC.
+OUI:00214B*
+ ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd
 
-OUI:0022A8*
- ID_OUI_FROM_DATABASE=Ouman Oy
+OUI:002145*
+ ID_OUI_FROM_DATABASE=Semptian Technologies Ltd.
+
+OUI:002144*
+ ID_OUI_FROM_DATABASE=SS Telecoms
+
+OUI:00213C*
+ ID_OUI_FROM_DATABASE=AliphCom
+
+OUI:00213B*
+ ID_OUI_FROM_DATABASE=Berkshire Products, Inc
 
 OUI:002132*
  ID_OUI_FROM_DATABASE=Masterclock, Inc.
@@ -36671,20 +37832,14 @@ OUI:00212C*
 OUI:002131*
  ID_OUI_FROM_DATABASE=Blynke Inc.
 
-OUI:00211F*
- ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD.
-
-OUI:002120*
- ID_OUI_FROM_DATABASE=Sequel Technologies
-
-OUI:002125*
- ID_OUI_FROM_DATABASE=KUK JE TONG SHIN Co.,LTD
+OUI:001FD1*
+ ID_OUI_FROM_DATABASE=OPTEX CO.,LTD.
 
-OUI:002119*
- ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics
+OUI:001FCA*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:002112*
- ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD
+OUI:001FBE*
+ ID_OUI_FROM_DATABASE=Shenzhen Mopnet Industrial Co.,Ltd
 
 OUI:001FB9*
  ID_OUI_FROM_DATABASE=Paltronics
@@ -36698,44 +37853,35 @@ OUI:001FB8*
 OUI:001FB2*
  ID_OUI_FROM_DATABASE=Sontheim Industrie Elektronik GmbH
 
-OUI:001FAB*
- ID_OUI_FROM_DATABASE=I.S HIGH TECH.INC
-
-OUI:001FA6*
- ID_OUI_FROM_DATABASE=Stilo srl
-
-OUI:001FA1*
- ID_OUI_FROM_DATABASE=Gtran Inc
-
-OUI:001F9C*
- ID_OUI_FROM_DATABASE=LEDCO
+OUI:00211F*
+ ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD.
 
-OUI:00215E*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:002120*
+ ID_OUI_FROM_DATABASE=Sequel Technologies
 
-OUI:002151*
- ID_OUI_FROM_DATABASE=Millinet Co., Ltd.
+OUI:002125*
+ ID_OUI_FROM_DATABASE=KUK JE TONG SHIN Co.,LTD
 
-OUI:002152*
- ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited
+OUI:002119*
+ ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics
 
-OUI:002157*
- ID_OUI_FROM_DATABASE=National Datacast, Inc.
+OUI:002112*
+ ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD
 
-OUI:00214B*
- ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd
+OUI:002103*
+ ID_OUI_FROM_DATABASE=GHI Electronics, LLC
 
-OUI:002145*
- ID_OUI_FROM_DATABASE=Semptian Technologies Ltd.
+OUI:0021B0*
+ ID_OUI_FROM_DATABASE=Tyco Telecommunications
 
-OUI:002144*
- ID_OUI_FROM_DATABASE=SS Telecoms
+OUI:0021A4*
+ ID_OUI_FROM_DATABASE=Dbii Networks
 
-OUI:00213C*
- ID_OUI_FROM_DATABASE=AliphCom
+OUI:00219A*
+ ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd
 
-OUI:00213B*
- ID_OUI_FROM_DATABASE=Berkshire Products, Inc
+OUI:002196*
+ ID_OUI_FROM_DATABASE=Telsey  S.p.A.
 
 OUI:002190*
  ID_OUI_FROM_DATABASE=Goliath Solutions
@@ -36749,24 +37895,6 @@ OUI:002184*
 OUI:002183*
  ID_OUI_FROM_DATABASE=VATECH HYDRO
 
-OUI:00217D*
- ID_OUI_FROM_DATABASE=PYXIS S.R.L.
-
-OUI:002177*
- ID_OUI_FROM_DATABASE=W. L. Gore & Associates
-
-OUI:002176*
- ID_OUI_FROM_DATABASE=YMax Telecom Ltd.
-
-OUI:002171*
- ID_OUI_FROM_DATABASE=Wesung TNC Co., Ltd.
-
-OUI:002164*
- ID_OUI_FROM_DATABASE=Special Design Bureau for Seismic Instrumentation
-
-OUI:002103*
- ID_OUI_FROM_DATABASE=GHI Electronics, LLC
-
 OUI:001FFA*
  ID_OUI_FROM_DATABASE=Coretree, Co, Ltd
 
@@ -36785,80 +37913,65 @@ OUI:001FE7*
 OUI:001FDB*
  ID_OUI_FROM_DATABASE=Network Supply Corp.,
 
-OUI:001FD1*
- ID_OUI_FROM_DATABASE=OPTEX CO.,LTD.
-
-OUI:001FCA*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:001FBE*
- ID_OUI_FROM_DATABASE=Shenzhen Mopnet Industrial Co.,Ltd
-
-OUI:001F62*
- ID_OUI_FROM_DATABASE=JSC Stilsoft
-
-OUI:001F67*
- ID_OUI_FROM_DATABASE=Hitachi,Ltd.
-
-OUI:001F55*
- ID_OUI_FROM_DATABASE=Honeywell Security (China) Co., Ltd.
+OUI:00217D*
+ ID_OUI_FROM_DATABASE=PYXIS S.R.L.
 
-OUI:001F56*
- ID_OUI_FROM_DATABASE=DIGITAL FORECAST
+OUI:002177*
+ ID_OUI_FROM_DATABASE=W. L. Gore & Associates
 
-OUI:001F4F*
- ID_OUI_FROM_DATABASE=Thinkware Co. Ltd.
+OUI:002176*
+ ID_OUI_FROM_DATABASE=YMax Telecom Ltd.
 
-OUI:001F48*
- ID_OUI_FROM_DATABASE=Mojix Inc.
+OUI:002171*
+ ID_OUI_FROM_DATABASE=Wesung TNC Co., Ltd.
 
-OUI:001F43*
- ID_OUI_FROM_DATABASE=ENTES ELEKTRONIK
+OUI:002164*
+ ID_OUI_FROM_DATABASE=Special Design Bureau for Seismic Instrumentation
 
-OUI:001F8E*
- ID_OUI_FROM_DATABASE=Metris USA Inc.
+OUI:00215E*
+ ID_OUI_FROM_DATABASE=IBM Corp
 
-OUI:001F88*
- ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG
+OUI:002151*
+ ID_OUI_FROM_DATABASE=Millinet Co., Ltd.
 
-OUI:001F81*
- ID_OUI_FROM_DATABASE=Accel Semiconductor Corp
+OUI:002204*
+ ID_OUI_FROM_DATABASE=KORATEK
 
-OUI:001B58*
- ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd.
+OUI:0021FF*
+ ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA
 
-OUI:001F78*
- ID_OUI_FROM_DATABASE=Blue Fox Porini Textile
+OUI:0021FB*
+ ID_OUI_FROM_DATABASE=LG Electronics
 
-OUI:001F6E*
- ID_OUI_FROM_DATABASE=Vtech Engineering Corporation
+OUI:0021F5*
+ ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc.
 
-OUI:001F68*
- ID_OUI_FROM_DATABASE=Martinsson Elektronik AB
+OUI:0021EF*
+ ID_OUI_FROM_DATABASE=Kapsys
 
-OUI:0021BC*
- ID_OUI_FROM_DATABASE=ZALA COMPUTER
+OUI:0021EE*
+ ID_OUI_FROM_DATABASE=Full Spectrum Inc.
 
-OUI:0021B7*
- ID_OUI_FROM_DATABASE=Lexmark International Inc.
+OUI:0021DC*
+ ID_OUI_FROM_DATABASE=TECNOALARM S.r.l.
 
-OUI:0021B0*
- ID_OUI_FROM_DATABASE=Tyco Telecommunications
+OUI:0021E2*
+ ID_OUI_FROM_DATABASE=Creative Electronic GmbH
 
-OUI:0021A4*
- ID_OUI_FROM_DATABASE=Dbii Networks
+OUI:001FAB*
+ ID_OUI_FROM_DATABASE=I.S HIGH TECH.INC
 
-OUI:00219A*
- ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd
+OUI:001FA6*
+ ID_OUI_FROM_DATABASE=Stilo srl
 
-OUI:002196*
- ID_OUI_FROM_DATABASE=Telsey  S.p.A.
+OUI:001FA1*
+ ID_OUI_FROM_DATABASE=Gtran Inc
 
-OUI:001E4B*
- ID_OUI_FROM_DATABASE=City Theatrical
+OUI:001F9C*
+ ID_OUI_FROM_DATABASE=LEDCO
 
-OUI:001E47*
- ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering
+OUI:001F8E*
+ ID_OUI_FROM_DATABASE=Metris USA Inc.
 
 OUI:001E41*
  ID_OUI_FROM_DATABASE=Microwave Communication & Component, Inc.
@@ -36872,6 +37985,33 @@ OUI:001E27*
 OUI:001E28*
  ID_OUI_FROM_DATABASE=Lumexis Corporation
 
+OUI:001E22*
+ ID_OUI_FROM_DATABASE=ARVOO Imaging Products BV
+
+OUI:001E1B*
+ ID_OUI_FROM_DATABASE=Digital Stream Technology, Inc.
+
+OUI:001E16*
+ ID_OUI_FROM_DATABASE=Keytronix
+
+OUI:001E15*
+ ID_OUI_FROM_DATABASE=Beech Hill Electronics
+
+OUI:001E11*
+ ID_OUI_FROM_DATABASE=ELELUX INTERNATIONAL LTD
+
+OUI:001E05*
+ ID_OUI_FROM_DATABASE=Xseed Technologies & Computing
+
+OUI:001E0C*
+ ID_OUI_FROM_DATABASE=Sherwood Information Partners, Inc.
+
+OUI:001DFE*
+ ID_OUI_FROM_DATABASE=Palm, Inc
+
+OUI:001DF9*
+ ID_OUI_FROM_DATABASE=Cybiotronics (Far East) Limited
+
 OUI:001DF2*
  ID_OUI_FROM_DATABASE=Netflix, Inc.
 
@@ -36881,50 +38021,68 @@ OUI:001DEB*
 OUI:001DEC*
  ID_OUI_FROM_DATABASE=Marusys
 
-OUI:001DE6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001F88*
+ ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG
 
-OUI:001DDA*
- ID_OUI_FROM_DATABASE=Mikroelektronika spol. s r. o.
+OUI:001F81*
+ ID_OUI_FROM_DATABASE=Accel Semiconductor Corp
 
-OUI:001DDF*
- ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
+OUI:001B58*
+ ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd.
 
-OUI:001DCC*
- ID_OUI_FROM_DATABASE=Hetra Secure Solutions
+OUI:001F78*
+ ID_OUI_FROM_DATABASE=Blue Fox Porini Textile
 
-OUI:001DC7*
- ID_OUI_FROM_DATABASE=L-3 Communications Geneva Aerospace
+OUI:001F6E*
+ ID_OUI_FROM_DATABASE=Vtech Engineering Corporation
 
-OUI:001DC0*
- ID_OUI_FROM_DATABASE=Enphase Energy
+OUI:001F68*
+ ID_OUI_FROM_DATABASE=Martinsson Elektronik AB
 
-OUI:001ED8*
- ID_OUI_FROM_DATABASE=Digital United Inc.
+OUI:001F62*
+ ID_OUI_FROM_DATABASE=JSC Stilsoft
 
-OUI:001ED2*
- ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc
+OUI:001F67*
+ ID_OUI_FROM_DATABASE=Hitachi,Ltd.
 
-OUI:001ED1*
- ID_OUI_FROM_DATABASE=Keyprocessor B.V.
+OUI:001F55*
+ ID_OUI_FROM_DATABASE=Honeywell Security (China) Co., Ltd.
 
-OUI:001ECC*
- ID_OUI_FROM_DATABASE=CDVI
+OUI:001E9B*
+ ID_OUI_FROM_DATABASE=San-Eisha, Ltd.
 
-OUI:001EC5*
- ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc
+OUI:001E94*
+ ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION
 
-OUI:001EC0*
- ID_OUI_FROM_DATABASE=Microchip Technology Inc.
+OUI:001E8F*
+ ID_OUI_FROM_DATABASE=CANON INC.
 
-OUI:001EBF*
- ID_OUI_FROM_DATABASE=Haas Automation Inc.
+OUI:001E87*
+ ID_OUI_FROM_DATABASE=Realease Limited
 
-OUI:001EB9*
- ID_OUI_FROM_DATABASE=Sing Fai Technology Limited
+OUI:001E80*
+ ID_OUI_FROM_DATABASE=Last Mile Ltd.
 
-OUI:001EB2*
- ID_OUI_FROM_DATABASE=LG innotek
+OUI:001E7B*
+ ID_OUI_FROM_DATABASE=R.I.CO. S.r.l.
+
+OUI:001E76*
+ ID_OUI_FROM_DATABASE=Thermo Fisher Scientific
+
+OUI:001E6A*
+ ID_OUI_FROM_DATABASE=Beijing Bluexon Technology Co.,Ltd
+
+OUI:001F56*
+ ID_OUI_FROM_DATABASE=DIGITAL FORECAST
+
+OUI:001F4F*
+ ID_OUI_FROM_DATABASE=Thinkware Co. Ltd.
+
+OUI:001F48*
+ ID_OUI_FROM_DATABASE=Mojix Inc.
+
+OUI:001F43*
+ ID_OUI_FROM_DATABASE=ENTES ELEKTRONIK
 
 OUI:001F2E*
  ID_OUI_FROM_DATABASE=Triangle Research Int'l Pte Ltd
@@ -36935,47 +38093,47 @@ OUI:001F2D*
 OUI:001F27*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001F20*
- ID_OUI_FROM_DATABASE=Logitech Europe SA
+OUI:001EF5*
+ ID_OUI_FROM_DATABASE=Hitek Automated Inc.
 
-OUI:001F14*
- ID_OUI_FROM_DATABASE=NexG
+OUI:001EFB*
+ ID_OUI_FROM_DATABASE=Trio Motion Technology Ltd
 
-OUI:001F1B*
- ID_OUI_FROM_DATABASE=RoyalTek Company Ltd.
+OUI:001EE9*
+ ID_OUI_FROM_DATABASE=Stoneridge Electronics AB
 
-OUI:001F0D*
- ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West
+OUI:001EEE*
+ ID_OUI_FROM_DATABASE=ETL Systems Ltd
 
-OUI:001F0E*
- ID_OUI_FROM_DATABASE=Japan Kyastem Co., Ltd
+OUI:001EE2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:001E22*
- ID_OUI_FROM_DATABASE=ARVOO Imaging Products BV
+OUI:001ED8*
+ ID_OUI_FROM_DATABASE=Digital United Inc.
 
-OUI:001E1B*
- ID_OUI_FROM_DATABASE=Digital Stream Technology, Inc.
+OUI:001ED2*
+ ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc
 
-OUI:001E16*
- ID_OUI_FROM_DATABASE=Keytronix
+OUI:001ED1*
+ ID_OUI_FROM_DATABASE=Keyprocessor B.V.
 
-OUI:001E15*
- ID_OUI_FROM_DATABASE=Beech Hill Electronics
+OUI:001ECC*
+ ID_OUI_FROM_DATABASE=CDVI
 
-OUI:001E11*
- ID_OUI_FROM_DATABASE=ELELUX INTERNATIONAL LTD
+OUI:001EC5*
+ ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc
 
-OUI:001E05*
- ID_OUI_FROM_DATABASE=Xseed Technologies & Computing
+OUI:001EC0*
+ ID_OUI_FROM_DATABASE=Microchip Technology Inc.
 
-OUI:001E0C*
- ID_OUI_FROM_DATABASE=Sherwood Information Partners, Inc.
+OUI:001EBF*
+ ID_OUI_FROM_DATABASE=Haas Automation Inc.
 
-OUI:001DFE*
- ID_OUI_FROM_DATABASE=Palm, Inc
+OUI:001EB9*
+ ID_OUI_FROM_DATABASE=Sing Fai Technology Limited
 
-OUI:001DF9*
- ID_OUI_FROM_DATABASE=Cybiotronics (Far East) Limited
+OUI:001EB2*
+ ID_OUI_FROM_DATABASE=LG innotek
 
 OUI:001EAD*
  ID_OUI_FROM_DATABASE=Wingtech Group Limited
@@ -36989,20 +38147,20 @@ OUI:001EA7*
 OUI:001EA1*
  ID_OUI_FROM_DATABASE=Brunata a/s
 
-OUI:001E9B*
- ID_OUI_FROM_DATABASE=San-Eisha, Ltd.
+OUI:001F20*
+ ID_OUI_FROM_DATABASE=Logitech Europe SA
 
-OUI:001E94*
- ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION
+OUI:001F14*
+ ID_OUI_FROM_DATABASE=NexG
 
-OUI:001E8F*
- ID_OUI_FROM_DATABASE=CANON INC.
+OUI:001F1B*
+ ID_OUI_FROM_DATABASE=RoyalTek Company Ltd.
 
-OUI:001E87*
- ID_OUI_FROM_DATABASE=Realease Limited
+OUI:001F0D*
+ ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West
 
-OUI:001E80*
- ID_OUI_FROM_DATABASE=Last Mile Ltd.
+OUI:001F0E*
+ ID_OUI_FROM_DATABASE=Japan Kyastem Co., Ltd
 
 OUI:001EFC*
  ID_OUI_FROM_DATABASE=JSC MASSA-K
@@ -37010,30 +38168,6 @@ OUI:001EFC*
 OUI:001F08*
  ID_OUI_FROM_DATABASE=RISCO LTD
 
-OUI:001EF5*
- ID_OUI_FROM_DATABASE=Hitek Automated Inc.
-
-OUI:001EFB*
- ID_OUI_FROM_DATABASE=Trio Motion Technology Ltd
-
-OUI:001EE9*
- ID_OUI_FROM_DATABASE=Stoneridge Electronics AB
-
-OUI:001EEE*
- ID_OUI_FROM_DATABASE=ETL Systems Ltd
-
-OUI:001EE2*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:001E7B*
- ID_OUI_FROM_DATABASE=R.I.CO. S.r.l.
-
-OUI:001E76*
- ID_OUI_FROM_DATABASE=Thermo Fisher Scientific
-
-OUI:001E6A*
- ID_OUI_FROM_DATABASE=Beijing Bluexon Technology Co.,Ltd
-
 OUI:001E71*
  ID_OUI_FROM_DATABASE=MIrcom Group of Companies
 
@@ -37049,29 +38183,11 @@ OUI:001E57*
 OUI:001E51*
  ID_OUI_FROM_DATABASE=Converter Industry Srl
 
-OUI:001DB9*
- ID_OUI_FROM_DATABASE=Wellspring Wireless
-
-OUI:001DB4*
- ID_OUI_FROM_DATABASE=KUMHO ENG CO.,LTD
-
-OUI:001DAF*
- ID_OUI_FROM_DATABASE=Nortel
-
-OUI:001D9E*
- ID_OUI_FROM_DATABASE=AXION TECHNOLOGIES
-
-OUI:001DA3*
- ID_OUI_FROM_DATABASE=SabiOso
-
-OUI:001D9D*
- ID_OUI_FROM_DATABASE=ARTJOY INTERNATIONAL LIMITED
-
-OUI:001D45*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001E4B*
+ ID_OUI_FROM_DATABASE=City Theatrical
 
-OUI:001D3E*
- ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD
+OUI:001E47*
+ ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering
 
 OUI:001D37*
  ID_OUI_FROM_DATABASE=Thales-Panda Transportation System
@@ -37097,32 +38213,8 @@ OUI:001D25*
 OUI:001D1A*
  ID_OUI_FROM_DATABASE=OvisLink S.A.
 
-OUI:001D7A*
- ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc.
-
-OUI:001D74*
- ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd.
-
-OUI:001D62*
- ID_OUI_FROM_DATABASE=InPhase Technologies
-
-OUI:001D61*
- ID_OUI_FROM_DATABASE=BIJ Corporation
-
-OUI:001D5B*
- ID_OUI_FROM_DATABASE=Tecvan Informática Ltda
-
-OUI:001D54*
- ID_OUI_FROM_DATABASE=Sunnic Technology & Merchandise INC.
-
-OUI:001D4A*
- ID_OUI_FROM_DATABASE=Carestream Health, Inc.
-
-OUI:001CE8*
- ID_OUI_FROM_DATABASE=Cummins Inc
-
-OUI:001CE4*
- ID_OUI_FROM_DATABASE=EleSy JSC
+OUI:001D14*
+ ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED
 
 OUI:001CDD*
  ID_OUI_FROM_DATABASE=COWBELL ENGINEERING CO., LTD.
@@ -37142,14 +38234,65 @@ OUI:001CCB*
 OUI:001CC5*
  ID_OUI_FROM_DATABASE=3Com Ltd
 
-OUI:001D0D*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment inc.
+OUI:001CB9*
+ ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD.
 
-OUI:001D14*
- ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED
+OUI:001CAF*
+ ID_OUI_FROM_DATABASE=Plato Networks Inc.
 
-OUI:001D08*
- ID_OUI_FROM_DATABASE=JIANGSU YINHE ELECTRONICS CO., LTD
+OUI:001CB4*
+ ID_OUI_FROM_DATABASE=Iridium Satellite LLC
+
+OUI:001C65*
+ ID_OUI_FROM_DATABASE=JoeScan, Inc.
+
+OUI:001C67*
+ ID_OUI_FROM_DATABASE=Pumpkin Networks, Inc.
+
+OUI:001C66*
+ ID_OUI_FROM_DATABASE=UCAMP CO.,LTD
+
+OUI:001C60*
+ ID_OUI_FROM_DATABASE=CSP Frontier Technologies,Inc.
+
+OUI:001C54*
+ ID_OUI_FROM_DATABASE=Hillstone Networks Inc
+
+OUI:001C59*
+ ID_OUI_FROM_DATABASE=DEVON IT
+
+OUI:001C4F*
+ ID_OUI_FROM_DATABASE=MACAB AB
+
+OUI:001C43*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:001C37*
+ ID_OUI_FROM_DATABASE=Callpod, Inc.
+
+OUI:001C3C*
+ ID_OUI_FROM_DATABASE=Seon Design Inc.
+
+OUI:001DE6*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001DDA*
+ ID_OUI_FROM_DATABASE=Mikroelektronika spol. s r. o.
+
+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
+
+OUI:001DC0*
+ ID_OUI_FROM_DATABASE=Enphase Energy
+
+OUI:001DB9*
+ ID_OUI_FROM_DATABASE=Wellspring Wireless
 
 OUI:001D07*
  ID_OUI_FROM_DATABASE=Shenzhen Sang Fei Consumer Communications Co.,Ltd
@@ -37166,14 +38309,11 @@ OUI:001CEE*
 OUI:001CF5*
  ID_OUI_FROM_DATABASE=Wiseblue Technology Limited
 
-OUI:001CB9*
- ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD.
-
-OUI:001CAF*
- ID_OUI_FROM_DATABASE=Plato Networks Inc.
+OUI:001CE8*
+ ID_OUI_FROM_DATABASE=Cummins Inc
 
-OUI:001CB4*
- ID_OUI_FROM_DATABASE=Iridium Satellite LLC
+OUI:001CE4*
+ ID_OUI_FROM_DATABASE=EleSy JSC
 
 OUI:001C9F*
  ID_OUI_FROM_DATABASE=Razorstream, LLC
@@ -37193,30 +38333,6 @@ OUI:001C87*
 OUI:001C82*
  ID_OUI_FROM_DATABASE=Genew Technologies
 
-OUI:001C1A*
- ID_OUI_FROM_DATABASE=Thomas Instrumentation, Inc
-
-OUI:001C0E*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:001C13*
- ID_OUI_FROM_DATABASE=OPTSYS TECHNOLOGY CO., LTD.
-
-OUI:001C07*
- ID_OUI_FROM_DATABASE=Cwlinux Limited
-
-OUI:001C00*
- ID_OUI_FROM_DATABASE=Entry Point, LLC
-
-OUI:001BF4*
- ID_OUI_FROM_DATABASE=KENWIN INDUSTRIAL(HK) LTD.
-
-OUI:001BEF*
- ID_OUI_FROM_DATABASE=Blossoms Digital Technology Co.,Ltd.
-
-OUI:001BE2*
- ID_OUI_FROM_DATABASE=AhnLab,Inc.
-
 OUI:001C7D*
  ID_OUI_FROM_DATABASE=Excelpoint Manufacturing Pte Ltd
 
@@ -37226,59 +38342,26 @@ OUI:001C73*
 OUI:001C78*
  ID_OUI_FROM_DATABASE=WYPLAY SAS
 
-OUI:001C6C*
- ID_OUI_FROM_DATABASE=Jabil Circuit (Guangzhou) Limited
-
-OUI:001C65*
- ID_OUI_FROM_DATABASE=JoeScan, Inc.
-
-OUI:001C67*
- ID_OUI_FROM_DATABASE=Pumpkin Networks, Inc.
-
-OUI:001C66*
- ID_OUI_FROM_DATABASE=UCAMP CO.,LTD
-
-OUI:001C60*
- ID_OUI_FROM_DATABASE=CSP Frontier Technologies,Inc.
-
-OUI:001C54*
- ID_OUI_FROM_DATABASE=Hillstone Networks Inc
-
-OUI:001C59*
- ID_OUI_FROM_DATABASE=DEVON IT
-
-OUI:001C4F*
- ID_OUI_FROM_DATABASE=MACAB AB
-
-OUI:001C43*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:001C37*
- ID_OUI_FROM_DATABASE=Callpod, Inc.
-
-OUI:001C3C*
- ID_OUI_FROM_DATABASE=Seon Design Inc.
-
-OUI:001C30*
- ID_OUI_FROM_DATABASE=Mode Lighting (UK ) Ltd.
+OUI:001D62*
+ ID_OUI_FROM_DATABASE=InPhase Technologies
 
-OUI:001C2B*
- ID_OUI_FROM_DATABASE=Alertme.com Limited
+OUI:001D61*
+ ID_OUI_FROM_DATABASE=BIJ Corporation
 
-OUI:001C2A*
- ID_OUI_FROM_DATABASE=Envisacor Technologies Inc.
+OUI:001D5B*
+ ID_OUI_FROM_DATABASE=Tecvan Informática Ltda
 
-OUI:001C29*
- ID_OUI_FROM_DATABASE=CORE DIGITAL ELECTRONICS CO., LTD
+OUI:001D54*
+ ID_OUI_FROM_DATABASE=Sunnic Technology & Merchandise INC.
 
-OUI:001C24*
- ID_OUI_FROM_DATABASE=Formosa Wireless Systems Corp.
+OUI:001D4A*
+ ID_OUI_FROM_DATABASE=Carestream Health, Inc.
 
-OUI:001C1F*
- ID_OUI_FROM_DATABASE=Quest Retail Technology Pty Ltd
+OUI:001D45*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001D97*
- ID_OUI_FROM_DATABASE=Alertus Technologies LLC
+OUI:001D3E*
+ ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD
 
 OUI:001D90*
  ID_OUI_FROM_DATABASE=EMCO Flow Systems
@@ -37289,65 +38372,29 @@ OUI:001D84*
 OUI:001D67*
  ID_OUI_FROM_DATABASE=AMEC
 
-OUI:001A93*
- ID_OUI_FROM_DATABASE=ERCO Leuchten GmbH
-
-OUI:001A98*
- ID_OUI_FROM_DATABASE=Asotel Communication Limited Taiwan Branch
-
-OUI:001A8E*
- ID_OUI_FROM_DATABASE=3Way Networks Ltd
-
-OUI:001A7D*
- ID_OUI_FROM_DATABASE=cyber-blue(HK)Ltd
-
-OUI:001A82*
- ID_OUI_FROM_DATABASE=PROBA Building Automation Co.,LTD
-
-OUI:001A7C*
- ID_OUI_FROM_DATABASE=Hirschmann Multimedia B.V.
-
-OUI:001A78*
- ID_OUI_FROM_DATABASE=ubtos
-
-OUI:001A7B*
- ID_OUI_FROM_DATABASE=Teleco, Inc.
-
-OUI:001A71*
- ID_OUI_FROM_DATABASE=Diostech Co., Ltd.
-
-OUI:001A6C*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:001A65*
- ID_OUI_FROM_DATABASE=Seluxit
-
-OUI:001B7D*
- ID_OUI_FROM_DATABASE=CXR Anderson Jacobson
-
-OUI:001B71*
- ID_OUI_FROM_DATABASE=Telular Corp.
+OUI:001D7A*
+ ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc.
 
-OUI:001B6A*
- ID_OUI_FROM_DATABASE=Powerwave Technologies Sweden AB
+OUI:001D74*
+ ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd.
 
-OUI:001B65*
- ID_OUI_FROM_DATABASE=China Gridcom Co., Ltd
+OUI:001DB4*
+ ID_OUI_FROM_DATABASE=KUMHO ENG CO.,LTD
 
-OUI:001B5E*
- ID_OUI_FROM_DATABASE=BPL Limited
+OUI:001DAF*
+ ID_OUI_FROM_DATABASE=Nortel
 
-OUI:001B57*
- ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PRIVATE LIMITED
+OUI:001D9E*
+ ID_OUI_FROM_DATABASE=AXION TECHNOLOGIES
 
-OUI:001B46*
- ID_OUI_FROM_DATABASE=Blueone Technology Co.,Ltd
+OUI:001DA3*
+ ID_OUI_FROM_DATABASE=SabiOso
 
-OUI:001B4B*
- ID_OUI_FROM_DATABASE=SANION Co., Ltd.
+OUI:001D9D*
+ ID_OUI_FROM_DATABASE=ARTJOY INTERNATIONAL LIMITED
 
-OUI:001BAD*
- ID_OUI_FROM_DATABASE=iControl Incorporated
+OUI:001D97*
+ ID_OUI_FROM_DATABASE=Alertus Technologies LLC
 
 OUI:001BA6*
  ID_OUI_FROM_DATABASE=intotech inc.
@@ -37379,11 +38426,32 @@ OUI:001B8A*
 OUI:001B84*
  ID_OUI_FROM_DATABASE=Scan Engineering Telecom
 
-OUI:001BD1*
- ID_OUI_FROM_DATABASE=SOGESTMATIC
+OUI:001B7D*
+ ID_OUI_FROM_DATABASE=CXR Anderson Jacobson
 
-OUI:001BD6*
- ID_OUI_FROM_DATABASE=Kelvin Hughes Ltd
+OUI:001B71*
+ ID_OUI_FROM_DATABASE=Telular Corp.
+
+OUI:001B6A*
+ ID_OUI_FROM_DATABASE=Powerwave Technologies Sweden AB
+
+OUI:001B65*
+ ID_OUI_FROM_DATABASE=China Gridcom Co., Ltd
+
+OUI:001B5E*
+ ID_OUI_FROM_DATABASE=BPL Limited
+
+OUI:001B57*
+ ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PRIVATE LIMITED
+
+OUI:001B46*
+ ID_OUI_FROM_DATABASE=Blueone Technology Co.,Ltd
+
+OUI:001B4B*
+ ID_OUI_FROM_DATABASE=SANION Co., Ltd.
+
+OUI:001B3F*
+ ID_OUI_FROM_DATABASE=ProCurve Networking by HP
 
 OUI:001BCF*
  ID_OUI_FROM_DATABASE=Dataupia Corporation
@@ -37403,38 +38471,8 @@ OUI:001BBE*
 OUI:001BB4*
  ID_OUI_FROM_DATABASE=Airvod Limited
 
-OUI:001BB9*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co.
-
-OUI:001B14*
- ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory
-
-OUI:001B0D*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:001B06*
- ID_OUI_FROM_DATABASE=Ateliers R. LAUMONIER
-
-OUI:001B08*
- ID_OUI_FROM_DATABASE=Danfoss Drives A/S
-
-OUI:001B01*
- ID_OUI_FROM_DATABASE=Applied Radio Technologies
-
-OUI:001AF5*
- ID_OUI_FROM_DATABASE=PENTAONE. CO., LTD.
-
-OUI:001AFA*
- ID_OUI_FROM_DATABASE=Welch Allyn, Inc.
-
-OUI:001AF0*
- ID_OUI_FROM_DATABASE=Alcatel - IPD
-
-OUI:001AE4*
- ID_OUI_FROM_DATABASE=Medicis Technologies Corporation
-
-OUI:001ADD*
- ID_OUI_FROM_DATABASE=PePWave Ltd
+OUI:001BAD*
+ ID_OUI_FROM_DATABASE=iControl Incorporated
 
 OUI:001AD1*
  ID_OUI_FROM_DATABASE=FARGO CO., LTD.
@@ -37457,32 +38495,59 @@ OUI:001ABB*
 OUI:001AC0*
  ID_OUI_FROM_DATABASE=JOYBIEN TECHNOLOGIES CO., LTD.
 
-OUI:001A60*
- ID_OUI_FROM_DATABASE=Wave Electronics Co.,Ltd.
+OUI:001AB4*
+ ID_OUI_FROM_DATABASE=FFEI Ltd.
 
-OUI:001A55*
- ID_OUI_FROM_DATABASE=ACA-Digital Corporation
+OUI:001AAF*
+ ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY
 
-OUI:001A5A*
- ID_OUI_FROM_DATABASE=Korea Electric Power Data Network  (KDN) Co., Ltd
+OUI:001C07*
+ ID_OUI_FROM_DATABASE=Cwlinux Limited
 
-OUI:001A4E*
- ID_OUI_FROM_DATABASE=NTI AG / LinMot
+OUI:001C00*
+ ID_OUI_FROM_DATABASE=Entry Point, LLC
 
-OUI:001A53*
- ID_OUI_FROM_DATABASE=Zylaya
+OUI:001BF4*
+ ID_OUI_FROM_DATABASE=KENWIN INDUSTRIAL(HK) LTD.
 
-OUI:001A42*
- ID_OUI_FROM_DATABASE=Techcity Technology co., Ltd.
+OUI:001BEF*
+ ID_OUI_FROM_DATABASE=Blossoms Digital Technology Co.,Ltd.
 
-OUI:001A47*
- ID_OUI_FROM_DATABASE=Agami Systems, Inc.
+OUI:001BE2*
+ ID_OUI_FROM_DATABASE=AhnLab,Inc.
 
-OUI:001A3B*
- ID_OUI_FROM_DATABASE=Doah Elecom Inc.
+OUI:001BD1*
+ ID_OUI_FROM_DATABASE=SOGESTMATIC
 
-OUI:001B3F*
- ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:001BD6*
+ ID_OUI_FROM_DATABASE=Kelvin Hughes Ltd
+
+OUI:001C30*
+ ID_OUI_FROM_DATABASE=Mode Lighting (UK ) Ltd.
+
+OUI:001C2B*
+ ID_OUI_FROM_DATABASE=Alertme.com Limited
+
+OUI:001C2A*
+ ID_OUI_FROM_DATABASE=Envisacor Technologies Inc.
+
+OUI:001C29*
+ ID_OUI_FROM_DATABASE=CORE DIGITAL ELECTRONICS CO., LTD
+
+OUI:001C24*
+ ID_OUI_FROM_DATABASE=Formosa Wireless Systems Corp.
+
+OUI:001C1F*
+ ID_OUI_FROM_DATABASE=Quest Retail Technology Pty Ltd
+
+OUI:001C1A*
+ ID_OUI_FROM_DATABASE=Thomas Instrumentation, Inc
+
+OUI:001C0E*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001C13*
+ ID_OUI_FROM_DATABASE=OPTSYS TECHNOLOGY CO., LTD.
 
 OUI:001B3A*
  ID_OUI_FROM_DATABASE=SIMS Corp.
@@ -37502,11 +38567,11 @@ OUI:001B20*
 OUI:001B19*
  ID_OUI_FROM_DATABASE=IEEE I&M Society TC9
 
-OUI:001AB4*
- ID_OUI_FROM_DATABASE=FFEI Ltd.
+OUI:001B14*
+ ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory
 
-OUI:001AAF*
- ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY
+OUI:001B0D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:001AA8*
  ID_OUI_FROM_DATABASE=Mamiya Digital Imaging Co., Ltd.
@@ -37517,8 +38582,38 @@ OUI:001A9F*
 OUI:001AA6*
  ID_OUI_FROM_DATABASE=Telefunken Radio Communication Systems GmbH &CO.KG
 
-OUI:00193F*
- ID_OUI_FROM_DATABASE=RDI technology(Shenzhen) Co.,LTD
+OUI:001A93*
+ ID_OUI_FROM_DATABASE=ERCO Leuchten GmbH
+
+OUI:001A98*
+ ID_OUI_FROM_DATABASE=Asotel Communication Limited Taiwan Branch
+
+OUI:001A8E*
+ ID_OUI_FROM_DATABASE=3Way Networks Ltd
+
+OUI:001B06*
+ ID_OUI_FROM_DATABASE=Ateliers R. LAUMONIER
+
+OUI:001B08*
+ ID_OUI_FROM_DATABASE=Danfoss Drives A/S
+
+OUI:001B01*
+ ID_OUI_FROM_DATABASE=Applied Radio Technologies
+
+OUI:001AF5*
+ ID_OUI_FROM_DATABASE=PENTAONE. CO., LTD.
+
+OUI:001AFA*
+ ID_OUI_FROM_DATABASE=Welch Allyn, Inc.
+
+OUI:001AF0*
+ ID_OUI_FROM_DATABASE=Alcatel - IPD
+
+OUI:001AE4*
+ ID_OUI_FROM_DATABASE=Medicis Technologies Corporation
+
+OUI:001ADD*
+ ID_OUI_FROM_DATABASE=PePWave Ltd
 
 OUI:001933*
  ID_OUI_FROM_DATABASE=Strix Systems, Inc.
@@ -37529,9 +38624,6 @@ OUI:001938*
 OUI:00192D*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:001921*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co.
-
 OUI:001926*
  ID_OUI_FROM_DATABASE=BitsGen Co., Ltd.
 
@@ -37550,12 +38642,6 @@ OUI:001915*
 OUI:00191A*
  ID_OUI_FROM_DATABASE=IRLINK
 
-OUI:001993*
- ID_OUI_FROM_DATABASE=Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea
-
-OUI:001998*
- ID_OUI_FROM_DATABASE=SATO CORPORATION
-
 OUI:00199D*
  ID_OUI_FROM_DATABASE=VIZIO, Inc.
 
@@ -37592,11 +38678,59 @@ OUI:001946*
 OUI:001944*
  ID_OUI_FROM_DATABASE=Fossil Partners, L.P.
 
-OUI:001A2F*
+OUI:00193F*
+ ID_OUI_FROM_DATABASE=RDI technology(Shenzhen) Co.,LTD
+
+OUI:001A7D*
+ ID_OUI_FROM_DATABASE=cyber-blue(HK)Ltd
+
+OUI:001A82*
+ ID_OUI_FROM_DATABASE=PROBA Building Automation Co.,LTD
+
+OUI:001A7C*
+ ID_OUI_FROM_DATABASE=Hirschmann Multimedia B.V.
+
+OUI:001A78*
+ ID_OUI_FROM_DATABASE=ubtos
+
+OUI:001A7B*
+ ID_OUI_FROM_DATABASE=Teleco, Inc.
+
+OUI:001A71*
+ ID_OUI_FROM_DATABASE=Diostech Co., Ltd.
+
+OUI:001A6C*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001A34*
- ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+OUI:001A65*
+ ID_OUI_FROM_DATABASE=Seluxit
+
+OUI:001A60*
+ ID_OUI_FROM_DATABASE=Wave Electronics Co.,Ltd.
+
+OUI:001A55*
+ ID_OUI_FROM_DATABASE=ACA-Digital Corporation
+
+OUI:001A5A*
+ ID_OUI_FROM_DATABASE=Korea Electric Power Data Network  (KDN) Co., Ltd
+
+OUI:001A4E*
+ ID_OUI_FROM_DATABASE=NTI AG / LinMot
+
+OUI:001A53*
+ ID_OUI_FROM_DATABASE=Zylaya
+
+OUI:001A42*
+ ID_OUI_FROM_DATABASE=Techcity Technology co., Ltd.
+
+OUI:001A47*
+ ID_OUI_FROM_DATABASE=Agami Systems, Inc.
+
+OUI:001A3B*
+ ID_OUI_FROM_DATABASE=Doah Elecom Inc.
+
+OUI:001A2F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:001A36*
  ID_OUI_FROM_DATABASE=Aipermon GmbH & Co. KG
@@ -37604,6 +38738,33 @@ OUI:001A36*
 OUI:001A25*
  ID_OUI_FROM_DATABASE=DELTA DORE
 
+OUI:0019C3*
+ ID_OUI_FROM_DATABASE=Qualitrol
+
+OUI:0019BE*
+ ID_OUI_FROM_DATABASE=Altai Technologies Limited
+
+OUI:0019BC*
+ ID_OUI_FROM_DATABASE=ELECTRO CHANCE SRL
+
+OUI:0019A4*
+ ID_OUI_FROM_DATABASE=Austar Technology (hang zhou) Co.,Ltd
+
+OUI:0019A9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:0019AB*
+ ID_OUI_FROM_DATABASE=Raycom CO ., LTD
+
+OUI:0019B0*
+ ID_OUI_FROM_DATABASE=HanYang System
+
+OUI:001993*
+ ID_OUI_FROM_DATABASE=Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea
+
+OUI:001998*
+ ID_OUI_FROM_DATABASE=SATO CORPORATION
+
 OUI:001A17*
  ID_OUI_FROM_DATABASE=Teak Technologies, Inc.
 
@@ -37619,35 +38780,11 @@ OUI:001A0B*
 OUI:001A06*
  ID_OUI_FROM_DATABASE=OpVista, Inc.
 
-OUI:0018CD*
- ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd
-
-OUI:0018D2*
- ID_OUI_FROM_DATABASE=High-Gain Antennas LLC
-
-OUI:0018D7*
- ID_OUI_FROM_DATABASE=Javad Navigation Systems Inc.
-
-OUI:0018D9*
- ID_OUI_FROM_DATABASE=Santosha Internatonal, Inc
-
-OUI:0018C1*
- ID_OUI_FROM_DATABASE=Almitec Informática e Comércio
-
-OUI:0018C8*
- ID_OUI_FROM_DATABASE=ISONAS Inc.
-
-OUI:0018BC*
- ID_OUI_FROM_DATABASE=ZAO NVP Bolid
-
-OUI:0018B5*
- ID_OUI_FROM_DATABASE=Magna Carta
-
-OUI:0018B0*
- ID_OUI_FROM_DATABASE=Nortel
+OUI:0019FA*
+ ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD.
 
-OUI:0018AE*
- ID_OUI_FROM_DATABASE=TVT CO.,LTD
+OUI:0019FF*
+ ID_OUI_FROM_DATABASE=Finnzymes
 
 OUI:001902*
  ID_OUI_FROM_DATABASE=Cambridge Consultants Ltd
@@ -37670,59 +38807,11 @@ OUI:0018EC*
 OUI:0018E5*
  ID_OUI_FROM_DATABASE=Adhoco AG
 
-OUI:0018A2*
- ID_OUI_FROM_DATABASE=XIP Technology AB
-
-OUI:0018A9*
- ID_OUI_FROM_DATABASE=Ethernet Direct Corporation
-
-OUI:00189D*
- ID_OUI_FROM_DATABASE=Navcast Inc.
-
-OUI:001893*
- ID_OUI_FROM_DATABASE=SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD
-
-OUI:001898*
- ID_OUI_FROM_DATABASE=KINGSTATE ELECTRONICS CORPORATION
-
-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.
-
-OUI:0019C8*
- ID_OUI_FROM_DATABASE=AnyDATA Corporation
-
-OUI:0019C3*
- ID_OUI_FROM_DATABASE=Qualitrol
-
-OUI:0019BE*
- ID_OUI_FROM_DATABASE=Altai Technologies Limited
-
-OUI:0019BC*
- ID_OUI_FROM_DATABASE=ELECTRO CHANCE SRL
-
-OUI:0019A4*
- ID_OUI_FROM_DATABASE=Austar Technology (hang zhou) Co.,Ltd
-
-OUI:0019A9*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:0019AB*
- ID_OUI_FROM_DATABASE=Raycom CO ., LTD
-
-OUI:0019B0*
- ID_OUI_FROM_DATABASE=HanYang System
-
-OUI:0019FA*
- ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD.
+OUI:0018CD*
+ ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd
 
-OUI:0019FF*
- ID_OUI_FROM_DATABASE=Finnzymes
+OUI:0018D2*
+ ID_OUI_FROM_DATABASE=High-Gain Antennas LLC
 
 OUI:0019EC*
  ID_OUI_FROM_DATABASE=Sagamore Systems, Inc.
@@ -37748,8 +38837,8 @@ OUI:0019D4*
 OUI:0019D9*
  ID_OUI_FROM_DATABASE=Zeutschel GmbH
 
-OUI:001823*
- ID_OUI_FROM_DATABASE=Delta Electronics, Inc.
+OUI:0019C8*
+ ID_OUI_FROM_DATABASE=AnyDATA Corporation
 
 OUI:001817*
  ID_OUI_FROM_DATABASE=D. E. Shaw Research, LLC
@@ -37769,11 +38858,14 @@ OUI:00180B*
 OUI:001805*
  ID_OUI_FROM_DATABASE=Beijing InHand Networking Technology Co.,Ltd.
 
-OUI:0017B8*
- ID_OUI_FROM_DATABASE=NOVATRON CO., LTD.
+OUI:0017F4*
+ ID_OUI_FROM_DATABASE=ZERON ALLIANCE
 
-OUI:0017BD*
- ID_OUI_FROM_DATABASE=Tibetsystem
+OUI:0017F9*
+ ID_OUI_FROM_DATABASE=Forcom Sp. z o.o.
+
+OUI:001800*
+ ID_OUI_FROM_DATABASE=UNIGRAND LTD
 
 OUI:0017B1*
  ID_OUI_FROM_DATABASE=ACIST Medical Systems, Inc.
@@ -37793,35 +38885,41 @@ OUI:0017A0*
 OUI:00179B*
  ID_OUI_FROM_DATABASE=Chant Sincere CO., LTD.
 
-OUI:00170F*
+OUI:00178F*
+ ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD.
+
+OUI:001794*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001705*
- ID_OUI_FROM_DATABASE=Methode Electronics
+OUI:00178D*
+ ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc.
 
-OUI:00170A*
- ID_OUI_FROM_DATABASE=INEW DIGITAL COMPANY
+OUI:0018D9*
+ ID_OUI_FROM_DATABASE=Santosha Internatonal, Inc
 
-OUI:0016F9*
- ID_OUI_FROM_DATABASE=CETRTA POT, d.o.o., Kranj
+OUI:0018C1*
+ ID_OUI_FROM_DATABASE=Almitec Informática e Comércio
 
-OUI:0016F2*
- ID_OUI_FROM_DATABASE=Dmobile System Co., Ltd.
+OUI:0018C8*
+ ID_OUI_FROM_DATABASE=ISONAS Inc.
 
-OUI:0016F7*
- ID_OUI_FROM_DATABASE=L-3 Communications, Aviation Recorders
+OUI:0018BC*
+ ID_OUI_FROM_DATABASE=ZAO NVP Bolid
 
-OUI:0016E6*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+OUI:0018B5*
+ ID_OUI_FROM_DATABASE=Magna Carta
 
-OUI:00178F*
- ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD.
+OUI:0018B0*
+ ID_OUI_FROM_DATABASE=Nortel
 
-OUI:001794*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0018AE*
+ ID_OUI_FROM_DATABASE=TVT CO.,LTD
 
-OUI:00178D*
- ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc.
+OUI:0018A2*
+ ID_OUI_FROM_DATABASE=XIP Technology AB
+
+OUI:0018A9*
+ ID_OUI_FROM_DATABASE=Ethernet Direct Corporation
 
 OUI:00177C*
  ID_OUI_FROM_DATABASE=Smartlink Network Systems Limited
@@ -37850,6 +38948,24 @@ OUI:001765*
 OUI:001767*
  ID_OUI_FROM_DATABASE=Earforce AS
 
+OUI:001759*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001880*
+ ID_OUI_FROM_DATABASE=Maxim Integrated Products
+
+OUI:00186D*
+ ID_OUI_FROM_DATABASE=Zhenjiang Sapphire Electronic Industry CO.
+
+OUI:001872*
+ ID_OUI_FROM_DATABASE=Expertise Engineering
+
+OUI:001874*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001879*
+ ID_OUI_FROM_DATABASE=dSys
+
 OUI:00185A*
  ID_OUI_FROM_DATABASE=uControl, Inc.
 
@@ -37889,8 +39005,8 @@ OUI:00182A*
 OUI:001836*
  ID_OUI_FROM_DATABASE=Reliance Electric Limited
 
-OUI:001759*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001823*
+ ID_OUI_FROM_DATABASE=Delta Electronics, Inc.
 
 OUI:001754*
  ID_OUI_FROM_DATABASE=Arkino HiTOP Corporation Limited
@@ -37916,30 +39032,6 @@ OUI:00173A*
 OUI:00172E*
  ID_OUI_FROM_DATABASE=FXC Inc.
 
-OUI:001727*
- ID_OUI_FROM_DATABASE=Thermo Ramsey Italia s.r.l.
-
-OUI:001722*
- ID_OUI_FROM_DATABASE=Hanazeder Electronic GmbH
-
-OUI:00171B*
- ID_OUI_FROM_DATABASE=Innovation Lab Corp.
-
-OUI:001714*
- ID_OUI_FROM_DATABASE=BR Controls Nederland bv
-
-OUI:001716*
- ID_OUI_FROM_DATABASE=Qno Technology Inc.
-
-OUI:0017F4*
- ID_OUI_FROM_DATABASE=ZERON ALLIANCE
-
-OUI:0017F9*
- ID_OUI_FROM_DATABASE=Forcom Sp. z o.o.
-
-OUI:001800*
- ID_OUI_FROM_DATABASE=UNIGRAND LTD
-
 OUI:0017ED*
  ID_OUI_FROM_DATABASE=WooJooIT Ltd.
 
@@ -37961,23 +39053,29 @@ OUI:0017D0*
 OUI:0017C4*
  ID_OUI_FROM_DATABASE=Quanta Microsystems, INC.
 
-OUI:001880*
- ID_OUI_FROM_DATABASE=Maxim Integrated Products
+OUI:0017B8*
+ ID_OUI_FROM_DATABASE=NOVATRON CO., LTD.
 
-OUI:00186D*
- ID_OUI_FROM_DATABASE=Zhenjiang Sapphire Electronic Industry CO.
+OUI:0017BD*
+ ID_OUI_FROM_DATABASE=Tibetsystem
 
-OUI:001872*
- ID_OUI_FROM_DATABASE=Expertise Engineering
+OUI:00189D*
+ ID_OUI_FROM_DATABASE=Navcast Inc.
 
-OUI:001874*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001893*
+ ID_OUI_FROM_DATABASE=SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD
 
-OUI:001879*
- ID_OUI_FROM_DATABASE=dSys
+OUI:001898*
+ ID_OUI_FROM_DATABASE=KINGSTATE ELECTRONICS CORPORATION
 
-OUI:001686*
- ID_OUI_FROM_DATABASE=Karl Storz Imaging
+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.
 
 OUI:00167F*
  ID_OUI_FROM_DATABASE=Bluebird Soft Inc.
@@ -38009,120 +39107,12 @@ OUI:001666*
 OUI:00165F*
  ID_OUI_FROM_DATABASE=Fairmount Automation
 
-OUI:0016AA*
- ID_OUI_FROM_DATABASE=Kei Communication Technology Inc.
-
-OUI:0016AF*
- ID_OUI_FROM_DATABASE=Shenzhen Union Networks Equipment Co.,Ltd.
-
-OUI:0016A5*
- ID_OUI_FROM_DATABASE=Tandberg Storage ASA
-
-OUI:001699*
- ID_OUI_FROM_DATABASE=Tonic DVB Marketing Ltd
-
-OUI:0016A0*
- ID_OUI_FROM_DATABASE=Auto-Maskin
-
-OUI:001692*
- ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc.
-
-OUI:001694*
- ID_OUI_FROM_DATABASE=Sennheiser Communications A/S
-
-OUI:00168D*
- ID_OUI_FROM_DATABASE=KORWIN CO., Ltd.
-
 OUI:00165A*
  ID_OUI_FROM_DATABASE=Harman Specialty Group
 
 OUI:001653*
  ID_OUI_FROM_DATABASE=LEGO System A/S IE Electronics Division
 
-OUI:00164C*
- ID_OUI_FROM_DATABASE=PLANET INT Co., Ltd
-
-OUI:001647*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:001642*
- ID_OUI_FROM_DATABASE=Pangolin
-
-OUI:00163D*
- ID_OUI_FROM_DATABASE=Tsinghua Tongfang Legend Silicon Tech. Co., Ltd.
-
-OUI:001636*
- ID_OUI_FROM_DATABASE=Quanta Computer Inc.
-
-OUI:001631*
- ID_OUI_FROM_DATABASE=Xteam
-
-OUI:00162F*
- ID_OUI_FROM_DATABASE=Geutebrück GmbH
-
-OUI:001630*
- ID_OUI_FROM_DATABASE=Vativ Technologies
-
-OUI:0015F5*
- ID_OUI_FROM_DATABASE=Sustainable Energy Systems
-
-OUI:0015F4*
- ID_OUI_FROM_DATABASE=Eventide
-
-OUI:0015EE*
- ID_OUI_FROM_DATABASE=Omnex Control Systems
-
-OUI:0015F3*
- ID_OUI_FROM_DATABASE=PELTOR AB
-
-OUI:0015E7*
- ID_OUI_FROM_DATABASE=Quantec Tontechnik
-
-OUI:0015E2*
- ID_OUI_FROM_DATABASE=Dr.Ing. Herbert Knauer GmbH
-
-OUI:0015DD*
- ID_OUI_FROM_DATABASE=IP Control Systems Ltd.
-
-OUI:0015D8*
- ID_OUI_FROM_DATABASE=Interlink Electronics
-
-OUI:0015CA*
- ID_OUI_FROM_DATABASE=TeraRecon, Inc.
-
-OUI:001598*
- ID_OUI_FROM_DATABASE=Kolektor group
-
-OUI:001593*
- ID_OUI_FROM_DATABASE=U4EA Technologies Inc.
-
-OUI:00158C*
- ID_OUI_FROM_DATABASE=Liab ApS
-
-OUI:001586*
- ID_OUI_FROM_DATABASE=Xiamen Overseas Chinese Electronic Co., Ltd.
-
-OUI:001585*
- ID_OUI_FROM_DATABASE=Aonvision Technolopy Corp.
-
-OUI:001587*
- ID_OUI_FROM_DATABASE=Takenaka Seisakusho Co.,Ltd
-
-OUI:001580*
- ID_OUI_FROM_DATABASE=U-WAY CORPORATION
-
-OUI:00157B*
- ID_OUI_FROM_DATABASE=Leuze electronic GmbH + Co. KG
-
-OUI:001576*
- ID_OUI_FROM_DATABASE=LABiTec - Labor Biomedical Technologies GmbH
-
-OUI:00156A*
- ID_OUI_FROM_DATABASE=DG2L Technologies Pvt. Ltd.
-
-OUI:00156F*
- ID_OUI_FROM_DATABASE=Xiranet Communications GmbH
-
 OUI:0016DF*
  ID_OUI_FROM_DATABASE=Lundinova AB
 
@@ -38147,6 +39137,12 @@ OUI:0016C2*
 OUI:0016BB*
  ID_OUI_FROM_DATABASE=Law-Chain Computer Technology Co Ltd
 
+OUI:0016AA*
+ ID_OUI_FROM_DATABASE=Kei Communication Technology Inc.
+
+OUI:0016AF*
+ ID_OUI_FROM_DATABASE=Shenzhen Union Networks Equipment Co.,Ltd.
+
 OUI:00162A*
  ID_OUI_FROM_DATABASE=Antik computers & communications s.r.o.
 
@@ -38168,26 +39164,95 @@ OUI:001606*
 OUI:0015FA*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001563*
+OUI:0015F5*
+ ID_OUI_FROM_DATABASE=Sustainable Energy Systems
+
+OUI:0015F4*
+ ID_OUI_FROM_DATABASE=Eventide
+
+OUI:001705*
+ ID_OUI_FROM_DATABASE=Methode Electronics
+
+OUI:00170A*
+ ID_OUI_FROM_DATABASE=INEW DIGITAL COMPANY
+
+OUI:0016F9*
+ ID_OUI_FROM_DATABASE=CETRTA POT, d.o.o., Kranj
+
+OUI:0016F2*
+ ID_OUI_FROM_DATABASE=Dmobile System Co., Ltd.
+
+OUI:0016F7*
+ ID_OUI_FROM_DATABASE=L-3 Communications, Aviation Recorders
+
+OUI:0016E6*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
+OUI:00164C*
+ ID_OUI_FROM_DATABASE=PLANET INT Co., Ltd
+
+OUI:001647*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001557*
- ID_OUI_FROM_DATABASE=Olivetti
+OUI:001642*
+ ID_OUI_FROM_DATABASE=Pangolin
 
-OUI:00155C*
- ID_OUI_FROM_DATABASE=Dresser Wayne
+OUI:00163D*
+ ID_OUI_FROM_DATABASE=Tsinghua Tongfang Legend Silicon Tech. Co., Ltd.
 
-OUI:00154B*
- ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd
+OUI:001636*
+ ID_OUI_FROM_DATABASE=Quanta Computer Inc.
 
-OUI:001550*
- ID_OUI_FROM_DATABASE=Nits Technology Inc
+OUI:001631*
+ ID_OUI_FROM_DATABASE=Xteam
+
+OUI:00162F*
+ ID_OUI_FROM_DATABASE=Geutebrück GmbH
+
+OUI:001630*
+ ID_OUI_FROM_DATABASE=Vativ Technologies
+
+OUI:0016A5*
+ ID_OUI_FROM_DATABASE=Tandberg Storage ASA
+
+OUI:001699*
+ ID_OUI_FROM_DATABASE=Tonic DVB Marketing Ltd
+
+OUI:0016A0*
+ ID_OUI_FROM_DATABASE=Auto-Maskin
+
+OUI:001692*
+ ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc.
+
+OUI:001694*
+ ID_OUI_FROM_DATABASE=Sennheiser Communications A/S
+
+OUI:00168D*
+ ID_OUI_FROM_DATABASE=KORWIN CO., Ltd.
+
+OUI:001686*
+ ID_OUI_FROM_DATABASE=Karl Storz Imaging
+
+OUI:0015EE*
+ ID_OUI_FROM_DATABASE=Omnex Control Systems
+
+OUI:0015F3*
+ ID_OUI_FROM_DATABASE=PELTOR AB
+
+OUI:0015E7*
+ ID_OUI_FROM_DATABASE=Quantec Tontechnik
+
+OUI:0015E2*
+ ID_OUI_FROM_DATABASE=Dr.Ing. Herbert Knauer GmbH
 
-OUI:001545*
- ID_OUI_FROM_DATABASE=SEECODE Co., Ltd.
+OUI:0015DD*
+ ID_OUI_FROM_DATABASE=IP Control Systems Ltd.
 
-OUI:00153E*
- ID_OUI_FROM_DATABASE=Q-Matic Sweden AB
+OUI:0015D8*
+ ID_OUI_FROM_DATABASE=Interlink Electronics
+
+OUI:0015CA*
+ ID_OUI_FROM_DATABASE=TeraRecon, Inc.
 
 OUI:0015BC*
  ID_OUI_FROM_DATABASE=Develco
@@ -38207,6 +39272,51 @@ OUI:0015A6*
 OUI:00159F*
  ID_OUI_FROM_DATABASE=Terascala, Inc.
 
+OUI:001598*
+ ID_OUI_FROM_DATABASE=Kolektor group
+
+OUI:001727*
+ ID_OUI_FROM_DATABASE=Thermo Ramsey Italia s.r.l.
+
+OUI:001722*
+ ID_OUI_FROM_DATABASE=Hanazeder Electronic GmbH
+
+OUI:00171B*
+ ID_OUI_FROM_DATABASE=Innovation Lab Corp.
+
+OUI:001714*
+ ID_OUI_FROM_DATABASE=BR Controls Nederland bv
+
+OUI:001716*
+ ID_OUI_FROM_DATABASE=Qno Technology Inc.
+
+OUI:00170F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:0014AA*
+ ID_OUI_FROM_DATABASE=Ashly Audio, Inc.
+
+OUI:00149D*
+ ID_OUI_FROM_DATABASE=Sound ID Inc.
+
+OUI:001498*
+ ID_OUI_FROM_DATABASE=Viking Design Technology
+
+OUI:00148A*
+ ID_OUI_FROM_DATABASE=Elin Ebg Traction Gmbh
+
+OUI:001491*
+ ID_OUI_FROM_DATABASE=Daniels Electronics Ltd. dbo Codan Rado Communications
+
+OUI:001485*
+ ID_OUI_FROM_DATABASE=Giga-Byte
+
+OUI:00147E*
+ ID_OUI_FROM_DATABASE=InnerWireless
+
+OUI:001478*
+ ID_OUI_FROM_DATABASE=ShenZhen TP-LINK Technologies Co., Ltd.
+
 OUI:001532*
  ID_OUI_FROM_DATABASE=Consumer Technologies Group, LLC
 
@@ -38237,8 +39347,11 @@ OUI:001515*
 OUI:001510*
  ID_OUI_FROM_DATABASE=Techsphere Co., Ltd
 
-OUI:001453*
- ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES CO.,LTD
+OUI:001502*
+ ID_OUI_FROM_DATABASE=BETA tech
+
+OUI:001509*
+ ID_OUI_FROM_DATABASE=Plus Technology Co., Ltd
 
 OUI:00144E*
  ID_OUI_FROM_DATABASE=SRISA
@@ -38261,65 +39374,59 @@ OUI:00143B*
 OUI:001436*
  ID_OUI_FROM_DATABASE=Qwerty Elektronik AB
 
-OUI:00142A*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co., Ltd
-
-OUI:0014AB*
- ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd.
-
-OUI:0014B0*
- ID_OUI_FROM_DATABASE=Naeil Community
+OUI:001423*
+ ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM
 
-OUI:0014B4*
- ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd
+OUI:001593*
+ ID_OUI_FROM_DATABASE=U4EA Technologies Inc.
 
-OUI:0014A9*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00158C*
+ ID_OUI_FROM_DATABASE=Liab ApS
 
-OUI:0014AA*
- ID_OUI_FROM_DATABASE=Ashly Audio, Inc.
+OUI:001586*
+ ID_OUI_FROM_DATABASE=Xiamen Overseas Chinese Electronic Co., Ltd.
 
-OUI:00149D*
- ID_OUI_FROM_DATABASE=Sound ID Inc.
+OUI:001585*
+ ID_OUI_FROM_DATABASE=Aonvision Technolopy Corp.
 
-OUI:001498*
- ID_OUI_FROM_DATABASE=Viking Design Technology
+OUI:001587*
+ ID_OUI_FROM_DATABASE=Takenaka Seisakusho Co.,Ltd
 
-OUI:00148A*
- ID_OUI_FROM_DATABASE=Elin Ebg Traction Gmbh
+OUI:001580*
+ ID_OUI_FROM_DATABASE=U-WAY CORPORATION
 
-OUI:001491*
- ID_OUI_FROM_DATABASE=Daniels Electronics Ltd. dbo Codan Rado Communications
+OUI:00157B*
+ ID_OUI_FROM_DATABASE=Leuze electronic GmbH + Co. KG
 
-OUI:001485*
- ID_OUI_FROM_DATABASE=Giga-Byte
+OUI:001576*
+ ID_OUI_FROM_DATABASE=LABiTec - Labor Biomedical Technologies GmbH
 
-OUI:001479*
- ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd.
+OUI:00156A*
+ ID_OUI_FROM_DATABASE=DG2L Technologies Pvt. Ltd.
 
-OUI:00147E*
- ID_OUI_FROM_DATABASE=InnerWireless
+OUI:00156F*
+ ID_OUI_FROM_DATABASE=Xiranet Communications GmbH
 
-OUI:001478*
- ID_OUI_FROM_DATABASE=ShenZhen TP-LINK Technologies Co., Ltd.
+OUI:001563*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001477*
- ID_OUI_FROM_DATABASE=Nertec  Inc.
+OUI:0014FD*
+ ID_OUI_FROM_DATABASE=Thecus Technology Corp.
 
-OUI:001472*
- ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard Group
+OUI:0014EF*
+ ID_OUI_FROM_DATABASE=TZero Technologies, Inc.
 
-OUI:001466*
- ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH
+OUI:0014F1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:00146B*
- ID_OUI_FROM_DATABASE=Anagran, Inc.
+OUI:0014F0*
+ ID_OUI_FROM_DATABASE=Business Security OL AB
 
-OUI:00145F*
- ID_OUI_FROM_DATABASE=ADITEC CO. LTD
+OUI:0014EA*
+ ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.)
 
-OUI:001458*
- ID_OUI_FROM_DATABASE=HS Automatic ApS
+OUI:0014E5*
+ ID_OUI_FROM_DATABASE=Alticast
 
 OUI:0014E6*
  ID_OUI_FROM_DATABASE=AIM Infrarotmodule GmbH
@@ -38348,56 +39455,56 @@ OUI:0014BA*
 OUI:0014B5*
  ID_OUI_FROM_DATABASE=PHYSIOMETRIX,INC
 
-OUI:0013C7*
- ID_OUI_FROM_DATABASE=IONOS Co.,Ltd.
+OUI:0014AB*
+ ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd.
 
-OUI:0013C0*
- ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda.
+OUI:0014B0*
+ ID_OUI_FROM_DATABASE=Naeil Community
 
-OUI:0013B6*
- ID_OUI_FROM_DATABASE=Sling Media, Inc.
+OUI:0014B4*
+ ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd
 
-OUI:0013AF*
- ID_OUI_FROM_DATABASE=NUMA Technology,Inc.
+OUI:0014A9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:0013B0*
- ID_OUI_FROM_DATABASE=Jablotron
+OUI:001557*
+ ID_OUI_FROM_DATABASE=Olivetti
 
-OUI:0013AA*
- ID_OUI_FROM_DATABASE=ALS  & TEC Ltd.
+OUI:00155C*
+ ID_OUI_FROM_DATABASE=Dresser Wayne
 
-OUI:0013A3*
- ID_OUI_FROM_DATABASE=Siemens Com CPE Devices
+OUI:00154B*
+ ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd
 
-OUI:00139E*
- ID_OUI_FROM_DATABASE=Ciara Technologies Inc.
+OUI:001550*
+ ID_OUI_FROM_DATABASE=Nits Technology Inc
 
-OUI:001502*
- ID_OUI_FROM_DATABASE=BETA tech
+OUI:001545*
+ ID_OUI_FROM_DATABASE=SEECODE Co., Ltd.
 
-OUI:001509*
- ID_OUI_FROM_DATABASE=Plus Technology Co., Ltd
+OUI:00153E*
+ ID_OUI_FROM_DATABASE=Q-Matic Sweden AB
 
-OUI:0014FD*
- ID_OUI_FROM_DATABASE=Thecus Technology Corp.
+OUI:001477*
+ ID_OUI_FROM_DATABASE=Nertec  Inc.
 
-OUI:0014EF*
- ID_OUI_FROM_DATABASE=TZero Technologies, Inc.
+OUI:001472*
+ ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard Group
 
-OUI:0014F1*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001466*
+ ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH
 
-OUI:0014F0*
- ID_OUI_FROM_DATABASE=Business Security OL AB
+OUI:00146B*
+ ID_OUI_FROM_DATABASE=Anagran, Inc.
 
-OUI:0014EA*
- ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.)
+OUI:00145F*
+ ID_OUI_FROM_DATABASE=ADITEC CO. LTD
 
-OUI:0014E5*
- ID_OUI_FROM_DATABASE=Alticast
+OUI:001458*
+ ID_OUI_FROM_DATABASE=HS Automatic ApS
 
-OUI:001423*
- ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM
+OUI:001453*
+ ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES CO.,LTD
 
 OUI:001419*
  ID_OUI_FROM_DATABASE=SIDSA
@@ -38423,20 +39530,38 @@ OUI:0013F8*
 OUI:0013F1*
  ID_OUI_FROM_DATABASE=AMOD Technology Co., Ltd.
 
-OUI:0013F7*
- ID_OUI_FROM_DATABASE=SMC Networks, Inc.
+OUI:00135C*
+ ID_OUI_FROM_DATABASE=OnSite Systems, Inc.
 
-OUI:0013E7*
- ID_OUI_FROM_DATABASE=Halcro
+OUI:001355*
+ ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc.
 
-OUI:0013DB*
- ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd
+OUI:001356*
+ ID_OUI_FROM_DATABASE=FLIR Radiation Inc
 
-OUI:0013CC*
- ID_OUI_FROM_DATABASE=Tall Maple Systems
+OUI:001350*
+ ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc
 
-OUI:001283*
- ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:001344*
+ ID_OUI_FROM_DATABASE=Fargo Electronics Inc.
+
+OUI:001349*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+
+OUI:001343*
+ ID_OUI_FROM_DATABASE=Matsushita Electronic Components (Europe) GmbH
+
+OUI:00133D*
+ ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co
+
+OUI:00132A*
+ ID_OUI_FROM_DATABASE=Sitronics Telecom Solutions
+
+OUI:001331*
+ ID_OUI_FROM_DATABASE=CellPoint Connect
+
+OUI:001336*
+ ID_OUI_FROM_DATABASE=Tianjin 712 Communication Broadcasting co., ltd.
 
 OUI:001284*
  ID_OUI_FROM_DATABASE=Lab33 Srl
@@ -38462,62 +39587,74 @@ OUI:001264*
 OUI:00125A*
  ID_OUI_FROM_DATABASE=Microsoft Corporation
 
-OUI:00125F*
- ID_OUI_FROM_DATABASE=AWIND Inc.
+OUI:0012FA*
+ ID_OUI_FROM_DATABASE=THX LTD
 
-OUI:001255*
- ID_OUI_FROM_DATABASE=NetEffect Incorporated
+OUI:001301*
+ ID_OUI_FROM_DATABASE=IronGate S.L.
 
-OUI:00124E*
- ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
+OUI:001307*
+ ID_OUI_FROM_DATABASE=Paravirtual Corporation
 
-OUI:001247*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
+OUI:0012F5*
+ ID_OUI_FROM_DATABASE=Imarda New Zealand Limited
 
-OUI:001248*
- ID_OUI_FROM_DATABASE=EMC Corporation (Kashya)
+OUI:0012EB*
+ ID_OUI_FROM_DATABASE=PDH Solutions, LLC
 
-OUI:001242*
- ID_OUI_FROM_DATABASE=Millennial Net
+OUI:0012DE*
+ ID_OUI_FROM_DATABASE=Radio Components Sweden AB
 
-OUI:001236*
- ID_OUI_FROM_DATABASE=ConSentry Networks
+OUI:0012DD*
+ ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd.
 
-OUI:00123B*
- ID_OUI_FROM_DATABASE=KeRo Systems ApS
+OUI:0012E4*
+ ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG
 
-OUI:001368*
- ID_OUI_FROM_DATABASE=Saab Danmark A/S
+OUI:0012D8*
+ ID_OUI_FROM_DATABASE=International Games System Co., Ltd.
 
-OUI:00135C*
- ID_OUI_FROM_DATABASE=OnSite Systems, Inc.
+OUI:0013B6*
+ ID_OUI_FROM_DATABASE=Sling Media, Inc.
 
-OUI:001355*
- ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc.
+OUI:0013AF*
+ ID_OUI_FROM_DATABASE=NUMA Technology,Inc.
 
-OUI:001356*
- ID_OUI_FROM_DATABASE=FLIR Radiation Inc
+OUI:0013B0*
+ ID_OUI_FROM_DATABASE=Jablotron
 
-OUI:001350*
- ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc
+OUI:0013AA*
+ ID_OUI_FROM_DATABASE=ALS  & TEC Ltd.
 
-OUI:001344*
- ID_OUI_FROM_DATABASE=Fargo Electronics Inc.
+OUI:0013A3*
+ ID_OUI_FROM_DATABASE=Siemens Com CPE Devices
 
-OUI:001349*
- ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+OUI:00139E*
+ ID_OUI_FROM_DATABASE=Ciara Technologies Inc.
 
-OUI:001343*
- ID_OUI_FROM_DATABASE=Matsushita Electronic Components (Europe) GmbH
+OUI:00139D*
+ ID_OUI_FROM_DATABASE=Marvell Hispana S.L.
 
-OUI:00133D*
- ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co
+OUI:0012A8*
+ ID_OUI_FROM_DATABASE=intec GmbH
 
-OUI:001397*
- ID_OUI_FROM_DATABASE=Oracle Corporation
+OUI:0012A2*
+ ID_OUI_FROM_DATABASE=VITA
 
-OUI:00139D*
- ID_OUI_FROM_DATABASE=Marvell Hispana S.L.
+OUI:0012A1*
+ ID_OUI_FROM_DATABASE=BluePacket Communications Co., Ltd.
+
+OUI:00129C*
+ ID_OUI_FROM_DATABASE=Yulinet
+
+OUI:001290*
+ ID_OUI_FROM_DATABASE=KYOWA Electric & Machinery Corp.
+
+OUI:001295*
+ ID_OUI_FROM_DATABASE=Aiware Inc.
+
+OUI:001283*
+ ID_OUI_FROM_DATABASE=Nortel Networks
 
 OUI:00138B*
  ID_OUI_FROM_DATABASE=Phantom Technologies LLC
@@ -38546,59 +39683,44 @@ OUI:001375*
 OUI:001363*
  ID_OUI_FROM_DATABASE=Verascape, Inc.
 
-OUI:0012FA*
- ID_OUI_FROM_DATABASE=THX LTD
-
-OUI:001301*
- ID_OUI_FROM_DATABASE=IronGate S.L.
-
-OUI:001307*
- ID_OUI_FROM_DATABASE=Paravirtual Corporation
-
-OUI:0012F5*
- ID_OUI_FROM_DATABASE=Imarda New Zealand Limited
-
-OUI:0012EB*
- ID_OUI_FROM_DATABASE=PDH Solutions, LLC
-
-OUI:0012DE*
- ID_OUI_FROM_DATABASE=Radio Components Sweden AB
+OUI:001368*
+ ID_OUI_FROM_DATABASE=Saab Danmark A/S
 
-OUI:0012DD*
- ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd.
+OUI:0013F7*
+ ID_OUI_FROM_DATABASE=SMC Networks, Inc.
 
-OUI:0012E4*
- ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG
+OUI:0013E7*
+ ID_OUI_FROM_DATABASE=Halcro
 
-OUI:0012AF*
- ID_OUI_FROM_DATABASE=ELPRO Technologies
+OUI:0013DB*
+ ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd
 
-OUI:0012A8*
- ID_OUI_FROM_DATABASE=intec GmbH
+OUI:0013CC*
+ ID_OUI_FROM_DATABASE=Tall Maple Systems
 
-OUI:0012A2*
- ID_OUI_FROM_DATABASE=VITA
+OUI:0013C7*
+ ID_OUI_FROM_DATABASE=IONOS Co.,Ltd.
 
-OUI:0012A1*
- ID_OUI_FROM_DATABASE=BluePacket Communications Co., Ltd.
+OUI:0013C0*
+ ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda.
 
-OUI:00129C*
- ID_OUI_FROM_DATABASE=Yulinet
+OUI:0012CB*
+ ID_OUI_FROM_DATABASE=CSS Inc.
 
-OUI:001290*
- ID_OUI_FROM_DATABASE=KYOWA Electric & Machinery Corp.
+OUI:0012C5*
+ ID_OUI_FROM_DATABASE=V-Show  Technology (China) Co.,Ltd
 
-OUI:001295*
- ID_OUI_FROM_DATABASE=Aiware Inc.
+OUI:0012CC*
+ ID_OUI_FROM_DATABASE=Bitatek CO., LTD
 
-OUI:00132A*
- ID_OUI_FROM_DATABASE=Sitronics Telecom Solutions
+OUI:0012B4*
+ ID_OUI_FROM_DATABASE=Work Microwave GmbH
 
-OUI:001331*
- ID_OUI_FROM_DATABASE=CellPoint Connect
+OUI:0012BB*
+ ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee
 
-OUI:001336*
- ID_OUI_FROM_DATABASE=Tianjin 712 Communication Broadcasting co., ltd.
+OUI:0012AF*
+ ID_OUI_FROM_DATABASE=ELPRO Technologies
 
 OUI:001324*
  ID_OUI_FROM_DATABASE=Schneider Electric Ultra Terminal
@@ -38618,47 +39740,53 @@ OUI:00130D*
 OUI:001308*
  ID_OUI_FROM_DATABASE=Nuvera Fuel Cells
 
-OUI:00122F*
- ID_OUI_FROM_DATABASE=Sanei Electric Inc.
+OUI:001181*
+ ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd,
 
-OUI:001235*
- ID_OUI_FROM_DATABASE=Andrew Corporation
+OUI:00117B*
+ ID_OUI_FROM_DATABASE=Büchi  Labortechnik AG
 
-OUI:00122B*
- ID_OUI_FROM_DATABASE=Virbiage Pty Ltd
+OUI:00116F*
+ ID_OUI_FROM_DATABASE=Netforyou Co., LTD.
 
-OUI:001212*
- ID_OUI_FROM_DATABASE=PLUS  Corporation
+OUI:001168*
+ ID_OUI_FROM_DATABASE=HomeLogic LLC
 
-OUI:001219*
- ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc
+OUI:00115E*
+ ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH
 
-OUI:0012D8*
- ID_OUI_FROM_DATABASE=International Games System Co., Ltd.
+OUI:001157*
+ ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd.
 
-OUI:0012CB*
- ID_OUI_FROM_DATABASE=CSS Inc.
+OUI:001158*
+ ID_OUI_FROM_DATABASE=Nortel Networks
 
-OUI:0012C5*
- ID_OUI_FROM_DATABASE=V-Show  Technology (China) Co.,Ltd
+OUI:001152*
+ ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS
 
-OUI:0012CC*
- ID_OUI_FROM_DATABASE=Bitatek CO., LTD
+OUI:0011A4*
+ ID_OUI_FROM_DATABASE=JStream Technologies Inc.
 
-OUI:0012B4*
- ID_OUI_FROM_DATABASE=Work Microwave GmbH
+OUI:001198*
+ ID_OUI_FROM_DATABASE=Prism Media Products Limited
 
-OUI:0012BB*
- ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee
+OUI:00119D*
+ ID_OUI_FROM_DATABASE=Diginfo Technology Corporation
 
-OUI:001206*
- ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd
+OUI:00119E*
+ ID_OUI_FROM_DATABASE=Solectron Brazil
 
-OUI:00120B*
- ID_OUI_FROM_DATABASE=Chinasys Technologies Limited
+OUI:00118E*
+ ID_OUI_FROM_DATABASE=Halytech Mace
 
-OUI:00120C*
- ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd
+OUI:001193*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001187*
+ ID_OUI_FROM_DATABASE=Category Solutions, Inc
+
+OUI:001182*
+ ID_OUI_FROM_DATABASE=IMI Norgren Ltd
 
 OUI:0011FF*
  ID_OUI_FROM_DATABASE=Digitro Tecnologia Ltda
@@ -38678,92 +39806,77 @@ OUI:0011EF*
 OUI:0011E9*
  ID_OUI_FROM_DATABASE=STARNEX CO., LTD.
 
-OUI:001187*
- ID_OUI_FROM_DATABASE=Category Solutions, Inc
-
-OUI:001182*
- ID_OUI_FROM_DATABASE=IMI Norgren Ltd
-
-OUI:001181*
- ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd,
-
-OUI:00117B*
- ID_OUI_FROM_DATABASE=Büchi  Labortechnik AG
-
-OUI:001174*
- ID_OUI_FROM_DATABASE=Wibhu Technologies, Inc.
-
-OUI:00116F*
- ID_OUI_FROM_DATABASE=Netforyou Co., LTD.
-
-OUI:001168*
- ID_OUI_FROM_DATABASE=HomeLogic LLC
+OUI:0011DD*
+ ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd.
 
-OUI:00115E*
- ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH
+OUI:0011E2*
+ ID_OUI_FROM_DATABASE=Hua Jung Components Co., Ltd.
 
-OUI:001157*
- ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd.
+OUI:000FFA*
+ ID_OUI_FROM_DATABASE=Optinel Systems, Inc.
 
-OUI:001158*
- ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:000FFF*
+ ID_OUI_FROM_DATABASE=Control4
 
-OUI:000FB2*
- ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd.
+OUI:000FF1*
+ ID_OUI_FROM_DATABASE=nex-G Systems Pte.Ltd
 
-OUI:000FA5*
- ID_OUI_FROM_DATABASE=BWA Technology GmbH
+OUI:000FE4*
+ ID_OUI_FROM_DATABASE=Pantech Co.,Ltd
 
-OUI:000FB1*
- ID_OUI_FROM_DATABASE=Cognio Inc.
+OUI:000FEA*
+ ID_OUI_FROM_DATABASE=Giga-Byte Technology Co.,LTD.
 
-OUI:000FAC*
- ID_OUI_FROM_DATABASE=IEEE 802.11
+OUI:000FE3*
+ ID_OUI_FROM_DATABASE=Damm Cellular Systems A/S
 
-OUI:000F9C*
- ID_OUI_FROM_DATABASE=Panduit Corp
+OUI:000FD7*
+ ID_OUI_FROM_DATABASE=Harman Music Group
 
-OUI:000FA0*
- ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC.
+OUI:001235*
+ ID_OUI_FROM_DATABASE=Andrew Corporation
 
-OUI:000F97*
- ID_OUI_FROM_DATABASE=Avanex Corporation
+OUI:00122B*
+ ID_OUI_FROM_DATABASE=Virbiage Pty Ltd
 
-OUI:000F8A*
- ID_OUI_FROM_DATABASE=WideView
+OUI:001212*
+ ID_OUI_FROM_DATABASE=PLUS  Corporation
 
-OUI:000F89*
- ID_OUI_FROM_DATABASE=Winnertec System Co., Ltd.
+OUI:001219*
+ ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc
 
-OUI:000F90*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001206*
+ ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd
 
-OUI:000FD7*
- ID_OUI_FROM_DATABASE=Harman Music Group
+OUI:00120B*
+ ID_OUI_FROM_DATABASE=Chinasys Technologies Limited
 
-OUI:000FD1*
- ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc.
+OUI:00120C*
+ ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd
 
-OUI:000FD2*
- ID_OUI_FROM_DATABASE=EWA Technologies, Inc.
+OUI:001130*
+ ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd.
 
-OUI:000FC4*
- ID_OUI_FROM_DATABASE=NST co.,LTD.
+OUI:00111E*
+ ID_OUI_FROM_DATABASE=EPSG (Ethernet Powerlink Standardization Group)
 
-OUI:000FCB*
- ID_OUI_FROM_DATABASE=3Com Ltd
+OUI:00111F*
+ ID_OUI_FROM_DATABASE=Doremi Labs, Inc.
 
-OUI:000FBF*
- ID_OUI_FROM_DATABASE=DGT Sp. z o.o.
+OUI:001112*
+ ID_OUI_FROM_DATABASE=Honeywell CMSS
 
-OUI:000FB8*
- ID_OUI_FROM_DATABASE=CallURL Inc.
+OUI:001118*
+ ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd.
 
-OUI:0011DD*
- ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd.
+OUI:001105*
+ ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd.
 
-OUI:0011E2*
- ID_OUI_FROM_DATABASE=Hua Jung Components Co., Ltd.
+OUI:00110C*
+ ID_OUI_FROM_DATABASE=Atmark Techno, Inc.
+
+OUI:000FF9*
+ ID_OUI_FROM_DATABASE=Valcretec, Inc.
 
 OUI:0011CF*
  ID_OUI_FROM_DATABASE=Thrane & Thrane A/S
@@ -38789,59 +39902,38 @@ OUI:0011BE*
 OUI:0011BD*
  ID_OUI_FROM_DATABASE=Bombardier Transportation
 
-OUI:001105*
- ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd.
-
-OUI:00110C*
- ID_OUI_FROM_DATABASE=Atmark Techno, Inc.
-
-OUI:000FF9*
- ID_OUI_FROM_DATABASE=Valcretec, Inc.
-
-OUI:000FFA*
- ID_OUI_FROM_DATABASE=Optinel Systems, Inc.
-
-OUI:000FFF*
- ID_OUI_FROM_DATABASE=Control4
-
-OUI:000FF1*
- ID_OUI_FROM_DATABASE=nex-G Systems Pte.Ltd
-
-OUI:000FE4*
- ID_OUI_FROM_DATABASE=Pantech Co.,Ltd
-
-OUI:000FEA*
- ID_OUI_FROM_DATABASE=Giga-Byte Technology Co.,LTD.
-
-OUI:000FE3*
- ID_OUI_FROM_DATABASE=Damm Cellular Systems A/S
-
 OUI:0011AB*
  ID_OUI_FROM_DATABASE=TRUSTABLE TECHNOLOGY CO.,LTD.
 
 OUI:0011B0*
  ID_OUI_FROM_DATABASE=Fortelink Inc.
 
-OUI:0011A4*
- ID_OUI_FROM_DATABASE=JStream Technologies Inc.
+OUI:00125F*
+ ID_OUI_FROM_DATABASE=AWIND Inc.
 
-OUI:001198*
- ID_OUI_FROM_DATABASE=Prism Media Products Limited
+OUI:001255*
+ ID_OUI_FROM_DATABASE=NetEffect Incorporated
 
-OUI:00119D*
- ID_OUI_FROM_DATABASE=Diginfo Technology Corporation
+OUI:00124E*
+ ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
 
-OUI:00119E*
- ID_OUI_FROM_DATABASE=Solectron Brazil
+OUI:001247*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd.
 
-OUI:00118E*
- ID_OUI_FROM_DATABASE=Halytech Mace
+OUI:001248*
+ ID_OUI_FROM_DATABASE=EMC Corporation (Kashya)
 
-OUI:001193*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:001242*
+ ID_OUI_FROM_DATABASE=Millennial Net
 
-OUI:001152*
- ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS
+OUI:001236*
+ ID_OUI_FROM_DATABASE=ConSentry Networks
+
+OUI:00123B*
+ ID_OUI_FROM_DATABASE=KeRo Systems ApS
+
+OUI:00122F*
+ ID_OUI_FROM_DATABASE=Sanei Electric Inc.
 
 OUI:00114F*
  ID_OUI_FROM_DATABASE=US Digital Television, Inc
@@ -38864,20 +39956,23 @@ OUI:001136*
 OUI:00112C*
  ID_OUI_FROM_DATABASE=IZT GmbH
 
-OUI:001130*
- ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd.
+OUI:000F77*
+ ID_OUI_FROM_DATABASE=DENTUM CO.,LTD
 
-OUI:00111E*
- ID_OUI_FROM_DATABASE=EPSG (Ethernet Powerlink Standardization Group)
+OUI:000F71*
+ ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd
 
-OUI:00111F*
- ID_OUI_FROM_DATABASE=Doremi Labs, Inc.
+OUI:000F78*
+ ID_OUI_FROM_DATABASE=Datacap Systems Inc
 
-OUI:001112*
- ID_OUI_FROM_DATABASE=Honeywell CMSS
+OUI:000F6A*
+ ID_OUI_FROM_DATABASE=Nortel Networks
 
-OUI:001118*
- ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd.
+OUI:000F65*
+ ID_OUI_FROM_DATABASE=icube Corp.
+
+OUI:000F5E*
+ ID_OUI_FROM_DATABASE=Veo
 
 OUI:000F58*
  ID_OUI_FROM_DATABASE=Adder Technology Limited
@@ -38915,9 +40010,6 @@ OUI:000F32*
 OUI:000F2B*
  ID_OUI_FROM_DATABASE=GREENBELL SYSTEMS
 
-OUI:000E98*
- ID_OUI_FROM_DATABASE=HME Clear-Com LTD.
-
 OUI:000E93*
  ID_OUI_FROM_DATABASE=Milénio 3 Sistemas Electrónicos, Lda.
 
@@ -38939,6 +40031,36 @@ OUI:000E74*
 OUI:000E79*
  ID_OUI_FROM_DATABASE=Ample Communications Inc.
 
+OUI:000E71*
+ ID_OUI_FROM_DATABASE=Gemstar Technology Development Ltd.
+
+OUI:000E6C*
+ ID_OUI_FROM_DATABASE=Device Drivers Limited
+
+OUI:000EB8*
+ ID_OUI_FROM_DATABASE=Iiga co.,Ltd
+
+OUI:000EB7*
+ ID_OUI_FROM_DATABASE=Knovative, Inc.
+
+OUI:000EBE*
+ ID_OUI_FROM_DATABASE=B&B Electronics Manufacturing Co.
+
+OUI:000EB2*
+ ID_OUI_FROM_DATABASE=Micro-Research Finland Oy
+
+OUI:000EAB*
+ ID_OUI_FROM_DATABASE=Cray Inc
+
+OUI:000EA5*
+ ID_OUI_FROM_DATABASE=BLIP Systems
+
+OUI:000E9F*
+ ID_OUI_FROM_DATABASE=TEMIC SDS GmbH
+
+OUI:000E98*
+ ID_OUI_FROM_DATABASE=HME Clear-Com LTD.
+
 OUI:000F24*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -38963,35 +40085,62 @@ OUI:000F00*
 OUI:000F05*
  ID_OUI_FROM_DATABASE=3B SYSTEM INC.
 
+OUI:000EF9*
+ ID_OUI_FROM_DATABASE=REA Elektronik GmbH
+
+OUI:000FAC*
+ ID_OUI_FROM_DATABASE=IEEE 802.11
+
+OUI:000F9C*
+ ID_OUI_FROM_DATABASE=Panduit Corp
+
+OUI:000FA0*
+ ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC.
+
+OUI:000F97*
+ ID_OUI_FROM_DATABASE=Avanex Corporation
+
+OUI:000F8A*
+ ID_OUI_FROM_DATABASE=WideView
+
+OUI:000F89*
+ ID_OUI_FROM_DATABASE=Winnertec System Co., Ltd.
+
+OUI:000F90*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
 OUI:000F7D*
  ID_OUI_FROM_DATABASE=Xirrus
 
 OUI:000F84*
  ID_OUI_FROM_DATABASE=Astute Networks, Inc.
 
-OUI:000F77*
- ID_OUI_FROM_DATABASE=DENTUM CO.,LTD
+OUI:000FD1*
+ ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc.
 
-OUI:000F71*
- ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd
+OUI:000FD2*
+ ID_OUI_FROM_DATABASE=EWA Technologies, Inc.
 
-OUI:000F78*
- ID_OUI_FROM_DATABASE=Datacap Systems Inc
+OUI:000FC4*
+ ID_OUI_FROM_DATABASE=NST co.,LTD.
 
-OUI:000F6A*
- ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:000FCB*
+ ID_OUI_FROM_DATABASE=3Com Ltd
 
-OUI:000F65*
- ID_OUI_FROM_DATABASE=icube Corp.
+OUI:000FBF*
+ ID_OUI_FROM_DATABASE=DGT Sp. z o.o.
 
-OUI:000F5E*
- ID_OUI_FROM_DATABASE=Veo
+OUI:000FB8*
+ ID_OUI_FROM_DATABASE=CallURL Inc.
 
-OUI:000E71*
- ID_OUI_FROM_DATABASE=Gemstar Technology Development Ltd.
+OUI:000FB2*
+ ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd.
 
-OUI:000E6C*
- ID_OUI_FROM_DATABASE=Device Drivers Limited
+OUI:000FA5*
+ ID_OUI_FROM_DATABASE=BWA Technology GmbH
+
+OUI:000FB1*
+ ID_OUI_FROM_DATABASE=Cognio Inc.
 
 OUI:000E65*
  ID_OUI_FROM_DATABASE=TransCore
@@ -39017,63 +40166,6 @@ OUI:000E40*
 OUI:000E3F*
  ID_OUI_FROM_DATABASE=Soronti, Inc.
 
-OUI:000EC5*
- ID_OUI_FROM_DATABASE=Digital Multitools Inc
-
-OUI:000EB8*
- ID_OUI_FROM_DATABASE=Iiga co.,Ltd
-
-OUI:000EB7*
- ID_OUI_FROM_DATABASE=Knovative, Inc.
-
-OUI:000EBE*
- ID_OUI_FROM_DATABASE=B&B Electronics Manufacturing Co.
-
-OUI:000EB2*
- ID_OUI_FROM_DATABASE=Micro-Research Finland Oy
-
-OUI:000EAB*
- ID_OUI_FROM_DATABASE=Cray Inc
-
-OUI:000EA5*
- ID_OUI_FROM_DATABASE=BLIP Systems
-
-OUI:000E9F*
- ID_OUI_FROM_DATABASE=TEMIC SDS GmbH
-
-OUI:000E0A*
- ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE
-
-OUI:000E12*
- ID_OUI_FROM_DATABASE=Adaptive Micro Systems Inc.
-
-OUI:000E04*
- ID_OUI_FROM_DATABASE=CMA/Microdialysis AB
-
-OUI:000DF7*
- ID_OUI_FROM_DATABASE=Space Dynamics Lab
-
-OUI:000DFE*
- ID_OUI_FROM_DATABASE=Hauppauge Computer Works, Inc.
-
-OUI:000E03*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
-OUI:000DF1*
- ID_OUI_FROM_DATABASE=IONIX INC.
-
-OUI:000DEB*
- ID_OUI_FROM_DATABASE=CompXs Limited
-
-OUI:000DF2*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:000DE4*
- ID_OUI_FROM_DATABASE=DIGINICS, Inc.
-
-OUI:000EF9*
- ID_OUI_FROM_DATABASE=REA Elektronik GmbH
-
 OUI:000EF2*
  ID_OUI_FROM_DATABASE=Infinico Corporation
 
@@ -39098,65 +40190,35 @@ OUI:000EDA*
 OUI:000ED6*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:000E37*
- ID_OUI_FROM_DATABASE=Harms & Wende GmbH & Co.KG
-
-OUI:000E38*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:000E31*
- ID_OUI_FROM_DATABASE=Olympus Soft Imaging Solutions GmbH
-
-OUI:000E2A*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:000E1E*
- ID_OUI_FROM_DATABASE=QLogic Corporation
-
-OUI:000E25*
- ID_OUI_FROM_DATABASE=Hannae Technology Co., Ltd
-
-OUI:000E18*
- ID_OUI_FROM_DATABASE=MyA Technology
-
-OUI:000E17*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:000E0E*
- ID_OUI_FROM_DATABASE=ESA elettronica S.P.A.
-
-OUI:000C7E*
- ID_OUI_FROM_DATABASE=Tellium Incorporated
-
-OUI:000C86*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000EC5*
+ ID_OUI_FROM_DATABASE=Digital Multitools Inc
 
-OUI:000C81*
- ID_OUI_FROM_DATABASE=Schneider Electric (Australia)
+OUI:000DB2*
+ ID_OUI_FROM_DATABASE=Ammasso, Inc.
 
-OUI:000C72*
- ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd.
+OUI:000DAD*
+ ID_OUI_FROM_DATABASE=Dataprobe, Inc.
 
-OUI:000C79*
- ID_OUI_FROM_DATABASE=Extel Communications P/L
+OUI:000D9E*
+ ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd.
 
-OUI:000C66*
- ID_OUI_FROM_DATABASE=Pronto Networks Inc
+OUI:000DA5*
+ ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc
 
-OUI:000C6B*
- ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH
+OUI:000D99*
+ ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group
 
-OUI:000C6D*
- ID_OUI_FROM_DATABASE=Edwards Ltd.
+OUI:000D8C*
+ ID_OUI_FROM_DATABASE=Shanghai Wedone Digital Ltd. CO.
 
-OUI:000DDF*
- ID_OUI_FROM_DATABASE=Japan Image & Network Inc.
+OUI:000D8B*
+ ID_OUI_FROM_DATABASE=T&D Corporation
 
-OUI:000DD2*
- ID_OUI_FROM_DATABASE=Simrad Optronics ASA
+OUI:000D85*
+ ID_OUI_FROM_DATABASE=Tapwave, Inc.
 
-OUI:000DD1*
- ID_OUI_FROM_DATABASE=Stryker Corporation
+OUI:000D86*
+ ID_OUI_FROM_DATABASE=Huber + Suhner AG
 
 OUI:000DD8*
  ID_OUI_FROM_DATABASE=BBN
@@ -39176,80 +40238,56 @@ OUI:000DC5*
 OUI:000DB9*
  ID_OUI_FROM_DATABASE=PC Engines GmbH
 
-OUI:000D8C*
- ID_OUI_FROM_DATABASE=Shanghai Wedone Digital Ltd. CO.
-
-OUI:000D8B*
- ID_OUI_FROM_DATABASE=T&D Corporation
-
-OUI:000D85*
- ID_OUI_FROM_DATABASE=Tapwave, Inc.
-
-OUI:000D86*
- ID_OUI_FROM_DATABASE=Huber + Suhner AG
-
-OUI:000D7E*
- ID_OUI_FROM_DATABASE=Axiowave Networks, Inc.
-
-OUI:000D78*
- ID_OUI_FROM_DATABASE=Engineering & Security
-
-OUI:000D77*
- ID_OUI_FROM_DATABASE=FalconStor Software
-
-OUI:000D6B*
- ID_OUI_FROM_DATABASE=Mita-Teknik A/S
-
-OUI:000D65*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000D4C*
+ ID_OUI_FROM_DATABASE=Outline Electronics Ltd.
 
-OUI:000D5F*
- ID_OUI_FROM_DATABASE=Minds Inc
+OUI:000D53*
+ ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp.
 
-OUI:000D66*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000D3F*
+ ID_OUI_FROM_DATABASE=VTI Instruments Corporation
 
-OUI:000CB1*
- ID_OUI_FROM_DATABASE=Salland Engineering (Europe) BV
+OUI:000D44*
+ ID_OUI_FROM_DATABASE=Audio BU - Logitech
 
-OUI:000CB7*
- ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd.
+OUI:000D38*
+ ID_OUI_FROM_DATABASE=NISSIN INC.
 
-OUI:000CBE*
- ID_OUI_FROM_DATABASE=Innominate Security Technologies AG
+OUI:000D32*
+ ID_OUI_FROM_DATABASE=DispenseSource, Inc.
 
-OUI:000CC3*
- ID_OUI_FROM_DATABASE=BeWAN systems
+OUI:000D31*
+ ID_OUI_FROM_DATABASE=Compellent Technologies, Inc.
 
-OUI:000CB2*
- ID_OUI_FROM_DATABASE=UNION co., ltd.
+OUI:000E04*
+ ID_OUI_FROM_DATABASE=CMA/Microdialysis AB
 
-OUI:000CA5*
- ID_OUI_FROM_DATABASE=Naman NZ LTd
+OUI:000DF7*
+ ID_OUI_FROM_DATABASE=Space Dynamics Lab
 
-OUI:000CAC*
- ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd.
+OUI:000DFE*
+ ID_OUI_FROM_DATABASE=Hauppauge Computer Works, Inc.
 
-OUI:000C94*
- ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI)
+OUI:000DF1*
+ ID_OUI_FROM_DATABASE=IONIX INC.
 
-OUI:000C99*
- ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd
+OUI:000DEB*
+ ID_OUI_FROM_DATABASE=CompXs Limited
 
-OUI:000CA0*
- ID_OUI_FROM_DATABASE=StorCase Technology, Inc.
+OUI:000DF2*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:000C8D*
- ID_OUI_FROM_DATABASE=MATRIX VISION GmbH
+OUI:000DE4*
+ ID_OUI_FROM_DATABASE=DIGINICS, Inc.
 
-OUI:000C92*
- ID_OUI_FROM_DATABASE=WolfVision Gmbh
+OUI:000DDF*
+ ID_OUI_FROM_DATABASE=Japan Image & Network Inc.
 
-OUI:000D32*
- ID_OUI_FROM_DATABASE=DispenseSource, Inc.
+OUI:000DD2*
+ ID_OUI_FROM_DATABASE=Simrad Optronics ASA
 
-OUI:000D31*
- ID_OUI_FROM_DATABASE=Compellent Technologies, Inc.
+OUI:000DD1*
+ ID_OUI_FROM_DATABASE=Stryker Corporation
 
 OUI:000D2C*
  ID_OUI_FROM_DATABASE=Patapsco Designs Ltd
@@ -39272,59 +40310,86 @@ OUI:000D0D*
 OUI:000D12*
  ID_OUI_FROM_DATABASE=AXELL Corporation
 
-OUI:000DB2*
- ID_OUI_FROM_DATABASE=Ammasso, Inc.
+OUI:000D00*
+ ID_OUI_FROM_DATABASE=Seaway Networks Inc.
 
-OUI:000DAD*
- ID_OUI_FROM_DATABASE=Dataprobe, Inc.
+OUI:000D06*
+ ID_OUI_FROM_DATABASE=Compulogic Limited
 
-OUI:000D9E*
- ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd.
+OUI:000CD1*
+ ID_OUI_FROM_DATABASE=SFOM Technology Corp.
 
-OUI:000DA5*
- ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc
+OUI:000CD6*
+ ID_OUI_FROM_DATABASE=PARTNER TECH
 
-OUI:000D99*
- ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group
+OUI:000CDD*
+ ID_OUI_FROM_DATABASE=AOS technologies AG
 
-OUI:000D58*
+OUI:000CCA*
+ ID_OUI_FROM_DATABASE=HGST a Western Digital Company
+
+OUI:000CC4*
+ ID_OUI_FROM_DATABASE=Tiptel AG
+
+OUI:000CB1*
+ ID_OUI_FROM_DATABASE=Salland Engineering (Europe) BV
+
+OUI:000E37*
+ ID_OUI_FROM_DATABASE=Harms & Wende GmbH & Co.KG
+
+OUI:000E38*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:000E31*
+ ID_OUI_FROM_DATABASE=Olympus Soft Imaging Solutions GmbH
+
+OUI:000E2A*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:000D4C*
- ID_OUI_FROM_DATABASE=Outline Electronics Ltd.
+OUI:000E1E*
+ ID_OUI_FROM_DATABASE=QLogic Corporation
 
-OUI:000D53*
- ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp.
+OUI:000E25*
+ ID_OUI_FROM_DATABASE=Hannae Technology Co., Ltd
+
+OUI:000E18*
+ ID_OUI_FROM_DATABASE=MyA Technology
+
+OUI:000E17*
+ ID_OUI_FROM_DATABASE=Private
 
-OUI:000D3F*
- ID_OUI_FROM_DATABASE=VTI Instruments Corporation
+OUI:000E0E*
+ ID_OUI_FROM_DATABASE=ESA elettronica S.P.A.
 
-OUI:000D44*
- ID_OUI_FROM_DATABASE=Audio BU - Logitech
+OUI:000E0A*
+ ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE
 
-OUI:000D38*
- ID_OUI_FROM_DATABASE=NISSIN INC.
+OUI:000E12*
+ ID_OUI_FROM_DATABASE=Adaptive Micro Systems Inc.
 
-OUI:000CD1*
- ID_OUI_FROM_DATABASE=SFOM Technology Corp.
+OUI:000D7E*
+ ID_OUI_FROM_DATABASE=Axiowave Networks, Inc.
 
-OUI:000CD6*
- ID_OUI_FROM_DATABASE=PARTNER TECH
+OUI:000D78*
+ ID_OUI_FROM_DATABASE=Engineering & Security
 
-OUI:000CDD*
- ID_OUI_FROM_DATABASE=AOS technologies AG
+OUI:000D77*
+ ID_OUI_FROM_DATABASE=FalconStor Software
 
-OUI:000CCA*
- ID_OUI_FROM_DATABASE=HGST a Western Digital Company
+OUI:000D6B*
+ ID_OUI_FROM_DATABASE=Mita-Teknik A/S
 
-OUI:000CC4*
- ID_OUI_FROM_DATABASE=Tiptel AG
+OUI:000D65*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:000D00*
- ID_OUI_FROM_DATABASE=Seaway Networks Inc.
+OUI:000D5F*
+ ID_OUI_FROM_DATABASE=Minds Inc
 
-OUI:000D06*
- ID_OUI_FROM_DATABASE=Compulogic Limited
+OUI:000D66*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:000D58*
+ ID_OUI_FROM_DATABASE=Private
 
 OUI:000CFA*
  ID_OUI_FROM_DATABASE=Digital Systems Corp
@@ -39347,72 +40412,6 @@ OUI:000CE7*
 OUI:000CE3*
  ID_OUI_FROM_DATABASE=Option International N.V.
 
-OUI:000B01*
- ID_OUI_FROM_DATABASE=DAIICHI ELECTRONICS CO., LTD.
-
-OUI:000AF0*
- ID_OUI_FROM_DATABASE=SHIN-OH ELECTRONICS CO., LTD. R&D
-
-OUI:000AF5*
- ID_OUI_FROM_DATABASE=Airgo Networks, Inc.
-
-OUI:000AEC*
- ID_OUI_FROM_DATABASE=Koatsu Gas Kogyo Co., Ltd.
-
-OUI:000AE5*
- ID_OUI_FROM_DATABASE=ScottCare Corporation
-
-OUI:000AE7*
- ID_OUI_FROM_DATABASE=ELIOP S.A.
-
-OUI:000AE0*
- ID_OUI_FROM_DATABASE=Fujitsu Softek
-
-OUI:000AC8*
- ID_OUI_FROM_DATABASE=ZPSYS CO.,LTD. (Planning&Management)
-
-OUI:000ACD*
- ID_OUI_FROM_DATABASE=Sunrich Technology Limited
-
-OUI:000AD4*
- ID_OUI_FROM_DATABASE=CoreBell Systems Inc.
-
-OUI:000B5E*
- ID_OUI_FROM_DATABASE=Audio Engineering Society Inc.
-
-OUI:000B63*
- ID_OUI_FROM_DATABASE=Kaleidescape
-
-OUI:000B55*
- ID_OUI_FROM_DATABASE=ADInstruments
-
-OUI:000B5A*
- ID_OUI_FROM_DATABASE=HyperEdge
-
-OUI:000B52*
- ID_OUI_FROM_DATABASE=JOYMAX ELECTRONICS CO. LTD.
-
-OUI:000B4D*
- ID_OUI_FROM_DATABASE=Emuzed
-
-OUI:000B41*
- ID_OUI_FROM_DATABASE=Ing. Büro Dr. Beutlhauser
-
-OUI:000B46*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:000B33*
- ID_OUI_FROM_DATABASE=Vivato Technologies
-
-OUI:000B3A*
- ID_OUI_FROM_DATABASE=QuStream Corporation
-
-OUI:000B3F*
- ID_OUI_FROM_DATABASE=Anthology Solutions Inc.
-
-OUI:000B95*
- ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd
-
 OUI:000B8F*
  ID_OUI_FROM_DATABASE=AKITA ELECTRONICS SYSTEMS CO.,LTD.
 
@@ -39437,35 +40436,35 @@ OUI:000B6F*
 OUI:000B76*
  ID_OUI_FROM_DATABASE=ET&T Technology Co. Ltd.
 
-OUI:000AC1*
- ID_OUI_FROM_DATABASE=Futuretel
+OUI:000B5E*
+ ID_OUI_FROM_DATABASE=Audio Engineering Society Inc.
 
-OUI:000AC6*
- ID_OUI_FROM_DATABASE=Overture Networks.
+OUI:000B63*
+ ID_OUI_FROM_DATABASE=Kaleidescape
 
-OUI:000AAE*
- ID_OUI_FROM_DATABASE=Rosemount Process Analytical
+OUI:000C7E*
+ ID_OUI_FROM_DATABASE=Tellium Incorporated
 
-OUI:000AB3*
- ID_OUI_FROM_DATABASE=Fa. GIRA
+OUI:000C86*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:000AB5*
- ID_OUI_FROM_DATABASE=Digital Electronic Network
+OUI:000C81*
+ ID_OUI_FROM_DATABASE=Schneider Electric (Australia)
 
-OUI:000ABA*
- ID_OUI_FROM_DATABASE=Arcon Technology Limited
+OUI:000C72*
+ ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd.
 
-OUI:000AA2*
- ID_OUI_FROM_DATABASE=SYSTEK INC.
+OUI:000C79*
+ ID_OUI_FROM_DATABASE=Extel Communications P/L
 
-OUI:000AA7*
- ID_OUI_FROM_DATABASE=FEI Electron Optics
+OUI:000C66*
+ ID_OUI_FROM_DATABASE=Pronto Networks Inc
 
-OUI:000A8F*
- ID_OUI_FROM_DATABASE=Aska International Inc.
+OUI:000C6B*
+ ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH
 
-OUI:000A94*
- ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD
+OUI:000C6D*
+ ID_OUI_FROM_DATABASE=Edwards Ltd.
 
 OUI:000C4E*
  ID_OUI_FROM_DATABASE=Winbest Technology CO,LT
@@ -39497,6 +40496,66 @@ OUI:000C2D*
 OUI:000C1A*
  ID_OUI_FROM_DATABASE=Quest Technical Solutions Inc.
 
+OUI:000B2E*
+ ID_OUI_FROM_DATABASE=Cal-Comp Electronics (Thailand) Public Company Limited Taipe
+
+OUI:000B1B*
+ ID_OUI_FROM_DATABASE=Systronix, Inc.
+
+OUI:000B20*
+ ID_OUI_FROM_DATABASE=Hirata corporation
+
+OUI:000B22*
+ ID_OUI_FROM_DATABASE=Environmental Systems and Services
+
+OUI:000B14*
+ ID_OUI_FROM_DATABASE=ViewSonic Corporation
+
+OUI:000B0D*
+ ID_OUI_FROM_DATABASE=Air2U, Inc.
+
+OUI:000B0F*
+ ID_OUI_FROM_DATABASE=Bosch Rexroth
+
+OUI:000B08*
+ ID_OUI_FROM_DATABASE=Pillar Data Systems
+
+OUI:000AFC*
+ ID_OUI_FROM_DATABASE=Core Tec Communications, LLC
+
+OUI:000B01*
+ ID_OUI_FROM_DATABASE=DAIICHI ELECTRONICS CO., LTD.
+
+OUI:000B55*
+ ID_OUI_FROM_DATABASE=ADInstruments
+
+OUI:000B5A*
+ ID_OUI_FROM_DATABASE=HyperEdge
+
+OUI:000B52*
+ ID_OUI_FROM_DATABASE=JOYMAX ELECTRONICS CO. LTD.
+
+OUI:000B4D*
+ ID_OUI_FROM_DATABASE=Emuzed
+
+OUI:000B41*
+ ID_OUI_FROM_DATABASE=Ing. Büro Dr. Beutlhauser
+
+OUI:000B46*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:000B33*
+ ID_OUI_FROM_DATABASE=Vivato Technologies
+
+OUI:000B3A*
+ ID_OUI_FROM_DATABASE=QuStream Corporation
+
+OUI:000B3F*
+ ID_OUI_FROM_DATABASE=Anthology Solutions Inc.
+
+OUI:000B27*
+ ID_OUI_FROM_DATABASE=Scion Corporation
+
 OUI:000C1E*
  ID_OUI_FROM_DATABASE=Global Cache
 
@@ -39512,8 +40571,14 @@ OUI:000C15*
 OUI:000C09*
  ID_OUI_FROM_DATABASE=Hitachi IE Systems Co., Ltd
 
-OUI:000BD3*
- ID_OUI_FROM_DATABASE=cd3o
+OUI:000BF6*
+ ID_OUI_FROM_DATABASE=Nitgen Co., Ltd
+
+OUI:000BFB*
+ ID_OUI_FROM_DATABASE=D-NET International Corporation
+
+OUI:000C02*
+ ID_OUI_FROM_DATABASE=ABB Oy
 
 OUI:000BC7*
  ID_OUI_FROM_DATABASE=ICET S.p.A.
@@ -39545,44 +40610,41 @@ OUI:000BAA*
 OUI:000B9E*
  ID_OUI_FROM_DATABASE=Yasing Technology Corp.
 
-OUI:000B27*
- ID_OUI_FROM_DATABASE=Scion Corporation
-
-OUI:000B2E*
- ID_OUI_FROM_DATABASE=Cal-Comp Electronics (Thailand) Public Company Limited Taipe
+OUI:000B95*
+ ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd
 
-OUI:000B1B*
- ID_OUI_FROM_DATABASE=Systronix, Inc.
+OUI:000CB7*
+ ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd.
 
-OUI:000B20*
- ID_OUI_FROM_DATABASE=Hirata corporation
+OUI:000CBE*
+ ID_OUI_FROM_DATABASE=Innominate Security Technologies AG
 
-OUI:000B22*
- ID_OUI_FROM_DATABASE=Environmental Systems and Services
+OUI:000CC3*
+ ID_OUI_FROM_DATABASE=BeWAN systems
 
-OUI:000B14*
- ID_OUI_FROM_DATABASE=ViewSonic Corporation
+OUI:000CB2*
+ ID_OUI_FROM_DATABASE=UNION co., ltd.
 
-OUI:000B0D*
- ID_OUI_FROM_DATABASE=Air2U, Inc.
+OUI:000CA5*
+ ID_OUI_FROM_DATABASE=Naman NZ LTd
 
-OUI:000B0F*
- ID_OUI_FROM_DATABASE=Bosch Rexroth
+OUI:000CAC*
+ ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd.
 
-OUI:000B08*
- ID_OUI_FROM_DATABASE=Pillar Data Systems
+OUI:000C94*
+ ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI)
 
-OUI:000AFC*
- ID_OUI_FROM_DATABASE=Core Tec Communications, LLC
+OUI:000C99*
+ ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd
 
-OUI:000BF6*
- ID_OUI_FROM_DATABASE=Nitgen Co., Ltd
+OUI:000CA0*
+ ID_OUI_FROM_DATABASE=StorCase Technology, Inc.
 
-OUI:000BFB*
- ID_OUI_FROM_DATABASE=D-NET International Corporation
+OUI:000C8D*
+ ID_OUI_FROM_DATABASE=MATRIX VISION GmbH
 
-OUI:000C02*
- ID_OUI_FROM_DATABASE=ABB Oy
+OUI:000C92*
+ ID_OUI_FROM_DATABASE=WolfVision Gmbh
 
 OUI:000BEA*
  ID_OUI_FROM_DATABASE=Zultys Technologies
@@ -39605,6 +40667,42 @@ OUI:000BD7*
 OUI:000BDC*
  ID_OUI_FROM_DATABASE=AKCP
 
+OUI:000BD3*
+ ID_OUI_FROM_DATABASE=cd3o
+
+OUI:000AF0*
+ ID_OUI_FROM_DATABASE=SHIN-OH ELECTRONICS CO., LTD. R&D
+
+OUI:000AF5*
+ ID_OUI_FROM_DATABASE=Airgo Networks, Inc.
+
+OUI:000AEC*
+ ID_OUI_FROM_DATABASE=Koatsu Gas Kogyo Co., Ltd.
+
+OUI:000AE5*
+ ID_OUI_FROM_DATABASE=ScottCare Corporation
+
+OUI:000AE7*
+ ID_OUI_FROM_DATABASE=ELIOP S.A.
+
+OUI:000AE0*
+ ID_OUI_FROM_DATABASE=Fujitsu Softek
+
+OUI:000AC8*
+ ID_OUI_FROM_DATABASE=ZPSYS CO.,LTD. (Planning&Management)
+
+OUI:000ACD*
+ ID_OUI_FROM_DATABASE=Sunrich Technology Limited
+
+OUI:000AD4*
+ ID_OUI_FROM_DATABASE=CoreBell Systems Inc.
+
+OUI:000AC1*
+ ID_OUI_FROM_DATABASE=Futuretel
+
+OUI:000AC6*
+ ID_OUI_FROM_DATABASE=Overture Networks.
+
 OUI:000994*
  ID_OUI_FROM_DATABASE=Cronyx Engineering
 
@@ -39635,11 +40733,35 @@ OUI:000968*
 OUI:000962*
  ID_OUI_FROM_DATABASE=Sonitor Technologies AS
 
-OUI:000A9B*
- ID_OUI_FROM_DATABASE=TB Group Inc
+OUI:000967*
+ ID_OUI_FROM_DATABASE=Tachyon, Inc
 
-OUI:000A9A*
- ID_OUI_FROM_DATABASE=Aiptek International Inc
+OUI:00096E*
+ ID_OUI_FROM_DATABASE=GIANT ELECTRONICS LTD.
+
+OUI:0009C3*
+ ID_OUI_FROM_DATABASE=NETAS
+
+OUI:0009B9*
+ ID_OUI_FROM_DATABASE=Action Imaging Solutions
+
+OUI:0009BA*
+ ID_OUI_FROM_DATABASE=MAKU Informationstechik GmbH
+
+OUI:0009AC*
+ ID_OUI_FROM_DATABASE=LANVOICE
+
+OUI:0009B3*
+ ID_OUI_FROM_DATABASE=MCM Systems Ltd
+
+OUI:0009A7*
+ ID_OUI_FROM_DATABASE=Bang & Olufsen A/S
+
+OUI:00099A*
+ ID_OUI_FROM_DATABASE=ELMO COMPANY, LIMITED
+
+OUI:0009A0*
+ ID_OUI_FROM_DATABASE=Microtechno Corporation
 
 OUI:000A80*
  ID_OUI_FROM_DATABASE=Telkonet Inc.
@@ -39668,35 +40790,8 @@ OUI:000A61*
 OUI:000A68*
  ID_OUI_FROM_DATABASE=SolarFlare Communications, Inc.
 
-OUI:0009C3*
- ID_OUI_FROM_DATABASE=NETAS
-
-OUI:0009B9*
- ID_OUI_FROM_DATABASE=Action Imaging Solutions
-
-OUI:0009BA*
- ID_OUI_FROM_DATABASE=MAKU Informationstechik GmbH
-
-OUI:0009AC*
- ID_OUI_FROM_DATABASE=LANVOICE
-
-OUI:0009B3*
- ID_OUI_FROM_DATABASE=MCM Systems Ltd
-
-OUI:0009A7*
- ID_OUI_FROM_DATABASE=Bang & Olufsen A/S
-
-OUI:00099A*
- ID_OUI_FROM_DATABASE=ELMO COMPANY, LIMITED
-
-OUI:0009A0*
- ID_OUI_FROM_DATABASE=Microtechno Corporation
-
-OUI:0009ED*
- ID_OUI_FROM_DATABASE=CipherOptics
-
-OUI:0009F2*
- ID_OUI_FROM_DATABASE=Cohu, Inc., Electronics Division
+OUI:000A5C*
+ ID_OUI_FROM_DATABASE=Carel s.p.a.
 
 OUI:0009E6*
  ID_OUI_FROM_DATABASE=Cyber Switching Inc.
@@ -39722,74 +40817,35 @@ OUI:0009CE*
 OUI:0009D3*
  ID_OUI_FROM_DATABASE=Western DataCom Co., Inc.
 
-OUI:000901*
- ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co
-
-OUI:0008FC*
- ID_OUI_FROM_DATABASE=Gigaphoton Inc.
-
-OUI:0008F9*
- ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
-
-OUI:0008F4*
- ID_OUI_FROM_DATABASE=Bluetake Technology Co., Ltd.
-
-OUI:0008EB*
- ID_OUI_FROM_DATABASE=ROMWin Co.,Ltd.
-
-OUI:0008E4*
- ID_OUI_FROM_DATABASE=Envenergy Inc
-
-OUI:0008DF*
- ID_OUI_FROM_DATABASE=Alistel Inc.
-
-OUI:0008D8*
- ID_OUI_FROM_DATABASE=Dowkey Microwave
-
-OUI:0008D2*
- ID_OUI_FROM_DATABASE=ZOOM Networks Inc.
-
-OUI:0008CC*
- ID_OUI_FROM_DATABASE=Remotec, Inc.
-
-OUI:0008D1*
- ID_OUI_FROM_DATABASE=KAREL INC.
-
-OUI:000967*
- ID_OUI_FROM_DATABASE=Tachyon, Inc
-
-OUI:00096E*
- ID_OUI_FROM_DATABASE=GIANT ELECTRONICS LTD.
-
-OUI:00095E*
- ID_OUI_FROM_DATABASE=Masstech Group Inc.
+OUI:000AAE*
+ ID_OUI_FROM_DATABASE=Rosemount Process Analytical
 
-OUI:000959*
- ID_OUI_FROM_DATABASE=Sitecsoft
+OUI:000AB3*
+ ID_OUI_FROM_DATABASE=Fa. GIRA
 
-OUI:00094D*
- ID_OUI_FROM_DATABASE=Braintree Communications Pty Ltd
+OUI:000AB5*
+ ID_OUI_FROM_DATABASE=Digital Electronic Network
 
-OUI:000952*
- ID_OUI_FROM_DATABASE=Auerswald GmbH & Co. KG
+OUI:000ABA*
+ ID_OUI_FROM_DATABASE=Arcon Technology Limited
 
-OUI:000946*
- ID_OUI_FROM_DATABASE=Cluster Labs GmbH
+OUI:000AA2*
+ ID_OUI_FROM_DATABASE=SYSTEK INC.
 
-OUI:000940*
- ID_OUI_FROM_DATABASE=AGFEO GmbH & Co. KG
+OUI:000AA7*
+ ID_OUI_FROM_DATABASE=FEI Electron Optics
 
-OUI:00093F*
- ID_OUI_FROM_DATABASE=Double-Win Enterpirse CO., LTD
+OUI:000A8F*
+ ID_OUI_FROM_DATABASE=Aska International Inc.
 
-OUI:00093A*
- ID_OUI_FROM_DATABASE=Molex Fiber Optics
+OUI:000A94*
+ ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD
 
-OUI:000933*
- ID_OUI_FROM_DATABASE=Ophit Co.Ltd.
+OUI:000A9B*
+ ID_OUI_FROM_DATABASE=TB Group Inc
 
-OUI:000A5C*
- ID_OUI_FROM_DATABASE=Carel s.p.a.
+OUI:000A9A*
+ ID_OUI_FROM_DATABASE=Aiptek International Inc
 
 OUI:000A50*
  ID_OUI_FROM_DATABASE=REMOTEK CORPORATION
@@ -39818,56 +40874,101 @@ OUI:000A3D*
 OUI:000A2F*
  ID_OUI_FROM_DATABASE=Artnix Inc.
 
-OUI:000927*
- ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD.
+OUI:000A20*
+ ID_OUI_FROM_DATABASE=SVA Networks, Inc.
 
-OUI:00092E*
- ID_OUI_FROM_DATABASE=B&Tech System Inc.
+OUI:000A25*
+ ID_OUI_FROM_DATABASE=CERAGON NETWORKS
 
-OUI:000920*
- ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD.
+OUI:000A14*
+ ID_OUI_FROM_DATABASE=TECO a.s.
 
-OUI:00091B*
- ID_OUI_FROM_DATABASE=Digital Generation Inc.
+OUI:000A19*
+ ID_OUI_FROM_DATABASE=Valere Power, Inc.
 
-OUI:000914*
- ID_OUI_FROM_DATABASE=COMPUTROLS INC.
+OUI:000A0D*
+ ID_OUI_FROM_DATABASE=FCI Deutschland GmbH
+
+OUI:000A12*
+ ID_OUI_FROM_DATABASE=Azylex Technology, Inc
+
+OUI:0009F9*
+ ID_OUI_FROM_DATABASE=ART JAPAN CO., LTD.
+
+OUI:0009FC*
+ ID_OUI_FROM_DATABASE=IPFLEX Inc.
+
+OUI:000A03*
+ ID_OUI_FROM_DATABASE=ENDESA SERVICIOS, S.L.
+
+OUI:0009ED*
+ ID_OUI_FROM_DATABASE=CipherOptics
+
+OUI:0009F2*
+ ID_OUI_FROM_DATABASE=Cohu, Inc., Electronics Division
+
+OUI:00095E*
+ ID_OUI_FROM_DATABASE=Masstech Group Inc.
+
+OUI:000959*
+ ID_OUI_FROM_DATABASE=Sitecsoft
+
+OUI:00094D*
+ ID_OUI_FROM_DATABASE=Braintree Communications Pty Ltd
+
+OUI:000952*
+ ID_OUI_FROM_DATABASE=Auerswald GmbH & Co. KG
+
+OUI:000946*
+ ID_OUI_FROM_DATABASE=Cluster Labs GmbH
+
+OUI:000940*
+ ID_OUI_FROM_DATABASE=AGFEO GmbH & Co. KG
+
+OUI:00093F*
+ ID_OUI_FROM_DATABASE=Double-Win Enterpirse CO., LTD
+
+OUI:00093A*
+ ID_OUI_FROM_DATABASE=Molex Fiber Optics
+
+OUI:000933*
+ ID_OUI_FROM_DATABASE=Ophit Co.Ltd.
 
-OUI:00090E*
- ID_OUI_FROM_DATABASE=Helix Technology Inc.
+OUI:00072C*
+ ID_OUI_FROM_DATABASE=Fabricom
 
-OUI:000908*
- ID_OUI_FROM_DATABASE=VTech Technology Corp.
+OUI:000733*
+ ID_OUI_FROM_DATABASE=DANCONTROL Engineering
 
-OUI:00090D*
- ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP.
+OUI:000732*
+ ID_OUI_FROM_DATABASE=AAEON Technology Inc.
 
-OUI:000A20*
- ID_OUI_FROM_DATABASE=SVA Networks, Inc.
+OUI:000716*
+ ID_OUI_FROM_DATABASE=J & S Marine Ltd.
 
-OUI:000A25*
- ID_OUI_FROM_DATABASE=CERAGON NETWORKS
+OUI:00071B*
+ ID_OUI_FROM_DATABASE=CDVI Americas Ltd
 
-OUI:000A14*
- ID_OUI_FROM_DATABASE=TECO a.s.
+OUI:000722*
+ ID_OUI_FROM_DATABASE=The Nielsen Company
 
-OUI:000A19*
- ID_OUI_FROM_DATABASE=Valere Power, Inc.
+OUI:00071C*
+ ID_OUI_FROM_DATABASE=AT&T Fixed Wireless Services
 
-OUI:000A0D*
- ID_OUI_FROM_DATABASE=FCI Deutschland GmbH
+OUI:00070A*
+ ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd.
 
-OUI:000A12*
- ID_OUI_FROM_DATABASE=Azylex Technology, Inc
+OUI:00070F*
+ ID_OUI_FROM_DATABASE=Fujant, Inc.
 
-OUI:0009F9*
- ID_OUI_FROM_DATABASE=ART JAPAN CO., LTD.
+OUI:000709*
+ ID_OUI_FROM_DATABASE=Westerstrand Urfabrik AB
 
-OUI:0009FC*
- ID_OUI_FROM_DATABASE=IPFLEX Inc.
+OUI:000702*
+ ID_OUI_FROM_DATABASE=Varian Medical Systems
 
-OUI:000A03*
- ID_OUI_FROM_DATABASE=ENDESA SERVICIOS, S.L.
+OUI:0006F3*
+ ID_OUI_FROM_DATABASE=AcceLight Networks
 
 OUI:0006F4*
  ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc.
@@ -39884,38 +40985,41 @@ OUI:0006FF*
 OUI:0006FD*
  ID_OUI_FROM_DATABASE=Comjet Information Systems Corp.
 
-OUI:0006E7*
- ID_OUI_FROM_DATABASE=Bit Blitz Communications Inc.
+OUI:00082D*
+ ID_OUI_FROM_DATABASE=Indus Teqsite Private Limited
 
-OUI:0006ED*
- ID_OUI_FROM_DATABASE=Inara Networks
+OUI:000821*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:0006DC*
- ID_OUI_FROM_DATABASE=Syabas Technology (Amquest)
+OUI:000814*
+ ID_OUI_FROM_DATABASE=TIL Technologies
 
-OUI:0006E1*
- ID_OUI_FROM_DATABASE=Techno Trade s.a
+OUI:00081A*
+ ID_OUI_FROM_DATABASE=Sanrad Intelligence Storage Communications (2000) Ltd.
 
-OUI:0006E6*
- ID_OUI_FROM_DATABASE=DongYang Telecom Co., Ltd.
+OUI:00080F*
+ ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB
 
-OUI:0006CF*
- ID_OUI_FROM_DATABASE=Thales Avionics In-Flight Systems, LLC
+OUI:000809*
+ ID_OUI_FROM_DATABASE=Systemonic AG
 
-OUI:0006D6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000803*
+ ID_OUI_FROM_DATABASE=Cos Tron
 
-OUI:0006D5*
- ID_OUI_FROM_DATABASE=Diamond Systems Corp.
+OUI:0007FF*
+ ID_OUI_FROM_DATABASE=Gluon Networks
 
-OUI:0006C9*
- ID_OUI_FROM_DATABASE=Technical Marketing Research, Inc.
+OUI:0007F9*
+ ID_OUI_FROM_DATABASE=Sensaphone
 
-OUI:0007B1*
- ID_OUI_FROM_DATABASE=Equator Technologies
+OUI:0007F3*
+ ID_OUI_FROM_DATABASE=Thinkengine Networks
 
-OUI:0007B8*
- ID_OUI_FROM_DATABASE=Corvalent Corporation
+OUI:0007EC*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:0007F2*
+ ID_OUI_FROM_DATABASE=IOA Corporation
 
 OUI:0007B2*
  ID_OUI_FROM_DATABASE=Transaccess S.A.
@@ -39953,41 +41057,11 @@ OUI:000785*
 OUI:00077B*
  ID_OUI_FROM_DATABASE=Millimetrix Broadband Networks
 
-OUI:000856*
- ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd.
-
-OUI:00082D*
- ID_OUI_FROM_DATABASE=Indus Teqsite Private Limited
-
-OUI:000821*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:000814*
- ID_OUI_FROM_DATABASE=TIL Technologies
-
-OUI:00081A*
- ID_OUI_FROM_DATABASE=Sanrad Intelligence Storage Communications (2000) Ltd.
-
-OUI:00080F*
- ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB
-
-OUI:000809*
- ID_OUI_FROM_DATABASE=Systemonic AG
-
-OUI:000803*
- ID_OUI_FROM_DATABASE=Cos Tron
-
-OUI:0007FF*
- ID_OUI_FROM_DATABASE=Gluon Networks
-
-OUI:0007F9*
- ID_OUI_FROM_DATABASE=Sensaphone
-
-OUI:000894*
- ID_OUI_FROM_DATABASE=InnoVISION Multimedia Ltd.
+OUI:00077E*
+ ID_OUI_FROM_DATABASE=Elrest GmbH
 
-OUI:00088F*
- ID_OUI_FROM_DATABASE=ADVANCED DIGITAL TECHNOLOGY
+OUI:00076F*
+ ID_OUI_FROM_DATABASE=Synoptics Limited
 
 OUI:000888*
  ID_OUI_FROM_DATABASE=OULLIM Information Technology Inc,.
@@ -40022,89 +41096,35 @@ OUI:000862*
 OUI:000850*
  ID_OUI_FROM_DATABASE=Arizona Instrument Corp.
 
-OUI:000738*
- ID_OUI_FROM_DATABASE=Young Technology Co., Ltd.
-
-OUI:00073F*
- ID_OUI_FROM_DATABASE=Woojyun Systec Co., Ltd.
-
-OUI:00072C*
- ID_OUI_FROM_DATABASE=Fabricom
-
-OUI:000733*
- ID_OUI_FROM_DATABASE=DANCONTROL Engineering
-
-OUI:000732*
- ID_OUI_FROM_DATABASE=AAEON Technology Inc.
-
-OUI:000716*
- ID_OUI_FROM_DATABASE=J & S Marine Ltd.
-
-OUI:00071B*
- ID_OUI_FROM_DATABASE=CDVI Americas Ltd
-
-OUI:000722*
- ID_OUI_FROM_DATABASE=The Nielsen Company
-
-OUI:00071C*
- ID_OUI_FROM_DATABASE=AT&T Fixed Wireless Services
-
-OUI:00070A*
- ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd.
-
-OUI:00070F*
- ID_OUI_FROM_DATABASE=Fujant, Inc.
-
-OUI:000709*
- ID_OUI_FROM_DATABASE=Westerstrand Urfabrik AB
-
-OUI:000702*
- ID_OUI_FROM_DATABASE=Varian Medical Systems
-
-OUI:0006F3*
- ID_OUI_FROM_DATABASE=AcceLight Networks
-
-OUI:0006C3*
- ID_OUI_FROM_DATABASE=Schindler Elevator Ltd.
-
-OUI:0006C8*
- ID_OUI_FROM_DATABASE=Sumitomo Metal Micro Devices, Inc.
-
-OUI:0006BF*
- ID_OUI_FROM_DATABASE=Accella Technologies Co., Ltd.
-
-OUI:0006B9*
- ID_OUI_FROM_DATABASE=A5TEK Corp.
-
-OUI:0006B2*
- ID_OUI_FROM_DATABASE=Linxtek Co.
+OUI:000856*
+ ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd.
 
-OUI:0006AC*
- ID_OUI_FROM_DATABASE=Intersoft Co.
+OUI:000927*
+ ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD.
 
-OUI:0006A6*
- ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd
+OUI:00092E*
+ ID_OUI_FROM_DATABASE=B&Tech System Inc.
 
-OUI:0006A2*
- ID_OUI_FROM_DATABASE=Microtune, Inc.
+OUI:000920*
+ ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD.
 
-OUI:000695*
- ID_OUI_FROM_DATABASE=Ensure Technologies, Inc.
+OUI:00091B*
+ ID_OUI_FROM_DATABASE=Digital Generation Inc.
 
-OUI:00069C*
- ID_OUI_FROM_DATABASE=Transmode Systems AB
+OUI:000914*
+ ID_OUI_FROM_DATABASE=COMPUTROLS INC.
 
-OUI:000696*
- ID_OUI_FROM_DATABASE=Advent Networks
+OUI:00090E*
+ ID_OUI_FROM_DATABASE=Helix Technology Inc.
 
-OUI:0007F3*
- ID_OUI_FROM_DATABASE=Thinkengine Networks
+OUI:000908*
+ ID_OUI_FROM_DATABASE=VTech Technology Corp.
 
-OUI:0007EC*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00090D*
+ ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP.
 
-OUI:0007F2*
- ID_OUI_FROM_DATABASE=IOA Corporation
+OUI:000901*
+ ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co
 
 OUI:0007E6*
  ID_OUI_FROM_DATABASE=edgeflow Canada Inc.
@@ -40130,11 +41150,11 @@ OUI:0007C4*
 OUI:0007BE*
  ID_OUI_FROM_DATABASE=DataLogic SpA
 
-OUI:00077E*
- ID_OUI_FROM_DATABASE=Elrest GmbH
+OUI:0007B1*
+ ID_OUI_FROM_DATABASE=Equator Technologies
 
-OUI:00076F*
- ID_OUI_FROM_DATABASE=Synoptics Limited
+OUI:0007B8*
+ ID_OUI_FROM_DATABASE=Corvalent Corporation
 
 OUI:00076E*
  ID_OUI_FROM_DATABASE=Sinetica Corporation Limited
@@ -40166,8 +41186,11 @@ OUI:00074B*
 OUI:000745*
  ID_OUI_FROM_DATABASE=Radlan Computer Communications Ltd.
 
-OUI:0008C2*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:000738*
+ ID_OUI_FROM_DATABASE=Young Technology Co., Ltd.
+
+OUI:00073F*
+ ID_OUI_FROM_DATABASE=Woojyun Systec Co., Ltd.
 
 OUI:0008BB*
  ID_OUI_FROM_DATABASE=NetExcell
@@ -40193,8 +41216,44 @@ OUI:0008A3*
 OUI:00089C*
  ID_OUI_FROM_DATABASE=Elecs Industry Co., Ltd.
 
-OUI:000690*
- ID_OUI_FROM_DATABASE=Euracom Communication GmbH
+OUI:000894*
+ ID_OUI_FROM_DATABASE=InnoVISION Multimedia Ltd.
+
+OUI:00088F*
+ ID_OUI_FROM_DATABASE=ADVANCED DIGITAL TECHNOLOGY
+
+OUI:0008FC*
+ ID_OUI_FROM_DATABASE=Gigaphoton Inc.
+
+OUI:0008F9*
+ ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies
+
+OUI:0008F4*
+ ID_OUI_FROM_DATABASE=Bluetake Technology Co., Ltd.
+
+OUI:0008EB*
+ ID_OUI_FROM_DATABASE=ROMWin Co.,Ltd.
+
+OUI:0008E4*
+ ID_OUI_FROM_DATABASE=Envenergy Inc
+
+OUI:0008DF*
+ ID_OUI_FROM_DATABASE=Alistel Inc.
+
+OUI:0008D8*
+ ID_OUI_FROM_DATABASE=Dowkey Microwave
+
+OUI:0008D2*
+ ID_OUI_FROM_DATABASE=ZOOM Networks Inc.
+
+OUI:0008CC*
+ ID_OUI_FROM_DATABASE=Remotec, Inc.
+
+OUI:0008D1*
+ ID_OUI_FROM_DATABASE=KAREL INC.
+
+OUI:0008C2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:00068F*
  ID_OUI_FROM_DATABASE=Telemonitor, Inc.
@@ -40235,11 +41294,11 @@ OUI:00055A*
 OUI:00065C*
  ID_OUI_FROM_DATABASE=Malachite Technologies, Inc.
 
-OUI:000610*
- ID_OUI_FROM_DATABASE=Abeona Networks Inc
+OUI:000650*
+ ID_OUI_FROM_DATABASE=Tiburon Networks, Inc.
 
-OUI:000616*
- ID_OUI_FROM_DATABASE=Tel Net Co., Ltd.
+OUI:000656*
+ ID_OUI_FROM_DATABASE=Tactel AB
 
 OUI:00060A*
  ID_OUI_FROM_DATABASE=Blue2space
@@ -40286,6 +41345,39 @@ OUI:0005CF*
 OUI:0005C9*
  ID_OUI_FROM_DATABASE=LG Innotek Co., Ltd.
 
+OUI:0006E7*
+ ID_OUI_FROM_DATABASE=Bit Blitz Communications Inc.
+
+OUI:0006ED*
+ ID_OUI_FROM_DATABASE=Inara Networks
+
+OUI:0006DC*
+ ID_OUI_FROM_DATABASE=Syabas Technology (Amquest)
+
+OUI:0006E1*
+ ID_OUI_FROM_DATABASE=Techno Trade s.a
+
+OUI:0006E6*
+ ID_OUI_FROM_DATABASE=DongYang Telecom Co., Ltd.
+
+OUI:0006CF*
+ ID_OUI_FROM_DATABASE=Thales Avionics In-Flight Systems, LLC
+
+OUI:0006D6*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:0006D5*
+ ID_OUI_FROM_DATABASE=Diamond Systems Corp.
+
+OUI:0006C9*
+ ID_OUI_FROM_DATABASE=Technical Marketing Research, Inc.
+
+OUI:0006C3*
+ ID_OUI_FROM_DATABASE=Schindler Elevator Ltd.
+
+OUI:0006C8*
+ ID_OUI_FROM_DATABASE=Sumitomo Metal Micro Devices, Inc.
+
 OUI:0005D5*
  ID_OUI_FROM_DATABASE=Speedcom Wireless
 
@@ -40310,50 +41402,17 @@ OUI:0005A2*
 OUI:0005AC*
  ID_OUI_FROM_DATABASE=Northern Digital, Inc.
 
-OUI:0004E5*
- ID_OUI_FROM_DATABASE=Glonet Systems, Inc.
-
-OUI:0004D9*
- ID_OUI_FROM_DATABASE=Titan Electronics, Inc.
-
-OUI:0004D3*
- ID_OUI_FROM_DATABASE=Toyokeiki Co., Ltd.
-
-OUI:0004CC*
- ID_OUI_FROM_DATABASE=Peek Traffic B.V.
-
-OUI:0004C0*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:0004C6*
- ID_OUI_FROM_DATABASE=Yamaha Motor Co., Ltd.
-
-OUI:0004B9*
- ID_OUI_FROM_DATABASE=S.I. Soubou, Inc.
-
-OUI:0004BA*
- ID_OUI_FROM_DATABASE=KDD Media Will Corporation
-
-OUI:0004AF*
- ID_OUI_FROM_DATABASE=Digital Fountain, Inc.
-
-OUI:0004B4*
- ID_OUI_FROM_DATABASE=CIAC
-
-OUI:0004B3*
- ID_OUI_FROM_DATABASE=Videotek, Inc.
-
-OUI:0004A6*
- ID_OUI_FROM_DATABASE=SAF Tehnika Ltd.
+OUI:000589*
+ ID_OUI_FROM_DATABASE=National Datacomputer
 
-OUI:0004A0*
- ID_OUI_FROM_DATABASE=Verity Instruments, Inc.
+OUI:000595*
+ ID_OUI_FROM_DATABASE=Alesis Corporation
 
-OUI:00050C*
- ID_OUI_FROM_DATABASE=Network Photonics, Inc.
+OUI:00058F*
+ ID_OUI_FROM_DATABASE=CLCsoft co.
 
-OUI:000512*
- ID_OUI_FROM_DATABASE=Zebra Technologies Inc
+OUI:000596*
+ ID_OUI_FROM_DATABASE=Genotech Co., Ltd.
 
 OUI:000506*
  ID_OUI_FROM_DATABASE=Reddo Networks AB
@@ -40379,11 +41438,47 @@ OUI:0004EF*
 OUI:0004DF*
  ID_OUI_FROM_DATABASE=Teracom Telematica Ltda.
 
-OUI:000553*
- ID_OUI_FROM_DATABASE=DVC Company, Inc.
+OUI:0004E5*
+ ID_OUI_FROM_DATABASE=Glonet Systems, Inc.
 
-OUI:000548*
- ID_OUI_FROM_DATABASE=Disco Corporation
+OUI:0004D9*
+ ID_OUI_FROM_DATABASE=Titan Electronics, Inc.
+
+OUI:00062D*
+ ID_OUI_FROM_DATABASE=TouchStar Technologies, L.L.C.
+
+OUI:000649*
+ ID_OUI_FROM_DATABASE=3M Deutschland GmbH
+
+OUI:000643*
+ ID_OUI_FROM_DATABASE=SONO Computer Co., Ltd.
+
+OUI:00064A*
+ ID_OUI_FROM_DATABASE=Honeywell Co., Ltd. (KOREA)
+
+OUI:00063F*
+ ID_OUI_FROM_DATABASE=Everex Communications Inc.
+
+OUI:000639*
+ ID_OUI_FROM_DATABASE=Newtec
+
+OUI:000633*
+ ID_OUI_FROM_DATABASE=Cross Match Technologies GmbH
+
+OUI:000626*
+ ID_OUI_FROM_DATABASE=MWE GmbH
+
+OUI:00061D*
+ ID_OUI_FROM_DATABASE=MIP Telecom, Inc.
+
+OUI:000623*
+ ID_OUI_FROM_DATABASE=MGE UPS Systems France
+
+OUI:000610*
+ ID_OUI_FROM_DATABASE=Abeona Networks Inc
+
+OUI:000616*
+ ID_OUI_FROM_DATABASE=Tel Net Co., Ltd.
 
 OUI:00054D*
  ID_OUI_FROM_DATABASE=Brans Technologies, Inc.
@@ -40418,53 +41513,41 @@ OUI:00051C*
 OUI:000516*
  ID_OUI_FROM_DATABASE=SMART Modular Technologies
 
-OUI:000650*
- ID_OUI_FROM_DATABASE=Tiburon Networks, Inc.
-
-OUI:000656*
- ID_OUI_FROM_DATABASE=Tactel AB
-
-OUI:00062D*
- ID_OUI_FROM_DATABASE=TouchStar Technologies, L.L.C.
-
-OUI:000649*
- ID_OUI_FROM_DATABASE=3M Deutschland GmbH
-
-OUI:000643*
- ID_OUI_FROM_DATABASE=SONO Computer Co., Ltd.
+OUI:00050C*
+ ID_OUI_FROM_DATABASE=Network Photonics, Inc.
 
-OUI:00064A*
- ID_OUI_FROM_DATABASE=Honeywell Co., Ltd. (KOREA)
+OUI:000512*
+ ID_OUI_FROM_DATABASE=Zebra Technologies Inc
 
-OUI:00063F*
- ID_OUI_FROM_DATABASE=Everex Communications Inc.
+OUI:0006BF*
+ ID_OUI_FROM_DATABASE=Accella Technologies Co., Ltd.
 
-OUI:000639*
- ID_OUI_FROM_DATABASE=Newtec
+OUI:0006B9*
+ ID_OUI_FROM_DATABASE=A5TEK Corp.
 
-OUI:000633*
- ID_OUI_FROM_DATABASE=Cross Match Technologies GmbH
+OUI:0006B2*
+ ID_OUI_FROM_DATABASE=Linxtek Co.
 
-OUI:000626*
- ID_OUI_FROM_DATABASE=MWE GmbH
+OUI:0006AC*
+ ID_OUI_FROM_DATABASE=Intersoft Co.
 
-OUI:00061D*
- ID_OUI_FROM_DATABASE=MIP Telecom, Inc.
+OUI:0006A6*
+ ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd
 
-OUI:000623*
- ID_OUI_FROM_DATABASE=MGE UPS Systems France
+OUI:0006A2*
+ ID_OUI_FROM_DATABASE=Microtune, Inc.
 
-OUI:000589*
- ID_OUI_FROM_DATABASE=National Datacomputer
+OUI:000695*
+ ID_OUI_FROM_DATABASE=Ensure Technologies, Inc.
 
-OUI:000595*
- ID_OUI_FROM_DATABASE=Alesis Corporation
+OUI:00069C*
+ ID_OUI_FROM_DATABASE=Transmode Systems AB
 
-OUI:00058F*
- ID_OUI_FROM_DATABASE=CLCsoft co.
+OUI:000696*
+ ID_OUI_FROM_DATABASE=Advent Networks
 
-OUI:000596*
- ID_OUI_FROM_DATABASE=Genotech Co., Ltd.
+OUI:000690*
+ ID_OUI_FROM_DATABASE=Euracom Communication GmbH
 
 OUI:00057D*
  ID_OUI_FROM_DATABASE=Sun Communications, Inc.
@@ -40490,47 +41573,14 @@ OUI:000566*
 OUI:000560*
  ID_OUI_FROM_DATABASE=LEADER COMM.CO., LTD
 
-OUI:000559*
- ID_OUI_FROM_DATABASE=Intracom S.A.
-
-OUI:0004A5*
- ID_OUI_FROM_DATABASE=Barco Projection Systems NV
-
-OUI:000499*
- ID_OUI_FROM_DATABASE=Chino Corporation
-
-OUI:00048D*
- ID_OUI_FROM_DATABASE=Teo Technologies, Inc
-
-OUI:000493*
- ID_OUI_FROM_DATABASE=Tsinghua Unisplendour Co., Ltd.
-
-OUI:000484*
- ID_OUI_FROM_DATABASE=Amann GmbH
-
-OUI:00048A*
- ID_OUI_FROM_DATABASE=Temia Vertriebs GmbH
-
-OUI:00047A*
- ID_OUI_FROM_DATABASE=AXXESSIT ASA
-
-OUI:000474*
- ID_OUI_FROM_DATABASE=LEGRAND
-
-OUI:00046E*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:000473*
- ID_OUI_FROM_DATABASE=Photonex Corporation
-
-OUI:000467*
- ID_OUI_FROM_DATABASE=Wuhan Research Institute of MII
-
-OUI:000461*
- ID_OUI_FROM_DATABASE=EPOX Computer Co., Ltd.
+OUI:000559*
+ ID_OUI_FROM_DATABASE=Intracom S.A.
 
-OUI:0003D9*
- ID_OUI_FROM_DATABASE=Secheron SA
+OUI:000553*
+ ID_OUI_FROM_DATABASE=DVC Company, Inc.
+
+OUI:000548*
+ ID_OUI_FROM_DATABASE=Disco Corporation
 
 OUI:0003D2*
  ID_OUI_FROM_DATABASE=Crossbeam Systems, Inc.
@@ -40565,6 +41615,48 @@ OUI:0003A8*
 OUI:0003A1*
  ID_OUI_FROM_DATABASE=HIPER Information & Communication, Inc.
 
+OUI:00044E*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00044F*
+ ID_OUI_FROM_DATABASE=Schubert System Elektronik Gmbh
+
+OUI:000454*
+ ID_OUI_FROM_DATABASE=Quadriga UK
+
+OUI:000445*
+ ID_OUI_FROM_DATABASE=LMS Skalar Instruments GmbH
+
+OUI:00044A*
+ ID_OUI_FROM_DATABASE=iPolicy Networks, Inc.
+
+OUI:000444*
+ ID_OUI_FROM_DATABASE=Western Multiplex Corporation
+
+OUI:00043E*
+ ID_OUI_FROM_DATABASE=Telencomm
+
+OUI:000438*
+ ID_OUI_FROM_DATABASE=Nortel Networks
+
+OUI:000432*
+ ID_OUI_FROM_DATABASE=Voyetra Turtle Beach, Inc.
+
+OUI:000437*
+ ID_OUI_FROM_DATABASE=Powin Information Technology, Inc.
+
+OUI:00042B*
+ ID_OUI_FROM_DATABASE=IT Access Co., Ltd.
+
+OUI:000425*
+ ID_OUI_FROM_DATABASE=Atmel Corporation
+
+OUI:000419*
+ ID_OUI_FROM_DATABASE=Fibercycle Networks, Inc.
+
+OUI:00041A*
+ ID_OUI_FROM_DATABASE=Ines Test and Measurement GmbH & CoKG
+
 OUI:000399*
  ID_OUI_FROM_DATABASE=Dongju Informations & Communications Co., Ltd.
 
@@ -40595,8 +41687,8 @@ OUI:000371*
 OUI:00036D*
  ID_OUI_FROM_DATABASE=Runtop, Inc.
 
-OUI:0002E3*
- ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc.
+OUI:000361*
+ ID_OUI_FROM_DATABASE=Widcomm, Inc.
 
 OUI:0002DE*
  ID_OUI_FROM_DATABASE=Astrodesign, Inc.
@@ -40637,44 +41729,8 @@ OUI:0002AF*
 OUI:0002AA*
  ID_OUI_FROM_DATABASE=PLcom Co., Ltd.
 
-OUI:00045B*
- ID_OUI_FROM_DATABASE=Techsan Electronics Co., Ltd.
-
-OUI:00044E*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
-OUI:00044F*
- ID_OUI_FROM_DATABASE=Schubert System Elektronik Gmbh
-
-OUI:000454*
- ID_OUI_FROM_DATABASE=Quadriga UK
-
-OUI:000445*
- ID_OUI_FROM_DATABASE=LMS Skalar Instruments GmbH
-
-OUI:00044A*
- ID_OUI_FROM_DATABASE=iPolicy Networks, Inc.
-
-OUI:000444*
- ID_OUI_FROM_DATABASE=Western Multiplex Corporation
-
-OUI:00043E*
- ID_OUI_FROM_DATABASE=Telencomm
-
-OUI:000438*
- ID_OUI_FROM_DATABASE=Nortel Networks
-
-OUI:000432*
- ID_OUI_FROM_DATABASE=Voyetra Turtle Beach, Inc.
-
-OUI:000437*
- ID_OUI_FROM_DATABASE=Powin Information Technology, Inc.
-
-OUI:00042B*
- ID_OUI_FROM_DATABASE=IT Access Co., Ltd.
-
-OUI:000361*
- ID_OUI_FROM_DATABASE=Widcomm, Inc.
+OUI:0002A3*
+ ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems
 
 OUI:00035A*
  ID_OUI_FROM_DATABASE=Photron Limited
@@ -40754,50 +41810,77 @@ OUI:0002F5*
 OUI:0002EA*
  ID_OUI_FROM_DATABASE=Focus Enhancements
 
-OUI:000269*
- ID_OUI_FROM_DATABASE=Nadatel Co., Ltd
+OUI:0002E3*
+ ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc.
 
-OUI:000265*
- ID_OUI_FROM_DATABASE=Virditech Co. Ltd.
+OUI:0004D3*
+ ID_OUI_FROM_DATABASE=Toyokeiki Co., Ltd.
 
-OUI:00025E*
- ID_OUI_FROM_DATABASE=High Technology Ltd
+OUI:0004CC*
+ ID_OUI_FROM_DATABASE=Peek Traffic B.V.
 
-OUI:000261*
- ID_OUI_FROM_DATABASE=Tilgin AB
+OUI:0004C0*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:000259*
- ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group
+OUI:0004B9*
+ ID_OUI_FROM_DATABASE=S.I. Soubou, Inc.
 
-OUI:000255*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0004BA*
+ ID_OUI_FROM_DATABASE=KDD Media Will Corporation
 
-OUI:000249*
- ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd.
+OUI:0004AF*
+ ID_OUI_FROM_DATABASE=Digital Fountain, Inc.
 
-OUI:000250*
- ID_OUI_FROM_DATABASE=Geyser Networks, Inc.
+OUI:0004B4*
+ ID_OUI_FROM_DATABASE=CIAC
 
-OUI:000242*
- ID_OUI_FROM_DATABASE=Videoframe Systems
+OUI:0004B3*
+ ID_OUI_FROM_DATABASE=Videotek, Inc.
 
-OUI:000244*
- ID_OUI_FROM_DATABASE=SURECOM Technology Co.
+OUI:0004A6*
+ ID_OUI_FROM_DATABASE=SAF Tehnika Ltd.
 
-OUI:00022C*
- ID_OUI_FROM_DATABASE=ABB Bomem, Inc.
+OUI:0004A0*
+ ID_OUI_FROM_DATABASE=Verity Instruments, Inc.
 
-OUI:00023A*
- ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH
+OUI:0004A5*
+ ID_OUI_FROM_DATABASE=Barco Projection Systems NV
 
-OUI:000425*
- ID_OUI_FROM_DATABASE=Atmel Corporation
+OUI:000499*
+ ID_OUI_FROM_DATABASE=Chino Corporation
 
-OUI:000419*
- ID_OUI_FROM_DATABASE=Fibercycle Networks, Inc.
+OUI:00048D*
+ ID_OUI_FROM_DATABASE=Teo Technologies, Inc
 
-OUI:00041A*
- ID_OUI_FROM_DATABASE=Ines Test and Measurement GmbH & CoKG
+OUI:000493*
+ ID_OUI_FROM_DATABASE=Tsinghua Unisplendour Co., Ltd.
+
+OUI:000484*
+ ID_OUI_FROM_DATABASE=Amann GmbH
+
+OUI:00048A*
+ ID_OUI_FROM_DATABASE=Temia Vertriebs GmbH
+
+OUI:00047A*
+ ID_OUI_FROM_DATABASE=AXXESSIT ASA
+
+OUI:000474*
+ ID_OUI_FROM_DATABASE=LEGRAND
+
+OUI:00046E*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:000473*
+ ID_OUI_FROM_DATABASE=Photonex Corporation
+
+OUI:000467*
+ ID_OUI_FROM_DATABASE=Wuhan Research Institute of MII
+
+OUI:000461*
+ ID_OUI_FROM_DATABASE=EPOX Computer Co., Ltd.
+
+OUI:00045B*
+ ID_OUI_FROM_DATABASE=Techsan Electronics Co., Ltd.
 
 OUI:000414*
  ID_OUI_FROM_DATABASE=Umezawa Musen Denki Co., Ltd.
@@ -40826,38 +41909,77 @@ OUI:0003EB*
 OUI:0003E5*
  ID_OUI_FROM_DATABASE=Hermstedt SG
 
-OUI:0002A3*
- ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems
+OUI:0003D9*
+ ID_OUI_FROM_DATABASE=Secheron SA
 
-OUI:000298*
- ID_OUI_FROM_DATABASE=Broadframe Corporation
+OUI:00022F*
+ ID_OUI_FROM_DATABASE=P-Cube, Ltd.
 
-OUI:000292*
- ID_OUI_FROM_DATABASE=Logic Innovations, Inc.
+OUI:000227*
+ ID_OUI_FROM_DATABASE=ESD Electronic System Design GmbH
 
-OUI:00028D*
- ID_OUI_FROM_DATABASE=Movita Technologies, Inc.
+OUI:00021F*
+ ID_OUI_FROM_DATABASE=Aculab PLC
 
-OUI:000283*
- ID_OUI_FROM_DATABASE=Spectrum Controls, Inc.
+OUI:00021B*
+ ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix
 
-OUI:000277*
- ID_OUI_FROM_DATABASE=Cash Systemes Industrie
+OUI:00020C*
+ ID_OUI_FROM_DATABASE=Metro-Optix
 
-OUI:00027C*
- ID_OUI_FROM_DATABASE=Trilithic, Inc.
+OUI:000218*
+ ID_OUI_FROM_DATABASE=Advanced Scientific Corp
 
-OUI:000275*
- ID_OUI_FROM_DATABASE=SMART Technologies, Inc.
+OUI:000213*
+ ID_OUI_FROM_DATABASE=S.D.E.L.
 
-OUI:000270*
- ID_OUI_FROM_DATABASE=Crewave Co., Ltd.
+OUI:00020F*
+ ID_OUI_FROM_DATABASE=AATR
 
-OUI:000104*
- ID_OUI_FROM_DATABASE=DVICO Co., Ltd.
+OUI:0001F9*
+ ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp.
 
-OUI:000110*
- ID_OUI_FROM_DATABASE=Gotham Networks
+OUI:000200*
+ ID_OUI_FROM_DATABASE=Net & Sys Co., Ltd.
+
+OUI:00015E*
+ ID_OUI_FROM_DATABASE=BEST TECHNOLOGY CO., LTD.
+
+OUI:000162*
+ ID_OUI_FROM_DATABASE=Cygnet Technologies, Inc.
+
+OUI:000169*
+ ID_OUI_FROM_DATABASE=Celestix Networks Pte Ltd.
+
+OUI:000175*
+ ID_OUI_FROM_DATABASE=Radiant Communications Corp.
+
+OUI:000159*
+ ID_OUI_FROM_DATABASE=S1 Corporation
+
+OUI:000165*
+ ID_OUI_FROM_DATABASE=AirSwitch Corporation
+
+OUI:000171*
+ ID_OUI_FROM_DATABASE=Allied Data Technologies
+
+OUI:000157*
+ ID_OUI_FROM_DATABASE=SYSWAVE CO., LTD
+
+OUI:000153*
+ ID_OUI_FROM_DATABASE=ARCHTEK TELECOM CORPORATION
+
+OUI:000144*
+ ID_OUI_FROM_DATABASE=EMC Corporation
+
+OUI:00014B*
+ ID_OUI_FROM_DATABASE=Ennovate Networks, Inc.
+
+OUI:00012C*
+ ID_OUI_FROM_DATABASE=Aravox Technologies, Inc.
+
+OUI:000138*
+ ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
 
 OUI:00010C*
  ID_OUI_FROM_DATABASE=System Talks Inc.
@@ -40892,41 +42014,32 @@ OUI:00B091*
 OUI:0030BE*
  ID_OUI_FROM_DATABASE=City-Net Technology, Inc.
 
-OUI:000233*
- ID_OUI_FROM_DATABASE=Mantra Communications, Inc.
-
-OUI:00022F*
- ID_OUI_FROM_DATABASE=P-Cube, Ltd.
-
-OUI:000227*
- ID_OUI_FROM_DATABASE=ESD Electronic System Design GmbH
-
-OUI:00021F*
- ID_OUI_FROM_DATABASE=Aculab PLC
+OUI:00303E*
+ ID_OUI_FROM_DATABASE=Radcom Ltd.
 
-OUI:00021B*
- ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix
+OUI:0030D7*
+ ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C.
 
-OUI:00020C*
- ID_OUI_FROM_DATABASE=Metro-Optix
+OUI:0030FC*
+ ID_OUI_FROM_DATABASE=Terawave Communications, Inc.
 
-OUI:000218*
- ID_OUI_FROM_DATABASE=Advanced Scientific Corp
+OUI:00300F*
+ ID_OUI_FROM_DATABASE=IMT - Information Management T
 
-OUI:000213*
- ID_OUI_FROM_DATABASE=S.D.E.L.
+OUI:003004*
+ ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC.
 
-OUI:00020F*
- ID_OUI_FROM_DATABASE=AATR
+OUI:003018*
+ ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd.
 
-OUI:0001F4*
- ID_OUI_FROM_DATABASE=Enterasys Networks
+OUI:003088*
+ ID_OUI_FROM_DATABASE=Ericsson
 
-OUI:0001F9*
- ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp.
+OUI:0030CA*
+ ID_OUI_FROM_DATABASE=Discovery Com
 
-OUI:000200*
- ID_OUI_FROM_DATABASE=Net & Sys Co., Ltd.
+OUI:00304F*
+ ID_OUI_FROM_DATABASE=PLANET Technology Corporation
 
 OUI:0001FC*
  ID_OUI_FROM_DATABASE=Keyence Corporation
@@ -40961,80 +42074,44 @@ OUI:0001D1*
 OUI:0001B3*
  ID_OUI_FROM_DATABASE=Precision Electronic Manufacturing
 
-OUI:000160*
- ID_OUI_FROM_DATABASE=ELMEX Co., LTD.
-
-OUI:00015E*
- ID_OUI_FROM_DATABASE=BEST TECHNOLOGY CO., LTD.
-
-OUI:000162*
- ID_OUI_FROM_DATABASE=Cygnet Technologies, Inc.
-
-OUI:000169*
- ID_OUI_FROM_DATABASE=Celestix Networks Pte Ltd.
-
-OUI:000175*
- ID_OUI_FROM_DATABASE=Radiant Communications Corp.
-
-OUI:000159*
- ID_OUI_FROM_DATABASE=S1 Corporation
-
-OUI:000165*
- ID_OUI_FROM_DATABASE=AirSwitch Corporation
-
-OUI:000171*
- ID_OUI_FROM_DATABASE=Allied Data Technologies
-
-OUI:000157*
- ID_OUI_FROM_DATABASE=SYSWAVE CO., LTD
-
-OUI:000153*
- ID_OUI_FROM_DATABASE=ARCHTEK TELECOM CORPORATION
-
-OUI:000144*
- ID_OUI_FROM_DATABASE=EMC Corporation
-
-OUI:003038*
- ID_OUI_FROM_DATABASE=XCP, INC.
-
-OUI:0030DB*
- ID_OUI_FROM_DATABASE=Mindready Solutions, Inc.
+OUI:0001B1*
+ ID_OUI_FROM_DATABASE=General Bandwidth
 
-OUI:00306A*
- ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD.
+OUI:0001BB*
+ ID_OUI_FROM_DATABASE=Frequentis
 
-OUI:003021*
- ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD
+OUI:00025E*
+ ID_OUI_FROM_DATABASE=High Technology Ltd
 
-OUI:0030EA*
- ID_OUI_FROM_DATABASE=TeraForce Technology Corporation
+OUI:000261*
+ ID_OUI_FROM_DATABASE=Tilgin AB
 
-OUI:0030F4*
- ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES
+OUI:000259*
+ ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group
 
-OUI:003087*
- ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG
+OUI:000255*
+ ID_OUI_FROM_DATABASE=IBM Corp
 
-OUI:003000*
- ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP.
+OUI:000249*
+ ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd.
 
-OUI:003034*
- ID_OUI_FROM_DATABASE=SET ENGINEERING
+OUI:000250*
+ ID_OUI_FROM_DATABASE=Geyser Networks, Inc.
 
-OUI:00308D*
- ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc.
+OUI:000242*
+ ID_OUI_FROM_DATABASE=Videoframe Systems
 
-OUI:00304B*
- ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC.
+OUI:000244*
+ ID_OUI_FROM_DATABASE=SURECOM Technology Co.
 
-OUI:0030FA*
- ID_OUI_FROM_DATABASE=TELICA, INC.
+OUI:00022C*
+ ID_OUI_FROM_DATABASE=ABB Bomem, Inc.
 
-OUI:0001B1*
- ID_OUI_FROM_DATABASE=General Bandwidth
+OUI:00023A*
+ ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH
 
-OUI:0001BB*
- ID_OUI_FROM_DATABASE=Frequentis
+OUI:000233*
+ ID_OUI_FROM_DATABASE=Mantra Communications, Inc.
 
 OUI:0001B7*
  ID_OUI_FROM_DATABASE=Centos, Inc.
@@ -41078,41 +42155,38 @@ OUI:0030F5*
 OUI:000184*
  ID_OUI_FROM_DATABASE=SIEB & MEYER AG
 
-OUI:00303E*
- ID_OUI_FROM_DATABASE=Radcom Ltd.
-
-OUI:0030D7*
- ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C.
+OUI:000160*
+ ID_OUI_FROM_DATABASE=ELMEX Co., LTD.
 
-OUI:0030FC*
- ID_OUI_FROM_DATABASE=Terawave Communications, Inc.
+OUI:000298*
+ ID_OUI_FROM_DATABASE=Broadframe Corporation
 
-OUI:00300F*
- ID_OUI_FROM_DATABASE=IMT - Information Management T
+OUI:000292*
+ ID_OUI_FROM_DATABASE=Logic Innovations, Inc.
 
-OUI:003004*
- ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC.
+OUI:00028D*
+ ID_OUI_FROM_DATABASE=Movita Technologies, Inc.
 
-OUI:003018*
- ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd.
+OUI:000283*
+ ID_OUI_FROM_DATABASE=Spectrum Controls, Inc.
 
-OUI:003088*
- ID_OUI_FROM_DATABASE=Ericsson
+OUI:000277*
+ ID_OUI_FROM_DATABASE=Cash Systemes Industrie
 
-OUI:0030CA*
- ID_OUI_FROM_DATABASE=Discovery Com
+OUI:00027C*
+ ID_OUI_FROM_DATABASE=Trilithic, Inc.
 
-OUI:00304F*
- ID_OUI_FROM_DATABASE=PLANET Technology Corporation
+OUI:000275*
+ ID_OUI_FROM_DATABASE=SMART Technologies, Inc.
 
-OUI:00014B*
- ID_OUI_FROM_DATABASE=Ennovate Networks, Inc.
+OUI:000270*
+ ID_OUI_FROM_DATABASE=Crewave Co., Ltd.
 
-OUI:00012C*
- ID_OUI_FROM_DATABASE=Aravox Technologies, Inc.
+OUI:000269*
+ ID_OUI_FROM_DATABASE=Nadatel Co., Ltd
 
-OUI:000138*
- ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+OUI:000265*
+ ID_OUI_FROM_DATABASE=Virditech Co. Ltd.
 
 OUI:000134*
  ID_OUI_FROM_DATABASE=Selectron Systems AG
@@ -41135,26 +42209,11 @@ OUI:000123*
 OUI:00011F*
  ID_OUI_FROM_DATABASE=RC Networks, Inc.
 
-OUI:003045*
- ID_OUI_FROM_DATABASE=Village Networks, Inc. (VNI)
-
-OUI:0030BB*
- ID_OUI_FROM_DATABASE=CacheFlow, Inc.
-
-OUI:003053*
- ID_OUI_FROM_DATABASE=Basler AG
-
-OUI:003072*
- ID_OUI_FROM_DATABASE=Intellibyte Inc.
-
-OUI:0030B1*
- ID_OUI_FROM_DATABASE=TrunkNet
-
-OUI:0030A7*
- ID_OUI_FROM_DATABASE=SCHWEITZER ENGINEERING
+OUI:000104*
+ ID_OUI_FROM_DATABASE=DVICO Co., Ltd.
 
-OUI:00D086*
- ID_OUI_FROM_DATABASE=FOVEON, INC.
+OUI:000110*
+ ID_OUI_FROM_DATABASE=Gotham Networks
 
 OUI:00D05A*
  ID_OUI_FROM_DATABASE=SYMBIONICS, LTD.
@@ -41201,50 +42260,47 @@ OUI:00D01E*
 OUI:00D0A9*
  ID_OUI_FROM_DATABASE=SHINANO KENSHI CO., LTD.
 
-OUI:0030E9*
- ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G
-
-OUI:003027*
- ID_OUI_FROM_DATABASE=KERBANGO, INC.
+OUI:00D0F2*
+ ID_OUI_FROM_DATABASE=MONTEREY NETWORKS
 
-OUI:0030F6*
- ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION
+OUI:0030DB*
+ ID_OUI_FROM_DATABASE=Mindready Solutions, Inc.
 
-OUI:0030B6*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:00306A*
+ ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD.
 
-OUI:0030B2*
- ID_OUI_FROM_DATABASE=L-3 Sonoma EO
+OUI:003021*
+ ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD
 
-OUI:0030D6*
- ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH
+OUI:0030EA*
+ ID_OUI_FROM_DATABASE=TeraForce Technology Corporation
 
-OUI:003008*
- ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC.
+OUI:0030F4*
+ ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES
 
-OUI:00306D*
- ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES
+OUI:003087*
+ ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG
 
-OUI:0030E4*
- ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN
+OUI:003000*
+ ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP.
 
-OUI:00301A*
- ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD.
+OUI:003034*
+ ID_OUI_FROM_DATABASE=SET ENGINEERING
 
-OUI:0030CD*
- ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC.
+OUI:00308D*
+ ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc.
 
-OUI:003001*
- ID_OUI_FROM_DATABASE=SMP
+OUI:00304B*
+ ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC.
 
-OUI:0030E1*
- ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc.
+OUI:0030FA*
+ ID_OUI_FROM_DATABASE=TELICA, INC.
 
-OUI:0050A7*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:0030E9*
+ ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G
 
-OUI:00D0EE*
- ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION
+OUI:003027*
+ ID_OUI_FROM_DATABASE=KERBANGO, INC.
 
 OUI:00D0B8*
  ID_OUI_FROM_DATABASE=Iomega Corporation
@@ -41288,104 +42344,56 @@ OUI:0050A9*
 OUI:00503C*
  ID_OUI_FROM_DATABASE=TSINGHUA NOVEL ELECTRONICS
 
-OUI:005030*
- ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS
-
-OUI:005037*
- ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO.
-
-OUI:00501F*
- ID_OUI_FROM_DATABASE=MRG SYSTEMS, LTD.
-
-OUI:005092*
- ID_OUI_FROM_DATABASE=Rigaku Corporation Osaka Plant
-
-OUI:00501C*
- ID_OUI_FROM_DATABASE=JATOM SYSTEMS, INC.
-
-OUI:00505C*
- ID_OUI_FROM_DATABASE=TUNDO CORPORATION
-
-OUI:005068*
- ID_OUI_FROM_DATABASE=ELECTRONIC INDUSTRIES ASSOCIATION
-
-OUI:00501A*
- ID_OUI_FROM_DATABASE=IQinVision
-
-OUI:005063*
- ID_OUI_FROM_DATABASE=OY COMSEL SYSTEM AB
-
-OUI:0050DE*
- ID_OUI_FROM_DATABASE=SIGNUM SYSTEMS CORP.
-
-OUI:00507B*
- ID_OUI_FROM_DATABASE=MERLOT COMMUNICATIONS
-
-OUI:005078*
- ID_OUI_FROM_DATABASE=MEGATON HOUSE, LTD.
-
-OUI:00508F*
- ID_OUI_FROM_DATABASE=ASITA TECHNOLOGIES INT'L LTD.
-
-OUI:005057*
- ID_OUI_FROM_DATABASE=BROADBAND ACCESS SYSTEMS
-
-OUI:005087*
- ID_OUI_FROM_DATABASE=TERASAKI ELECTRIC CO., LTD.
-
-OUI:00D03E*
- ID_OUI_FROM_DATABASE=ROCKETCHIPS, INC.
+OUI:0050B6*
+ ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD.
 
-OUI:00D03F*
- ID_OUI_FROM_DATABASE=AMERICAN COMMUNICATION
+OUI:0050FF*
+ ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD.
 
-OUI:00D033*
- ID_OUI_FROM_DATABASE=DALIAN DAXIAN NETWORK
+OUI:005032*
+ ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC.
 
-OUI:00D0CE*
- ID_OUI_FROM_DATABASE=ASYST ELECTRONIC
+OUI:0030F6*
+ ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION
 
-OUI:00D090*
+OUI:0030B6*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:00D0B6*
- ID_OUI_FROM_DATABASE=CRESCENT NETWORKS, INC.
-
-OUI:00D0D2*
- ID_OUI_FROM_DATABASE=EPILOG CORPORATION
+OUI:0030B2*
+ ID_OUI_FROM_DATABASE=L-3 Sonoma EO
 
-OUI:0050B6*
- ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD.
+OUI:0030D6*
+ ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH
 
-OUI:0050FF*
- ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD.
+OUI:003008*
+ ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC.
 
-OUI:005032*
- ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC.
+OUI:00306D*
+ ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES
 
-OUI:0050DA*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:0030E4*
+ ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN
 
-OUI:0050F9*
- ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC
+OUI:00301A*
+ ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD.
 
-OUI:0050F6*
- ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP.
+OUI:0030CD*
+ ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC.
 
-OUI:00506C*
- ID_OUI_FROM_DATABASE=Beijer Electronics Products AB
+OUI:003001*
+ ID_OUI_FROM_DATABASE=SMP
 
-OUI:0050A5*
- ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD.
+OUI:0030E1*
+ ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc.
 
-OUI:0050FC*
- ID_OUI_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD.
+OUI:0030D8*
+ ID_OUI_FROM_DATABASE=SITEK
 
-OUI:005000*
- ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC.
+OUI:003062*
+ ID_OUI_FROM_DATABASE=IP Video Networks Inc
 
-OUI:00D071*
- ID_OUI_FROM_DATABASE=ECHELON CORP.
+OUI:003081*
+ ID_OUI_FROM_DATABASE=ALTOS C&C
 
 OUI:00D066*
  ID_OUI_FROM_DATABASE=WINTRISS ENGINEERING CORP.
@@ -41417,8 +42425,29 @@ OUI:00D038*
 OUI:00D00C*
  ID_OUI_FROM_DATABASE=SNIJDER MICRO SYSTEMS
 
-OUI:00D0F2*
- ID_OUI_FROM_DATABASE=MONTEREY NETWORKS
+OUI:00D086*
+ ID_OUI_FROM_DATABASE=FOVEON, INC.
+
+OUI:00D03F*
+ ID_OUI_FROM_DATABASE=AMERICAN COMMUNICATION
+
+OUI:00D033*
+ ID_OUI_FROM_DATABASE=DALIAN DAXIAN NETWORK
+
+OUI:00D0CE*
+ ID_OUI_FROM_DATABASE=ASYST ELECTRONIC
+
+OUI:00D090*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:00D0B6*
+ ID_OUI_FROM_DATABASE=CRESCENT NETWORKS, INC.
+
+OUI:00D0D2*
+ ID_OUI_FROM_DATABASE=EPILOG CORPORATION
+
+OUI:00D071*
+ ID_OUI_FROM_DATABASE=ECHELON CORP.
 
 OUI:00D07B*
  ID_OUI_FROM_DATABASE=COMCAM INTERNATIONAL INC
@@ -41435,14 +42464,11 @@ OUI:00D04C*
 OUI:00D0FD*
  ID_OUI_FROM_DATABASE=OPTIMA TELE.COM, INC.
 
-OUI:0030D8*
- ID_OUI_FROM_DATABASE=SITEK
-
-OUI:003062*
- ID_OUI_FROM_DATABASE=IP Video Networks Inc
+OUI:0050A7*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:003081*
- ID_OUI_FROM_DATABASE=ALTOS C&C
+OUI:00D0EE*
+ ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION
 
 OUI:00D0B0*
  ID_OUI_FROM_DATABASE=BITSWITCH LTD.
@@ -41459,6 +42485,30 @@ OUI:00D045*
 OUI:00D0D0*
  ID_OUI_FROM_DATABASE=ZHONGXING TELECOM LTD.
 
+OUI:00D03E*
+ ID_OUI_FROM_DATABASE=ROCKETCHIPS, INC.
+
+OUI:003045*
+ ID_OUI_FROM_DATABASE=Village Networks, Inc. (VNI)
+
+OUI:0030BB*
+ ID_OUI_FROM_DATABASE=CacheFlow, Inc.
+
+OUI:003053*
+ ID_OUI_FROM_DATABASE=Basler AG
+
+OUI:003072*
+ ID_OUI_FROM_DATABASE=Intellibyte Inc.
+
+OUI:0030B1*
+ ID_OUI_FROM_DATABASE=TrunkNet
+
+OUI:0030A7*
+ ID_OUI_FROM_DATABASE=SCHWEITZER ENGINEERING
+
+OUI:003038*
+ ID_OUI_FROM_DATABASE=XCP, INC.
+
 OUI:00902C*
  ID_OUI_FROM_DATABASE=DATA & CONTROL EQUIPMENT LTD.
 
@@ -41477,89 +42527,50 @@ OUI:009017*
 OUI:00907B*
  ID_OUI_FROM_DATABASE=E-TECH, INC.
 
-OUI:00102A*
- ID_OUI_FROM_DATABASE=ZF MICROSYSTEMS, INC.
-
-OUI:00107D*
- ID_OUI_FROM_DATABASE=AURORA COMMUNICATIONS, LTD.
-
-OUI:00101C*
- ID_OUI_FROM_DATABASE=OHM TECHNOLOGIES INTL, LLC
-
-OUI:00106C*
- ID_OUI_FROM_DATABASE=EDNT GmbH
-
-OUI:0010D4*
- ID_OUI_FROM_DATABASE=STORAGE COMPUTER CORPORATION
-
-OUI:0010BF*
- ID_OUI_FROM_DATABASE=InterAir Wireless
-
-OUI:001036*
- ID_OUI_FROM_DATABASE=INTER-TEL INTEGRATED SYSTEMS
-
-OUI:001026*
- ID_OUI_FROM_DATABASE=ACCELERATED NETWORKS, INC.
-
-OUI:00104B*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
-
-OUI:000629*
- ID_OUI_FROM_DATABASE=IBM Corp
-
-OUI:001004*
- ID_OUI_FROM_DATABASE=THE BRANTLEY COILE COMPANY,INC
-
-OUI:00103A*
- ID_OUI_FROM_DATABASE=DIAMOND NETWORK TECH
-
-OUI:0010D8*
- ID_OUI_FROM_DATABASE=CALISTA
-
-OUI:001031*
- ID_OUI_FROM_DATABASE=OBJECTIVE COMMUNICATIONS, INC.
+OUI:00909D*
+ ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC
 
-OUI:00107E*
- ID_OUI_FROM_DATABASE=BACHMANN ELECTRONIC GmbH
+OUI:009038*
+ ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, INC.
 
-OUI:0010C0*
- ID_OUI_FROM_DATABASE=ARMA, Inc.
+OUI:00501F*
+ ID_OUI_FROM_DATABASE=MRG SYSTEMS, LTD.
 
-OUI:001016*
- ID_OUI_FROM_DATABASE=T.SQWARE
+OUI:005092*
+ ID_OUI_FROM_DATABASE=Rigaku Corporation Osaka Plant
 
-OUI:00103D*
- ID_OUI_FROM_DATABASE=PHASECOM, LTD.
+OUI:00501C*
+ ID_OUI_FROM_DATABASE=JATOM SYSTEMS, INC.
 
-OUI:0010C2*
- ID_OUI_FROM_DATABASE=WILLNET, INC.
+OUI:00505C*
+ ID_OUI_FROM_DATABASE=TUNDO CORPORATION
 
-OUI:00107A*
- ID_OUI_FROM_DATABASE=AmbiCom, Inc.
+OUI:005068*
+ ID_OUI_FROM_DATABASE=ELECTRONIC INDUSTRIES ASSOCIATION
 
-OUI:0010C4*
- ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD.
+OUI:00501A*
+ ID_OUI_FROM_DATABASE=IQinVision
 
-OUI:0010EB*
- ID_OUI_FROM_DATABASE=SELSIUS SYSTEMS, INC.
+OUI:005063*
+ ID_OUI_FROM_DATABASE=OY COMSEL SYSTEM AB
 
-OUI:0010FE*
- ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+OUI:0050DE*
+ ID_OUI_FROM_DATABASE=SIGNUM SYSTEMS CORP.
 
-OUI:00102E*
- ID_OUI_FROM_DATABASE=NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD.
+OUI:00507B*
+ ID_OUI_FROM_DATABASE=MERLOT COMMUNICATIONS
 
-OUI:0010C1*
- ID_OUI_FROM_DATABASE=OI ELECTRIC CO., LTD.
+OUI:005078*
+ ID_OUI_FROM_DATABASE=MEGATON HOUSE, LTD.
 
-OUI:00103E*
- ID_OUI_FROM_DATABASE=NETSCHOOLS CORPORATION
+OUI:00508F*
+ ID_OUI_FROM_DATABASE=ASITA TECHNOLOGIES INT'L LTD.
 
-OUI:001049*
- ID_OUI_FROM_DATABASE=ShoreTel, Inc
+OUI:005057*
+ ID_OUI_FROM_DATABASE=BROADBAND ACCESS SYSTEMS
 
-OUI:00105E*
- ID_OUI_FROM_DATABASE=Spirent plc, Service Assurance Broadband
+OUI:005087*
+ ID_OUI_FROM_DATABASE=TERASAKI ELECTRIC CO., LTD.
 
 OUI:005088*
  ID_OUI_FROM_DATABASE=AMANO CORPORATION
@@ -41591,6 +42602,30 @@ OUI:0050EB*
 OUI:0050BC*
  ID_OUI_FROM_DATABASE=HAMMER STORAGE SOLUTIONS
 
+OUI:00900F*
+ ID_OUI_FROM_DATABASE=KAWASAKI HEAVY INDUSTRIES, LTD
+
+OUI:009036*
+ ID_OUI_FROM_DATABASE=ens, inc.
+
+OUI:0090E9*
+ ID_OUI_FROM_DATABASE=JANZ COMPUTER AG
+
+OUI:009032*
+ ID_OUI_FROM_DATABASE=PELCOMBE GROUP LTD.
+
+OUI:0090B8*
+ ID_OUI_FROM_DATABASE=ROHDE & SCHWARZ GMBH & CO. KG
+
+OUI:009058*
+ ID_OUI_FROM_DATABASE=Ultra Electronics Ltd., Command and Control Systems
+
+OUI:0090BE*
+ ID_OUI_FROM_DATABASE=IBC/INTEGRATED BUSINESS COMPUTERS
+
+OUI:009062*
+ ID_OUI_FROM_DATABASE=ICP VORTEX COMPUTERSYSTEME GmbH
+
 OUI:0090C3*
  ID_OUI_FROM_DATABASE=TOPIC SEMICONDUCTOR CORP.
 
@@ -41633,11 +42668,14 @@ OUI:0010D5*
 OUI:0010E5*
  ID_OUI_FROM_DATABASE=SOLECTRON TEXAS
 
-OUI:00909D*
- ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC
+OUI:00102A*
+ ID_OUI_FROM_DATABASE=ZF MICROSYSTEMS, INC.
 
-OUI:009038*
- ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, INC.
+OUI:00107D*
+ ID_OUI_FROM_DATABASE=AURORA COMMUNICATIONS, LTD.
+
+OUI:00101C*
+ ID_OUI_FROM_DATABASE=OHM TECHNOLOGIES INTL, LLC
 
 OUI:0090C5*
  ID_OUI_FROM_DATABASE=INTERNET MAGIC, INC.
@@ -41696,68 +42734,131 @@ OUI:009098*
 OUI:0090CF*
  ID_OUI_FROM_DATABASE=NORTEL
 
-OUI:00900F*
- ID_OUI_FROM_DATABASE=KAWASAKI HEAVY INDUSTRIES, LTD
+OUI:0050DA*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
 
-OUI:009036*
- ID_OUI_FROM_DATABASE=ens, inc.
+OUI:0050F9*
+ ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC
 
-OUI:0090E9*
- ID_OUI_FROM_DATABASE=JANZ COMPUTER AG
+OUI:0050F6*
+ ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP.
 
-OUI:009032*
- ID_OUI_FROM_DATABASE=PELCOMBE GROUP LTD.
+OUI:00506C*
+ ID_OUI_FROM_DATABASE=Beijer Electronics Products AB
 
-OUI:0090B8*
- ID_OUI_FROM_DATABASE=ROHDE & SCHWARZ GMBH & CO. KG
+OUI:0050A5*
+ ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD.
 
-OUI:009058*
- ID_OUI_FROM_DATABASE=Ultra Electronics Ltd., Command and Control Systems
+OUI:005000*
+ ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC.
 
-OUI:0090BE*
- ID_OUI_FROM_DATABASE=IBC/INTEGRATED BUSINESS COMPUTERS
+OUI:005030*
+ ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS
 
-OUI:009062*
- ID_OUI_FROM_DATABASE=ICP VORTEX COMPUTERSYSTEME GmbH
+OUI:005037*
+ ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO.
 
-OUI:00108F*
- ID_OUI_FROM_DATABASE=RAPTOR SYSTEMS
+OUI:00106C*
+ ID_OUI_FROM_DATABASE=EDNT GmbH
 
-OUI:001089*
- ID_OUI_FROM_DATABASE=WebSonic
+OUI:0010D4*
+ ID_OUI_FROM_DATABASE=STORAGE COMPUTER CORPORATION
 
-OUI:001086*
- ID_OUI_FROM_DATABASE=ATTO Technology, Inc.
+OUI:0010BF*
+ ID_OUI_FROM_DATABASE=InterAir Wireless
 
-OUI:001027*
- ID_OUI_FROM_DATABASE=L-3 COMMUNICATIONS EAST
+OUI:001036*
+ ID_OUI_FROM_DATABASE=INTER-TEL INTEGRATED SYSTEMS
 
-OUI:0010B8*
- ID_OUI_FROM_DATABASE=ISHIGAKI COMPUTER SYSTEM CO.
+OUI:001026*
+ ID_OUI_FROM_DATABASE=ACCELERATED NETWORKS, INC.
 
-OUI:00104C*
- ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc
+OUI:00104B*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
 
-OUI:001001*
- ID_OUI_FROM_DATABASE=Citel
+OUI:000629*
+ ID_OUI_FROM_DATABASE=IBM Corp
 
-OUI:0010CF*
- ID_OUI_FROM_DATABASE=FIBERLANE COMMUNICATIONS
+OUI:001004*
+ ID_OUI_FROM_DATABASE=THE BRANTLEY COILE COMPANY,INC
 
-OUI:001068*
- ID_OUI_FROM_DATABASE=COMOS TELECOM
+OUI:00103A*
+ ID_OUI_FROM_DATABASE=DIAMOND NETWORK TECH
 
-OUI:001067*
- ID_OUI_FROM_DATABASE=Ericsson
+OUI:0010D8*
+ ID_OUI_FROM_DATABASE=CALISTA
 
-OUI:0010F1*
- ID_OUI_FROM_DATABASE=I-O CORPORATION
+OUI:001031*
+ ID_OUI_FROM_DATABASE=OBJECTIVE COMMUNICATIONS, INC.
 
-OUI:001073*
- ID_OUI_FROM_DATABASE=TECHNOBOX, INC.
+OUI:00103D*
+ ID_OUI_FROM_DATABASE=PHASECOM, LTD.
 
-OUI:00E0C0*
- ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., LTD.
+OUI:0010C2*
+ ID_OUI_FROM_DATABASE=WILLNET, INC.
+
+OUI:00107A*
+ ID_OUI_FROM_DATABASE=AmbiCom, Inc.
+
+OUI:0010C4*
+ ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD.
+
+OUI:0010EB*
+ ID_OUI_FROM_DATABASE=SELSIUS SYSTEMS, INC.
+
+OUI:0010FE*
+ ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+
+OUI:00102E*
+ ID_OUI_FROM_DATABASE=NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD.
+
+OUI:0010C1*
+ ID_OUI_FROM_DATABASE=OI ELECTRIC CO., LTD.
+
+OUI:00103E*
+ ID_OUI_FROM_DATABASE=NETSCHOOLS CORPORATION
+
+OUI:001049*
+ ID_OUI_FROM_DATABASE=ShoreTel, Inc
+
+OUI:00105E*
+ ID_OUI_FROM_DATABASE=Spirent plc, Service Assurance Broadband
+
+OUI:0010B1*
+ ID_OUI_FROM_DATABASE=FOR-A CO., LTD.
+
+OUI:001041*
+ ID_OUI_FROM_DATABASE=BRISTOL BABCOCK, INC.
+
+OUI:0010F7*
+ ID_OUI_FROM_DATABASE=IRIICHI TECHNOLOGIES Inc.
+
+OUI:00E0FD*
+ ID_OUI_FROM_DATABASE=A-TREND TECHNOLOGY CO., LTD.
+
+OUI:00E0FB*
+ ID_OUI_FROM_DATABASE=LEIGHTRONIX, INC.
+
+OUI:00E0D3*
+ ID_OUI_FROM_DATABASE=DATENTECHNIK GmbH
+
+OUI:00E05E*
+ ID_OUI_FROM_DATABASE=JAPAN AVIATION ELECTRONICS INDUSTRY, LTD.
+
+OUI:00E0E5*
+ ID_OUI_FROM_DATABASE=CINCO NETWORKS, INC.
+
+OUI:00E0A1*
+ ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG
+
+OUI:00E028*
+ ID_OUI_FROM_DATABASE=APTIX CORPORATION
+
+OUI:00E0F2*
+ ID_OUI_FROM_DATABASE=ARLOTTO COMNET, INC.
+
+OUI:00E020*
+ ID_OUI_FROM_DATABASE=TECNOMEN OY
 
 OUI:00E046*
  ID_OUI_FROM_DATABASE=BENTLY NEVADA CORP.
@@ -41792,6 +42893,51 @@ OUI:00E012*
 OUI:00E0D8*
  ID_OUI_FROM_DATABASE=LANBit Computer, Inc.
 
+OUI:00108F*
+ ID_OUI_FROM_DATABASE=RAPTOR SYSTEMS
+
+OUI:001089*
+ ID_OUI_FROM_DATABASE=WebSonic
+
+OUI:001086*
+ ID_OUI_FROM_DATABASE=ATTO Technology, Inc.
+
+OUI:001027*
+ ID_OUI_FROM_DATABASE=L-3 COMMUNICATIONS EAST
+
+OUI:0010B8*
+ ID_OUI_FROM_DATABASE=ISHIGAKI COMPUTER SYSTEM CO.
+
+OUI:00104C*
+ ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc
+
+OUI:001001*
+ ID_OUI_FROM_DATABASE=Citel
+
+OUI:0010CF*
+ ID_OUI_FROM_DATABASE=FIBERLANE COMMUNICATIONS
+
+OUI:001068*
+ ID_OUI_FROM_DATABASE=COMOS TELECOM
+
+OUI:001067*
+ ID_OUI_FROM_DATABASE=Ericsson
+
+OUI:0010F1*
+ ID_OUI_FROM_DATABASE=I-O CORPORATION
+
+OUI:001073*
+ ID_OUI_FROM_DATABASE=TECHNOBOX, INC.
+
+OUI:00107E*
+ ID_OUI_FROM_DATABASE=BACHMANN ELECTRONIC GmbH
+
+OUI:0010C0*
+ ID_OUI_FROM_DATABASE=ARMA, Inc.
+
+OUI:001016*
+ ID_OUI_FROM_DATABASE=T.SQWARE
+
 OUI:00E02D*
  ID_OUI_FROM_DATABASE=InnoMediaLogic, Inc.
 
@@ -41828,38 +42974,17 @@ OUI:00E0C7*
 OUI:00E0C4*
  ID_OUI_FROM_DATABASE=HORNER ELECTRIC, INC.
 
-OUI:00E04D*
- ID_OUI_FROM_DATABASE=INTERNET INITIATIVE JAPAN, INC
-
-OUI:00607F*
- ID_OUI_FROM_DATABASE=AURORA TECHNOLOGIES, INC.
-
-OUI:00E039*
- ID_OUI_FROM_DATABASE=PARADYNE CORP.
-
-OUI:006091*
- ID_OUI_FROM_DATABASE=FIRST PACIFIC NETWORKS, INC.
-
-OUI:006002*
- ID_OUI_FROM_DATABASE=SCREEN SUBTITLING SYSTEMS, LTD
-
-OUI:006061*
- ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP.
-
-OUI:0060BD*
- ID_OUI_FROM_DATABASE=HUBBELL-PULSECOM
-
-OUI:00E0A1*
- ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG
+OUI:0010E6*
+ ID_OUI_FROM_DATABASE=APPLIED INTELLIGENT SYSTEMS, INC.
 
-OUI:00E028*
- ID_OUI_FROM_DATABASE=APTIX CORPORATION
+OUI:00101E*
+ ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRONIC INSTRUMENTS CORP.
 
-OUI:00E0F2*
- ID_OUI_FROM_DATABASE=ARLOTTO COMNET, INC.
+OUI:0010F2*
+ ID_OUI_FROM_DATABASE=ANTEC
 
-OUI:00E020*
- ID_OUI_FROM_DATABASE=TECNOMEN OY
+OUI:0010BE*
+ ID_OUI_FROM_DATABASE=MARCH NETWORKS CORPORATION
 
 OUI:00E0C5*
  ID_OUI_FROM_DATABASE=BCOM ELECTRONICS INC.
@@ -41882,77 +43007,50 @@ OUI:00E0F0*
 OUI:00E0B7*
  ID_OUI_FROM_DATABASE=PI GROUP, LTD.
 
-OUI:0010B1*
- ID_OUI_FROM_DATABASE=FOR-A CO., LTD.
-
-OUI:001041*
- ID_OUI_FROM_DATABASE=BRISTOL BABCOCK, INC.
-
-OUI:0010F7*
- ID_OUI_FROM_DATABASE=IRIICHI TECHNOLOGIES Inc.
-
-OUI:0010E6*
- ID_OUI_FROM_DATABASE=APPLIED INTELLIGENT SYSTEMS, INC.
-
-OUI:00101E*
- ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRONIC INSTRUMENTS CORP.
-
-OUI:0010F2*
- ID_OUI_FROM_DATABASE=ANTEC
-
-OUI:0010BE*
- ID_OUI_FROM_DATABASE=MARCH NETWORKS CORPORATION
-
-OUI:006074*
- ID_OUI_FROM_DATABASE=QSC AUDIO PRODUCTS
-
-OUI:006058*
- ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC.
-
-OUI:00601B*
- ID_OUI_FROM_DATABASE=MESA ELECTRONICS
+OUI:00E0C0*
+ ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., LTD.
 
-OUI:0060FF*
- ID_OUI_FROM_DATABASE=QuVis, Inc.
+OUI:006098*
+ ID_OUI_FROM_DATABASE=HT COMMUNICATIONS
 
-OUI:006056*
- ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC.
+OUI:0060F7*
+ ID_OUI_FROM_DATABASE=DATAFUSION SYSTEMS
 
-OUI:0060D8*
- ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC.
+OUI:0060DE*
+ ID_OUI_FROM_DATABASE=Kayser-Threde GmbH
 
-OUI:00607A*
- ID_OUI_FROM_DATABASE=DVS GMBH
+OUI:0060D0*
+ ID_OUI_FROM_DATABASE=SNMP RESEARCH INCORPORATED
 
-OUI:006097*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:006079*
+ ID_OUI_FROM_DATABASE=Mainstream Data, Inc.
 
-OUI:0060E3*
- ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS
+OUI:006020*
+ ID_OUI_FROM_DATABASE=PIVOTAL NETWORKING, INC.
 
-OUI:00E0FD*
- ID_OUI_FROM_DATABASE=A-TREND TECHNOLOGY CO., LTD.
+OUI:0005A8*
+ ID_OUI_FROM_DATABASE=WYLE ELECTRONICS
 
-OUI:00E0FB*
- ID_OUI_FROM_DATABASE=LEIGHTRONIX, INC.
+OUI:0060B7*
+ ID_OUI_FROM_DATABASE=CHANNELMATIC, INC.
 
-OUI:00E0D3*
- ID_OUI_FROM_DATABASE=DATENTECHNIK GmbH
+OUI:0060A3*
+ ID_OUI_FROM_DATABASE=CONTINUUM TECHNOLOGY CORP.
 
-OUI:00E05E*
- ID_OUI_FROM_DATABASE=JAPAN AVIATION ELECTRONICS INDUSTRY, LTD.
+OUI:006050*
+ ID_OUI_FROM_DATABASE=INTERNIX INC.
 
-OUI:00E0E5*
- ID_OUI_FROM_DATABASE=CINCO NETWORKS, INC.
+OUI:0060E0*
+ ID_OUI_FROM_DATABASE=AXIOM TECHNOLOGY CO., LTD.
 
-OUI:00E0CF*
- ID_OUI_FROM_DATABASE=INTEGRATED DEVICE TECHNOLOGY, INC.
+OUI:0060A8*
+ ID_OUI_FROM_DATABASE=TIDOMAT AB
 
-OUI:00A0FD*
- ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC.
+OUI:00608E*
+ ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH
 
-OUI:00A0F5*
- ID_OUI_FROM_DATABASE=RADGUARD LTD.
+OUI:0060F0*
+ ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC
 
 OUI:00A022*
  ID_OUI_FROM_DATABASE=CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING
@@ -41993,60 +43091,6 @@ OUI:00A065*
 OUI:00A044*
  ID_OUI_FROM_DATABASE=NTT IT CO., LTD.
 
-OUI:006008*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
-
-OUI:0060EF*
- ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY CO., LTD.
-
-OUI:006098*
- ID_OUI_FROM_DATABASE=HT COMMUNICATIONS
-
-OUI:0060F7*
- ID_OUI_FROM_DATABASE=DATAFUSION SYSTEMS
-
-OUI:0060DE*
- ID_OUI_FROM_DATABASE=Kayser-Threde GmbH
-
-OUI:0060D0*
- ID_OUI_FROM_DATABASE=SNMP RESEARCH INCORPORATED
-
-OUI:006079*
- ID_OUI_FROM_DATABASE=Mainstream Data, Inc.
-
-OUI:006020*
- ID_OUI_FROM_DATABASE=PIVOTAL NETWORKING, INC.
-
-OUI:0005A8*
- ID_OUI_FROM_DATABASE=WYLE ELECTRONICS
-
-OUI:0060B7*
- ID_OUI_FROM_DATABASE=CHANNELMATIC, INC.
-
-OUI:0060A3*
- ID_OUI_FROM_DATABASE=CONTINUUM TECHNOLOGY CORP.
-
-OUI:006050*
- ID_OUI_FROM_DATABASE=INTERNIX INC.
-
-OUI:0060E0*
- ID_OUI_FROM_DATABASE=AXIOM TECHNOLOGY CO., LTD.
-
-OUI:0060A8*
- ID_OUI_FROM_DATABASE=TIDOMAT AB
-
-OUI:00A056*
- ID_OUI_FROM_DATABASE=MICROPROSS
-
-OUI:00A051*
- ID_OUI_FROM_DATABASE=ANGIA COMMUNICATIONS. INC.
-
-OUI:00A0A6*
- ID_OUI_FROM_DATABASE=M.I. SYSTEMS, K.K.
-
-OUI:00A0B0*
- ID_OUI_FROM_DATABASE=I-O DATA DEVICE, INC.
-
 OUI:00A05F*
  ID_OUI_FROM_DATABASE=BTG Electronics Design BV
 
@@ -42077,32 +43121,8 @@ OUI:00A0F7*
 OUI:00A09C*
  ID_OUI_FROM_DATABASE=Xyplex, Inc.
 
-OUI:00A092*
- ID_OUI_FROM_DATABASE=H. BOLLMANN MANUFACTURERS, LTD
-
-OUI:00A04D*
- ID_OUI_FROM_DATABASE=EDA INSTRUMENTS, INC.
-
-OUI:00A0DB*
- ID_OUI_FROM_DATABASE=FISHER & PAYKEL PRODUCTION
-
-OUI:00A0A5*
- ID_OUI_FROM_DATABASE=TEKNOR MICROSYSTEME, INC.
-
-OUI:00A018*
- ID_OUI_FROM_DATABASE=CREATIVE CONTROLLERS, INC.
-
-OUI:00A09F*
- ID_OUI_FROM_DATABASE=COMMVISION CORP.
-
-OUI:00A06B*
- ID_OUI_FROM_DATABASE=DMS DORSCH MIKROSYSTEM GMBH
-
-OUI:006051*
- ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR
-
-OUI:00605E*
- ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING
+OUI:00A0A0*
+ ID_OUI_FROM_DATABASE=COMPACT DATA, LTD.
 
 OUI:0060C6*
  ID_OUI_FROM_DATABASE=DCS AG
@@ -42128,11 +43148,14 @@ OUI:00A039*
 OUI:00A06D*
  ID_OUI_FROM_DATABASE=MANNESMANN TALLY CORPORATION
 
-OUI:00608E*
- ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH
+OUI:00A056*
+ ID_OUI_FROM_DATABASE=MICROPROSS
 
-OUI:0060F0*
- ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC
+OUI:00A051*
+ ID_OUI_FROM_DATABASE=ANGIA COMMUNICATIONS. INC.
+
+OUI:00A0A6*
+ ID_OUI_FROM_DATABASE=M.I. SYSTEMS, K.K.
 
 OUI:0060D2*
  ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD.
@@ -42152,104 +43175,74 @@ OUI:00608B*
 OUI:0060C3*
  ID_OUI_FROM_DATABASE=NETVISION CORPORATION
 
-OUI:00A0A0*
- ID_OUI_FROM_DATABASE=COMPACT DATA, LTD.
-
-OUI:00A0A4*
- ID_OUI_FROM_DATABASE=MICROS SYSTEMS, INC.
-
-OUI:00A024*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
-
-OUI:00A08B*
- ID_OUI_FROM_DATABASE=ASTON ELECTRONIC DESIGNS LTD.
-
-OUI:00A0AA*
- ID_OUI_FROM_DATABASE=SPACELABS MEDICAL
-
-OUI:00A04F*
- ID_OUI_FROM_DATABASE=AMERITEC CORP.
-
-OUI:00A073*
- ID_OUI_FROM_DATABASE=COM21, INC.
-
-OUI:00A084*
- ID_OUI_FROM_DATABASE=Dataplex Pty Ltd
-
-OUI:00A034*
- ID_OUI_FROM_DATABASE=AXEL
-
-OUI:00C0BC*
- ID_OUI_FROM_DATABASE=TELECOM AUSTRALIA/CSSC
-
-OUI:00C0EF*
- ID_OUI_FROM_DATABASE=ABIT CORPORATION
+OUI:006051*
+ ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR
 
-OUI:00C03C*
- ID_OUI_FROM_DATABASE=TOWER TECH S.R.L.
+OUI:00605E*
+ ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING
 
-OUI:00C061*
- ID_OUI_FROM_DATABASE=SOLECTEK CORPORATION
+OUI:006058*
+ ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC.
 
-OUI:00C074*
- ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM
+OUI:00601B*
+ ID_OUI_FROM_DATABASE=MESA ELECTRONICS
 
-OUI:00C07F*
- ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP.
+OUI:0060FF*
+ ID_OUI_FROM_DATABASE=QuVis, Inc.
 
-OUI:00C027*
- ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC.
+OUI:006056*
+ ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC.
 
-OUI:00C025*
- ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION
+OUI:0060D8*
+ ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC.
 
-OUI:00C022*
- ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC.
+OUI:00607A*
+ ID_OUI_FROM_DATABASE=DVS GMBH
 
-OUI:00C0E6*
- ID_OUI_FROM_DATABASE=Verilink Corporation
+OUI:006097*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
 
-OUI:00C05C*
- ID_OUI_FROM_DATABASE=ELONEX PLC
+OUI:0060E3*
+ ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS
 
-OUI:00C0C1*
- ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC.
+OUI:006008*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
 
-OUI:00C091*
- ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC.
+OUI:0060EF*
+ ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY CO., LTD.
 
-OUI:00C002*
- ID_OUI_FROM_DATABASE=SERCOMM CORPORATION
+OUI:00E04D*
+ ID_OUI_FROM_DATABASE=INTERNET INITIATIVE JAPAN, INC
 
-OUI:00C0F5*
- ID_OUI_FROM_DATABASE=METACOMP, INC.
+OUI:00607F*
+ ID_OUI_FROM_DATABASE=AURORA TECHNOLOGIES, INC.
 
-OUI:00C042*
- ID_OUI_FROM_DATABASE=DATALUX CORP.
+OUI:00E039*
+ ID_OUI_FROM_DATABASE=PARADYNE CORP.
 
-OUI:00C089*
- ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION
+OUI:006091*
+ ID_OUI_FROM_DATABASE=FIRST PACIFIC NETWORKS, INC.
 
-OUI:00C09D*
- ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC
+OUI:006002*
+ ID_OUI_FROM_DATABASE=SCREEN SUBTITLING SYSTEMS, LTD
 
-OUI:00C0A5*
- ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS
+OUI:006061*
+ ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP.
 
-OUI:00C0E3*
- ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC.
+OUI:0060BD*
+ ID_OUI_FROM_DATABASE=HUBBELL-PULSECOM
 
-OUI:00C071*
- ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC.
+OUI:006074*
+ ID_OUI_FROM_DATABASE=QSC AUDIO PRODUCTS
 
-OUI:00C0AF*
- ID_OUI_FROM_DATABASE=TEKLOGIX INC.
+OUI:00A024*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
 
-OUI:00209F*
- ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC.
+OUI:00A0FD*
+ ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC.
 
-OUI:0020B7*
- ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE
+OUI:00A0F5*
+ ID_OUI_FROM_DATABASE=RADGUARD LTD.
 
 OUI:00201B*
  ID_OUI_FROM_DATABASE=NORTHERN TELECOM/NETWORK
@@ -42293,6 +43286,39 @@ OUI:00206B*
 OUI:0020FC*
  ID_OUI_FROM_DATABASE=MATROX
 
+OUI:002035*
+ ID_OUI_FROM_DATABASE=IBM Corp
+
+OUI:0020E2*
+ ID_OUI_FROM_DATABASE=INFORMATION RESOURCE ENGINEERING
+
+OUI:002058*
+ ID_OUI_FROM_DATABASE=ALLIED SIGNAL INC.
+
+OUI:00208C*
+ ID_OUI_FROM_DATABASE=GALAXY NETWORKS, INC.
+
+OUI:002063*
+ ID_OUI_FROM_DATABASE=WIPRO INFOTECH LTD.
+
+OUI:0020DC*
+ ID_OUI_FROM_DATABASE=DENSITRON TAIWAN LTD.
+
+OUI:002078*
+ ID_OUI_FROM_DATABASE=RUNTOP, INC.
+
+OUI:002042*
+ ID_OUI_FROM_DATABASE=DATAMETRICS CORP.
+
+OUI:0020F8*
+ ID_OUI_FROM_DATABASE=CARRERA COMPUTERS, INC.
+
+OUI:00200C*
+ ID_OUI_FROM_DATABASE=ADASTRA SYSTEMS CORP.
+
+OUI:0020C4*
+ ID_OUI_FROM_DATABASE=INET,INC.
+
 OUI:00C003*
  ID_OUI_FROM_DATABASE=GLOBALNET COMMUNICATIONS
 
@@ -42305,29 +43331,26 @@ OUI:00C04D*
 OUI:00C055*
  ID_OUI_FROM_DATABASE=MODULAR COMPUTING TECHNOLOGIES
 
-OUI:00C067*
- ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES
-
-OUI:00C0B4*
- ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC.
+OUI:00A0DB*
+ ID_OUI_FROM_DATABASE=FISHER & PAYKEL PRODUCTION
 
-OUI:00C080*
- ID_OUI_FROM_DATABASE=NETSTAR, INC.
+OUI:00A0A5*
+ ID_OUI_FROM_DATABASE=TEKNOR MICROSYSTEME, INC.
 
-OUI:00C015*
- ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION
+OUI:00A018*
+ ID_OUI_FROM_DATABASE=CREATIVE CONTROLLERS, INC.
 
-OUI:00C09F*
- ID_OUI_FROM_DATABASE=QUANTA COMPUTER, INC.
+OUI:00A09F*
+ ID_OUI_FROM_DATABASE=COMMVISION CORP.
 
-OUI:0070B3*
- ID_OUI_FROM_DATABASE=DATA RECALL LTD.
+OUI:00A06B*
+ ID_OUI_FROM_DATABASE=DMS DORSCH MIKROSYSTEM GMBH
 
-OUI:00E6D3*
- ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP.
+OUI:00209F*
+ ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC.
 
-OUI:00C083*
- ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC.
+OUI:0020B7*
+ ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE
 
 OUI:00C005*
  ID_OUI_FROM_DATABASE=LIVINGSTON ENTERPRISES, INC.
@@ -42362,44 +43385,35 @@ OUI:00C0C6*
 OUI:00C03B*
  ID_OUI_FROM_DATABASE=MULTIACCESS COMPUTING CORP.
 
-OUI:0020F4*
- ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION
-
-OUI:00204E*
- ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC.
-
-OUI:002027*
- ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD
-
-OUI:0020ED*
- ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD.
+OUI:00C099*
+ ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD.
 
-OUI:00200E*
- ID_OUI_FROM_DATABASE=SATELLITE TECHNOLOGY MGMT, INC
+OUI:00C0FC*
+ ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC.
 
-OUI:002096*
- ID_OUI_FROM_DATABASE=Invensys
+OUI:00C067*
+ ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES
 
-OUI:0020BB*
- ID_OUI_FROM_DATABASE=ZAX CORPORATION
+OUI:00C0B4*
+ ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC.
 
-OUI:00204D*
- ID_OUI_FROM_DATABASE=INOVIS GMBH
+OUI:00C080*
+ ID_OUI_FROM_DATABASE=NETSTAR, INC.
 
-OUI:002089*
- ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC.
+OUI:00C015*
+ ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION
 
-OUI:00205F*
- ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH
+OUI:00C09F*
+ ID_OUI_FROM_DATABASE=QUANTA COMPUTER, INC.
 
-OUI:002035*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0070B3*
+ ID_OUI_FROM_DATABASE=DATA RECALL LTD.
 
-OUI:0020E2*
- ID_OUI_FROM_DATABASE=INFORMATION RESOURCE ENGINEERING
+OUI:00E6D3*
+ ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP.
 
-OUI:002058*
- ID_OUI_FROM_DATABASE=ALLIED SIGNAL INC.
+OUI:00C083*
+ ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC.
 
 OUI:002081*
  ID_OUI_FROM_DATABASE=TITAN ELECTRONICS
@@ -42425,65 +43439,65 @@ OUI:0020DE*
 OUI:0020F7*
  ID_OUI_FROM_DATABASE=CYBERDATA CORPORATION
 
-OUI:0020EE*
- ID_OUI_FROM_DATABASE=GTECH CORPORATION
-
-OUI:00208C*
- ID_OUI_FROM_DATABASE=GALAXY NETWORKS, INC.
+OUI:000267*
+ ID_OUI_FROM_DATABASE=NODE RUNNER, INC.
 
-OUI:002063*
- ID_OUI_FROM_DATABASE=WIPRO INFOTECH LTD.
+OUI:002064*
+ ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC.
 
-OUI:0020DC*
- ID_OUI_FROM_DATABASE=DENSITRON TAIWAN LTD.
+OUI:002032*
+ ID_OUI_FROM_DATABASE=ALCATEL TAISEL
 
-OUI:002078*
- ID_OUI_FROM_DATABASE=RUNTOP, INC.
+OUI:002027*
+ ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD
 
-OUI:002042*
- ID_OUI_FROM_DATABASE=DATAMETRICS CORP.
+OUI:0020ED*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD.
 
-OUI:0020F8*
- ID_OUI_FROM_DATABASE=CARRERA COMPUTERS, INC.
+OUI:00200E*
+ ID_OUI_FROM_DATABASE=SATELLITE TECHNOLOGY MGMT, INC
 
-OUI:00200C*
- ID_OUI_FROM_DATABASE=ADASTRA SYSTEMS CORP.
+OUI:002096*
+ ID_OUI_FROM_DATABASE=Invensys
 
-OUI:0020C4*
- ID_OUI_FROM_DATABASE=INET,INC.
+OUI:0020BB*
+ ID_OUI_FROM_DATABASE=ZAX CORPORATION
 
-OUI:00C099*
- ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD.
+OUI:00204D*
+ ID_OUI_FROM_DATABASE=INOVIS GMBH
 
-OUI:00C0FC*
- ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC.
+OUI:002089*
+ ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC.
 
-OUI:00C0D0*
- ID_OUI_FROM_DATABASE=RATOC SYSTEM INC.
+OUI:00205F*
+ ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH
 
-OUI:00C07A*
- ID_OUI_FROM_DATABASE=PRIVA B.V.
+OUI:0020EE*
+ ID_OUI_FROM_DATABASE=GTECH CORPORATION
 
-OUI:000701*
- ID_OUI_FROM_DATABASE=RACAL-DATACOM
+OUI:00A08B*
+ ID_OUI_FROM_DATABASE=ASTON ELECTRONIC DESIGNS LTD.
 
-OUI:00C09C*
- ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION
+OUI:00A0AA*
+ ID_OUI_FROM_DATABASE=SPACELABS MEDICAL
 
-OUI:00C004*
- ID_OUI_FROM_DATABASE=JAPAN BUSINESS COMPUTER CO.LTD
+OUI:00A04F*
+ ID_OUI_FROM_DATABASE=AMERITEC CORP.
 
-OUI:00C062*
- ID_OUI_FROM_DATABASE=IMPULSE TECHNOLOGY
+OUI:00A073*
+ ID_OUI_FROM_DATABASE=COM21, INC.
 
-OUI:000267*
- ID_OUI_FROM_DATABASE=NODE RUNNER, INC.
+OUI:00A084*
+ ID_OUI_FROM_DATABASE=Dataplex Pty Ltd
 
-OUI:002064*
- ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC.
+OUI:00A034*
+ ID_OUI_FROM_DATABASE=AXEL
 
-OUI:002032*
- ID_OUI_FROM_DATABASE=ALCATEL TAISEL
+OUI:00A092*
+ ID_OUI_FROM_DATABASE=H. BOLLMANN MANUFACTURERS, LTD
+
+OUI:00A04D*
+ ID_OUI_FROM_DATABASE=EDA INSTRUMENTS, INC.
 
 OUI:00207F*
  ID_OUI_FROM_DATABASE=KYOEI SANGYO CO., LTD.
@@ -42497,86 +43511,71 @@ OUI:002068*
 OUI:00202A*
  ID_OUI_FROM_DATABASE=N.V. DZINE
 
-OUI:008006*
- ID_OUI_FROM_DATABASE=COMPUADD CORPORATION
-
-OUI:0080EF*
- ID_OUI_FROM_DATABASE=RATIONAL
-
-OUI:0080C4*
- ID_OUI_FROM_DATABASE=DOCUMENT TECHNOLOGIES, INC.
-
-OUI:008095*
- ID_OUI_FROM_DATABASE=BASIC MERTON HANDELSGES.M.B.H.
-
-OUI:008053*
- ID_OUI_FROM_DATABASE=INTELLICOM, INC.
-
-OUI:008026*
- ID_OUI_FROM_DATABASE=NETWORK PRODUCTS CORPORATION
+OUI:0020F4*
+ ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION
 
-OUI:0080FE*
- ID_OUI_FROM_DATABASE=AZURE TECHNOLOGIES, INC.
+OUI:00204E*
+ ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC.
 
-OUI:008028*
- ID_OUI_FROM_DATABASE=TRADPOST (HK) LTD
+OUI:00C074*
+ ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM
 
-OUI:0080B6*
- ID_OUI_FROM_DATABASE=THEMIS COMPUTER
+OUI:00C07F*
+ ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP.
 
-OUI:008058*
- ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORPORATION
+OUI:00C027*
+ ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC.
 
-OUI:0080C0*
- ID_OUI_FROM_DATABASE=PENRIL DATACOMM
+OUI:00C025*
+ ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION
 
-OUI:0080F5*
- ID_OUI_FROM_DATABASE=Quantel Ltd
+OUI:00C022*
+ ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC.
 
-OUI:00401D*
- ID_OUI_FROM_DATABASE=INVISIBLE SOFTWARE, INC.
+OUI:00C0E6*
+ ID_OUI_FROM_DATABASE=Verilink Corporation
 
-OUI:0040BD*
- ID_OUI_FROM_DATABASE=STARLIGHT NETWORKS, INC.
+OUI:00C05C*
+ ID_OUI_FROM_DATABASE=ELONEX PLC
 
-OUI:00406D*
- ID_OUI_FROM_DATABASE=LANCO, INC.
+OUI:00C0C1*
+ ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC.
 
-OUI:00404D*
- ID_OUI_FROM_DATABASE=TELECOMMUNICATIONS TECHNIQUES
+OUI:00C091*
+ ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC.
 
-OUI:0040A5*
- ID_OUI_FROM_DATABASE=CLINICOMP INTL.
+OUI:00C002*
+ ID_OUI_FROM_DATABASE=SERCOMM CORPORATION
 
-OUI:004059*
- ID_OUI_FROM_DATABASE=YOSHIDA KOGYO K. K.
+OUI:00C0F5*
+ ID_OUI_FROM_DATABASE=METACOMP, INC.
 
-OUI:004021*
- ID_OUI_FROM_DATABASE=RASTER GRAPHICS
+OUI:00C042*
+ ID_OUI_FROM_DATABASE=DATALUX CORP.
 
-OUI:004081*
- ID_OUI_FROM_DATABASE=MANNESMANN SCANGRAPHIC GMBH
+OUI:00C089*
+ ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION
 
-OUI:00806C*
- ID_OUI_FROM_DATABASE=CEGELEC PROJECTS LTD
+OUI:00C09D*
+ ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC
 
-OUI:00404A*
- ID_OUI_FROM_DATABASE=WEST AUSTRALIAN DEPARTMENT
+OUI:00C0A5*
+ ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS
 
-OUI:00400A*
- ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES, INC.
+OUI:00C0E3*
+ ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC.
 
-OUI:004032*
- ID_OUI_FROM_DATABASE=DIGITAL COMMUNICATIONS
+OUI:00C071*
+ ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC.
 
-OUI:004042*
- ID_OUI_FROM_DATABASE=N.A.T. GMBH
+OUI:00C0AF*
+ ID_OUI_FROM_DATABASE=TEKLOGIX INC.
 
-OUI:0040C2*
- ID_OUI_FROM_DATABASE=APPLIED COMPUTING DEVICES
+OUI:00C05D*
+ ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES
 
-OUI:00403C*
- ID_OUI_FROM_DATABASE=FORKS, INC.
+OUI:00C0E4*
+ ID_OUI_FROM_DATABASE=SIEMENS BUILDING
 
 OUI:0040C4*
  ID_OUI_FROM_DATABASE=KINKEI SYSTEM CORPORATION
@@ -42602,38 +43601,8 @@ OUI:004090*
 OUI:00409A*
  ID_OUI_FROM_DATABASE=NETWORK EXPRESS, INC.
 
-OUI:0040DE*
- ID_OUI_FROM_DATABASE=Elsag Datamat spa
-
-OUI:004063*
- ID_OUI_FROM_DATABASE=VIA TECHNOLOGIES, INC.
-
-OUI:00406C*
- ID_OUI_FROM_DATABASE=COPERNIQUE
-
-OUI:0040DF*
- ID_OUI_FROM_DATABASE=DIGALOG SYSTEMS, INC.
-
-OUI:004015*
- ID_OUI_FROM_DATABASE=ASCOM INFRASYS AG
-
-OUI:008056*
- ID_OUI_FROM_DATABASE=SPHINX Electronics GmbH & Co KG
-
-OUI:008060*
- ID_OUI_FROM_DATABASE=NETWORK INTERFACE CORPORATION
-
-OUI:00805E*
- ID_OUI_FROM_DATABASE=LSI LOGIC CORPORATION
-
-OUI:008093*
- ID_OUI_FROM_DATABASE=XYRON CORPORATION
-
-OUI:00C05D*
- ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES
-
-OUI:00C0E4*
- ID_OUI_FROM_DATABASE=SIEMENS BUILDING
+OUI:004055*
+ ID_OUI_FROM_DATABASE=METRONIX GMBH
 
 OUI:00C01B*
  ID_OUI_FROM_DATABASE=SOCKET COMMUNICATIONS, INC.
@@ -42659,24 +43628,48 @@ OUI:004037*
 OUI:0040CC*
  ID_OUI_FROM_DATABASE=SILCOM MANUF'G TECHNOLOGY INC.
 
-OUI:004052*
- ID_OUI_FROM_DATABASE=STAR TECHNOLOGIES, INC.
-
-OUI:00407A*
- ID_OUI_FROM_DATABASE=SOCIETE D'EXPLOITATION DU CNIT
-
-OUI:004089*
- ID_OUI_FROM_DATABASE=MEIDENSHA CORPORATION
-
-OUI:00405A*
- ID_OUI_FROM_DATABASE=GOLDSTAR INFORMATION & COMM.
-
 OUI:00404C*
  ID_OUI_FROM_DATABASE=HYPERTEC PTY LTD.
 
 OUI:00C0EE*
  ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
 
+OUI:0040A5*
+ ID_OUI_FROM_DATABASE=CLINICOMP INTL.
+
+OUI:004059*
+ ID_OUI_FROM_DATABASE=YOSHIDA KOGYO K. K.
+
+OUI:004021*
+ ID_OUI_FROM_DATABASE=RASTER GRAPHICS
+
+OUI:004081*
+ ID_OUI_FROM_DATABASE=MANNESMANN SCANGRAPHIC GMBH
+
+OUI:00806C*
+ ID_OUI_FROM_DATABASE=CEGELEC PROJECTS LTD
+
+OUI:00404A*
+ ID_OUI_FROM_DATABASE=WEST AUSTRALIAN DEPARTMENT
+
+OUI:00400A*
+ ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES, INC.
+
+OUI:004032*
+ ID_OUI_FROM_DATABASE=DIGITAL COMMUNICATIONS
+
+OUI:004042*
+ ID_OUI_FROM_DATABASE=N.A.T. GMBH
+
+OUI:0040C2*
+ ID_OUI_FROM_DATABASE=APPLIED COMPUTING DEVICES
+
+OUI:00403C*
+ ID_OUI_FROM_DATABASE=FORKS, INC.
+
+OUI:004004*
+ ID_OUI_FROM_DATABASE=ICM CO. LTD.
+
 OUI:00C0CB*
  ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY CORPORATION
 
@@ -42689,8 +43682,47 @@ OUI:00C01A*
 OUI:00404B*
  ID_OUI_FROM_DATABASE=MAPLE COMPUTER SYSTEMS
 
-OUI:004055*
- ID_OUI_FROM_DATABASE=METRONIX GMBH
+OUI:00401D*
+ ID_OUI_FROM_DATABASE=INVISIBLE SOFTWARE, INC.
+
+OUI:0040BD*
+ ID_OUI_FROM_DATABASE=STARLIGHT NETWORKS, INC.
+
+OUI:00406D*
+ ID_OUI_FROM_DATABASE=LANCO, INC.
+
+OUI:00404D*
+ ID_OUI_FROM_DATABASE=TELECOMMUNICATIONS TECHNIQUES
+
+OUI:00C0D0*
+ ID_OUI_FROM_DATABASE=RATOC SYSTEM INC.
+
+OUI:00C07A*
+ ID_OUI_FROM_DATABASE=PRIVA B.V.
+
+OUI:000701*
+ ID_OUI_FROM_DATABASE=RACAL-DATACOM
+
+OUI:00C09C*
+ ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION
+
+OUI:00C004*
+ ID_OUI_FROM_DATABASE=JAPAN BUSINESS COMPUTER CO.LTD
+
+OUI:00C062*
+ ID_OUI_FROM_DATABASE=IMPULSE TECHNOLOGY
+
+OUI:00C0BC*
+ ID_OUI_FROM_DATABASE=TELECOM AUSTRALIA/CSSC
+
+OUI:00C0EF*
+ ID_OUI_FROM_DATABASE=ABIT CORPORATION
+
+OUI:00C03C*
+ ID_OUI_FROM_DATABASE=TOWER TECH S.R.L.
+
+OUI:00C061*
+ ID_OUI_FROM_DATABASE=SOLECTEK CORPORATION
 
 OUI:004045*
  ID_OUI_FROM_DATABASE=TWINHEAD CORPORATION
@@ -42707,8 +43739,17 @@ OUI:0040B9*
 OUI:0040C7*
  ID_OUI_FROM_DATABASE=RUBY TECH CORPORATION
 
-OUI:004004*
- ID_OUI_FROM_DATABASE=ICM CO. LTD.
+OUI:004052*
+ ID_OUI_FROM_DATABASE=STAR TECHNOLOGIES, INC.
+
+OUI:00407A*
+ ID_OUI_FROM_DATABASE=SOCIETE D'EXPLOITATION DU CNIT
+
+OUI:004089*
+ ID_OUI_FROM_DATABASE=MEIDENSHA CORPORATION
+
+OUI:00405A*
+ ID_OUI_FROM_DATABASE=GOLDSTAR INFORMATION & COMM.
 
 OUI:004070*
  ID_OUI_FROM_DATABASE=INTERWARE CO., LTD.
@@ -42725,21 +43766,45 @@ OUI:0080AA*
 OUI:00C0E7*
  ID_OUI_FROM_DATABASE=FIBERDATA AB
 
-OUI:00800A*
- ID_OUI_FROM_DATABASE=JAPAN COMPUTER CORP.
+OUI:008095*
+ ID_OUI_FROM_DATABASE=BASIC MERTON HANDELSGES.M.B.H.
 
-OUI:00806E*
- ID_OUI_FROM_DATABASE=NIPPON STEEL CORPORATION
+OUI:008053*
+ ID_OUI_FROM_DATABASE=INTELLICOM, INC.
 
-OUI:008010*
- ID_OUI_FROM_DATABASE=COMMODORE INTERNATIONAL
+OUI:008026*
+ ID_OUI_FROM_DATABASE=NETWORK PRODUCTS CORPORATION
+
+OUI:0080FE*
+ ID_OUI_FROM_DATABASE=AZURE TECHNOLOGIES, INC.
+
+OUI:008028*
+ ID_OUI_FROM_DATABASE=TRADPOST (HK) LTD
+
+OUI:0080B6*
+ ID_OUI_FROM_DATABASE=THEMIS COMPUTER
+
+OUI:008058*
+ ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORPORATION
+
+OUI:0080C0*
+ ID_OUI_FROM_DATABASE=PENRIL DATACOMM
+
+OUI:0080F5*
+ ID_OUI_FROM_DATABASE=Quantel Ltd
+
+OUI:00608C*
+ ID_OUI_FROM_DATABASE=3COM CORPORATION
+
+OUI:00804E*
+ ID_OUI_FROM_DATABASE=APEX COMPUTER COMPANY
+
+OUI:00800E*
+ ID_OUI_FROM_DATABASE=ATLANTIX CORPORATION
 
 OUI:0080DA*
  ID_OUI_FROM_DATABASE=Bruel & Kjaer Sound & Vibration Measurement A/S
 
-OUI:0080E5*
- ID_OUI_FROM_DATABASE=NetApp, Inc
-
 OUI:0080BC*
  ID_OUI_FROM_DATABASE=HITACHI ENGINEERING CO., LTD
 
@@ -42758,50 +43823,74 @@ OUI:00807D*
 OUI:008063*
  ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH
 
-OUI:00608C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+OUI:008030*
+ ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS
 
-OUI:00804E*
- ID_OUI_FROM_DATABASE=APEX COMPUTER COMPANY
+OUI:008022*
+ ID_OUI_FROM_DATABASE=SCAN-OPTICS
 
-OUI:00800E*
- ID_OUI_FROM_DATABASE=ATLANTIX CORPORATION
+OUI:000041*
+ ID_OUI_FROM_DATABASE=ICE CORPORATION
 
-OUI:00806F*
- ID_OUI_FROM_DATABASE=ONELAN LTD.
+OUI:0040DE*
+ ID_OUI_FROM_DATABASE=Elsag Datamat spa
 
-OUI:008098*
- ID_OUI_FROM_DATABASE=TDK CORPORATION
+OUI:004063*
+ ID_OUI_FROM_DATABASE=VIA TECHNOLOGIES, INC.
 
-OUI:00809C*
- ID_OUI_FROM_DATABASE=LUXCOM, INC.
+OUI:00406C*
+ ID_OUI_FROM_DATABASE=COPERNIQUE
 
-OUI:008065*
- ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD.
+OUI:0040DF*
+ ID_OUI_FROM_DATABASE=DIGALOG SYSTEMS, INC.
 
-OUI:008016*
- ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN
+OUI:004015*
+ ID_OUI_FROM_DATABASE=ASCOM INFRASYS AG
 
-OUI:0080E6*
- ID_OUI_FROM_DATABASE=PEER NETWORKS, INC.
+OUI:008056*
+ ID_OUI_FROM_DATABASE=SPHINX Electronics GmbH & Co KG
 
-OUI:0080A2*
- ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS
+OUI:008060*
+ ID_OUI_FROM_DATABASE=NETWORK INTERFACE CORPORATION
 
-OUI:0080E0*
- ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC.
+OUI:00805E*
+ ID_OUI_FROM_DATABASE=LSI LOGIC CORPORATION
 
-OUI:008050*
- ID_OUI_FROM_DATABASE=ZIATECH CORPORATION
+OUI:008093*
+ ID_OUI_FROM_DATABASE=XYRON CORPORATION
 
-OUI:0000E0*
- ID_OUI_FROM_DATABASE=QUADRAM CORP.
+OUI:008006*
+ ID_OUI_FROM_DATABASE=COMPUADD CORPORATION
 
-OUI:000057*
- ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD.
+OUI:0080EF*
+ ID_OUI_FROM_DATABASE=RATIONAL
 
-OUI:0000D6*
- ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING
+OUI:0080C4*
+ ID_OUI_FROM_DATABASE=DOCUMENT TECHNOLOGIES, INC.
+
+OUI:00801D*
+ ID_OUI_FROM_DATABASE=INTEGRATED INFERENCE MACHINES
+
+OUI:008015*
+ ID_OUI_FROM_DATABASE=SEIKO SYSTEMS, INC.
+
+OUI:008034*
+ ID_OUI_FROM_DATABASE=SMT GOUPIL
+
+OUI:0080C9*
+ ID_OUI_FROM_DATABASE=ALBERTA MICROELECTRONIC CENTRE
+
+OUI:00800B*
+ ID_OUI_FROM_DATABASE=CSK CORPORATION
+
+OUI:00800A*
+ ID_OUI_FROM_DATABASE=JAPAN COMPUTER CORP.
+
+OUI:00806E*
+ ID_OUI_FROM_DATABASE=NIPPON STEEL CORPORATION
+
+OUI:008010*
+ ID_OUI_FROM_DATABASE=COMMODORE INTERNATIONAL
 
 OUI:0000C8*
  ID_OUI_FROM_DATABASE=ALTOS COMPUTER SYSTEMS
@@ -42830,56 +43919,56 @@ OUI:0000E7*
 OUI:0000F3*
  ID_OUI_FROM_DATABASE=GANDALF DATA LIMITED
 
-OUI:000064*
- ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation
+OUI:00005C*
+ ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC.
 
-OUI:00002C*
- ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED
+OUI:0000AC*
+ ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING
 
-OUI:00002A*
- ID_OUI_FROM_DATABASE=TRW - SEDD/INP
+OUI:0000F2*
+ ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS
 
-OUI:0000F1*
- ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION
+OUI:000030*
+ ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD
 
-OUI:000083*
- ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC
+OUI:000035*
+ ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION
 
-OUI:000020*
- ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB
+OUI:0000E0*
+ ID_OUI_FROM_DATABASE=QUADRAM CORP.
 
-OUI:00007A*
- ID_OUI_FROM_DATABASE=DANA COMPUTER INC.
+OUI:000057*
+ ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD.
 
-OUI:00007C*
- ID_OUI_FROM_DATABASE=AMPERE INCORPORATED
+OUI:0000D6*
+ ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING
 
-OUI:00008A*
- ID_OUI_FROM_DATABASE=DATAHOUSE INFORMATION SYSTEMS
+OUI:00806F*
+ ID_OUI_FROM_DATABASE=ONELAN LTD.
 
-OUI:000068*
- ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS
+OUI:008098*
+ ID_OUI_FROM_DATABASE=TDK CORPORATION
 
-OUI:0000A8*
- ID_OUI_FROM_DATABASE=STRATUS COMPUTER INC.
+OUI:00809C*
+ ID_OUI_FROM_DATABASE=LUXCOM, INC.
 
-OUI:0000DF*
- ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV
+OUI:008065*
+ ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD.
 
-OUI:000062*
- ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS
+OUI:008016*
+ ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN
 
-OUI:0000AD*
- ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC.
+OUI:0080E6*
+ ID_OUI_FROM_DATABASE=PEER NETWORKS, INC.
 
-OUI:0000D0*
- ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD.
+OUI:0080A2*
+ ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS
 
-OUI:000093*
- ID_OUI_FROM_DATABASE=PROTEON INC.
+OUI:0080E0*
+ ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC.
 
-OUI:008008*
- ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS
+OUI:008050*
+ ID_OUI_FROM_DATABASE=ZIATECH CORPORATION
 
 OUI:0080FF*
  ID_OUI_FROM_DATABASE=SOC. DE TELEINFORMATIQUE RTC
@@ -42899,14 +43988,8 @@ OUI:000024*
 OUI:000048*
  ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION
 
-OUI:008030*
- ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS
-
-OUI:008022*
- ID_OUI_FROM_DATABASE=SCAN-OPTICS
-
-OUI:000041*
- ID_OUI_FROM_DATABASE=ICE CORPORATION
+OUI:000016*
+ ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS     .
 
 OUI:00001E*
  ID_OUI_FROM_DATABASE=TELSIST INDUSTRIA ELECTRONICA
@@ -42923,44 +44006,23 @@ OUI:0080F9*
 OUI:008005*
  ID_OUI_FROM_DATABASE=CACTUS COMPUTER INC.
 
-OUI:00801D*
- ID_OUI_FROM_DATABASE=INTEGRATED INFERENCE MACHINES
-
-OUI:008015*
- ID_OUI_FROM_DATABASE=SEIKO SYSTEMS, INC.
-
-OUI:008034*
- ID_OUI_FROM_DATABASE=SMT GOUPIL
-
-OUI:0080C9*
- ID_OUI_FROM_DATABASE=ALBERTA MICROELECTRONIC CENTRE
-
-OUI:00800B*
- ID_OUI_FROM_DATABASE=CSK CORPORATION
-
-OUI:000016*
- ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS     .
-
-OUI:00005C*
- ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC.
-
-OUI:0000AC*
- ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING
+OUI:008008*
+ ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS
 
-OUI:0000F2*
- ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS
+OUI:08005E*
+ ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC.
 
-OUI:000030*
- ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD
+OUI:08005A*
+ ID_OUI_FROM_DATABASE=IBM Corp
 
-OUI:000035*
- ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION
+OUI:080056*
+ ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER
 
-OUI:020701*
- ID_OUI_FROM_DATABASE=RACAL-DATACOM
+OUI:080053*
+ ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY
 
-OUI:080011*
- ID_OUI_FROM_DATABASE=TEKTRONIX INC.
+OUI:08004F*
+ ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
 
 OUI:080040*
  ID_OUI_FROM_DATABASE=FERRANTI COMPUTER SYS. LIMITED
@@ -42974,38 +44036,53 @@ OUI:08003D*
 OUI:080039*
  ID_OUI_FROM_DATABASE=SPIDER SYSTEMS LIMITED
 
-OUI:080030*
- ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION
+OUI:00DD0C*
+ ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
 
-OUI:080027*
- ID_OUI_FROM_DATABASE=Cadmus Computer Systems
+OUI:000005*
+ ID_OUI_FROM_DATABASE=XEROX CORPORATION
 
-OUI:00009B*
- ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC
+OUI:0000AA*
+ ID_OUI_FROM_DATABASE=XEROX CORPORATION
 
-OUI:00DD0F*
- ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+OUI:000064*
+ ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation
 
-OUI:000001*
- ID_OUI_FROM_DATABASE=XEROX CORPORATION
+OUI:00002C*
+ ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED
 
-OUI:080021*
- ID_OUI_FROM_DATABASE=3M COMPANY
+OUI:00002A*
+ ID_OUI_FROM_DATABASE=TRW - SEDD/INP
 
-OUI:AA0004*
- ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+OUI:0000F1*
+ ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION
 
-OUI:08000C*
- ID_OUI_FROM_DATABASE=MIKLYN DEVELOPMENT CO.
+OUI:000083*
+ ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC
 
-OUI:00DD08*
- ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+OUI:000020*
+ ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB
 
-OUI:0000D8*
- ID_OUI_FROM_DATABASE=NOVELL, INC.
+OUI:00007A*
+ ID_OUI_FROM_DATABASE=DANA COMPUTER INC.
 
-OUI:0000A0*
- ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd.
+OUI:00007C*
+ ID_OUI_FROM_DATABASE=AMPERE INCORPORATED
+
+OUI:00008A*
+ ID_OUI_FROM_DATABASE=DATAHOUSE INFORMATION SYSTEMS
+
+OUI:080030*
+ ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION
+
+OUI:080027*
+ ID_OUI_FROM_DATABASE=Cadmus Computer Systems
+
+OUI:020701*
+ ID_OUI_FROM_DATABASE=RACAL-DATACOM
+
+OUI:080011*
+ ID_OUI_FROM_DATABASE=TEKTRONIX INC.
 
 OUI:08007F*
  ID_OUI_FROM_DATABASE=CARNEGIE-MELLON UNIVERSITY
@@ -43016,14 +44093,8 @@ OUI:080082*
 OUI:08007B*
  ID_OUI_FROM_DATABASE=SANYO ELECTRIC CO. LTD.
 
-OUI:00DD0C*
- ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
-
-OUI:000005*
- ID_OUI_FROM_DATABASE=XEROX CORPORATION
-
-OUI:0000AA*
- ID_OUI_FROM_DATABASE=XEROX CORPORATION
+OUI:080074*
+ ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD.
 
 OUI:00406B*
  ID_OUI_FROM_DATABASE=SYSGEN
@@ -43043,35 +44114,56 @@ OUI:08004B*
 OUI:080003*
  ID_OUI_FROM_DATABASE=ADVANCED COMPUTER COMM.
 
-OUI:080074*
- ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD.
+OUI:00009B*
+ ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC
 
-OUI:08005E*
- ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC.
+OUI:000068*
+ ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS
 
-OUI:08005A*
- ID_OUI_FROM_DATABASE=IBM Corp
+OUI:0000A8*
+ ID_OUI_FROM_DATABASE=STRATUS COMPUTER INC.
 
-OUI:080056*
- ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER
+OUI:0000DF*
+ ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV
 
-OUI:080053*
- ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY
+OUI:000062*
+ ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS
 
-OUI:08004F*
- ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
+OUI:0000AD*
+ ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC.
 
-OUI:F8E71E*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:0000D0*
+ ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD.
 
-OUI:00194B*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:000093*
+ ID_OUI_FROM_DATABASE=PROTEON INC.
 
-OUI:001F95*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:0000A0*
+ ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd.
 
-OUI:000E59*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:00DD0F*
+ ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+
+OUI:000001*
+ ID_OUI_FROM_DATABASE=XEROX CORPORATION
+
+OUI:080021*
+ ID_OUI_FROM_DATABASE=3M COMPANY
+
+OUI:AA0004*
+ ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION
+
+OUI:08000C*
+ ID_OUI_FROM_DATABASE=MIKLYN DEVELOPMENT CO.
+
+OUI:00DD08*
+ ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+
+OUI:0000D8*
+ ID_OUI_FROM_DATABASE=NOVELL, INC.
+
+OUI:F8E71E*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
 
 OUI:A01B29*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -43085,6 +44177,15 @@ OUI:ECDF3A*
 OUI:E45AA2*
  ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
 
+OUI:00194B*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:001F95*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:000E59*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
 OUI:00235A*
  ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
 
@@ -43103,6 +44204,9 @@ OUI:94C150*
 OUI:60FE20*
  ID_OUI_FROM_DATABASE=2Wire Inc
 
+OUI:D4AE52*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
 OUI:989096*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
@@ -43115,6 +44219,12 @@ OUI:00D09E*
 OUI:000D72*
  ID_OUI_FROM_DATABASE=2Wire Inc
 
+OUI:B0E754*
+ ID_OUI_FROM_DATABASE=2Wire Inc
+
+OUI:B8E625*
+ ID_OUI_FROM_DATABASE=2Wire Inc
+
 OUI:000F1F*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
@@ -43124,15 +44234,6 @@ OUI:14FEB5*
 OUI:0015C5*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
-OUI:D4AE52*
- ID_OUI_FROM_DATABASE=Dell Inc.
-
-OUI:B0E754*
- ID_OUI_FROM_DATABASE=2Wire Inc
-
-OUI:B8E625*
- ID_OUI_FROM_DATABASE=2Wire Inc
-
 OUI:549F35*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
@@ -43160,12 +44261,12 @@ OUI:A4A1C2*
 OUI:348446*
  ID_OUI_FROM_DATABASE=Ericsson AB
 
-OUI:AC2B6E*
- ID_OUI_FROM_DATABASE=Intel Corporate
-
 OUI:F8F1B6*
  ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
 
+OUI:AC2B6E*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
 OUI:00216A*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
@@ -43178,19 +44279,22 @@ OUI:0016EB*
 OUI:0018DE*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:681729*
+OUI:28B2BD*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:5C514F*
+OUI:08D40C*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:B808CF*
+OUI:843A4B*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:C8F733*
+OUI:681729*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:4851B7*
+OUI:5C514F*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:B808CF*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
 OUI:5CC5D4*
@@ -43202,25 +44306,22 @@ OUI:7CCCB8*
 OUI:F40669*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:3CA9F4*
- ID_OUI_FROM_DATABASE=Intel Corporate
-
-OUI:28B2BD*
+OUI:C8F733*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:08D40C*
+OUI:0CD292*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:843A4B*
+OUI:78929C*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:0CD292*
+OUI:6805CA*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:78929C*
+OUI:4851B7*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:6805CA*
+OUI:3CA9F4*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
 OUI:ACA31E*
@@ -43241,6 +44342,9 @@ OUI:84D47E*
 OUI:A85840*
  ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
 
+OUI:002423*
+ ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc.
+
 OUI:002243*
  ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
 
@@ -43262,23 +44366,14 @@ OUI:240A64*
 OUI:D0E782*
  ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
 
-OUI:0C4C39*
- ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
-
-OUI:002423*
- ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc.
-
 OUI:A81D16*
  ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
 
 OUI:38A53C*
  ID_OUI_FROM_DATABASE=COMECER Netherlands
 
-OUI:001D8B*
- ID_OUI_FROM_DATABASE=ADB Broadband Italia
-
-OUI:A4526F*
- ID_OUI_FROM_DATABASE=ADB Broadband Italia
+OUI:0C4C39*
+ ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
 
 OUI:581243*
  ID_OUI_FROM_DATABASE=AcSiP Technology Corp.
@@ -43292,15 +44387,18 @@ OUI:0030F1*
 OUI:001974*
  ID_OUI_FROM_DATABASE=16063
 
-OUI:ECF00E*
- ID_OUI_FROM_DATABASE=AboCom
-
 OUI:3039F2*
  ID_OUI_FROM_DATABASE=ADB Broadband Italia
 
 OUI:000827*
  ID_OUI_FROM_DATABASE=ADB Broadband Italia
 
+OUI:001D8B*
+ ID_OUI_FROM_DATABASE=ADB Broadband Italia
+
+OUI:A4526F*
+ ID_OUI_FROM_DATABASE=ADB Broadband Italia
+
 OUI:001CA8*
  ID_OUI_FROM_DATABASE=AirTies Wireless Netowrks
 
@@ -43313,6 +44411,12 @@ OUI:18FE34*
 OUI:54F6C5*
  ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD
 
+OUI:A43111*
+ ID_OUI_FROM_DATABASE=ZIV
+
+OUI:ECF00E*
+ ID_OUI_FROM_DATABASE=AboCom
+
 OUI:28EF01*
  ID_OUI_FROM_DATABASE=Private
 
@@ -43322,12 +44426,6 @@ OUI:5C338E*
 OUI:001AEB*
  ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K.
 
-OUI:747548*
- ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
-
-OUI:A43111*
- ID_OUI_FROM_DATABASE=ZIV
-
 OUI:5C93A2*
  ID_OUI_FROM_DATABASE=Liteon Technology Corporation
 
@@ -43337,39 +44435,12 @@ OUI:E8C74F*
 OUI:E8F724*
  ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
 
-OUI:1C1448*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:707E43*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:001AAD*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:A47AA4*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:701A04*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:747548*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
 
-OUI:00D9D1*
+OUI:080046*
  ID_OUI_FROM_DATABASE=Sony Corporation
 
-OUI:48D224*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-
-OUI:2CD05A*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-
-OUI:74E543*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-
-OUI:A4DB30*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-
-OUI:B8EE65*
- ID_OUI_FROM_DATABASE=Liteon Technology Corporation
-
 OUI:001DBA*
  ID_OUI_FROM_DATABASE=Sony Corporation
 
@@ -43391,6 +44462,24 @@ OUI:001B59*
 OUI:78843C*
  ID_OUI_FROM_DATABASE=Sony Corporation
 
+OUI:701A04*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:48D224*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:2CD05A*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:74E543*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:A4DB30*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:B8EE65*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
 OUI:0023F1*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -43400,29 +44489,17 @@ OUI:3017C8*
 OUI:18002D*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:3C0771*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:D8D43C*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:0CFE45*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
-OUI:F8D0AC*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
 OUI:04E676*
  ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
 
 OUI:0022F4*
  ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
 
-OUI:00041F*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+OUI:1C1448*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:080046*
- ID_OUI_FROM_DATABASE=Sony Corporation
+OUI:707E43*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
 OUI:0003E0*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -43433,6 +44510,12 @@ OUI:00128A*
 OUI:001225*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
+OUI:001AAD*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:A47AA4*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
 OUI:3C754A*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
@@ -43451,45 +44534,39 @@ OUI:002395*
 OUI:0023ED*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:001B52*
+OUI:745612*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:00230B*
+OUI:E46449*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:001E8D*
+OUI:002493*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:0023A2*
+OUI:40FC89*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:001BDD*
+OUI:001B52*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:001404*
+OUI:00230B*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:745612*
+OUI:001E8D*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:E46449*
+OUI:0023A2*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:002493*
+OUI:001BDD*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:40FC89*
+OUI:001404*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
 OUI:00195E*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:000D92*
- ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
-
-OUI:009096*
- ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
-
 OUI:0011F5*
  ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
 
@@ -43505,8 +44582,11 @@ OUI:000B6A*
 OUI:40BA61*
  ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
 
-OUI:841B5E*
- ID_OUI_FROM_DATABASE=NETGEAR
+OUI:000D92*
+ ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
+
+OUI:009096*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
 
 OUI:204E7F*
  ID_OUI_FROM_DATABASE=NETGEAR
@@ -43523,11 +44603,8 @@ OUI:C03F0E*
 OUI:001F33*
  ID_OUI_FROM_DATABASE=NETGEAR
 
-OUI:1883BF*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:9C80DF*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+OUI:841B5E*
+ ID_OUI_FROM_DATABASE=NETGEAR
 
 OUI:001CCC*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
@@ -43535,18 +44612,6 @@ OUI:001CCC*
 OUI:94EBCD*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
 
-OUI:644FB0*
- ID_OUI_FROM_DATABASE=Hyunjin.com
-
-OUI:001A2A*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:001D19*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
-OUI:88252C*
- ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
-
 OUI:A4E4B8*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
 
@@ -43559,6 +44624,24 @@ OUI:BC0543*
 OUI:002675*
  ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd
 
+OUI:001D19*
+ ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+
+OUI:88252C*
+ ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+
+OUI:1883BF*
+ ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+
+OUI:9C80DF*
+ ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+
+OUI:644FB0*
+ ID_OUI_FROM_DATABASE=Hyunjin.com
+
+OUI:001A2A*
+ ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
+
 OUI:001F3F*
  ID_OUI_FROM_DATABASE=AVM GmbH
 
@@ -43571,85 +44654,40 @@ OUI:6CB0CE*
 OUI:100D7F*
  ID_OUI_FROM_DATABASE=NETGEAR
 
-OUI:0020D6*
- ID_OUI_FROM_DATABASE=Breezecom, Ltd.
-
 OUI:001018*
  ID_OUI_FROM_DATABASE=Broadcom
 
 OUI:001BE9*
  ID_OUI_FROM_DATABASE=Broadcom
 
-OUI:307C5E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0010DB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:00121E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0014F6*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:EC3EF7*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0C8610*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:40A677*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:841888*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:002688*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0017CB*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:DC38E1*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:40B4F0*
- ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:0020D6*
+ ID_OUI_FROM_DATABASE=Breezecom, Ltd.
 
 OUI:008077*
  ID_OUI_FROM_DATABASE=Brother industries, LTD.
 
-OUI:029D8E*
- ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC.
-
 OUI:FC2F40*
  ID_OUI_FROM_DATABASE=Calxeda, Inc.
 
+OUI:029D8E*
+ ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC.
+
 OUI:0026E4*
  ID_OUI_FROM_DATABASE=Canal +
 
-OUI:389496*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:0CB319*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:08EE8B*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
-OUI:84A466*
+OUI:E458E7*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:981DFA*
+OUI:8CBFA6*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:FCF136*
+OUI:7840E4*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:0C8910*
+OUI:9000DB*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:54FA3E*
+OUI:183A2D*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:A89FBA*
@@ -43667,13 +44705,16 @@ OUI:5C2E59*
 OUI:646CB2*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:F884F2*
+OUI:A48431*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:14B484*
+OUI:E4F8EF*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:608F5C*
+OUI:1867B0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:F40E22*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:4CBCA5*
@@ -43688,51 +44729,66 @@ OUI:B0D09C*
 OUI:4CA56D*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:A48431*
+OUI:08373D*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:E4F8EF*
+OUI:50F520*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:1432D1*
+OUI:A4EBD3*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:E458E7*
+OUI:28987B*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:8CBFA6*
+OUI:9C3AAF*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:7840E4*
+OUI:1432D1*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:9000DB*
+OUI:F884F2*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:183A2D*
+OUI:14B484*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:08373D*
+OUI:608F5C*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:50F520*
+OUI:389496*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:A4EBD3*
+OUI:0CB319*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:28987B*
+OUI:08EE8B*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:1867B0*
+OUI:84A466*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:F40E22*
+OUI:981DFA*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:9C3AAF*
+OUI:FCF136*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:0C8910*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:54FA3E*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
+OUI:702559*
+ ID_OUI_FROM_DATABASE=CyberTAN Technology Inc.
+
+OUI:0090D6*
+ ID_OUI_FROM_DATABASE=Crystal Group, Inc.
+
+OUI:02CF1C*
+ ID_OUI_FROM_DATABASE=Communication Machinery Corporation
+
 OUI:BCF2AF*
  ID_OUI_FROM_DATABASE=devolo AG
 
@@ -43742,36 +44798,30 @@ OUI:0270B3*
 OUI:000FF6*
  ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP
 
-OUI:702559*
- ID_OUI_FROM_DATABASE=CyberTAN Technology Inc.
-
-OUI:0090D6*
- ID_OUI_FROM_DATABASE=Crystal Group, Inc.
-
 OUI:001DAA*
  ID_OUI_FROM_DATABASE=DrayTek Corp.
 
-OUI:02CF1C*
- ID_OUI_FROM_DATABASE=Communication Machinery Corporation
-
 OUI:0C75BD*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:38F0C8*
  ID_OUI_FROM_DATABASE=Livestream
 
+OUI:0C1167*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
 OUI:74EAE8*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
 OUI:A811FC*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:0C1167*
- ID_OUI_FROM_DATABASE=Cisco Systems, Inc
-
 OUI:001982*
  ID_OUI_FROM_DATABASE=SmarDTV
 
+OUI:00904B*
+ ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
+
 OUI:10C6FC*
  ID_OUI_FROM_DATABASE=Garmin International
 
@@ -43796,15 +44846,6 @@ OUI:002682*
 OUI:001A73*
  ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
 
-OUI:00904B*
- ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
-
-OUI:D86BF7*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
-OUI:A4C0E1*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
 OUI:34AF2C*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
@@ -43820,12 +44861,6 @@ OUI:600194*
 OUI:F44D17*
  ID_OUI_FROM_DATABASE=GOLDCARD HIGH-TECH CO.,LTD.
 
-OUI:001E35*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
-OUI:001FC5*
- ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
-
 OUI:0021BD*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
@@ -43835,7 +44870,10 @@ OUI:002709*
 OUI:E84ECE*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
-OUI:0009BF*
+OUI:D86BF7*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
+OUI:A4C0E1*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
 OUI:001AE9*
@@ -43844,6 +44882,15 @@ OUI:001AE9*
 OUI:001CBE*
  ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
 
+OUI:001E35*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
+OUI:001FC5*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
+OUI:0009BF*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
 OUI:002403*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
@@ -43853,56 +44900,440 @@ OUI:002265*
 OUI:0019B7*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:002404*
+OUI:001D6E*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:0002EE*
+OUI:001B33*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001C9A*
+OUI:ECF35B*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:EC9B5B*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:BCC6DB*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:0021AA*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001F01*
+OUI:002669*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:000EED*
+OUI:0022FD*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001E3A*
+OUI:002109*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001A89*
+OUI:002108*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:0021AA*
+OUI:001F01*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:002669*
+OUI:000EED*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:0022FD*
+OUI:001E3A*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:002109*
+OUI:001A89*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:002108*
+OUI:002404*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001D6E*
+OUI:0002EE*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001B33*
+OUI:001C9A*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:ECF35B*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:B83241*
+ ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd.
 
-OUI:EC9B5B*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:9897D1*
+ ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
 
-OUI:BCC6DB*
- ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:94C960*
+ ID_OUI_FROM_DATABASE=Zhongshan B&T technology.co.,ltd
+
+OUI:E04FBD*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
+
+OUI:001479*
+ ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd.
+
+OUI:9C4FDA*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:1C5CF2*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:0821EF*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:B462AD*
+ ID_OUI_FROM_DATABASE=Elysia Germany GmbH
+
+OUI:747818*
+ ID_OUI_FROM_DATABASE=Jurumani Solutions
+
+OUI:A0CBFD*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:34145F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:803896*
+ ID_OUI_FROM_DATABASE=SHARP Corporation
+
+OUI:00D9D1*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:F8D0AC*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:0CFE45*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:D8D43C*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:3C0771*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:686E23*
+ ID_OUI_FROM_DATABASE=Wi3 Inc.
+
+OUI:B8A175*
+ ID_OUI_FROM_DATABASE=Roku, Inc.
+
+OUI:80D160*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
+OUI:0080E5*
+ ID_OUI_FROM_DATABASE=NetApp
+
+OUI:E49A79*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:28A02B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:B44BD2*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:002340*
+ ID_OUI_FROM_DATABASE=MiXTelematics
+
+OUI:B48B19*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:4CCC6A*
+ ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD.
+
+OUI:00AF1F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:245EBE*
+ ID_OUI_FROM_DATABASE=QNAP Systems, Inc.
+
+OUI:A89352*
+ ID_OUI_FROM_DATABASE=SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD
+
+OUI:AC5F3E*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+
+OUI:985BB0*
+ ID_OUI_FROM_DATABASE=KMDATA INC.
+
+OUI:6C8FB5*
+ ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
+
+OUI:D4E33F*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:143E60*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:248A07*
+ ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc.
+
+OUI:9C9D5D*
+ ID_OUI_FROM_DATABASE=Raden Inc
+
+OUI:B07FB9*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:70661B*
+ ID_OUI_FROM_DATABASE=Sonova AG
+
+OUI:1C98EC*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:EC438B*
+ ID_OUI_FROM_DATABASE=YAPTV
+
+OUI:E8FD72*
+ ID_OUI_FROM_DATABASE=SHANGHAI LINGUO TECHNOLOGY CO., LTD.
+
+OUI:98BB1E*
+ ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd.
+
+OUI:001D0D*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:00041F*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:20A90E*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
+OUI:CCB11A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:1866DA*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:981FB1*
+ ID_OUI_FROM_DATABASE=Shenzhen Lemon Network Technology Co.,Ltd
+
+OUI:40476A*
+ ID_OUI_FROM_DATABASE=AG Acquisition Corp. d.b.a. ASTRO Gaming
+
+OUI:A4BF01*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:0004C6*
+ ID_OUI_FROM_DATABASE=YAMAHA MOTOR CO.,LTD
+
+OUI:509EA7*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:DCCF96*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:64CC2E*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:14D11F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:54511B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:68536C*
+ ID_OUI_FROM_DATABASE=SPnS Co.,Ltd
+
+OUI:005BA1*
+ ID_OUI_FROM_DATABASE=shanghai huayuan chuangxin software CO., LTD.
+
+OUI:B07E70*
+ ID_OUI_FROM_DATABASE=Zadara Storage Ltd.
+
+OUI:405EE1*
+ ID_OUI_FROM_DATABASE=Shenzhen H&T Intelligent Control Co.,Ltd.
+
+OUI:88795B*
+ ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+
+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
+
+OUI:9466E7*
+ ID_OUI_FROM_DATABASE=WOM Engineering
+
+OUI:F8A188*
+ ID_OUI_FROM_DATABASE=LED Roadway Lighting
+
+OUI:001174*
+ ID_OUI_FROM_DATABASE=Mojo Networks, Inc.
+
+OUI:BC15AC*
+ ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A.
+
+OUI:1C740D*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+
+OUI:140C5B*
+ ID_OUI_FROM_DATABASE=PLNetworks
+
+OUI:D0B0CD*
+ ID_OUI_FROM_DATABASE=Moen
+
+OUI:DCFE07*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:E47E66*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:9C741A*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:EC93ED*
+ ID_OUI_FROM_DATABASE=DDoS-Guard LTD
+
+OUI:4C72B9*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:0071C2*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:F462D0*
+ ID_OUI_FROM_DATABASE=Not for Radio, LLC
+
+OUI:94513D*
+ ID_OUI_FROM_DATABASE=iSmart Alarm, Inc.
+
+OUI:C89CDC*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:002511*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:000E03*
+ ID_OUI_FROM_DATABASE=Emulex Corporation
+
+OUI:001BB9*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:001921*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:00142A*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:0050FC*
+ ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
+
+OUI:200A5E*
+ ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing Co., Ltd.
+
+OUI:0001F4*
+ ID_OUI_FROM_DATABASE=Enterasys
+
+OUI:487ADA*
+ ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+
+OUI:1C7370*
+ ID_OUI_FROM_DATABASE=Neotech
+
+OUI:30E37A*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:A08CFD*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:4CA003*
+ ID_OUI_FROM_DATABASE=T-21 Technologies LLC
+
+OUI:F0EE58*
+ ID_OUI_FROM_DATABASE=PACE Telematics GmbH
+
+OUI:001397*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:00A0A4*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:4000E0*
+ ID_OUI_FROM_DATABASE=Derek(Shaoguan)Limited
+
+OUI:A4E597*
+ ID_OUI_FROM_DATABASE=Gessler GmbH
+
+OUI:001A34*
+ ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+
+OUI:0024F4*
+ ID_OUI_FROM_DATABASE=Kaminario, Ltd.
+
+OUI:001D08*
+ ID_OUI_FROM_DATABASE=Jiangsu Yinhe  Electronics Co.,Ltd.
+
+OUI:0018D7*
+ ID_OUI_FROM_DATABASE=JAVAD GNSS, Inc.
+
+OUI:001C6C*
+ ID_OUI_FROM_DATABASE=30805
+
+OUI:00A0B0*
+ ID_OUI_FROM_DATABASE=I-O DATA DEVICE, INC.
+
+OUI:00E0CF*
+ ID_OUI_FROM_DATABASE=INTEGRATED DEVICE
+
+OUI:547F54*
+ ID_OUI_FROM_DATABASE=INGENICO
+
+OUI:48C049*
+ ID_OUI_FROM_DATABASE=Broad Telecom SA
+
+OUI:DC38E1*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:40A677*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0C8610*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:EC3EF7*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0014F6*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:00121E*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0010DB*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:307C5E*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:002688*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:841888*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:40B4F0*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0017CB*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:E0A3AC*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:044E5A*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:E00EDA*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
 OUI:D86CE9*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -45236,12 +46667,6 @@ OUI:346C0F*
 OUI:3C912B*
  ID_OUI_FROM_DATABASE=Vexata Inc
 
-OUI:F8C96C*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
-OUI:48555F*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:54369B*
  ID_OUI_FROM_DATABASE=1Verge Internet Technology (Beijing) Co., Ltd.
 
@@ -45440,9 +46865,6 @@ OUI:14EDE4*
 OUI:3438AF*
  ID_OUI_FROM_DATABASE=Inlab Software GmbH
 
-OUI:D897BA*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:049B9C*
  ID_OUI_FROM_DATABASE=Eadingcore  Intelligent Technology Co., Ltd.
 
@@ -45473,9 +46895,6 @@ OUI:EC59E7*
 OUI:08EFAB*
  ID_OUI_FROM_DATABASE=SAYME WIRELESS SENSOR NETWORK
 
-OUI:BC52B4*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:C81B6B*
  ID_OUI_FROM_DATABASE=Innova Security
 
@@ -45512,9 +46931,6 @@ OUI:2C600C*
 OUI:902CC7*
  ID_OUI_FROM_DATABASE=C-MAX Asia Limited
 
-OUI:B8AEED*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
 OUI:1C965A*
  ID_OUI_FROM_DATABASE=Weifang goertek Electronics CO.,LTD
 
@@ -45959,9 +47375,6 @@ OUI:7C9763*
 OUI:0444A1*
  ID_OUI_FROM_DATABASE=TELECON GALICIA,S.A.
 
-OUI:C03FD5*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., LTD
-
 OUI:84569C*
  ID_OUI_FROM_DATABASE=Coho Data, Inc.,
 
@@ -46130,9 +47543,6 @@ OUI:C0C687*
 OUI:142BD2*
  ID_OUI_FROM_DATABASE=Armtel Ltd.
 
-OUI:D4AD2D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:F845AD*
  ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
 
@@ -46196,9 +47606,6 @@ OUI:341B22*
 OUI:B4346C*
  ID_OUI_FROM_DATABASE=MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED
 
-OUI:4C55CC*
- ID_OUI_FROM_DATABASE=ACKme Networks Pty Ltd
-
 OUI:9C1465*
  ID_OUI_FROM_DATABASE=Edata Elektronik San. ve Tic. A.Ş.
 
@@ -46343,12 +47750,6 @@ OUI:784B08*
 OUI:0C2D89*
  ID_OUI_FROM_DATABASE=QiiQ Communications Inc.
 
-OUI:34BF90*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
-OUI:D467E7*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:604A1C*
  ID_OUI_FROM_DATABASE=SUYIN Corporation
 
@@ -46406,9 +47807,6 @@ OUI:381766*
 OUI:204C6D*
  ID_OUI_FROM_DATABASE=Hugo Brennenstuhl Gmbh & Co. KG.
 
-OUI:D49524*
- ID_OUI_FROM_DATABASE=Clover Network, Inc.
-
 OUI:DC825B*
  ID_OUI_FROM_DATABASE=JANUS, spol. s r.o.
 
@@ -46580,9 +47978,6 @@ OUI:78995C*
 OUI:8CC5E1*
  ID_OUI_FROM_DATABASE=ShenZhen Konka Telecommunication Technology Co.,Ltd
 
-OUI:7427EA*
- ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., Ltd.
-
 OUI:6CB311*
  ID_OUI_FROM_DATABASE=Shenzhen Lianrui Electronics Co.,Ltd
 
@@ -46730,9 +48125,6 @@ OUI:CC3A61*
 OUI:A00363*
  ID_OUI_FROM_DATABASE=Robert Bosch Healthcare GmbH
 
-OUI:4C8FA5*
- ID_OUI_FROM_DATABASE=Jastec
-
 OUI:F0F644*
  ID_OUI_FROM_DATABASE=Whitesky Science & Technology Co.,Ltd.
 
@@ -46808,9 +48200,6 @@ OUI:A854B2*
 OUI:98291D*
  ID_OUI_FROM_DATABASE=Jaguar de Mexico, SA de CV
 
-OUI:8C3C4A*
- ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC.
-
 OUI:18863A*
  ID_OUI_FROM_DATABASE=DIGITAL ART SYSTEM
 
@@ -46988,9 +48377,6 @@ OUI:E44F5F*
 OUI:08B738*
  ID_OUI_FROM_DATABASE=Lite-On Technogy Corp.
 
-OUI:702526*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:9C6650*
  ID_OUI_FROM_DATABASE=Glodio Technolies Co.,Ltd Tianjin Branch
 
@@ -47084,9 +48470,6 @@ OUI:346E8A*
 OUI:ACEE3B*
  ID_OUI_FROM_DATABASE=6harmonics Inc
 
-OUI:04C1B9*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:681605*
  ID_OUI_FROM_DATABASE=Systems And Electronic Development FZCO
 
@@ -47438,9 +48821,6 @@ OUI:DC3C2E*
 OUI:40BC8B*
  ID_OUI_FROM_DATABASE=itelio GmbH
 
-OUI:903AA0*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:88C36E*
  ID_OUI_FROM_DATABASE=Beijing Ereneben lnformation Technology Limited
 
@@ -47966,9 +49346,6 @@ OUI:20D5AB*
 OUI:F05849*
  ID_OUI_FROM_DATABASE=CareView Communications
 
-OUI:E06995*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:BC15A6*
  ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd.
 
@@ -47984,9 +49361,6 @@ OUI:F05D89*
 OUI:AC02CF*
  ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda
 
-OUI:A0B662*
- ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd.
-
 OUI:9067B5*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent
 
@@ -48515,9 +49889,6 @@ OUI:E43593*
 OUI:E0BC43*
  ID_OUI_FROM_DATABASE=C2 Microsystems, Inc.
 
-OUI:7071BC*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:7884EE*
  ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A.
 
@@ -48890,9 +50261,6 @@ OUI:0026A4*
 OUI:00269E*
  ID_OUI_FROM_DATABASE=Quanta Computer Inc
 
-OUI:002697*
- ID_OUI_FROM_DATABASE=Cheetah Technologies, L.P.
-
 OUI:002698*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -48914,9 +50282,6 @@ OUI:002678*
 OUI:002672*
  ID_OUI_FROM_DATABASE=AAMP of America
 
-OUI:00266C*
- ID_OUI_FROM_DATABASE=Inventec
-
 OUI:00266B*
  ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED
 
@@ -49661,9 +51026,6 @@ OUI:002207*
 OUI:002202*
  ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB
 
-OUI:0021FD*
- ID_OUI_FROM_DATABASE=DSTA S.L.
-
 OUI:0021F9*
  ID_OUI_FROM_DATABASE=WIRECOM Technologies
 
@@ -49739,9 +51101,6 @@ OUI:001E2C*
 OUI:001E20*
  ID_OUI_FROM_DATABASE=Intertain Inc.
 
-OUI:001E25*
- ID_OUI_FROM_DATABASE=Intek Digital Inc
-
 OUI:001E19*
  ID_OUI_FROM_DATABASE=GTRI
 
@@ -50489,9 +51848,6 @@ OUI:001990*
 OUI:001989*
  ID_OUI_FROM_DATABASE=Sonitrol Corporation
 
-OUI:001A45*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
 OUI:001A3E*
  ID_OUI_FROM_DATABASE=Faster Technology LLC
 
@@ -50735,9 +52091,6 @@ OUI:00186B*
 OUI:001870*
  ID_OUI_FROM_DATABASE=E28 Shanghai Limited
 
-OUI:00185C*
- ID_OUI_FROM_DATABASE=EDS Lab Pte Ltd
-
 OUI:001863*
  ID_OUI_FROM_DATABASE=Veritech Electronics Limited
 
@@ -50924,9 +52277,6 @@ OUI:00169B*
 OUI:0016A2*
  ID_OUI_FROM_DATABASE=CentraLite Systems, Inc.
 
-OUI:00168F*
- ID_OUI_FROM_DATABASE=GN Netcom as
-
 OUI:001696*
  ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited
 
@@ -51611,9 +52961,6 @@ OUI:001160*
 OUI:001154*
  ID_OUI_FROM_DATABASE=Webpro Technologies Inc.
 
-OUI:00115B*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
 OUI:00114B*
  ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH
 
@@ -52172,9 +53519,6 @@ OUI:000E3A*
 OUI:000E2D*
  ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd.
 
-OUI:000E2E*
- ID_OUI_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD.
-
 OUI:000CEA*
  ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme
 
@@ -52238,9 +53582,6 @@ OUI:000C5C*
 OUI:000C61*
  ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital
 
-OUI:000C49*
- ID_OUI_FROM_DATABASE=Dangaard Telecom RTC Division A/S
-
 OUI:000CBA*
  ID_OUI_FROM_DATABASE=Jamex, Inc.
 
@@ -52880,9 +54221,6 @@ OUI:0008AC*
 OUI:0008A5*
  ID_OUI_FROM_DATABASE=Peninsula Systems Inc.
 
-OUI:00089F*
- ID_OUI_FROM_DATABASE=EFM Networks
-
 OUI:000899*
  ID_OUI_FROM_DATABASE=Netbind, Inc.
 
@@ -52937,18 +54275,12 @@ OUI:0008B8*
 OUI:00079B*
  ID_OUI_FROM_DATABASE=Aurora Networks
 
-OUI:000795*
- ID_OUI_FROM_DATABASE=Elitegroup Computer System Co. (ECS)
-
 OUI:00078F*
  ID_OUI_FROM_DATABASE=Emkay Innovative Products
 
 OUI:000788*
  ID_OUI_FROM_DATABASE=Clipcomm, Inc.
 
-OUI:000782*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:000779*
  ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd.
 
@@ -53843,9 +55175,6 @@ OUI:00016B*
 OUI:000167*
  ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION
 
-OUI:00020E*
- ID_OUI_FROM_DATABASE=ECI Telecom, Ltd
-
 OUI:000215*
  ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B
 
@@ -54551,9 +55880,6 @@ OUI:00106F*
 OUI:0010C6*
  ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
 
-OUI:00104F*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:0010DA*
  ID_OUI_FROM_DATABASE=Kollmorgen Corp
 
@@ -54722,9 +56048,6 @@ OUI:0060B5*
 OUI:006027*
  ID_OUI_FROM_DATABASE=Superior Modular Products
 
-OUI:0060DC*
- ID_OUI_FROM_DATABASE=Toyo Network Systems  & System Integration Co. LTD
-
 OUI:0060C1*
  ID_OUI_FROM_DATABASE=WaveSpan Corporation
 
@@ -55058,9 +56381,6 @@ OUI:00A0FA*
 OUI:00A014*
  ID_OUI_FROM_DATABASE=CSIR
 
-OUI:00A045*
- ID_OUI_FROM_DATABASE=PHOENIX CONTACT GMBH & CO.
-
 OUI:00A064*
  ID_OUI_FROM_DATABASE=KVB/ANALECT
 
@@ -55427,9 +56747,6 @@ OUI:00C02C*
 OUI:00C0ED*
  ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC
 
-OUI:00C0F0*
- ID_OUI_FROM_DATABASE=KINGSTON TECHNOLOGY CORP.
-
 OUI:00C0D1*
  ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION
 
@@ -55886,9 +57203,6 @@ OUI:00006F*
 OUI:00005A*
  ID_OUI_FROM_DATABASE=SysKonnect GmbH
 
-OUI:0000C9*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
 OUI:000023*
  ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB
 
@@ -56231,12 +57545,6 @@ OUI:70F1A1*
 OUI:6CFAA7*
  ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
 
-OUI:0015C1*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
-OUI:0019C5*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
 OUI:0024EF*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -56246,9 +57554,6 @@ OUI:6C0E0D*
 OUI:B4527D*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:280DFC*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
 OUI:E063E5*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -56459,54 +57764,9 @@ OUI:000DB6*
 OUI:18C086*
  ID_OUI_FROM_DATABASE=Broadcom
 
-OUI:80ACAC*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:003146*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:000585*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:F01C2D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:5C4527*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:44F477*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:CCE17F*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:3C6104*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:C03E0F*
  ID_OUI_FROM_DATABASE=BSkyB Ltd
 
-OUI:54E032*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:78FE3D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:F8C001*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:50C58D*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0024DC*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:001F12*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:0019E2*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:0020D4*
  ID_OUI_FROM_DATABASE=Cabletron Systems, Inc.
 
@@ -56684,9 +57944,6 @@ OUI:14C126*
 OUI:4C2578*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:001EA4*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-
 OUI:001262*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
@@ -56696,21 +57953,375 @@ OUI:00174B*
 OUI:002547*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
-OUI:001DE9*
- ID_OUI_FROM_DATABASE=Nokia Danmark A/S
-
 OUI:001D3B*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
 OUI:0014A7*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
+OUI:001EA4*
+ ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+
 OUI:001CD6*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
+OUI:001DE9*
+ ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+
 OUI:D099D5*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent
 
+OUI:DC0077*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:0060DC*
+ ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd.
+
+OUI:9CAED3*
+ ID_OUI_FROM_DATABASE=Seiko Epson Corporation
+
+OUI:F45C89*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:A41588*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:8C3C4A*
+ ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC
+
+OUI:0021FD*
+ ID_OUI_FROM_DATABASE=LACROIX TRAFFIC S.A.U
+
+OUI:4CB44A*
+ ID_OUI_FROM_DATABASE=NANOWAVE Technologies Inc.
+
+OUI:78C3E9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:9C5C8E*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
+OUI:102AB3*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:70884D*
+ ID_OUI_FROM_DATABASE=JAPAN RADIO CO., LTD.
+
+OUI:4C55CC*
+ ID_OUI_FROM_DATABASE=Zentri Pty Ltd
+
+OUI:BCEC5D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:DC415F*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:30636B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:280DFC*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:84683E*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+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
+
+OUI:702526*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:903AA0*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:E0CDFD*
+ ID_OUI_FROM_DATABASE=Beijing E3Control Technology Co, LTD
+
+OUI:BC52B4*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:08BE77*
+ ID_OUI_FROM_DATABASE=Green Electronics
+
+OUI:208B37*
+ ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
+
+OUI:280C28*
+ ID_OUI_FROM_DATABASE=Unigen DataStorage Corporation
+
+OUI:980CA5*
+ ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+
+OUI:1CC035*
+ ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC.
+
+OUI:34543C*
+ ID_OUI_FROM_DATABASE=TAKAOKA TOKO CO.,LTD.
+
+OUI:D49524*
+ ID_OUI_FROM_DATABASE=Clover Network, Inc.
+
+OUI:0034DA*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
+OUI:9046A2*
+ ID_OUI_FROM_DATABASE=Tedipay UK Ltd
+
+OUI:6479A7*
+ ID_OUI_FROM_DATABASE=Phison Electronics Corp.
+
+OUI:0019C5*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:0015C1*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:C83870*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:288335*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:44783E*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:202D07*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:FC2FAA*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:D4612E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:1C6758*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:0452C7*
+ ID_OUI_FROM_DATABASE=Bose Corporation
+
+OUI:E85659*
+ ID_OUI_FROM_DATABASE=Advanced-Connectek Inc.
+
+OUI:34E70B*
+ ID_OUI_FROM_DATABASE=Beijing HAN Networks Co., Ltd
+
+OUI:8801F2*
+ ID_OUI_FROM_DATABASE=Vitec System Engineering Inc.
+
+OUI:FC084A*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+
+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.
+
+OUI:D4AD2D*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:48555F*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:04A316*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:98072D*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:A082AC*
+ ID_OUI_FROM_DATABASE=Linear DMS Solutions Sdn. Bhd.
+
+OUI:705A9E*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:002697*
+ ID_OUI_FROM_DATABASE=Alpha  Technologies Inc.
+
+OUI:4CB8B5*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
+OUI:1CABC0*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+
+OUI:84E323*
+ ID_OUI_FROM_DATABASE=Green Wave Telecommunication SDN BHD
+
+OUI:7071BC*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:44650D*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:E06995*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:D897BA*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:54D9E4*
+ ID_OUI_FROM_DATABASE=BRILLIANTTS CO., LTD
+
+OUI:E4F3F5*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+
+OUI:00185C*
+ ID_OUI_FROM_DATABASE=EDSLAB Technologies
+
+OUI:000E2E*
+ ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd.
+
+OUI:00020E*
+ ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
+
+OUI:0000C9*
+ ID_OUI_FROM_DATABASE=Emulex Corporation
+
+OUI:00115B*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:000795*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:B8AEED*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:C03FD5*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:7427EA*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:00089F*
+ ID_OUI_FROM_DATABASE=EFM Networks
+
+OUI:042AE2*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:001A45*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:00168F*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:00104F*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:000782*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:083FBC*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:903809*
+ ID_OUI_FROM_DATABASE=Ericsson AB
+
+OUI:1C1B0D*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
+OUI:E42F56*
+ ID_OUI_FROM_DATABASE=OptoMET GmbH
+
+OUI:00A045*
+ ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH
+
+OUI:00266C*
+ ID_OUI_FROM_DATABASE=INVENTEC Corporation
+
+OUI:001E25*
+ ID_OUI_FROM_DATABASE=INTEK DIGITAL
+
+OUI:A0B662*
+ ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd.
+
+OUI:00C0F0*
+ ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc.
+
+OUI:4C8FA5*
+ ID_OUI_FROM_DATABASE=Jastec
+
+OUI:000C49*
+ ID_OUI_FROM_DATABASE=Dangaard Telecom Denmark A/S
+
+OUI:CCE17F*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:44F477*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:5C4527*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:F01C2D*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:F8C001*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:78FE3D*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:54E032*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:3C6104*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0019E2*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:001F12*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:0024DC*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:50C58D*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:000585*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:003146*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:80ACAC*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:BC7574*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:20A680*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:50DD4F*
+ ID_OUI_FROM_DATABASE=Automation Components, Inc
+
+OUI:904D4A*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:7C79E8*
+ ID_OUI_FROM_DATABASE=PayRange Inc.
+
 OUI:2C3996*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
@@ -57812,9 +59423,6 @@ OUI:98E848*
 OUI:A0F9E0*
  ID_OUI_FROM_DATABASE=VIVATEL COMPANY LIMITED
 
-OUI:0C54B9*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:F8C372*
  ID_OUI_FROM_DATABASE=TSUZUKI DENKI
 
@@ -58118,9 +59726,6 @@ OUI:3C8375*
 OUI:C8458F*
  ID_OUI_FROM_DATABASE=Wyler AG
 
-OUI:74852A*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:149A10*
  ID_OUI_FROM_DATABASE=Microsoft Corporation
 
@@ -58592,9 +60197,6 @@ OUI:E4F4C6*
 OUI:DC663A*
  ID_OUI_FROM_DATABASE=Apacer Technology Inc.
 
-OUI:FCF152*
- ID_OUI_FROM_DATABASE=Sony Corporation
-
 OUI:B009D3*
  ID_OUI_FROM_DATABASE=Avizia
 
@@ -58640,9 +60242,6 @@ OUI:D896E0*
 OUI:300D2A*
  ID_OUI_FROM_DATABASE=Zhejiang Wellcom Technology Co.,Ltd.
 
-OUI:C4084A*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:8496D8*
  ID_OUI_FROM_DATABASE=Pace plc
 
@@ -58688,9 +60287,6 @@ OUI:345D10*
 OUI:58E326*
  ID_OUI_FROM_DATABASE=Compass Technologies Inc.
 
-OUI:F08CFB*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
-
 OUI:848DC7*
  ID_OUI_FROM_DATABASE=Cisco SPVTG
 
@@ -58820,9 +60416,6 @@ OUI:E0DB88*
 OUI:D86194*
  ID_OUI_FROM_DATABASE=Objetivos y Sevicios de Valor Añadido
 
-OUI:FCF8B7*
- ID_OUI_FROM_DATABASE=TRONTEQ Electronic
-
 OUI:589CFC*
  ID_OUI_FROM_DATABASE=FreeBSD Foundation
 
@@ -58832,9 +60425,6 @@ OUI:602103*
 OUI:085DDD*
  ID_OUI_FROM_DATABASE=Mercury Corporation
 
-OUI:88B1E1*
- ID_OUI_FROM_DATABASE=AirTight Networks, Inc.
-
 OUI:98349D*
  ID_OUI_FROM_DATABASE=Krauss Maffei Technologies GmbH
 
@@ -58922,9 +60512,6 @@ OUI:9486D4*
 OUI:F89550*
  ID_OUI_FROM_DATABASE=Proton Products Chengdu Ltd
 
-OUI:943BB1*
- ID_OUI_FROM_DATABASE=KAONMEDIA
-
 OUI:447BC4*
  ID_OUI_FROM_DATABASE=DualShine Technology(SZ)Co.,Ltd
 
@@ -59618,9 +61205,6 @@ OUI:5809E5*
 OUI:74ECF1*
  ID_OUI_FROM_DATABASE=Acumen
 
-OUI:649968*
- ID_OUI_FROM_DATABASE=Elentec
-
 OUI:6815D3*
  ID_OUI_FROM_DATABASE=Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A.
 
@@ -60161,9 +61745,6 @@ OUI:F4044C*
 OUI:1CBBA8*
  ID_OUI_FROM_DATABASE=OJSC Ufimskiy Zavod Promsvyaz
 
-OUI:34AA99*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:506028*
  ID_OUI_FROM_DATABASE=Xirrus Inc.
 
@@ -60212,9 +61793,6 @@ OUI:10F96F*
 OUI:B01C91*
  ID_OUI_FROM_DATABASE=Elim Co
 
-OUI:ECA86B*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEMS CO., LTD.
-
 OUI:0CA2F4*
  ID_OUI_FROM_DATABASE=Chameleon Technology (UK) Limited
 
@@ -60458,15 +62036,9 @@ OUI:4C0289*
 OUI:C0E54E*
  ID_OUI_FROM_DATABASE=DENX Computer Systems GmbH
 
-OUI:386077*
- ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
-
 OUI:E435FB*
  ID_OUI_FROM_DATABASE=Sabre Technology (Hull) Ltd
 
-OUI:146308*
- ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD.
-
 OUI:28BE9B*
  ID_OUI_FROM_DATABASE=Technicolor USA Inc.
 
@@ -60497,9 +62069,6 @@ OUI:68F125*
 OUI:706F81*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:9CDF03*
- ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
-
 OUI:30E4DB*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -61394,9 +62963,6 @@ OUI:94592D*
 OUI:9CC077*
  ID_OUI_FROM_DATABASE=PrintCounts, LLC
 
-OUI:4487FC*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
-
 OUI:A85BB0*
  ID_OUI_FROM_DATABASE=Shenzhen Dehoo Technology Co.,Ltd
 
@@ -61814,9 +63380,6 @@ OUI:0026FE*
 OUI:0026F8*
  ID_OUI_FROM_DATABASE=Golden Highway Industry Development Co., Ltd.
 
-OUI:0026F7*
- ID_OUI_FROM_DATABASE=Infosys Technologies Ltd.
-
 OUI:0026F1*
  ID_OUI_FROM_DATABASE=ProCurve Networking by HP
 
@@ -62306,9 +63869,6 @@ OUI:00237A*
 OUI:002377*
  ID_OUI_FROM_DATABASE=Isotek Electronics Ltd
 
-OUI:002378*
- ID_OUI_FROM_DATABASE=GN Netcom A/S
-
 OUI:002371*
  ID_OUI_FROM_DATABASE=SOAM Systel
 
@@ -62396,9 +63956,6 @@ OUI:0021A5*
 OUI:00219F*
  ID_OUI_FROM_DATABASE=SATEL OY
 
-OUI:002197*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM
-
 OUI:00218A*
  ID_OUI_FROM_DATABASE=Electronic Design and Manufacturing Company
 
@@ -62978,9 +64535,6 @@ OUI:001BFF*
 OUI:001BFA*
  ID_OUI_FROM_DATABASE=G.i.N. mbH
 
-OUI:001BF3*
- ID_OUI_FROM_DATABASE=TRANSRADIO SenderSysteme Berlin AG
-
 OUI:001BE3*
  ID_OUI_FROM_DATABASE=Health Hero Network, Inc.
 
@@ -63758,9 +65312,6 @@ OUI:0015FB*
 OUI:0015F6*
  ID_OUI_FROM_DATABASE=SCIENCE AND ENGINEERING SERVICES, INC.
 
-OUI:00177D*
- ID_OUI_FROM_DATABASE=IDT International Limited
-
 OUI:001782*
  ID_OUI_FROM_DATABASE=LoBenn Inc.
 
@@ -65366,9 +66917,6 @@ OUI:000B2D*
 OUI:000ABB*
  ID_OUI_FROM_DATABASE=Taiwan Secom Co,. Ltd
 
-OUI:000AC2*
- ID_OUI_FROM_DATABASE=FiberHome Telecommunication Technologies CO.,LTD
-
 OUI:000AC7*
  ID_OUI_FROM_DATABASE=Unication Group
 
@@ -65996,9 +67544,6 @@ OUI:0005AB*
 OUI:000588*
  ID_OUI_FROM_DATABASE=Sensoria Corp.
 
-OUI:000594*
- ID_OUI_FROM_DATABASE=HMS Technology Center Ravensburg GmbH
-
 OUI:00058E*
  ID_OUI_FROM_DATABASE=Flextronics International GmbH & Co. Nfg. KG
 
@@ -66602,9 +68147,6 @@ OUI:000168*
 OUI:000174*
  ID_OUI_FROM_DATABASE=CyberOptics Corporation
 
-OUI:00015D*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:000164*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -66968,9 +68510,6 @@ OUI:00D012*
 OUI:00D092*
  ID_OUI_FROM_DATABASE=GLENAYRE WESTERN MULTIPLEX
 
-OUI:00D0EC*
- ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS, INC
-
 OUI:00D0C5*
  ID_OUI_FROM_DATABASE=COMPUTATIONAL SYSTEMS, INC.
 
@@ -67100,9 +68639,6 @@ OUI:009019*
 OUI:0090DC*
  ID_OUI_FROM_DATABASE=TECO INFORMATION SYSTEMS
 
-OUI:00D0A2*
- ID_OUI_FROM_DATABASE=INTEGRATED DEVICE
-
 OUI:00D0AE*
  ID_OUI_FROM_DATABASE=ORESIS COMMUNICATIONS, INC.
 
@@ -67196,9 +68732,6 @@ OUI:00900A*
 OUI:00904E*
  ID_OUI_FROM_DATABASE=DELEM BV
 
-OUI:009050*
- ID_OUI_FROM_DATABASE=TELESTE OY
-
 OUI:00904A*
  ID_OUI_FROM_DATABASE=CONCUR SYSTEM TECHNOLOGIES
 
@@ -67406,9 +68939,6 @@ OUI:009020*
 OUI:009065*
  ID_OUI_FROM_DATABASE=FINISAR CORPORATION
 
-OUI:001035*
- ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEMS CO., LTD
-
 OUI:001053*
  ID_OUI_FROM_DATABASE=COMPUTER TECHNOLOGY CORP.
 
@@ -67508,9 +69038,6 @@ OUI:001008*
 OUI:0010CC*
  ID_OUI_FROM_DATABASE=CLP COMPUTER LOGISTIK PLANUNG GmbH
 
-OUI:00109B*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
 OUI:001094*
  ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc
 
@@ -67715,9 +69242,6 @@ OUI:0060AF*
 OUI:00601F*
  ID_OUI_FROM_DATABASE=STALLION TECHNOLOGIES
 
-OUI:0060B1*
- ID_OUI_FROM_DATABASE=INPUT/OUTPUT, INC.
-
 OUI:00608F*
  ID_OUI_FROM_DATABASE=TEKRAM TECHNOLOGY CO., LTD.
 
@@ -67811,9 +69335,6 @@ OUI:00E011*
 OUI:00E021*
  ID_OUI_FROM_DATABASE=FREEGATE CORP.
 
-OUI:00E0D5*
- ID_OUI_FROM_DATABASE=Emulex Corporation
-
 OUI:00E0AB*
  ID_OUI_FROM_DATABASE=DIMAT S.A.
 
@@ -67937,9 +69458,6 @@ OUI:0020A7*
 OUI:0020DA*
  ID_OUI_FROM_DATABASE=Alcatel North America ESD
 
-OUI:0020F2*
- ID_OUI_FROM_DATABASE=Oracle Corporation
-
 OUI:002005*
  ID_OUI_FROM_DATABASE=SIMPLE TECHNOLOGY
 
@@ -68057,9 +69575,6 @@ OUI:0020A2*
 OUI:002098*
  ID_OUI_FROM_DATABASE=HECTRONIC AB
 
-OUI:00208F*
- ID_OUI_FROM_DATABASE=ECI TELECOM LTD.
-
 OUI:002065*
  ID_OUI_FROM_DATABASE=SUPERNET NETWORKING INC.
 
@@ -68087,9 +69602,6 @@ OUI:0020E8*
 OUI:00204F*
  ID_OUI_FROM_DATABASE=DEUTSCHE AEROSPACE AG
 
-OUI:002088*
- ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION
-
 OUI:00202E*
  ID_OUI_FROM_DATABASE=DAYSTAR DIGITAL
 
@@ -68567,9 +70079,6 @@ OUI:008059*
 OUI:00806B*
  ID_OUI_FROM_DATABASE=SCHMID TELECOMMUNICATION
 
-OUI:0080B8*
- ID_OUI_FROM_DATABASE=B.U.G. MORISEIKI, INCORPORATED
-
 OUI:00802C*
  ID_OUI_FROM_DATABASE=THE SAGE GROUP PLC
 
@@ -68795,9 +70304,6 @@ OUI:080042*
 OUI:026086*
  ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD.
 
-OUI:08000D*
- ID_OUI_FROM_DATABASE=INTERNATIONAL COMPUTERS LTD.
-
 OUI:00DD05*
  ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
 
@@ -69149,9 +70655,6 @@ OUI:ACD074*
 OUI:D05349*
  ID_OUI_FROM_DATABASE=Liteon Technology Corporation
 
-OUI:0025DC*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
 OUI:00BB3A*
  ID_OUI_FROM_DATABASE=Private
 
@@ -69167,9 +70670,6 @@ OUI:00014A*
 OUI:001CA4*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:00248D*
- ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
-
 OUI:002345*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -69350,54 +70850,18 @@ OUI:001BA9*
 OUI:0011B6*
  ID_OUI_FROM_DATABASE=Open Systems International
 
-OUI:002283*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:2C6BF5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:64649B*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:541E56*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:E03E44*
  ID_OUI_FROM_DATABASE=Broadcom
 
 OUI:D40129*
  ID_OUI_FROM_DATABASE=Broadcom
 
-OUI:544B8C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:84B59C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:100E7E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:288A1C*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:FCB698*
  ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
 
-OUI:3C94D5*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:B0A86E*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
-OUI:AC4BC8*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:00E03A*
  ID_OUI_FROM_DATABASE=Cabletron Systems, Inc.
 
-OUI:002159*
- ID_OUI_FROM_DATABASE=Juniper Networks
-
 OUI:000117*
  ID_OUI_FROM_DATABASE=Canal +
 
@@ -69605,9 +71069,6 @@ OUI:00BD3A*
 OUI:A04E04*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:001CFC*
- ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
-
 OUI:001370*
  ID_OUI_FROM_DATABASE=Nokia Danmark A/S
 
@@ -69646,3 +71107,339 @@ OUI:0026CC*
 
 OUI:240B0A*
  ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:C4E510*
+ ID_OUI_FROM_DATABASE=Mechatro, Inc.
+
+OUI:74C330*
+ ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+
+OUI:403F8C*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:14C3C2*
+ ID_OUI_FROM_DATABASE=K.A. Schmersal GmbH & Co. KG
+
+OUI:10785B*
+ ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+
+OUI:20768F*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:C0C522*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:9C5CF9*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
+OUI:88A084*
+ ID_OUI_FROM_DATABASE=Formation Data Systems
+
+OUI:0025DC*
+ ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
+
+OUI:001CFC*
+ ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
+
+OUI:00D0EC*
+ ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC
+
+OUI:8CC661*
+ ID_OUI_FROM_DATABASE=Current, powered by GE
+
+OUI:009050*
+ ID_OUI_FROM_DATABASE=Teleste Corporation
+
+OUI:BC44B0*
+ ID_OUI_FROM_DATABASE=Elastifile
+
+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.
+
+OUI:80ED2C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:E8B2AC*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:FCF152*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:0080B8*
+ ID_OUI_FROM_DATABASE=DMG MORI B.U.G. CO., LTD.
+
+OUI:8489AD*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:40B688*
+ ID_OUI_FROM_DATABASE=LEGIC Identsystems AG
+
+OUI:A09D91*
+ ID_OUI_FROM_DATABASE=SoundBridge
+
+OUI:30785C*
+ ID_OUI_FROM_DATABASE=Partow Tamas Novin (Parman)
+
+OUI:0C54B9*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:C4084A*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:34AA99*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:441102*
+ ID_OUI_FROM_DATABASE=EDMI  Europe Ltd
+
+OUI:2C21D7*
+ ID_OUI_FROM_DATABASE=IMAX Corporation
+
+OUI:0026F7*
+ ID_OUI_FROM_DATABASE=Nivetti Systems Pvt. Ltd.
+
+OUI:24C3F9*
+ ID_OUI_FROM_DATABASE=Securitas Direct AB
+
+OUI:DC4D23*
+ ID_OUI_FROM_DATABASE=MRV Comunications
+
+OUI:085BDA*
+ ID_OUI_FROM_DATABASE=CliniCare LTD
+
+OUI:00248D*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
+OUI:0C5A9E*
+ ID_OUI_FROM_DATABASE=Wi-SUN Alliance
+
+OUI:00C164*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:10D0AB*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:C4BED4*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
+OUI:98E7F5*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:24BCF8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:042DB4*
+ ID_OUI_FROM_DATABASE=First Property (Beijing) Co., Ltd Modern MOMA Branch
+
+OUI:202DF8*
+ ID_OUI_FROM_DATABASE=Digital Media Cartridge Ltd.
+
+OUI:008A96*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:007888*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:98DED0*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:30FC68*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:5CCA1A*
+ ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
+
+OUI:000594*
+ ID_OUI_FROM_DATABASE=HMS Industrial Networks
+
+OUI:000AC2*
+ ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd.
+
+OUI:F08CFB*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:FCF8B7*
+ ID_OUI_FROM_DATABASE=TRONTEQ Electronic
+
+OUI:D4F207*
+ ID_OUI_FROM_DATABASE=DIAODIAO(Beijing)Technology CO.,Ltd
+
+OUI:D4883F*
+ ID_OUI_FROM_DATABASE=HDPRO CO., LTD.
+
+OUI:FC0F4B*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:A86AC1*
+ ID_OUI_FROM_DATABASE=HanbitEDS Co., Ltd.
+
+OUI:40163B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:001BF3*
+ ID_OUI_FROM_DATABASE=TRANSRADIO SenderSysteme Berlin AG
+
+OUI:E0071B*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:88B1E1*
+ ID_OUI_FROM_DATABASE=Mojo Networks, Inc.
+
+OUI:74DFBF*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:FC3F7C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:608334*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:84AD58*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:746FF7*
+ ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
+
+OUI:B01BD2*
+ ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited
+
+OUI:386077*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:74852A*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:60B4F7*
+ ID_OUI_FROM_DATABASE=Plume Design Inc
+
+OUI:A4D8CA*
+ ID_OUI_FROM_DATABASE=HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED
+
+OUI:ECA86B*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:4487FC*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:002197*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:649968*
+ ID_OUI_FROM_DATABASE=Elentec
+
+OUI:00109B*
+ ID_OUI_FROM_DATABASE=Emulex Corporation
+
+OUI:00E0D5*
+ ID_OUI_FROM_DATABASE=Emulex Corporation
+
+OUI:001035*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+
+OUI:9CDF03*
+ ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
+
+OUI:00208F*
+ ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
+
+OUI:F0407B*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:94885E*
+ ID_OUI_FROM_DATABASE=Surfilter Network Technology Co., Ltd.
+
+OUI:002378*
+ ID_OUI_FROM_DATABASE=GN Netcom A/S
+
+OUI:002088*
+ ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION
+
+OUI:BC6A44*
+ ID_OUI_FROM_DATABASE=Commend International GmbH
+
+OUI:90C7D8*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:F8DA0C*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:0020F2*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:00015D*
+ ID_OUI_FROM_DATABASE=Oracle Corporation
+
+OUI:943BB1*
+ ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+
+OUI:146308*
+ ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD.
+
+OUI:08000D*
+ ID_OUI_FROM_DATABASE=International Computers, Ltd
+
+OUI:00D0A2*
+ ID_OUI_FROM_DATABASE=INTEGRATED DEVICE
+
+OUI:0060B1*
+ ID_OUI_FROM_DATABASE=Input/Output, Inc.
+
+OUI:00177D*
+ ID_OUI_FROM_DATABASE=IDT Technology Limited
+
+OUI:AC4BC8*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:B0A86E*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:3C94D5*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:288A1C*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:100E7E*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:84B59C*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:544B8C*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:541E56*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:64649B*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:2C6BF5*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:002283*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:F4CC55*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:EC13DB*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:002159*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:5C70A3*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
+OUI:3497F6*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
+OUI:50680A*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
index a825e744e10fb09e1c8bcb0de797d0754f84847c..516abad246ab07ad3332b1be4ff1108a95cb9f5e 100644 (file)
@@ -1654,7 +1654,7 @@ bluetooth:v0224*
  ID_VENDOR_FROM_DATABASE=Comarch SA
 
 bluetooth:v0225*
- ID_VENDOR_FROM_DATABASE=Nestl Nespresso S.A.
+ ID_VENDOR_FROM_DATABASE=Nestlé Nespresso S.A.
 
 bluetooth:v0226*
  ID_VENDOR_FROM_DATABASE=Merlinia A/S
@@ -1780,7 +1780,7 @@ bluetooth:v024E*
  ID_VENDOR_FROM_DATABASE=Microtronics Engineering GmbH
 
 bluetooth:v024F*
- ID_VENDOR_FROM_DATABASE=Schneider Schreibgerte GmbH
+ ID_VENDOR_FROM_DATABASE=Schneider Schreibgeräte GmbH
 
 bluetooth:v0250*
  ID_VENDOR_FROM_DATABASE=Sapphire Circuits LLC
@@ -1897,7 +1897,7 @@ bluetooth:v0275*
  ID_VENDOR_FROM_DATABASE=Geotab
 
 bluetooth:v0276*
- ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gertebau GmbH
+ ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gerätebau GmbH
 
 bluetooth:v0277*
  ID_VENDOR_FROM_DATABASE=bewhere inc
@@ -2066,3 +2066,168 @@ bluetooth:v02AD*
 
 bluetooth:v02AE*
  ID_VENDOR_FROM_DATABASE=WeatherFlow, Inc.
+
+bluetooth:v02AF*
+ ID_VENDOR_FROM_DATABASE=Technicolor USA Inc.
+
+bluetooth:v02B0*
+ ID_VENDOR_FROM_DATABASE=Bestechnic(Shanghai),Ltd
+
+bluetooth:v02B1*
+ ID_VENDOR_FROM_DATABASE=Raden Inc
+
+bluetooth:v02B2*
+ ID_VENDOR_FROM_DATABASE=JouZen Oy
+
+bluetooth:v02B3*
+ ID_VENDOR_FROM_DATABASE=CLABER S.P.A.
+
+bluetooth:v02B4*
+ ID_VENDOR_FROM_DATABASE=Hyginex, Inc.
+
+bluetooth:v02B5*
+ ID_VENDOR_FROM_DATABASE=HANSHIN ELECTRIC RAILWAY CO.,LTD.
+
+bluetooth:v02B6*
+ ID_VENDOR_FROM_DATABASE=Schneider Electric
+
+bluetooth:v02B7*
+ ID_VENDOR_FROM_DATABASE=Oort Technologies LLC
+
+bluetooth:v02B8*
+ ID_VENDOR_FROM_DATABASE=Chrono Therapeutics
+
+bluetooth:v02B9*
+ ID_VENDOR_FROM_DATABASE=Rinnai Corporation
+
+bluetooth:v02BA*
+ ID_VENDOR_FROM_DATABASE=Swissprime Technologies AG
+
+bluetooth:v02BB*
+ ID_VENDOR_FROM_DATABASE=Koha.,Co.Ltd
+
+bluetooth:v02BC*
+ ID_VENDOR_FROM_DATABASE=Genevac Ltd
+
+bluetooth:v02BD*
+ ID_VENDOR_FROM_DATABASE=Chemtronics
+
+bluetooth:v02BE*
+ ID_VENDOR_FROM_DATABASE=Seguro Technology Sp. z o.o.
+
+bluetooth:v02BF*
+ ID_VENDOR_FROM_DATABASE=Redbird Flight Simulations
+
+bluetooth:v02C0*
+ ID_VENDOR_FROM_DATABASE=Dash Robotics
+
+bluetooth:v02C1*
+ ID_VENDOR_FROM_DATABASE=LINE Corporation
+
+bluetooth:v02C2*
+ ID_VENDOR_FROM_DATABASE=Guillemot Corporation
+
+bluetooth:v02C3*
+ ID_VENDOR_FROM_DATABASE=Techtronic Power Tools Technology Limited
+
+bluetooth:v02C4*
+ ID_VENDOR_FROM_DATABASE=Wilson Sporting Goods
+
+bluetooth:v02C5*
+ ID_VENDOR_FROM_DATABASE=Lenovo (Singapore) Pte Ltd. ( 联想(新加坡) )
+
+bluetooth:v02C6*
+ ID_VENDOR_FROM_DATABASE=Ayatan Sensors
+
+bluetooth:v02C7*
+ ID_VENDOR_FROM_DATABASE=Electronics Tomorrow Limited
+
+bluetooth:v02C8*
+ ID_VENDOR_FROM_DATABASE=VASCO Data Security International, Inc.
+
+bluetooth:v02C9*
+ ID_VENDOR_FROM_DATABASE=PayRange Inc.
+
+bluetooth:v02CA*
+ ID_VENDOR_FROM_DATABASE=ABOV Semiconductor
+
+bluetooth:v02CB*
+ ID_VENDOR_FROM_DATABASE=AINA-Wireless Inc.
+
+bluetooth:v02CC*
+ ID_VENDOR_FROM_DATABASE=Eijkelkamp Soil & Water
+
+bluetooth:v02CD*
+ ID_VENDOR_FROM_DATABASE=BMA ergonomics b.v.
+
+bluetooth:v02CE*
+ ID_VENDOR_FROM_DATABASE=Teva Branded Pharmaceutical Products R&D, Inc.
+
+bluetooth:v02CF*
+ ID_VENDOR_FROM_DATABASE=Anima
+
+bluetooth:v02D0*
+ ID_VENDOR_FROM_DATABASE=3M
+
+bluetooth:v02D1*
+ ID_VENDOR_FROM_DATABASE=Empatica Srl
+
+bluetooth:v02D2*
+ ID_VENDOR_FROM_DATABASE=Afero, Inc.
+
+bluetooth:v02D3*
+ ID_VENDOR_FROM_DATABASE=Powercast Corporation
+
+bluetooth:v02D4*
+ ID_VENDOR_FROM_DATABASE=Secuyou ApS
+
+bluetooth:v02D5*
+ ID_VENDOR_FROM_DATABASE=OMRON Corporation
+
+bluetooth:v02D6*
+ ID_VENDOR_FROM_DATABASE=Send Solutions
+
+bluetooth:v02D7*
+ ID_VENDOR_FROM_DATABASE=NIPPON SYSTEMWARE CO.,LTD.
+
+bluetooth:v02D8*
+ ID_VENDOR_FROM_DATABASE=Neosfar
+
+bluetooth:v02D9*
+ ID_VENDOR_FROM_DATABASE=Fliegl Agrartechnik GmbH
+
+bluetooth:v02DA*
+ ID_VENDOR_FROM_DATABASE=Gilvader
+
+bluetooth:v02DB*
+ ID_VENDOR_FROM_DATABASE=Digi International Inc (R)
+
+bluetooth:v02DC*
+ ID_VENDOR_FROM_DATABASE=DeWalch Technologies, Inc.
+
+bluetooth:v02DD*
+ ID_VENDOR_FROM_DATABASE=Flint Rehabilitation Devices, LLC
+
+bluetooth:v02DE*
+ ID_VENDOR_FROM_DATABASE=Samsung SDS Co., Ltd.
+
+bluetooth:v02DF*
+ ID_VENDOR_FROM_DATABASE=Blur Product Development
+
+bluetooth:v02E0*
+ ID_VENDOR_FROM_DATABASE=University of Michigan
+
+bluetooth:v02E1*
+ ID_VENDOR_FROM_DATABASE=Victron Energy BV
+
+bluetooth:v02E2*
+ ID_VENDOR_FROM_DATABASE=NTT docomo
+
+bluetooth:v02E3*
+ ID_VENDOR_FROM_DATABASE=Carmanah Technologies Corp.
+
+bluetooth:v02E4*
+ ID_VENDOR_FROM_DATABASE=Bytestorm Ltd.
+
+bluetooth:v02E5*
+ ID_VENDOR_FROM_DATABASE=Espressif Incorporated ( 乐鑫信息科技(上海)有限公司 )
index 695409086ad3e8665b31c55235f7153793151dc8..91c784b891893e880ff2156bfec47a487b962628 100644 (file)
@@ -1016,6 +1016,9 @@ pci:v00001000d0000005Fsv00001028sd00001F4D*
 pci:v00001000d0000005Fsv00001054sd0000306A*
  ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (SAS 3004 iMR ROMB)
 
+pci:v00001000d0000005Fsv00001D49sd000004DB*
+ ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (ServeRAID M1210 SAS/SATA Controller)
+
 pci:v00001000d00000060*
  ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078
 
@@ -4496,6 +4499,24 @@ pci:v00001002d0000665Fsv00001682sd00007360*
 pci:v00001002d00006660*
  ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330]
 
+pci:v00001002d00006660sv00001028sd000005EA*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M)
+
+pci:v00001002d00006660sv00001028sd000006BF*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M335)
+
+pci:v00001002d00006660sv0000103Csd00001970*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M)
+
+pci:v00001002d00006660sv0000103Csd000080BE*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330)
+
+pci:v00001002d00006660sv0000103Csd00008136*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330)
+
+pci:v00001002d00006660sv000017AAsd00003804*
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330)
+
 pci:v00001002d00006660sv000017AAsd00003809*
  ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330)
 
@@ -8199,7 +8220,10 @@ pci:v00001002d0000692F*
  ID_MODEL_FROM_DATABASE=Tonga XTV GL [FirePro S7150V]
 
 pci:v00001002d00006938*
- ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X Mac Edition]
+ ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X Mac Edition]
+
+pci:v00001002d00006938sv0000174Bsd0000E308*
+ ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X Mac Edition] (Radeon R9 380X Nitro 4G D5)
 
 pci:v00001002d00006939*
  ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380]
@@ -8207,6 +8231,9 @@ pci:v00001002d00006939*
 pci:v00001002d00006939sv0000148Csd00009380*
  ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380)
 
+pci:v00001002d00006939sv0000174Bsd0000E308*
+ ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380 Nitro 4G D5)
+
 pci:v00001002d0000700F*
  ID_MODEL_FROM_DATABASE=RS100 AGP Bridge
 
@@ -9437,6 +9464,12 @@ pci:v00001002d00009918*
 pci:v00001002d00009919*
  ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G]
 
+pci:v00001002d00009920*
+ ID_MODEL_FROM_DATABASE=Liverpool Graphics
+
+pci:v00001002d00009921*
+ ID_MODEL_FROM_DATABASE=Liverpool HDMI/DP Audio Controller
+
 pci:v00001002d00009990*
  ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7520G]
 
@@ -9575,6 +9608,12 @@ pci:v00001002d0000AAC0*
 pci:v00001002d0000AAC8*
  ID_MODEL_FROM_DATABASE=Hawaii HDMI Audio
 
+pci:v00001002d0000AAD8*
+ ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380]
+
+pci:v00001002d0000AAD8sv0000174Bsd0000AAD8*
+ ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] (Radeon R9 285/380 HDMI Audio)
+
 pci:v00001002d0000AC00*
  ID_MODEL_FROM_DATABASE=Theater 600 Pro
 
@@ -10820,7 +10859,7 @@ pci:v00001014d0000034Asv00001014sd000004C7*
 pci:v00001014d0000034Asv00001014sd000004C8*
  ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2))
 
-pci:v00001014d0000034Asv00001014sd00000C49*
+pci:v00001014d0000034Asv00001014sd000004C9*
  ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD))
 
 pci:v00001014d0000044B*
@@ -10829,6 +10868,15 @@ pci:v00001014d0000044B*
 pci:v00001014d000004AA*
  ID_MODEL_FROM_DATABASE=Flash Adapter 90 (PCIe2 0.9TB)
 
+pci:v00001014d000004DA*
+ ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC)
+
+pci:v00001014d000004DAsv00001014sd000004FB*
+ ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x16 20GB Cache 12Gb Quad SAS RAID+ Adapter(580B))
+
+pci:v00001014d000004DAsv00001014sd000004FC*
+ ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x8 12Gb Quad SAS RAID+ Adapter(580A))
+
 pci:v00001014d00003022*
  ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter
 
@@ -11165,6 +11213,15 @@ pci:v00001022d00001423*
 pci:v00001022d00001426*
  ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Port
 
+pci:v00001022d00001436*
+ ID_MODEL_FROM_DATABASE=Liverpool Processor Root Complex
+
+pci:v00001022d00001437*
+ ID_MODEL_FROM_DATABASE=Liverpool I/O Memory Management Unit
+
+pci:v00001022d00001438*
+ ID_MODEL_FROM_DATABASE=Liverpool Processor Root Port
+
 pci:v00001022d00001439*
  ID_MODEL_FROM_DATABASE=Family 16h Processor Functions 5:1
 
@@ -15353,6 +15410,9 @@ pci:v0000104Cd0000803Bsv0000103Csd0000309F*
 pci:v0000104Cd0000803Bsv0000103Csd000030A3*
  ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (Compaq nw8440)
 
+pci:v0000104Cd0000803Bsv0000104Dsd00008212*
+ ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (VAIO VGN-N21E)
+
 pci:v0000104Cd0000803Bsv0000104Dsd0000902D*
  ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (VAIO VGN-NR120E)
 
@@ -15446,6 +15506,9 @@ pci:v0000104Cd00008400sv000016ABsd00008501*
 pci:v0000104Cd00008401*
  ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface
 
+pci:v0000104Cd00008888*
+ ID_MODEL_FROM_DATABASE=Multicore DSP+ARM KeyStone II SOC
+
 pci:v0000104Cd00009000*
  ID_MODEL_FROM_DATABASE=Wireless Interface (of unknown type)
 
@@ -15812,6 +15875,30 @@ pci:v0000104Dd0000808A*
 pci:v0000104Dd000081CE*
  ID_MODEL_FROM_DATABASE=SxS Pro memory card
 
+pci:v0000104Dd0000908F*
+ ID_MODEL_FROM_DATABASE=Aeolia ACPI
+
+pci:v0000104Dd0000909E*
+ ID_MODEL_FROM_DATABASE=Aeolia Ethernet Controller (Marvell Yukon 2 Family)
+
+pci:v0000104Dd0000909F*
+ ID_MODEL_FROM_DATABASE=Aeolia SATA AHCI Controller
+
+pci:v0000104Dd000090A0*
+ ID_MODEL_FROM_DATABASE=Aeolia SD/MMC Host Controller
+
+pci:v0000104Dd000090A1*
+ ID_MODEL_FROM_DATABASE=Aeolia PCI Express Glue and Miscellaneous Devices
+
+pci:v0000104Dd000090A2*
+ ID_MODEL_FROM_DATABASE=Aeolia DMA Controller
+
+pci:v0000104Dd000090A3*
+ ID_MODEL_FROM_DATABASE=Aeolia Memory (DDR3/SPM)
+
+pci:v0000104Dd000090A4*
+ ID_MODEL_FROM_DATABASE=Aeolia USB 3.0 xHCI Host Controller
+
 pci:v0000104E*
  ID_VENDOR_FROM_DATABASE=Oak Technology, Inc
 
@@ -17247,10 +17334,10 @@ pci:v00001077d00001664*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF)
 
 pci:v00001077d00001664sv00001077sd0000E4F1*
- ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 40GbE Adapter (SR-IOV VF))
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45462H 40GbE Adapter (SR-IOV VF))
 
 pci:v00001077d00001664sv00001077sd0000E4F2*
- ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 40GbE Adapter (SR-IOV VF))
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45461H 40GbE Adapter (SR-IOV VF))
 
 pci:v00001077d00001664sv00001077sd0000E4F3*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 40GbE Adapter (SR-IOV VF))
@@ -17259,10 +17346,10 @@ pci:v00001077d00001664sv00001077sd0000E4F4*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45411H 40GbE Adapter (SR-IOV VF))
 
 pci:v00001077d00001664sv00001077sd0000E4F6*
- ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45411H 25GbE Adapter (SR-IOV VF))
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45211H 25GbE Adapter (SR-IOV VF))
 
 pci:v00001077d00001664sv00001077sd0000E4F7*
- ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 25GbE Adapter (SR-IOV VF))
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45212H 25GbE Adapter (SR-IOV VF))
 
 pci:v00001077d00001664sv00001077sd0000E4F8*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45611H 100GbE Adapter (SR-IOV VF))
@@ -17273,9 +17360,21 @@ pci:v00001077d00002020*
 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)
+
+pci:v00001077d00002031sv0000103Csd000017E8*
+ ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP 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)
+
 pci:v00001077d00002031sv0000103Csd00008002*
  ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (3830C 16G Fibre Channel Host Bus Adapter)
 
+pci:v00001077d00002071*
+ ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter
+
 pci:v00001077d00002100*
  ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter
 
@@ -17288,6 +17387,15 @@ pci:v00001077d00002200*
 pci:v00001077d00002200sv00001077sd00000002*
  ID_MODEL_FROM_DATABASE=QLA2200 64-bit Fibre Channel Adapter (QLA2200)
 
+pci:v00001077d00002261*
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe 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)
+
+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)
+
 pci:v00001077d00002300*
  ID_MODEL_FROM_DATABASE=QLA2300 64-bit Fibre Channel Adapter
 
@@ -17327,6 +17435,9 @@ pci:v00001077d00002532sv0000103Csd00003262*
 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)
+
 pci:v00001077d00003022*
  ID_MODEL_FROM_DATABASE=ISP4022-based Ethernet NIC
 
@@ -17972,6 +18083,9 @@ pci:v00001093d00000160*
 pci:v00001093d00000162*
  ID_MODEL_FROM_DATABASE=PCI-MIO-16XE-50
 
+pci:v00001093d00000FE1*
+ ID_MODEL_FROM_DATABASE=PXI-8320
+
 pci:v00001093d00001150*
  ID_MODEL_FROM_DATABASE=PCI-6533 (PCI-DIO-32HS)
 
@@ -18245,9 +18359,18 @@ pci:v00001093d0000700B*
 pci:v00001093d0000700C*
  ID_MODEL_FROM_DATABASE=PCI-5421
 
+pci:v00001093d0000701A*
+ ID_MODEL_FROM_DATABASE=VXIpc-87xB
+
+pci:v00001093d0000701B*
+ ID_MODEL_FROM_DATABASE=VXIpc-770
+
 pci:v00001093d00007023*
  ID_MODEL_FROM_DATABASE=PXI-2593
 
+pci:v00001093d00007027*
+ ID_MODEL_FROM_DATABASE=PCI-MXI-2 Universal
+
 pci:v00001093d0000702C*
  ID_MODEL_FROM_DATABASE=PXI-7831R
 
@@ -19052,6 +19175,9 @@ pci:v00001093d00007322*
 pci:v00001093d00007327*
  ID_MODEL_FROM_DATABASE=PXI-6529
 
+pci:v00001093d0000732C*
+ ID_MODEL_FROM_DATABASE=VXI-8360T
+
 pci:v00001093d00007331*
  ID_MODEL_FROM_DATABASE=PXIe-5602
 
@@ -19469,6 +19595,9 @@ pci:v00001093d000075E6*
 pci:v00001093d000075EF*
  ID_MODEL_FROM_DATABASE=PXIe-5632
 
+pci:v00001093d0000761C*
+ ID_MODEL_FROM_DATABASE=VXI-8360LT
+
 pci:v00001093d0000761F*
  ID_MODEL_FROM_DATABASE=PXI-2540
 
@@ -19559,6 +19688,9 @@ pci:v00001093d000076A4*
 pci:v00001093d000076A5*
  ID_MODEL_FROM_DATABASE=PXIe-6537B
 
+pci:v00001093d0000783E*
+ ID_MODEL_FROM_DATABASE=PXI-8368
+
 pci:v00001093d00009020*
  ID_MODEL_FROM_DATABASE=PXI-2501
 
@@ -19586,6 +19718,9 @@ pci:v00001093d00009090*
 pci:v00001093d000090A0*
  ID_MODEL_FROM_DATABASE=PXI-4021
 
+pci:v00001093d0000A001*
+ ID_MODEL_FROM_DATABASE=PCI-MXI-2
+
 pci:v00001093d0000B001*
  ID_MODEL_FROM_DATABASE=PCI-1408
 
@@ -19853,9 +19988,15 @@ pci:v00001093d0000C4C4sv00001093sd0000762C*
 pci:v00001093d0000C4C4sv00001093sd0000762D*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4145)
 
+pci:v00001093d0000C4C4sv00001093sd0000762E*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5606)
+
 pci:v00001093d0000C4C4sv00001093sd00007644*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4841)
 
+pci:v00001093d0000C4C4sv00001093sd0000764A*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-8237R-S)
+
 pci:v00001093d0000C4C4sv00001093sd00007658*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (4CH))
 
@@ -19877,6 +20018,12 @@ pci:v00001093d0000C4C4sv00001093sd000076B6*
 pci:v00001093d0000C4C4sv00001093sd000076B7*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7975R)
 
+pci:v00001093d0000C4C4sv00001093sd000076B8*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5696)
+
+pci:v00001093d0000C4C4sv00001093sd000076B9*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5654)
+
 pci:v00001093d0000C4C4sv00001093sd000076C8*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6614)
 
@@ -19889,6 +20036,9 @@ pci:v00001093d0000C4C4sv00001093sd000076CB*
 pci:v00001093d0000C4C4sv00001093sd000076CC*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (2CH))
 
+pci:v00001093d0000C4C4sv00001093sd000076CE*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1459)
+
 pci:v00001093d0000C4C4sv00001093sd000076D0*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5160 (2CH))
 
@@ -19898,9 +20048,33 @@ pci:v00001093d0000C4C4sv00001093sd000076D1*
 pci:v00001093d0000C4C4sv00001093sd000076DC*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4610)
 
+pci:v00001093d0000C4C4sv00001093sd000076EC*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2524)
+
+pci:v00001093d0000C4C4sv00001093sd000076ED*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2525)
+
+pci:v00001093d0000C4C4sv00001093sd000076EE*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2526)
+
+pci:v00001093d0000C4C4sv00001093sd000076EF*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2737)
+
+pci:v00001093d0000C4C4sv00001093sd000076F0*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2738)
+
+pci:v00001093d0000C4C4sv00001093sd000076F1*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2739)
+
 pci:v00001093d0000C4C4sv00001093sd000076FB*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1473R-LX110)
 
+pci:v00001093d0000C4C4sv00001093sd000076FC*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5105)
+
+pci:v00001093d0000C4C4sv00001093sd000076FD*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5114)
+
 pci:v00001093d0000C4C4sv00001093sd000076FE*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R)
 
@@ -19925,15 +20099,24 @@ pci:v00001093d0000C4C4sv00001093sd0000770C*
 pci:v00001093d0000C4C4sv00001093sd00007711*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4464)
 
+pci:v00001093d0000C4C4sv00001093sd00007712*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4463)
+
 pci:v00001093d0000C4C4sv00001093sd00007716*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6612)
 
+pci:v00001093d0000C4C4sv00001093sd0000771D*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (Unconfigured CA4 Switch)
+
 pci:v00001093d0000C4C4sv00001093sd0000771E*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4339)
 
 pci:v00001093d0000C4C4sv00001093sd00007735*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9033)
 
+pci:v00001093d0000C4C4sv00001093sd0000773E*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R)
+
 pci:v00001093d0000C4C4sv00001093sd0000774B*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9031)
 
@@ -19943,6 +20126,15 @@ pci:v00001093d0000C4C4sv00001093sd0000774D*
 pci:v00001093d0000C4C4sv00001093sd00007755*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9030)
 
+pci:v00001093d0000C4C4sv00001093sd00007768*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2747)
+
+pci:v00001093d0000C4C4sv00001093sd00007769*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2748)
+
+pci:v00001093d0000C4C4sv00001093sd0000776A*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2746)
+
 pci:v00001093d0000C4C4sv00001093sd00007777*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7976R)
 
@@ -19955,6 +20147,15 @@ pci:v00001093d0000C4C4sv00001093sd00007783*
 pci:v00001093d0000C4C4sv00001093sd00007784*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R)
 
+pci:v00001093d0000C4C4sv00001093sd00007790*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (4CH))
+
+pci:v00001093d0000C4C4sv00001093sd00007791*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (8CH))
+
+pci:v00001093d0000C4C4sv00001093sd00007793*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5171R (8CH))
+
 pci:v00001093d0000C4C4sv00001093sd000077A5*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6345)
 
@@ -19967,6 +20168,12 @@ pci:v00001093d0000C4C4sv00001093sd000077A7*
 pci:v00001093d0000C4C4sv00001093sd000077A8*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6375)
 
+pci:v00001093d0000C4C4sv00001093sd000077AA*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1458)
+
+pci:v00001093d0000C4C4sv00001093sd000077AD*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (IC-3173)
+
 pci:v00001093d0000C4C4sv00001093sd000077B4*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7820R)
 
@@ -19979,6 +20186,48 @@ pci:v00001093d0000C4C4sv00001093sd000077B6*
 pci:v00001093d0000C4C4sv00001093sd000077B9*
  ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9038)
 
+pci:v00001093d0000C4C4sv00001093sd000077BA*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4136)
+
+pci:v00001093d0000C4C4sv00001093sd000077BB*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4137)
+
+pci:v00001093d0000C4C4sv00001093sd000077C0*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R)
+
+pci:v00001093d0000C4C4sv00001093sd000077C1*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R)
+
+pci:v00001093d0000C4C4sv00001093sd000077C2*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R)
+
+pci:v00001093d0000C4C4sv00001093sd000077CA*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6738)
+
+pci:v00001093d0000C4C4sv00001093sd000077CB*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6739)
+
+pci:v00001093d0000C4C4sv00001093sd000077DB*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9035)
+
+pci:v00001093d0000C4C4sv00001093sd000077DC*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9036)
+
+pci:v00001093d0000C4C4sv00001093sd000077DD*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9039)
+
+pci:v00001093d0000C4C4sv00001093sd00007802*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4302)
+
+pci:v00001093d0000C4C4sv00001093sd00007803*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4303)
+
+pci:v00001093d0000C4C4sv00001093sd00007805*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4305)
+
+pci:v00001093d0000C4C4sv00001093sd0000788E*
+ ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4304)
+
 pci:v00001093d0000C801*
  ID_MODEL_FROM_DATABASE=PCI-GPIB
 
@@ -20090,6 +20339,27 @@ pci:v00001093d0000E261*
 pci:v00001093d0000E271*
  ID_MODEL_FROM_DATABASE=PXI-8462
 
+pci:v00001093d0000F110*
+ ID_MODEL_FROM_DATABASE=VMEpc-650
+
+pci:v00001093d0000F120*
+ ID_MODEL_FROM_DATABASE=VXIpc-650
+
+pci:v00001093d0000FE00*
+ ID_MODEL_FROM_DATABASE=VXIpc-87x
+
+pci:v00001093d0000FE41*
+ ID_MODEL_FROM_DATABASE=VXIpc-860
+
+pci:v00001093d0000FE51*
+ ID_MODEL_FROM_DATABASE=VXIpc-74x
+
+pci:v00001093d0000FE61*
+ ID_MODEL_FROM_DATABASE=VXIpc-850
+
+pci:v00001093d0000FE70*
+ ID_MODEL_FROM_DATABASE=VXIpc-880
+
 pci:v00001094*
  ID_VENDOR_FROM_DATABASE=First International Computers [FIC]
 
@@ -21152,6 +21422,9 @@ pci:v000010B5d00008747*
 pci:v000010B5d000087B0*
  ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch
 
+pci:v000010B5d000087B0sv00001093sd00007761*
+ ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch (PXIe-8830mc)
+
 pci:v000010B5d00009016*
  ID_MODEL_FROM_DATABASE=PLX 9016 8-port serial controller
 
@@ -21185,6 +21458,9 @@ pci:v000010B5d00009030sv000010B5sd00003068*
 pci:v000010B5d00009030sv000010B5sd00003463*
  ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D (v2) (3V/5V): Timecode Reader Board)
 
+pci:v000010B5d00009030sv000010B5sd00003591*
+ ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PLURA PCL PCI L (v2) (3.3V/5V): Time Code Reader Board)
+
 pci:v000010B5d00009030sv000012FEsd00000111*
  ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (CPCI-ASIO4 (ESD 4-port Serial Interface Board))
 
@@ -28619,6 +28895,9 @@ pci:v000010DEd00000F01*
 pci:v000010DEd00000F02*
  ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730]
 
+pci:v000010DEd00000F06*
+ ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730]
+
 pci:v000010DEd00000FBB*
  ID_MODEL_FROM_DATABASE=GM204 High Definition Audio Controller
 
@@ -28748,6 +29027,9 @@ pci:v000010DEd00000FEC*
 pci:v000010DEd00000FED*
  ID_MODEL_FROM_DATABASE=GK107M [GeForce 820M]
 
+pci:v000010DEd00000FEE*
+ ID_MODEL_FROM_DATABASE=GK107M [GeForce 810M]
+
 pci:v000010DEd00000FEF*
  ID_MODEL_FROM_DATABASE=GK107GL [GRID K340]
 
@@ -29108,6 +29390,9 @@ pci:v000010DEd000010D8*
 pci:v000010DEd00001140*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M]
 
+pci:v000010DEd00001140sv00001019sd00000799*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
 pci:v000010DEd00001140sv00001019sd0000999F*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M)
 
@@ -29405,6 +29690,9 @@ pci:v000010DEd00001140sv00001028sd00000662*
 pci:v000010DEd00001140sv00001028sd0000068D*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
 
+pci:v000010DEd00001140sv00001028sd000006C1*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
 pci:v000010DEd00001140sv0000103Csd000018EF*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M)
 
@@ -30023,6 +30311,12 @@ pci:v000010DEd00001140sv00001854sd00000190*
 pci:v000010DEd00001140sv00001854sd00000192*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M)
 
+pci:v000010DEd00001140sv00001854sd00000224*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
+pci:v000010DEd00001140sv00001B0Asd000001C0*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
 pci:v000010DEd00001140sv00001B0Asd000020DD*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M)
 
@@ -30041,6 +30335,18 @@ pci:v000010DEd00001140sv00001B0Asd000090D7*
 pci:v000010DEd00001140sv00001B0Asd000090DD*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
 
+pci:v000010DEd00001140sv00001B50sd00005530*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
+pci:v000010DEd00001140sv00001B6Csd00005531*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M)
+
+pci:v000010DEd00001140sv00001BABsd00000106*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M)
+
+pci:v000010DEd00001140sv00001D05sd00001013*
+ ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M)
+
 pci:v000010DEd00001180*
  ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680]
 
@@ -30527,6 +30833,9 @@ pci:v000010DEd00001346*
 pci:v000010DEd00001347*
  ID_MODEL_FROM_DATABASE=GM108M [GeForce 940M]
 
+pci:v000010DEd0000134D*
+ ID_MODEL_FROM_DATABASE=GM108M [GeForce 940MX]
+
 pci:v000010DEd0000137A*
  ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M]
 
@@ -30569,9 +30878,27 @@ pci:v000010DEd00001398*
 pci:v000010DEd0000139A*
  ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M]
 
+pci:v000010DEd0000139Asv000017AAsd0000362C*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A)
+
+pci:v000010DEd0000139Asv000017AAsd0000362F*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A)
+
+pci:v000010DEd0000139Asv000017AAsd0000363F*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A)
+
+pci:v000010DEd0000139Asv000017AAsd00003640*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A)
+
+pci:v000010DEd0000139Asv000017AAsd000036B9*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A)
+
 pci:v000010DEd0000139B*
  ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M]
 
+pci:v000010DEd0000139Bsv0000103Csd00002B4C*
+ ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] (GeForce GTX 960A)
+
 pci:v000010DEd0000139C*
  ID_MODEL_FROM_DATABASE=GM107M [GeForce 940M]
 
@@ -30587,6 +30914,9 @@ pci:v000010DEd000013B2*
 pci:v000010DEd000013B3*
  ID_MODEL_FROM_DATABASE=GM107GLM [Quadro K2200M]
 
+pci:v000010DEd000013B9*
+ ID_MODEL_FROM_DATABASE=GM107GL [NVS 810]
+
 pci:v000010DEd000013BA*
  ID_MODEL_FROM_DATABASE=GM107GL [Quadro K2200]
 
@@ -30623,6 +30953,9 @@ pci:v000010DEd000013D8*
 pci:v000010DEd000013D9*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M]
 
+pci:v000010DEd000013DA*
+ ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980]
+
 pci:v000010DEd000013F0*
  ID_MODEL_FROM_DATABASE=GM204GL [Quadro M5000]
 
@@ -30647,6 +30980,12 @@ pci:v000010DEd00001401*
 pci:v000010DEd00001402*
  ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 950]
 
+pci:v000010DEd00001407*
+ ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 750 v2]
+
+pci:v000010DEd00001427*
+ ID_MODEL_FROM_DATABASE=GM206M [GeForce GTX 965M]
+
 pci:v000010DEd00001617*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980M]
 
@@ -30656,6 +30995,9 @@ pci:v000010DEd00001618*
 pci:v000010DEd00001619*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M]
 
+pci:v000010DEd0000161A*
+ ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980]
+
 pci:v000010DEd000017C2*
  ID_MODEL_FROM_DATABASE=GM200 [GeForce GTX TITAN X]
 
@@ -30665,6 +31007,9 @@ pci:v000010DEd000017C8*
 pci:v000010DEd000017F0*
  ID_MODEL_FROM_DATABASE=GM200GL [Quadro M6000]
 
+pci:v000010DEd000017FD*
+ ID_MODEL_FROM_DATABASE=GM200GL [Tesla M40]
+
 pci:v000010DF*
  ID_VENDOR_FROM_DATABASE=Emulex Corporation
 
@@ -31142,15 +31487,24 @@ pci:v000010ECd00005229sv0000103Csd0000194E*
 pci:v000010ECd00005229sv0000103Csd00001985*
  ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Pavilion 17-e163sg Notebook PC)
 
+pci:v000010ECd0000522A*
+ ID_MODEL_FROM_DATABASE=RTS522A PCI Express Card Reader
+
 pci:v000010ECd00005249*
  ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader
 
 pci:v000010ECd00005249sv0000103Csd00001909*
  ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader (ZBook 15)
 
+pci:v000010ECd0000524A*
+ ID_MODEL_FROM_DATABASE=RTS524A PCI Express Card Reader
+
 pci:v000010ECd00005250*
  ID_MODEL_FROM_DATABASE=RTS5250 PCI Express Card Reader
 
+pci:v000010ECd0000525A*
+ ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader
+
 pci:v000010ECd00005286*
  ID_MODEL_FROM_DATABASE=RTS5286 PCI Express Card Reader
 
@@ -35789,6 +36143,9 @@ pci:v00001137d00000040sv00001137sd0000012E*
 pci:v00001137d00000040sv00001137sd00000137*
  ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine)
 
+pci:v00001137d00000040sv00001137sd0000014D*
+ ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe)
+
 pci:v00001137d00000041*
  ID_MODEL_FROM_DATABASE=VIC PCIe Downstream Port
 
@@ -35810,6 +36167,9 @@ pci:v00001137d00000042sv00001137sd000000CE*
 pci:v00001137d00000042sv00001137sd0000012E*
  ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1227 PCIe Management Controller)
 
+pci:v00001137d00000042sv00001137sd0000014D*
+ ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1385 PCIe Management Controller)
+
 pci:v00001137d00000043*
  ID_MODEL_FROM_DATABASE=VIC Ethernet NIC
 
@@ -35885,6 +36245,9 @@ pci:v00001137d00000044sv00001137sd0000012E*
 pci:v00001137d00000044sv00001137sd00000137*
  ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1380 Mezzanine Ethernet NIC Dynamic)
 
+pci:v00001137d00000044sv00001137sd0000014D*
+ ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1385 PCIe Ethernet NIC Dynamic)
+
 pci:v00001137d00000045*
  ID_MODEL_FROM_DATABASE=VIC FCoE HBA
 
@@ -35921,6 +36284,9 @@ pci:v00001137d00000045sv00001137sd0000012E*
 pci:v00001137d00000045sv00001137sd00000137*
  ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1380 Mezzanine FCoE HBA)
 
+pci:v00001137d00000045sv00001137sd0000014D*
+ ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1385 PCIe FCoE HBA)
+
 pci:v00001137d00000046*
  ID_MODEL_FROM_DATABASE=VIC SCSI Controller
 
@@ -35945,6 +36311,9 @@ pci:v00001137d0000007Asv00001137sd0000012C*
 pci:v00001137d0000007Asv00001137sd00000137*
  ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine)
 
+pci:v00001137d0000007Asv00001137sd0000014D*
+ ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe)
+
 pci:v00001137d000000CF*
  ID_MODEL_FROM_DATABASE=VIC Userspace NIC
 
@@ -45239,9 +45608,6 @@ pci:v00001412d00001712*
 pci:v00001412d00001712sv00001412sd00001712*
  ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24)
 
-pci:v00001412d00001712sv00001412sd00003632*
- ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta Audiophile 192)
-
 pci:v00001412d00001712sv00001412sd0000D630*
  ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010)
 
@@ -45314,6 +45680,9 @@ pci:v00001412d00001724sv00001412sd00003630*
 pci:v00001412d00001724sv00001412sd00003631*
  ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Revolution 5.1)
 
+pci:v00001412d00001724sv00001412sd00003632*
+ ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Audiophile 192)
+
 pci:v00001412d00001724sv0000153Bsd00001145*
  ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 7.1 Space)
 
@@ -46118,6 +46487,18 @@ pci:v00001425d00005096*
 pci:v00001425d00005097*
  ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller
 
+pci:v00001425d00005098*
+ ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller
+
+pci:v00001425d00005099*
+ ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller
+
+pci:v00001425d0000509A*
+ ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller
+
+pci:v00001425d0000509B*
+ ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller
+
 pci:v00001425d00005401*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
 
@@ -46241,6 +46622,18 @@ pci:v00001425d00005496*
 pci:v00001425d00005497*
  ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller
 
+pci:v00001425d00005498*
+ ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller
+
+pci:v00001425d00005499*
+ ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller
+
+pci:v00001425d0000549A*
+ ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller
+
+pci:v00001425d0000549B*
+ ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller
+
 pci:v00001425d00005501*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
 
@@ -46364,6 +46757,18 @@ pci:v00001425d00005596*
 pci:v00001425d00005597*
  ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller
 
+pci:v00001425d00005598*
+ ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller
+
+pci:v00001425d00005599*
+ ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller
+
+pci:v00001425d0000559A*
+ ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller
+
+pci:v00001425d0000559B*
+ ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller
+
 pci:v00001425d00005601*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
 
@@ -46487,6 +46892,18 @@ pci:v00001425d00005696*
 pci:v00001425d00005697*
  ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller
 
+pci:v00001425d00005698*
+ ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller
+
+pci:v00001425d00005699*
+ ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller
+
+pci:v00001425d0000569A*
+ ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller
+
+pci:v00001425d0000569B*
+ ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller
+
 pci:v00001425d00005701*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
 
@@ -46727,6 +47144,18 @@ pci:v00001425d00005896*
 pci:v00001425d00005897*
  ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller [VF]
 
+pci:v00001425d00005898*
+ ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00005899*
+ ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d0000589A*
+ ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d0000589B*
+ ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller [VF]
+
 pci:v00001425d0000A000*
  ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller
 
@@ -46928,6 +47357,9 @@ pci:v0000144Dd00001600*
 pci:v0000144Dd0000A800*
  ID_MODEL_FROM_DATABASE=XP941 PCIe SSD
 
+pci:v0000144Dd0000A802*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller
+
 pci:v0000144Dd0000A820*
  ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X
 
@@ -48155,6 +48587,9 @@ pci:v000014E4d00001657*
 pci:v000014E4d00001657sv0000103Csd0000169D*
  ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331FLR Adapter)
 
+pci:v000014E4d00001657sv0000103Csd000022BE*
+ ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331i Adapter)
+
 pci:v000014E4d00001659*
  ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express
 
@@ -48833,6 +49268,30 @@ pci:v000014E4d000016C7sv000014E4sd00000009*
 pci:v000014E4d000016C7sv000014E4sd0000000A*
  ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX)
 
+pci:v000014E4d000016C8*
+ ID_MODEL_FROM_DATABASE=BCM57301 NetXtreme-C Single-port 10Gb Ethernet
+
+pci:v000014E4d000016C9*
+ ID_MODEL_FROM_DATABASE=BCM57302 NetXtreme-C Dual-port 10Gb/25Gb Ethernet
+
+pci:v000014E4d000016CA*
+ ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet
+
+pci:v000014E4d000016CB*
+ ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Ethernet Virtual Function
+
+pci:v000014E4d000016D0*
+ ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Dual-port 10Gb Ethernet
+
+pci:v000014E4d000016D1*
+ ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet
+
+pci:v000014E4d000016D2*
+ ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet
+
+pci:v000014E4d000016D3*
+ ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Virtual Function
+
 pci:v000014E4d000016DD*
  ID_MODEL_FROM_DATABASE=NetLink BCM5781 Gigabit Ethernet PCI Express
 
@@ -49433,6 +49892,9 @@ pci:v000014E4d000043A1*
 pci:v000014E4d000043A2*
  ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter
 
+pci:v000014E4d000043A3*
+ ID_MODEL_FROM_DATABASE=BCM4350 802.11ac Wireless Network Adapter
+
 pci:v000014E4d000043A9*
  ID_MODEL_FROM_DATABASE=BCM43217 802.11b/g/n
 
@@ -49475,6 +49937,9 @@ pci:v000014E4d00004401sv00001025sd00000035*
 pci:v000014E4d00004401sv00001025sd00000064*
  ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Extensa 3000 series laptop)
 
+pci:v000014E4d00004401sv00001028sd00008127*
+ ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Dimension 2400)
+
 pci:v000014E4d00004401sv0000103Csd000008B0*
  ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (tc1100 tablet)
 
@@ -51569,6 +52034,12 @@ pci:v000015B3d0000020B*
 pci:v000015B3d0000020D*
  ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Flash Recovery]
 
+pci:v000015B3d00000262*
+ ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable] EN
+
+pci:v000015B3d00000263*
+ ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN
+
 pci:v000015B3d00001002*
  ID_MODEL_FROM_DATABASE=MT25400 Family [ConnectX-2 Virtual Function]
 
@@ -51608,6 +52079,9 @@ pci:v000015B3d00001007sv0000103Csd000022F3*
 pci:v000015B3d00001007sv0000103Csd000022F4*
  ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+FLR-QSFP Adapter)
 
+pci:v000015B3d00001007sv0000103Csd0000801F*
+ ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (Ethernet 10G 2-port 546SFP+ Adapter)
+
 pci:v000015B3d00001007sv0000117Csd00000090*
  ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ41)
 
@@ -51663,7 +52137,7 @@ pci:v000015B3d00001016*
  ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function]
 
 pci:v000015B3d00001017*
- ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-4]
+ ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5]
 
 pci:v000015B3d00001018*
  ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Virtual Function]
@@ -53276,12 +53750,18 @@ pci:v0000168Cd00000030sv00001A56sd00002001*
 pci:v0000168Cd00000032*
  ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter
 
+pci:v0000168Cd00000032sv00001028sd00000208*
+ ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Wireless 1506 WLAN Half Mini-Card)
+
 pci:v0000168Cd00000032sv0000103Csd00001838*
  ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter)
 
 pci:v0000168Cd00000032sv0000105Bsd0000E044*
  ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Unex DHXA-225)
 
+pci:v0000168Cd00000032sv00001A3Bsd00001186*
+ ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NE186H)
+
 pci:v0000168Cd00000033*
  ID_MODEL_FROM_DATABASE=AR9580 Wireless Network Adapter
 
@@ -54155,6 +54635,9 @@ pci:v00001797d00006816*
 pci:v00001797d00006817*
  ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller
 
+pci:v00001797d00006864*
+ ID_MODEL_FROM_DATABASE=TW6864 multimedia video controller
+
 pci:v00001799*
  ID_VENDOR_FROM_DATABASE=Belkin
 
@@ -55550,6 +56033,15 @@ pci:v00001912d00000014*
 pci:v00001912d00000015*
  ID_MODEL_FROM_DATABASE=uPD720202 USB 3.0 Host Controller
 
+pci:v00001912d0000001A*
+ ID_MODEL_FROM_DATABASE=SH7758 PCIe-PCI Bridge [PPB]
+
+pci:v00001912d0000001B*
+ ID_MODEL_FROM_DATABASE=SH7758 PCIe End-Point [PBI]
+
+pci:v00001912d0000001D*
+ ID_MODEL_FROM_DATABASE=SH7758 PCIe Switch [PS]
+
 pci:v00001919*
  ID_VENDOR_FROM_DATABASE=Soltek Computer Inc.
 
@@ -55805,6 +56297,9 @@ pci:v00001924d00000903sv00001924sd0000800C*
 pci:v00001924d00000903sv00001924sd0000800D*
  ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x02F-R3 Flareon 7000 Series 10G Adapter)
 
+pci:v00001924d00000903sv00001924sd00008010*
+ ID_MODEL_FROM_DATABASE=SFC9120 (SFA7942Q-R1 QSFP+ AOE Adapter)
+
 pci:v00001924d00000923*
  ID_MODEL_FROM_DATABASE=SFC9140
 
@@ -55817,6 +56312,15 @@ pci:v00001924d00000923sv00001924sd0000800E*
 pci:v00001924d00000923sv00001924sd0000800F*
  ID_MODEL_FROM_DATABASE=SFC9140 (SFN7xx4F-R1 Flareon Ultra 7000 Series 10G Adapter)
 
+pci:v00001924d00000A03*
+ ID_MODEL_FROM_DATABASE=SFC9220
+
+pci:v00001924d00000A03sv00001924sd00008012*
+ ID_MODEL_FROM_DATABASE=SFC9220 (SFN8522-R1 Flareon Ultra 8000 Series 10G Adapter)
+
+pci:v00001924d00000A03sv00001924sd00008014*
+ ID_MODEL_FROM_DATABASE=SFC9220 (SFN8542-R1 Flareon Ultra 8000 Series 10/40G Adapter)
+
 pci:v00001924d00001803*
  ID_MODEL_FROM_DATABASE=SFC9020 Virtual Function [Solarstorm]
 
@@ -56309,6 +56813,9 @@ pci:v00001969d00001083*
 pci:v00001969d00001090*
  ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet
 
+pci:v00001969d00001090sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet (VivoBook X202E, X202EV)
+
 pci:v00001969d00001091*
  ID_MODEL_FROM_DATABASE=AR8161 Gigabit Ethernet
 
@@ -56516,6 +57023,9 @@ pci:v0000199Fd00008521*
 pci:v000019A2*
  ID_VENDOR_FROM_DATABASE=Emulex Corporation
 
+pci:v000019A2d00000120*
+ ID_MODEL_FROM_DATABASE=x1 PCIe Gen2 Bridge[Pilot4]
+
 pci:v000019A2d00000200*
  ID_MODEL_FROM_DATABASE=BladeEngine 10Gb PCI-E iSCSI adapter
 
@@ -57482,6 +57992,12 @@ pci:v00001B85d00001041*
 pci:v00001B85d00008788*
  ID_MODEL_FROM_DATABASE=RevoDrive Hybrid
 
+pci:v00001B94*
+ ID_VENDOR_FROM_DATABASE=Signatec / Dynamic Signals Corp
+
+pci:v00001B94d0000E400*
+ ID_MODEL_FROM_DATABASE=PX14400 Dual Xilinx Virtex5 based Digitizer
+
 pci:v00001B96*
  ID_VENDOR_FROM_DATABASE=Western Digital
 
@@ -57668,6 +58184,12 @@ pci:v00001C2Cd000000A5*
 pci:v00001C2Cd000000A6*
  ID_MODEL_FROM_DATABASE=FBC1CG Capture 1x100Gb
 
+pci:v00001C2Cd000000A9*
+ ID_MODEL_FROM_DATABASE=FBC2XGHH Capture 2x10Gb
+
+pci:v00001C2Cd000000AF*
+ ID_MODEL_FROM_DATABASE=Capture slave device
+
 pci:v00001C32*
  ID_VENDOR_FROM_DATABASE=Highland Technology, Inc.
 
@@ -57695,6 +58217,12 @@ pci:v00001C58*
 pci:v00001C58d00000003*
  ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD
 
+pci:v00001C58d00000003sv00001014sd000004F5*
+ ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 1.6TB NVMe Adapter)
+
+pci:v00001C58d00000003sv00001014sd000004F6*
+ ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 3.2TB NVMe Adapter)
+
 pci:v00001C7E*
  ID_VENDOR_FROM_DATABASE=TTTech Computertechnik AG
 
@@ -57752,6 +58280,12 @@ pci:v00001CE4d00000002*
 pci:v00001CE4d00000003*
  ID_MODEL_FROM_DATABASE=ExaNIC X10
 
+pci:v00001CE4d00000004*
+ ID_MODEL_FROM_DATABASE=ExaNIC X10-GM
+
+pci:v00001CE4d00000005*
+ ID_MODEL_FROM_DATABASE=ExaNIC X40
+
 pci:v00001CF7*
  ID_VENDOR_FROM_DATABASE=Subspace Dynamics
 
@@ -57761,6 +58295,9 @@ pci:v00001D00*
 pci:v00001D1D*
  ID_VENDOR_FROM_DATABASE=CNEX Labs
 
+pci:v00001D1Dd00001F1F*
+ ID_MODEL_FROM_DATABASE=QEMU NVM Express LightNVM Controller
+
 pci:v00001D1Dd00002807*
  ID_MODEL_FROM_DATABASE=8800 series NVMe SSD
 
@@ -57785,6 +58322,9 @@ pci:v00001D44*
 pci:v00001D44d0000A400*
  ID_MODEL_FROM_DATABASE=PM2x24/PM3224
 
+pci:v00001D49*
+ ID_VENDOR_FROM_DATABASE=Lenovo
+
 pci:v00001D5C*
  ID_VENDOR_FROM_DATABASE=Fantasia Trading LLC
 
@@ -57959,6 +58499,9 @@ pci:v00001FC9d00004025sv00001FC9sd00003015*
 pci:v00001FC9d00004026*
  ID_MODEL_FROM_DATABASE=TN9610 10GbE SFP+ Ethernet Adapter
 
+pci:v00001FC9d00004027*
+ ID_MODEL_FROM_DATABASE=TN9710 10GBase-T/NBASE-T Ethernet Adapter
+
 pci:v00001FCC*
  ID_VENDOR_FROM_DATABASE=StreamLabs
 
@@ -58046,6 +58589,9 @@ pci:v00002BD8*
 pci:v00003000*
  ID_VENDOR_FROM_DATABASE=Hansol Electronics Inc.
 
+pci:v00003112*
+ ID_VENDOR_FROM_DATABASE=Satelco Ingenieria S.A.
+
 pci:v00003142*
  ID_VENDOR_FROM_DATABASE=Post Impression Systems.
 
@@ -58166,6 +58712,9 @@ pci:v000037D9d00001140*
 pci:v000037D9d00001141*
  ID_MODEL_FROM_DATABASE=PCI-485(422)
 
+pci:v000037D9d00001142*
+ ID_MODEL_FROM_DATABASE=PCI-CAN2
+
 pci:v00003842*
  ID_VENDOR_FROM_DATABASE=eVga.com. Corp.
 
@@ -59495,6 +60044,18 @@ pci:v0000544C*
 pci:v0000544Cd00000350*
  ID_MODEL_FROM_DATABASE=TL880-based HDTV/ATSC tuner
 
+pci:v0000544D*
+ ID_VENDOR_FROM_DATABASE=TBS Technologies
+
+pci:v0000544Dd00006178*
+ ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card
+
+pci:v0000544Dd00006178sv0000544Dsd00006904*
+ ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card (TBS6904 DVB-S2 Quad Tuner PCIe Card)
+
+pci:v0000544Dd00006178sv0000544Dsd00006905*
+ ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card (TBS6905 DVB-S2 Quad Tuner PCIe Card)
+
 pci:v00005452*
  ID_VENDOR_FROM_DATABASE=SCANLAB AG
 
@@ -60080,6 +60641,9 @@ pci:v00008086d00000154sv00001025sd00000813*
 pci:v00008086d00000154sv0000103Csd000017F6*
  ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (ProBook 4540s)
 
+pci:v00008086d00000154sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (VivoBook X202EV)
+
 pci:v00008086d00000154sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (N56VZ)
 
@@ -60095,6 +60659,9 @@ pci:v00008086d00000155sv00008086sd00002010*
 pci:v00008086d00000156*
  ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller
 
+pci:v00008086d00000156sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (VivoBook X202EV)
+
 pci:v00008086d00000158*
  ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller
 
@@ -60920,6 +61487,12 @@ pci:v00008086d00000953sv00008086sd00003709*
 pci:v00008086d00000953sv00008086sd0000370A*
  ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3600 SSD [2.5" SFF])
 
+pci:v00008086d00000953sv00008086sd0000370D*
+ ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [Add-in Card])
+
+pci:v00008086d00000953sv00008086sd0000370E*
+ ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [2.5" SFF])
+
 pci:v00008086d0000095A*
  ID_MODEL_FROM_DATABASE=Wireless 7265
 
@@ -61806,7 +62379,10 @@ pci:v00008086d00000F34*
  ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB EHCI
 
 pci:v00008086d00000F35*
- ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB xHCI
+ ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI
+
+pci:v00008086d00000F35sv00001025sd00000936*
+ ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI (Aspire ES1)
 
 pci:v00008086d00000F37*
  ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series OTG USB Device
@@ -63303,7 +63879,7 @@ pci:v00008086d00001130sv0000104Dsd000080DF*
  ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Vaio PCG-FX403)
 
 pci:v00008086d00001130sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d00001130sv00008086sd00004557*
  ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (D815EGEW Mainboard)
@@ -63324,7 +63900,7 @@ pci:v00008086d00001132sv0000104Dsd000080DF*
  ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Vaio PCG-FX403)
 
 pci:v00008086d00001132sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EEA2 Mainboard)
+ ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d00001132sv00008086sd00004541*
  ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EEA Motherboard)
@@ -64502,6 +65078,9 @@ pci:v00008086d00001572sv00008086sd00004005*
 pci:v00008086d00001572sv00008086sd00004006*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+
 
+pci:v00008086d00001578*
+ ID_MODEL_FROM_DATABASE=DSL6540 Thunderbolt [Alpine Ridge]
+
 pci:v00008086d0000157B*
  ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection
 
@@ -64664,6 +65243,9 @@ pci:v00008086d000015AD*
 pci:v00008086d000015AE*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X552 1000BASE-T
 
+pci:v00008086d000015B6*
+ ID_MODEL_FROM_DATABASE=DSL6540 USB 3.1 Controller [Alpine Ridge]
+
 pci:v00008086d000015B7*
  ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I219-LM
 
@@ -64682,6 +65264,18 @@ pci:v00008086d000015D1sv00008086sd00000002*
 pci:v00008086d000015D1sv00008086sd000000A2*
  ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1)
 
+pci:v00008086d000015D6*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-V
+
+pci:v00008086d000015D7*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-LM
+
+pci:v00008086d000015D8*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V
+
+pci:v00008086d000015E3*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-LM
+
 pci:v00008086d00001600*
  ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI
 
@@ -64692,7 +65286,7 @@ pci:v00008086d00001602*
  ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics
 
 pci:v00008086d00001603*
- ID_MODEL_FROM_DATABASE=Broadwell-U Camarillo Device
+ ID_MODEL_FROM_DATABASE=Broadwell-U Processor Thermal Subsystem
 
 pci:v00008086d00001604*
  ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI
@@ -64797,61 +65391,67 @@ pci:v00008086d0000163E*
  ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics
 
 pci:v00008086d00001900*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001901*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x16)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x16)
+
+pci:v00008086d00001903*
+ ID_MODEL_FROM_DATABASE=Skylake Processor Thermal Subsystem
 
 pci:v00008086d00001904*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001905*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x8)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x8)
 
 pci:v00008086d00001908*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001909*
- ID_MODEL_FROM_DATABASE=Sky Lake PCIe Controller (x4)
+ ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x4)
 
 pci:v00008086d0000190C*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d0000190F*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001910*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001911*
- ID_MODEL_FROM_DATABASE=Sky Lake Gaussian Mixture Model
+ ID_MODEL_FROM_DATABASE=Skylake Gaussian Mixture Model
 
 pci:v00008086d00001912*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d00001916*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d00001918*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001919*
- ID_MODEL_FROM_DATABASE=Sky Lake Imaging Unit
+ ID_MODEL_FROM_DATABASE=Skylake Imaging Unit
+
+pci:v00008086d0000191B*
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d0000191E*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d0000191F*
- ID_MODEL_FROM_DATABASE=Sky Lake Host Bridge/DRAM Registers
+ ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
 pci:v00008086d00001926*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d00001932*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d0000193B*
- ID_MODEL_FROM_DATABASE=Sky Lake Integrated Graphics
+ ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics
 
 pci:v00008086d00001960*
  ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor
@@ -65582,6 +66182,9 @@ pci:v00008086d00001E02sv00001849sd00001E02*
 pci:v00008086d00001E03*
  ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode]
 
+pci:v00008086d00001E03sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (VivoBook X202EV)
+
 pci:v00008086d00001E03sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (N56VZ)
 
@@ -65612,6 +66215,9 @@ pci:v00008086d00001E0E*
 pci:v00008086d00001E10*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1
 
+pci:v00008086d00001E10sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (VivoBook X202EV)
+
 pci:v00008086d00001E10sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (N56VZ)
 
@@ -65627,6 +66233,9 @@ pci:v00008086d00001E10sv00001849sd00001E10*
 pci:v00008086d00001E12*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2
 
+pci:v00008086d00001E12sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (VivoBook X202EV)
+
 pci:v00008086d00001E12sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (N56VZ)
 
@@ -65639,6 +66248,9 @@ pci:v00008086d00001E14*
 pci:v00008086d00001E16*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4
 
+pci:v00008086d00001E16sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (VivoBook X202EV)
+
 pci:v00008086d00001E16sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (N56VZ)
 
@@ -65672,6 +66284,9 @@ pci:v00008086d00001E1Esv00001849sd00001E1E*
 pci:v00008086d00001E20*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller
 
+pci:v00008086d00001E20sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (VivoBook X202EV)
+
 pci:v00008086d00001E20sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (N56VZ)
 
@@ -65690,6 +66305,9 @@ pci:v00008086d00001E20sv00001849sd00001898*
 pci:v00008086d00001E22*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller
 
+pci:v00008086d00001E22sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (VivoBook X202EV)
+
 pci:v00008086d00001E22sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (N56VZ)
 
@@ -65714,6 +66332,9 @@ pci:v00008086d00001E25*
 pci:v00008086d00001E26*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1
 
+pci:v00008086d00001E26sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (VivoBook X202EV)
+
 pci:v00008086d00001E26sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (N56VZ)
 
@@ -65729,6 +66350,9 @@ pci:v00008086d00001E26sv00001849sd00001E26*
 pci:v00008086d00001E2D*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2
 
+pci:v00008086d00001E2Dsv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (VivoBook X202EV)
+
 pci:v00008086d00001E2Dsv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (N56VZ)
 
@@ -65747,6 +66371,9 @@ pci:v00008086d00001E31*
 pci:v00008086d00001E31sv0000103Csd000017AB*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (ProBook 6570b)
 
+pci:v00008086d00001E31sv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (VivoBook X202EV)
+
 pci:v00008086d00001E31sv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (N56VZ)
 
@@ -65765,6 +66392,9 @@ pci:v00008086d00001E33*
 pci:v00008086d00001E3A*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1
 
+pci:v00008086d00001E3Asv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (VivoBook X202EV)
+
 pci:v00008086d00001E3Asv00001043sd00001477*
  ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (N56VZ)
 
@@ -65891,6 +66521,9 @@ pci:v00008086d00001E5D*
 pci:v00008086d00001E5E*
  ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller
 
+pci:v00008086d00001E5Esv00001043sd0000108D*
+ ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller (VivoBook X202EV)
+
 pci:v00008086d00001E5F*
  ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller
 
@@ -66411,7 +67044,7 @@ pci:v00008086d00002442sv0000147Bsd00000507*
  ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (TH7II-RAID)
 
 pci:v00008086d00002442sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d00002442sv00008086sd00004557*
  ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D815EGEW Mainboard)
@@ -66456,7 +67089,7 @@ pci:v00008086d00002443sv000015D9sd00003280*
  ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Supermicro P4SBE Mainboard)
 
 pci:v00008086d00002443sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d00002443sv00008086sd00004557*
  ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EGEW Mainboard)
@@ -66495,7 +67128,7 @@ pci:v00008086d00002444sv0000147Bsd00000507*
  ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (TH7II-RAID)
 
 pci:v00008086d00002444sv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d00002444sv00008086sd00005744*
  ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (S845WD1-E mainboard)
@@ -66536,6 +67169,9 @@ pci:v00008086d00002445sv0000147Bsd00000507*
 pci:v00008086d00002445sv00008086sd00004557*
  ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (D815EGEW Mainboard)
 
+pci:v00008086d00002445sv00008086sd00004656*
+ ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Desktop Board D815EFV)
+
 pci:v00008086d00002446*
  ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller
 
@@ -66744,7 +67380,7 @@ pci:v00008086d0000244Bsv000015D9sd00003280*
  ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Supermicro P4SBE Mainboard)
 
 pci:v00008086d0000244Bsv00008086sd00004532*
- ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EEA2 mainboard)
+ ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Desktop Board D815EEA2/D815EFV)
 
 pci:v00008086d0000244Bsv00008086sd00004557*
  ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EGEW Mainboard)
@@ -67022,6 +67658,9 @@ pci:v00008086d000024C2sv00001025sd00000064*
 pci:v00008086d000024C2sv00001028sd00000126*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Optiplex GX260)
 
+pci:v00008086d000024C2sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Dimension 2400)
+
 pci:v00008086d000024C2sv00001028sd00000163*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude D505)
 
@@ -67103,6 +67742,9 @@ pci:v00008086d000024C3sv00001028sd00000126*
 pci:v00008086d000024C3sv00001028sd0000014F*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Latitude X300)
 
+pci:v00008086d000024C3sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Dimension 2400)
+
 pci:v00008086d000024C3sv00001028sd0000018D*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Inspiron 700m/710m)
 
@@ -67166,6 +67808,9 @@ pci:v00008086d000024C4sv00001025sd00000064*
 pci:v00008086d000024C4sv00001028sd00000126*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Optiplex GX260)
 
+pci:v00008086d000024C4sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Dimension 2400)
+
 pci:v00008086d000024C4sv00001028sd00000163*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude D505)
 
@@ -67247,6 +67892,9 @@ pci:v00008086d000024C5sv00001028sd0000014F*
 pci:v00008086d000024C5sv00001028sd00000152*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D500)
 
+pci:v00008086d000024C5sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Dimension 2400)
+
 pci:v00008086d000024C5sv00001028sd00000163*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D505)
 
@@ -67295,9 +67943,6 @@ pci:v00008086d000024C5sv00001734sd00001005*
 pci:v00008086d000024C5sv00001734sd00001055*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Amilo M1420)
 
-pci:v00008086d000024C5sv00008086sd000024C5*
- ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Dell Dimension 2400)
-
 pci:v00008086d000024C6*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
 
@@ -67370,6 +68015,9 @@ pci:v00008086d000024C7sv00001025sd00000064*
 pci:v00008086d000024C7sv00001028sd00000126*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Optiplex GX260)
 
+pci:v00008086d000024C7sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Dimension 2400)
+
 pci:v00008086d000024C7sv00001028sd00000163*
  ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude D505)
 
@@ -67478,6 +68126,9 @@ pci:v00008086d000024CBsv00001014sd00000267*
 pci:v00008086d000024CBsv00001028sd00000126*
  ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Optiplex GX260)
 
+pci:v00008086d000024CBsv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Dimension 2400)
+
 pci:v00008086d000024CBsv00001043sd00008089*
  ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (P4B533)
 
@@ -67538,6 +68189,9 @@ pci:v00008086d000024CDsv00001028sd00000139*
 pci:v00008086d000024CDsv00001028sd00000152*
  ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D500)
 
+pci:v00008086d000024CDsv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Dimension 2400)
+
 pci:v00008086d000024CDsv00001028sd00000163*
  ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D505)
 
@@ -68165,6 +68819,18 @@ pci:v00008086d000024F0sv000010A9sd0000802E*
 pci:v00008086d000024F0sv000010A9sd0000802F*
  ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 2-port)
 
+pci:v00008086d000024F0sv00008086sd00002628*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16)
+
+pci:v00008086d000024F0sv00008086sd00002629*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x8)
+
+pci:v00008086d000024F0sv00008086sd0000262A*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 2 Ports, Split PCIe x16)
+
+pci:v00008086d000024F0sv00008086sd0000262D*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, IO Module AHWKPTP100HF)
+
 pci:v00008086d000024F1*
  ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [integrated]
 
@@ -68321,6 +68987,9 @@ pci:v00008086d00002562sv00000E11sd000000B9*
 pci:v00008086d00002562sv00001014sd00000267*
  ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (NetVista A30p)
 
+pci:v00008086d00002562sv00001028sd00000160*
+ ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (Dimension 2400)
+
 pci:v00008086d00002562sv00001734sd00001003*
  ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (D1521 Mainboard (Fujitsu-Siemens))
 
@@ -73613,6 +74282,9 @@ pci:v00008086d00003165sv00008086sd00004010*
 pci:v00008086d00003165sv00008086sd00004210*
  ID_MODEL_FROM_DATABASE=Wireless 3165 (Dual Band Wireless AC 3165)
 
+pci:v00008086d00003166*
+ ID_MODEL_FROM_DATABASE=Intel Dual Band Wireless-AC 3165 Plus Bluetooth
+
 pci:v00008086d00003200*
  ID_MODEL_FROM_DATABASE=GD31244 PCI-X SATA HBA
 
@@ -77747,6 +78419,9 @@ pci:v00008086d00009C31*
 pci:v00008086d00009C31sv000017AAsd00002214*
  ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (ThinkPad X240)
 
+pci:v00008086d00009C31sv00008086sd00007270*
+ ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (Apple MacBookAir6,2 / MacBookPro11,1)
+
 pci:v00008086d00009C35*
  ID_MODEL_FROM_DATABASE=8 Series SDIO Controller
 
@@ -77921,6 +78596,75 @@ pci:v00008086d00009CE5*
 pci:v00008086d00009CE6*
  ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO GSPI Controller #1
 
+pci:v00008086d00009D03*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode]
+
+pci:v00008086d00009D14*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5
+
+pci:v00008086d00009D15*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6
+
+pci:v00008086d00009D21*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC
+
+pci:v00008086d00009D23*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus
+
+pci:v00008086d00009D27*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #0
+
+pci:v00008086d00009D28*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #1
+
+pci:v00008086d00009D29*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #0
+
+pci:v00008086d00009D2A*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #1
+
+pci:v00008086d00009D2D*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Secure Digital IO Controller
+
+pci:v00008086d00009D2F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller
+
+pci:v00008086d00009D31*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem
+
+pci:v00008086d00009D3A*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1
+
+pci:v00008086d00009D48*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller
+
+pci:v00008086d00009D60*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0
+
+pci:v00008086d00009D60sv00008086sd00009D60*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C])
+
+pci:v00008086d00009D61*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #1
+
+pci:v00008086d00009D62*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2
+
+pci:v00008086d00009D63*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #3
+
+pci:v00008086d00009D64*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #4
+
+pci:v00008086d00009D65*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #5
+
+pci:v00008086d00009D66*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #2
+
+pci:v00008086d00009D70*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio
+
 pci:v00008086d0000A000*
  ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge
 
@@ -78057,16 +78801,16 @@ pci:v00008086d0000A126*
  ID_MODEL_FROM_DATABASE=Sunrise Point-H Northpeak
 
 pci:v00008086d0000A127*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #0
 
 pci:v00008086d0000A128*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART #1
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #1
 
 pci:v00008086d0000A129*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS SPI #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO SPI #0
 
 pci:v00008086d0000A12A*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS SPI #1
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO SPI #1
 
 pci:v00008086d0000A12F*
  ID_MODEL_FROM_DATABASE=Sunrise Point-H USB 3.0 xHCI Controller
@@ -78195,13 +78939,13 @@ pci:v00008086d0000A15F*
  ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller
 
 pci:v00008086d0000A160*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS I2C Controller #0
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #0
 
 pci:v00008086d0000A161*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS I2C Controller #1
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #1
 
 pci:v00008086d0000A166*
- ID_MODEL_FROM_DATABASE=Sunrise Point-H LPSS UART Controller #2
+ ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART Controller #2
 
 pci:v00008086d0000A167*
  ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Root Port #17
index 803c2c21fd3436df85004bcd987d7072e36fe11d..46b7ed9ab448d34bc921cb3ff5c8a859f9a82eb8 100644 (file)
@@ -465,7 +465,7 @@ usb:v03F0p011D*
  ID_MODEL_FROM_DATABASE=Bluetooth 1.2 Interface [Broadcom BCM2035]
 
 usb:v03F0p0121*
- ID_MODEL_FROM_DATABASE=HP49g+ Calculator
+ ID_MODEL_FROM_DATABASE=HP 39g+ [F2224A], 39gs [F2223A], 40gs [F2225A], 48gII [F2226A], 49g+ [F2228A], 50g [F2229A, NW240AA]
 
 usb:v03F0p0122*
  ID_MODEL_FROM_DATABASE=HID Internet Keyboard
@@ -567,7 +567,7 @@ usb:v03F0p042A*
  ID_MODEL_FROM_DATABASE=LaserJet M1132 MFP
 
 usb:v03F0p0441*
- ID_MODEL_FROM_DATABASE=HP Prime Calculator
+ ID_MODEL_FROM_DATABASE=Prime [NW280AA, G8X92AA]
 
 usb:v03F0p0504*
  ID_MODEL_FROM_DATABASE=DeskJet 885c
@@ -632,6 +632,9 @@ usb:v03F0p0712*
 usb:v03F0p0714*
  ID_MODEL_FROM_DATABASE=Printing Support
 
+usb:v03F0p0741*
+ ID_MODEL_FROM_DATABASE=Prime Wireless Kit [FOK65AA]
+
 usb:v03F0p0801*
  ID_MODEL_FROM_DATABASE=ScanJet 7400c
 
@@ -833,6 +836,9 @@ usb:v03F0p1524*
 usb:v03F0p1539*
  ID_MODEL_FROM_DATABASE=Mini Magnetic Stripe Reader
 
+usb:v03F0p1541*
+ ID_MODEL_FROM_DATABASE=Prime [G8X92AA]
+
 usb:v03F0p1602*
  ID_MODEL_FROM_DATABASE=PhotoSmart 330 series
 
@@ -1130,6 +1136,9 @@ usb:v03F0p2A11*
 usb:v03F0p2A17*
  ID_MODEL_FROM_DATABASE=LaserJet 2430
 
+usb:v03F0p2A1D*
+ ID_MODEL_FROM_DATABASE=Integrated Module with Bluetooth 2.1 Wireless technology
+
 usb:v03F0p2B11*
  ID_MODEL_FROM_DATABASE=PSC 2170 series
 
@@ -1898,6 +1907,9 @@ usb:v03F0pC802*
 usb:v03F0pD104*
  ID_MODEL_FROM_DATABASE=Bluetooth Dongle
 
+usb:v03F0pD507*
+ ID_MODEL_FROM_DATABASE=39gII [NW249AA]
+
 usb:v03F0pEFBE*
  ID_MODEL_FROM_DATABASE=NEC Picty900
 
@@ -3719,6 +3731,9 @@ usb:v041Ep3090*
 usb:v041Ep30D3*
  ID_MODEL_FROM_DATABASE=Sound Blaster Play!
 
+usb:v041Ep3100*
+ ID_MODEL_FROM_DATABASE=IR Receiver (SB0540)
+
 usb:v041Ep3121*
  ID_MODEL_FROM_DATABASE=WoW tap chat
 
@@ -5627,6 +5642,9 @@ usb:v0458p0083*
 usb:v0458p0087*
  ID_MODEL_FROM_DATABASE=Ergo 525V Laser Mouse
 
+usb:v0458p0089*
+ ID_MODEL_FROM_DATABASE=Genius Traveler 350
+
 usb:v0458p00CA*
  ID_MODEL_FROM_DATABASE=Pen Mouse
 
@@ -7031,6 +7049,9 @@ usb:v046Ap0081*
 usb:v046Ap0106*
  ID_MODEL_FROM_DATABASE=R-300 Wireless Mouse Receiver
 
+usb:v046Ap010D*
+ ID_MODEL_FROM_DATABASE=MX-Board 3.0 Keyboard
+
 usb:v046B*
  ID_VENDOR_FROM_DATABASE=American Megatrends, Inc.
 
@@ -11898,7 +11919,7 @@ usb:v04B3p4484*
  ID_MODEL_FROM_DATABASE=SMSC USB20H04 3-Port Hub [ThinkPad X4 UltraBase, Wistron S Note-3 Media Slice]
 
 usb:v04B3p4485*
- ID_MODEL_FROM_DATABASE=Serial Converter
+ ID_MODEL_FROM_DATABASE=ThinkPad Dock Hub
 
 usb:v04B3p4524*
  ID_MODEL_FROM_DATABASE=40 Character Vacuum Fluorescent Display
@@ -12570,7 +12591,7 @@ usb:v04B8p087C*
  ID_MODEL_FROM_DATABASE=PX-1700F
 
 usb:v04B8p087D*
- ID_MODEL_FROM_DATABASE=PX-B750F
+ ID_MODEL_FROM_DATABASE=PX-B750F/WP-4525 Series
 
 usb:v04B8p087F*
  ID_MODEL_FROM_DATABASE=PX-403A
@@ -15071,6 +15092,9 @@ usb:v04F3p0103*
 usb:v04F3p01A4*
  ID_MODEL_FROM_DATABASE=Wireless Keyboard
 
+usb:v04F3p0201*
+ ID_MODEL_FROM_DATABASE=Touchscreen
+
 usb:v04F3p0210*
  ID_MODEL_FROM_DATABASE=Optical Mouse
 
@@ -16406,6 +16430,9 @@ usb:v04F9p035D*
 usb:v04F9p035E*
  ID_MODEL_FROM_DATABASE=MFC-1910NW
 
+usb:v04F9p0360*
+ ID_MODEL_FROM_DATABASE=DCP-1618W
+
 usb:v04F9p0361*
  ID_MODEL_FROM_DATABASE=MFC-1919NW
 
@@ -18795,61 +18822,61 @@ usb:v056Ap0010*
  ID_MODEL_FROM_DATABASE=ET-0405 [Graphire]
 
 usb:v056Ap0011*
- ID_MODEL_FROM_DATABASE=Graphire 2 4x5
+ ID_MODEL_FROM_DATABASE=ET-0405A [Graphire2 (4x5)]
 
 usb:v056Ap0012*
- ID_MODEL_FROM_DATABASE=Graphire 2 5x7
+ ID_MODEL_FROM_DATABASE=ET-0507A [Graphire2 (5x7)]
 
 usb:v056Ap0013*
- ID_MODEL_FROM_DATABASE=Graphire 3 4x5
+ ID_MODEL_FROM_DATABASE=CTE-430 [Graphire3 (4x5)]
 
 usb:v056Ap0014*
- ID_MODEL_FROM_DATABASE=Graphire 3 6x8
+ ID_MODEL_FROM_DATABASE=CTE-630 [Graphire3 (6x8)]
 
 usb:v056Ap0015*
- ID_MODEL_FROM_DATABASE=Graphire 4 4x5
+ ID_MODEL_FROM_DATABASE=CTE-440 [Graphire4 (4x5)]
 
 usb:v056Ap0016*
- ID_MODEL_FROM_DATABASE=Graphire 4 6x8
+ ID_MODEL_FROM_DATABASE=CTE-640 [Graphire4 (6x8)]
 
 usb:v056Ap0017*
- ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun]
+ ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun (small)]
 
 usb:v056Ap0018*
- ID_MODEL_FROM_DATABASE=Bamboo Fun 6x8
+ ID_MODEL_FROM_DATABASE=CTE-650 [Bamboo Fun (medium)]
 
 usb:v056Ap0019*
- ID_MODEL_FROM_DATABASE=Bamboo One Medium
+ ID_MODEL_FROM_DATABASE=CTE-631 [Bamboo One]
 
 usb:v056Ap0020*
- ID_MODEL_FROM_DATABASE=Intuos 4x5
+ ID_MODEL_FROM_DATABASE=GD-0405 [Intuos (4x5)]
 
 usb:v056Ap0021*
- ID_MODEL_FROM_DATABASE=Intuos 6x8
+ ID_MODEL_FROM_DATABASE=GD-0608 [Intuos (6x8)]
 
 usb:v056Ap0022*
- ID_MODEL_FROM_DATABASE=Intuos 9x12
+ ID_MODEL_FROM_DATABASE=GD-0912 [Intuos (9x12)]
 
 usb:v056Ap0023*
- ID_MODEL_FROM_DATABASE=Intuos 12x12
+ ID_MODEL_FROM_DATABASE=GD-1212 [Intuos (12x12)]
 
 usb:v056Ap0024*
- ID_MODEL_FROM_DATABASE=Intuos 12x18
+ ID_MODEL_FROM_DATABASE=GD-1218 [Intuos (12x18)]
 
 usb:v056Ap0026*
- ID_MODEL_FROM_DATABASE=Intuos5 touch S
+ ID_MODEL_FROM_DATABASE=PTH-450 [Intuos5 touch (S)]
 
 usb:v056Ap0027*
- ID_MODEL_FROM_DATABASE=Intuos5 touch M
+ ID_MODEL_FROM_DATABASE=PTH-650 [Intuos5 touch (M)]
 
 usb:v056Ap0028*
- ID_MODEL_FROM_DATABASE=Intuos5 touch L
+ ID_MODEL_FROM_DATABASE=PTH-850 [Intuos5 touch (L)]
 
 usb:v056Ap0029*
- ID_MODEL_FROM_DATABASE=Intuos5 S
+ ID_MODEL_FROM_DATABASE=PTK-450 [Intuos5 (S)]
 
 usb:v056Ap002A*
- ID_MODEL_FROM_DATABASE=Intuos5 M
+ ID_MODEL_FROM_DATABASE=PTK-650 [Intuos5 (M)]
 
 usb:v056Ap0030*
  ID_MODEL_FROM_DATABASE=PL400
@@ -18879,49 +18906,70 @@ usb:v056Ap0039*
  ID_MODEL_FROM_DATABASE=DTU-710
 
 usb:v056Ap003F*
- ID_MODEL_FROM_DATABASE=Cintiq 21UX (DTZ-2100)
+ ID_MODEL_FROM_DATABASE=DTZ-2100 [Cintiq 21UX]
 
 usb:v056Ap0041*
- ID_MODEL_FROM_DATABASE=Intuos2 4x5
+ ID_MODEL_FROM_DATABASE=XD-0405-U [Intuos2 (4x5)]
 
 usb:v056Ap0042*
- ID_MODEL_FROM_DATABASE=Intuos2 6x8
+ ID_MODEL_FROM_DATABASE=XD-0608-U [Intuos2 (6x8)]
 
 usb:v056Ap0043*
- ID_MODEL_FROM_DATABASE=Intuos2 9x12
+ ID_MODEL_FROM_DATABASE=XD-0912-U [Intuos2 (9x12)]
 
 usb:v056Ap0044*
- ID_MODEL_FROM_DATABASE=Intuos2 12x12
+ ID_MODEL_FROM_DATABASE=XD-1212-U [Intuos2 (12x12)]
 
 usb:v056Ap0045*
- ID_MODEL_FROM_DATABASE=Intuos2 12x18
+ ID_MODEL_FROM_DATABASE=XD-1218-U [Intuos2 (12x18)]
 
 usb:v056Ap0047*
  ID_MODEL_FROM_DATABASE=Intuos2 6x8
 
+usb:v056Ap0057*
+ ID_MODEL_FROM_DATABASE=DTK-2241
+
+usb:v056Ap0059*
+ ID_MODEL_FROM_DATABASE=DTH-2242 tablet
+
+usb:v056Ap005B*
+ ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] tablet
+
+usb:v056Ap005D*
+ ID_MODEL_FROM_DATABASE=DTH-2242 touchscreen
+
+usb:v056Ap005E*
+ ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] touchscreen
+
 usb:v056Ap0060*
- ID_MODEL_FROM_DATABASE=Volito
+ ID_MODEL_FROM_DATABASE=FT-0405 [Volito, PenPartner, PenStation (4x5)]
 
 usb:v056Ap0061*
- ID_MODEL_FROM_DATABASE=PenStation2
+ ID_MODEL_FROM_DATABASE=FT-0203 [Volito, PenPartner, PenStation (2x3)]
 
 usb:v056Ap0062*
- ID_MODEL_FROM_DATABASE=Volito2 4x5
+ ID_MODEL_FROM_DATABASE=CTF-420 [Volito2]
 
 usb:v056Ap0063*
- ID_MODEL_FROM_DATABASE=Volito2 2x3
+ ID_MODEL_FROM_DATABASE=CTF-220 [BizTablet]
 
 usb:v056Ap0064*
- ID_MODEL_FROM_DATABASE=PenPartner2
+ ID_MODEL_FROM_DATABASE=CTF-221 [PenPartner2]
 
 usb:v056Ap0065*
- ID_MODEL_FROM_DATABASE=Bamboo
+ ID_MODEL_FROM_DATABASE=MTE-450 [Bamboo]
 
 usb:v056Ap0069*
- ID_MODEL_FROM_DATABASE=Bamboo One
+ ID_MODEL_FROM_DATABASE=CTF-430 [Bamboo One]
+
+usb:v056Ap006A*
+ ID_MODEL_FROM_DATABASE=CTE-460 [Bamboo One Pen (S)]
+
+usb:v056Ap006B*
+ ID_MODEL_FROM_DATABASE=CTE-660 [Bamboo One Pen (M)]
 
 usb:v056Ap0081*
- ID_MODEL_FROM_DATABASE=Graphire Wireless 6x8
+ ID_MODEL_FROM_DATABASE=CTE-630BT [Graphire Wireless (6x8)]
 
 usb:v056Ap0084*
  ID_MODEL_FROM_DATABASE=Wireless adapter for Bamboo tablets
@@ -18932,41 +18980,44 @@ usb:v056Ap0090*
 usb:v056Ap0093*
  ID_MODEL_FROM_DATABASE=TPC93
 
+usb:v056Ap0097*
+ ID_MODEL_FROM_DATABASE=TPC97
+
 usb:v056Ap009A*
  ID_MODEL_FROM_DATABASE=TPC9A
 
 usb:v056Ap00B0*
- ID_MODEL_FROM_DATABASE=Intuos3 4x5
+ ID_MODEL_FROM_DATABASE=PTZ-430 [Intuos3 (4x5)]
 
 usb:v056Ap00B1*
- ID_MODEL_FROM_DATABASE=Intuos3 6x18
+ ID_MODEL_FROM_DATABASE=PTZ-630 [Intuos3 (6x8)]
 
 usb:v056Ap00B2*
- ID_MODEL_FROM_DATABASE=Intuos3 9x12
+ ID_MODEL_FROM_DATABASE=PTZ-930 [Intuos3 (9x12)]
 
 usb:v056Ap00B3*
- ID_MODEL_FROM_DATABASE=Intuos3 12x12
+ ID_MODEL_FROM_DATABASE=PTZ-1230 [Intuos3 (12x12)]
 
 usb:v056Ap00B4*
- ID_MODEL_FROM_DATABASE=Intuos3 12x19
+ ID_MODEL_FROM_DATABASE=PTZ-1231W [Intuos3 (12x19)]
 
 usb:v056Ap00B5*
- ID_MODEL_FROM_DATABASE=Intuos3 6x11 (PTZ-631W)
+ ID_MODEL_FROM_DATABASE=PTZ-631W [Intuos3 (6x11)]
 
 usb:v056Ap00B7*
- ID_MODEL_FROM_DATABASE=Intuos3 4x6
+ ID_MODEL_FROM_DATABASE=PTZ-431W [Intuos3 (4x6)]
 
 usb:v056Ap00B8*
- ID_MODEL_FROM_DATABASE=Intuos4 4x6
+ ID_MODEL_FROM_DATABASE=PTK-440 [Intuos4 (4x6)]
 
 usb:v056Ap00B9*
- ID_MODEL_FROM_DATABASE=Intuos4 6x9
+ ID_MODEL_FROM_DATABASE=PTK-640 [Intuos4 (6x9)]
 
 usb:v056Ap00BA*
- ID_MODEL_FROM_DATABASE=Intuos4 8x13
+ ID_MODEL_FROM_DATABASE=PTK-840 [Intuos4 (8x13)]
 
 usb:v056Ap00BB*
- ID_MODEL_FROM_DATABASE=Intuos4 12x19
+ ID_MODEL_FROM_DATABASE=PTK-1240 [Intuos4 (12x19)]
 
 usb:v056Ap00C0*
  ID_MODEL_FROM_DATABASE=DTF-521
@@ -18975,64 +19026,181 @@ usb:v056Ap00C4*
  ID_MODEL_FROM_DATABASE=DTF-720
 
 usb:v056Ap00C5*
- ID_MODEL_FROM_DATABASE=Cintiq 20WSX
+ ID_MODEL_FROM_DATABASE=DTZ-20WSX [Cintiq 20WSX]
 
 usb:v056Ap00C6*
- ID_MODEL_FROM_DATABASE=Cintiq 12WX
+ ID_MODEL_FROM_DATABASE=DTZ-12WX [Cintiq 12WX]
 
 usb:v056Ap00C7*
  ID_MODEL_FROM_DATABASE=DTU-1931
 
 usb:v056Ap00CC*
- ID_MODEL_FROM_DATABASE=Cintiq 21UX (DTK-2100)
+ ID_MODEL_FROM_DATABASE=DTK-2100 [Cintiq 21UX]
+
+usb:v056Ap00CE*
+ ID_MODEL_FROM_DATABASE=DTU-2231
+
+usb:v056Ap00D0*
+ ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch]
 
 usb:v056Ap00D1*
- ID_MODEL_FROM_DATABASE=Bamboo Pen & Touch (CTH-460-DE)
+ ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch]
+
+usb:v056Ap00D2*
+ ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)]
 
 usb:v056Ap00D3*
- ID_MODEL_FROM_DATABASE=Bamboo Fun (CTH-661)
+ ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)]
 
 usb:v056Ap00D4*
- ID_MODEL_FROM_DATABASE=Bamboo Pen (CTL-460)
+ ID_MODEL_FROM_DATABASE=CTL-460 [Bamboo Pen (S)]
+
+usb:v056Ap00D5*
+ ID_MODEL_FROM_DATABASE=CTL-660 [Bamboo Pen (M)]
 
 usb:v056Ap00D6*
- ID_MODEL_FROM_DATABASE=Bamboo Pen & Touch (CTH-460)
+ ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch]
+
+usb:v056Ap00D7*
+ ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)]
+
+usb:v056Ap00D8*
+ ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)]
+
+usb:v056Ap00D9*
+ ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch]
+
+usb:v056Ap00DA*
+ ID_MODEL_FROM_DATABASE=CTH-461SE [Bamboo Pen & Touch Special Edition (S)]
 
 usb:v056Ap00DB*
- ID_MODEL_FROM_DATABASE=Bamboo Fun (CTH-661SE-NL)
+ ID_MODEL_FROM_DATABASE=CTH-661SE [Bamboo Pen & Touch Special Edition (M)]
+
+usb:v056Ap00DC*
+ ID_MODEL_FROM_DATABASE=CTT-470 [Bamboo Touch]
 
 usb:v056Ap00DD*
- ID_MODEL_FROM_DATABASE=Bamboo Pen (CTL-470)
+ ID_MODEL_FROM_DATABASE=CTL-470 [Bamboo Connect]
 
 usb:v056Ap00DE*
  ID_MODEL_FROM_DATABASE=CTH-470 [Bamboo Fun Pen & Touch]
 
+usb:v056Ap00DF*
+ ID_MODEL_FROM_DATABASE=CTH-670 [Bamboo Create/Fun]
+
+usb:v056Ap00E2*
+ ID_MODEL_FROM_DATABASE=TPCE2
+
+usb:v056Ap00E3*
+ ID_MODEL_FROM_DATABASE=TPCE3
+
+usb:v056Ap00E5*
+ ID_MODEL_FROM_DATABASE=TPCE5
+
+usb:v056Ap00E6*
+ ID_MODEL_FROM_DATABASE=TPCE6
+
+usb:v056Ap00EC*
+ ID_MODEL_FROM_DATABASE=TPCEC
+
+usb:v056Ap00ED*
+ ID_MODEL_FROM_DATABASE=TPCED
+
+usb:v056Ap00EF*
+ ID_MODEL_FROM_DATABASE=TPCEF
+
+usb:v056Ap00F4*
+ ID_MODEL_FROM_DATABASE=DTK-2400 [Cintiq 24HD] tablet
+
 usb:v056Ap00F6*
- ID_MODEL_FROM_DATABASE=Cintiq 24HD touch (DTH-2400) touchscreen
+ ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] touchscreen
 
 usb:v056Ap00F8*
- ID_MODEL_FROM_DATABASE=Cintiq 24HD touch (DTH-2400) tablet
+ ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] tablet
+
+usb:v056Ap00FA*
+ ID_MODEL_FROM_DATABASE=DTK-2200 [Cintiq 22HD] tablet
+
+usb:v056Ap00FB*
+ ID_MODEL_FROM_DATABASE=DTU-1031
+
+usb:v056Ap0100*
+ ID_MODEL_FROM_DATABASE=TPC100
+
+usb:v056Ap0101*
+ ID_MODEL_FROM_DATABASE=TPC101
+
+usb:v056Ap010D*
+ ID_MODEL_FROM_DATABASE=TPC10D
+
+usb:v056Ap010E*
+ ID_MODEL_FROM_DATABASE=TPC10E
+
+usb:v056Ap010F*
+ ID_MODEL_FROM_DATABASE=TPC10F
+
+usb:v056Ap0116*
+ ID_MODEL_FROM_DATABASE=TPC116
+
+usb:v056Ap012C*
+ ID_MODEL_FROM_DATABASE=TPC12C
+
+usb:v056Ap0300*
+ ID_MODEL_FROM_DATABASE=CTL-471 [Bamboo Splash, One by Wacom (S)]
+
+usb:v056Ap0301*
+ ID_MODEL_FROM_DATABASE=CTL-671 [One by Wacom (M)]
 
 usb:v056Ap0302*
- ID_MODEL_FROM_DATABASE=Intuos CTH480S2 [Manga]
+ ID_MODEL_FROM_DATABASE=CTH-480 [Intuos Pen & Touch (S)]
+
+usb:v056Ap0303*
+ ID_MODEL_FROM_DATABASE=CTH-680 [Intuos Pen & Touch (M)]
+
+usb:v056Ap0304*
+ ID_MODEL_FROM_DATABASE=DTK-1300 [Cintiq 13HD]
 
 usb:v056Ap0307*
- ID_MODEL_FROM_DATABASE=Cintiq Companion Hybrid 13HD (DTH-A1300) tablet
+ ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] tablet
 
 usb:v056Ap0309*
- ID_MODEL_FROM_DATABASE=Cintiq Companion Hybrid 13HD (DTH-A1300) touchscreen
+ ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] touchscreen
 
 usb:v056Ap030E*
- ID_MODEL_FROM_DATABASE=Intuos Pen Small (CTL480)
+ ID_MODEL_FROM_DATABASE=CTL-480 [Intuos Pen (S)]
+
+usb:v056Ap0314*
+ ID_MODEL_FROM_DATABASE=PTH-451 [Intuos pro (S)]
+
+usb:v056Ap0315*
+ ID_MODEL_FROM_DATABASE=PTH-651 [Intuos pro (M)]
+
+usb:v056Ap0317*
+ ID_MODEL_FROM_DATABASE=PTH-851 [Intuos pro (L)]
+
+usb:v056Ap032F*
+ ID_MODEL_FROM_DATABASE=DTU-1031X
 
 usb:v056Ap0400*
  ID_MODEL_FROM_DATABASE=PenPartner 4x5
 
+usb:v056Ap4001*
+ ID_MODEL_FROM_DATABASE=TPC4001
+
+usb:v056Ap4004*
+ ID_MODEL_FROM_DATABASE=TPC4004
+
 usb:v056Ap4850*
  ID_MODEL_FROM_DATABASE=PenPartner 6x8
 
+usb:v056Ap5000*
+ ID_MODEL_FROM_DATABASE=TPC5000
+
+usb:v056Ap5002*
+ ID_MODEL_FROM_DATABASE=TPC5002
+
 usb:v056Ap5010*
- ID_MODEL_FROM_DATABASE=Thinkpad T550 touchscreen
+ ID_MODEL_FROM_DATABASE=TPC5010
 
 usb:v056B*
  ID_VENDOR_FROM_DATABASE=Decicon, Inc.
@@ -20546,6 +20714,9 @@ usb:v058Fp6387*
 usb:v058Fp6390*
  ID_MODEL_FROM_DATABASE=USB 2.0-IDE bridge
 
+usb:v058Fp6391*
+ ID_MODEL_FROM_DATABASE=IDE Bridge
+
 usb:v058Fp9213*
  ID_MODEL_FROM_DATABASE=MacAlly Kbd Hub
 
@@ -20588,6 +20759,9 @@ usb:v058Fp9368*
 usb:v058Fp9380*
  ID_MODEL_FROM_DATABASE=Flash Drive
 
+usb:v058Fp9381*
+ ID_MODEL_FROM_DATABASE=Flash Drive
+
 usb:v058Fp9382*
  ID_MODEL_FROM_DATABASE=Acer/Sweex Flash drive
 
@@ -21563,6 +21737,9 @@ usb:v05ACp8281*
 usb:v05ACp8286*
  ID_MODEL_FROM_DATABASE=Bluetooth Host Controller
 
+usb:v05ACp828C*
+ ID_MODEL_FROM_DATABASE=Bluetooth Host Controller
+
 usb:v05ACp8300*
  ID_MODEL_FROM_DATABASE=Built-in iSight (no firmware loaded)
 
@@ -21950,6 +22127,9 @@ usb:v05CAp1812*
 usb:v05CAp1814*
  ID_MODEL_FROM_DATABASE=HD Webcam
 
+usb:v05CAp1815*
+ ID_MODEL_FROM_DATABASE=Dell Laptop Integrated Webcam
+
 usb:v05CAp1820*
  ID_MODEL_FROM_DATABASE=Integrated Webcam
 
@@ -22367,6 +22547,9 @@ usb:v05DAp20ED*
 usb:v05DAp20EE*
  ID_MODEL_FROM_DATABASE=Micortek ScanMaker X12USL
 
+usb:v05DAp2838*
+ ID_MODEL_FROM_DATABASE=RT2832U
+
 usb:v05DAp3008*
  ID_MODEL_FROM_DATABASE=Scanner
 
@@ -33638,6 +33821,90 @@ usb:v0A85*
 usb:v0A86*
  ID_VENDOR_FROM_DATABASE=NITGen Co., Ltd
 
+usb:v0A89*
+ ID_VENDOR_FROM_DATABASE=Aktiv
+
+usb:v0A89p0001*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth/Net
+
+usb:v0A89p0002*
+ ID_MODEL_FROM_DATABASE=Guardant ID
+
+usb:v0A89p0003*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth 2
+
+usb:v0A89p0004*
+ ID_MODEL_FROM_DATABASE=Rutoken
+
+usb:v0A89p0005*
+ ID_MODEL_FROM_DATABASE=Guardant Fidus
+
+usb:v0A89p0006*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth 3
+
+usb:v0A89p0007*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth 2
+
+usb:v0A89p0008*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time
+
+usb:v0A89p0009*
+ ID_MODEL_FROM_DATABASE=Guardant Code
+
+usb:v0A89p000A*
+ ID_MODEL_FROM_DATABASE=Guardant Sign Pro
+
+usb:v0A89p000B*
+ ID_MODEL_FROM_DATABASE=Guardant Sign Pro HID
+
+usb:v0A89p000C*
+ ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time
+
+usb:v0A89p000D*
+ ID_MODEL_FROM_DATABASE=Guardant Code HID
+
+usb:v0A89p000F*
+ ID_MODEL_FROM_DATABASE=Guardant System Firmware Update
+
+usb:v0A89p0020*
+ ID_MODEL_FROM_DATABASE=Rutoken S
+
+usb:v0A89p0025*
+ ID_MODEL_FROM_DATABASE=Rutoken lite
+
+usb:v0A89p0026*
+ ID_MODEL_FROM_DATABASE=Rutoken lite HID
+
+usb:v0A89p002A*
+ ID_MODEL_FROM_DATABASE=Rutoken Mass Storage
+
+usb:v0A89p002B*
+ ID_MODEL_FROM_DATABASE=Guardant Mass Storage
+
+usb:v0A89p0030*
+ ID_MODEL_FROM_DATABASE=Rutoken ECP
+
+usb:v0A89p0040*
+ ID_MODEL_FROM_DATABASE=Rutoken ECP HID
+
+usb:v0A89p0060*
+ ID_MODEL_FROM_DATABASE=Rutoken Magistra
+
+usb:v0A89p0061*
+ ID_MODEL_FROM_DATABASE=Rutoken Magistra
+
+usb:v0A89p0069*
+ ID_MODEL_FROM_DATABASE=Reader
+
+usb:v0A89p0080*
+ ID_MODEL_FROM_DATABASE=Rutoken PinPad Ex
+
+usb:v0A89p0081*
+ ID_MODEL_FROM_DATABASE=Rutoken PinPad In
+
+usb:v0A89p0082*
+ ID_MODEL_FROM_DATABASE=Rutoken PinPad 2
+
 usb:v0A8D*
  ID_VENDOR_FROM_DATABASE=Picturetel
 
@@ -48467,6 +48734,9 @@ usb:v1871*
 usb:v1871p0101*
  ID_MODEL_FROM_DATABASE=UVC camera (Bresser microscope)
 
+usb:v1871p0141*
+ ID_MODEL_FROM_DATABASE=Camera
+
 usb:v1871p0D01*
  ID_MODEL_FROM_DATABASE=USB2.0 Camera
 
@@ -48548,6 +48818,9 @@ usb:v18A5p0216*
 usb:v18A5p0218*
  ID_MODEL_FROM_DATABASE=External Hard Drive
 
+usb:v18A5p0224*
+ ID_MODEL_FROM_DATABASE=Store 'n' Go Micro Plus
+
 usb:v18A5p0227*
  ID_MODEL_FROM_DATABASE=Pocket Hard Drive
 
@@ -48555,11 +48828,20 @@ usb:v18A5p022B*
  ID_MODEL_FROM_DATABASE=Portable Hard Drive (Store'n'Go)
 
 usb:v18A5p0237*
- ID_MODEL_FROM_DATABASE=Portable Harddrive (500 GB)
+ ID_MODEL_FROM_DATABASE=Portable Harddrive
+
+usb:v18A5p0243*
+ ID_MODEL_FROM_DATABASE=Flash Drive (Store'n'Go)
 
 usb:v18A5p0302*
  ID_MODEL_FROM_DATABASE=Flash Drive
 
+usb:v18A5p0304*
+ ID_MODEL_FROM_DATABASE=Store 'n' Go
+
+usb:v18A5p4123*
+ ID_MODEL_FROM_DATABASE=Store N Go
+
 usb:v18B1*
  ID_VENDOR_FROM_DATABASE=Petalynx
 
@@ -48611,6 +48893,18 @@ usb:v18CDpCAFE*
 usb:v18D1*
  ID_VENDOR_FROM_DATABASE=Google Inc.
 
+usb:v18D1p0001*
+ ID_MODEL_FROM_DATABASE=Onda V972 (storage access)
+
+usb:v18D1p0003*
+ ID_MODEL_FROM_DATABASE=Android-powered device using AllWinner Technology SoC
+
+usb:v18D1p0006*
+ ID_MODEL_FROM_DATABASE=Onda V972 MTP
+
+usb:v18D1p0008*
+ ID_MODEL_FROM_DATABASE=Onda V972 PTP (camera)
+
 usb:v18D1p0D02*
  ID_MODEL_FROM_DATABASE=Celkon A88
 
@@ -48641,6 +48935,9 @@ usb:v18D1p4E22*
 usb:v18D1p4E24*
  ID_MODEL_FROM_DATABASE=Nexus S (tether)
 
+usb:v18D1p4E30*
+ ID_MODEL_FROM_DATABASE=Galaxy Nexus (fastboot)
+
 usb:v18D1p4E40*
  ID_MODEL_FROM_DATABASE=Nexus 7 (fastboot)
 
@@ -48653,17 +48950,29 @@ usb:v18D1p4E42*
 usb:v18D1p4E43*
  ID_MODEL_FROM_DATABASE=Nexus 7 (PTP)
 
+usb:v18D1p4E44*
+ ID_MODEL_FROM_DATABASE=Nexus 7 2012 (PTP)
+
+usb:v18D1p4EE0*
+ ID_MODEL_FROM_DATABASE=Nexus 4 (bootloader)
+
 usb:v18D1p4EE1*
- ID_MODEL_FROM_DATABASE=Nexus 4 / 10
+ ID_MODEL_FROM_DATABASE=Nexus Device (MTP)
 
 usb:v18D1p4EE2*
- ID_MODEL_FROM_DATABASE=Nexus 4 (debug)
+ ID_MODEL_FROM_DATABASE=Nexus Device (debug)
 
 usb:v18D1p4EE3*
- ID_MODEL_FROM_DATABASE=Nexus 4 (tether)
+ ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (tether)
 
 usb:v18D1p4EE4*
- ID_MODEL_FROM_DATABASE=Nexus 4 (debug + tether)
+ ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (debug + tether)
+
+usb:v18D1p4EE5*
+ ID_MODEL_FROM_DATABASE=Nexus 4 (PTP)
+
+usb:v18D1p4EE6*
+ ID_MODEL_FROM_DATABASE=Nexus 4/5 (PTP + debug)
 
 usb:v18D1p7102*
  ID_MODEL_FROM_DATABASE=Toshiba Thrive tablet
@@ -48671,6 +48980,12 @@ usb:v18D1p7102*
 usb:v18D1pB004*
  ID_MODEL_FROM_DATABASE=Pandigital / B&N Novel 9" tablet
 
+usb:v18D1pD001*
+ ID_MODEL_FROM_DATABASE=Nexus 4 (fastboot)
+
+usb:v18D1pD002*
+ ID_MODEL_FROM_DATABASE=Nexus 4 (debug)
+
 usb:v18D1pD109*
  ID_MODEL_FROM_DATABASE=LG G2x MTP
 
@@ -52358,6 +52673,12 @@ usb:v2478*
 usb:v2478p2008*
  ID_MODEL_FROM_DATABASE=U209-000-R Serial Port
 
+usb:v248A*
+ ID_VENDOR_FROM_DATABASE=Maxxter
+
+usb:v248Ap8366*
+ ID_MODEL_FROM_DATABASE=Wireless Optical Mouse ACT-MUSW-002
+
 usb:v249C*
  ID_VENDOR_FROM_DATABASE=M2Tech s.r.l.
 
index f7a82ee26cb8b8d3cf1a2a9dae822082cc43ff80..d060d81f6110833374a8f2fca76372d32f89ccb6 100644 (file)
@@ -25,8 +25,7 @@
 #   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
-# (or /dev/input/event*).
+#   udevadm info /dev/input/eventXX.
 #
 # Allowed properties are:
 #    EVDEV_ABS_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
@@ -115,6 +114,13 @@ evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInsp
  EVDEV_ABS_35=25:2000:22
  EVDEV_ABS_36=0:1351:28
 
+# Dell Latitude E6220
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220*
+ EVDEV_ABS_00=76:1815:22
+ EVDEV_ABS_01=131:1330:30
+ EVDEV_ABS_35=76:1815:22
+ EVDEV_ABS_36=131:1330:30
+
 #########################################
 # Google
 #########################################
@@ -126,6 +132,17 @@ evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus*
  EVDEV_ABS_35=::10
  EVDEV_ABS_36=::10
 
+#########################################
+# HP
+#########################################
+
+# HP Pavilion dm4
+evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4*
+ EVDEV_ABS_00=1360:5563:47
+ EVDEV_ABS_01=1269:4618:61
+ EVDEV_ABS_35=1360:5563:47
+ EVDEV_ABS_36=1269:4618:61
+
 #########################################
 # Lenovo
 #########################################
@@ -141,3 +158,14 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510*
  EVDEV_ABS_01=841:5330:100
  EVDEV_ABS_35=778:6239:72
  EVDEV_ABS_36=841:5330:100
+
+#########################################
+# Samsung
+#########################################
+
+# Samsung 305V4
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A*
+ EVDEV_ABS_00=0:2480:28
+ EVDEV_ABS_01=0:1116:24
+ EVDEV_ABS_35=0:2480:28
+ EVDEV_ABS_36=0:1116:24
index 94906abcbfe6788d5696227543f2b870f66c254f..01213b6069bb9d7e37ff691e8cde57c6cc4c3da9 100644 (file)
@@ -56,8 +56,7 @@
 #   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
-# (or /dev/input/event*).
+#   udevadm info /dev/input/eventXX.
 
 ##########################################
 # Acer
@@ -499,6 +498,13 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook450G0:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:*
  KEYBOARD_KEY_b2=www                                    # Earth
 
+# HP ProBook 440 G3
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3*
+ KEYBOARD_KEY_92=brightnessdown
+ KEYBOARD_KEY_97=brightnessup
+ KEYBOARD_KEY_ee=switchvideomode
+ KEYBOARD_KEY_81=f20                                    # micmute
+
 ###########################################################
 # IBM
 ###########################################################
@@ -652,6 +658,11 @@ evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
  KEYBOARD_KEY_f1=f21
 
+# Lenovo Thinkcentre M800z AIO machine
+# key_scancode 00 is KEY_MICMUTE
+keyboard:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+ KEYBOARD_KEY_00=f20
+
 # enhanced USB keyboard
 evdev:input:b0003v04B3p301B*
  KEYBOARD_KEY_90001=prog1 # ThinkVantage
index 2383d586a3bbac6170abd734490c3afa5dcfc1e9..54ace7cbc159d59c537de1614a9aa9fe6dc7c3f6 100644 (file)
@@ -41,8 +41,7 @@
 #   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
-# (or /dev/input/event*).
+#   udevadm info /dev/input/eventXX.
 #
 # Allowed properties are:
 #    MOUSE_DPI
@@ -309,6 +308,8 @@ mouse:usb:v046dpc046:name:Logitech USB Optical Mouse:
 mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
 # Logitech USB Laser Mouse M-U0011-O rebranded as "terra Laser"
 mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
+# Logitech USB Laser Mouse M-U0007 [M500]
+mouse:usb:v046dpc069:name:Logitech USB Laser Mouse:
 # Logitech V500 Cordless Notebook Mouse
 mouse:usb:v046dpc510:name:Logitech USB Receiver:
 # Logitech M560 Wireless Mouse
@@ -340,8 +341,6 @@ mouse:usb:v046dp1024:name:Logitech M310:
 
 # Logitech USB Laser Mouse M-UAS144 [LS1 Laser Mouse]
 mouse:usb:v046dpc062:name:Logitech USB Laser Mouse:
-# Logitech USB Laser Mouse M-U0007
-mouse:usb:v046dpc069:name:Logitech USB Laser Mouse:
  MOUSE_DPI=1200@125
 
 # Logitech T620 (or, the soap)
index 9d288e38fd1350c9ac01fd03af924df9dd410414..b2af467d5f5426705e066b1febb0804afe0feb6c 100644 (file)
@@ -37,8 +37,7 @@
 #   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
-# (or /dev/input/event*).
+#   udevadm info /dev/input/eventXX.
 #
 # Allowed properties are:
 #   POINTINGSTICK_CONST_ACCEL
 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:pvr*
   POINTINGSTICK_CONST_ACCEL=0.5
 
+# Latitude E6320
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr*
+  POINTINGSTICK_CONST_ACCEL=2.0
+
 # Latitude E6400
 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr*
   POINTINGSTICK_CONST_ACCEL=1.5
index db5df250f451054441b216f6372baa784b12502d..51ac88be61875444b52737cf85141d8de2255adf 100644 (file)
@@ -43,7 +43,7 @@ AC_DEFUN([CC_CHECK_FLAG_APPEND], [
   AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
                  AS_TR_SH([cc_cv_$2_$3]),
           [eval "AS_TR_SH([cc_save_$2])='${$2}'"
-           eval "AS_TR_SH([$2])='-Werror `echo "$3" | sed 's/^-Wno-/-W/'`'"
+           eval "AS_TR_SH([$2])='${cc_save_$2} -Werror `echo "$3" | sed 's/^-Wno-/-W/'`'"
            AC_LINK_IFELSE([AC_LANG_SOURCE(ifelse([$4], [],
                                                  [int main(void) { return 0; } ],
                                                  [$4]))],
index bf5eeab938eccf6b69180572ad89f747232bba3a..d928e5a83fd8248e078ee50bf18b30f02e9aad7f 100644 (file)
@@ -1,4 +1,5 @@
 /systemd.directives.xml
 /systemd.index.xml
 /*.[13578]
+/*.html
 /custom-entities.ent
index d8c1085021e5c5a645d89e2b9a5dc034b2113942..26d778d4dd30a0c94595a299cd4088426eb3551c 100644 (file)
@@ -448,7 +448,7 @@ ARRAY "s" {
     <example>
       <title>Invoking a Method</title>
 
-      <para>The following command invokes the
+      <para>The following command invokes the
       <literal>StartUnit</literal> method on the
       <literal>org.freedesktop.systemd1.Manager</literal>
       interface of the
index 84c23014e4bf255e045828a72ab933dd288687f1..e89d73e7f1dc9f126aba781bc5f11a2f4869876c 100644 (file)
@@ -37,7 +37,8 @@
 <xsl:template match="citerefentry[not(@project)]">
   <a>
     <xsl:attribute name="href">
-      <xsl:value-of select="refentrytitle"/><xsl:text>.html</xsl:text>
+      <xsl:value-of select="refentrytitle"/><xsl:text>.html#</xsl:text>
+      <xsl:value-of select="refentrytitle/@target"/>
     </xsl:attribute>
     <xsl:call-template name="inline.charseq"/>
   </a>
diff --git a/man/dnssec-trust-anchors.d.xml b/man/dnssec-trust-anchors.d.xml
new file mode 100644 (file)
index 0000000..4bdc167
--- /dev/null
@@ -0,0 +1,200 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="dnssec-trust-anchors.d" conditional='ENABLE_RESOLVED'
+    xmlns:xi="http://www.w3.org/2001/XInclude">
+  <refentryinfo>
+    <title>dnssec-trust-anchors.d</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>dnssec-trust-anchors.d</refentrytitle>
+    <manvolnum>5</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>dnssec-trust-anchors.d</refname>
+    <refname>systemd.positive</refname>
+    <refname>systemd.negative</refname>
+    <refpurpose>DNSSEC trust anchor configuration files</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <para><filename>/etc/dnssec-trust-anchors.d/*.positive</filename></para>
+    <para><filename>/run/dnssec-trust-anchors.d/*.positive</filename></para>
+    <para><filename>/usr/lib/dnssec-trust-anchors.d/*.positive</filename></para>
+    <para><filename>/etc/dnssec-trust-anchors.d/*.negative</filename></para>
+    <para><filename>/run/dnssec-trust-anchors.d/*.negative</filename></para>
+    <para><filename>/usr/lib/dnssec-trust-anchors.d/*.negative</filename></para>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>The DNSSEC trust anchor configuration files define positive
+    and negative trust anchors
+    <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    bases DNSSEC integrity proofs on.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Positive Trust Anchors</title>
+
+    <para>Positive trust anchor configuration files contain DNSKEY and
+    DS resource record definitions to use as base for DNSSEC integrity
+    proofs. See <ulink
+    url="https://tools.ietf.org/html/rfc4035#section-4.4">RFC 4035,
+    Section 4.4</ulink> for more information about DNSSEC trust
+    anchors.</para>
+
+    <para>Positive trust anchors are read from files with the suffix
+    <filename>.positive</filename> located in
+    <filename>/etc/dnssec-trust-anchors.d/</filename>,
+    <filename>/run/dnssec-trust-anchors.d/</filename> and
+    <filename>/usr/lib/dnssec-trust-anchors.d/</filename>. These
+    directories are searched in the specified order, and a trust
+    anchor file of the same name in an earlier path overrides a trust
+    anchor files in a later path. To disable a trust anchor file
+    shipped in <filename>/usr/lib/dnssec-trust-anchors.d/</filename>
+    it is sufficient to provide an identically-named file in
+    <filename>/etc/dnssec-trust-anchors.d/</filename> or
+    <filename>/run/dnssec-trust-anchors.d/</filename> that is either
+    empty or a symlink to <filename>/dev/null</filename> ("masked").</para>
+
+    <para>Positive trust anchor files are simple text files resembling
+    DNS zone files, as documented in <ulink
+    url="https://tools.ietf.org/html/rfc1035#section-5">RFC 1035, Section
+    5</ulink>. One DS or DNSKEY resource record may be listed per
+    line. Empty lines and lines starting with a semicolon
+    (<literal>;</literal>) are ignored and considered comments. A DS
+    resource record is specified like in the following example:</para>
+
+    <programlisting>. IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5</programlisting>
+
+    <para>The first word specifies the domain, use
+    <literal>.</literal> for the root domain. The domain may be
+    specified with or without trailing dot, which is considered
+    equivalent. The second word must be <literal>IN</literal> the
+    third word <literal>DS</literal>. The following words specify the
+    key tag, signature algorithm, digest algorithm, followed by the
+    hex-encoded key fingerprint. See <ulink
+    url="https://tools.ietf.org/html/rfc4034#section-5">RFC 4034,
+    Section 5</ulink> for details about the precise syntax and meaning
+    of these fields.</para>
+
+    <para>Alternatively, DNSKEY resource records may be used to define
+    trust anchors, like in the following example:</para>
+
+    <programlisting>. IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=</programlisting>
+
+    <para>The first word specifies the domain again, the second word
+    must be <literal>IN</literal>, followed by
+    <literal>DNSKEY</literal>. The subsequent words encode the DNSKEY
+    flags, protocol and algorithm fields, followed by the key data
+    encoded in Base64. See <ulink
+    url="https://tools.ietf.org/html/rfc4034#section-2">RFC 4034,
+    Section 2</ulink> for details about the precise syntax and meaning
+    of these fields.</para>
+
+    <para>If multiple DS or DNSKEY records are defined for the same
+    domain (possibly even in different trust anchor files), all keys
+    are used and are considered equivalent as base for DNSSEC
+    proofs.</para>
+
+    <para>Note that <filename>systemd-resolved</filename> will
+    automatically use a built-in trust anchor key for the Internet
+    root domain if no positive trust anchors are defined for the root
+    domain. In most cases it is hence unnecessary to define an
+    explicit key with trust anchor files. The built-in key is disabled
+    as soon as at least one trust anchor key for the root domain is
+    defined in trust anchor files.</para>
+
+    <para>It is generally recommended to encode trust anchors in DS
+    resource records, rather than DNSKEY resource records.</para>
+
+    <para>If a trust anchor specified via a DS record is found revoked
+    it is automatically removed from the trust anchor database for the
+    runtime. See <ulink url="https://tools.ietf.org/html/rfc5011">RFC
+    5011</ulink> for details about revoked trust anchors. Note that
+    <filename>systemd-resolved</filename> will not update its trust
+    anchor database from DNS servers automatically. Instead, it is
+    recommended to update the resolver software or update the new
+    trust anchor via adding in new trust anchor files.</para>
+
+    <para>The current DNSSEC trust anchor for the Internet's root
+    domain is available at the <ulink
+    url="https://data.iana.org/root-anchors/root-anchors.xml">IANA
+    Trust Anchor and Keys</ulink> page.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Negative Trust Anchors</title>
+
+    <para>Negative trust anchors define domains where DNSSEC
+    validation shall be turned off. Negative trust anchor files are
+    found at the same location as positive trust anchor files, and
+    follow the same overriding rules. They are text files with the
+    <filename>.negative</filename> suffix. Empty lines and lines whose
+    first character is <literal>;</literal> are ignored. Each line
+    specifies one domain name where DNSSEC validation shall be
+    disabled on.</para>
+
+    <para>Negative trust anchors are useful to support private DNS
+    subtrees that are not referenced from the Internet DNS hierarchy,
+    and not signed.</para>
+
+    <para><ulink url="https://tools.ietf.org/html/rfc7646">RFC
+    7646</ulink> for details on negative trust anchors.</para>
+
+    <para>If no negative trust anchor files are configured a built-in
+    set of well-known private DNS zone domains is used as negative
+    trust anchors.</para>
+
+    <para>It is also possibly to define per-interface negative trust
+    anchors using the <varname>DNSSECNegativeTrustAnchors=</varname>
+    setting in
+    <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    files.</para>
+  </refsect1>
+
+  <refsect1>
+      <title>See Also</title>
+      <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      </para>
+  </refsect1>
+
+</refentry>
index 345c56cefa772ba2a2613f58bf315f513b5a16f7..538a592f8da6c8ce55d1cbbf253fb5611934d0f2 100644 (file)
@@ -63,7 +63,7 @@
     and restrictions systemd makes on the file system
     hierarchy.</para>
 
-    <para>Many of the paths described here are queriable
+    <para>Many of the paths described here can be queried
     with the
     <citerefentry><refentrytitle>systemd-path</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     tool.</para>
index 9688450e1c2bf8180802d2c4ee4a7fb2a9489e35..8a4c0d5ac0cf16c4c6241e2719c66243922c927c 100644 (file)
     for DNS domain name labels, even though this is not a strict
     requirement.</para>
 
-    <para>Depending on the operating system, other configuration files
-    might be checked for configuration of the hostname as well,
-    however only as fallback.</para>
-
     <para>You may use
     <citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     to change the value of this file during runtime from the command
index b1f038156d62541571cd9541798243e8614a8e4f..60004e9d041bacf452306ead8737353c664c8acd 100644 (file)
     high-level "pretty" hostname which might include all kinds of
     special characters (e.g. "Lennart's Laptop"), the static hostname
     which is used to initialize the kernel hostname at boot (e.g.
-    "lennarts-laptop"), and the transient hostname which is a default
-    received from network configuration. If a static hostname is set,
-    and is valid (something other than localhost), then the transient
-    hostname is not used.</para>
+    "lennarts-laptop"), and the transient hostname which is a fallback
+    value received from network configuration. If a static hostname is
+    set, and is valid (something other than localhost), then the
+    transient hostname is not used.</para>
 
     <para>Note that the pretty hostname has little restrictions on the
     characters used, while the static and transient hostnames are
index fc60258d0b9222e91d190a9a3cdb8933711030fb..2d345963d946d0e4c95097becce3ef9123419719 100644 (file)
     <literal>[Remote]</literal> section:</para>
 
     <variablelist>
+      <varlistentry>
+        <term><varname>Seal=</varname></term>
+
+        <listitem><para>Periodically sign the data in the journal using Forward Secure Sealing.
+        </para></listitem>
+      </varlistentry>
+
 
       <varlistentry>
         <term><varname>SplitMode=</varname></term>
   <refsect1>
       <title>See Also</title>
       <para>
-        <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+        <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       </para>
index b57afb6ebfbcefef384c127a6a8e94e2d0f212b7..b281f26b45eb68bb270addc823b9bff52f8d077d 100644 (file)
       paths may be specified. If a file path refers to an executable
       file, this is equivalent to an <literal>_EXE=</literal> match
       for the canonicalized binary path. Similarly, if a path refers
-      to a device node, this is equivalent to a
-      <literal>_KERNEL_DEVICE=</literal> match for the device.</para>
+      to a device node then match is added for the kernel name of the
+      device (<literal>_KERNEL_DEVICE=</literal>). Also, matches for the
+      kernel names of all the parent devices are added automatically.
+      Device node paths are not stable across reboots, therefore match
+      for the current boot id (<literal>_BOOT_ID=</literal>) is
+      always added as well. Note that only the log entries for
+      the existing device nodes maybe queried by providing path to
+      the device node.</para>
 
       <para>Additional constraints may be added using options
       <option>--boot</option>, <option>--unit=</option>, etc., to
         field can take in all entries of the journal.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>-N</option></term>
+        <term><option>--fields</option></term>
+
+        <listitem><para>Print all field names currently used in all entries of the journal.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--system</option></term>
         <term><option>--user</option></term>
index 309220632e3c5877b98c2c9890fbaae8b38d1b1e..42d5e006bb77736a91572ff6625cb88621b4a205 100644 (file)
@@ -91,6 +91,7 @@
         <term><varname>systemd.default_standard_output=</varname></term>
         <term><varname>systemd.default_standard_error=</varname></term>
         <term><varname>systemd.setenv=</varname></term>
+        <term><varname>systemd.machine_id=</varname></term>
         <listitem>
           <para>Parameters understood by the system and service
           manager to control system behavior. For details, see
index 94376656d5ea90c3e9938b10a6cbdab74c51c110..597759e33a9dd4822c7f0bdb9597bf264f27c0f5 100644 (file)
         <varname>TasksMax=</varname> setting of the per-user slice
         unit, see
         <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-        for details. Defaults to 4096.</para></listitem>
+        for details. Defaults to 12288 (12K).</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><varname>RemoveIPC=</varname></term>
 
-        <listitem><para>Controls whether System V and POSIX IPC
-        objects belonging to the user shall be removed when the user
-        fully logs out. Takes a boolean argument. If enabled, the user
-        may not consume IPC resources after the last of the user's
-        sessions terminated. This covers System V semaphores, shared
-        memory and message queues, as well as POSIX shared memory and
-        message queues. Note that IPC objects of the root user are
-        excluded from the effect of this setting. Defaults to
-        <literal>yes</literal>.</para></listitem>
+        <listitem><para>Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the
+        user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the
+        last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as
+        well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users
+        are excluded from the effect of this setting. Defaults to <literal>yes</literal>.</para></listitem>
       </varlistentry>
 
     </variablelist>
index db72c2a01cad8a879276bb4afdd090e67d820a9c..d318ec54eca78335b06e5a1cc582866db7b2508b 100644 (file)
     at install time. Use
     <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     to initialize it on mounted (but not booted) system images.</para>
+
+    <para>The machine-id may also be set, for example when network
+    booting, by setting the <varname>systemd.machine_id=</varname>
+    kernel command line parameter or passing the option
+    <option>--machine-id=</option> to systemd. A machine-id may not
+    be set to all zeros.</para>
   </refsect1>
 
   <refsect1>
index 0e18953700396d99846c40b18aa4aef624628e20..0e07c201bdb9e0d86b42e023bc34adeaba5e29a9 100644 (file)
         <literal>checksum</literal> is specified, the download is
         checked for integrity after the transfer is complete, but no
         signatures are verified. If <literal>signature</literal> is
-        specified, the checksum is verified and the images's signature
+        specified, the checksum is verified and the image's signature
         is checked against a local keyring of trustable vendors. It is
         strongly recommended to set this option to
         <literal>signature</literal> if the server and protocol
         image.</para></listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><option>--dkr-index-url</option></term>
-
-        <listitem><para>Specifies the index server to use for
-        downloading <literal>dkr</literal> images with the
-        <command>pull-dkr</command>. Takes a
-        <literal>http://</literal>, <literal>https://</literal>
-        URL.</para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><option>--format=</option></term>
 
         below.</para></listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><command>pull-dkr</command> <replaceable>REMOTE</replaceable> [<replaceable>NAME</replaceable>]</term>
-
-        <listitem><para>Downloads a <literal>dkr</literal> container
-        image and makes it available locally. The remote name refers
-        to a <literal>dkr</literal> container name. If omitted, the
-        local machine name is derived from the <literal>dkr</literal>
-        container name.</para>
-
-        <para>Image verification is not available for
-        <literal>dkr</literal> containers, and thus
-        <option>--verify=no</option> must always be specified with
-        this command.</para>
-
-        <para>This command downloads all (missing) layers for the
-        specified container and places them in read-only subvolumes in
-        <filename>/var/lib/machines/</filename>. A writable snapshot
-        of the newest layer is then created under the specified local
-        machine name. To omit creation of this writable snapshot, pass
-        <literal>-</literal> as local machine name.</para>
-
-        <para>The read-only layer subvolumes are prefixed with
-        <filename>.dkr-</filename>, and thus not shown by
-        <command>list-images</command>, unless <option>--all</option>
-        is passed.</para>
-
-        <para>To specify the <literal>dkr</literal> index server to
-        use for looking up the specified container, use
-        <option>--dkr-index-url=</option>.</para>
-
-        <para>Note that pressing C-c during execution of this command
-        will not abort the download. Use
-        <command>cancel-transfer</command>, described
-        below.</para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><command>import-tar</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term>
         <term><command>import-raw</command> <replaceable>FILE</replaceable> [<replaceable>NAME</replaceable>]</term>
         image is read from standard input, in which case the second
         argument is mandatory.</para>
 
-        <para>Similar as with <command>pull-tar</command>,
-        <command>pull-raw</command> the file system
-        <filename>/var/lib/machines.raw</filename> is increased in
-        size of necessary and appropriate. Optionally, the
+        <para>Both <command>pull-tar</command> and <command>pull-raw</command>
+        will resize <filename>/var/lib/machines.raw</filename> and the
+        filesystem therein as necessary. Optionally, the
         <option>--read-only</option> switch may be used to create a
         read-only container or VM image. No cryptographic validation
         is done when importing the images.</para>
     <para>Note that many image operations are only supported,
     efficient or atomic on btrfs file systems. Due to this, if the
     <command>pull-tar</command>, <command>pull-raw</command>,
-    <command>pull-dkr</command>, <command>import-tar</command>,
-    <command>import-raw</command> and <command>set-limit</command>
-    commands notice that <filename>/var/lib/machines</filename> is
-    empty and not located on btrfs, they will implicitly set up a
-    loopback file <filename>/var/lib/machines.raw</filename>
-    containing a btrfs file system that is mounted to
+    <command>import-tar</command>, <command>import-raw</command> and
+    <command>set-limit</command> commands notice that
+    <filename>/var/lib/machines</filename> is empty and not located on
+    btrfs, they will implicitly set up a loopback file
+    <filename>/var/lib/machines.raw</filename> containing a btrfs file
+    system that is mounted to
     <filename>/var/lib/machines</filename>. The size of this loopback
     file may be controlled dynamically with
     <command>set-limit</command>.</para>
       login prompt into the container is requested.</para>
     </example>
 
-    <example>
-      <title>Download a Fedora <literal>dkr</literal> image</title>
-
-      <programlisting># machinectl pull-dkr --verify=no mattdm/fedora
-# systemd-nspawn -M fedora</programlisting>
-
-      <para>Downloads a <literal>dkr</literal> image and opens a shell
-      in it. Note that the specified download command might require an
-      index server to be specified with the
-      <literal>--dkr-index-url=</literal>.</para>
-    </example>
-
     <example>
       <title>Exports a container image as tar file</title>
 
index 859bec29e3ec5dc0fe7dc895da7558cc0debab81..251bdecbad1f993a45bce7180d0682249a2bf8c4 100644 (file)
@@ -71,9 +71,9 @@
       is on the local loopback) and the IPv6 address ::1 (which is the
       local host).</para></listitem>
 
-      <listitem><para>The hostname <literal>localhost</literal> is
-      resolved to the IP addresses 127.0.0.1 and
-      ::1.</para></listitem>
+      <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
+      <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
+      resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
 
       <listitem><para>The hostname <literal>gateway</literal> is
       resolved to all current default routing gateway addresses,
index 811e33f4fa4370dd2b242b09ca580cad02e9aa88..920ce9e89b2f99e51e775541485d1092fc373131 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
   <refsect1>
     <title>Options</title>
 
+    <para>The following options are available in the <literal>[Resolve]</literal> section:</para>
+
     <variablelist class='network-directives'>
 
       <varlistentry>
         <term><varname>DNS=</varname></term>
-        <listitem><para>A space-separated list of IPv4 and IPv6
-        addresses to be used as system DNS servers. DNS requests are
-        sent to one of the listed DNS servers in parallel to any
-        per-interface DNS servers acquired from
-        <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-        For compatibility reasons, if set to the empty list, the DNS
-        servers listed in <filename>/etc/resolv.conf</filename> are
-        used, if any are configured there. This setting defaults to
-        the empty list.</para></listitem>
+        <listitem><para>A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. DNS requests
+        are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from
+        <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
+        set at runtime by external applications.  For compatibility reasons, if this setting is not specified, the DNS
+        servers listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any servers
+        are configured in it. This setting defaults to the empty list.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><varname>FallbackDNS=</varname></term>
-        <listitem><para>A space-separated list of IPv4 and IPv6
-        addresses to be used as the fallback DNS servers. Any
-        per-interface DNS servers obtained from
+        <listitem><para>A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any
+        per-link DNS servers obtained from
         <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        take precedence over this setting, as do any servers set via
-        <varname>DNS=</varname> above or
-        <filename>/etc/resolv.conf</filename>. This setting is hence
-        only used if no other DNS server information is known. If this
-        option is not given, a compiled-in list of DNS servers is used
-        instead.</para></listitem>
+        take precedence over this setting, as do any servers set via <varname>DNS=</varname> above or
+        <filename>/etc/resolv.conf</filename>. This setting is hence only used if no other DNS server information is
+        known. If this option is not given, a compiled-in list of DNS servers is used instead.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>Domains=</varname></term>
+        <listitem><para>A space-separated list of domains. These domains are used as search suffixes when resolving
+        single-label host names (domain names which contain no dot), in order to qualify them into fully-qualified
+        domain names (FQDNs). Search domains are strictly processed in the order they are specified, until the name
+        with the suffix appended is found. For compatibility reasons, if this setting is not specified, the search
+        domains listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any domains
+        are configured in it. This setting defaults to the empty list.</para>
+
+        <para>Specified domain names may optionally be prefixed with <literal>~</literal>. In this case they do not
+        define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured
+        with the system <varname>DNS=</varname> setting (see above), in case additional, suitable per-link DNS servers
+        are known. If no per-link DNS servers are known using the <literal>~</literal> syntax has no effect. Use the
+        construct <literal>~.</literal> (which is composed of <literal>~</literal> to indicate a routing domain and
+        <literal>.</literal> to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the
+        system DNS server defined with <varname>DNS=</varname> preferably for all domains.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <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-interface LLMNR settings. LLMNR will be
-        enabled on an interface only if the per-interface and the
+        also maintains per-link LLMNR settings. LLMNR 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
+        <literal>allow-downgrade</literal>. If true all DNS lookups are
+        DNSSEC-validated locally (excluding LLMNR and Multicast
+        DNS). If the response to a lookup request is detected to be invalid
+        a lookup failure is returned to applications. Note that
+        this mode requires a DNS server that supports DNSSEC. If the
+        DNS server does not properly support DNSSEC all validations
+        will fail. If set to <literal>allow-downgrade</literal> DNSSEC
+        validation is attempted, but if the server does not support
+        DNSSEC properly, DNSSEC mode is automatically disabled. Note
+        that this mode makes DNSSEC validation vulnerable to
+        "downgrade" attacks, where an attacker might be able to
+        trigger a downgrade to non-DNSSEC mode by synthesizing a DNS
+        response that suggests DNSSEC was not supported. If set to
+        false, DNS lookups are not DNSSEC validated.</para>
+
+        <para>Note that DNSSEC validation requires retrieval of
+        additional DNS data, and thus results in a small DNS look-up
+        time penalty.</para>
+
+        <para>DNSSEC requires knowledge of "trust anchors" to prove
+        data integrity. The trust anchor for the Internet root domain
+        is built into the resolver, additional trust anchors may be
+        defined with
+        <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+        Trust anchors may change at regular intervals, and old trust
+        anchors may be revoked. In such a case DNSSEC validation is
+        not possible until new trust anchors are configured locally or
+        the resolver software package is updated with the new root
+        trust anchor. In effect, when the built-in trust anchor is
+        revoked and <varname>DNSSEC=</varname> is true, all further
+        lookups will fail, as it cannot be proved anymore whether
+        lookups are correctly signed, or validly unsigned. If
+        <varname>DNSSEC=</varname> is set to
+        <literal>allow-downgrade</literal> the resolver will
+        automatically turn off DNSSEC validation in such a case.</para>
+
+        <para>Client programs looking up DNS data will be informed
+        whether lookups could be verified using DNSSEC, or whether the
+        returned data could not be verified (either because the data
+        was found unsigned in the DNS, or the DNS server did not
+        support DNSSEC or no appropriate trust anchors were known). In
+        the latter case it is assumed that client programs employ a
+        secondary scheme to validate the returned DNS data, should
+        this be required.</para>
+
+        <para>It is recommended to set <varname>DNSSEC=</varname> to
+        true on systems where it is known that the DNS server supports
+        DNSSEC correctly, and where software or trust anchor updates
+        happen regularly. On other systems it is recommended to set
+        <varname>DNSSEC=</varname> to
+        <literal>allow-downgrade</literal>.</para>
+
+        <para>In addition to this global DNSSEC setting
+        <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        also maintains per-link DNSSEC settings. For system DNS
+        servers (see above), only the global DNSSEC setting is in
+        effect. For per-link DNS servers the per-link
+        setting is in effect, unless it is unset in which case the
+        global setting is used instead.</para>
+
+        <para>Site-private DNS zones generally conflict with DNSSEC
+        operation, unless a negative (if the private zone is not
+        signed) or positive (if the private zone is signed) trust
+        anchor is configured for them. If
+        <literal>allow-downgrade</literal> mode is selected, it is
+        attempted to detect site-private DNS zones using top-level
+        domains (TLDs) that are not known by the DNS root server. This
+        logic does not work in all private zone setups.</para>
+
+        <para>Defaults to off.</para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>4</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>4</manvolnum></citerefentry>
       </para>
   </refsect1>
 
diff --git a/man/sd-bus.xml b/man/sd-bus.xml
new file mode 100644 (file)
index 0000000..336dd33
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 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/>.
+-->
+
+<refentry id="sd-bus" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd-bus</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Documentation</contrib>
+        <firstname>Zbigniew</firstname>
+        <surname>Jędrzejewski-Szmek</surname>
+        <email>zbyszek@in.waw.pl</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd-bus</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd-bus</refname>
+    <refpurpose>A lightweight D-Bus and kdbus client library</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+    </funcsynopsis>
+
+    <cmdsynopsis>
+      <command>pkg-config --cflags --libs libsystemd</command>
+    </cmdsynopsis>
+
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><filename>sd-bus.h</filename> provides an implementation
+    of a D-Bus client. It can interoperate both with the traditional
+    <citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+    and with kdbus. See
+    <ulink url="http://www.freedesktop.org/software/dbus/" />
+    for more information about the big picture.
+    </para>
+
+    <important>
+      <para>Interfaces described here have not been declared stable yet,
+      and are not accessible from <filename>libsystemd.so</filename>.
+      This documentation is provided in hope it might be useful for
+      developers, without any guarantees of availability or stability.
+      </para>
+    </important>
+
+    <para>See
+    <citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_append_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_append_string_memfd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_append_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_get_cookie</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_set_address</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_path_encode</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_bus_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for more information about the functions available.</para>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>dbus-send</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <ulink url="https://developer.gnome.org/gio/stable/gdbus.html">gdbus</ulink>
+    </para>
+  </refsect1>
+
+</refentry>
index b7ba363656606d9c6f049e3999e903677d5b66ea..b06d99f34623f2c7e438cf2dac084947025e6371 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para><filename>sd-daemon.h</filename> provide APIs for new-style
+    <para><filename>sd-daemon.h</filename> provides APIs for new-style
     daemons, as implemented by the
     <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    init system.</para>
+    service manager.</para>
 
     <para>See
     <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd-event.xml b/man/sd-event.xml
new file mode 100644 (file)
index 0000000..fc615f0
--- /dev/null
@@ -0,0 +1,187 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd-event" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd-event</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd-event</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd-event</refname>
+    <refpurpose>A generic event loop implementation</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+    </funcsynopsis>
+
+    <cmdsynopsis>
+      <command>pkg-config --cflags --libs libsystemd</command>
+    </cmdsynopsis>
+
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><filename>sd-event.h</filename> provides a generic event
+    loop implementation, based on Linux <citerefentry
+    project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+    </para>
+
+    <para>See
+    <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_get_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for more information about the functions available.</para>
+
+    <para>The event loop design is targeted on running a separate
+    instance of the event loop in each thread; it has no concept of
+    distributing events from a single event loop instance onto
+    multiple worker threads. Dispatching events is strictly ordered
+    and subject to configurable priorities. In each event loop
+    iteration a single event source is dispatched. Each time an event
+    source is dispatched the kernel is polled for new events, before
+    the next event source is dispatched. The event loop is designed to
+    honour priorities and provide fairness within each priority. It is
+    not designed to provide optimal throughput, as this contradicts
+    these goals due the limitations of the underlying <citerefentry
+    project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+    primitives.</para>
+
+    <para>The event loop implementation provides the following features:</para>
+
+    <orderedlist>
+      <listitem><para>I/O event sources, based on <citerefentry
+      project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>'s
+      file descriptor watching, including edge triggered events (<constant>EPOLLET</constant>). See <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>Timer event sources, based on <citerefentry
+      project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      supporting the <constant>CLOCK_MONOTONIC</constant>,
+      <constant>CLOCK_REALTIME</constant>,
+      <constant>CLOCK_BOOTIME</constant> clocks, as well as the
+      <constant>CLOCK_REALTIME_ALARM</constant> and
+      <constant>CLOCK_BOOTTIME_ALARM</constant> clocks that can resume
+      the system from suspend. When creating timer events a required
+      accuracy parameter may be specified which allows coalescing of
+      timer events to minimize power consumption. See <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>UNIX process signal events, based on
+      <citerefentry
+      project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      including full support for real-time signals, and queued parameters. See <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>Child process state change events, based on
+      <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>. See <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>Static event sources, of three types: defer,
+      post and exit, for invoking calls in each event loop, after
+      other event sources or at event loop termination. See
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>Event sources may be assigned a 64bit priority
+      value, that controls the order in which event sources are
+      dispatched if multiple are pending simultaneously. See
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>The event loop may automatically send watchdog
+      notification messages to the service manager. See
+      <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      <listitem><para>The event loop may be integrated into foreign
+      event loops, such as the GLib one. See
+      <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      for an example.</para></listitem>
+    </orderedlist>
+
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_get_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index 9b1a52207fe8c67bb3d009fd7d7b931414027bc0..09747a480c4a526e9e170ca54e21f5427efe00d6 100644 (file)
     <citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
     <citerefentry><refentrytitle>sd_journal_get_usage</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-    <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     and
-    <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     for more information about the functions implemented.</para>
 
     <para>Command line access for submitting entries to the journal is
       <citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_catalog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_has_runtime_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_has_persistent_files</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
index aec12bda164246338bb653f0eb0a5dec84b88376..3bcda46656e3b5b4afd51a7925540c956007494c 100644 (file)
     modified by the caller.</para>
 
     <para>All functions that take a <parameter>char***</parameter>
-    parameter will store the answer there as an address of a an array
+    parameter will store the answer there as an address of an array
     of strings. Each individual string is NUL-terminated, and the
     array is NULL-terminated as a whole. It will be valid as long as
     <parameter>c</parameter> remains valid, and should not be freed or
index 84dd509744360a78d8d4a54d05b5c66b514d86f0..082f7b67db6bc44b500bae640443dee837ae65a9 100644 (file)
@@ -48,6 +48,7 @@
     <refname>sd_bus_creds_get_augmented_mask</refname>
     <refname>sd_bus_creds_ref</refname>
     <refname>sd_bus_creds_unref</refname>
+    <refname>sd_bus_creds_unrefp</refname>
 
     <refpurpose>Retrieve credentials object for the specified PID</refpurpose>
   </refnamediv>
         <funcdef>sd_bus_creds *<function>sd_bus_creds_unref</function></funcdef>
         <paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
       </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_bus_creds_unrefp</function></funcdef>
+        <paramdef>sd_bus_creds **<parameter>c</parameter></paramdef>
+      </funcprototype>
     </funcsynopsis>
 
     <para>
 
     <para><function>sd_bus_creds_unref()</function> destroys a reference
     to <parameter>c</parameter>.</para>
+
+    <para><function>sd_bus_creds_unrefp()</function> is similar to
+    <function>sd_bus_creds_unref()</function> but takes a pointer to a
+    pointer to an <type>sd_bus_creds</type> object. This call is useful in
+    conjunction with GCC's and LLVM's <ulink
+    url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+    Variable Attribute</ulink>. Note that this function is defined as
+    inline function.</para>
+
+    <para><function>sd_bus_creds_ref()</function>,
+    <function>sd_bus_creds_unref()</function> and
+    <function>sd_bus_creds_unrefp()</function> execute no operation if
+    the passed in bus credentials object is
+    <constant>NULL</constant>.</para>
+
   </refsect1>
 
   <refsect1>
index e1cab6e567b1cfd782619ad35a3a9bd7177bbd76..d281b5dd44d123c4e9bb4c59af0d488f9d4c9fd6 100644 (file)
@@ -46,6 +46,7 @@
     <refname>sd_bus_new</refname>
     <refname>sd_bus_ref</refname>
     <refname>sd_bus_unref</refname>
+    <refname>sd_bus_unrefp</refname>
 
     <refpurpose>Create a new bus object and create or destroy references to it</refpurpose>
   </refnamediv>
         <funcdef>sd_bus *<function>sd_bus_unref</function></funcdef>
         <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
       </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_bus_unrefp</function></funcdef>
+        <paramdef>sd_bus **<parameter>bus</parameter></paramdef>
+      </funcprototype>
     </funcsynopsis>
   </refsynopsisdiv>
 
     only allocate a bus object but also start the connection to a
     well-known bus in a single function invocation.</para>
 
-    <para><function>sd_bus_ref()</function> creates a new reference to
-    <parameter>bus</parameter>.</para>
+    <para><function>sd_bus_ref()</function> increases the reference
+    counter of <parameter>bus</parameter> by one.</para>
 
-    <para><function>sd_bus_unref()</function> destroys a reference to
-    <parameter>bus</parameter>. Once the reference count has dropped
-    to zero, <parameter>bus</parameter> cannot be used anymore, so
-    further calls to <function>sd_bus_ref()</function> or
+    <para><function>sd_bus_unref()</function> decreases the reference
+    counter of <parameter>bus</parameter> by one. Once the reference
+    count has dropped to zero, <parameter>bus</parameter> is destroyed
+    and cannot be used anymore, so further calls to
+    <function>sd_bus_ref()</function> or
     <function>sd_bus_unref()</function> are illegal.</para>
+
+    <para><function>sd_bus_unrefp()</function> is similar to
+    <function>sd_bus_unref()</function> but takes a pointer to a
+    pointer to an <type>sd_bus</type> object. This call is useful in
+    conjunction with GCC's and LLVM's <ulink
+    url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+    Variable Attribute</ulink>. Note that this function is defined as
+    inline function. Use a declaration like the following, in order to
+    allocate a bus object that is freed automatically as the code
+    block is left:</para>
+
+    <programlisting>{
+        __attribute__((cleanup(sd_bus_unrefp)) sd_bus *bus = NULL;
+        int r;
+        …
+        r = sd_bus_default(&amp;bus);
+        if (r &lt; 0)
+                fprintf(stderr, "Failed to allocate bus: %s\n", strerror(-r));
+        …
+}</programlisting>
+
+    <para><function>sd_bus_ref()</function>,
+    <function>sd_bus_unref()</function> and
+    <function>sd_bus_unrefp()</function> execute no operation if the
+    passed in bus object is <constant>NULL</constant>.</para>
   </refsect1>
 
   <refsect1>
     positive integer. On failure, it returns a negative errno-style
     error code.</para>
 
-    <para><function>sd_bus_ref</function> always returns the argument.
+    <para><function>sd_bus_ref()</function> always returns the argument.
     </para>
 
-    <para><function>sd_bus_unref</function> always returns
+    <para><function>sd_bus_unref()</function> always returns
     <constant>NULL</constant>.</para>
   </refsect1>
 
index 77bec4e706aa6da0931c1566be49c5a295acd7f2..bc732db7fa4a7d6de1331e7627180800273ac5db 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_add_child">
+<refentry id="sd_event_add_child" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_add_child</title>
   <refnamediv>
     <refname>sd_event_add_child</refname>
     <refname>sd_event_source_get_child_pid</refname>
+    <refname>sd_event_child_handler_t</refname>
 
-    <refpurpose>Add a child state change event source to an event loop</refpurpose>
+    <refpurpose>Add a child process state change event source to an event loop</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_child_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>const siginfo_t *<parameter>si</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_add_child</function></funcdef>
         <paramdef>void *<parameter>userdata</parameter></paramdef>
       </funcprototype>
 
-      <funcprototype>
-        <funcdef>typedef int (*<function>sd_event_child_handler_t</function>)</funcdef>
-        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
-        <paramdef>const siginfo_t *<parameter>si</parameter></paramdef>
-        <paramdef>void *<parameter>userdata</parameter></paramdef>
-      </funcprototype>
-
       <funcprototype>
         <funcdef>int <function>sd_event_source_get_child_pid</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
     <title>Description</title>
 
     <para><function>sd_event_add_child()</function> adds a new child
-    state change event source to an event loop object. The event loop
-    is specified in <parameter>event</parameter>, the event source is
-    returned in the <parameter>source</parameter> parameter. The
-    <parameter>pid</parameter> parameter specifies the process to
-    watch. The <parameter>handler</parameter> must reference a
-    function to call when the process changes state. The handler
-    function will be passed the <parameter>userdata</parameter>
-    pointer, which may be chosen freely by the caller. The handler
-    also receives a pointer to a <structname>const
-    siginfo_t</structname> structure containing the information about
-    the event. The <parameter>options</parameter> parameter determines
-    which state changes will be watched for. It must contain an OR-ed
-    mask of <constant>WEXITED</constant> (watch for the child
+    process state change event source to an event loop. The event loop
+    object is specified in the <parameter>event</parameter> parameter,
+    the event source object is returned in the
+    <parameter>source</parameter> parameter. The
+    <parameter>pid</parameter> parameter specifies the PID of the
+    process to watch. The <parameter>handler</parameter> must
+    reference a function to call when the process changes state. The
+    handler function will be passed the
+    <parameter>userdata</parameter> pointer, which may be chosen
+    freely by the caller. The handler also receives a pointer to a
+    <structname>siginfo_t</structname> structure containing
+    information about the child process event. The
+    <parameter>options</parameter> parameter determines which state
+    changes will be watched for. It must contain an OR-ed mask of
+    <constant>WEXITED</constant> (watch for the child process
     terminating), <constant>WSTOPPED</constant> (watch for the child
-    being stopped by a signal), and <constant>WCONTINUED</constant>
-    (watch for the child being resumed by a signal). See
-    <citerefentry><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    process being stopped by a signal), and
+    <constant>WCONTINUED</constant> (watch for the child process being
+    resumed by a signal). See <citerefentry
+    project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     for further information.</para>
 
     <para>Only a single handler may be installed for a specific
-    child. The handler is enabled
-    for a single event (<constant>SD_EVENT_ONESHOT</constant>),
-    but this may be
-    changed with
+    child process. The handler is enabled for a single event
+    (<constant>SD_EVENT_ONESHOT</constant>), but this may be changed
+    with
     <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
     If the handler function returns a negative error code, it will be
-    disabled after the invocation, even if
-    <constant>SD_EVENT_ON</constant> mode is set.
+    disabled after the invocation, even if the
+    <constant>SD_EVENT_ON</constant> mode was requested before.
     </para>
 
+    <para>To destroy an event source object use
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    but note that the event source is only removed from the event loop
+    when all references to the event source are dropped. To make sure
+    an event source does not fire anymore, even when there's still a
+    reference to it kept, consider setting the event source to
+    <constant>SD_EVENT_OFF</constant> with
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+    <para>If the second parameter of
+    <function>sd_event_add_child()</function> is passed as NULL no
+    reference to the event source object is returned. In this case the
+    event source is considered "floating", and will be destroyed
+    implicitly when the event loop itself is destroyed.</para>
+
+    <para>Note that the <parameter>handler</parameter> function is
+    invoked at a time where the child process is not reaped yet (and
+    thus still is exposed as a zombie process by the kernel). However,
+    the child will be reaped automatically after the function
+    returns. Child processes for which no child process state change
+    event sources are installed will not be reaped by the event loop
+    implementation.</para>
+
+    <para>If both a child process state change event source and a
+    <constant>SIGCHLD</constant> signal event source is installed in
+    the same event loop, the configured event source priorities decide
+    which event source is dispatched first. If the signal handler is
+    processed first, it should leave the child processes for which
+    child process state change event sources are installed unreaped.</para>
+
     <para><function>sd_event_source_get_child_pid()</function>
-    retrieves the configured <parameter>pid</parameter> of a child
-    state change event source created previously with
+    retrieves the configured PID of a child process state change event
+    source created previously with
     <function>sd_event_add_child()</function>. It takes the event
     source object as the <parameter>source</parameter> parameter and a
-    pointer to <type>pid_t</type> to return the result in.
+    pointer to a <type>pid_t</type> variable to return the process ID
+    in.
     </para>
   </refsect1>
 
         <term><constant>-EBUSY</constant></term>
 
         <listitem><para>A handler is already installed for this
-        child.</para></listitem>
+        child process.</para></listitem>
 
       </varlistentry>
 
 
       </varlistentry>
 
-    </variablelist>
-  </refsect1>
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
 
-  <refsect1>
-    <title>Notes</title>
+        <listitem><para>The passed event source is not a child process event source.</para></listitem>
+      </varlistentry>
 
-    <para><function>sd_event_add_child()</function> and the other functions
-    described here are available as a shared library, which can be
-    compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
+    </variablelist>
   </refsect1>
 
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
   <refsect1>
     <title>See Also</title>
 
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 826f2fd224a5654083b5ad3e19e329b23f363402..d9ebd3b179a85401eef2a2fc2f591926602805e3 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_add_defer">
+<refentry id="sd_event_add_defer" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_add_defer</title>
     <refname>sd_event_add_defer</refname>
     <refname>sd_event_add_post</refname>
     <refname>sd_event_add_exit</refname>
+    <refname>sd_event_handler_t</refname>
 
     <refpurpose>Add static event sources to an event loop</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_add_defer</function></funcdef>
         <paramdef>void *<parameter>userdata</parameter></paramdef>
       </funcprototype>
 
-      <funcprototype>
-        <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
-        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
-        <paramdef>void *<parameter>userdata</parameter></paramdef>
-      </funcprototype>
-
     </funcsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
     <title>Description</title>
 
-    <para>These three functions add new event sources to an event loop
-    object. The event loop is specified in
-    <parameter>event</parameter>, the event source is returned in the
-    <parameter>source</parameter> parameter. The event sources are
-    enabled statically and will "fire" when the event loop is run and
-    the conditions described below are met. The handler function will
-    be passed the <parameter>userdata</parameter> pointer, which may
-    be chosen freely by the caller.</para>
+    <para>These three functions add new static event sources to an
+    event loop. The event loop object is specified in the
+    <parameter>event</parameter> parameter, the event source object is
+    returned in the <parameter>source</parameter> parameter. The event
+    sources are enabled statically and will "fire" when the event loop
+    is run and the conditions described below are met. The handler
+    function will be passed the <parameter>userdata</parameter>
+    pointer, which may be chosen freely by the caller.</para>
 
     <para><function>sd_event_add_defer()</function> adds a new event
-    source that will "fire" the next time the event loop is run. By
-    default, the handler will be called once
-    (<constant>SD_EVENT_ONESHOT</constant>).</para>
+    source that will be dispatched instantly, before the event loop
+    goes to sleep again and waits for new events. By default, the
+    handler will be called once
+    (<constant>SD_EVENT_ONESHOT</constant>). Note that if the event
+    source is set to <constant>SD_EVENT_ON</constant> the event loop
+    will never go to sleep again, but continuously call the handler,
+    possibly interleaved with other event sources.</para>
 
     <para><function>sd_event_add_post()</function> adds a new event
-    source that will "fire" if any event handlers are invoked whenever
-    the event loop is run. By default, the source is enabled
-    permanently (<constant>SD_EVENT_ON</constant>).</para>
+    source that is run before the event loop will sleep and wait
+    for new events, but only after at least one other non-post event
+    source was dispatched. By default, the source is enabled
+    permanently (<constant>SD_EVENT_ON</constant>). Note that this
+    event source type will still allow the event loop to go to sleep
+    again, even if set to <constant>SD_EVENT_ON</constant>, as long as
+    no other event source is ever triggered.</para>
 
     <para><function>sd_event_add_exit()</function> adds a new event
-    source that will "fire" when the event loop is terminated
-    with <function>sd_event_exit()</function>.</para>
+    source that will be dispatched when the event loop is terminated
+    with <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
 
     <para>The
     <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     function may be used to enable the event source permanently
     (<constant>SD_EVENT_ON</constant>) or to make it fire just once
-    (<constant>SD_EVENT_ONESHOT</constant>). If the handler function
-    returns a negative error code, it will be disabled after the
-    invocation, even if <constant>SD_EVENT_ON</constant> mode is
-    set.</para>
+    (<constant>SD_EVENT_ONESHOT</constant>).</para>
+
+    <para>If the handler function returns a negative error code, it
+    will be disabled after the invocation, even if the
+    <constant>SD_EVENT_ON</constant> mode was requested before.</para>
+
+    <para>To destroy an event source object use
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    but note that the event source is only removed from the event loop
+    when all references to the event source are dropped. To make sure
+    an event source does not fire anymore, even when there's still a
+    reference to it kept, consider setting the event source to
+    <constant>SD_EVENT_OFF</constant> with
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+    <para>If the second parameter of these functions is passed as
+    NULL no reference to the event source object is returned. In this
+    case the event source is considered "floating", and will be
+    destroyed implicitly when the event loop itself is
+    destroyed.</para>
   </refsect1>
 
   <refsect1>
     </variablelist>
   </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
-
-    <para>Functions described here are available as a shared library,
-    which can be compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry
-    project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
+  <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
     <title>See Also</title>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/man/sd_event_add_io.xml b/man/sd_event_add_io.xml
new file mode 100644 (file)
index 0000000..c374916
--- /dev/null
@@ -0,0 +1,300 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_add_io" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_add_io</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_add_io</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_add_io</refname>
+    <refname>sd_event_source_get_io_events</refname>
+    <refname>sd_event_source_set_io_events</refname>
+    <refname>sd_event_source_get_io_revents</refname>
+    <refname>sd_event_source_get_io_fd</refname>
+    <refname>sd_event_source_set_io_fd</refname>
+    <refname>sd_event_source</refname>
+    <refname>sd_event_io_handler_t</refname>
+
+    <refpurpose>Add an I/O event source to an event loop</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_io_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>int <parameter>fd</parameter></paramdef>
+        <paramdef>uint32_t <parameter>revents</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_add_io</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+        <paramdef>int <parameter>fd</parameter></paramdef>
+        <paramdef>uint32_t <parameter>events</parameter></paramdef>
+        <paramdef>sd_event_io_handler_t <parameter>handler</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_io_events</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>uint32_t *<parameter>events</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_io_events</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>uint32_t <parameter>events</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_io_revents</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>uint32_t *<parameter>revents</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_io_fd</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_io_fd</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>int <parameter>fd</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_add_io()</function> adds a new I/O event
+    source to an event loop. The event loop object is specified in the
+    <parameter>event</parameter> parameter, the event source object is
+    returned in the <parameter>source</parameter> parameter. The
+    <parameter>fd</parameter> parameter takes the UNIX file descriptor
+    to watch, which may refer to a socket, a FIFO, a message queue, a
+    serial connection, a character device, or any other file descriptor
+    compatible with Linux
+    <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
+    <parameter>events</parameter> parameter takes a bit mask of events
+    to watch for, a combination of the following event flags:
+    <constant>EPOLLIN</constant>, <constant>EPOLLOUT</constant>,
+    <constant>EPOLLRDHUP</constant>, <constant>EPOLLPRI</constant>,
+    and <constant>EPOLLET</constant>, see
+    <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    for details. The <parameter>handler</parameter> shall reference a
+    function to call when the event source is triggered. The
+    <parameter>userdata</parameter> pointer will be passed to the
+    handler function, and may be chosen freely by the caller. The
+    handler will also be passed the file descriptor the event was seen
+    on, as well as the actual event flags. It's generally a subset of
+    the events watched, however may additionally include
+    <constant>EPOLLERR</constant> and <constant>EPOLLHUP</constant>.
+    </para>
+
+    <para>By default, an event source will stay enabled
+    continuously (<constant>SD_EVENT_ON</constant>), but this may be
+    changed with
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+    If the handler function returns a negative error code, it will be
+    disabled after the invocation, even if the
+    <constant>SD_EVENT_ON</constant> mode was requested before. Note
+    that an event source set to <constant>SD_EVENT_ON</constant> will
+    fire continuously unless data is read from or written to the file
+    descriptor to reset the mask of events seen.
+    </para>
+
+    <para>Setting the I/O event mask to watch for to 0 does not mean
+    that the event source won't be triggered anymore, as
+    <constant>EPOLLHUP</constant> and <constant>EPOLLERR</constant>
+    may be triggered even with a zero event mask. To temporarily
+    disable an I/O event source use
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with <constant>SD_EVENT_OFF</constant> instead.</para>
+
+    <para>To destroy an event source object use
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    but note that the event source is only removed from the event loop
+    when all references to the event source are dropped. To make sure
+    an event source does not fire anymore, even if it is still referenced,
+    disable the event source using
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with <constant>SD_EVENT_OFF</constant>.</para>
+
+    <para>If the second parameter of
+    <function>sd_event_add_io()</function> is
+    <constant>NULL</constant> no reference to the event source object
+    is returned. In this case the event source is considered
+    "floating", and will be destroyed implicitly when the event loop
+    itself is destroyed.</para>
+
+    <para>It is recommended to use
+    <function>sd_event_add_io()</function> only in conjunction with
+    file descriptors that have <constant>O_NONBLOCK</constant> set, to
+    ensure that all I/O operations from invoked handlers are properly
+    asynchronous and non-blocking. Using file descriptors without
+    <constant>O_NONBLOCK</constant> might result in unexpected
+    starvation of other event sources. See
+    <citerefentry project='man-pages'><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    for details on enabling <constant>O_NONBLOCK</constant> mode.</para>
+
+    <para><function>sd_event_source_get_io_events()</function> retrieves
+    the configured mask of watched I/O events of an event source created
+    previously with <function>sd_event_add_io()</function>. It takes
+    the event source object and a pointer to a variable to store the
+    mask in.</para>
+
+    <para><function>sd_event_source_set_io_events()</function>
+    configures the mask of watched I/O events of an event source created
+    previously with <function>sd_event_add_io()</function>. It takes the
+    event source object and the new event mask.</para>
+
+    <para><function>sd_event_source_get_io_revents()</function>
+    retrieves the I/O event mask of currently seen but undispatched
+    events from an event source created previously with
+    <function>sd_event_add_io()</function>. It takes the event source
+    object and a pointer to a variable to store the event mask
+    in. When called from a handler function on the handler's event
+    source object this will return the same mask as passed to the
+    handler's <parameter>revents</parameter> parameter. This call is
+    primarily useful to check for undispatched events of an event
+    source from the handler of an unrelated (possibly higher priority)
+    event source. Note the relation between
+    <function>sd_event_source_get_pending()</function> and
+    <function>sd_event_source_get_io_revents()</function>: both
+    functions will report non-zero results when there's an event
+    pending for the event source, but the former applies to all event
+    source types, the latter only to I/O event sources.</para>
+
+    <para><function>sd_event_source_get_io_fd()</function> retrieves
+    the UNIX file descriptor of an event source created previously
+    with <function>sd_event_add_io()</function>. It takes the event
+    source object and returns the non-negative file descriptor
+    or a negative error number on error (see below).</para>
+
+    <para><function>sd_event_source_set_io_fd()</function>
+    changes the UNIX file descriptor of an I/O event source created
+    previously with <function>sd_event_add_io()</function>. It takes
+    the event source object and the new file descriptor.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, these functions return 0 or a positive
+    integer. On failure, they return a negative errno-style error
+    code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned values may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory to allocate an object.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para>An invalid argument has been passed.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ESTALE</constant></term>
+
+        <listitem><para>The event loop is already terminated.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
+
+        <listitem><para>The passed event source is not an I/O event source.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_get_pending</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index 0923fe0ae7942b8b63cf6eff69b4d13179dcfb84..e98f1d2682172bd492da2e61026fb7af16377984 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_add_signal">
+<refentry id="sd_event_add_signal" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_add_signal</title>
   <refnamediv>
     <refname>sd_event_add_signal</refname>
     <refname>sd_event_source_get_signal</refname>
+    <refname>sd_event_signal_handler_t</refname>
 
-    <refpurpose>Add a signal event source to an event loop</refpurpose>
+    <refpurpose>Add a UNIX process signal event source to an event
+    loop</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_signal_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>const struct signalfd_siginfo *<parameter>si</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_add_signal</function></funcdef>
         <paramdef>void *<parameter>userdata</parameter></paramdef>
       </funcprototype>
 
-      <funcprototype>
-        <funcdef>typedef int (*<function>sd_event_signal_handler_t</function>)</funcdef>
-        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
-        <paramdef>const struct signalfd_siginfo *<parameter>si</parameter></paramdef>
-        <paramdef>void *<parameter>userdata</parameter></paramdef>
-      </funcprototype>
-
       <funcprototype>
         <funcdef>int <function>sd_event_source_get_signal</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_event_add_signal()</function> adds a new signal
-    event source to an event loop object. The event loop is specified
-    in <parameter>event</parameter>, and the event source is returned in
-    the <parameter>source</parameter> parameter. The
-    <parameter>signal</parameter> parameter specifies the signal to be handled
-    (see
-    <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
-    The <parameter>handler</parameter> must reference a function to
-    call when the signal is delivered or be <constant>NULL</constant>.
-    The handler function will be passed the
-    <parameter>userdata</parameter> pointer, which may be chosen
+    <para><function>sd_event_add_signal()</function> adds a new UNIX
+    process signal event source to an event loop. The event loop
+    object is specified in the <parameter>event</parameter> parameter,
+    and the event source object is returned in the
+    <parameter>source</parameter> parameter. The
+    <parameter>signal</parameter> parameter specifies the numeric
+    signal to be handled (see <citerefentry
+    project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
+    The <parameter>handler</parameter> parameter must reference a
+    function to call when the signal is received or be
+    <constant>NULL</constant>.  The handler function will be passed
+    the <parameter>userdata</parameter> pointer, which may be chosen
     freely by the caller. The handler also receives a pointer to a
-    <structname>const struct signalfd_siginfo</structname> containing
-    the information about the received signal. See
-    <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    <structname>signalfd_siginfo</structname> structure containing
+    information about the received signal. See <citerefentry
+    project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     for further information.</para>
 
     <para>Only a single handler may be installed for a specific
-    signal. The signal will be unblocked, and must be
-    blocked when the function is called. If the handler is not
-    specified (<parameter>handler</parameter> is
+    signal. The signal will be unblocked by this call, and must be
+    blocked before this function is called in all threads (using
+    <citerefentry
+    project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry>). If
+    the handler is not specified (<parameter>handler</parameter> is
     <constant>NULL</constant>), a default handler which causes the
-    program to exit will be used.  By default, the handler is enabled
-    permanently (<constant>SD_EVENT_ON</constant>), but this may be
-    changed with
+    program to exit cleanly will be used.</para>
+
+    <para>By default, the event source is enabled permanently
+    (<constant>SD_EVENT_ON</constant>), but this may be changed with
     <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
     If the handler function returns a negative error code, it will be
-    disabled after the invocation, even if
-    <constant>SD_EVENT_ON</constant> mode is set.
+    disabled after the invocation, even if the
+    <constant>SD_EVENT_ON</constant> mode was requested before.
     </para>
 
-    <para><function>sd_event_source_get_signal()</function> retrieves
-    the configured signal number of a signal event source created
-    previously with <function>sd_event_add_signal()</function>. It
-    takes the event source object as the <parameter>source</parameter>
+    <para>To destroy an event source object use
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    but note that the event source is only removed from the event loop
+    when all references to the event source are dropped. To make sure
+    an event source does not fire anymore, even if it is still referenced,
+    disable the event source using
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with <constant>SD_EVENT_OFF</constant>.</para>
+
+    <para>If the second parameter of
+    <function>sd_event_add_signal()</function> is
+    <constant>NULL</constant> no reference to the event source object
+    is returned. In this case the event source is considered
+    "floating", and will be destroyed implicitly when the event loop
+    itself is destroyed.</para>
+
+    <para><function>sd_event_source_get_signal()</function> returns
+    the configured signal number of an event source created previously
+    with <function>sd_event_add_signal()</function>. It takes the
+    event source object as the <parameter>source</parameter>
     parameter.</para>
-
   </refsect1>
 
   <refsect1>
 
     <para>On success, these functions return 0 or a positive
     integer. On failure, they return a negative errno-style error
-    code. </para>
+    code.</para>
   </refsect1>
 
   <refsect1>
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>An invalid argument has been passed.</para></listitem>
-
       </varlistentry>
 
       <varlistentry>
 
         <listitem><para>A handler is already installed for this
         signal or the signal was not blocked previously.</para></listitem>
-
       </varlistentry>
 
       <varlistentry>
         <term><constant>-ESTALE</constant></term>
 
         <listitem><para>The event loop is already terminated.</para></listitem>
-
       </varlistentry>
 
       <varlistentry>
         <term><constant>-ECHILD</constant></term>
 
         <listitem><para>The event loop has been created in a different process.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
 
+        <listitem><para>The passed event source is not a signal event source.</para></listitem>
       </varlistentry>
 
     </variablelist>
   </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
-
-    <para><function>sd_event_add_signal()</function> and the other functions
-    described here are available as a shared library, which can be
-    compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
+  <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
     <title>See Also</title>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>signalfd</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index c5f7aee19d728a1e4844499ed33ee1e2858f2f0d..a2c0d54b56da0e5ccf202eb8d584869fde50214e 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_add_time">
+<refentry id="sd_event_add_time" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_add_time</title>
     <refname>sd_event_source_get_time_accuracy</refname>
     <refname>sd_event_source_set_time_accuracy</refname>
     <refname>sd_event_source_get_time_clock</refname>
+    <refname>sd_event_time_handler_t</refname>
 
     <refpurpose>Add a timer event source to an event loop</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_time_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_add_time</function></funcdef>
         <paramdef>void *<parameter>userdata</parameter></paramdef>
       </funcprototype>
 
-      <funcprototype>
-        <funcdef>typedef int (*<function>sd_event_time_handler_t</function>)</funcdef>
-        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
-        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
-        <paramdef>void *<parameter>userdata</parameter></paramdef>
-      </funcprototype>
-
       <funcprototype>
         <funcdef>int <function>sd_event_source_get_time</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>usec_t *<parameter>usec</parameter></paramdef>
+        <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_source_set_time</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>usec_t <parameter>usec</parameter></paramdef>
+        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_source_get_time_accuracy</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>usec_t *<parameter>usec</parameter></paramdef>
+        <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_source_set_time_accuracy</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>usec_t <parameter>usec</parameter></paramdef>
+        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_event_add_time()</function> adds a new timer
-    event source to an event loop object. The event loop is specified
-    in <parameter>event</parameter>, the event source is returned in
-    the <parameter>source</parameter> parameter. The
-    <parameter>clock</parameter> parameter takes a clock identifier,
-    one of <constant>CLOCK_REALTIME</constant>,
-    <constant>CLOCK_MONOTONIC</constant> and
-    <constant>CLOCK_BOOTTIME_ALARM</constant>. See
-    <citerefentry><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-    for details regarding the various types of clocks. The
-    <parameter>usec</parameter> parameter takes a time value in
-    microseconds, relative to the clock's epoch specifying when the
-    timer shall elapse the earliest. The
-    <parameter>accuracy</parameter> parameter takes an additional
-    accuracy value in microseconds specifying a time the timer event
-    may be delayed. Specify 0 for selecting the default accuracy
-    (250ms). Specify 1 for most accurate timers. Consider specifying
-    60000000 or larger (1h) for long-running events that may be
-    delayed substantially. Picking higher accuracy values allows the
-    system to coalesce timer events more aggressively, thus improving
-    power efficiency. The <parameter>handler</parameter> shall
-    reference a function to call when the timer elapses. The handler
-    function will be passed the <parameter>userdata</parameter>
-    pointer, which may be chosen freely by the caller. The handler is
-    also passed the configured time it was triggered, however it might
-    actually have been called at a slightly later time, subject to the
-    specified accuracy value, the kernel timer slack (see
-    <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>)
-    and additional scheduling latencies.</para>
+    <para><function>sd_event_add_time()</function> adds a new timer event source to an event loop. The event loop
+    object is specified in the <parameter>event</parameter> parameter, the event source object is returned in the
+    <parameter>source</parameter> parameter. The <parameter>clock</parameter> parameter takes a clock identifier, one
+    of <constant>CLOCK_REALTIME</constant>, <constant>CLOCK_MONOTONIC</constant>, <constant>CLOCK_BOOTTIME</constant>,
+    <constant>CLOCK_REALTIME_ALARM</constant>, or <constant>CLOCK_BOOTTIME_ALARM</constant>. See
+    <citerefentry><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details
+    regarding the various types of clocks. The <parameter>usec</parameter> parameter specifies the earliest time, in
+    microseconds (µs), relative to the clock's epoch, when the timer shall be triggered. If a time already in the past
+    is specified (including <constant>0</constant>), this timer source "fires" immediately and is ready to be
+    dispatched. If the paramater is specified as <constant>UINT64_MAX</constant> the timer event will never elapse,
+    which may be used as an alternative to explicitly disabling a timer event source with
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>. The
+    <parameter>accuracy</parameter> parameter specifies an additional accuracy value in µs specifying how much the
+    timer event may be delayed. Use <constant>0</constant> to select the default accuracy (250ms). Use 1µs for maximum
+    accuracy. Consider specifying 60000000µs (1min) or larger for long-running events that may be delayed
+    substantially. Picking higher accuracy values allows the system to coalesce timer events more aggressively,
+    improving power efficiency. The <parameter>handler</parameter> parameter shall reference a function to call when
+    the timer elapses. The handler function will be passed the <parameter>userdata</parameter> pointer, which may be
+    chosen freely by the caller. The handler is also passed the configured trigger time, even if it is actually called
+    slightly later, subject to the specified accuracy value, the kernel timer slack (see
+    <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), and additional
+    scheduling latencies. To query the actual time the handler was called use
+    <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
 
     <para>By default, the timer will elapse once
     (<constant>SD_EVENT_ONESHOT</constant>), but this may be changed
     with
     <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
     If the handler function returns a negative error code, it will be
-    disabled after the invocation, even if
-    <constant>SD_EVENT_ON</constant> mode is set.
+    disabled after the invocation, even if the
+    <constant>SD_EVENT_ON</constant> mode was requested before. Note
+    that a timer event set to <constant>SD_EVENT_ON</constant> will
+    fire continuously unless its configured time is updated using
+    <function>sd_event_source_set_time()</function>.
     </para>
 
+    <para>To destroy an event source object use
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    but note that the event source is only removed from the event loop
+    when all references to the event source are dropped. To make sure
+    an event source does not fire anymore, even if it is still referenced,
+    disable the event source using
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with <constant>SD_EVENT_OFF</constant>.</para>
+
+    <para>If the second parameter of
+    <function>sd_event_add_time()</function> is
+    <constant>NULL</constant> no reference to the event source object
+    is returned. In this case the event source is considered
+    "floating", and will be destroyed implicitly when the event loop
+    itself is destroyed.</para>
+
+    <para>If the <parameter>handler</parameter> to
+    <function>sd_event_add_time()</function> is
+    <constant>NULL</constant>, and the event source fires, this will
+    be considered a request to exit the event loop. In this case, the
+    <parameter>userdata</parameter> parameter, cast to an integer, is
+    used for the exit code passed to
+    <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+    <para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and
+    <constant>CLOCK_REALTIME_ALARM</constant> to define event sources
+    that may wake up the system from suspend.</para>
+
+    <para>In order to set up relative timers (that is, relative to the
+    current time), retrieve the current time via
+    <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    add the desired timespan to it, and use the result as
+    the <parameter>usec</parameter> parameter to
+    <function>sd_event_add_time()</function>.</para>
+
+    <para>In order to set up repetitive timers (that is, timers that
+    are triggered in regular intervals), set up the timer normally,
+    for the first invocation. Each time the event handler is invoked,
+    update the timer's trigger time with
+    <citerefentry><refentrytitle>sd_event_source_set_time</refentrytitle><manvolnum>3</manvolnum></citerefentry> for the next timer
+    iteration, and reenable the timer using
+    <function>sd_event_source_set_enabled()</function>. To calculate
+    the next point in time to pass to
+    <function>sd_event_source_set_time()</function>, either use as
+    base the <parameter>usec</parameter> parameter passed to the timer
+    callback, or the timestamp returned by
+    <function>sd_event_now()</function>. In the former case timer
+    events will be regular, while in the latter case the scheduling
+    latency will keep accumulating on the timer.</para>
+
     <para><function>sd_event_source_get_time()</function> retrieves
-    the configured time value of a timer event source created
+    the configured time value of an event source created
     previously with <function>sd_event_add_time()</function>. It takes
     the event source object and a pointer to a variable to store the
-    time in microseconds in.</para>
+    time in, relative to the selected clock's epoch, in µs.</para>
 
     <para><function>sd_event_source_set_time()</function> changes the
-    configured time value of a timer event source created previously
-    with <function>sd_event_add_time()</function>. It takes the event
-    source object and a time relative to the selected clock's
-    epoch, in microseconds.</para>
+    time of an event source created previously with
+    <function>sd_event_add_time()</function>. It takes the event
+    source object and a time relative to the selected clock's epoch,
+    in µs.</para>
 
     <para><function>sd_event_source_get_time_accuracy()</function>
-    retrieves the configured accuracy value of a timer event source
+    retrieves the configured accuracy value of a event source
     created previously with <function>sd_event_add_time()</function>. It
     takes the event source object and a pointer to a variable to store
-    the accuracy in microseconds in.</para>
+    the accuracy in. The accuracy is specified in µs.</para>
 
     <para><function>sd_event_source_set_time_accuracy()</function>
     changes the configured accuracy of a timer event source created
     previously with <function>sd_event_add_time()</function>. It takes
-    the event source object and an accuracy, in microseconds.</para>
+    the event source object and accuracy, in µs.</para>
 
     <para><function>sd_event_source_get_time_clock()</function>
-    retrieves the configured clock of a timer event source created
+    retrieves the configured clock of a event source created
     previously with <function>sd_event_add_time()</function>. It takes
     the event source object and a pointer to a variable to store the
     clock identifier in.</para>
-
   </refsect1>
 
   <refsect1>
   <refsect1>
     <title>Errors</title>
 
-    <para>Returned errors may indicate the following problems:</para>
+    <para>Returned values may indicate the following problems:</para>
 
     <variablelist>
       <varlistentry>
         <listitem><para>The selected clock is not supported by the event loop implementation.</para></listitem>
 
       </varlistentry>
-    </variablelist>
-  </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
 
-    <para><function>sd_event_add_time()</function> and the other functions
-    described here are available as a shared library, which can be
-    compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
+        <listitem><para>The passed event source is not a timer event source.</para></listitem>
+      </varlistentry>
+    </variablelist>
   </refsect1>
 
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
   <refsect1>
     <title>See Also</title>
 
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>timerfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/man/sd_event_exit.xml b/man/sd_event_exit.xml
new file mode 100644 (file)
index 0000000..9846a3e
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_exit" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_exit</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_exit</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_exit</refname>
+    <refname>sd_event_get_exit_code</refname>
+
+    <refpurpose>Ask the event loop to exit</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_exit</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>int <parameter>code</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_get_exit_code</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>int *<parameter>code</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_exit()</function> requests the event loop
+    specified in the <parameter>event</parameter> event loop object to
+    exit. The <parameter>code</parameter> parameter may be any integer
+    value and is returned as-is by
+    <citerefentry><refentrytitle>sd_event_loop</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    after the last event loop iteration. It may also be queried
+    using <function>sd_event_get_exit_code()</function>, see
+    below. </para>
+
+    <para>When exiting is requested the event loop will stop listening
+    for and dispatching regular event sources. Instead it will proceed
+    with executing only event sources registered with
+    <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    in the order defined by their priority. After all exit event
+    sources have been dispatched the event loop is terminated.</para>
+
+    <para>If <function>sd_event_exit()</function> is invoked a second
+    time while the event loop is still processing exit event sources,
+    the exit code stored in the event loop object is updated, but
+    otherwise no further operation is executed.</para>
+
+    <para><function>sd_event_get_exit_code()</function> may be used to
+    query the exit code passed into
+    <function>sd_event_exit()</function> earlier.</para>
+
+    <para>While the full positive and negative integer ranges may be used
+    for the exit code, care should be taken not pick exit codes that
+    conflict with regular exit codes returned by
+    <function>sd_event_loop()</function>, if these exit codes shall be
+    distinguishable.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, <function>sd_event_exit()</function> and
+    <function>sd_event_get_exit_code()</function> return 0 or a positive
+    integer. On failure, they return a negative errno-style error
+    code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para>The event loop object or error code pointer are invalid.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop was created in a different process.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ESTALE</constant></term>
+
+        <listitem><para>The event loop has exited already and all exit handlers are already processed.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENODATA</constant></term>
+
+        <listitem><para>The event loop has not been requested to exit yet.</para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index ecdbe76ec411cfad61825c5303d07d10cb9d90d5..f68752dd0e8b5097df435c2cc70bb71052bd5d83 100644 (file)
@@ -21,8 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_get_fd"
-        xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="sd_event_get_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_get_fd</title>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
 
       <funcprototype>
         <funcdef>int <function>sd_event_get_fd</function></funcdef>
-        <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
       </funcprototype>
 
     </funcsynopsis>
     <title>Description</title>
 
     <para><function>sd_event_get_fd()</function> returns the file
-    descriptor that the event loop object returned by the
+    descriptor that an event loop object returned by the
     <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    function uses to wait for events. This file descriptor can be
-    polled for events. This makes it possible to embed the
+    function uses to wait for events. This file descriptor may itself
+    be polled for
+    <constant>POLLIN</constant>/<constant>EPOLLIN</constant>
+    events. This makes it possible to embed an
     <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    event loop inside of another event loop.</para>
+    event loop into another, possibly foreign, event loop.</para>
+
+    <para>The returned file descriptor refers to an <citerefentry
+    project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+    object. It is recommended not to alter it by invoking
+    <citerefentry
+    project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    on it, in order to avoid interference with the event loop's inner
+    logic and assumptions.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
     <para>On success, <function>sd_event_get_fd()</function> returns a
-    non-negative integer. On failure, it returns a negative
+    non-negative file descriptor. On failure, it returns a negative
     errno-style error code.</para>
   </refsect1>
 
     <title>Examples</title>
 
     <example>
-      <title>Integration in glib event loop</title>
+      <title>Integration in the GLib event loop</title>
 
       <programlisting><xi:include href="glib-event-glue.c" parse="text" /></programlisting>
     </example>
   </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
-
-    <para><function>sd_event_get_fd()</function> is available as a
-    shared library, which can be compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry
-    project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
+  <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>epoll_ctl</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index f6c5d3981485b9b9acba9e2f6449476b8eba4280..2c23b00a8c7bd80c2293d8ce37d6aadd7650b9b4 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_new">
+<refentry id="sd_event_new" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_new</title>
     <refname>sd_event_default</refname>
     <refname>sd_event_ref</refname>
     <refname>sd_event_unref</refname>
+    <refname>sd_event_unrefp</refname>
+    <refname>sd_event_get_tid</refname>
+    <refname>sd_event</refname>
 
     <refpurpose>Acquire and release an event loop object</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>typedef</token> struct sd_event sd_event;</funcsynopsisinfo>
 
       <funcprototype>
         <funcdef>int <function>sd_event_new</function></funcdef>
-        <paramdef>sd_bus **<parameter>event</parameter></paramdef>
+        <paramdef>sd_event **<parameter>event</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
         <funcdef>int <function>sd_event_default</function></funcdef>
-        <paramdef>sd_bus **<parameter>event</parameter></paramdef>
+        <paramdef>sd_event **<parameter>event</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
-        <funcdef>sd_bus *<function>sd_event_ref</function></funcdef>
-        <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+        <funcdef>sd_event *<function>sd_event_ref</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
-        <funcdef>sd_bus *<function>sd_event_unref</function></funcdef>
-        <paramdef>sd_bus *<parameter>event</parameter></paramdef>
+        <funcdef>sd_event *<function>sd_event_unref</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_event_unrefp</function></funcdef>
+        <paramdef>sd_event **<parameter>event</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_get_tid</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>pid_t *<parameter>tid</parameter></paramdef>
       </funcprototype>
 
     </funcsynopsis>
     thread. All threads have exactly either zero or one default event loop
     objects associated, but never more.</para>
 
+    <para>After allocating an event loop object, add event sources to
+    it with
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    or
+    <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    and then execute the event loop using
+    <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
     <para><function>sd_event_ref()</function> increases the reference
     count of the specified event loop object by one.</para>
 
     distinct objects. Note that, in order to free an event loop object,
     all remaining event sources of the event loop also need to be
     freed as each keeps a reference to it.</para>
+
+    <para><function>sd_event_unrefp()</function> is similar to
+    <function>sd_event_unref()</function> but takes a pointer to a
+    pointer to an <type>sd_event</type> object. This call is useful in
+    conjunction with GCC's and LLVM's <ulink
+    url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+    Variable Attribute</ulink>. Note that this function is defined as
+    inline function. Use a declaration like the following,
+    in order to allocate an event loop object that is freed
+    automatically as the code block is left:</para>
+
+    <programlisting>{
+        __attribute__((cleanup(sd_event_unrefp)) sd_event *event = NULL;
+        int r;
+        …
+        r = sd_event_default(&amp;event);
+        if (r &lt; 0)
+                fprintf(stderr, "Failed to allocate event loop: %s\n", strerror(-r));
+        …
+}</programlisting>
+
+    <para><function>sd_event_ref()</function>,
+    <function>sd_event_unref()</function> and
+    <function>sd_event_unrefp()</function> execute no operation if the
+    passed in event loop object is <constant>NULL</constant>.</para>
+
+    <para><function>sd_event_get_tid()</function> retrieves the thread
+    identifier ("TID") of the thread the specified event loop object
+    is associated with. This call is only supported for event loops
+    allocated with <function>sd_event_default()</function>, and
+    returns the identifier for the thread the event loop is the
+    default event loop of. See <citerefentry
+    project='man-pages'><refentrytitle>gettid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    for more information on thread identifiers.</para>
   </refsect1>
 
   <refsect1>
         <listitem><para>The maximum number of event loops has been allocated.</para></listitem>
 
       </varlistentry>
-    </variablelist>
-  </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
+      <varlistentry>
+        <term><constant>-ENXIO</constant></term>
 
-    <para><function>sd_event_new()</function> and the other functions
-    described here are available as a shared library, which can be
-    compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
+        <listitem><para><function>sd_event_get_tid()</function> was
+        invoked on an event loop object that was not allocated with
+        <function>sd_event_default()</function>.</para></listitem>
+      </varlistentry>
+
+    </variablelist>
   </refsect1>
 
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
   <refsect1>
     <title>See Also</title>
 
       <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>gettid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/man/sd_event_now.xml b/man/sd_event_now.xml
new file mode 100644 (file)
index 0000000..2c83b0b
--- /dev/null
@@ -0,0 +1,146 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_now" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_now</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_now</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_now</refname>
+
+    <refpurpose>Retrieve current event loop iteration timestamp</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_now</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>clockid_t <parameter>clock</parameter></paramdef>
+        <paramdef>uint64_t *<parameter>usec</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_now()</function> returns the time when
+    the most recent event loop iteration began. A timestamp
+    is taken right after returning from the event sleep, and before
+    dispatching any event sources. The <parameter>event</parameter>
+    parameter specifies the event loop object to retrieve the timestamp
+    from. The <parameter>clock</parameter> parameter specifies the clock to
+    retrieve the timestamp for, and is one of
+    <constant>CLOCK_REALTIME</constant> (or equivalently
+    <constant>CLOCK_REALTIME_ALARM</constant>),
+    <constant>CLOCK_MONOTONIC</constant>, or
+    <constant>CLOCK_BOOTTIME</constant> (or equivalently
+    <constant>CLOCK_BOOTTIME_ALARM</constant>), see
+    <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    for more information on the various clocks. The retrieved
+    timestamp is stored in the <parameter>usec</parameter> parameter,
+    in µs since the clock's epoch. If this function is invoked before
+    the first event loop iteration, the current time is returned, as
+    reported by <function>clock_gettime()</function>. To distinguish
+    this case from a regular invocation the return value will be
+    positive, and zero when the returned timestamp refers to an actual
+    event loop iteration.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>If the first event loop iteration has not run yet
+    <function>sd_event_now()</function> writes current time to
+    <parameter>usec</parameter> and returns a positive return value.
+    Otherwise, it will write the requested timestamp to <parameter>usec</parameter>
+    and return 0. On failure, the call returns a negative errno-style
+    error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned values may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para>An invalid parameter was
+        passed.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EOPNOTSUPP</constant></term>
+
+        <listitem><para>Unsupported clock type.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop object was created in a
+        different process.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index 06236fcd1ad25e69f6fc04fb7b63e2dc44bd9a65..5b68959165d9280de8121b4f5c6bc2fb88f05c67 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_run">
+<refentry id="sd_event_run" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_run</title>
@@ -46,7 +46,7 @@
     <refname>sd_event_run</refname>
     <refname>sd_event_loop</refname>
 
-    <refpurpose>Run the libsystemd event loop</refpurpose>
+    <refpurpose>Run an event loop</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
@@ -56,7 +56,7 @@
       <funcprototype>
         <funcdef>int <function>sd_event_run</function></funcdef>
         <paramdef>sd_event *<parameter>event</parameter></paramdef>
-        <paramdef>uint64_t <parameter>timeout</parameter></paramdef>
+        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_event_run()</function> can be used to run one
-    iteration of the event loop of libsystemd. This function waits
-    until an event to process is available, and dispatches a handler
-    for it. The <parameter>timeout</parameter> parameter specifices the
-    maximum time (in microseconds) to wait. <constant>(uint64_t)
-    -1</constant> may be used to specify an infinite timeout.</para>
-
-    <para><function>sd_event_loop</function> runs
-    <function>sd_event_wait</function> in a loop with a timeout of
-    infinity. This makes it suitable for the main event loop of a
-    program.</para>
+    <para><function>sd_event_run()</function> may be used to run a single
+    iteration of the event loop specified in the
+    <parameter>event</parameter> parameter. The function waits until an event to
+    process is available, and dispatches the registered handler for
+    it. The <parameter>usec</parameter> parameter specifies the
+    maximum time (in microseconds) to wait for an event. Use
+    <constant>(uint64_t) -1</constant> to specify an infinite
+    timeout.</para>
+
+    <para><function>sd_event_loop()</function> invokes
+    <function>sd_event_run()</function> in a loop, thus implementing
+    the actual event loop. The call returns as soon as exiting was
+    requested using
+    <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
 
     <para>The event loop object <parameter>event</parameter> is
     created with
-    <function>sd_event_new</function>.
-    Events to wait for and their handlers can be registered with
-    <function>sd_event_add_time</function>,
-    <function>sd_event_add_child</function>,
-    <function>sd_event_add_signal</function>,
-    <function>sd_event_add_defer</function>,
-    <function>sd_event_add_exit</function>,
+    <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+    Events sources to wait for and their handlers may be registered
+    with
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     and
-    <function>sd_event_add_post</function>.
+    <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
     </para>
 
-    <para>For more fine-grained control,
-    <function>sd_event_prepare</function>,
-    <function>sd_event_wait</function>, and
-    <function>sd_event_dispatch</function> may be used. Along with
-    <function>sd_event_get_fd</function>, those functions make it
-    possible to integrate the libsystemd loop inside of another event
-    loop.</para>
+    <para>For low-level control of event loop execution, use
+    <citerefentry><refentrytitle>sd_event_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    and
+    <citerefentry><refentrytitle>sd_event_dispatch</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    which are wrapped by <function>sd_event_run()</function>. Along
+    with
+    <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    these functions allow integration of an
+    <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    event loop into foreign event loop implementations.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
-    <para>On success, these functions return 0 or a positive integer.
-    On failure, they return a negative errno-style error code.
-    <function>sd_event_run</function> returns 0 if the event loop is
-    finished, and a positive value if it can be continued.</para>
+    <para>On failure, these functions return a negative errno-style
+    error code. <function>sd_event_run()</function> returns a
+    positive, non-zero integer if an event source was dispatched, and
+    zero when the specified timeout hit before an event source has
+    seen any event, and hence no event source was
+    dispatched. <function>sd_event_loop()</function> returns the exit
+    code specified when invoking
+    <function>sd_event_exit()</function>.</para>
   </refsect1>
 
   <refsect1>
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>The <parameter>event</parameter> parameter is
-        <constant>NULL</constant>.</para></listitem>
+        invalid or <constant>NULL</constant>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
     <para>Other errors are possible, too.</para>
   </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
-
-    <para><function>sd_event_run()</function> and
-    <function>sd_event_loop()</function> are available
-    as a shared library, which can be compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
+  <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_wait</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <ulink url="https://developer.gnome.org/glib/unstable/glib-The-Main-Event-Loop.html">GLib Main Event Loop</ulink>.
     </para>
   </refsect1>
diff --git a/man/sd_event_set_name.xml b/man/sd_event_set_name.xml
deleted file mode 100644 (file)
index 1471e12..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
-  This file is part of systemd.
-
-  Copyright 2014 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/>.
--->
-
-<refentry id="sd_event_set_name"
-        xmlns:xi="http://www.w3.org/2001/XInclude">
-
-  <refentryinfo>
-    <title>sd_event_set_name</title>
-    <productname>systemd</productname>
-
-    <authorgroup>
-      <author>
-        <contrib>More text</contrib>
-        <firstname>Zbigniew</firstname>
-        <surname>Jędrzejewski-Szmek</surname>
-        <email>zbyszek@in.waw.pl</email>
-      </author>
-    </authorgroup>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>sd_event_set_name</refentrytitle>
-    <manvolnum>3</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>sd_event_set_name</refname>
-    <refname>sd_event_get_name</refname>
-
-    <refpurpose>Set human-readable names for event sources</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
-
-      <funcprototype>
-        <funcdef>int <function>sd_event_set_name</function></funcdef>
-        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>const char *<parameter>name</parameter></paramdef>
-      </funcprototype>
-
-      <funcprototype>
-        <funcdef>int <function>sd_event_get_name</function></funcdef>
-        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
-        <paramdef>const char **<parameter>name</parameter></paramdef>
-      </funcprototype>
-
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para><function>sd_event_set_name()</function> can be used to set
-    an arbitrary name for the event source
-    <parameter>source</parameter>. This name will be used in error
-    messages generated by
-    <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    for this source. The <parameter>name</parameter> must point
-    to a <constant>NUL</constant>-terminated string or be
-    <constant>NULL</constant>. In the latter case, the name will be
-    unset. The string is copied internally, so the
-    <parameter>name</parameter> argument is not referenced after the
-    function returns.</para>
-
-    <para><function>sd_event_set_name()</function> can be used to
-    query the current name assigned to source
-    <parameter>source</parameter>. It returns a pointer to the current
-    name (possibly <constant>NULL</constant>) in
-    <parameter>name</parameter>.</para>
-  </refsect1>
-
-  <refsect1>
-    <title>Return Value</title>
-
-    <para>On success, <function>sd_event_set_name()</function> and
-    <function>sd_event_get_name()</function> return a
-    non-negative integer. On failure, they return a negative
-    errno-style error code.</para>
-  </refsect1>
-
-  <refsect1>
-    <title>Errors</title>
-
-    <para>Returned errors may indicate the following problems:</para>
-
-    <variablelist>
-      <varlistentry>
-        <term><constant>-EINVAL</constant></term>
-
-        <listitem><para><parameter>source</parameter> is not a valid
-        pointer to an <structname>sd_event_source</structname>
-        structure or the <parameter>name</parameter> argument for
-        <function>sd_event_get_name()</function> is
-        <constant>NULL</constant>.</para></listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><constant>-ENOMEM</constant></term>
-
-        <listitem><para>Not enough memory to copy the
-        name.</para></listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Notes</title>
-
-    <para>The functions described here are available as a
-    shared library, which can be compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry
-    project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
-
-  <refsect1>
-    <title>See Also</title>
-
-    <para>
-      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    </para>
-  </refsect1>
-
-</refentry>
diff --git a/man/sd_event_set_watchdog.xml b/man/sd_event_set_watchdog.xml
new file mode 100644 (file)
index 0000000..cbc5bc0
--- /dev/null
@@ -0,0 +1,177 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_set_watchdog" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_set_watchdog</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_set_watchdog</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_set_watchdog</refname>
+    <refname>sd_event_get_watchdog</refname>
+
+    <refpurpose>Enable event loop watchdog support</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_set_watchdog</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>int b</paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_get_watchdog</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_set_watchdog()</function> may be used to
+    enable or disable automatic watchdog notification support in the
+    event loop object specified in the <parameter>event</parameter>
+    parameter. Specifically, depending on the <parameter>b</parameter>
+    boolean argument this will make sure the event loop wakes up in
+    regular intervals and sends watchdog notification messages to the
+    service manager, if this was requested by the service
+    manager. Watchdog support is determined with
+    <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    and watchdog messages are sent with
+    <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>. See
+    the <varname>WatchdogSec=</varname> setting in
+    <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    for details on how to enable watchdog support for a service and
+    the protocol used. The wake-up interval is chosen as half the
+    watchdog timeout declared by the service manager via the
+    <varname>$WATCHDOG_USEC</varname> environment variable. If the
+    service manager did not request watchdog notifications, or if the
+    process was not invoked by the service manager this call with a
+    true <parameter>b</parameter> parameter executes no
+    operation. Passing a false <parameter>b</parameter> parameter will
+    disable the automatic sending of watchdog notification messages if
+    it was enabled before. Newly allocated event loop objects have
+    this feature disabled.</para>
+
+    <para>The first watchdog notification message is sent immediately
+    when <function>set_event_set_watchdog()</function> is invoked with
+    a true <parameter>b</parameter> parameter.</para>
+
+    <para>The watchdog logic is designed to allow the service manager
+    to automatically detect services that ceased processing of
+    incoming events, and thus appear "hung". Watchdog notifications
+    are sent out only at the beginning of each event loop
+    iteration. If an event source dispatch function blocks for an
+    excessively long time and does not return execution to the event
+    loop quickly, this might hence cause the notification message to
+    be delayed, and possibly result in abnormal program termination,
+    as configured in the service unit file.</para>
+
+    <para><function>sd_event_get_watchdog()</function> may be used to
+    determine whether watchdog support was previously requested by a
+    call to <function>sd_event_set_watchdog()</function> with a true
+    <parameter>b</parameter> parameter and successfully
+    enabled.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, <function>sd_event_set_watchdog()</function> and
+    <function>sd_event_get_watchdog()</function> return a non-zero
+    positive integer if the service manager requested watchdog support
+    and watchdog support was successfully enabled. They return zero if
+    the service manager did not request watchdog support, or if
+    watchdog support was explicitly disabled with a false
+    <parameter>b</parameter> parameter. On failure, they return a
+    negative errno-style error
+    code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para>The passed event loop object was invalid.</para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_get_event.xml b/man/sd_event_source_get_event.xml
new file mode 100644 (file)
index 0000000..2fdbd41
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_get_event" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_get_event</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_get_event</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_get_event</refname>
+
+    <refpurpose>Retrieve the event loop of an event source</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>sd_event* <function>sd_event_source_get_event</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_get_event()</function> may be used
+    to retrieve the event loop object the event source object specified
+    as <parameter>source</parameter> is associated with. The event
+    loop object is specified when creating an event source object with
+    calls such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    or
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, <function>sd_event_source_get_event()</function>
+    returns the associated event loop object. On failure, it returns
+    NULL.</para>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_get_pending.xml b/man/sd_event_source_get_pending.xml
new file mode 100644 (file)
index 0000000..7f88bd1
--- /dev/null
@@ -0,0 +1,167 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_get_pending" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_get_pending</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_get_pending</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_get_pending</refname>
+
+    <refpurpose>Determine pending state of event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_pending</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_get_pending()</function> may be
+    used to determine whether the event source object specified as
+    <parameter>source</parameter> has seen events but has not been
+    dispatched yet (and thus is marked "pending").</para>
+
+    <para>Event source objects initially are not marked pending, when
+    they are created with calls such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    with the exception of those created with
+    <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    which are immediately marked pending, and
+    <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for which the "pending" concept is not defined. For details see
+    the respective manual pages.</para>
+
+    <para>In each event loop iteration one event source of those
+    marked pending is dispatched, in the order defined by the event
+    source priority, as set with
+    <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+    <para>For I/O event sources, as created with
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    the call
+    <citerefentry><refentrytitle>sd_event_source_get_io_revents</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    may be used to query the type of event pending in more
+    detail.</para>
+
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success,
+    <function>sd_event_source_get_pending()</function> returns an
+    integer greater than zero when the event source is marked pending,
+    and zero when the event source is not marked pending. On failure,
+    it returns a negative errno-style error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para><parameter>source</parameter> is not a valid
+        pointer to an <structname>sd_event_source</structname>
+        object.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
+
+        <listitem><para><parameter>source</parameter> refers to an
+        event source object created with
+        <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ESTALE</constant></term>
+
+        <listitem><para>The event loop is already terminated.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_description.xml b/man/sd_event_source_set_description.xml
new file mode 100644 (file)
index 0000000..b9488a6
--- /dev/null
@@ -0,0 +1,170 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2014 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/>.
+-->
+
+<refentry id="sd_event_source_set_description" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_set_description</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>More text</contrib>
+        <firstname>Zbigniew</firstname>
+        <surname>Jędrzejewski-Szmek</surname>
+        <email>zbyszek@in.waw.pl</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_set_description</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_set_description</refname>
+    <refname>sd_event_source_get_description</refname>
+
+    <refpurpose>Set or retrieve descriptive names of event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_description</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>const char *<parameter>description</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_description</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>const char **<parameter>description</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_set_description()</function> may
+    be used to set an arbitrary descriptive name for the event source
+    object specified as <parameter>source</parameter>. This name will
+    be used in debugging messages generated by
+    <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for this event source, and may be queried using
+    <function>sd_event_source_get_description()</function> for
+    debugging purposes. The <parameter>description</parameter> parameter shall
+    point to a <constant>NUL</constant>-terminated string or be
+    <constant>NULL</constant>. In the latter case, the descriptive
+    name will be unset. The string is copied internally, hence the
+    <parameter>description</parameter> argument is not referenced
+    after the function returns.</para>
+
+    <para><function>sd_event_source_get_description()</function> may
+    be used to query the current descriptive name assigned to the
+    event source object <parameter>source</parameter>. It returns a
+    pointer to the current name in <parameter>description</parameter>,
+    stored in memory internal to the event source. The memory is
+    invalidated when the event source is destroyed or the descriptive
+    name is changed.</para>
+
+    <para>Event source objects generally have no description set when
+    they are created, except for UNIX signal event sources created
+    with
+    <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    whose descriptive name is initialized to the signal's C constant
+    name (e.g. <literal>SIGINT</literal> or
+    <literal>SIGTERM</literal>).</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, <function>sd_event_source_set_description()</function> and
+    <function>sd_event_source_get_description()</function> return a
+    non-negative integer. On failure, they return a negative
+    errno-style error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para><parameter>source</parameter> is not a valid
+        pointer to an <structname>sd_event_source</structname>
+        object or the <parameter>description</parameter> argument for
+        <function>sd_event_source_get_description()</function> is
+        <constant>NULL</constant>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory to copy the
+        name.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENXIO</constant></term>
+
+        <listitem><para>No name was set for the event
+        source.</para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_enabled.xml b/man/sd_event_source_set_enabled.xml
new file mode 100644 (file)
index 0000000..6844f29
--- /dev/null
@@ -0,0 +1,179 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_enabled" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_set_enabled</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_set_enabled</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_set_enabled</refname>
+    <refname>sd_event_source_get_enabled</refname>
+    <refname>SD_EVENT_ON</refname>
+    <refname>SD_EVENT_OFF</refname>
+    <refname>SD_EVENT_ONESHOT</refname>
+
+    <refpurpose>Enable or disable event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>enum</token> {
+        <constant>SD_EVENT_OFF</constant> = 0,
+        <constant>SD_EVENT_ON</constant> = 1,
+        <constant>SD_EVENT_ONESHOT</constant> = -1,
+};</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_enabled</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>int <parameter>enabled</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_enabled</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>int *<parameter>enabled</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_set_enabled()</function> may be
+    used to enable or disable the event source object specified as
+    <parameter>source</parameter>. The <parameter>enabled</parameter>
+    parameter takes one of <constant>SD_EVENT_ON</constant> (to
+    enable), <constant>SD_EVENT_OFF</constant> (to disable) or
+    <constant>SD_EVENT_ONESHOT</constant>. If invoked with
+    <constant>SD_EVENT_ONESHOT</constant> the event source will be
+    enabled but automatically reset to
+    <constant>SD_EVENT_OFF</constant> after the event source was
+    dispatched once.</para>
+
+    <para>Event sources that are disabled will not result in event
+    loop wakeups and will not be dispatched, until they are enabled
+    again.</para>
+
+    <para><function>sd_event_source_get_enabled()</function> may be
+    used to query whether the event source object
+    <parameter>source</parameter> is currently enabled or not. It
+    returns the enablement state in
+    <parameter>enabled</parameter>.</para>
+
+    <para>Event source objects are enabled when they are first created
+    with calls such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. However,
+    depending on the event source type they are enabled continuously
+    (<constant>SD_EVENT_ON</constant>) or only for a single invocation
+    of the event source handler
+    (<constant>SD_EVENT_ONESHOT</constant>). For details see the
+    respective manual pages.</para>
+
+    <para>As event source objects stay active and may be dispatched as
+    long as there is at least one reference to them, in many cases it
+    is a good idea to combine a call to
+    <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    with a prior call to
+    <function>sd_event_source_set_enabled()</function> with
+    <constant>SD_EVENT_OFF</constant>, to ensure the event source is
+    not dispatched again until all other remaining references are dropped.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success, <function>sd_event_source_set_enabled()</function> and
+    <function>sd_event_source_get_enabled()</function> return a
+    non-negative integer. On failure, they return a negative
+    errno-style error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para><parameter>source</parameter> is not a valid
+        pointer to an <structname>sd_event_source</structname>
+        object.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_prepare.xml b/man/sd_event_source_set_prepare.xml
new file mode 100644 (file)
index 0000000..24861d0
--- /dev/null
@@ -0,0 +1,171 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_prepare" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_set_prepare</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_set_prepare</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_set_prepare</refname>
+
+    <refpurpose>Set a preparation callback for event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_prepare</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>sd_event_handler_t <parameter>callback</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>typedef int (*<function>sd_event_handler_t</function>)</funcdef>
+        <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_set_prepare()</function> may be
+    used to set a preparation callback for the event source object
+    specified as <parameter>source</parameter>. The callback function
+    specified as <parameter>callback</parameter> will be invoked
+    immediately before the event loop goes to sleep to wait for
+    incoming events. It is invoked with the user data pointer passed
+    when the event source was created. The callback function may be
+    used to reconfigure the precise events to wait for. If the
+    <parameter>callback</parameter> parameter is passed as NULL the
+    callback function is reset. </para>
+
+    <para>Event source objects have no preparation callback associated
+    when they are first created with calls such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+    callback functions are supported for all event source types with
+    the exception of those created with
+    <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+    callback functions are dispatched in the order indicated by the
+    event source's priority field, as set with
+    <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Preparation
+    callbacks of disabled event sources (see
+    <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+    are not invoked.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success,
+    <function>sd_event_source_set_prepare()</function> returns a
+    non-negative integer. On failure, it returns a negative
+    errno-style error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para><parameter>source</parameter> is not a valid
+        pointer to an <structname>sd_event_source</structname>
+        object.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ESTALE</constant></term>
+
+        <listitem><para>The event loop is already terminated.</para></listitem>
+
+      </varlistentry>
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-EDOM</constant></term>
+
+        <listitem><para>The specified event source has been created
+        with
+        <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml
new file mode 100644 (file)
index 0000000..9234f42
--- /dev/null
@@ -0,0 +1,189 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_priority" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_set_priority</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_set_priority</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_set_priority</refname>
+    <refname>sd_event_source_get_priority</refname>
+    <refname>SD_EVENT_PRIORITY_IMPORTANT</refname>
+    <refname>SD_EVENT_PRIORITY_NORMAL</refname>
+    <refname>SD_EVENT_PRIORITY_IDLE</refname>
+
+    <refpurpose>Set or retrieve the priority of event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcsynopsisinfo><token>enum</token> {
+        <constant>SD_EVENT_SOURCE_IMPORTANT</constant> = -100,
+        <constant>SD_EVENT_SOURCE_NORMAL</constant> = 0,
+        <constant>SD_EVENT_SOURCE_IDLE</constant> = 100,
+};</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_set_priority</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>int64_t <parameter>priority</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_event_source_get_priority</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>int64_t *<parameter>priority</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_set_priority()</function> may be
+    used to set the priority for the event source object specified as
+    <parameter>source</parameter>. The priority is specified as an
+    arbitrary signed 64bit integer. The priority is initialized to
+    <constant>SD_EVENT_PRIORITY_NORMAL</constant> (0) when the event
+    source is allocated with a call such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    or
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    and may be changed with this call. If multiple event sources have seen events at the same time, they are dispatched in the order indicated by the
+    event sources' priorities. Event sources with smaller priority
+    values are dispatched first. As well-known points of reference,
+    the constants <constant>SD_EVENT_PRIORITY_IMPORTANT</constant>
+    (-100), <constant>SD_EVENT_PRIORITY_NORMAL</constant> (0) and
+    <constant>SD_EVENT_PRIORITY_IDLE</constant> (100) may be used to
+    indicate event sources that shall be dispatched early, normally or
+    late. It is recommended to specify priorities based on these
+    definitions, and relative to them -- however, the full 64bit
+    signed integer range is available for ordering event
+    sources.</para>
+
+    <para>Priorities define the order in which event sources that have
+    seen events are dispatched. Care should be taken to ensure that
+    high-priority event sources (those with negative priority values
+    assigned) do not cause starvation of low-priority event sources
+    (those with positive priority values assigned).</para>
+
+    <para>The order in which event sources with the same priority are
+    dispatched is undefined, but the event loop generally tries to
+    dispatch them in the order it learnt about events on them. As the
+    backing kernel primitives do not provide accurate information
+    about the order in which events occurred this is not necessarily
+    reliable. However, it is guaranteed that if events are seen on
+    multiple same-priority event sources at the same time, each one is
+    not dispatched again until all others have been dispatched
+    once. This behaviour guarantees that within each priority
+    particular event sources do not starve or dominate the event
+    loop.</para>
+
+    <para><function>sd_event_source_get_priority()</function> may be
+    used to query the current priority assigned to the event source
+    object <parameter>source</parameter>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success,
+    <function>sd_event_source_set_priority()</function> and
+    <function>sd_event_source_get_priority()</function> return a
+    non-negative integer. On failure, they return a negative
+    errno-style error code.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Errors</title>
+
+    <para>Returned errors may indicate the following problems:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><constant>-EINVAL</constant></term>
+
+        <listitem><para><parameter>source</parameter> is not a valid
+        pointer to an <structname>sd_event_source</structname>
+        object.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ENOMEM</constant></term>
+
+        <listitem><para>Not enough memory.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ESTALE</constant></term>
+
+        <listitem><para>The event loop is already terminated.</para></listitem>
+
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>-ECHILD</constant></term>
+
+        <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_userdata.xml b/man/sd_event_source_set_userdata.xml
new file mode 100644 (file)
index 0000000..533d491
--- /dev/null
@@ -0,0 +1,119 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_set_userdata" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_set_userdata</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_set_userdata</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_set_userdata</refname>
+    <refname>sd_event_source_get_userdata</refname>
+
+    <refpurpose>Set or retrieve user data pointer of event sources</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>void* <function>sd_event_source_set_userdata</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void* <function>sd_event_source_get_userdata</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_set_userdata()</function> may be
+    used to set an arbitrary user data pointer for the event source
+    object specified as <parameter>source</parameter>. The user data
+    pointer is usually specified when creating an event source object
+    with calls such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    or
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+    and may be updated with this call. The user data pointer is also
+    passed to all handler callback functions associated with the event
+    source. The <parameter>userdata</parameter> parameter specifies
+    the new user data pointer to set, the function returns the
+    previous user data pointer. Note that <constant>NULL</constant> is
+    a valid user data pointer.</para>
+
+    <para><function>sd_event_source_get_userdata()</function> may be
+    used to query the current user data pointer assigned to the event
+    source object <parameter>source</parameter>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para>On success,
+    <function>sd_event_source_set_userdata()</function> and
+    <function>sd_event_source_get_userdata()</function> return the
+    previously set user data pointer. On failure, they return
+    NULL.</para>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml
new file mode 100644 (file)
index 0000000..2c4d450
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_event_source_unref" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_event_source_unref</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_event_source_unref</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_event_source_unref</refname>
+    <refname>sd_event_source_unrefp</refname>
+    <refname>sd_event_source_ref</refname>
+
+    <refpurpose>Increase or decrease event source reference counters</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>sd_event_source* <function>sd_event_source_unref</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_event_source_unrefp</function></funcdef>
+        <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>sd_event_source* <function>sd_event_source_ref</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_event_source_unref()</function> may be used to
+    decrement by one the reference counter of the event source object
+    specified as <parameter>source</parameter>. The reference counter
+    is initially set to one, when the event source is created with calls
+    such as
+    <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    or
+    <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>. When
+    the reference counter reaches zero it is removed from its event loop
+    object and destroyed.</para>
+
+    <para><function>sd_event_source_unrefp()</function> is similar to
+    <function>sd_event_source_unref()</function> but takes a pointer to a
+    pointer to an <type>sd_event_source</type> object. This call is useful in
+    conjunction with GCC's and LLVM's <ulink
+    url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+    Variable Attribute</ulink>. Note that this function is defined as
+    inline function.</para>
+
+    <para><function>sd_event_source_ref()</function> may be used
+    to increase by one the reference counter of the event source object
+    specified as <parameter>source</parameter>.</para>
+
+    <para><function>sd_event_source_unref()</function>,
+    <function>sd_bus_creds_unrefp()</function> and
+    <function>sd_bus_creds_ref()</function> execute no operation if
+    the passed event source object is
+    <constant>NULL</constant>.</para>
+
+    <para>Note that event source objects stay alive and may be
+    dispatched as long as they have a reference counter greater than
+    zero. In order to drop a reference of an event source and make
+    sure the associated event source handler function is not called
+    anymore it is recommended to combine a call of
+    <function>sd_event_source_unref()</function> with a prior call to
+    <function>sd_event_source_set_enabled()</function> with
+    <constant>SD_EVENT_OFF</constant>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para><function>sd_event_source_unref()</function> always returns
+    <constant>NULL</constant>.
+    <function>sd_event_source_ref()</function> always returns the
+    event source object passed in.</para>
+  </refsect1>
+
+  <xi:include href="libsystemd-pkgconfig.xml" />
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index 7ca50aedf9b05d859db401f1c36de91f7dff82f8..f2aea00e985c0dc05cf358445111918f0d922c85 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="sd_event_wait">
+<refentry id="sd_event_wait" xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>sd_event_wait</title>
     <refname>sd_event_wait</refname>
     <refname>sd_event_prepare</refname>
     <refname>sd_event_dispatch</refname>
-
-    <refpurpose>Run parts of the libsystemd event loop</refpurpose>
+    <refname>sd_event_get_state</refname>
+    <refname>SD_EVENT_INITIAL</refname>
+    <refname>SD_EVENT_PREPARING</refname>
+    <refname>SD_EVENT_ARMED</refname>
+    <refname>SD_EVENT_PENDING</refname>
+    <refname>SD_EVENT_RUNNING</refname>
+    <refname>SD_EVENT_EXITING</refname>
+    <refname>SD_EVENT_FINISHED</refname>
+
+    <refpurpose>Low-level event loop operations</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <funcsynopsis>
       <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
 
+      <funcsynopsisinfo><token>enum</token> {
+        <constant>SD_EVENT_INITIAL</constant>,
+        <constant>SD_EVENT_PREPARING</constant>,
+        <constant>SD_EVENT_ARMED</constant>,
+        <constant>SD_EVENT_PENDING</constant>,
+        <constant>SD_EVENT_RUNNING</constant>,
+        <constant>SD_EVENT_EXITING</constant>,
+        <constant>SD_EVENT_FINISHED</constant>,
+};</funcsynopsisinfo>
+
       <funcprototype>
         <funcdef>int <function>sd_event_prepare</function></funcdef>
         <paramdef>sd_event *<parameter>event</parameter></paramdef>
@@ -62,7 +80,7 @@
       <funcprototype>
         <funcdef>int <function>sd_event_wait</function></funcdef>
         <paramdef>sd_event *<parameter>event</parameter></paramdef>
-        <paramdef>uint64_t <parameter>timeout</parameter></paramdef>
+        <paramdef>uint64_t <parameter>usec</parameter></paramdef>
       </funcprototype>
 
       <funcprototype>
         <paramdef>sd_event *<parameter>event</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>int <function>sd_event_get_state</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+      </funcprototype>
+
     </funcsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
     <title>Description</title>
 
-    <para>Functions described here form parts of an event loop.</para>
-
-    <para><function>sd_event_prepare</function> checks for pending
+    <para>The low-level <function>sd_event_prepare()</function>,
+    <function>sd_event_wait()</function> and
+    <function>sd_event_dispatch()</function> functions may be used to
+    execute specific phases of an event loop. See
+    <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    and
+    <citerefentry><refentrytitle>sd_event_loop</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    for higher-level functions that execute individual but complete
+    iterations of an event loop or run it continuously.</para>
+
+    <para><function>sd_event_prepare()</function> checks for pending
     events and arms necessary timers. If any events are ready to be
-    processed, it returns a positive value, and the events should be
-    processed with <function>sd_event_dispatch</function>.
-    <function>sd_event_dispatch</function> runs a handler for one of
-    the events from the sources with the highest priority. On success,
-    <function>sd_event_dispatch</function> returns either 0, which
-    means that the loop is finished, or a positive value, which means
-    that the loop is again in the initial state and
-    <function>sd_event_prepare</function> should be called again.
-    </para>
+    processed ("pending"), it returns a positive, non-zero value, and the caller
+    should process these events with
+    <function>sd_event_dispatch()</function>.</para>
+
+    <para><function>sd_event_dispatch()</function> dispatches the
+    highest priority event source that has a pending event. On
+    success, <function>sd_event_dispatch()</function> returns either
+    zero, which indicates that no further event sources may be
+    dispatched and exiting of the event loop was requested via
+    <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>;
+    or a positive non-zero value, which means that an event source was
+    dispatched and the loop returned to its initial state, and the
+    caller should initiate the next event loop iteration by invoking
+    <function>sd_event_prepare()</function> again.</para>
+
+    <para>In case <function>sd_event_prepare()</function> returned
+    zero, <function>sd_event_wait()</function> should be called to
+    wait for further events or a timeout. If any events are ready to
+    be processed, it returns a positive, non-zero value, and the
+    events should be dispatched with
+    <function>sd_event_dispatch()</function>. Otherwise, the event
+    loop returned to its initial state and the next event loop
+    iteration should be initiated by invoking
+    <function>sd_event_prepare()</function> again.</para>
+
+    <para><function>sd_event_get_state()</function> may be used to
+    determine the state the event loop is currently in. It returns one
+    of the states described below.</para>
+
+    <para>All four functions take, as the first argument, the event
+    loop object <parameter>event</parameter> that has been created
+    with <function>sd_event_new()</function>. The timeout for
+    <function>sd_event_wait()</function> is specified in
+    <parameter>usec</parameter> in milliseconds.  <constant>(uint64_t)
+    -1</constant> may be used to specify an infinite timeout.</para>
+</refsect1>
+
+  <refsect1>
+    <title>State Machine</title>
+
+    <para>The event loop knows the following states, that may be
+    queried with <function>sd_event_get_state()</function>.</para>
 
-    <para>In case <function>sd_event_prepare</function> returned 0,
-    <function>sd_event_wait</function> should be called to wait for
-    events or a timeout. If any events are ready to be processed, it
-    returns a positive value, and the events should be processed with
-    <function>sd_event_dispatch</function>. Otherwise, the loop is
-    back in the initial state and <function>sd_event_prepare</function>
-    should be called again.</para>
+    <variablelist>
+      <varlistentry>
+        <term><constant>SD_EVENT_INITIAL</constant></term>
+
+        <listitem><para>The initial state the event loop is in,
+        before each event loop iteration. Use
+        <function>sd_event_prepare()</function> to transition the
+        event loop into the <constant>SD_EVENT_ARMED</constant> or
+        <constant>SD_EVENT_PENDING</constant> states.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_PREPARING</constant></term>
+
+        <listitem><para>An event source is currently being prepared,
+        i.e. the preparation handler is currently being executed, as
+        set with
+        <citerefentry><refentrytitle>sd_event_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
+        state is only seen in the event source preparation handler
+        that is invoked from the
+        <function>sd_event_prepare()</function> call and is
+        immediately followed by <constant>SD_EVENT_ARMED</constant> or
+        <constant>SD_EVENT_PENDING</constant>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_ARMED</constant></term>
+
+        <listitem><para><function>sd_event_prepare()</function> has
+        been called and no event sources were ready to be
+        dispatched. Use <function>sd_event_wait()</function> to wait
+        for new events, and transition into
+        <constant>SD_EVENT_PENDING</constant> or back into
+        <constant>SD_EVENT_INITIAL</constant>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_PENDING</constant></term>
+
+        <listitem><para><function>sd_event_prepare()</function> or
+        <function>sd_event_wait()</function> have been called and
+        there were event sources with events pending. Use
+        <function>sd_event_dispatch()</function> to dispatch the
+        highest priority event source and transition back to
+        <constant>SD_EVENT_INITIAL</constant>, or
+        <constant>SD_EVENT_FINISHED</constant>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_RUNNING</constant></term>
+
+        <listitem><para>A regular event source is currently being
+        dispatched. This state is only seen in the event source
+        handler that is invoked from the
+        <function>sd_event_dispatch()</function> call, and is
+        immediately followed by <constant>SD_EVENT_INITIAL</constant>
+        or <constant>SD_EVENT_FINISHED</constant> as soon the event
+        source handler returns. Note that during dispatching of exit
+        event sources the <constant>SD_EVENT_EXITING</constant> state
+        is seen instead.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_EXITING</constant></term>
+
+        <listitem><para>Similar to
+        <constant>SD_EVENT_RUNNING</constant> but is the state in
+        effect while dispatching exit event sources. It is followed by
+        <constant>SD_EVENT_INITIAL</constant> or
+        <constant>SD_EVENT_FINISHED</constant> as soon as the event
+        handler returns.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><constant>SD_EVENT_FINISHED</constant></term>
+
+        <listitem><para>The event loop has exited. All exit event
+        sources have run. If the event loop is in this state it serves
+        no purpose anymore, and should be freed.</para></listitem>
+      </varlistentry>
+
+    </variablelist>
+
+    <para>A simplified flow chart of the states and the calls to
+    transition between them is shown below. Note that
+    <constant>SD_EVENT_PREPARING</constant>,
+    <constant>SD_EVENT_RUNNING</constant> and
+    <constant>SD_EVENT_EXITING</constant> are not shown here.</para>
 
     <programlisting>
-             ┌──────────┐
-             │ initial  ├──←←←←←←←←←←←←←←←←←←←─┐
-             └───┬──────┘                      ↑
-                 │                             ↑
-           sd_event_prepare   ┌─────────┐      ↑
-                 ├ 0 →→→→→→→──┤  armed  │      ↑
-                 1            └───┬─────┘      ↑
-                 ↓                │            ↑
-                 ↓           sd_event_wait     ↑
-                 ├───←←←←←←←─── 1 ┴─ 0 →→→→→→→─┘
-             ┌───┴──────┐                      ↑
-             │ pending  │                      ↑
-             └───┬──────┘                      ↑
-                 │                             ↑
-           sd_event_dispatch                   ↑
-                 ↓                             ↑
-                 ├ 1 ──────────→→→→→→→─────────┘
-                 0
-                 ↓
-             ┌───┴──────┐
-             │ finished │
-             └──────────┘
+          INITIAL -&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---&lt;---\
+             |                                                     |
+             |                                                     ^
+             |                                                     |
+             v                 ret == 0                            |
+      sd_event_prepare() &gt;---&gt;---&gt;---&gt;---&gt;- ARMED                  |
+             |                                |                    ^
+             | ret > 0                        |                    |
+             |                                |                    |
+             v                                v          ret == 0  |
+          PENDING &lt;---&lt;---&lt;---&lt;---&lt;---&lt; sd_event_wait() &gt;---&gt;---&gt;--+
+             |           ret > 0                                   ^
+             |                                                     |
+             |                                                     |
+             v                                                     |
+      sd_event_dispatch() &gt;---&gt;---&gt;---&gt;---&gt;---&gt;---&gt;---&gt;---&gt;---&gt;---&gt;/
+             |                             ret > 0
+             | ret == 0
+             |
+             v
+          FINISHED
     </programlisting>
-
-    <para>All three functions take, as the first argument, the event
-    loop object <parameter>event</parameter> that is created with
-    <function>sd_event_new</function>. The timeout for
-    <function>sd_event_wait</function> is specified with
-    <parameter>timeout</parameter> in milliseconds.
-    <constant>(uint64_t) -1</constant> may be used to specify an
-    infinite timeout.</para>
   </refsect1>
 
   <refsect1>
 
     <para>On success, these functions return 0 or a positive integer.
     On failure, they return a negative errno-style error code. In case
-    of <function>sd_event_prepare</function> and
-    <function>sd_event_wait</function>, a positive value means that
-    events are ready to be processed and 0 means that no events are
-    ready. In case of <function>sd_event_dispatch</function>, a
-    positive value means that the loop is again in the initial state
-    and 0 means the loop is finished. For any of these functions, a
-    negative return value means the loop must be aborted.</para>
+    of <function>sd_event_prepare()</function> and
+    <function>sd_event_wait()</function>, a positive, non-zero return
+    code indicates that events are ready to be processed and zero
+    indicates that no events are ready. In case of
+    <function>sd_event_dispatch()</function>, a positive, non-zero
+    return code indicates that the event loop returned to its initial
+    state and zero indicates the event loop has
+    exited. <function>sd_event_get_state()</function> returns a
+    positive or zero state on success.</para>
   </refsect1>
 
   <refsect1>
         <term><constant>-EINVAL</constant></term>
 
         <listitem><para>The <parameter>event</parameter> parameter is
-        <constant>NULL</constant>.</para></listitem>
+        invalid or <constant>NULL</constant>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
     <para>Other errors are possible, too.</para>
   </refsect1>
 
-  <refsect1>
-    <title>Notes</title>
-
-    <para>Functions described here are available
-    as a shared library, which can be compiled and linked to with the
-    <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    file.</para>
-  </refsect1>
+  <xi:include href="libsystemd-pkgconfig.xml" />
 
   <refsect1>
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+      <citerefentry><refentrytitle>sd_event_add_post</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_source_set_prepare</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml
new file mode 100644 (file)
index 0000000..fa58841
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_journal_enumerate_fields">
+
+  <refentryinfo>
+    <title>sd_journal_enumerate_fields</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_journal_enumerate_fields</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_journal_enumerate_fields</refname>
+    <refname>sd_journal_restart_fields</refname>
+    <refname>SD_JOURNAL_FOREACH_FIELD</refname>
+    <refpurpose>Read used field names from the journal</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-journal.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_journal_enumerate_fields</function></funcdef>
+        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+        <paramdef>const char **<parameter>field</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_journal_restart_fields</function></funcdef>
+        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef><function>SD_JOURNAL_FOREACH_FIELD</function></funcdef>
+        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+        <paramdef>const char *<parameter>field</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_journal_enumerate_fields()</function> may be used to iterate through all field names used in the
+    opened journal files. On each invocation the next field name is returned. The order of the returned field names is
+    not defined. It takes two arguments: the journal context object, plus a pointer to a constant string pointer where
+    the field name is stored in. The returned data is in a read-only memory map and is only valid until the next
+    invocation of <function>sd_journal_enumerate_fields()</function>. Note that this call is subject to the data field
+    size threshold as controlled by <function>sd_journal_set_data_threshold()</function>.</para>
+
+    <para><function>sd_journal_restart_fields()</function> resets the field name enumeration index to the beginning of
+    the list. The next invocation of <function>sd_journal_enumerate_fields()</function> will return the first field
+    name again.</para>
+
+    <para>The <function>SD_JOURNAL_FOREACH_FIELD()</function> macro may be used as a handy wrapper around
+    <function>sd_journal_restart_fields()</function> and <function>sd_journal_enumerate_fields()</function>.</para>
+
+    <para>These functions currently are not influenced by matches set with <function>sd_journal_add_match()</function>
+    but this might change in a later version of this software.</para>
+
+    <para>To retrieve the possible values a specific field can take use
+    <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para><function>sd_journal_enumerate_fields()</function> returns a
+    positive integer if the next field name has been read, 0 when no
+    more field names are known, or a negative errno-style error code.
+    <function>sd_journal_restart_fields()</function> returns
+    nothing.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Notes</title>
+
+    <para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
+    interfaces are available as a shared library, which can be compiled and linked to with the
+    <constant>libsystemd</constant> <citerefentry
+    project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Examples</title>
+
+    <para>Use the <function>SD_JOURNAL_FOREACH_FIELD</function> macro to iterate through all field names in use in the
+    current journal.</para>
+
+    <programlisting>#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;systemd/sd-journal.h&gt;
+
+int main(int argc, char *argv[]) {
+        sd_journal *j;
+        const char *field;
+        int r;
+
+        r = sd_journal_open(&amp;j, SD_JOURNAL_LOCAL_ONLY);
+        if (r &lt; 0) {
+                fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
+                return 1;
+        }
+        SD_JOURNAL_FOREACH_FIELD(j, field)
+                printf("%s\n", field);
+        sd_journal_close(j);
+        return 0;
+}</programlisting>
+
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml
new file mode 100644 (file)
index 0000000..237e649
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2016 Jan Synáček
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_journal_has_runtime_files">
+
+  <refentryinfo>
+    <title>sd_journal_has_runtime_files</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Jan</firstname>
+        <surname>Synáček</surname>
+        <email>jan.synacek@gmail.com</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_journal_has_runtime_files</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_journal_has_runtime_files</refname>
+    <refname>sd_journal_has_persistent_files</refname>
+    <refpurpose>Query availability of runtime or persistent journal files.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-journal.h&gt;</funcsynopsisinfo>
+
+      <funcprototype>
+        <funcdef>int <function>sd_journal_has_runtime_files</function></funcdef>
+        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>int <function>sd_journal_has_persistent_files</function></funcdef>
+        <paramdef>sd_journal *<parameter>j</parameter></paramdef>
+      </funcprototype>
+
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><function>sd_journal_has_runtime_files()</function> returns a positive value
+    if runtime journal files (present in /run/systemd/journal/) have been found.
+    Otherwise returns 0.</para>
+
+    <para><function>sd_journal_has_persistent_files()</function> returns a positive value
+    if persistent journal files (present in /var/log/journal/) have been found.
+    Otherwise returns 0.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return value</title>
+    <para>Both <function>sd_journal_has_runtime_files()</function>
+    and <function>sd_journal_has_persistent_files()</function> return -EINVAL
+    if their argument is NULL.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index ac0e5f633f30fcebb4f1d704fa05e0a53811ae14..dbff55c1053f20c27d03117b8f95667830c68d91 100644 (file)
     <para>Note that these functions currently are not influenced by
     matches set with <function>sd_journal_add_match()</function> but
     this might change in a later version of this software.</para>
+
+    <para>To enumerate all field names currently in use (and thus all suitable field parameters for
+    <function>sd_journal_query_unique()</function>), use the
+    <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    call.</para>
   </refsect1>
 
   <refsect1>
 #include &lt;systemd/sd-journal.h&gt;
 
 int main(int argc, char *argv[]) {
-  sd_journal *j;
-  const void *d;
-  size_t l;
-  int r;
-
-  r = sd_journal_open(&amp;j, SD_JOURNAL_LOCAL_ONLY);
-  if (r &lt; 0) {
-    fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
-    return 1;
-  }
-  r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
-  if (r &lt; 0) {
-    fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
-    return 1;
-  }
-  SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
-    printf("%.*s\n", (int) l, (const char*) d);
-  sd_journal_close(j);
-  return 0;
+        sd_journal *j;
+        const void *d;
+        size_t l;
+        int r;
+
+        r = sd_journal_open(&amp;j, SD_JOURNAL_LOCAL_ONLY);
+        if (r &lt; 0) {
+                fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
+                return 1;
+        }
+        r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
+        if (r &lt; 0) {
+                fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
+                return 1;
+        }
+        SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
+                printf("%.*s\n", (int) l, (const char*) d);
+        sd_journal_close(j);
+        return 0;
 }</programlisting>
 
   </refsect1>
@@ -198,6 +203,7 @@ int main(int argc, char *argv[]) {
       <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
index db21d702529bd215348379a58ee6bf9f3757f813..5625ab9207c8a0d51be9d4ff1fc797f7e0de43b3 100644 (file)
@@ -45,6 +45,7 @@
   <refnamediv>
     <refname>sd_login_monitor_new</refname>
     <refname>sd_login_monitor_unref</refname>
+    <refname>sd_login_monitor_unrefp</refname>
     <refname>sd_login_monitor_flush</refname>
     <refname>sd_login_monitor_get_fd</refname>
     <refname>sd_login_monitor_get_events</refname>
         <paramdef>sd_login_monitor *<parameter>m</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>void <function>sd_login_monitor_unrefp</function></funcdef>
+        <paramdef>sd_login_monitor **<parameter>m</parameter></paramdef>
+      </funcprototype>
+
       <funcprototype>
         <funcdef>int <function>sd_login_monitor_flush</function></funcdef>
         <paramdef>sd_login_monitor *<parameter>m</parameter></paramdef>
     descriptor returned by
     <function>sd_login_monitor_get_fd()</function>.</para>
 
+    <para><function>sd_login_monitor_unrefp()</function> is similar to
+    <function>sd_login_monitor_unref()</function> but takes a pointer
+    to a pointer to an <type>sd_login_monitor</type> object. This call
+    is useful in conjunction with GCC's and LLVM's <ulink
+    url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up
+    Variable Attribute</ulink>. Note that this function is defined as
+    inline function. Use a declaration like the following, in order to
+    allocate a login monitor object that is freed automatically as the
+    code block is left:</para>
+
+    <programlisting>{
+        __attribute__((cleanup(sd_login_monitor_unrefp)) sd_login_monitor *m = NULL;
+        int r;
+        …
+        r = sd_login_monitor_default(&amp;m);
+        if (r &lt; 0)
+                fprintf(stderr, "Failed to allocate login monitor object: %s\n", strerror(-r));
+        …
+}</programlisting>
+
     <para><function>sd_login_monitor_flush()</function> may be used to
     reset the wakeup state of the monitor object. Whenever an event
     causes the monitor to wake up the event loop via the file
     state. If this call is not invoked, the file descriptor will
     immediately wake up the event loop again.</para>
 
+    <para><function>sd_login_monitor_unref()</function> and
+    <function>sd_login_monitor_unrefp()</function> execute no
+    operation if the passed in monitor object is
+    <constant>NULL</constant>.</para>
+
     <para><function>sd_login_monitor_get_fd()</function> may be used
     to retrieve the file descriptor of the monitor object that may be
     integrated in an application defined event loop, based around
index dbf63304530c84e1e6e8f2b8ff0dae8e04fb5c75..bd6cfdcd29cf910a0b83b17cbb96b49406461a91 100644 (file)
         multiple file descriptors are submitted at once, the specified
         name will be assigned to all of them. In order to assign
         different names to submitted file descriptors, submit them in
-        seperate invocations of
+        separate invocations of
         <function>sd_pid_notify_with_fds()</function>. The name may
         consist of any ASCII character, but must not contain control
         characters or <literal>:</literal>. It may not be longer than
index 6e1d505dce9e5e49398080c0409250290b69fe80..c5e6ddab024b00e082b9f16003011c2741dfea0b 100644 (file)
     <function>sd_seat_get_sessions()</function>,
     <function>sd_seat_can_multi_session()</function>,
     <function>sd_seat_can_tty()</function> and
-    <function>sd_seat_can_grapical()</function> interfaces are
+    <function>sd_seat_can_graphical()</function> interfaces are
     available as a shared library, which can be compiled and linked to
     with the
     <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
index 144ab1db61475be5729cf2ffb60a7c7ad96e9c98..6e27528a715fc9ff2f187baf2477dbc755388398 100644 (file)
     <varname>WatchdogSec=</varname> in service files. See
     <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     for details.</para>
+
+    <para>Use
+    <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+    to enable automatic watchdog support in
+    <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>-based event loops.</para>
   </refsect1>
 
   <refsect1>
       <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 755a74f9877b5a7509723d27ec4f77146419770e..1480bf8380192586eee5730f20dddfc2f39924e4 100644 (file)
@@ -683,14 +683,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             <para>Start (activate) one or more units specified on the
             command line.</para>
 
-            <para>Note that glob patterns operate on a list of currently
-            loaded units. Units which are not active and are not in a
-            failed state usually are not loaded, and would not be
-            matched by any pattern. In addition, in case of
-            instantiated units, systemd is often unaware of the
-            instance name until the instance has been started. Therefore,
-            using glob patterns with <command>start</command>
-            has limited usefulness.</para>
+            <para>Note that glob patterns operate on the set of primary names of currently loaded units. Units which
+            are not active and are not in a failed state usually are not loaded, and will not be matched by any
+            pattern. In addition, in case of instantiated units, systemd is often unaware of the instance name until
+            the instance has been started. Therefore, using glob patterns with <command>start</command> has limited
+            usefulness. Also, secondary alias names of units are not considered.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -736,9 +733,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
           <listitem>
             <para>Restart one or more units specified on the command
             line if the units are running. This does nothing if units are not
-            running.  Note that, for compatibility with Red Hat init
-            scripts, <command>condrestart</command> is equivalent to this
-            command.</para>
+            running.</para>
+            <!-- Note that we don't document condrestart here, as that is just compatibility support, and we generally
+                 don't document that. -->
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -751,14 +748,14 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
           </listitem>
         </varlistentry>
         <varlistentry>
-          <term><command>reload-or-try-restart <replaceable>PATTERN</replaceable>...</command></term>
+          <term><command>try-reload-or-restart <replaceable>PATTERN</replaceable>...</command></term>
 
           <listitem>
             <para>Reload one or more units if they support it. If not,
             restart them instead. This does nothing if the units are not
-            running. Note that, for compatibility with SysV init scripts,
-            <command>force-reload</command> is equivalent to this
-            command.</para>
+            running.</para>
+            <!-- Note that we don't document force-reload here, as that is just compatibility support, and we generally
+                 don't document that. -->
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -832,7 +829,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
             output. If you are looking for computer-parsable output,
             use <command>show</command> instead. By default, this
             function only shows 10 lines of output and ellipsizes
-            lines to fit in the terminal window. This can be changes
+            lines to fit in the terminal window. This can be changed
             with <option>--lines</option> and <option>--full</option>,
             see above. In addition, <command>journalctl
             --unit=<replaceable>NAME</replaceable></command> or
@@ -888,6 +885,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
 
             <para>Example: <command>systemctl set-property foobar.service CPUShares=777</command></para>
 
+            <para>If the specified unit appears to be inactive, the
+            changes will be only stored on disk as described
+            previously hence they will be effective when the unit will
+            be started.</para>
+
             <para>Note that this command allows changing multiple
             properties at the same time, which is preferable over
             setting them individually. Like unit file configuration
@@ -1132,7 +1134,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
                 <tbody>
                   <row>
                     <entry><literal>enabled</literal></entry>
-                    <entry morerows='1'>Enabled through a symlink in a <filename>.wants/</filename> or <filename>.requires/</filename> subdirectory of <filename>/etc/systemd/system/</filename> (persistently) or <filename>/run/systemd/system/</filename> (transiently).</entry>
+                    <entry morerows='1'>Enabled via <filename>.wants/</filename>, <filename>.requires/</filename> or alias symlinks (permanently in <filename>/etc/systemd/system/</filename>, or transiently in <filename>/run/systemd/system/</filename>).</entry>
                     <entry morerows='1'>0</entry>
                   </row>
                   <row>
@@ -1171,7 +1173,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
                   </row>
                   <row>
                     <entry><literal>bad</literal></entry>
-                    <entry>Unit file is invalid or another error occured. Note that <command>is-enabled</command> will not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
+                    <entry>Unit file is invalid or another error occurred. Note that <command>is-enabled</command> will not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
                     <entry>&gt; 0</entry>
                   </row>
                 </tbody>
@@ -1696,34 +1698,28 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
     <refsect2>
       <title>Parameter Syntax</title>
 
-      <para>Unit commands listed above take either a single unit name
-      (designated as <replaceable>NAME</replaceable>), or multiple
-      unit specifications (designated as
-      <replaceable>PATTERN</replaceable>...). In the first case, the
-      unit name with or without a suffix must be given. If the suffix
-      is not specified, systemctl will append a suitable suffix,
-      <literal>.service</literal> by default, and a type-specific
-      suffix in case of commands which operate only on specific unit
-      types. For example,
+      <para>Unit commands listed above take either a single unit name (designated as <replaceable>NAME</replaceable>),
+      or multiple unit specifications (designated as <replaceable>PATTERN</replaceable>...). In the first case, the
+      unit name with or without a suffix must be given. If the suffix is not specified (unit name is "abbreviated"),
+      systemctl will append a suitable suffix, <literal>.service</literal> by default, and a type-specific suffix in
+      case of commands which operate only on specific unit types. For example,
       <programlisting># systemctl start sshd</programlisting> and
       <programlisting># systemctl start sshd.service</programlisting>
       are equivalent, as are
       <programlisting># systemctl isolate default</programlisting>
       and
       <programlisting># systemctl isolate default.target</programlisting>
-      Note that (absolute) paths to device nodes are automatically
-      converted to device unit names, and other (absolute) paths to
-      mount unit names.
+      Note that (absolute) paths to device nodes are automatically converted to device unit names, and other (absolute)
+      paths to mount unit names.
       <programlisting># systemctl status /dev/sda
 # systemctl status /home</programlisting>
       are equivalent to:
       <programlisting># systemctl status dev-sda.device
 # systemctl status home.mount</programlisting>
-      In the second case, shell-style globs will be matched against
-      currently loaded units; literal unit names, with or without
-      a suffix, will be treated as in the first case. This means that
-      literal unit names always refer to exactly one unit, but globs
-      may match zero units and this is not considered an error.</para>
+      In the second case, shell-style globs will be matched against the primary names of all currently loaded units;
+      literal unit names, with or without a suffix, will be treated as in the first case. This means that literal unit
+      names always refer to exactly one unit, but globs may match zero units and this is not considered an
+      error.</para>
 
       <para>Glob patterns use
       <citerefentry project='man-pages'><refentrytitle>fnmatch</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@@ -1731,16 +1727,16 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
       <literal>*</literal>, <literal>?</literal>,
       <literal>[]</literal> may be used. See
       <citerefentry project='man-pages'><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-      for more details. The patterns are matched against the names of
+      for more details. The patterns are matched against the primary names of
       currently loaded units, and patterns which do not match anything
       are silently skipped. For example:
       <programlisting># systemctl stop sshd@*.service</programlisting>
-      will stop all <filename>sshd@.service</filename> instances.
+      will stop all <filename>sshd@.service</filename> instances. Note that alias names of units, and units that aren't
+      loaded are not considered for glob expansion.
       </para>
 
-      <para>For unit file commands, the specified
-      <replaceable>NAME</replaceable> should be the full name of the
-      unit file, or the absolute path to the unit file:
+      <para>For unit file commands, the specified <replaceable>NAME</replaceable> should be the name of the unit file
+      (possibly abbreviated, see above), or the absolute path to the unit file:
       <programlisting># systemctl enable foo.service</programlisting>
       or
       <programlisting># systemctl link /path/to/foo.service</programlisting>
index 5fe1a39057a320e8e2ee718a56537492584ebd54..995e6eecce6cf2535c8d51a9f018eecb296dff13 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para><command>systemd-activate</command> can be used to
-    launch a socket-activated daemon from the command line for
-    testing purposes. It can also be used to launch single instances
-    of the daemon per connection (inetd-style).
+    <para><command>systemd-activate</command> may be used to launch a socket-activated service binary from the command
+    line for testing purposes. It may also be used to launch individual instances of the service binary per connection.
     </para>
 
     <para>The daemon to launch and its options should be specified
     after options intended for <command>systemd-activate</command>.
     </para>
 
-    <para>If the <option>-a</option> option is given, file descriptor
-    of the connection will be used as the standard input and output of
-    the launched process. Otherwise, standard input and output will be
-    inherited, and sockets will be passed through file descriptors 3
-    and higher. Sockets passed through <varname>$LISTEN_FDS</varname>
-    to <command>systemd-activate</command> will be passed through to
-    the daemon, in the original positions. Other sockets specified
-    with <option>--listen</option> will use consecutive descriptors.
+    <para>If the <option>--inetd</option> option is given, the socket file descriptor will be used as the standard
+    input and output of the launched process. Otherwise, standard input and output will be inherited, and sockets will
+    be passed through file descriptors 3 and higher. Sockets passed through <varname>$LISTEN_FDS</varname> to
+    <command>systemd-activate</command> will be passed through to the daemon, in the original positions. Other sockets
+    specified with <option>--listen=</option> will use consecutive descriptors.  By default,
+    <command>systemd-activate</command> listens on a stream socket, use <option>--datagram</option> and
+    <option>--seqpacket</option> to listen on datagram or sequential packet sockets instead (see below).
     </para>
   </refsect1>
 
         <term><option>-a</option></term>
         <term><option>--accept</option></term>
 
-        <listitem><para>Launch a separate instance of daemon per
-        connection and pass the connection socket as standard input
-        and standard output.</para></listitem>
+        <listitem><para>Launch an instance of the service binary for each connection and pass the connection
+        socket.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-d</option></term>
+        <term><option>--datagram</option></term>
+
+        <listitem><para>Listen on a datagram socket (<constant>SOCK_DGRAM</constant>), instead of a stream socket
+        (<constant>SOCK_STREAM</constant>). May not be combined with <option>--seqpacket</option>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--seqpacket</option></term>
+
+        <listitem><para>Listen on a sequential packet socket (<constant>SOCK_SEQPACKET</constant>), instead of a stream
+        socket (<constant>SOCK_STREAM</constant>). May not be combined with
+        <option>--datagram</option>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--inetd</option></term>
+
+        <listitem><para>Use the inetd protocol for passing file descriptors, i.e. as standard input and standard
+        output, instead of the new-style protocol for passing file descriptors using <varname>$LISTEN_FDS</varname>
+        (see above).</para></listitem>
       </varlistentry>
 
       <varlistentry>
     <example>
       <title>Run an echo server on port 2000</title>
 
-      <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 -a cat</programlisting>
+      <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 --inetd -a cat</programlisting>
     </example>
 
     <example>
index 6fb322e8499d542433d2c7e4a6e4ba420a962f17..2a4d24349b82d9d1b9987d27f250c3adf62c0ff5 100644 (file)
         possible to cache multiple passwords under the same keyname,
         in which case they will be stored as NUL-separated list of
         passwords. Use
-        <citerefentry><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        <citerefentry project='die-net'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
         to access the cached key via the kernel keyring
         directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
       </varlistentry>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>keyctl</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>
     </para>
index 5d19322cdcb561241d878122a85ee053278bf82d..2b7f4e69ab0da1cc9fd4e18c2d20d8a27330b160 100644 (file)
@@ -59,7 +59,7 @@
 
     <para><command>systemd-detect-virt</command> detects execution in
     a virtualized environment. It identifies the virtualization
-    technology and can distinguish full VM virtualization from
+    technology and can distinguish full machine virtualization from
     container virtualization. <filename>systemd-detect-virt</filename>
     exits with a return value of 0 (success) if a virtualization
     technology is detected, and non-zero (error) otherwise. By default,
@@ -88,7 +88,7 @@
         </thead>
         <tbody>
           <row>
-            <entry morerows="9">VM</entry>
+            <entry valign="top" morerows="9">VM</entry>
             <entry><varname>qemu</varname></entry>
             <entry>QEMU software virtualization</entry>
           </row>
           </row>
 
           <row>
-            <entry morerows="5">Container</entry>
+            <entry valign="top" morerows="5">Container</entry>
             <entry><varname>openvz</varname></entry>
             <entry>OpenVZ/Virtuozzo</entry>
           </row>
     </table>
 
     <para>If multiple virtualization solutions are used, only the
-    "innermost" is detected and identified. That means if both VM
-    virtualization and container virtualization are used in
+    "innermost" is detected and identified. That means if both
+    machine and container virtualization are used in
     conjunction, only the latter will be identified (unless
     <option>--vm</option> is passed).</para>
   </refsect1>
         <term><option>-v</option></term>
         <term><option>--vm</option></term>
 
-        <listitem><para>Only detects VM virtualization (i.e. full
-        hardware virtualization).</para></listitem>
+        <listitem><para>Only detects hardware virtualization).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 5407773f2369790017d73957d7e85e18bbe8d266..dbb3869a24fbf589d9d08f535513ea711f5dfb41 100644 (file)
@@ -64,7 +64,7 @@
     used to escape and to undo escaping of strings.</para>
 
     <para>The command takes any number of strings on the command line,
-    and will process them individually, one after the other. It will
+    and will process them individually, one after another. It will
     output them separated by spaces to stdout.</para>
 
     <para>By default, this command will escape the strings passed,
index 6df2248578f8155268096e269de43feb99f984ef..e32ac268505f2b7c915c7ba718e8e08c947b9e41 100644 (file)
       </varlistentry>
 
       <varlistentry>
-        <term><constant>application/event-stream</constant></term>
+        <term><constant>text/event-stream</constant></term>
 
         <listitem><para>Entries are formatted as JSON data structures,
         wrapped in a format suitable for <ulink
index ebaca2657f48859be0c446811bbe6d4e84d81a1a..3899f175d4848989abf7b82d5904f7baf737f35f 100644 (file)
@@ -293,15 +293,24 @@ journalctl -o export | systemd-journal-remote -o /tmp/dir -
     </programlisting>
     </para>
 
-    <para>Retrieve events from a remote
+    <para>Retrieve all available events from a remote
     <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     instance and store them in
-    <filename>/var/log/journal/some.host/remote-some~host.journal</filename>:
+    <filename>/var/log/journal/remote/remote-some.host.journal</filename>:
     <programlisting>
 systemd-journal-remote --url http://some.host:19531/
     </programlisting>
     </para>
-  </refsect1>
+
+    <para>Retrieve current boot events and wait for new events from a remote
+    <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    instance, and store them in
+    <filename>/var/log/journal/remote/remote-some.host.journal</filename>:
+    <programlisting>
+systemd-journal-remote --url http://some.host:19531/entries?boot&amp;follow
+    </programlisting>
+    </para>
+</refsect1>
 
   <refsect1>
     <title>See Also</title>
index f1054b03bb1255591de6b473d942c23e21ca2ffc..2810638bc26f46f58212412bf130e93678be49af 100644 (file)
     <programlisting>mkdir -p /var/log/journal
 systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
 
-    <para><filename>systemd-journald</filename> will forward all
-    received log messages to the
-    <constant>AF_UNIX</constant>/<constant>SOCK_DGRAM</constant>
-    socket <filename>/run/systemd/journal/syslog</filename>, if it
-    exists, which may be used by Unix syslog daemons to process the
-    data further.</para>
-
     <para>See
     <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     for information about the configuration of this service.</para>
index a97b7c44eb913cba2eb500eb43ab9be09edd0971..86cdb4e1245081087e2bdbb8a9dcc2677b649b6a 100644 (file)
         <option>--ephemeral</option>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>-a</option></term>
+        <term><option>--as-pid2</option></term>
+
+        <listitem><para>Invoke the shell or specified program as process ID (PID) 2 instead of PID 1 (init). By
+        default, if neither this option nor <option>--boot</option> is used, the selected binary is run as process with
+        PID 1, a mode only suitable for programs that are aware of the special semantics that the process with PID 1
+        has on UNIX. For example, it needs to reap all processes reparented to it, and should implement
+        <command>sysvinit</command> compatible signal handling (specifically: it needs to reboot on SIGINT, reexecute
+        on SIGTERM, reload configuration on SIGHUP, and so on). With <option>--as-pid2</option> a minimal stub init
+        process is run as PID 1 and the selected binary is executed as PID 2 (and hence does not need to implement any
+        special semantics). The stub init process will reap processes as necessary and react appropriately to
+        signals. It is recommended to use this mode to invoke arbitrary commands in containers, unless they have been
+        modified to run correctly as PID 1. Or in other words: this switch should be used for pretty much all commands,
+        except when the command refers to an init or shell implementation, as these are generally capable of running
+        correctly as PID 1). This option may not be combined with <option>--boot</option> or
+        <option>--share-system</option>.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>-b</option></term>
         <term><option>--boot</option></term>
 
-        <listitem><para>Automatically search for an init binary and
-        invoke it instead of a shell or a user supplied program. If
-        this option is used, arguments specified on the command line
-        are used as arguments for the init binary. This option may not
-        be combined with <option>--share-system</option>.
-        </para></listitem>
+        <listitem><para>Automatically search for an init binary and invoke it as PID 1, instead of a shell or a user
+        supplied program. If this option is used, arguments specified on the command line are used as arguments for the
+        init binary. This option may not be combined with <option>--as-pid2</option> or
+        <option>--share-system</option>.</para>
+
+        <para>The following table explains the different modes of invocation and relationship to
+        <option>--as-pid2</option> (see above):</para>
+
+        <table>
+          <title>Invocation Mode</title>
+          <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+            <colspec colname="switch" />
+            <colspec colname="explanation" />
+            <thead>
+              <row>
+                <entry>Switch</entry>
+                <entry>Explanation</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>Neither <option>--as-pid2</option> nor <option>--boot</option> specified</entry>
+                <entry>The passed parameters are interpreted as command line, which is executed as PID 1 in the container.</entry>
+              </row>
+
+              <row>
+                <entry><option>--as-pid2</option> specified</entry>
+                <entry>The passed parameters are interpreted as command line, which are executed as PID 2 in the container. A stub init process is run as PID 1.</entry>
+              </row>
+
+              <row>
+                <entry><option>--boot</option> specified</entry>
+                <entry>An init binary as automatically searched and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process.</entry>
+              </row>
+
+            </tbody>
+          </tgroup>
+        </table>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--chdir=</option></term>
+
+        <listitem><para>Change to the specified working directory before invoking the process in the container. Expects
+        an absolute path in the container's file system namespace.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <option>yes</option>, full volatile mode is enabled. This
         means the root directory is mounted as a mostly unpopulated
         <literal>tmpfs</literal> instance, and
-        <filename>/usr</filename> from the OS tree is mounted into it,
-        read-only (the system thus starts up with read-only OS
+        <filename>/usr</filename> from the OS tree is mounted into it
+        in read-only mode (the system thus starts up with read-only OS
         resources, but pristine state and configuration, any changes
         to the either are lost on shutdown). When the mode parameter
         is specified as <option>state</option>, the OS tree is
index da6026e3b38928a06d2eb02d6ea64d0568622740..e2b23eec5109b83918e29720cc992e14a5dcd5a3 100644 (file)
@@ -60,7 +60,7 @@
     <para><command>systemd-path</command> may be used to query system
     and user paths. The tool makes many of the paths described in
     <citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-    queriable.</para>
+    available for querying.</para>
 
     <para>When invoked without arguments, a list of known paths and
     their current values is shown. When at least one argument is
diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml
new file mode 100644 (file)
index 0000000..f1e663c
--- /dev/null
@@ -0,0 +1,277 @@
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="systemd-resolve"
+          xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>systemd-resolve</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>systemd-resolve</refentrytitle>
+    <manvolnum>1</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>systemd-resolve</refname>
+    <refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="plain" rep="repeat"><replaceable>HOSTNAME</replaceable></arg>
+    </cmdsynopsis>
+
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="plain" rep="repeat"><replaceable>ADDRESS</replaceable></arg>
+    </cmdsynopsis>
+
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <command> --type=<replaceable>TYPE</replaceable></command>
+      <arg choice="plain" rep="repeat"><replaceable>RRDOMAIN</replaceable></arg>
+    </cmdsynopsis>
+
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <command> --service</command>
+      <arg choice="plain"><arg choice="opt"><arg choice="opt"><replaceable>NAME</replaceable></arg>
+      <replaceable>TYPE</replaceable></arg> <replaceable>DOMAIN</replaceable></arg>
+    </cmdsynopsis>
+
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <command> --statistics</command>
+    </cmdsynopsis>
+
+    <cmdsynopsis>
+      <command>systemd-resolve</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <command> --reset-statistics</command>
+    </cmdsynopsis>
+
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><command>systemd-resolve</command> may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource
+    records and services with the
+    <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    resolver service. By default, the specified list of parameters will be resolved as hostnames, retrieving their IPv4
+    and IPv6 addresses. If the parameters specified are formatted as IPv4 or IPv6 operation the reverse operation is
+    done, and a hostname is retrieved for the specified addresses.</para>
+
+    <para>The <option>--type=</option> switch may be used to specify a DNS resource record type (A, AAAA, SOA, MX, ...) in
+    order to request a specific DNS resource record, instead of the address or reverse address lookups.
+    The special value <literal>help</literal> may be used to list known values.</para>
+
+    <para>The <option>--service</option> switch may be used to resolve <ulink
+    url="https://tools.ietf.org/html/rfc2782">SRV</ulink> and <ulink
+    url="https://tools.ietf.org/html/rfc6763">DNS-SD</ulink> services (see below). In this mode, between one and three
+    arguments are required. If three parameters are passed the first is assumed to be the DNS-SD service name, the
+    second the SRV service type, and the third the domain to search in. In this case a full DNS-SD style SRV and TXT
+    lookup is executed. If only two parameters are specified, the first is assumed to be the SRV service type, and the
+    second the domain to look in. In this case no TXT RR is requested. Finally, if only one parameter is specified, it
+    is assumed to be a domain name, that is already prefixed with an SRV type, and an SRV lookup is done (no
+    TXT).</para>
+
+    <para>The <option>--statistics</option> switch may be used to show resolver statistics, including information about
+    the number of succesful and failed DNSSEC validations.</para>
+
+    <para>The <option>--reset-statistics</option> may be used to reset various statistics counters maintained the
+    resolver, including those shown in the <option>--statistics</option> output. This operation requires root
+    privileges.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Options</title>
+    <variablelist>
+      <varlistentry>
+        <term><option>-4</option></term>
+        <term><option>-6</option></term>
+
+        <listitem><para>By default, when resolving a hostname, both IPv4 and IPv6
+        addresses are acquired. By specifying <option>-4</option> only IPv4 addresses are requested, by specifying
+        <option>-6</option> only IPv6 addresses are requested.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-i</option> <replaceable>INTERFACE</replaceable></term>
+        <term><option>--interface=</option><replaceable>INTERFACE</replaceable></term>
+
+        <listitem><para>Specifies the network interface to execute the query on. This may either be specified as numeric
+        interface index or as network interface string (e.g. <literal>en0</literal>). Note that this option has no
+        effect if system-wide DNS configuration (as configured in <filename>/etc/resolv.conf</filename> or
+        <filename>/etc/systemd/resolve.conf</filename>) in place of per-link configuration is used.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-p</option> <replaceable>PROTOCOL</replaceable></term>
+        <term><option>--protocol=</option><replaceable>PROTOCOL</replaceable></term>
+
+        <listitem><para>Specifies the network protocol for the query. May be one of <literal>dns</literal>
+        (i.e. classic unicast DNS), <literal>llmnr</literal> (<ulink
+        url="https://tools.ietf.org/html/rfc4795">Link-Local Multicast Name Resolution</ulink>),
+        <literal>llmr-ipv4</literal>, <literal>llmnr-ipv6</literal> (LLMNR via the indicated underlying IP
+        protocols). By default the lookup is done via all protocols suitable for the lookup. If used, limits the set of
+        protocols that may be used. Use this option multiple times to enable resolving via multiple protocols at the
+        same time. The setting <literal>llmnr</literal> is identical to specifying this switch once with
+        <literal>llmnr-ipv4</literal> and once via <literal>llmnr-ipv6</literal>. Note that this option does not force
+        the service to resolve the operation with the specified protocol, as that might require a suitable network
+        interface and configuration.
+        The special value <literal>help</literal> may be used to list known values.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-t</option> <replaceable>TYPE</replaceable></term>
+        <term><option>--type=</option><replaceable>TYPE</replaceable></term>
+        <term><option>-c</option> <replaceable>CLASS</replaceable></term>
+        <term><option>--class=</option><replaceable>CLASS</replaceable></term>
+
+        <listitem><para>Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to
+        look up. If these options are used a DNS resource record set matching the specified class and type is
+        requested. The class defaults to IN if only a type is specified.
+        The special value <literal>help</literal> may be used to list known values.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--service</option></term>
+
+        <listitem><para>Enables service resolution. This enables DNS-SD and simple SRV service resolution, depending
+        on the specified list of parameters (see above).</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--service-address=</option><replaceable>BOOL</replaceable></term>
+
+        <listitem><para>Takes a boolean parameter. If true (the default), when doing a service lookup with
+        <option>--service</option> the hostnames contained in the SRV resource records are resolved as well.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--service-txt=</option><replaceable>BOOL</replaceable></term>
+
+        <listitem><para>Takes a boolean parameter. If true (the default), when doing a DNS-SD service lookup with
+        <option>--service</option> the TXT service metadata record is resolved as well.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--cname=</option><replaceable>BOOL</replaceable></term>
+
+        <listitem><para>Takes a boolean parameter. If true (the default), DNS CNAME or DNAME redirections are
+        followed. Otherwise, if a CNAME or DNAME record is encountered while resolving, an error is
+        returned.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--search=</option><replaceable>BOOL</replaceable></term>
+
+        <listitem><para>Takes a boolean parameter. If true (the default), any specified single-label hostnames will be
+        searched in the domains configured in the search domain list, if it is non-empty. Otherwise, the search domain
+        logic is disabled.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--legend=</option><replaceable>BOOL</replaceable></term>
+
+        <listitem><para>Takes a boolean parameter. If true (the default), column headers and meta information about the
+        query response are shown. Otherwise, this output is suppressed.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--statistics</option></term>
+
+        <listitem><para>If specified general resolver statistics are shown, including information whether DNSSEC is
+        enabled and available, as well as resolution and validation statistics.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--reset-statistics</option></term>
+
+        <listitem><para>Resets the statistics counters shown in <option>--statistics</option> to zero.</para></listitem>
+      </varlistentry>
+
+      <xi:include href="standard-options.xml" xpointer="help" />
+      <xi:include href="standard-options.xml" xpointer="version" />
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Examples</title>
+
+    <example>
+      <title>Retrieve the addresses of the <literal>www.0pointer.net</literal> domain</title>
+
+      <programlisting>$ systemd-resolve www.0pointer.net</programlisting>
+    </example>
+
+    <example>
+      <title>Retrieve the domain of the <literal>85.214.157.71</literal> IP address</title>
+
+      <programlisting>$ systemd-resolve 85.214.157.71</programlisting>
+    </example>
+
+    <example>
+      <title>Retrieve the MX record of the <literal>0pointer.net</literal> domain</title>
+
+      <programlisting>$ systemd-resolve -t MX 0pointer.net</programlisting>
+    </example>
+
+    <example>
+      <title>Resolve an SRV service</title>
+
+      <programlisting>$ systemd-resolve --service _xmpp-server._tcp gmail.com</programlisting>
+    </example>
+
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+</refentry>
index 43d568c6f7ed1626511a9a0c3c6488f09dfe6640..7a9e23a2c61e7bcb30a9db0f5d08276f10228bde 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para><command>systemd-resolved</command> is a system service that
-    manages network name resolution. It implements a caching DNS stub
-    resolver and an LLMNR resolver and responder. It also generates
-    <filename>/run/systemd/resolve/resolv.conf</filename> for
-    compatibility which may be symlinked from
-    <filename>/etc/resolv.conf</filename>. The glibc NSS module
-    <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-    is necessary to allow libc's NSS resolver functions to resolve
-    host names via <command>systemd-resolved</command>.</para>
+    <para><command>systemd-resolved</command> is a system service that provides network name resolution to local
+    applications. It implements a caching and validating DNS/DNSSEC stub resolver, as well as an LLMNR resolver and
+    responder. In addition it maintains the <filename>/run/systemd/resolve/resolv.conf</filename> file for
+    compatibility with traditional Linux programs. This file may be symlinked from
+    <filename>/etc/resolv.conf</filename>.</para>
+
+    <para>The glibc NSS module
+    <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry> is required to
+    permit glibc's NSS resolver functions to resolve host names via <command>systemd-resolved</command>.</para>
 
     <para>The DNS servers contacted are determined from the global
     settings in <filename>/etc/systemd/resolved.conf</filename>, the
       is on the local loopback) and the IPv6 address ::1 (which is the
       local host).</para></listitem>
 
-      <listitem><para>The hostname <literal>localhost</literal> is
-      resolved to the IP addresses 127.0.0.1 and
-      ::1.</para></listitem>
+      <listitem><para>The hostname <literal>localhost</literal> (as well as any hostname ending in
+      <literal>.localhost</literal>, <literal>.localdomain</literal> or equal to <literal>localdomain</literal>) is
+      resolved to the IP addresses 127.0.0.1 and ::1.</para></listitem>
 
       <listitem><para>The hostname <literal>gateway</literal> is
       resolved to all current default routing gateway addresses,
       ordered by their metric. This assigns a stable hostname to the
       current gateway, useful for referencing it independently of the
       current network configuration state.</para></listitem>
+
+      <listitem><para>The mappings defined in <filename>/etc/hosts</filename> are resolved to their configured
+      addresses and back.</para></listitem>
     </itemizedlist>
 
     <para>Lookup requests are routed to the available DNS servers
     <itemizedlist>
       <listitem><para>Lookups for the special hostname
       <literal>localhost</literal> are never routed to the
-      network.</para></listitem>
+      network. (A few other, special domains are handled the same way.)</para></listitem>
 
       <listitem><para>Single-label names are routed to all local
       interfaces capable of IP multicasting, using the LLMNR
       <listitem><para>Multi-label names are routed to all local
       interfaces that have a DNS sever configured, plus the globally
       configured DNS server if there is one. Address lookups from the
-      link-local addres range are never routed to
+      link-local address range are never routed to
       DNS.</para></listitem>
     </itemizedlist>
 
     per-interface domains are exclusively routed to the matching
     interfaces.</para>
 
-    <para>Note that
-    <filename>/run/systemd/resolve/resolv.conf</filename> should not
-    be used directly, but only through a symlink from
-    <filename>/etc/resolv.conf</filename>.</para>
+    <para>Note that <filename>/run/systemd/resolve/resolv.conf</filename> should not be used directly by applications,
+    but only through a symlink from <filename>/etc/resolv.conf</filename>.</para>
+
+    <para>See the <ulink url="http://www.freedesktop.org/wiki/Software/systemd/resolved"> resolved D-Bus API
+    Documentation</ulink> for information about the APIs <filename>systemd-resolved</filename> provides.</para>
+
   </refsect1>
 
   <refsect1>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-resolve</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>hosts</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
index ead52951daace5a634872503f18e906479b8e13f..edc6df914aba2c1736a3c4f7594edd8cc0c6a949 100644 (file)
         <listitem><para>These settings control various default
         resource limits for units. See
         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        for details. Use the string <varname>infinity</varname> to
-        configure no limit on a specific resource. The multiplicative suffixes
-        K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for
-        resource limits measured in bytes (e.g. DefaultLimitAS=16G). These
-        settings may be overridden in individual units using the corresponding
-        LimitXXX= directives. Note that these resource limits are only
-        defaults for units, they are not applied to PID 1
+        for details. The resource limit is possible to specify in two formats,
+        <option>value</option> to set soft and hard limits to the same value,
+        or <option>soft:hard</option> to set both limits individually (e.g. DefaultLimitAS=4G:16G).
+        Use the string <varname>infinity</varname> to
+        configure no limit on a specific resource. The multiplicative
+        suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
+        may be used for resource limits measured in bytes
+        (e.g. DefaultLimitAS=16G). For the limits referring to time values,
+        the usual time units ms, s, min, h and so on may be used (see
+        <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+        for details). Note that if no time unit is specified for
+        <varname>DefaultLimitCPU=</varname> the default unit of seconds is
+        implied, while for <varname>DefaultLimitRTTIME=</varname> the default
+        unit of microseconds is implied. Also, note that the effective
+        granularity of the limits might influence their
+        enforcement. For example, time limits specified for
+        <varname>DefaultLimitCPU=</varname> will be rounded up implicitly to
+        multiples of 1s. These  settings may be overridden in individual units
+        using the corresponding LimitXXX= directives. Note that these resource
+        limits are only defaults for units, they are not applied to PID 1
         itself.</para></listitem>
       </varlistentry>
     </variablelist>
index 6dda6c5e69fa316df09153c4d8201e401a4d2e5b..f0f77c509159e524838cfc62ca3aca7041305a22 100644 (file)
         <listitem><para>These settings set both soft and hard limits
         of various resources for executed processes. See
         <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        for details. Use the string <varname>infinity</varname> to
+        for details. The resource limit is possible to specify in two formats,
+        <option>value</option> to set soft and hard limits to the same value,
+        or <option>soft:hard</option> to set both limits individually (e.g. LimitAS=4G:16G).
+        Use the string <varname>infinity</varname> to
         configure no limit on a specific resource. The multiplicative
         suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
         may be used for resource limits measured in bytes
         settings.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>AmbientCapabilities=</varname></term>
+
+        <listitem><para>Controls which capabilities to include in the
+        ambient capability set for the executed process. Takes a
+        whitespace-separated list of capability names as read by
+        <citerefentry project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+        e.g. <constant>CAP_SYS_ADMIN</constant>,
+        <constant>CAP_DAC_OVERRIDE</constant>,
+        <constant>CAP_SYS_PTRACE</constant>. This option may appear more than
+        once in which case the ambient capability sets are merged.
+        If the list of capabilities is prefixed with <literal>~</literal>, all
+        but the listed capabilities will be included, the effect of the
+        assignment inverted. If the empty string is
+        assigned to this option, the ambient capability set is reset to
+        the empty capability set, and all prior settings have no effect.
+        If set to <literal>~</literal> (without any further argument), the
+        ambient capability set is reset to the full set of available
+        capabilities, also undoing any previous settings. Note that adding
+        capabilities to ambient capability set adds them to the process's
+        inherited capability set.
+        </para><para>
+        Ambient capability sets are useful if you want to execute a process
+        as a non-privileged user but still want to give it some capabilities.
+        Note that in this case option <constant>keep-caps</constant> is
+        automatically added to <varname>SecureBits=</varname> to retain the
+        capabilities over the user change.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>SecureBits=</varname></term>
         <listitem><para>Controls the secure bits set for the executed
       <varlistentry>
         <term><varname>$LISTEN_FDS</varname></term>
         <term><varname>$LISTEN_PID</varname></term>
+        <term><varname>$LISTEN_FDNAMES</varname></term>
 
         <listitem><para>Information about file descriptors passed to a
         service for socket activation. See
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>$NOTIFY_SOCKET</varname></term>
+
+        <listitem><para>The socket
+        <function>sd_notify()</function> talks to. See
+        <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>$WATCHDOG_PID</varname></term>
+        <term><varname>$WATCHDOG_USEC</varname></term>
+
+        <listitem><para>Information about watchdog keep-alive notifications. See
+        <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>$TERM</varname></term>
 
 
     <para>Additional variables may be configured by the following
     means: for processes spawned in specific units, use the
-    <varname>Environment=</varname> and
-    <varname>EnvironmentFile=</varname> options above; to specify
+    <varname>Environment=</varname>, <varname>EnvironmentFile=</varname>
+    and <varname>PassEnvironment=</varname> options above; to specify
     variables globally, use <varname>DefaultEnvironment=</varname>
     (see
     <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
index b36aab32598ad2e1edbbaef299f1cc34bc6ad94e..4b80dab108a9e9fead2b3a28f3a416f287f541b4 100644 (file)
             Generators are run very early at boot and cannot rely on
             any external services. They may not talk to any other
             process. That includes simple things such as logging to
-            <citerefentry
-            project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+            <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
             or <command>systemd</command> itself (this means: no
-            <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>!). They
-            can however rely on the most basic kernel functionality to
-            be available, including a mounted <filename>/sys</filename>,
-            <filename>/proc</filename>, <filename>/dev</filename>.
+            <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!.
+            Non-essential file systems like
+            <filename>/var</filename> and <filename>/home</filename>
+            are mounted after generators have run. Generators
+            can however rely on the most basic kernel functionality to be
+            available, including a mounted <filename>/sys</filename>,
+            <filename>/proc</filename>, <filename>/dev</filename>,
+            <filename>/usr</filename>.
           </para>
         </listitem>
 
     </example>
 
     <example>
-      <title>Debuging a generator</title>
+      <title>Debugging a generator</title>
 
       <programlisting>dir=$(mktemp -d)
 SYSTEMD_LOG_LEVEL=debug &systemgeneratordir;/systemd-fstab-generator \
index a724d88584717d71b9ad4ce5df0bcf0dc2b0ad55..4a8d265fed72f140b2a3f34c4c530e5fbac72549 100644 (file)
@@ -88,7 +88,8 @@
     configured in a unit file <filename>home-lennart.mount</filename>.
     For details about the escaping logic used to convert a file system
     path to a unit name, see
-    <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+    <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    Note that mount units cannot be templated.</para>
 
     <para>Optionally, a mount unit may be accompanied by an automount
     unit, to allow on-demand or parallelized mounting. See
index 16e41e05b371085e57d09d6b7c96afecf1219ca4..b697d0c9a6e36137f3f382b37d65bd358dbccf73 100644 (file)
         VXLAN Group Policy </ulink> document. Defaults to false.</para>
       </listitem>
     </varlistentry>
+    <varlistentry>
+      <term><varname>DestinationPort=</varname></term>
+      <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>
+      </listitem>
+    </varlistentry>
+    <varlistentry>
+      <term><varname>PortRange=</varname></term>
+        <listitem>
+          <para>Configures VXLAN port range. VXLAN bases source
+          UDP port based on flow to help the receiver to be able
+          to load balance based on outer header flow. It
+          restricts the port range to the normal UDP local
+          ports, and allows overriding via configuration.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
index e6dedb027d11a80054ed2398e3a317cc326e43bf..f88751b672f0c21c24124782d8649416d889fe27 100644 (file)
             <literal>ipv4</literal>, or <literal>ipv6</literal>.</para>
 
             <para>Note that DHCPv6 will by default be triggered by Router
-            Advertisment, if that is enabled, regardless of this parameter.
+            Advertisement, if that is enabled, regardless of this parameter.
             By enabling DHCPv6 support explicitly, the DHCPv6 client will
             be started regardless of the presence of routers on the link,
             or what flags the routers pass. See
         <varlistentry>
           <term><varname>LLMNR=</varname></term>
           <listitem>
-            <para>A boolean or <literal>resolve</literal>. When true, enables
-            Link-Local Multicast Name Resolution on the link. When set to
-            <literal>resolve</literal>, only resolution is enabled, but not
-            announcement. Defaults to true.</para>
+            <para>A boolean or <literal>resolve</literal>. When true,
+            enables <ulink
+            url="https://tools.ietf.org/html/rfc4795">Link-Local
+            Multicast Name Resolution</ulink> on the link. When set to
+            <literal>resolve</literal>, only resolution is enabled,
+            but not host registration and announcement. Defaults to
+            true. This setting is read by
+            <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>MulticastDNS=</varname></term>
+          <listitem>
+            <para>A boolean or <literal>resolve</literal>. When true,
+            enables <ulink
+            url="https://tools.ietf.org/html/rfc6762">Multicast
+            DNS</ulink> support on the link. When set to
+            <literal>resolve</literal>, only resolution is enabled,
+            but not host or service registration and
+            announcement. Defaults to false. This setting is read by
+            <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>DNSSEC=</varname></term>
+          <listitem>
+            <para>A boolean or
+            <literal>allow-downgrade</literal>. When true, enables
+            <ulink
+            url="https://tools.ietf.org/html/rfc4033">DNSSEC</ulink>
+            DNS validation support on the link. When set to
+            <literal>allow-downgrade</literal>, compatibility with
+            non-DNSSEC capable networks is increased, by automatically
+            turning off DNSEC in this case. This option defines a
+            per-interface setting for
+            <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+            global <varname>DNSSEC=</varname> option. Defaults to
+            false. This setting is read by
+            <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>DNSSECNegativeTrustAnchors=</varname></term>
+          <listitem><para>A space-separated list of DNSSEC negative
+          trust anchor domains. If specified and DNSSEC is enabled,
+          look-ups done via the interface's DNS server will be subject
+          to the list of negative trust anchors, and not require
+          authentication for the specified domains, or anything below
+          it. Use this to disable DNSSEC authentication for specific
+          private domains, that cannot be proven valid using the
+          Internet DNS hierarchy. Defaults to the empty list. This
+          setting is read by
+          <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
             <para>A DNS server address, which must be in the format
             described in
             <citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
-            This option may be specified more than once.</para>
+            This option may be specified more than once. This setting is read by
+            <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>Domains=</varname></term>
           <listitem>
-            <para>The domains used for DNS resolution over this link.</para>
+            <para>The domains used for DNS host name resolution on this link. Takes a list of DNS domain names which
+            are used as search suffixes for extending single-label host names (host names containing no dots) to become
+            fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, each of
+            the specified search domains are appended to it in turn, converting it into a fully qualified domain name,
+            until one of them may be successfully resolved.</para>
+
+            <para>The specified domains are also used for routing of DNS queries: look-ups for host names ending in the
+            domains specified here are preferably routed to the DNS servers configured for this interface. If a domain
+            name is prefixed with <literal>~</literal>, the domain name becomes a pure "routing" domain, is used for
+            DNS query routing purposes only and is not used in the described domain search logic. By specifying a
+            routing domain of <literal>~.</literal> (the tilda indicating definition of a routing domain, the dot
+            referring to the DNS root domain which is the implied suffix of all valid DNS names) it is possible to
+            route all DNS traffic preferably to the DNS server specified for this interface. The route domain logic is
+            particularly useful on multi-homed hosts with DNS servers serving particular private DNS zones on each
+            interface.</para>
+
+            <para>This setting is read by
+            <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>NTP=</varname></term>
           <listitem>
-            <para>An NTP server address. This option may be specified more than once.</para>
+            <para>An NTP server address. This option may be specified more than once. This setting is read by
+            <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
         <varlistentry>
           <term><varname>UseDomains=</varname></term>
           <listitem>
-            <para>When true (not the default), the domain name
-            received from the DHCP server will be used for DNS
-            resolution over this link. When a name cannot be resolved
-            as specified, the domain name will be used a suffix and
-            name resolution of that will be attempted.</para>
+            <para>Takes a boolean argument, or a the special value <literal>route</literal>. When true, the domain name
+            received from the DHCP server will be used as DNS search domain over this link, similar to the effect of
+            the <option>Domains=</option> setting. If set to <literal>route</literal>, the domain name received from
+            the DHCP server will be used for routing DNS queries only, but not for searching, similar to the effect of
+            the <option>Domains=</option> setting when the argument is prefixed with <literal>~</literal>. Defaults to
+            false.</para>
+
+            <para>It is recommended to enable this option only on trusted networks, as setting this affects resolution
+            of all host names, in particular to single-label names. It is generally safer to use the supplied domain
+            only as routing domain, rather than as search domain, in order to not have it affect local resolution of
+            single-label names.</para>
 
-            <para>This corresponds to the <option>domain</option>
-            option in <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-            and should not be enabled on untrusted networks.</para>
+            <para>When set to true, this setting corresponds to the <option>domain</option> option in <citerefentry
+            project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>UseTimezone=</varname></term>
 
           <listitem><para>When true, the timezone received from the
-          DHCP server will be set as as timezone of the local
+          DHCP server will be set as timezone of the local
           system. Defaults to <literal>no</literal>.</para></listitem>
         </varlistentry>
 
@@ -1011,9 +1084,10 @@ DHCP=yes
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-networkd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index e952688331e67016515684acb89e7c62ef684e32..c07a4b0243d45eb39ebdb21afb9bf6d903131089 100644 (file)
       <varlistentry>
         <term><varname>Boot=</varname></term>
 
-        <listitem><para>Takes a boolean argument, which defaults to off. If
-        enabled, <command>systemd-nspawn</command> will automatically
-        search for an <filename>init</filename> executable and invoke
-        it. In this case, the specified parameters using
-        <varname>Parameters=</varname> are passed as additional
-        arguments to the <filename>init</filename> process. This
-        setting corresponds to the <option>--boot</option> switch on
-        the <command>systemd-nspawn</command> command
-        line. </para></listitem>
+        <listitem><para>Takes a boolean argument, which defaults to off. If enabled, <command>systemd-nspawn</command>
+        will automatically search for an <filename>init</filename> executable and invoke it. In this case, the
+        specified parameters using <varname>Parameters=</varname> are passed as additional arguments to the
+        <filename>init</filename> process. This setting corresponds to the <option>--boot</option> switch on the
+        <command>systemd-nspawn</command> command line. This option may not be combined with
+        <varname>ProcessTwo=yes</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>ProcessTwo=</varname></term>
+
+        <listitem><para>Takes a boolean argument, which defaults to off. If enabled, the specified program is run as
+        PID 2. A stub init process is run as PID 1. This setting corresponds to the <option>--as-pid2</option> switch
+        on the <command>systemd-nspawn</command> command line. This option may not be combined with
+        <varname>Boot=yes</varname>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         switch.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>WorkingDirectory=</varname></term>
+
+        <listitem><para>Selects the working directory for the process invoked in the container. Expects an absolute
+        path in the container's file system namespace. This corresponds to the <option>--chdir=</option> command line
+        switch.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>Capability=</varname></term>
         <term><varname>DropCapability=</varname></term>
 
         <listitem><para>Takes a space-separated list of Linux process
         capabilities (see
-        <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+        <citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
         for details). The <varname>Capability=</varname> setting
         specifies additional capabilities to pass on top of the
         default set of capabilities. The
index b1106c759dcd6c2eb3aaf50174a8fe3217a4e4d6..08cdf06e23cc92ed04f44161373e6eae39e6152e 100644 (file)
         </listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><varname>NetClass=</varname></term>
-        <listitem><para>Configures a network class number to assign to the
-        unit. This value will be set to the
-        <literal>net_cls.class_id</literal> property of the
-        <literal>net_cls</literal> cgroup of the unit. The directive
-        accepts a numerical value (for fixed number assignment) and the keyword
-        <literal>auto</literal> (for dynamic allocation). Network traffic of
-        all processes inside the unit will have the network class ID assigned
-        by the kernel. Also see
-        the kernel docs for
-        <ulink url="https://www.kernel.org/doc/Documentation/cgroups/net_cls.txt">net_cls controller</ulink>
-        and
-        <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
-        </para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><varname>Slice=</varname></term>
 
           this setting is the parent slice. Since the name of a slice
           unit implies the parent slice, it is hence redundant to ever
           set this parameter directly for slice units.</para>
+
+          <para>Special care should be taken when relying on the default slice assignment in templated service units
+          that have <varname>DefaultDependencies=no</varname> set, see
+          <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>, section
+          "Automatic Dependencies" for details.</para>
+
         </listitem>
       </varlistentry>
 
index 20a71afe59a991300d193b281c8918b1654049da..d7760d4f2c3ea57c9a7103f3c38cd8f0cfc97c33 100644 (file)
     involved with early boot or late system shutdown should disable
     this option.</para>
 
+    <para>Instanced service units (i.e. service units with an <literal>@</literal> in their name) are assigned by
+    default a per-template slice unit (see
+    <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>), named after the
+    template unit, containing all instances of the specific template. This slice is normally stopped at shutdown,
+    together with all template instances. If that is not desired, set <varname>DefaultDependencies=no</varname> in the
+    template unit, and either define your own per-template slice unit file that also sets
+    <varname>DefaultDependencies=no</varname>, or set <varname>Slice=system.slice</varname> (or another suitable slice)
+    in the template unit. Also see
+    <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
     <para>Additional implicit dependencies may be added as result of
     execution and resource control parameters as documented in
     <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         with a <literal>-</literal> exit successfully.</para>
 
         <para><varname>ExecStartPost=</varname> commands are only run after
-        the service has started, as determined by <varname>Type=</varname>
+        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
         used to start long-running processes. All processes forked
         off by processes invoked via <varname>ExecStartPre=</varname> will
         be killed before the next service process is run.</para>
+
+        <para>Note that if any of the commands specified in <varname>ExecStartPre=</varname>,
+        <varname>ExecStart=</varname>, or <varname>ExecStartPost=</varname> fail (and are not prefixed with
+        <literal>-</literal>, see above) or time out before the service is fully up, execution continues with commands
+        specified in <varname>ExecStopPost=</varname>, the commands in <varname>ExecStop=</varname> are skipped.</para>
         </listitem>
       </varlistentry>
 
         <constant>SIGKILL</constant> immediately after the command
         exited, this would not result in a clean stop. The specified
         command should hence be a synchronous operation, not an
-        asynchronous one.</para></listitem>
+        asynchronous one.</para>
+
+        <para>Note that the commands specified in <varname>ExecStop=</varname> are only executed when the service
+        started successfuly first. They are not invoked if the service was never started at all, or in case its
+        start-up failed, for example because any of the commands specified in <varname>ExecStart=</varname>,
+        <varname>ExecStartPre=</varname> or <varname>ExecStartPost=</varname> failed (and weren't prefixed with
+        <literal>-</literal>, see above) or timed out. Use <varname>ExecStopPost=</varname> to invoke commands when a
+        service failed to start up correctly and is shut down again.</para>
+
+        <para>It is recommended to use this setting for commands that communicate with the service requesting clean
+        termination. When the commands specified with this option are executed it should be assumed that the service is
+        still fully up and is able to react correctly to all commands. For post-mortem clean-up steps use
+        <varname>ExecStopPost=</varname> instead.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><varname>ExecStopPost=</varname></term>
-        <listitem><para>Additional commands that are executed after
-        the service was stopped. This includes cases where the
-        commands configured in <varname>ExecStop=</varname> were used,
-        where the service does not have any
-        <varname>ExecStop=</varname> defined, or where the service
-        exited unexpectedly. This argument takes multiple command
-        lines, following the same scheme as described for
-        <varname>ExecStart=</varname>. Use of these settings is
-        optional. Specifier and environment variable substitution is
-        supported.</para></listitem>
+        <listitem><para>Additional commands that are executed after the service is stopped. This includes cases where
+        the commands configured in <varname>ExecStop=</varname> were used, where the service does not have any
+        <varname>ExecStop=</varname> defined, or where the service exited unexpectedly. This argument takes multiple
+        command lines, following the same scheme as described for <varname>ExecStart=</varname>. Use of these settings
+        is optional. Specifier and environment variable substitution is supported. Note that – unlike
+        <varname>ExecStop=</varname> – commands specified with this setting are invoked when a service failed to start
+        up correctly and is shut down again.</para>
+
+        <para>It is recommended to use this setting for clean-up operations that shall be executed even when the
+        service failed to start up correctly. Commands configured with this setting need to be able to operate even if
+        the service failed starting up half-way and left incompletely initialized data around. As the service's
+        processes have been terminated already when the commands specified with this setting are executed they should
+        not attempt to communicate with them.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         configured time, the service will be considered failed and
         will be shut down again. Takes a unit-less value in seconds,
         or a time span value such as "5min 20s". Pass
-        <literal>0</literal> to disable the timeout logic. Defaults to
+        <literal>infinity</literal> to disable the timeout logic. Defaults to
         <varname>DefaultTimeoutStartSec=</varname> from the manager
         configuration file, except when
         <varname>Type=oneshot</varname> is used, in which case the
         <varname>KillMode=</varname> in
         <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
         Takes a unit-less value in seconds, or a time span value such
-        as "5min 20s". Pass <literal>0</literal> to disable the
+        as "5min 20s". Pass <literal>infinity</literal> to disable the
         timeout logic. Defaults to
         <varname>DefaultTimeoutStopSec=</varname> from the manager
         configuration file (see
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>RuntimeMaxSec=</varname></term>
+
+        <listitem><para>Configures a maximum time for the service to run. If this is used and the service has been
+        active for longer than the specified time it is terminated and put into a failure state. Note that this setting
+        does not have any effect on <varname>Type=oneshot</varname> services, as they terminate immediately after
+        activation completed. Pass <literal>infinity</literal> (the default) to configure no runtime
+        limit.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>WatchdogSec=</varname></term>
         <listitem><para>Configures the watchdog timeout for a service.
         larger than the configured time, then the service is placed in
         a failed state and it will be terminated with
         <constant>SIGABRT</constant>. By setting
-        <varname>Restart=</varname> to <option>on-failure</option> or
+        <varname>Restart=</varname> to <option>on-failure</option>,
+        <option>on-watchdog</option>, <option>on-abnormal</option> or
         <option>always</option>, the service will be automatically
         restarted. The time configured here will be passed to the
         executed service process in the
         check whether the service manager expects watchdog keep-alive
         notifications. See
         <citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-       for details.
+        for details.
+        <citerefentry><refentrytitle>sd_event_set_watchdog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+        may be used to enable automatic watchdog notification support.
         </para></listitem>
       </varlistentry>
 
         <constant>SIGPIPE</constant>. Exit status definitions can
         either be numeric exit codes or termination signal names,
         separated by spaces. For example:
-        <programlisting>SuccessExitStatus=1 2 8
-        SIGKILL</programlisting> ensures that exit codes 1, 2, 8 and
+
+        <programlisting>SuccessExitStatus=1 2 8 SIGKILL</programlisting>
+
+        ensures that exit codes 1, 2, 8 and
         the termination signal <constant>SIGKILL</constant> are
         considered clean service terminations.
         </para>
         signal names, and are separated by spaces. Defaults to the
         empty list, so that, by default, no exit status is excluded
         from the configured restart logic. For example:
-        <programlisting>RestartPreventExitStatus=1 6
-        SIGABRT</programlisting> ensures that exit codes 1 and 6 and
-        the termination signal <constant>SIGABRT</constant> will not
-        result in automatic service restarting. This option may appear
-        more than once, in which case the list of restart-preventing
-        statuses is merged. If the empty string is assigned to this
-        option, the list is reset and all prior assignments of this
-        option will have no effect.</para></listitem>
+
+        <programlisting>RestartPreventExitStatus=1 6 SIGABRT</programlisting>
+
+        ensures that exit codes 1 and 6 and the termination signal
+        <constant>SIGABRT</constant> will not result in automatic
+        service restarting. This option may appear more than once, in
+        which case the list of restart-preventing statuses is
+        merged. If the empty string is assigned to this option, the
+        list is reset and all prior assignments of this option will
+        have no effect.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         effect.</para></listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><varname>StartLimitInterval=</varname></term>
-        <term><varname>StartLimitBurst=</varname></term>
-
-        <listitem><para>Configure service start rate limiting. By
-        default, services which are started more than 5 times within
-        10 seconds are not permitted to start any more times until the
-        10 second interval ends. With these two options, this rate
-        limiting may be modified. Use
-        <varname>StartLimitInterval=</varname> to configure the
-        checking interval (defaults to
-        <varname>DefaultStartLimitInterval=</varname> in manager
-        configuration file, set to 0 to disable any kind of rate
-        limiting). Use <varname>StartLimitBurst=</varname> to
-        configure how many starts per interval are allowed (defaults
-        to <varname>DefaultStartLimitBurst=</varname> in manager
-        configuration file). These configuration options are
-        particularly useful in conjunction with
-        <varname>Restart=</varname>; however, they apply to all kinds
-        of starts (including manual), not just those triggered by the
-        <varname>Restart=</varname> logic. Note that units which are
-        configured for <varname>Restart=</varname> and which reach the
-        start limit are not attempted to be restarted anymore;
-        however, they may still be restarted manually at a later
-        point, from which point on, the restart logic is again
-        activated. Note that <command>systemctl reset-failed</command>
-        will cause the restart rate counter for a service to be
-        flushed, which is useful if the administrator wants to
-        manually start a service and the start limit interferes with
-        that.</para></listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><varname>StartLimitAction=</varname></term>
-
-        <listitem><para>Configure the action to take if the rate limit
-        configured with <varname>StartLimitInterval=</varname> and
-        <varname>StartLimitBurst=</varname> is hit. Takes one of
-        <option>none</option>,
-        <option>reboot</option>,
-        <option>reboot-force</option>,
-        <option>reboot-immediate</option>,
-        <option>poweroff</option>,
-        <option>poweroff-force</option> or
-        <option>poweroff-immediate</option>. If
-        <option>none</option> is set, hitting the rate limit will
-        trigger no action besides that the start will not be
-        permitted. <option>reboot</option> causes a reboot following
-        the normal shutdown procedure (i.e. equivalent to
-        <command>systemctl reboot</command>).
-        <option>reboot-force</option> causes a forced reboot which
-        will terminate all processes forcibly but should cause no
-        dirty file systems on reboot (i.e. equivalent to
-        <command>systemctl reboot -f</command>) and
-        <option>reboot-immediate</option> causes immediate execution
-        of the
-        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        system call, which might result in data loss. Similarly,
-        <option>poweroff</option>, <option>poweroff-force</option>,
-        <option>poweroff-immediate</option> have the effect of
-        powering down the system with similar semantics. Defaults to
-        <option>none</option>.</para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><varname>FailureAction=</varname></term>
-        <listitem><para>Configure the action to take when the service
-        enters a failed state. Takes the same values as
-        <varname>StartLimitAction=</varname> and executes the same
-        actions. Defaults to <option>none</option>. </para></listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><varname>RebootArgument=</varname></term>
-        <listitem><para>Configure the optional argument for the
-        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        system call if <varname>StartLimitAction=</varname> or
-        <varname>FailureAction=</varname> is a reboot action. This
-        works just like the optional argument to <command>systemctl
-        reboot</command> command.</para></listitem>
+        <listitem><para>Configure the action to take when the service enters a failed state. Takes the same values as
+        the unit setting <varname>StartLimitAction=</varname> and executes the same actions (see
+        <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Defaults to
+        <option>none</option>. </para></listitem>
       </varlistentry>
 
       <varlistentry>
index beac053bf0e61572d3b7d4e9d71814f3a2852dd7..43841c23996144b3de099b90518622fe743efc3e 100644 (file)
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>SocketProtocol=</varname></term>
+        <listitem><para>Takes a one of <option>udplite</option>
+        or <option>sctp</option>. Specifies a socket protocol
+        (<constant>IPPROTO_UDPLITE</constant>) UDP-Lite
+        (<constant>IPPROTO_SCTP</constant>) SCTP socket respectively. </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>BindIPv6Only=</varname></term>
         <listitem><para>Takes a one of <option>default</option>,
index 54e7c49a9e4de676bece3ec9550ab9a3477b493c..055d854555a287cbd8971ad391721e5ebf2fc137 100644 (file)
@@ -92,6 +92,7 @@
     <filename>shutdown.target</filename>,
     <filename>sigpwr.target</filename>,
     <filename>sleep.target</filename>,
+    <filename>slices.target</filename>,
     <filename>smartcard.target</filename>,
     <filename>sockets.target</filename>,
     <filename>sound.target</filename>,
       <varlistentry>
         <term><filename>emergency.target</filename></term>
         <listitem>
-          <para>A special target unit that starts an emergency shell
-          on the main console. This unit is supposed to be used with
-          the kernel command line option
-          <varname>systemd.unit=</varname> and has otherwise little
-          use.
-          </para>
+          <para>A special target unit that starts an emergency shell on the main console. This target does not pull in
+          any serices or mounts. It is the most minimal version of starting the system in order to acquire an
+          interactive shell; the only processes running are usually just the system manager (PID 1) and the shell
+          process. This unit is supposed to be used with the kernel command line option
+          <varname>systemd.unit=</varname>; it is also used when a file system check on a required file system fails,
+          and boot-up cannot continue. Compare with <filename>rescue.target</filename>, which serves a similar purpose,
+          but also starts the most basic services and mounts all file systems.</para>
+
+          <para>Use the <literal>systemd.unit=emergency.target</literal> kernel command line option to boot into this
+          mode. A short alias for this kernel command line option is <literal>emergency</literal>, for compatibility
+          with SysV.</para>
+
+          <para>In many ways booting into <filename>emergency.target</filename> is similar to the effect of booting
+          with <literal>init=/bin/sh</literal> on the kernel command line, except that emergency mode provides you with
+          the full system and service manager, and allows starting individual units in order to continue the boot
+          process in steps.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
       <varlistentry>
         <term><filename>rescue.target</filename></term>
         <listitem>
-          <para>A special target unit for setting up the base system
-          and a rescue shell.</para>
+          <para>A special target unit that pulls in the base system (including system mounts) and spawns a rescue
+          shell. Isolate to this target in order to administer the system in single-user mode with all file systems
+          mounted but with no services running, except for the most basic. Compare with
+          <filename>emergency.target</filename>, which is much more reduced and does not provide the file systems or
+          most basic services.</para>
 
-          <para><filename>runlevel1.target</filename> is an alias for
-          this target unit, for compatibility with SysV.</para>
+          <para><filename>runlevel1.target</filename> is an alias for this target unit, for compatibility with
+          SysV.</para>
+
+          <para>Use the <literal>systemd.unit=rescue.target</literal> kernel command line option to boot into this
+          mode. A short alias for this kernel command line option is <literal>1</literal>, for compatibility with
+          SysV.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
           hook units into the sleep state logic.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><filename>slices.target</filename></term>
+        <listitem>
+          <para>A special target unit that sets up all slice units (see
+          <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+          details) that shall be active after boot. By default the generic <filename>user.slice</filename>,
+          <filename>system.slice</filename>, <filename>machines.slice</filename> slice units, as well as the the root
+          slice unit <filename>-.slice</filename> are pulled in and ordered before this unit (see below).</para>
+
+          <para>It's a good idea to add <varname>WantedBy=slices.target</varname> lines to the <literal>[Install]</literal>
+          section of all slices units that may be installed dynamically.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><filename>sockets.target</filename></term>
         <listitem>
           <para>A special target unit that sets up all socket
-          units.(see
+          units (see
           <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
           for details) that shall be active after boot.</para>
 
       <varlistentry>
         <term><filename>umount.target</filename></term>
         <listitem>
-          <para>A special target unit that umounts all mount and
+          <para>A special target unit that unmounts all mount and
           automount points on system shutdown.</para>
 
           <para>Mounts that shall be unmounted on system shutdown
index a6fcc95e4c345558307f9f5f45b52a9363babd94..ffcac82263093c999fb1d9a995dc3033af8942f1 100644 (file)
     the value and all values plus multiples of the repetition value
     are matched.</para>
 
+    <para>The seconds component may contain decimal fractions both in
+    the value and the repetition. All fractions are rounded to 6
+    decimal places.</para>
+
     <para>Either time or date specification may be omitted, in which
     case the current day and 00:00:00 is implied, respectively. If the
     second component is not specified, <literal>:00</literal> is
@@ -276,6 +280,7 @@ Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03
     Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40
           Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40
           2003-03-05 05:40 → 2003-03-05 05:40:00
+05:40:23.4200004/3.1700005 → 05:40:23.420000/3.170001
       2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC
                 2003-03-05 → 2003-03-05 00:00:00
                      03-05 → *-03-05 00:00:00
index 38415888205473d8c398c610c43408cf905efbf0..29e235e2dc61fb204afa1d944d58f1fe4d6c69a2 100644 (file)
         <varname>OnUnitInactiveSec=</varname> and ending the time
         configured with <varname>AccuracySec=</varname> later. Within
         this time window, the expiry time will be placed at a
-        host-specific, randomized but stable position that is
+        host-specific, randomized, but stable position that is
         synchronized between all local timer units. This is done in
-        order to distribute the wake-up time in networked
-        installations, as well as optimizing power consumption to
-        suppress unnecessary CPU wake-ups. To get best accuracy, set
-        this option to 1us. Note that the timer is still subject to
-        the timer slack configured via
+        order to optimize power consumption to suppress unnecessary
+        CPU wake-ups. To get best accuracy, set this option to
+        1us. Note that the timer is still subject to the timer slack
+        configured via
         <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
         <varname>TimerSlackNSec=</varname> setting. See
         <citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
         this value as high as possible and as low as
         necessary.</para></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>RandomizedDelaySec=</varname></term>
+
+        <listitem><para>Delay the timer by a randomly selected, evenly
+        distributed amount of time between 0 and the specified time
+        value. Defaults to 0, indicating that no randomized delay
+        shall be applied. Each timer unit will determine this delay
+        randomly each time it is started, and the delay will simply be
+        added on top of the next determined elapsing time. This is
+        useful to stretch dispatching of similarly configured timer
+        events over a certain amount time, to avoid that they all fire
+        at the same time, possibly resulting in resource
+        congestion. Note the relation to
+        <varname>AccuracySec=</varname> above: the latter allows the
+        service manager to coalesce timer events within a specified
+        time range in order to minimize wakeups, the former does the
+        opposite: it stretches timer events over a time range, to make
+        it unlikely that they fire simultaneously. If
+        <varname>RandomizedDelaySec=</varname> and
+        <varname>AccuracySec=</varname> are used in conjunction, first
+        the randomized delay is added, and then the result is
+        possibly further shifted to coalesce it with other timer
+        events happening on the system. As mentioned above
+        <varname>AccuracySec=</varname> defaults to 1min and
+        <varname>RandomizedDelaySec=</varname> to 0, thus encouraging
+        coalescing of timer events. In order to optimally stretch
+        timer events over a certain range of time, make sure to set
+        <varname>RandomizedDelaySec=</varname> to a higher value, and
+        <varname>AccuracySec=1us</varname>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>Unit=</varname></term>
 
       </varlistentry>
 
       <varlistentry>
-        <term><varname>RemainAfterExit=</varname></term>
+        <term><varname>RemainAfterElapse=</varname></term>
 
         <listitem><para>Takes a boolean argument. If true, an elapsed
-        timer will stay loaded, and its state remains
-        queriable. Defaults to
+        timer will stay loaded, and its state remains queriable. If
+        false, an elapsed timer unit that cannot elapse anymore is
+        unloaded. Turning this off is particularly useful for
+        transient timer units that shall disappear after they first
+        elapse. Note that this setting has an effect on repeatedly
+        starting a timer unit that only elapses once: if
+        <varname>RemainAfterElapse=</varname> is on, it will not be
+        started again, and is guaranteed to elapse only once. However,
+        if <varname>RemainAfterLeapse=</varname> is off, it might be
+        started again if it is already elapsed, and thus be triggered
+        multiple times. Defaults to
         <varname>yes</varname>.</para></listitem>
       </varlistentry>
     </variablelist>
index 5b12378eda67b2891c33493acb7ddbce7feb3013..5794681963d48aa5e2c0b5097e0265e16ea3b32b 100644 (file)
     directory suffix is <filename>.requires/</filename> in this
     case.</para>
 
-    <para>Along with a unit file <filename>foo.service</filename>, a
-    directory <filename>foo.service.d/</filename> may exist. All files
-    with the suffix <literal>.conf</literal> from this directory will
-    be parsed after the file itself is parsed. This is useful to alter
-    or add configuration settings to a unit, without having to modify
-    their unit files. Make sure that the file that is included has the
-    appropriate section headers before any directive. Note that, for
-    instanced units, this logic will first look for the instance
-    <literal>.d/</literal> subdirectory and read its
-    <literal>.conf</literal> files, followed by the template
-    <literal>.d/</literal> subdirectory and reads its
-    <literal>.conf</literal> files.</para>
-
+    <para>Along with a unit file <filename>foo.service</filename>, a "drop-in" directory
+    <filename>foo.service.d/</filename> may exist. All files with the suffix <literal>.conf</literal> from this
+    directory will be parsed after the file itself is parsed. This is useful to alter or add configuration settings for
+    a unit, without having to modify unit files. Each drop-in file must have appropriate section headers. Note that for
+    instantiated units, this logic will first look for the instance <literal>.d/</literal> subdirectory and read its
+    <literal>.conf</literal> files, followed by the template <literal>.d/</literal> subdirectory and the
+    <literal>.conf</literal> files there. Also note that settings from the <literal>[Install]</literal> section are not
+    honoured in drop-in unit files, and have no effect.</para>
+
+    <para>In addition to <filename>/etc/systemd/system</filename>,
+    the drop-in <literal>.conf</literal> files for system services
+    can be placed in <filename>/usr/lib/systemd/system</filename> or
+    <filename>/run/systemd/system</filename> directories. Drop-in
+    files in <filename>/etc</filename> take precedence over those in
+    <filename>/run</filename> which in turn take precedence over
+    those in <filename>/usr/lib</filename>. Drop-in files under any of
+    these directories take precedence over unit files wherever located.
+    (Of course, since <filename>/run</filename> is temporary and
+    <filename>/usr/lib</filename> is for vendors, it is unlikely
+    drop-ins should be used in either of those places.)</para>
     <!-- Note that we do not document .include here, as we
          consider it mostly obsolete, and want people to
          use .d/ drop-ins instead. -->
         <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 0 (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 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>
 
         <para><varname>JobTimeoutAction=</varname>
         optionally configures an additional
         system call.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>StartLimitInterval=</varname></term>
+        <term><varname>StartLimitBurst=</varname></term>
+
+        <listitem><para>Configure unit start rate limiting. By default, units which are started more than 5 times
+        within 10 seconds are not permitted to start any more times until the 10 second interval ends. With these two
+        options, this rate limiting may be modified. Use <varname>StartLimitInterval=</varname> to configure the
+        checking interval (defaults to <varname>DefaultStartLimitInterval=</varname> in manager configuration file, set
+        to 0 to disable any kind of rate limiting). Use <varname>StartLimitBurst=</varname> to configure how many
+        starts per interval are allowed (defaults to <varname>DefaultStartLimitBurst=</varname> in manager
+        configuration file). These configuration options are particularly useful in conjunction with the service
+        setting <varname>Restart=</varname> (see
+        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>); however,
+        they apply to all kinds of starts (including manual), not just those triggered by the
+        <varname>Restart=</varname> logic. Note that units which are configured for <varname>Restart=</varname> and
+        which reach the start limit are not attempted to be restarted anymore; however, they may still be restarted
+        manually at a later point, from which point on, the restart logic is again activated. Note that
+        <command>systemctl reset-failed</command> will cause the restart rate counter for a service to be flushed,
+        which is useful if the administrator wants to manually start a unit and the start limit interferes with
+        that.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>StartLimitAction=</varname></term>
+
+        <listitem><para>Configure the action to take if the rate limit configured with
+        <varname>StartLimitInterval=</varname> and <varname>StartLimitBurst=</varname> is hit. Takes one of
+        <option>none</option>, <option>reboot</option>, <option>reboot-force</option>,
+        <option>reboot-immediate</option>, <option>poweroff</option>, <option>poweroff-force</option> or
+        <option>poweroff-immediate</option>. If <option>none</option> is set, hitting the rate limit will trigger no
+        action besides that the start will not be permitted. <option>reboot</option> causes a reboot following the
+        normal shutdown procedure (i.e. equivalent to <command>systemctl reboot</command>).
+        <option>reboot-force</option> causes a forced reboot which will terminate all processes forcibly but should
+        cause no dirty file systems on reboot (i.e. equivalent to <command>systemctl reboot -f</command>) and
+        <option>reboot-immediate</option> causes immediate execution of the
+        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call, which
+        might result in data loss. Similarly, <option>poweroff</option>, <option>poweroff-force</option>,
+        <option>poweroff-immediate</option> have the effect of powering down the system with similar
+        semantics. Defaults to <option>none</option>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>RebootArgument=</varname></term>
+        <listitem><para>Configure the optional argument for the
+        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call if
+        <varname>StartLimitAction=</varname> or a service's <varname>FailureAction=</varname> is a reboot action. This
+        works just like the optional argument to <command>systemctl reboot</command> command.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>ConditionArchitecture=</varname></term>
         <term><varname>ConditionVirtualization=</varname></term>
              useful and probably just
              confusing. -->
 
-        <listitem><para>Before starting a unit verify that the
-        specified condition is true. If it is not true, the starting
-        of the unit will be skipped, however all ordering dependencies
-        of it are still respected. A failing condition will not result
-        in the unit being moved into a failure state. The condition is
-        checked at the time the queued start job is to be
-        executed.</para>
+        <listitem><para>Before starting a unit, verify that the specified condition is true. If it is not true, the
+        starting of the unit will be (mostly silently) skipped, however all ordering dependencies of it are still
+        respected. A failing condition will not result in the unit being moved into a failure state. The condition is
+        checked at the time the queued start job is to be executed. Use condition expressions in order to silently skip
+        units that do not apply to the local running system, for example because the kernel or runtime environment
+        doesn't require its functionality. Use the various <varname>AssertArchitecture=</varname>,
+        <varname>AssertVirtualization=</varname>, … options for a similar mechanism that puts the unit in a failure
+        state and logs about the failed check (see below).</para>
 
         <para><varname>ConditionArchitecture=</varname> may be used to
         check whether the system is running on a specific
 
         <para><varname>ConditionSecurity=</varname> may be used to
         check whether the given security module is enabled on the
-        system. Currently, the recognized values values are
+        system. Currently, the recognized values are
         <varname>selinux</varname>,
         <varname>apparmor</varname>,
         <varname>ima</varname>,
         <filename>/var</filename> on the next following boot. Units
         making use of this condition should order themselves before
         <citerefentry><refentrytitle>systemd-update-done.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-        to make sure they run before the stamp files's modification
+        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
         <term><varname>AssertFileNotEmpty=</varname></term>
         <term><varname>AssertFileIsExecutable=</varname></term>
 
-        <listitem><para>Similar to the
-        <varname>ConditionArchitecture=</varname>,
-        <varname>ConditionVirtualization=</varname>, etc., condition
-        settings described above, these settings add assertion checks
-        to the start-up of the unit. However, unlike the conditions
-        settings, any assertion setting that is not met results in
-        failure of the start job it was triggered
-        by.</para></listitem>
+        <listitem><para>Similar to the <varname>ConditionArchitecture=</varname>,
+        <varname>ConditionVirtualization=</varname>, …, condition settings described above, these settings add
+        assertion checks to the start-up of the unit. However, unlike the conditions settings, any assertion setting
+        that is not met results in failure of the start job (which means this is logged loudly). Use assertion
+        expressions for units that cannot operate when specific requirements are not met, and when this is something
+        the administrator or user should look into.</para></listitem>
       </varlistentry>
 
       <varlistentry>
   <refsect1>
     <title>[Install] Section Options</title>
 
-    <para>Unit file may include an <literal>[Install]</literal>
-    section, which carries installation information for the unit. This
-    section is not interpreted by
-    <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    during runtime. It is used exclusively by the
-    <command>enable</command> and <command>disable</command> commands
-    of the
-    <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    tool during installation of a unit:</para>
+    <para>Unit files may include an <literal>[Install]</literal> section, which carries installation information for
+    the unit. This section is not interpreted by
+    <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> during runtime; it is
+    used by the <command>enable</command> and <command>disable</command> commands of the
+    <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> tool during
+    installation of a unit. Note that settings in the <literal>[Install]</literal> section may not appear in
+    <filename>.d/*.conf</filename> unit file drop-ins (see above).</para>
 
     <variablelist class='unit-directives'>
       <varlistentry>
@@ -1402,6 +1449,7 @@ PrivateTmp=yes</programlisting>
       cannot be reset to an empty list, so dependencies can only be
       added in drop-ins. If you want to remove dependencies, you have
       to override the entire unit.</para>
+
     </example>
   </refsect1>
 
index 6de18f8294c6db374a645ba90269bd0b8fcffcc9..b8d91b89438c6e42517a084ae0941e7576eaa57d 100644 (file)
         <option>inherit</option>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--machine-id=</option></term>
+
+        <listitem><para>Override the machine-id set on the hard drive,
+        useful for network booting or for containers. May not be set
+        to all zeros.</para></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
         script runlevel link farms.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>$SYSTEMD_COLORS</varname></term>
+
+        <listitem><para>Controls whether colorized output should be generated.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>$LISTEN_PID</varname></term>
         <term><varname>$LISTEN_FDS</varname></term>
         than once to set multiple variables.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>systemd.machine_id=</varname></term>
+
+        <listitem><para>Takes a 32 character hex value to be
+        used for setting the machine-id. Intended mostly for
+        network booting where the same machine-id is desired
+        for every boot.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>quiet</varname></term>
 
index 42b53b2759de38f121b6e23aec883c0f6590e38a..18ee3800d67c4687ee73b755b99351cdb4799596 100644 (file)
@@ -113,7 +113,7 @@ u root 0 "Superuser" /root</programlisting>
         <varlistentry>
           <term><varname>m</varname></term>
           <listitem><para>Add a user to a group. If the user or group
-          are not existing yet, they will be implicitly
+          do not exist yet, they will be implicitly
           created.</para></listitem>
         </varlistentry>
 
index 10c2de89f6a36dcf65810b053f45853d0c5bc3c7..8c86fd007422d4d185fb7fa1ccd49628e2acf36a 100644 (file)
@@ -68,6 +68,8 @@
   <refsect1>
     <title>Options</title>
 
+    <para>The following settings are configured in the <literal>[Time]</literal> section:</para>
+
     <variablelist class='network-directives'>
 
       <varlistentry>
index 5bf1f2956bb30e53736113cf922545689d74518c..3b6b1e3f112f6f69f6539677b7f1430c3c2950e9 100644 (file)
           be removed and be replaced by the symlink. If the argument
           is omitted, symlinks to files with the same name residing in
           the directory <filename>/usr/share/factory/</filename> are
-          created.</para></listitem>
+          created. Note that permissions and ownership on symlinks
+          are ignored.</para></listitem>
         </varlistentry>
 
         <varlistentry>
           <command>systemd-tmpfiles</command> will automatically add
           the required base entries for user and group based on the
           access mode of the file, unless base entries already exist
-          or are explictly specified. The mask will be added if not
+          or are explicitly specified. The mask will be added if not
           specified explicitly or already present. Lines of this type
           accept shell-style globs in place of normal path names. This
           can be useful for allowing additional access to certain
index 11db1a0fab9f3af4dfa0677405bb351cb870f018..0bb71c8e912f50b7aaf0ed8a3532aa9eb97dce98 100644 (file)
     a <filename>uevent</filename> file. <function>udev_device_new_from_devnum</function>
     takes a device type, which can be <constant>b</constant> for block devices or
     <constant>c</constant> for character devices, as well as a devnum (see
-    <citerefentry><refentrytitle>makedev</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
+    <citerefentry project='man-pages'><refentrytitle>makedev</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
     <function>udev_device_new_from_subsystem_sysname</function> looks up devices based
     on the provided subsystem and sysname
     (see <citerefentry><refentrytitle>udev_device_get_subsystem</refentrytitle><manvolnum>3</manvolnum></citerefentry>
 
     <para><function>udev_device_new_from_environment</function>
     creates a device from the current environment (see
-    <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
+    <citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
     Each key-value pair is interpreted in the same way as if it was
     received in an uevent (see
     <citerefentry><refentrytitle>udev_monitor_receive_device</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
     <function>udev_device_new_from_device_id()</function> and
     <function>udev_device_new_from_environment()</function> return a
     pointer to the allocated udev device. On failure,
-    <constant>NULL</constant> is returned.
+    <constant>NULL</constant> is returned,
+    and <varname>errno</varname> is set appropriately.
     <function>udev_device_ref()</function> returns the argument
     that it was passed, unmodified.
     <function>udev_device_unref()</function> always returns
index 95cde045b62c938413ac1bad361cb42659ebe25c..94c9986d60473708fd2788ea4f1f1abfbc7e7d90 100644 (file)
--- a/po/el.po
+++ b/po/el.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2014-04-29 09:17+0300\n"
 "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>\n"
 "Language-Team: team@lists.gnome.gr\n"
@@ -451,6 +451,15 @@ msgid ""
 "interface."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+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 ""
@@ -461,20 +470,68 @@ msgid "Authentication is required to log into a local container."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
+msgid "Log into the local host"
 msgstr ""
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
 #, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+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
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+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
+#, fuzzy
+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
+#, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 #, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machine and container "
@@ -520,3 +577,38 @@ msgid ""
 msgstr ""
 "Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα "
 "ενεργοποιηθεί."
+
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
index ceca42386a9be24acbbf7b2a5a26fe8c92e8da51..681b30d5b2f0eab0c1547a404597204199c77e8e 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2015-04-24 13:26+0200\n"
 "Last-Translator: Álex Puchades <alex94puchades@gmail.com>\n"
 "Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
@@ -446,6 +446,15 @@ msgstr ""
 "Se requiere autenticación para indicar al firmware que arranque la interfaz "
 "de configuración."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "Se requiere autenticación para establecer el nombre de equipo local."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Conectarse a un contenedor local"
@@ -455,21 +464,70 @@ msgid "Authentication is required to log into a local container."
 msgstr "Se requiere autenticación para conectarse a un contenedor local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#, fuzzy
+msgid "Log into the local host"
+msgstr "Conectarse a un contenedor local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Se requiere autenticación para conectarse a un contenedor local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Conectarse a un contenedor local"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Se requiere autenticación para conectarse a un contenedor local."
+
+#: ../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
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Se requiere autenticación para establecer el nombre de equipo local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Conectarse a un contenedor 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 "Se requiere autenticación para conectarse a un contenedor local."
+
+#: ../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
+#, fuzzy
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Se requiere autenticación para establecer el nombre de equipo local."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Administrar máquinas virtuales y contenedores locales"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Se requiere autenticación para administrar las máquinas virtuales y los "
 "contenedores locales."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Administrar imágenes de máquina virtual y de contenedor locales"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -517,6 +575,41 @@ msgstr ""
 "Se requiere autenticación para activar/desactivar la sincronización de hora "
 "por red."
 
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Se requiere autenticación para recargar el estado de systemd."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Se requiere autenticación para conectarse a un contenedor local."
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Se requiere autenticación para establecer el nombre de equipo local."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr ""
 #~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
index c5dee25052039b928b00572b82af3d74e0df4a16..88fecbc506a30c48caf033fd81729e6f081c78cd 100644 (file)
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,14 +1,14 @@
 # Hungarian translation of systemd
-# Copyright (C) 2015. Free Software Foundation, Inc.
+# Copyright (C) 2015, 2016. Free Software Foundation, Inc.
 # This file is distributed under the same license as the systemd package.
 #
-# Gabor Kelemen <kelemeng at gnome dot hu>, 2015.
+# Gabor Kelemen <kelemeng at gnome dot hu>, 2015, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-01-02 22:58+0100\n"
+"POT-Creation-Date: 2016-01-02 13:41+0100\n"
+"PO-Revision-Date: 2016-01-02 13:45+0100\n"
 "Last-Translator: Gabor Kelemen <kelemeng at ubuntu dot com>\n"
 "Language-Team: Hungarian <openscope at googlegroups dot com>\n"
 "Language: hu\n"
@@ -29,15 +29,13 @@ msgstr ""
 "Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
 msgid "Manage system services or other units"
-msgstr "Rendszerszolgáltatások vagy -egységek kezelése"
+msgstr "Rendszerszolgáltatások vagy más egységek kezelése"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
-"Hitelesítés szükséges a rendszerszolgáltatások vagy -egységek kezeléséhez."
+"Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
@@ -51,14 +49,16 @@ msgstr ""
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
 msgid "Set or unset system and service manager environment variables"
 msgstr ""
+"Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy "
+"törlése"
 
 #: ../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 ""
-"Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez."
+"Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti "
+"változóinak beállításához vagy törléséhez."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
 msgid "Reload the systemd state"
@@ -98,30 +98,27 @@ msgstr "Hitelesítés szükséges a helyi gép információinak beállításáho
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép importálása"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to import a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához."
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép exportálása"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to export a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához."
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
-msgstr ""
+msgstr "VM vagy konténer lemezkép letöltése"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to download a VM or container image"
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez."
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
@@ -409,65 +406,113 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások "
+"kezeléséhez."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Aktív munkamenetek zárolása vagy feloldása"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr ""
+"Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
+msgstr ""
+"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet "
+"bootolja"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Falüzenet beállítása"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Hitelesítés szükséges a falüzenet beállításához"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Bejelentkezés helyi konténerbe"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to log into a local container."
 msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
-msgstr ""
+msgid "Log into the local host"
+msgstr "Bejelentkezés a helyi gépre"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Parancsértelmező elérése helyi konténerben"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Parancsértelmező elérése a helyi gépen"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Pszeudoterminál elérése helyi konténerben"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Pszeudoterminál elérése helyi gépen"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Virtuális gépek és konténerek kezelése"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
-msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
+msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Helyi virtuális gép és konténer lemezképek kezelése"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
-msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
+msgstr ""
+"Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek "
+"kezeléséhez."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -506,3 +551,34 @@ msgid ""
 "Authentication is required to control whether network time synchronization "
 "shall be enabled."
 msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez."
+
+#: ../src/core/dbus-unit.c:449
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:556
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”."
+
+#: ../src/core/dbus-unit.c:586
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: "
+"„$(unit)”."
+
+#: ../src/core/dbus-unit.c:618
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
+"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”."
index e11e7e3faadbb1494e8061c855aef93f88a7ba8c..a8547b9395229ca575b296c56de81ba20ae9b5e3 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-06-10 23:10+0100\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
+"PO-Revision-Date: 2015-11-22 16:54+0100\n"
 "Last-Translator: Daniele Medri <dmedri@gmail.com>\n"
 "Language-Team: Italian\n"
 "Language: it\n"
@@ -16,7 +16,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 1.7.6\n"
+"X-Generator: Poedit 1.8.5\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
@@ -443,6 +443,14 @@ msgstr ""
 "Autenticazione richiesta per indicare al firmware di avviare l'interfaccia "
 "di configurazione."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Configura un messaggio per gli utenti"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Accedi in un container locale"
@@ -452,20 +460,62 @@ msgid "Authentication is required to log into a local container."
 msgstr "Autenticazione richiesta per accedere in un container locale."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Accedi in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Autenticazione richiesta per accedere in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Apri una shell in un container locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Autenticazione richiesta per aprire una shell in un container locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Apri una shell in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Autenticazione richiesta per aprire una shell in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Apri un pseudo TTY in un container locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Autenticazione richiesta per aprire un pseudo TTY in un container locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Apri un pseudo TTY in un host locale"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Gestisci le virtual machine e i container locali"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Autenticazione richiesta per gestire le virtual machine e i container locali."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Gestisci le immagini locali delle virtual machine e dei container"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -514,3 +564,32 @@ msgid ""
 msgstr ""
 "Autenticazione richiesta per verificare se la sincronizzazione dell'orario "
 "in rete possa essere attivata."
+
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autenticazione richiesta per avviare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autenticazione richiesta per fermare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autenticazione richiesta per ricaricare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autenticazione richiesta per riavviare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autenticazione richiesta per terminare '$(unit)'."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'."
index 1dd5900e2f7bd482f31cce03b165b06095819c97..2a11371f97924d3a2ffeecac714c2f8a7b9fb105 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\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"
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
@@ -441,6 +441,15 @@ msgid ""
 "interface."
 msgstr "É necessária autenticação para definir nome de máquina local."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "É necessária autenticação para definir nome de máquina local."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Conectar a um contêiner local"
@@ -451,20 +460,69 @@ 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"
+
+#: ../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."
+
+#: ../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"
+
+#: ../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."
+
+#: ../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
+#, 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."
+
+#: ../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"
+
+#: ../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."
+
+#: ../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
+#, 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."
+
+#: ../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:4
+#: ../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."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 #, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machine and container "
@@ -510,3 +568,38 @@ msgid ""
 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
+msgid "Authentication is required to start '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "É necessária autenticação para recarregar o estado do sistema."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "É necessária autenticação para se conectar a um contêiner local."
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "É necessária autenticação para definir nome de máquina local."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "É necessária autenticação para definir o horário do sistema."
index efb6f7b414d71a92cc9dfcdeca0df3ac0009e55a..0c0fab780e4b3cba82fff4f67c36750825d3faca 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,13 +1,13 @@
 # translation of ru.po to Rissian
 # Julia Dronova <juliette.tux@gmail.com>, 2013.
-# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2015.
+# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2015-03-22 21:53+0300\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
+"PO-Revision-Date: 2016-02-02 20:22+0300\n"
 "Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n"
 "Language: ru\n"
 "MIME-Version: 1.0\n"
@@ -26,12 +26,10 @@ msgid ""
 msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
 msgid "Manage system services or other units"
 msgstr "Управление системными службами и юнитами"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
 "Для управления системными службами и юнитами, необходимо пройти "
@@ -456,14 +454,24 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию."
+msgstr ""
+"Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, "
+"необходимо пройти аутентификацию."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Отправить сообщение на все терминалы"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+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"
@@ -474,21 +482,70 @@ msgid "Authentication is required to log into a local container."
 msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию."
 
 #: ../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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -536,6 +593,39 @@ msgstr ""
 "Чтобы включить или выключить синхронизацию времени по сети, необходимо "
 "пройти аутентификацию."
 
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr ""
+"Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти "
+"аутентификацию."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти "
+"аутентификацию."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти "
+"аутентификацию."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr ""
 #~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C"
index af8f421abbf831b346325ced8f1553059d089fb8..28307413096b44c1913bad8eba1fbf1529cf3aa8 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2015-03-14 11:09+0100\n"
 "Last-Translator: Sebastian Rasmussen <sebras@gmail.com>\n"
 "Language-Team: Swedish\n"
@@ -418,6 +418,15 @@ msgid ""
 "interface."
 msgstr "Autentisering krävs för att ange lokalt värdnamn."
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+msgid "Authentication is required to set a wall message"
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Logga till en lokal behållare"
@@ -427,20 +436,69 @@ msgid "Authentication is required to log into a local container."
 msgstr "Autentisering krävs för att logga till en lokal behållare"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#, fuzzy
+msgid "Log into the local host"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../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
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Logga till en lokal behållare"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../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
+#, fuzzy
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
 msgstr "Hantera lokala virtuella maskiner och behållare"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr ""
 "Autentisering krävs för att hantera lokala virtuella maskiner och behållare."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
 msgstr "Hantera lokala virtuella maskin- och behållaravbildningar"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -490,6 +548,41 @@ msgstr ""
 "Autentisering krävs för att kontrollera huruvida synkronisering av "
 "nätverkstid ska vara aktiverat."
 
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autentisering krävs för att logga till en lokal behållare"
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Autentisering krävs för att ange lokalt värdnamn."
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Autentisering krävs för ange systemtiden."
+
 #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
 #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller."
 
index 656d59c79ebf04b207ecb46ddd0df76a39041952..66044b8686bd27926b386daa1b9a90cf7e256893 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
@@ -2,21 +2,21 @@
 # Copyright (C) 2014 systemd's COPYRIGHT HOLDER
 # This file is distributed under the same license as the systemd package.
 # Eugene Melnik <jeka7js@gmail.com>, 2014.
-# Daniel Korostil <ted.korostiled@gmail.com>, 2014.
+# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
-"PO-Revision-Date: 2014-07-16 19:13+0300\n"
+"POT-Creation-Date: 2016-01-11 09:21+0200\n"
+"PO-Revision-Date: 2016-01-11 11:00+0300\n"
 "Last-Translator: Daniel Korostil <ted.korostiled@gmail.com>\n"
 "Language-Team: linux.org.ua\n"
 "Language: uk\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 "X-Generator: Virtaal 0.7.1\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
@@ -30,43 +30,42 @@ msgstr "Засвідчення потрібно, щоб надіслати вв
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
 msgid "Manage system services or other units"
-msgstr ""
+msgstr "Керувати системними службами й іншими одиницями"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й іншими одиницями."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
-msgstr ""
+msgstr "Керувати системними службами й файлами одиниць"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
-#, fuzzy
 msgid "Authentication is required to manage system service or unit files."
-msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб керувати системними службами й файлами одиниць."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
-#, fuzzy
 msgid "Set or unset system and service manager environment variables"
-msgstr "Привілейований доступ до менеджера системи і служб"
+msgstr ""
+"Встановити або забрати змінну середовища з керування службами і системою"
 
 #: ../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 "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+msgstr ""
+"Засвідчення потрібно, щоб установити або забрати змінні середовища з "
+"керування службами і системою."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
-#, fuzzy
 msgid "Reload the systemd state"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83"
+msgstr "Ð\9fеÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
-#, fuzzy
 msgid "Authentication is required to reload the systemd state."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð²ÐºÐ°Ð·Ð°Ñ\82и Ñ\81иÑ\81Ñ\82емний Ñ\87аÑ\81."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð¿ÐµÑ\80езапÑ\83Ñ\81Ñ\82иÑ\82и Ñ\81Ñ\82ан Ñ\81иÑ\81Ñ\82еми."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
 msgid "Set host name"
@@ -98,30 +97,31 @@ msgstr "Засвідчення потрібно, щоб вказати лока
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr ""
+msgstr "Імпортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to import a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr ""
+msgstr "Експортувати образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to export a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr ""
+"Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної "
+"машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
-msgstr ""
+msgstr "Звантажити образ контейнера або віртуальної машини"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to download a VM or container image"
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
@@ -277,7 +277,7 @@ msgstr "Засвідчення потрібно, щоб вимкнути сис
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system while other users are logged in"
-msgstr "Ð\92имикнÑ\83Ñ\82и Ñ\81иÑ\81Ñ\82емÑ\83, ÐºÐ¾Ð»Ð¸ Ñ\96нÑ\88Ñ\96 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87Ñ\96 Ñ\89е Ð² Ð½Ñ\96й"
+msgstr "Вимкнути систему, коли інші користувачі ще в ній"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid ""
@@ -288,7 +288,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while an application asked to inhibit it"
-msgstr "Вимкнути систему, коли програми намагаються першкодити цьому"
+msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
@@ -296,7 +296,7 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Reboot the system"
@@ -308,7 +308,7 @@ msgstr "Для перезавантаження системи необхідн
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system while other users are logged in"
-msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\89і користувачі в системі"
+msgstr "Ð\9fеÑ\80езаванÑ\82ажиÑ\82и, Ñ\8fкÑ\89о Ñ\96нÑ\88і користувачі в системі"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid ""
@@ -319,7 +319,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while an application asked to inhibit it"
-msgstr "Перезапустити систему, коли програми намагаються першкодити цьому"
+msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
@@ -327,7 +327,7 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Suspend the system"
@@ -350,15 +350,15 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while an application asked to inhibit it"
-msgstr "Призупинити систему, коли програми намагаються першкодити цьому"
+msgstr "Призупинити систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
 msgstr ""
-"Засвідчення потрібно, щоб призупнити систему, коли програми намагаються "
-"першкодити цьому."
+"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð¿Ñ\80изÑ\83пиниÑ\82и Ñ\81иÑ\81Ñ\82емÑ\83, ÐºÐ¾Ð»Ð¸ Ð¿Ñ\80огÑ\80ами Ð½Ð°Ð¼Ð°Ð³Ð°Ñ\8eÑ\82Ñ\8cÑ\81Ñ\8f "
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Hibernate the system"
@@ -381,7 +381,7 @@ msgstr ""
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Приспати систему, коли програми намагаються першкодити цьому"
+msgstr "Приспати систему, коли програми намагаються перешкодити цьому"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
@@ -389,67 +389,118 @@ msgid ""
 "asked to inhibit it."
 msgstr ""
 "Засвідчення потрібно, щоб приспати систему, коли програми намагаються "
-"першкодити цьому."
+"перешкодити цьому."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Керувати сеансами, користувачами і робочими місцями"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
-msgstr "Засвідчення потрібно, щоб під'єднувати пристрої до місць."
+msgstr ""
+"Засвідчення потрібно, щоб керувати сеансами, користувачами і робочими "
+"місцями."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Заблокувати або розблокувати сеанси"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð²ÐºÐ°Ð·Ð°Ñ\82и Ð»Ð¾ÐºÐ°Ð»Ñ\8cнÑ\83 Ñ\96нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e Ð¿Ñ\80о Ð¼Ð°Ñ\88ини."
+msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð·Ð°Ð±Ð»Ð¾ÐºÑ\83ваÑ\82и Ð°Ð±Ð¾ Ñ\80озблокÑ\83ваÑ\82и Ñ\81еанÑ\81и."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
+msgstr "Дозволити мікрокоду визначати, чи завантажувати інтерфейс встановлення"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr ""
+"Засвідчення потрібне, щоб дозволити мікрокоду визначати, чи завантажувати "
+"інтерфейс встановлення."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Вказати повідомлення на стіні"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+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 ""
+msgstr "Увійти в локальний контейнер"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to log into a local container."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Manage local virtual machines and containers"
-msgstr ""
+msgid "Log into the local host"
+msgstr "Увійти в локальний вузол"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
+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 "Перейняти псевдо TTY в локальному контейнері"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Перейняти псевдо TTY на локальному вузлі"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY на локальному вузлі."
+
+#: ../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 "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними віртуальними машинами і "
+"контейнерами."
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Керувати локальними образами віртуальних машин і контейнерів"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr ""
+"Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і "
+"контейнерів."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -488,3 +539,31 @@ msgid ""
 msgstr ""
 "Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу "
 "запущено."
+
+#: ../src/core/dbus-unit.c:449
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Засвідчення потрібно, щоб запустити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:450
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Засвідчення потрібно, щоб зупинити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:451
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Засвідчення потрібно, щоб перезавантажити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Засвідчення потрібно, щоб перезапустити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:556
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Засвідчення потрібне, щоб вбити «$(unit)»."
+
+#: ../src/core/dbus-unit.c:586
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "Засвідчення потрібне, щоб скинути «пошкоджений» стан з «$(unit)»."
+
+#: ../src/core/dbus-unit.c:618
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "Засвідчення потрібно, щоб вказати властивості на «$(unit)»."
index fb276a1577ac2b1df0a733d17d6ecd2f2bb262d0..5a214a3c486661584b8d5af300fbdfce371f48a3 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-18 00:53+0200\n"
+"POT-Creation-Date: 2015-11-22 16:37+0100\n"
 "PO-Revision-Date: 2015-06-11 12:44+0800\n"
 "Last-Translator: Jeff Huang <s8321414@gmail.com>\n"
 "Language-Team: chinese-l10n <chinese-l10n@googlegroups.com>\n"
@@ -373,6 +373,15 @@ msgid ""
 "interface."
 msgstr "對韌體的指示以開始設定介面需要驗證。"
 
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#, fuzzy
+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 "登入到本機容器"
@@ -382,19 +391,68 @@ msgid "Authentication is required to log into a local container."
 msgstr "登入到本機容器需要驗證。"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#, fuzzy
+msgid "Log into the local host"
+msgstr "登入到本機容器"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#, fuzzy
+msgid "Authentication is required to log into the local host."
+msgstr "登入到本機容器需要驗證。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#, fuzzy
+msgid "Acquire a shell in a local container"
+msgstr "登入到本機容器"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#, fuzzy
+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
+#, fuzzy
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr "設定主機名稱需要驗證。"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#, fuzzy
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "登入到本機容器"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#, fuzzy
+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
+#, fuzzy
+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:4
+#: ../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:5
+#: ../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:6
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
@@ -435,3 +493,38 @@ msgid ""
 "Authentication is required to control whether network time synchronization "
 "shall be enabled."
 msgstr "控制網路時間同步是否啟用需要驗證。"
+
+#: ../src/core/dbus-unit.c:428
+#, fuzzy
+msgid "Authentication is required to start '$(unit)'."
+msgstr "設定系統時間需要驗證。"
+
+#: ../src/core/dbus-unit.c:429
+#, fuzzy
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "設定系統時間需要驗證。"
+
+#: ../src/core/dbus-unit.c:430
+#, fuzzy
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "重新載入 systemd 狀態需要驗證。"
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#, fuzzy
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "設定系統時間需要驗證。"
+
+#: ../src/core/dbus-unit.c:535
+#, fuzzy
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "登入到本機容器需要驗證。"
+
+#: ../src/core/dbus-unit.c:565
+#, fuzzy
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr "設定主機名稱需要驗證。"
+
+#: ../src/core/dbus-unit.c:597
+#, fuzzy
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr "設定系統時間需要驗證。"
index 321d439f0c08757e5a75760510fd870321533ccb..7c8a9ce361f20205587c6e39dee0de6ef107eb2b 100644 (file)
@@ -24,6 +24,12 @@ __contains_word () {
         done
 }
 
+__get_machines() {
+        local a b
+        (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \
+               { while read a b; do echo " $a"; done; } | sort -u;
+}
+
 __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
                   ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE
                   _{P,U,G}ID _COMM _EXE _CMDLINE
@@ -49,11 +55,11 @@ _journalctl() {
                               --utc -x --catalog --no-full --force --dump-catalog
                               --flush --rotate --sync'
                        [ARG]='-b --boot --this-boot -D --directory --file -F --field
-                              -o --output -u --unit --user-unit -p --priority
+                              -M --machine -o --output -u --unit --user-unit -p --priority
                               --vacuum-size --vacuum-time'
                 [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until
                               --after-cursor --verify-key -t --identifier
-                              --root -M --machine'
+                              --root'
         )
 
         if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then
@@ -74,6 +80,9 @@ _journalctl() {
                         ;;
                         --field|-F)
                                 comps=${__journal_fields[*]}
+                       ;;
+                        --machine|-M)
+                                comps=$( __get_machines )
                         ;;
                         --priority|-p)
                                 comps=${__syslog_priorities[*]}
index 7a083d28756cde70594649ea676402b589bebdec..776eca4e626aeded37569c7e75f0c8d296287add 100644 (file)
@@ -41,7 +41,8 @@ _loginctl () {
         if __contains_word "$prev" ${OPTS[ARG]}; then
                 case $prev in
                         --signal|-s)
-                                comps=$(compgen -A signal)
+                                _signals
+                                return
                         ;;
                         --kill-who)
                                 comps='all leader'
index 140465d31685d3fffe9353f30a112919f0a3e179..e7829ca968f68eb44d6cc55f6b349d2e7c9bf7d9 100644 (file)
@@ -40,7 +40,7 @@ _machinectl() {
         )
 
         local -A VERBS=(
-               [STANDALONE]='list list-images pull-tar pull-raw pull-dkr import-tar import-raw export-tar export-raw list-transfers cancel-transfer'
+               [STANDALONE]='list list-images pull-tar pull-raw import-tar import-raw export-tar export-raw list-transfers cancel-transfer'
                  [MACHINES]='status show start login shell enable disable poweroff reboot terminate kill copy-to copy-from image-status show-image clone rename read-only remove set-limit'
         )
 
@@ -57,7 +57,8 @@ _machinectl() {
         if __contains_word "$prev" ${OPTS[ARG]}; then
                 case $prev in
                         --signal|-s)
-                                comps=$(compgen -A signal)
+                                _signals
+                                return
                         ;;
                         --kill-who)
                                 comps='all leader'
index d80d8f02a810479bf736c39646690270eefd3038..ef7dc6285ab4f8629edd822ce4cdb40b4101a1ec 100644 (file)
@@ -115,7 +115,8 @@ _systemctl () {
         if __contains_word "$prev" ${OPTS[ARG]}; then
                 case $prev in
                         --signal|-s)
-                                comps=$(compgen -A signal)
+                                _signals
+                                return
                         ;;
                         --type|-t)
                                 comps=$(__systemctl $mode -t help)
@@ -169,7 +170,7 @@ _systemctl () {
           [STARTABLE_UNITS]='start'
           [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart'
          [ISOLATABLE_UNITS]='isolate'
-         [RELOADABLE_UNITS]='reload condreload reload-or-try-restart force-reload'
+         [RELOADABLE_UNITS]='reload condreload try-reload-or-restart force-reload'
         [RESTARTABLE_UNITS]='restart reload-or-restart'
          [TARGET_AND_UNITS]='add-wants add-requires'
              [MASKED_UNITS]='unmask'
index f9b740380c26546e294fa2bf4b8a97aaf20bbd39..429e712eb3f526fa63987ebbf08923951625fe05 100644 (file)
@@ -57,7 +57,7 @@ _systemd_nspawn() {
                       [ARG]='-D --directory -u --user --uuid --capability --drop-capability --link-journal --bind --bind-ro -M --machine
                              -S --slice --setenv -Z --selinux-context -L --selinux-apifs-context --register --network-interface --network-bridge
                              --personality -i --image --tmpfs --volatile
-                             --network-macvlan'
+                             --network-macvlan --kill-signal'
         )
 
         _init_completion || return
@@ -132,6 +132,10 @@ _systemd_nspawn() {
                                 compopt -o nospace
                                 comps=$( compgen -A file -- "$cur" )
                         ;;
+                        --kill-signal)
+                                _signals
+                                return
+                        ;;
                 esac
                 COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
                 return 0
index ef790e558fbc063ec5014cd178497403a7dd7b71..a425b8c700531137615beb62f9f1f020c094314f 100644 (file)
@@ -1,6 +1,6 @@
 #compdef busctl
 
-# hostnamectl(1) completion                               -*- shell-script -*-
+# busctl(1) completion                               -*- shell-script -*-
 #
 # This file is part of systemd.
 #
index b50f0cafc98f66f943a97f76e34efc2bff6d5455..2bee23b6d3aa33c1c61f507e04acfaec442079cc 100644 (file)
@@ -34,7 +34,10 @@ _journal_none() {
 _journal_fields() {
     local -a _fields cmd
     cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" )
-    _fields=( ${(f)"$(_call_program fields $cmd[@])"} )
+    _fields=$(_call_program fields $cmd[@])
+    _fields=${_fields//'\'/'\\'}
+    _fields=${_fields//':'/'\:'}
+    _fields=( ${(f)_fields} )
     typeset -U _fields
     _describe 'possible values' _fields
 }
index 7898d7c05b614d505a3ba2100200915efb30ee77..198fa28f7b3720da78e0e78200ea14eb677177c9 100644 (file)
@@ -44,7 +44,6 @@ _available_machines() {
 
     "pull-tar:Download a TAR container image"
     "pull-raw:Download a RAW container or VM image"
-    "pull-dkr:Download a DKR container image"
     "list-transfers:Show list of downloads in progress"
     "cancel-transfer:Cancel a download"
   )
@@ -57,7 +56,7 @@ _available_machines() {
     if (( $#cmd )); then
       if (( CURRENT == 2 )); then
         case $cmd in
-          list*|cancel-transfer|pull-tar|pull-raw|pull-dkr)
+          list*|cancel-transfer|pull-tar|pull-raw)
             msg="no options" ;;
           start)
             _available_machines ;;
@@ -97,5 +96,4 @@ _arguments \
   {-o+,--output=}'[Change journal output mode.]:output modes:_sd_outputmodes' \
   '--verify=[Verification mode for downloaded images.]:verify:(no checksum signature)' \
   '--force[Download image even if already exists.]' \
-  '--dkr-index-url=[Specify the index URL to use for DKR image downloads.]' \
   '*::machinectl command:_machinectl_command'
index 58c88c9d982dd28c3c31c6f13b86d181b7edba94..667243eb53bbf15a61c30394973130d211284a40 100644 (file)
@@ -17,7 +17,7 @@
     "force-reload:Reload one or more units if possible, otherwise restart if active"
     "hibernate:Hibernate the system"
     "hybrid-sleep:Hibernate and suspend the system"
-    "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active"
+    "try-reload-or-restart:Reload one or more units if possible, otherwise restart if active"
     "isolate:Start one unit and stop all others"
     "kill:Send signal to processes of a unit"
     "is-active:Check whether units are active"
@@ -69,7 +69,7 @@
     # Deal with any aliases
     case $cmd in
       condrestart) cmd="try-restart";;
-      force-reload) cmd="reload-or-try-restart";;
+      force-reload) cmd="try-reload-or-restart";;
     esac
 
     if (( $#cmd )); then
@@ -230,7 +230,7 @@ done
 }
 
 # Completion functions for RELOADABLE_UNITS
-for fun in reload reload-or-try-restart force-reload ; do
+for fun in reload try-reload-or-restart force-reload ; do
   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
   {
     local _sys_active_units; _systemctl_active_units
index 05459dc5f67f0126ee45a35fcb8b8e041888833c..62114ff0952051eeb5efcec1e147d2a261d0e594 100644 (file)
@@ -27,7 +27,7 @@ case "$service" in
             '--no-pager[Do not pipe output into a pager]' \
             {-a,--all}'[Show all groups, including empty]' \
             '-k[Include kernel threads in output]' \
-            ':cgroups:(cpuset cpu cpuacct memory devices freezer net_cls blkio)'
+            ':cgroups:(cpuset cpu cpuacct memory devices freezer blkio)'
     ;;
     systemd-cgtop)
         _arguments \
index 2f25734612bfedb5366636f283036b0a16c34239..c5277884a805d8d30f46c1ab67011db9db25f72d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b7e6255f4905f6c0190a60cf753680712e4d2b1b..0db4967edba151cf26ee2671f4f6ee6cd5405f6a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 static char** arg_listen = NULL;
 static bool arg_accept = false;
+static int arg_socket_type = SOCK_STREAM;
 static char** arg_args = NULL;
 static char** arg_setenv = NULL;
 static const char *arg_fdname = NULL;
+static bool arg_inetd = false;
 
 static int add_epoll(int epoll_fd, int fd) {
         struct epoll_event ev = {
@@ -97,8 +97,7 @@ static int open_sockets(int *epoll_fd, bool accept) {
          */
 
         STRV_FOREACH(address, arg_listen) {
-
-                fd = make_socket_fd(LOG_DEBUG, *address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC));
+                fd = make_socket_fd(LOG_DEBUG, *address, arg_socket_type, (arg_accept*SOCK_CLOEXEC));
                 if (fd < 0) {
                         log_open();
                         return log_error_errno(fd, "Failed to open '%s': %m", *address);
@@ -129,14 +128,20 @@ static int open_sockets(int *epoll_fd, bool accept) {
         return count;
 }
 
-static int launch(char* name, char **argv, char **env, int fds) {
+static int exec_process(const char* name, char **argv, char **env, int start_fd, int n_fds) {
 
-        static const char* tocopy[] = {"TERM=", "PATH=", "USER=", "HOME="};
         _cleanup_strv_free_ char **envp = NULL;
-        _cleanup_free_ char *tmp = NULL;
+        _cleanup_free_ char *joined = NULL;
         unsigned n_env = 0, length;
-        char **s;
+        const char *tocopy;
         unsigned i;
+        char **s;
+        int r;
+
+        if (arg_inetd && n_fds != 1) {
+                log_error("--inetd only supported for single file descriptors.");
+                return -EINVAL;
+        }
 
         length = strv_length(arg_setenv);
 
@@ -146,70 +151,119 @@ static int launch(char* name, char **argv, char **env, int fds) {
                 return log_oom();
 
         STRV_FOREACH(s, arg_setenv) {
-                if (strchr(*s, '='))
-                        envp[n_env++] = *s;
-                else {
+
+                if (strchr(*s, '=')) {
+                        char *k;
+
+                        k = strdup(*s);
+                        if (!k)
+                                return log_oom();
+
+                        envp[n_env++] = k;
+                } else {
                         _cleanup_free_ char *p;
+                        const char *n;
 
                         p = strappend(*s, "=");
                         if (!p)
                                 return log_oom();
-                        envp[n_env] = strv_find_prefix(env, p);
-                        if (envp[n_env])
-                                n_env ++;
+
+                        n = strv_find_prefix(env, p);
+                        if (!n)
+                                continue;
+
+                        envp[n_env] = strdup(n);
+                        if (!envp[n_env])
+                                return log_oom();
+
+                        n_env ++;
                 }
         }
 
-        for (i = 0; i < ELEMENTSOF(tocopy); i++) {
-                envp[n_env] = strv_find_prefix(env, tocopy[i]);
-                if (envp[n_env])
-                        n_env ++;
+        FOREACH_STRING(tocopy, "TERM=", "PATH=", "USER=", "HOME=") {
+                const char *n;
+
+                n = strv_find_prefix(env, tocopy);
+                if (!n)
+                        continue;
+
+                envp[n_env] = strdup(n);
+                if (!envp[n_env])
+                        return log_oom();
+
+                n_env ++;
         }
 
-        if ((asprintf((char**)(envp + n_env++), "LISTEN_FDS=%d", fds) < 0) ||
-            (asprintf((char**)(envp + n_env++), "LISTEN_PID=%d", getpid()) < 0))
-                return log_oom();
+        if (arg_inetd) {
+                assert(n_fds == 1);
+
+                r = dup2(start_fd, STDIN_FILENO);
+                if (r < 0)
+                        return log_error_errno(errno, "Failed to dup connection to stdin: %m");
+
+                r = dup2(start_fd, STDOUT_FILENO);
+                if (r < 0)
+                        return log_error_errno(errno, "Failed to dup connection to stdout: %m");
 
-        if (arg_fdname) {
-                char *e;
+                start_fd = safe_close(start_fd);
+        } else {
+                if (start_fd != SD_LISTEN_FDS_START) {
+                        assert(n_fds == 1);
+
+                        r = dup2(start_fd, SD_LISTEN_FDS_START);
+                        if (r < 0)
+                                return log_error_errno(errno, "Failed to dup connection: %m");
 
-                e = strappend("LISTEN_FDNAMES=", arg_fdname);
-                if (!e)
+                        safe_close(start_fd);
+                        start_fd = SD_LISTEN_FDS_START;
+                }
+
+                if (asprintf((char**)(envp + n_env++), "LISTEN_FDS=%i", n_fds) < 0)
                         return log_oom();
 
-                for (i = 1; i < (unsigned) fds; i++) {
-                        char *c;
+                if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT, getpid()) < 0)
+                        return log_oom();
 
-                        c = strjoin(e, ":", arg_fdname, NULL);
-                        if (!c) {
-                                free(e);
+                if (arg_fdname) {
+                        char *e;
+
+                        e = strappend("LISTEN_FDNAMES=", arg_fdname);
+                        if (!e)
                                 return log_oom();
+
+                        for (i = 1; i < (unsigned) n_fds; i++) {
+                                char *c;
+
+                                c = strjoin(e, ":", arg_fdname, NULL);
+                                if (!c) {
+                                        free(e);
+                                        return log_oom();
+                                }
+
+                                free(e);
+                                e = c;
                         }
 
-                        free(e);
-                        e = c;
+                        envp[n_env++] = e;
                 }
-
-                envp[n_env++] = e;
         }
 
-        tmp = strv_join(argv, " ");
-        if (!tmp)
+        joined = strv_join(argv, " ");
+        if (!joined)
                 return log_oom();
 
-        log_info("Execing %s (%s)", name, tmp);
+        log_info("Execing %s (%s)", name, joined);
         execvpe(name, argv, envp);
 
-        return log_error_errno(errno, "Failed to execp %s (%s): %m", name, tmp);
+        return log_error_errno(errno, "Failed to execp %s (%s): %m", name, joined);
 }
 
-static int launch1(const char* child, char** argv, char **env, int fd) {
-        _cleanup_free_ char *tmp = NULL;
+static int fork_and_exec_process(const char* child, char** argv, char **env, int fd) {
+        _cleanup_free_ char *joined = NULL;
         pid_t parent_pid, child_pid;
-        int r;
 
-        tmp = strv_join(argv, " ");
-        if (!tmp)
+        joined = strv_join(argv, " ");
+        if (!joined)
                 return log_oom();
 
         parent_pid = getpid();
@@ -224,24 +278,6 @@ static int launch1(const char* child, char** argv, char **env, int fd) {
                 (void) reset_all_signal_handlers();
                 (void) reset_signal_mask();
 
-                r = dup2(fd, STDIN_FILENO);
-                if (r < 0) {
-                        log_error_errno(errno, "Failed to dup connection to stdin: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
-                r = dup2(fd, STDOUT_FILENO);
-                if (r < 0) {
-                        log_error_errno(errno, "Failed to dup connection to stdout: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
-                r = close(fd);
-                if (r < 0) {
-                        log_error_errno(errno, "Failed to close dupped connection: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
                 /* Make sure the child goes away when the parent dies */
                 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
                         _exit(EXIT_FAILURE);
@@ -251,31 +287,27 @@ static int launch1(const char* child, char** argv, char **env, int fd) {
                 if (getppid() != parent_pid)
                         _exit(EXIT_SUCCESS);
 
-                execvp(child, argv);
-                log_error_errno(errno, "Failed to exec child %s: %m", child);
+                exec_process(child, argv, env, fd, 1);
                 _exit(EXIT_FAILURE);
         }
 
-        log_info("Spawned %s (%s) as PID %d", child, tmp, child_pid);
-
+        log_info("Spawned %s (%s) as PID %d", child, joined, child_pid);
         return 0;
 }
 
 static int do_accept(const char* name, char **argv, char **envp, int fd) {
         _cleanup_free_ char *local = NULL, *peer = NULL;
-        _cleanup_close_ int fd2 = -1;
+        _cleanup_close_ int fd_accepted = -1;
 
-        fd2 = accept(fd, NULL, NULL);
-        if (fd2 < 0) {
-                log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd);
-                return fd2;
-        }
+        fd_accepted = accept4(fd, NULL, NULL, 0);
+        if (fd_accepted < 0)
+                return log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd);
 
-        getsockname_pretty(fd2, &local);
-        getpeername_pretty(fd2, &peer);
+        getsockname_pretty(fd_accepted, &local);
+        getpeername_pretty(fd_accepted, true, &peer);
         log_info("Connection from %s to %s", strna(peer), strna(local));
 
-        return launch1(name, argv, envp, fd2);
+        return fork_and_exec_process(name, argv, envp, fd_accepted);
 }
 
 /* SIGCHLD handler. */
@@ -283,32 +315,38 @@ static void sigchld_hdl(int sig, siginfo_t *t, void *data) {
         PROTECT_ERRNO;
 
         log_info("Child %d died with code %d", t->si_pid, t->si_status);
+
         /* Wait for a dead child. */
-        waitpid(t->si_pid, NULL, 0);
+        (void) waitpid(t->si_pid, NULL, 0);
 }
 
 static int install_chld_handler(void) {
-        int r;
-        struct sigaction act = {
+        static const struct sigaction act = {
                 .sa_flags = SA_SIGINFO,
                 .sa_sigaction = sigchld_hdl,
         };
 
+        int r;
+
         r = sigaction(SIGCHLD, &act, 0);
         if (r < 0)
-                log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
-        return r;
+                return log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
+
+        return 0;
 }
 
 static void help(void) {
         printf("%s [OPTIONS...]\n\n"
                "Listen on sockets and launch child on connection.\n\n"
                "Options:\n"
+               "  -h --help                Show this help and exit\n"
+               "     --version             Print version string and exit\n"
                "  -l --listen=ADDR         Listen for raw connections at ADDR\n"
+               "  -d --datagram            Listen on datagram instead of stream socket\n"
+               "     --seqpacket           Listen on SOCK_SEQPACKET instead of stream socket\n"
                "  -a --accept              Spawn separate child for each connection\n"
-               "  -h --help                Show this help and exit\n"
                "  -E --setenv=NAME[=VALUE] Pass an environment variable to children\n"
-               "  --version                Print version string and exit\n"
+               "     --inetd               Enable inetd file descriptor passing protocol\n"
                "\n"
                "Note: file descriptors from sd_listen_fds() will be passed through.\n"
                , program_invocation_short_name);
@@ -318,16 +356,21 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_FDNAME,
+                ARG_SEQPACKET,
+                ARG_INETD,
         };
 
         static const struct option options[] = {
                 { "help",        no_argument,       NULL, 'h'           },
                 { "version",     no_argument,       NULL, ARG_VERSION   },
+                { "datagram",    no_argument,       NULL, 'd'           },
+                { "seqpacket",   no_argument,       NULL, ARG_SEQPACKET },
                 { "listen",      required_argument, NULL, 'l'           },
                 { "accept",      no_argument,       NULL, 'a'           },
                 { "setenv",      required_argument, NULL, 'E'           },
                 { "environment", required_argument, NULL, 'E'           }, /* legacy alias */
                 { "fdname",      required_argument, NULL, ARG_FDNAME    },
+                { "inetd",       no_argument,       NULL, ARG_INETD     },
                 {}
         };
 
@@ -336,7 +379,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "+hl:aE:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0)
                 switch(c) {
                 case 'h':
                         help();
@@ -352,6 +395,24 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case 'd':
+                        if (arg_socket_type == SOCK_SEQPACKET) {
+                                log_error("--datagram may not be combined with --seqpacket.");
+                                return -EINVAL;
+                        }
+
+                        arg_socket_type = SOCK_DGRAM;
+                        break;
+
+                case ARG_SEQPACKET:
+                        if (arg_socket_type == SOCK_DGRAM) {
+                                log_error("--seqpacket may not be combined with --datagram.");
+                                return -EINVAL;
+                        }
+
+                        arg_socket_type = SOCK_SEQPACKET;
+                        break;
+
                 case 'a':
                         arg_accept = true;
                         break;
@@ -372,6 +433,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_fdname = optarg;
                         break;
 
+                case ARG_INETD:
+                        arg_inetd = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -385,6 +450,12 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
+        if (arg_socket_type == SOCK_DGRAM && arg_accept) {
+                log_error("Datagram sockets do not accept connections. "
+                          "The --datagram and --accept options may not be combined.");
+                return -EINVAL;
+        }
+
         arg_args = argv + optind;
 
         return 1 /* work to do */;
@@ -427,15 +498,14 @@ int main(int argc, char **argv, char **envp) {
 
                 log_info("Communication attempt on fd %i.", event.data.fd);
                 if (arg_accept) {
-                        r = do_accept(argv[optind], argv + optind, envp,
-                                      event.data.fd);
+                        r = do_accept(argv[optind], argv + optind, envp, event.data.fd);
                         if (r < 0)
                                 return EXIT_FAILURE;
                 } else
                         break;
         }
 
-        launch(argv[optind], argv + optind, envp, n);
+        exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, n);
 
         return EXIT_SUCCESS;
 }
index deb102c22c35e373fe7f9bba2f9633bc1f370742..d36c8db3d4061254a6b5efed5f8510daf6d0f238 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "pager.h"
 #include "path-util.h"
 #include "strv.h"
+#include "unit-name.h"
+
+static int prepare_filename(const char *filename, char **ret) {
+        int r;
+        const char *name;
+        _cleanup_free_ char *abspath = NULL;
+        _cleanup_free_ char *dir = NULL;
+        _cleanup_free_ char *with_instance = NULL;
+        char *c;
+
+        assert(filename);
+        assert(ret);
+
+        r = path_make_absolute_cwd(filename, &abspath);
+        if (r < 0)
+                return r;
+
+        name = basename(abspath);
+        if (!unit_name_is_valid(name, UNIT_NAME_ANY))
+                return -EINVAL;
+
+        if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
+                r = unit_name_replace_instance(name, "i", &with_instance);
+                if (r < 0)
+                        return r;
+        }
+
+        dir = dirname_malloc(abspath);
+        if (!dir)
+                return -ENOMEM;
+
+        if (with_instance)
+                c = path_join(NULL, dir, with_instance);
+        else
+                c = path_join(NULL, dir, name);
+        if (!c)
+                return -ENOMEM;
+
+        *ret = c;
+        return 0;
+}
 
 static int generate_path(char **var, char **filenames) {
         char **filename;
@@ -164,7 +203,7 @@ static int verify_documentation(Unit *u, bool check_man) {
 }
 
 static int verify_unit(Unit *u, bool check_man) {
-        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
         int r, k;
 
         assert(u);
@@ -193,7 +232,7 @@ static int verify_unit(Unit *u, bool check_man) {
 }
 
 int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man) {
-        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
         Manager *m = NULL;
         FILE *serial = NULL;
         FDSet *fdset = NULL;
@@ -233,18 +272,19 @@ int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man)
         log_debug("Loading remaining units from the command line...");
 
         STRV_FOREACH(filename, filenames) {
-                char fname[UNIT_NAME_MAX + 2 + 1] = "./";
+                _cleanup_free_ char *prepared = NULL;
 
                 log_debug("Handling %s...", *filename);
 
-                /* manager_load_unit does not like pure basenames, so prepend
-                 * the local directory, but only for valid names. manager_load_unit
-                 * will print the error for other ones. */
-                if (!strchr(*filename, '/') && strlen(*filename) <= UNIT_NAME_MAX) {
-                        strncat(fname + 2, *filename, UNIT_NAME_MAX);
-                        k = manager_load_unit(m, NULL, fname, &err, &units[count]);
-                } else
-                        k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
+                k = prepare_filename(*filename, &prepared);
+                if (k < 0) {
+                        log_error_errno(k, "Failed to prepare filename %s: %m", *filename);
+                        if (r == 0)
+                                r = k;
+                        continue;
+                }
+
+                k = manager_load_unit(m, NULL, prepared, &err, &units[count]);
                 if (k < 0) {
                         log_error_errno(k, "Failed to load %s: %m", *filename);
                         if (r == 0)
index d2d4a7f1902d9b529d81a5b0001ff2df78a8e657..54adad93e11136b3917671ac5e76a2838d3e4099 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e922d6fb32d30bdcf9c4300d87c3328937243c42..a84708478140c827766f648602a9dcb83fd702ed 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -134,7 +132,7 @@ static void pager_open_if_enabled(void) {
 }
 
 static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -161,7 +159,7 @@ static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *in
 }
 
 static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -339,8 +337,8 @@ static void free_host_info(struct host_info *hi) {
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info*, free_host_info);
 
 static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r, c = 0;
         struct boot_times *boot_times = NULL;
         struct unit_times *unit_times = NULL;
@@ -455,7 +453,7 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
                 {}
         };
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(free_host_infop) struct host_info *host;
         int r;
 
@@ -899,8 +897,8 @@ static int list_dependencies(sd_bus *bus, const char *name) {
         int r;
         const char *id;
         _cleanup_free_ char *path = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         struct boot_times *boot;
 
         assert(bus);
@@ -1096,7 +1094,7 @@ static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) {
         int r;
 
         STRV_FOREACH(pattern, patterns) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_free_ char *unit = NULL, *unit_id = NULL;
 
                 if (strv_extend(&expanded_patterns, *pattern) < 0)
@@ -1133,8 +1131,8 @@ static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) {
 }
 
 static int dot(sd_bus *bus, char* patterns[]) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_strv_free_ char **expanded_patterns = NULL;
         _cleanup_strv_free_ char **expanded_from_patterns = NULL;
         _cleanup_strv_free_ char **expanded_to_patterns = NULL;
@@ -1198,8 +1196,8 @@ static int dot(sd_bus *bus, char* patterns[]) {
 }
 
 static int dump(sd_bus *bus, char **args) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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 *text = NULL;
         int r;
 
@@ -1231,7 +1229,7 @@ static int dump(sd_bus *bus, char **args) {
 }
 
 static int set_log_level(sd_bus *bus, char **args) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -1258,7 +1256,7 @@ static int set_log_level(sd_bus *bus, char **args) {
 }
 
 static int set_log_target(sd_bus *bus, char **args) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -1456,7 +1454,7 @@ int main(int argc, char *argv[]) {
                                  arg_user ? MANAGER_USER : MANAGER_SYSTEM,
                                  arg_man);
         else {
-                _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+                _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
 
                 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
                 if (r < 0) {
index a5448660003e23c3d2c83473ef5b94946ab6a534..adc9286612a3f8468e78998c2f66dccc83ed9e17 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b0fa079fec2b560b0979d43704a1c4e8de1ce39b..45be135a231ba755450c17f63b992cc66cc8311d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -323,7 +321,7 @@ int main(int argc, char *argv[]) {
         errno = 0;
         device = udev_device_new_from_subsystem_sysname(udev, ss, sysname);
         if (!device) {
-                if (errno != 0)
+                if (errno > 0)
                         log_error_errno(errno, "Failed to get backlight or LED device '%s:%s': %m", ss, sysname);
                 else
                         log_oom();
index 07dfff6ad4bdb14e7e1bb57c8c3a60b6af26106a..3fac9c508ba9bdf1bf375e083cde160ca2012d89 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,7 +21,7 @@
 #include <sys/socket.h>
 
 #include "af-list.h"
-#include "util.h"
+#include "macro.h"
 
 static const struct af_name* lookup_af(register const char *str, register unsigned int len);
 
index e346ab87f5ad3d0afd21f6352c0795ad0e94c6fe..135248dc64a1a02b395878134386e0765ed07455 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 48183e381f188fdf785560a144c368adb2e68eea..b540dcddf589fafb0b4de1cccbd162c5b10ad90e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdint.h>
+#include <string.h>
+
 #include "alloc-util.h"
+#include "macro.h"
 #include "util.h"
 
 void* memdup(const void *p, size_t l) {
index 12b602e1855781b640d61c29b17ca71c9602500b..679ba7f398727a7a951711ec3d523bd4fca4922a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <alloca.h>
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 
index 03d8ad740309e1b8beb79cb4ea39eaf5978c68e3..6792d1ee3fb3509201e417d10b31d08393089c32 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,7 +21,7 @@
 #include <string.h>
 
 #include "arphrd-list.h"
-#include "util.h"
+#include "macro.h"
 
 static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
 
index 5ca182c9e8edee6dbc6484a33788ab0026fabb6a..c0f8758dbe2b95eba05d929183541f7c1b9251a8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index cfc5d224e1997061fb43158c9fd2421ccbe20ef5..a1f163f27b46204e2d6ec60e0b2097743b747fee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <pthread.h>
+#include <stddef.h>
 #include <unistd.h>
 
 #include "async.h"
 #include "fd-util.h"
 #include "log.h"
+#include "macro.h"
 #include "util.h"
 
 int asynchronous_job(void* (*func)(void *p), void *arg) {
index 7f1ef79532d81b5526a81f6632452ea2a5fe0477..9bd13ff6e0e786a923e272ab93bb0fafecc4d51c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4612297334156aa325b62894603120c30e45be50..5741fecdd67edbc7bb8aee0045cee804e415c000 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -20,7 +18,9 @@
 ***/
 
 #include <errno.h>
+#include <linux/netlink.h>
 #include <stdio.h>
+#include <sys/socket.h>
 
 #include "alloc-util.h"
 #include "audit-util.h"
@@ -30,7 +30,6 @@
 #include "parse-util.h"
 #include "process-util.h"
 #include "user-util.h"
-#include "util.h"
 
 int audit_session_from_pid(pid_t pid, uint32_t *id) {
         _cleanup_free_ char *s = NULL;
index 6de331c73e5f8b4d341a4680be9c8a35c3c31a42..e0485039918fed397997aa4e9585df709af2c72d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdint.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #define AUDIT_SESSION_INVALID ((uint32_t) -1)
index 2d55bab4abb39c5c9fca8dbaa47b6de284973e3e..2da633b31188a305ad95186ce2f314e8bb6ddfd0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -32,7 +30,6 @@
 #include "barrier.h"
 #include "fd-util.h"
 #include "macro.h"
-#include "util.h"
 
 /**
  * Barriers
@@ -198,6 +195,7 @@ static bool barrier_write(Barrier *b, uint64_t buf) {
         if (barrier_i_aborted(b))
                 return false;
 
+        assert(b->me >= 0);
         do {
                 len = write(b->me, &buf, sizeof(buf));
         } while (len < 0 && IN_SET(errno, EAGAIN, EINTR));
index b8954694d3bb2149f4928f047095b755dec630ff..6347fddc4d7cf01df6b8896d0cfe0002c66718af 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include "macro.h"
index 1449e2ea852504b682ac54fb4ea0a1775ae9c8ce..ad1fda0198f4264b3344d80764a89386644fc194 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "alloc-util.h"
 #include "bitmap.h"
-#include "util.h"
+#include "hashmap.h"
+#include "macro.h"
 
 struct Bitmap {
         uint64_t *bitmaps;
@@ -133,7 +138,8 @@ bool bitmap_isset(Bitmap *b, unsigned n) {
 bool bitmap_isclear(Bitmap *b) {
         unsigned i;
 
-        assert(b);
+        if (!b)
+                return true;
 
         for (i = 0; i < b->n_bitmaps; i++)
                 if (b->bitmaps[i] != 0)
@@ -143,7 +149,9 @@ bool bitmap_isclear(Bitmap *b) {
 }
 
 void bitmap_clear(Bitmap *b) {
-        assert(b);
+
+        if (!b)
+                return;
 
         b->bitmaps = mfree(b->bitmaps);
         b->n_bitmaps = 0;
@@ -190,7 +198,10 @@ bool bitmap_equal(Bitmap *a, Bitmap *b) {
         Bitmap *c;
         unsigned i;
 
-        if (!a ^ !b)
+        if (a == b)
+                return true;
+
+        if (!a != !b)
                 return false;
 
         if (!a)
index 2874bc99f7b90fbfb000e449f2da22f009262904..f5f8f2f0180e082c26b9068422adc6b0aab87cd1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "macro.h"
+#include <stdbool.h>
+
 #include "hashmap.h"
+#include "macro.h"
 
 typedef struct Bitmap Bitmap;
 
index c689310324f02ddf53bb745b84b367a57ba6f34e..7aa75eb091242e3d17b137440a18ad7efa6d266b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d3ae57331c8a6875fcca5106351aa0dc2b0fc328..66bdf9736ef514cc00a1bbd80b196cd1e58cf7ee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 #include "macro.h"
index be40dc570221275e9b24fd5711c2f25e22255708..359d85f2e8a9a99eeaa56eaa0ab6eeef5af2c14e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/loop.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
 #ifdef HAVE_LINUX_BTRFS_H
 #include <linux/btrfs.h>
 #endif
 #include "copy.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "io-util.h"
 #include "macro.h"
 #include "missing.h"
 #include "path-util.h"
 #include "selinux-util.h"
 #include "smack-util.h"
+#include "sparse-endian.h"
 #include "stat-util.h"
 #include "string-util.h"
+#include "time-util.h"
 #include "util.h"
 
 /* WARNING: Be careful with file system ioctls! When we get an fd, we
@@ -900,6 +912,10 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
         dev_t dev = 0;
         int r;
 
+        /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
+        if (!FILE_SIZE_VALID(new_size))
+                return -EINVAL;
+
         /* btrfs cannot handle file systems < 16M, hence use this as minimum */
         if (new_size < 16*1024*1024)
                 new_size = 16*1024*1024;
@@ -2038,7 +2054,7 @@ int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
 
                 args.key.nr_items = 256;
                 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
-                        return -errno;
+                        return negative_errno();
 
                 if (args.key.nr_items <= 0)
                         break;
index 8c11ce35d26ff18591835f00ef2ec574ed80375e..37802c2565ead2fda1a42a665c34a99e71c3ae90 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #pragma once
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <sys/types.h>
 
+#include "sd-id128.h"
+
 #include "time-util.h"
 
 typedef struct BtrfsSubvolInfo {
index 24873ab9d7f31783f1d19ac0a1ae5d492c818573..633c2aaccb58bcdb72ab162733da18b60a77ba4c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index c1534657ac921124ca8939d62b3e7301ad269c4e..d4531c79476daef45905ea5e60da2eaee491d4d1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -25,7 +23,6 @@
 #include "bus-label.h"
 #include "hexdecoct.h"
 #include "macro.h"
-#include "util.h"
 
 char *bus_label_escape(const char *s) {
         char *r, *t;
index ed1dc4e0a7788b69483a3fc337ff27996579d913..62fb2c450cfbe98f5f1876bc2a7cb7a03c33671b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/src/basic/c-rbtree.c b/src/basic/c-rbtree.c
new file mode 100644 (file)
index 0000000..914d7e5
--- /dev/null
@@ -0,0 +1,679 @@
+/***
+  This file is part of systemd. See COPYING for details.
+
+  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/>.
+***/
+
+/*
+ * RB-Tree Implementation
+ * This implements the insertion/removal of elements in RB-Trees. You're highly
+ * recommended to have an RB-Tree documentation at hand when reading this. Both
+ * insertion and removal can be split into a handful of situations that can
+ * occur. Those situations are enumerated as "Case 1" to "Case n" here, and
+ * follow closely the cases described in most RB-Tree documentations. This file
+ * does not explain why it is enough to handle just those cases, nor does it
+ * provide a proof of correctness. Dig out your algorithm 101 handbook if
+ * you're interested.
+ *
+ * This implementation is *not* straightforward. Usually, a handful of
+ * rotation, reparent, swap and link helpers can be used to implement the
+ * rebalance operations. However, those often perform unnecessary writes.
+ * Therefore, this implementation hard-codes all the operations. You're highly
+ * recommended to look at the two basic helpers before reading the code:
+ *     c_rbtree_swap_child()
+ *     c_rbtree_set_parent_and_color()
+ * Those are the only helpers used, hence, you should really know what they do
+ * before digging into the code.
+ *
+ * For a highlevel documentation of the API, see the header file and docbook
+ * comments.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include "c-rbtree.h"
+
+enum {
+        C_RBNODE_RED   = 0,
+        C_RBNODE_BLACK = 1,
+};
+
+static inline unsigned long c_rbnode_color(CRBNode *n) {
+        return (unsigned long)n->__parent_and_color & 1UL;
+}
+
+static inline _Bool c_rbnode_is_red(CRBNode *n) {
+        return c_rbnode_color(n) == C_RBNODE_RED;
+}
+
+static inline _Bool c_rbnode_is_black(CRBNode *n) {
+        return c_rbnode_color(n) == C_RBNODE_BLACK;
+}
+
+/**
+ * c_rbnode_leftmost() - return leftmost child
+ * @n:          current node, or NULL
+ *
+ * This returns the leftmost child of @n. If @n is NULL, this will return NULL.
+ * In all other cases, this function returns a valid pointer. That is, if @n
+ * does not have any left children, this returns @n.
+ *
+ * Worst case runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to leftmost child, or NULL.
+ */
+CRBNode *c_rbnode_leftmost(CRBNode *n) {
+        if (n)
+                while (n->left)
+                        n = n->left;
+        return n;
+}
+
+/**
+ * c_rbnode_rightmost() - return rightmost child
+ * @n:          current node, or NULL
+ *
+ * This returns the rightmost child of @n. If @n is NULL, this will return
+ * NULL. In all other cases, this function returns a valid pointer. That is, if
+ * @n does not have any right children, this returns @n.
+ *
+ * Worst case runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to rightmost child, or NULL.
+ */
+CRBNode *c_rbnode_rightmost(CRBNode *n) {
+        if (n)
+                while (n->right)
+                        n = n->right;
+        return n;
+}
+
+/**
+ * c_rbnode_next() - return next node
+ * @n:          current node, or NULL
+ *
+ * An RB-Tree always defines a linear order of its elements. This function
+ * returns the logically next node to @n. If @n is NULL, the last node or
+ * unlinked, this returns NULL.
+ *
+ * Worst case runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to next node, or NULL.
+ */
+CRBNode *c_rbnode_next(CRBNode *n) {
+        CRBNode *p;
+
+        if (!c_rbnode_is_linked(n))
+                return NULL;
+        if (n->right)
+                return c_rbnode_leftmost(n->right);
+
+        while ((p = c_rbnode_parent(n)) && n == p->right)
+                n = p;
+
+        return p;
+}
+
+/**
+ * c_rbnode_prev() - return previous node
+ * @n:          current node, or NULL
+ *
+ * An RB-Tree always defines a linear order of its elements. This function
+ * returns the logically previous node to @n. If @n is NULL, the first node or
+ * unlinked, this returns NULL.
+ *
+ * Worst case runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to previous node, or NULL.
+ */
+CRBNode *c_rbnode_prev(CRBNode *n) {
+        CRBNode *p;
+
+        if (!c_rbnode_is_linked(n))
+                return NULL;
+        if (n->left)
+                return c_rbnode_rightmost(n->left);
+
+        while ((p = c_rbnode_parent(n)) && n == p->left)
+                n = p;
+
+        return p;
+}
+
+/**
+ * c_rbtree_first() - return first node
+ * @t:          tree to operate on
+ *
+ * An RB-Tree always defines a linear order of its elements. This function
+ * returns the logically first node in @t. If @t is empty, NULL is returned.
+ *
+ * Fixed runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to first node, or NULL.
+ */
+CRBNode *c_rbtree_first(CRBTree *t) {
+        assert(t);
+        return c_rbnode_leftmost(t->root);
+}
+
+/**
+ * c_rbtree_last() - return last node
+ * @t:          tree to operate on
+ *
+ * An RB-Tree always defines a linear order of its elements. This function
+ * returns the logically last node in @t. If @t is empty, NULL is returned.
+ *
+ * Fixed runtime (n: number of elements in tree): O(log(n))
+ *
+ * Return: Pointer to last node, or NULL.
+ */
+CRBNode *c_rbtree_last(CRBTree *t) {
+        assert(t);
+        return c_rbnode_rightmost(t->root);
+}
+
+/*
+ * Set the color and parent of a node. This should be treated as a simple
+ * assignment of the 'color' and 'parent' fields of the node. No other magic is
+ * applied. But since both fields share its backing memory, this helper
+ * function is provided.
+ */
+static inline void c_rbnode_set_parent_and_color(CRBNode *n, CRBNode *p, unsigned long c) {
+        assert(!((unsigned long)p & 1));
+        assert(c < 2);
+        n->__parent_and_color = (CRBNode*)((unsigned long)p | c);
+}
+
+/* same as c_rbnode_set_parent_and_color(), but keeps the current parent */
+static inline void c_rbnode_set_color(CRBNode *n, unsigned long c) {
+        c_rbnode_set_parent_and_color(n, c_rbnode_parent(n), c);
+}
+
+/* same as c_rbnode_set_parent_and_color(), but keeps the current color */
+static inline void c_rbnode_set_parent(CRBNode *n, CRBNode *p) {
+        c_rbnode_set_parent_and_color(n, p, c_rbnode_color(n));
+}
+
+/*
+ * This function partially replaces an existing child pointer to a new one. The
+ * existing child must be given as @old, the new child as @new. @p must be the
+ * parent of @old (or NULL if it has no parent).
+ * This function ensures that the parent of @old now points to @new. However,
+ * it does *NOT* change the parent pointer of @new. The caller must ensure
+ * this.
+ * If @p is NULL, this function ensures that the root-pointer is adjusted
+ * instead (given as @t).
+ */
+static inline void c_rbtree_swap_child(CRBTree *t, CRBNode *p, CRBNode *old, CRBNode *new) {
+        if (p) {
+                if (p->left == old)
+                        p->left = new;
+                else
+                        p->right = new;
+        } else {
+                t->root = new;
+        }
+}
+
+static inline CRBNode *c_rbtree_paint_one(CRBTree *t, CRBNode *n) {
+        CRBNode *p, *g, *gg, *u, *x;
+
+        /*
+         * Paint a single node according to RB-Tree rules. The node must
+         * already be linked into the tree and painted red.
+         * We repaint the node or rotate the tree, if required. In case a
+         * recursive repaint is required, the next node to be re-painted
+         * is returned.
+         *      p: parent
+         *      g: grandparent
+         *      gg: grandgrandparent
+         *      u: uncle
+         *      x: temporary
+         */
+
+        /* node is red, so we can access the parent directly */
+        p = n->__parent_and_color;
+
+        if (!p) {
+                /* Case 1:
+                 * We reached the root. Mark it black and be done. As all
+                 * leaf-paths share the root, the ratio of black nodes on each
+                 * path stays the same. */
+                c_rbnode_set_parent_and_color(n, p, C_RBNODE_BLACK);
+                n = NULL;
+        } else if (c_rbnode_is_black(p)) {
+                /* Case 2:
+                 * The parent is already black. As our node is red, we did not
+                 * change the number of black nodes on any path, nor do we have
+                 * multiple consecutive red nodes. */
+                n = NULL;
+        } else if (p == p->__parent_and_color->left) { /* parent is red, so grandparent exists */
+                g = p->__parent_and_color;
+                gg = c_rbnode_parent(g);
+                u = g->right;
+
+                if (u && c_rbnode_is_red(u)) {
+                        /* Case 3:
+                         * Parent and uncle are both red. We know the
+                         * grandparent must be black then. Repaint parent and
+                         * uncle black, the grandparent red and recurse into
+                         * the grandparent. */
+                        c_rbnode_set_parent_and_color(p, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(u, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(g, gg, C_RBNODE_RED);
+                        n = g;
+                } else {
+                        /* parent is red, uncle is black */
+
+                        if (n == p->right) {
+                                /* Case 4:
+                                 * We're the right child. Rotate on parent to
+                                 * become left child, so we can handle it the
+                                 * same as case 5. */
+                                x = n->left;
+                                p->right = n->left;
+                                n->left = p;
+                                if (x)
+                                        c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK);
+                                c_rbnode_set_parent_and_color(p, n, C_RBNODE_RED);
+                                p = n;
+                        }
+
+                        /* 'n' is invalid from here on! */
+                        n = NULL;
+
+                        /* Case 5:
+                         * We're the red left child or a red parent, black
+                         * grandparent and uncle. Rotate on grandparent and
+                         * switch color with parent. Number of black nodes on
+                         * each path stays the same, but we got rid of the
+                         * double red path. As the grandparent is still black,
+                         * we're done. */
+                        x = p->right;
+                        g->left = x;
+                        p->right = g;
+                        if (x)
+                                c_rbnode_set_parent_and_color(x, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(p, gg, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(g, p, C_RBNODE_RED);
+                        c_rbtree_swap_child(t, gg, g, p);
+                }
+        } else /* if (p == p->__parent_and_color->left) */ { /* same as above, but mirrored */
+                g = p->__parent_and_color;
+                gg = c_rbnode_parent(g);
+                u = g->left;
+
+                if (u && c_rbnode_is_red(u)) {
+                        c_rbnode_set_parent_and_color(p, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(u, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(g, gg, C_RBNODE_RED);
+                        n = g;
+                } else {
+                        if (n == p->left) {
+                                x = n->right;
+                                p->left = n->right;
+                                n->right = p;
+                                if (x)
+                                        c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK);
+                                c_rbnode_set_parent_and_color(p, n, C_RBNODE_RED);
+                                p = n;
+                        }
+
+                        n = NULL;
+
+                        x = p->left;
+                        g->right = x;
+                        p->left = g;
+                        if (x)
+                                c_rbnode_set_parent_and_color(x, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(p, gg, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(g, p, C_RBNODE_RED);
+                        c_rbtree_swap_child(t, gg, g, p);
+                }
+        }
+
+        return n;
+}
+
+static inline void c_rbtree_paint(CRBTree *t, CRBNode *n) {
+        assert(t);
+        assert(n);
+
+        while (n)
+                n = c_rbtree_paint_one(t, n);
+}
+
+/**
+ * c_rbtree_add() - add node to tree
+ * @t:          tree to operate one
+ * @p:          parent node to link under, or NULL
+ * @l:          left/right slot of @p (or root) to link at
+ * @n:          node to add
+ *
+ * This links @n into the tree given as @t. The caller must provide the exact
+ * spot where to link the node. That is, the caller must traverse the tree
+ * based on their search order. Once they hit a leaf where to insert the node,
+ * call this function to link it and rebalance the tree.
+ *
+ * A typical insertion would look like this (@t is your tree, @n is your node):
+ *
+ *        CRBNode **i, *p;
+ *
+ *        i = &t->root;
+ *        p = NULL;
+ *        while (*i) {
+ *                p = *i;
+ *                if (compare(n, *i) < 0)
+ *                        i = &(*i)->left;
+ *                else
+ *                        i = &(*i)->right;
+ *        }
+ *
+ *        c_rbtree_add(t, p, i, n);
+ *
+ * Once the node is linked into the tree, a simple lookup on the same tree can
+ * be coded like this:
+ *
+ *        CRBNode *i;
+ *
+ *        i = t->root;
+ *        while (i) {
+ *                int v = compare(n, i);
+ *                if (v < 0)
+ *                        i = (*i)->left;
+ *                else if (v > 0)
+ *                        i = (*i)->right;
+ *                else
+ *                        break;
+ *        }
+ *
+ * When you add nodes to a tree, the memory contents of the node do not matter.
+ * That is, there is no need to initialize the node via c_rbnode_init().
+ * However, if you relink nodes multiple times during their lifetime, it is
+ * usually very convenient to use c_rbnode_init() and c_rbtree_remove_init().
+ * In those cases, you should validate that a node is unlinked before you call
+ * c_rbtree_add().
+ */
+void c_rbtree_add(CRBTree *t, CRBNode *p, CRBNode **l, CRBNode *n) {
+        assert(t);
+        assert(l);
+        assert(n);
+        assert(!p || l == &p->left || l == &p->right);
+        assert(p || l == &t->root);
+
+        c_rbnode_set_parent_and_color(n, p, C_RBNODE_RED);
+        n->left = n->right = NULL;
+        *l = n;
+
+        c_rbtree_paint(t, n);
+}
+
+static inline CRBNode *c_rbtree_rebalance_one(CRBTree *t, CRBNode *p, CRBNode *n) {
+        CRBNode *s, *x, *y, *g;
+
+        /*
+         * Rebalance tree after a node was removed. This happens only if you
+         * remove a black node and one path is now left with an unbalanced
+         * number or black nodes.
+         * This function assumes all paths through p and n have one black node
+         * less than all other paths. If recursive fixup is required, the
+         * current node is returned.
+         */
+
+        if (n == p->left) {
+                s = p->right;
+                if (c_rbnode_is_red(s)) {
+                        /* Case 3:
+                         * We have a red node as sibling. Rotate it onto our
+                         * side so we can later on turn it black. This way, we
+                         * gain the additional black node in our path. */
+                        g = c_rbnode_parent(p);
+                        x = s->left;
+                        p->right = x;
+                        s->left = p;
+                        c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p));
+                        c_rbnode_set_parent_and_color(p, s, C_RBNODE_RED);
+                        c_rbtree_swap_child(t, g, p, s);
+                        s = x;
+                }
+
+                x = s->right;
+                if (!x || c_rbnode_is_black(x)) {
+                        y = s->left;
+                        if (!y || c_rbnode_is_black(y)) {
+                                /* Case 4:
+                                 * Our sibling is black and has only black
+                                 * children. Flip it red and turn parent black.
+                                 * This way we gained a black node in our path,
+                                 * or we fix it recursively one layer up, which
+                                 * will rotate the red sibling as parent. */
+                                c_rbnode_set_parent_and_color(s, p, C_RBNODE_RED);
+                                if (c_rbnode_is_black(p))
+                                        return p;
+
+                                c_rbnode_set_parent_and_color(p, c_rbnode_parent(p), C_RBNODE_BLACK);
+                                return NULL;
+                        }
+
+                        /* Case 5:
+                         * Left child of our sibling is red, right one is black.
+                         * Rotate on parent so the right child of our sibling is
+                         * now red, and we can fall through to case 6. */
+                        x = y->right;
+                        s->left = y->right;
+                        y->right = s;
+                        p->right = y;
+                        if (x)
+                                c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK);
+                        x = s;
+                        s = y;
+                }
+
+                /* Case 6:
+                 * The right child of our sibling is red. Rotate left and flip
+                 * colors, which gains us an additional black node in our path,
+                 * that was previously on our sibling. */
+                g = c_rbnode_parent(p);
+                y = s->left;
+                p->right = y;
+                s->left = p;
+                c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK);
+                if (y)
+                        c_rbnode_set_parent_and_color(y, p, c_rbnode_color(y));
+                c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p));
+                c_rbnode_set_parent_and_color(p, s, C_RBNODE_BLACK);
+                c_rbtree_swap_child(t, g, p, s);
+        } else /* if (!n || n == p->right) */ { /* same as above, but mirrored */
+                s = p->left;
+                if (c_rbnode_is_red(s)) {
+                        g = c_rbnode_parent(p);
+                        x = s->right;
+                        p->left = x;
+                        s->right = p;
+                        c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(s, g, C_RBNODE_BLACK);
+                        c_rbnode_set_parent_and_color(p, s, C_RBNODE_RED);
+                        c_rbtree_swap_child(t, g, p, s);
+                        s = x;
+                }
+
+                x = s->left;
+                if (!x || c_rbnode_is_black(x)) {
+                        y = s->right;
+                        if (!y || c_rbnode_is_black(y)) {
+                                c_rbnode_set_parent_and_color(s, p, C_RBNODE_RED);
+                                if (c_rbnode_is_black(p))
+                                        return p;
+
+                                c_rbnode_set_parent_and_color(p, c_rbnode_parent(p), C_RBNODE_BLACK);
+                                return NULL;
+                        }
+
+                        x = y->left;
+                        s->right = y->left;
+                        y->left = s;
+                        p->left = y;
+                        if (x)
+                                c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK);
+                        x = s;
+                        s = y;
+                }
+
+                g = c_rbnode_parent(p);
+                y = s->right;
+                p->left = y;
+                s->right = p;
+                c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK);
+                if (y)
+                        c_rbnode_set_parent_and_color(y, p, c_rbnode_color(y));
+                c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p));
+                c_rbnode_set_parent_and_color(p, s, C_RBNODE_BLACK);
+                c_rbtree_swap_child(t, g, p, s);
+        }
+
+        return NULL;
+}
+
+static inline void c_rbtree_rebalance(CRBTree *t, CRBNode *p) {
+        CRBNode *n = NULL;
+
+        assert(t);
+        assert(p);
+
+        do {
+                n = c_rbtree_rebalance_one(t, p, n);
+                p = n ? c_rbnode_parent(n) : NULL;
+        } while (p);
+}
+
+/**
+ * c_rbtree_remove() - remove node from tree
+ * @t:          tree to operate one
+ * @n:          node to remove
+ *
+ * This removes the given node from its tree. Once unlinked, the tree is
+ * rebalanced.
+ * The caller *must* ensure that the given tree is actually the tree it is
+ * linked on. Otherwise, behavior is undefined.
+ *
+ * This does *NOT* reset @n to being unlinked (for performance reason, this
+ * function *never* modifies @n at all). If you need this, use
+ * c_rbtree_remove_init().
+ */
+void c_rbtree_remove(CRBTree *t, CRBNode *n) {
+        CRBNode *p, *s, *gc, *x, *next = NULL;
+        unsigned long c;
+
+        assert(t);
+        assert(n);
+        assert(c_rbnode_is_linked(n));
+
+        /*
+         * There are three distinct cases during node removal of a tree:
+         *  * The node has no children, in which case it can simply be removed.
+         *  * The node has exactly one child, in which case the child displaces
+         *    its parent.
+         *  * The node has two children, in which case there is guaranteed to
+         *    be a successor to the node (successor being the node ordered
+         *    directly after it). This successor cannot have two children by
+         *    itself (two interior nodes can never be successive). Therefore,
+         *    we can simply swap the node with its successor (including color)
+         *    and have reduced this case to either of the first two.
+         *
+         * Whenever the node we removed was black, we have to rebalance the
+         * tree. Note that this affects the actual node we _remove_, not @n (in
+         * case we swap it).
+         *
+         *      p: parent
+         *      s: successor
+         *      gc: grand-...-child
+         *      x: temporary
+         *      next: next node to rebalance on
+         */
+
+        if (!n->left) {
+                /*
+                 * Case 1:
+                 * The node has no left child. If it neither has a right child,
+                 * it is a leaf-node and we can simply unlink it. If it also
+                 * was black, we have to rebalance, as always if we remove a
+                 * black node.
+                 * But if the node has a right child, the child *must* be red
+                 * (otherwise, the right path has more black nodes as the
+                 * non-existing left path), and the node to be removed must
+                 * hence be black. We simply replace the node with its child,
+                 * turning the red child black, and thus no rebalancing is
+                 * required.
+                 */
+                p = c_rbnode_parent(n);
+                c = c_rbnode_color(n);
+                c_rbtree_swap_child(t, p, n, n->right);
+                if (n->right)
+                        c_rbnode_set_parent_and_color(n->right, p, c);
+                else
+                        next = (c == C_RBNODE_BLACK) ? p : NULL;
+        } else if (!n->right) {
+                /*
+                 * Case 1.1:
+                 * The node has exactly one child, and it is on the left. Treat
+                 * it as mirrored case of Case 1 (i.e., replace the node by its
+                 * child).
+                 */
+                p = c_rbnode_parent(n);
+                c = c_rbnode_color(n);
+                c_rbtree_swap_child(t, p, n, n->left);
+                c_rbnode_set_parent_and_color(n->left, p, c);
+        } else {
+                /*
+                 * Case 2:
+                 * We are dealing with a full interior node with a child not on
+                 * both sides. Find its successor and swap it. Then remove the
+                 * node similar to Case 1. For performance reasons we don't
+                 * perform the full swap, but skip links that are about to be
+                 * removed, anyway.
+                 */
+                s = n->right;
+                if (!s->left) {
+                        /* right child is next, no need to touch grandchild */
+                        p = s;
+                        gc = s->right;
+                } else {
+                        /* find successor and swap partially */
+                        s = c_rbnode_leftmost(s);
+                        p = c_rbnode_parent(s);
+
+                        gc = s->right;
+                        p->left = s->right;
+                        s->right = n->right;
+                        c_rbnode_set_parent(n->right, s);
+                }
+
+                /* node is partially swapped, now remove as in Case 1 */
+                s->left = n->left;
+                c_rbnode_set_parent(n->left, s);
+
+                x = c_rbnode_parent(n);
+                c = c_rbnode_color(n);
+                c_rbtree_swap_child(t, x, n, s);
+                if (gc)
+                        c_rbnode_set_parent_and_color(gc, p, C_RBNODE_BLACK);
+                else
+                        next = c_rbnode_is_black(s) ? p : NULL;
+                c_rbnode_set_parent_and_color(s, x, c);
+        }
+
+        if (next)
+                c_rbtree_rebalance(t, next);
+}
diff --git a/src/basic/c-rbtree.h b/src/basic/c-rbtree.h
new file mode 100644 (file)
index 0000000..20c5515
--- /dev/null
@@ -0,0 +1,297 @@
+#pragma once
+
+/***
+  This file is part of systemd. See COPYING for details.
+
+  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/>.
+***/
+
+/*
+ * Standalone Red-Black-Tree Implementation in Standard ISO-C11
+ *
+ * This header provides an RB-Tree API, that is fully implemented in ISO-C11
+ * and has no external dependencies. Furthermore, tree traversal, memory
+ * allocations, and key comparisons a fully in control of the API user. The
+ * implementation only provides the RB-Tree specific rebalancing and coloring.
+ *
+ * A tree is represented by the "CRBTree" structure. It contains a *singly*
+ * field, which is a pointer to the root node. If NULL, the tree is empty. If
+ * non-NULL, there is at least a single element in the tree.
+ *
+ * Each node of the tree is represented by the "CRBNode" structure. It has
+ * three fields. The @left and @right members can be accessed by the API user
+ * directly to traverse the tree. The third member is an implementation detail
+ * and encodes the parent pointer and color of the node.
+ * API users are required to embed the CRBNode object into their own objects
+ * and then use offsetof() (i.e., container_of() and friends) to turn CRBNode
+ * pointers into pointers to their own structure.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CRBNode CRBNode;
+typedef struct CRBTree CRBTree;
+
+/**
+ * struct CRBNode - Node of a Red-Black Tree
+ * @__parent_and_color:         internal state
+ * @left:                       left child, or NULL
+ * @right:                      right child, or NULL
+ *
+ * Each node in an RB-Tree must embed an CRBNode object. This object contains
+ * pointers to its left and right child, which can be freely accessed by the
+ * API user at any time. They are NULL, if the node does not have a left/right
+ * child.
+ *
+ * The @__parent_and_color field must never be accessed directly. It encodes
+ * the pointer to the parent node, and the color of the node. Use the accessor
+ * functions instead.
+ *
+ * There is no reason to initialize a CRBNode object before linking it.
+ * However, if you need a boolean state that tells you whether the node is
+ * linked or not, you should initialize the node via c_rbnode_init() or
+ * C_RBNODE_INIT.
+ */
+struct CRBNode {
+        CRBNode *__parent_and_color;
+        CRBNode *left;
+        CRBNode *right;
+};
+
+#define C_RBNODE_INIT(_var) { .__parent_and_color = &(_var) }
+
+CRBNode *c_rbnode_leftmost(CRBNode *n);
+CRBNode *c_rbnode_rightmost(CRBNode *n);
+CRBNode *c_rbnode_next(CRBNode *n);
+CRBNode *c_rbnode_prev(CRBNode *n);
+
+/**
+ * struct CRBTree - Red-Black Tree
+ * @root:       pointer to the root node, or NULL
+ *
+ * Each Red-Black Tree is rooted in an CRBTree object. This object contains a
+ * pointer to the root node of the tree. The API user is free to access the
+ * @root member at any time, and use it to traverse the tree.
+ *
+ * To initialize an RB-Tree, set it to NULL / all zero.
+ */
+struct CRBTree {
+        CRBNode *root;
+};
+
+CRBNode *c_rbtree_first(CRBTree *t);
+CRBNode *c_rbtree_last(CRBTree *t);
+
+void c_rbtree_add(CRBTree *t, CRBNode *p, CRBNode **l, CRBNode *n);
+void c_rbtree_remove(CRBTree *t, CRBNode *n);
+
+/**
+ * c_rbnode_init() - mark a node as unlinked
+ * @n:          node to operate on
+ *
+ * This marks the node @n as unlinked. The node will be set to a valid state
+ * that can never happen if the node is linked in a tree. Furthermore, this
+ * state is fully known to the implementation, and as such handled gracefully
+ * in all cases.
+ *
+ * You are *NOT* required to call this on your node. c_rbtree_add() can handle
+ * uninitialized nodes just fine. However, calling this allows to use
+ * c_rbnode_is_linked() to check for the state of a node. Furthermore,
+ * iterators and accessors can be called on initialized (yet unlinked) nodes.
+ *
+ * Use the C_RBNODE_INIT macro if you want to initialize static variables.
+ */
+static inline void c_rbnode_init(CRBNode *n) {
+        *n = (CRBNode)C_RBNODE_INIT(*n);
+}
+
+/**
+ * c_rbnode_is_linked() - check whether a node is linked
+ * @n:          node to check, or NULL
+ *
+ * This checks whether the passed node is linked. If you pass NULL, or if the
+ * node is not linked into a tree, this will return false. Otherwise, this
+ * returns true.
+ *
+ * Note that you must have either linked the node or initialized it, before
+ * calling this function. Never call this function on uninitialized nodes.
+ * Furthermore, removing a node via c_rbtree_remove() does *NOT* mark the node
+ * as unlinked. You have to call c_rbnode_init() yourself after removal, or use
+ * the c_rbtree_remove_init() helper.
+ *
+ * Return: true if the node is linked, false if not.
+ */
+static inline _Bool c_rbnode_is_linked(CRBNode *n) {
+        return n && n->__parent_and_color != n;
+}
+
+/**
+ * c_rbnode_parent() - return parent pointer
+ * @n           node to access
+ *
+ * This returns a pointer to the parent of the given node @n. If @n does not
+ * have a parent, NULL is returned. If @n is not linked, @n itself is returned.
+ *
+ * You should not call this on unlinked or uninitialized nodes! If you do, you
+ * better know how its semantics.
+ *
+ * Return: Pointer to parent.
+ */
+static inline CRBNode *c_rbnode_parent(CRBNode *n) {
+        return (CRBNode*)((unsigned long)n->__parent_and_color & ~1UL);
+}
+
+/**
+ * c_rbtree_remove_init() - safely remove node from tree and reinitialize it
+ * @t:          tree to operate on
+ * @n:          node to remove, or NULL
+ *
+ * This is almost the same as c_rbtree_remove(), but extends it slightly, to be
+ * more convenient to use in many cases:
+ *  - if @n is unlinked or NULL, this is a no-op
+ *  - @n is reinitialized after being removed
+ */
+static inline void c_rbtree_remove_init(CRBTree *t, CRBNode *n) {
+        if (c_rbnode_is_linked(n)) {
+                c_rbtree_remove(t, n);
+                c_rbnode_init(n);
+        }
+}
+
+/**
+ * CRBCompareFunc - compare a node to a key
+ * @t:          tree where the node is linked to
+ * @k:          key to compare
+ * @n:          node to compare
+ *
+ * If you use the tree-traversal helpers (which are optional), you need to
+ * provide this callback so they can compare nodes in a tree to the key you
+ * look for.
+ *
+ * The tree @t is provided as optional context to this callback. The key you
+ * look for is provided as @k, the current node that should be compared to is
+ * provided as @n. This function should work like strcmp(), that is, return -1
+ * if @key orders before @n, 0 if both compare equal, and 1 if it orders after
+ * @n.
+ */
+typedef int (*CRBCompareFunc) (CRBTree *t, void *k, CRBNode *n);
+
+/**
+ * c_rbtree_find_node() - find node
+ * @t:          tree to search through
+ * @f:          comparison function
+ * @k:          key to search for
+ *
+ * This searches through @t for a node that compares equal to @k. The function
+ * @f must be provided by the caller, which is used to compare nodes to @k. See
+ * the documentation of CRBCompareFunc for details.
+ *
+ * If there are multiple entries that compare equal to @k, this will return a
+ * pseudo-randomly picked node. If you need stable lookup functions for trees
+ * where duplicate entries are allowed, you better code your own lookup.
+ *
+ * Return: Pointer to matching node, or NULL.
+ */
+static inline CRBNode *c_rbtree_find_node(CRBTree *t, CRBCompareFunc f, const void *k) {
+        CRBNode *i;
+
+        assert(t);
+        assert(f);
+
+        i = t->root;
+        while (i) {
+                int v = f(t, (void *)k, i);
+                if (v < 0)
+                        i = i->left;
+                else if (v > 0)
+                        i = i->right;
+                else
+                        return i;
+        }
+
+        return NULL;
+}
+
+/**
+ * c_rbtree_find_entry() - find entry
+ * @_t:         tree to search through
+ * @_f:         comparison function
+ * @_k:         key to search for
+ * @_t:         type of the structure that embeds the nodes
+ * @_o:         name of the node-member in type @_t
+ *
+ * This is very similar to c_rbtree_find_node(), but instead of returning a
+ * pointer to the CRBNode, it returns a pointer to the surrounding object. This
+ * object must embed the CRBNode object. The type of the surrounding object
+ * must be given as @_t, and the name of the embedded CRBNode member as @_o.
+ *
+ * See c_rbtree_find_node() for more details.
+ *
+ * Return: Pointer to found entry, NULL if not found.
+ */
+#define c_rbtree_find_entry(_m, _f, _k, _t, _o) \
+        ((_t *)(((char *)c_rbtree_find_node((_m), (_f), (_k)) ?: \
+                (char *)NULL + offsetof(_t, _o)) - offsetof(_t, _o)))
+
+/**
+ * c_rbtree_find_slot() - find slot to insert new node
+ * @t:          tree to search through
+ * @f:          comparison function
+ * @k:          key to search for
+ * @p:          output storage for parent pointer
+ *
+ * This searches through @t just like c_rbtree_find_node() does. However,
+ * instead of returning a pointer to a node that compares equal to @k, this
+ * searches for a slot to insert a node with key @k. A pointer to the slot is
+ * returned, and a pointer to the parent of the slot is stored in @p. Both
+ * can be passed directly to c_rbtree_add(), together with your node to insert.
+ *
+ * If there already is a node in the tree, that compares equal to @k, this will
+ * return NULL and store the conflicting node in @p. In all other cases,
+ * this will return a pointer (non-NULL) to the empty slot to insert the node
+ * at. @p will point to the parent node of that slot.
+ *
+ * If you want trees that allow duplicate nodes, you better code your own
+ * insertion function.
+ *
+ * Return: Pointer to slot to insert node, or NULL on conflicts.
+ */
+static inline CRBNode **c_rbtree_find_slot(CRBTree *t, CRBCompareFunc f, const void *k, CRBNode **p) {
+        CRBNode **i;
+
+        assert(t);
+        assert(f);
+        assert(p);
+
+        i = &t->root;
+        *p = NULL;
+        while (*i) {
+                int v = f(t, (void *)k, *i);
+                *p = *i;
+                if (v < 0)
+                        i = &(*i)->left;
+                else if (v > 0)
+                        i = &(*i)->right;
+                else
+                        return NULL;
+        }
+
+        return i;
+}
+
+#ifdef __cplusplus
+}
+#endif
index 157ae1fb74b327000f68c7d42357e1f5acdfad88..775879076d0d8c07dbfe954054328a9e25686979 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "alloc-util.h"
 #include "calendarspec.h"
 #include "fileio.h"
+#include "macro.h"
+#include "parse-util.h"
 #include "string-util.h"
 
 #define BITS_WEEKDAYS   127
@@ -49,7 +54,7 @@ void calendar_spec_free(CalendarSpec *c) {
         free_chain(c->day);
         free_chain(c->hour);
         free_chain(c->minute);
-        free_chain(c->second);
+        free_chain(c->microsecond);
 
         free(c);
 }
@@ -135,7 +140,7 @@ int calendar_spec_normalize(CalendarSpec *c) {
         sort_chain(&c->day);
         sort_chain(&c->hour);
         sort_chain(&c->minute);
-        sort_chain(&c->second);
+        sort_chain(&c->microsecond);
 
         return 0;
 }
@@ -177,7 +182,7 @@ _pure_ bool calendar_spec_valid(CalendarSpec *c) {
         if (!chain_valid(c->minute, 0, 59))
                 return false;
 
-        if (!chain_valid(c->second, 0, 59))
+        if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1))
                 return false;
 
         return true;
@@ -232,7 +237,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
         }
 }
 
-static void format_chain(FILE *f, int space, const CalendarComponent *c) {
+static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) {
         assert(f);
 
         if (!c) {
@@ -241,14 +246,25 @@ static void format_chain(FILE *f, int space, const CalendarComponent *c) {
         }
 
         assert(c->value >= 0);
-        fprintf(f, "%0*i", space, c->value);
-
-        if (c->repeat > 0)
-                fprintf(f, "/%i", c->repeat);
+        if (!usec)
+                fprintf(f, "%0*i", space, c->value);
+        else if (c->value % USEC_PER_SEC == 0)
+                fprintf(f, "%0*i", space, (int) (c->value / USEC_PER_SEC));
+        else
+                fprintf(f, "%0*i.%06i", space, (int) (c->value / USEC_PER_SEC), (int) (c->value % USEC_PER_SEC));
+
+        if (c->repeat > 0) {
+                if (!usec)
+                        fprintf(f, "/%i", c->repeat);
+                else if (c->repeat % USEC_PER_SEC == 0)
+                        fprintf(f, "/%i", (int) (c->repeat / USEC_PER_SEC));
+                else
+                        fprintf(f, "/%i.%06i", (int) (c->repeat / USEC_PER_SEC), (int) (c->repeat % USEC_PER_SEC));
+        }
 
         if (c->next) {
                 fputc(',', f);
-                format_chain(f, space, c->next);
+                format_chain(f, space, c->next, usec);
         }
 }
 
@@ -270,17 +286,17 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
                 fputc(' ', f);
         }
 
-        format_chain(f, 4, c->year);
+        format_chain(f, 4, c->year, false);
         fputc('-', f);
-        format_chain(f, 2, c->month);
+        format_chain(f, 2, c->month, false);
         fputc('-', f);
-        format_chain(f, 2, c->day);
+        format_chain(f, 2, c->day, false);
         fputc(' ', f);
-        format_chain(f, 2, c->hour);
+        format_chain(f, 2, c->hour, false);
         fputc(':', f);
-        format_chain(f, 2, c->minute);
+        format_chain(f, 2, c->minute, false);
         fputc(':', f);
-        format_chain(f, 2, c->second);
+        format_chain(f, 2, c->microsecond, true);
 
         if (c->utc)
                 fputs(" UTC", f);
@@ -391,35 +407,70 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
         }
 }
 
-static int prepend_component(const char **p, CalendarComponent **c) {
-        unsigned long value, repeat = 0;
-        char *e = NULL, *ee = NULL;
-        CalendarComponent *cc;
-
-        assert(p);
-        assert(c);
+static int parse_component_decimal(const char **p, bool usec, unsigned long *res) {
+        unsigned long value;
+        const char *e = NULL;
+        char *ee = NULL;
+        int r;
 
         errno = 0;
-        value = strtoul(*p, &e, 10);
+        value = strtoul(*p, &ee, 10);
         if (errno > 0)
                 return -errno;
-        if (e == *p)
+        if (ee == *p)
                 return -EINVAL;
         if ((unsigned long) (int) value != value)
                 return -ERANGE;
+        e = ee;
 
-        if (*e == '/') {
-                repeat = strtoul(e+1, &ee, 10);
-                if (errno > 0)
-                        return -errno;
-                if (ee == e+1)
-                        return -EINVAL;
-                if ((unsigned long) (int) repeat != repeat)
-                        return -ERANGE;
-                if (repeat <= 0)
+        if (usec) {
+                if (value * USEC_PER_SEC / USEC_PER_SEC != value)
                         return -ERANGE;
 
-                e = ee;
+                value *= USEC_PER_SEC;
+                if (*e == '.') {
+                        unsigned add;
+
+                        e++;
+                        r = parse_fractional_part_u(&e, 6, &add);
+                        if (r < 0)
+                                return r;
+
+                        if (add + value < value)
+                                return -ERANGE;
+                        value += add;
+                }
+        }
+
+        *p = e;
+        *res = value;
+
+        return 0;
+}
+
+static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
+        unsigned long value, repeat = 0;
+        CalendarComponent *cc;
+        int r;
+        const char *e;
+
+        assert(p);
+        assert(c);
+
+        e = *p;
+
+        r = parse_component_decimal(&e, usec, &value);
+        if (r < 0)
+                return r;
+
+        if (*e == '/') {
+                e++;
+                r = parse_component_decimal(&e, usec, &repeat);
+                if (r < 0)
+                        return r;
+
+                if (repeat == 0)
+                        return -ERANGE;
         }
 
         if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':')
@@ -438,13 +489,31 @@ static int prepend_component(const char **p, CalendarComponent **c) {
 
         if (*e ==',') {
                 *p += 1;
-                return prepend_component(p, c);
+                return prepend_component(p, usec, c);
         }
 
         return 0;
 }
 
-static int parse_chain(const char **p, CalendarComponent **c) {
+static int const_chain(int value, CalendarComponent **c) {
+        CalendarComponent *cc = NULL;
+
+        assert(c);
+
+        cc = new0(CalendarComponent, 1);
+        if (!cc)
+                return -ENOMEM;
+
+        cc->value = value;
+        cc->repeat = 0;
+        cc->next = *c;
+
+        *c = cc;
+
+        return 0;
+}
+
+static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
         const char *t;
         CalendarComponent *cc = NULL;
         int r;
@@ -455,12 +524,19 @@ static int parse_chain(const char **p, CalendarComponent **c) {
         t = *p;
 
         if (t[0] == '*') {
+                if (usec) {
+                        r = const_chain(0, c);
+                        if (r < 0)
+                                return r;
+                        (*c)->repeat = USEC_PER_SEC;
+                } else
+                        *c = NULL;
+
                 *p = t + 1;
-                *c = NULL;
                 return 0;
         }
 
-        r = prepend_component(&t, &cc);
+        r = prepend_component(&t, usec, &cc);
         if (r < 0) {
                 free_chain(cc);
                 return r;
@@ -471,24 +547,6 @@ static int parse_chain(const char **p, CalendarComponent **c) {
         return 0;
 }
 
-static int const_chain(int value, CalendarComponent **c) {
-        CalendarComponent *cc = NULL;
-
-        assert(c);
-
-        cc = new0(CalendarComponent, 1);
-        if (!cc)
-                return -ENOMEM;
-
-        cc->value = value;
-        cc->repeat = 0;
-        cc->next = *c;
-
-        *c = cc;
-
-        return 0;
-}
-
 static int parse_date(const char **p, CalendarSpec *c) {
         const char *t;
         int r;
@@ -503,7 +561,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
         if (*t == 0)
                 return 0;
 
-        r = parse_chain(&t, &first);
+        r = parse_chain(&t, false, &first);
         if (r < 0)
                 return r;
 
@@ -519,7 +577,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
         }
 
         t++;
-        r = parse_chain(&t, &second);
+        r = parse_chain(&t, false, &second);
         if (r < 0) {
                 free_chain(first);
                 return r;
@@ -540,7 +598,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
         }
 
         t++;
-        r = parse_chain(&t, &third);
+        r = parse_chain(&t, false, &third);
         if (r < 0) {
                 free_chain(first);
                 free_chain(second);
@@ -582,7 +640,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
                 goto finish;
         }
 
-        r = parse_chain(&t, &h);
+        r = parse_chain(&t, false, &h);
         if (r < 0)
                 goto fail;
 
@@ -592,7 +650,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
         }
 
         t++;
-        r = parse_chain(&t, &m);
+        r = parse_chain(&t, false, &m);
         if (r < 0)
                 goto fail;
 
@@ -610,7 +668,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
         }
 
         t++;
-        r = parse_chain(&t, &s);
+        r = parse_chain(&t, true, &s);
         if (r < 0)
                 goto fail;
 
@@ -639,7 +697,8 @@ finish:
         *p = t;
         c->hour = h;
         c->minute = m;
-        c->second = s;
+        c->microsecond = s;
+
         return 0;
 
 fail:
@@ -671,7 +730,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         }
 
         if (strcaseeq(p, "minutely")) {
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -679,7 +738,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -690,7 +749,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -704,7 +763,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -724,7 +783,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -738,7 +797,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -765,7 +824,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -789,7 +848,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-                r = const_chain(0, &c->second);
+                r = const_chain(0, &c->microsecond);
                 if (r < 0)
                         goto fail;
 
@@ -906,14 +965,16 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
         return (weekdays_bits & (1 << k));
 }
 
-static int find_next(const CalendarSpec *spec, struct tm *tm) {
+static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
         struct tm c;
+        int tm_usec;
         int r;
 
         assert(spec);
         assert(tm);
 
         c = *tm;
+        tm_usec = *usec;
 
         for (;;) {
                 /* Normalize the current date */
@@ -927,7 +988,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 if (r > 0) {
                         c.tm_mon = 0;
                         c.tm_mday = 1;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                 }
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc))
                         return r;
@@ -938,29 +999,29 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
 
                 if (r > 0) {
                         c.tm_mday = 1;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                 }
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_year ++;
                         c.tm_mon = 0;
                         c.tm_mday = 1;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
                 r = find_matching_component(spec->day, &c.tm_mday);
                 if (r > 0)
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_mon ++;
                         c.tm_mday = 1;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
                 if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
                         c.tm_mday++;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
@@ -969,7 +1030,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         c.tm_min = c.tm_sec = 0;
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_mday ++;
-                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
@@ -978,19 +1039,23 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         c.tm_sec = 0;
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_hour ++;
-                        c.tm_min = c.tm_sec = 0;
+                        c.tm_min = c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
-                r = find_matching_component(spec->second, &c.tm_sec);
+                c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec;
+                r = find_matching_component(spec->microsecond, &c.tm_sec);
+                tm_usec = c.tm_sec % USEC_PER_SEC;
+                c.tm_sec /= USEC_PER_SEC;
+
                 if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_min ++;
-                        c.tm_sec = 0;
+                        c.tm_sec = tm_usec = 0;
                         continue;
                 }
 
-
                 *tm = c;
+                *usec = tm_usec;
                 return 0;
         }
 }
@@ -999,14 +1064,17 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
         struct tm tm;
         time_t t;
         int r;
+        usec_t tm_usec;
 
         assert(spec);
         assert(next);
 
-        t = (time_t) (usec / USEC_PER_SEC) + 1;
+        usec++;
+        t = (time_t) (usec / USEC_PER_SEC);
         assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc));
+        tm_usec = usec % USEC_PER_SEC;
 
-        r = find_next(spec, &tm);
+        r = find_next(spec, &tm, &tm_usec);
         if (r < 0)
                 return r;
 
@@ -1014,6 +1082,6 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
         if (t == (time_t) -1)
                 return -EINVAL;
 
-        *next = (usec_t) t * USEC_PER_SEC;
+        *next = (usec_t) t * USEC_PER_SEC + tm_usec;
         return 0;
 }
index 56dc02f391bc12cd8cc00d73a66d80ed915d6089..f6472c1244d1d1502dfab185539157c5e5c5bdc5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,6 +23,8 @@
  * time, a la cron */
 
 #include <stdbool.h>
+
+#include "time-util.h"
 #include "util.h"
 
 typedef struct CalendarComponent {
@@ -44,7 +44,7 @@ typedef struct CalendarSpec {
 
         CalendarComponent *hour;
         CalendarComponent *minute;
-        CalendarComponent *second;
+        CalendarComponent *microsecond;
 } CalendarSpec;
 
 void calendar_spec_free(CalendarSpec *c);
index f0974900cdd15305fe37cc39095a22156dd5102b..3e773a06f5f012233bb47dd0a834a1ce3ad33537 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <string.h>
 
 #include "cap-list.h"
+#include "macro.h"
 #include "missing.h"
 #include "parse-util.h"
 #include "util.h"
index 9824fad70f1edc6f0d984a8964cfbb9ef887f6df..c1f6b94ad3279433afca35499573dfe57b80212e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0eb5c03d65601f6f457675f30564c084b0c5c80f..d4c5bd69374d5cd0098193dd1999d2dcaee3a30c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,6 +20,7 @@
 #include <errno.h>
 #include <grp.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/capability.h>
 #include <sys/prctl.h>
 #include <unistd.h>
@@ -95,7 +94,62 @@ unsigned long cap_last_cap(void) {
         return p;
 }
 
-int capability_bounding_set_drop(uint64_t drop, bool right_now) {
+int capability_update_inherited_set(cap_t caps, uint64_t set) {
+        unsigned long i;
+
+        /* Add capabilities in the set to the inherited caps. Do not apply
+         * them yet. */
+
+        for (i = 0; i < cap_last_cap(); i++) {
+
+                if (set & (UINT64_C(1) << i)) {
+                        cap_value_t v;
+
+                        v = (cap_value_t) i;
+
+                        /* Make the capability inheritable. */
+                        if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, CAP_SET) < 0)
+                                return -errno;
+                }
+        }
+
+        return 0;
+}
+
+int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
+        unsigned long i;
+        _cleanup_cap_free_ cap_t caps = NULL;
+
+        /* Add the capabilities to the ambient set. */
+
+        if (also_inherit) {
+                int r;
+                caps = cap_get_proc();
+                if (!caps)
+                        return -errno;
+
+                r = capability_update_inherited_set(caps, set);
+                if (r < 0)
+                        return -errno;
+
+                if (cap_set_proc(caps) < 0)
+                        return -errno;
+        }
+
+        for (i = 0; i < cap_last_cap(); i++) {
+
+                if (set & (UINT64_C(1) << i)) {
+
+                        /* Add the capability to the ambient set. */
+                        if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0)
+                                return -errno;
+                }
+        }
+
+        return 0;
+}
+
+int capability_bounding_set_drop(uint64_t keep, bool right_now) {
         _cleanup_cap_free_ cap_t after_cap = NULL;
         cap_flag_value_t fv;
         unsigned long i;
@@ -136,7 +190,7 @@ int capability_bounding_set_drop(uint64_t drop, bool right_now) {
 
         for (i = 0; i <= cap_last_cap(); i++) {
 
-                if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
+                if (!(keep & (UINT64_C(1) << i))) {
                         cap_value_t v;
 
                         /* Drop it from the bounding set */
@@ -175,7 +229,7 @@ finish:
         return r;
 }
 
-static int drop_from_file(const char *fn, uint64_t drop) {
+static int drop_from_file(const char *fn, uint64_t keep) {
         int r, k;
         uint32_t hi, lo;
         uint64_t current, after;
@@ -195,7 +249,7 @@ static int drop_from_file(const char *fn, uint64_t drop) {
                 return -EIO;
 
         current = (uint64_t) lo | ((uint64_t) hi << 32ULL);
-        after = current & ~drop;
+        after = current & keep;
 
         if (current == after)
                 return 0;
@@ -212,14 +266,14 @@ static int drop_from_file(const char *fn, uint64_t drop) {
         return r;
 }
 
-int capability_bounding_set_drop_usermode(uint64_t drop) {
+int capability_bounding_set_drop_usermode(uint64_t keep) {
         int r;
 
-        r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", drop);
+        r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep);
         if (r < 0)
                 return r;
 
-        r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", drop);
+        r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep);
         if (r < 0)
                 return r;
 
@@ -256,7 +310,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
                 return log_error_errno(errno, "Failed to disable keep capabilities flag: %m");
 
         /* Drop all caps from the bounding set, except the ones we want */
-        r = capability_bounding_set_drop(~keep_capabilities, true);
+        r = capability_bounding_set_drop(keep_capabilities, true);
         if (r < 0)
                 return log_error_errno(r, "Failed to drop capabilities: %m");
 
index 4eb5c2a835d60c55a4395682943e546e86e6593f..35a896e229fa0ef3544fc96239030554488bf33f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <sys/capability.h>
+#include <sys/types.h>
 
+#include "macro.h"
 #include "util.h"
 
+#define CAP_ALL (uint64_t) -1
+
 unsigned long cap_last_cap(void);
 int have_effective_cap(int value);
-int capability_bounding_set_drop(uint64_t drop, bool right_now);
-int capability_bounding_set_drop_usermode(uint64_t drop);
+int capability_bounding_set_drop(uint64_t keep, bool right_now);
+int capability_bounding_set_drop_usermode(uint64_t keep);
+
+int capability_ambient_set_apply(uint64_t set, bool also_inherit);
+int capability_update_inherited_set(cap_t caps, uint64_t ambient_set);
 
 int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
 
@@ -43,3 +49,9 @@ static inline void cap_free_charpp(char **p) {
                 cap_free(*p);
 }
 #define _cleanup_cap_free_charp_ _cleanup_(cap_free_charpp)
+
+static inline bool cap_test_all(uint64_t caps) {
+        uint64_t m;
+        m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1;
+        return (caps & m) == m;
+}
index f7fc2c2c975d05dd0919a3b62ba69a74a37bbd4f..6ef00d51df28e2da6d90fc5e7c5efe2fd120d412 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <dirent.h>
 #include <errno.h>
 #include <ftw.h>
+#include <limits.h>
 #include <signal.h>
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "cgroup-util.h"
+#include "def.h"
 #include "dirent-util.h"
 #include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
 #include "fs-util.h"
+#include "log.h"
 #include "login-util.h"
 #include "macro.h"
+#include "missing.h"
 #include "mkdir.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "set.h"
 #include "special.h"
 #include "stat-util.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "unit-name.h"
 #include "user-util.h"
-#include "util.h"
 
 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
         _cleanup_free_ char *fs = NULL;
@@ -87,7 +91,7 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
                 if (feof(f))
                         return 0;
 
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
         }
 
         if (ul <= 0)
@@ -642,7 +646,7 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) {
                 if (errno == ENOENT)
                         r = 0;
-                else if (errno != 0)
+                else if (errno > 0)
                         r = -errno;
                 else
                         r = -EIO;
@@ -711,7 +715,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
         if (pid == 0)
                 pid = getpid();
 
-        snprintf(c, sizeof(c), PID_FMT"\n", pid);
+        xsprintf(c, PID_FMT "\n", pid);
 
         return write_string_file(fs, c, 0);
 }
@@ -2085,7 +2089,7 @@ int cg_kernel_controllers(Set *controllers) {
                         if (feof(f))
                                 break;
 
-                        if (ferror(f) && errno != 0)
+                        if (ferror(f) && errno > 0)
                                 return -errno;
 
                         return -EBADMSG;
@@ -2130,7 +2134,7 @@ int cg_unified(void) {
         else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
                 unified_cache = false;
         else
-                return -ENOEXEC;
+                return -ENOMEDIUM;
 
         return unified_cache;
 }
@@ -2265,7 +2269,6 @@ static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
         [CGROUP_CONTROLLER_MEMORY] = "memory",
         [CGROUP_CONTROLLER_DEVICES] = "devices",
         [CGROUP_CONTROLLER_PIDS] = "pids",
-        [CGROUP_CONTROLLER_NET_CLS] = "net_cls",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
index 01359fa7cb40643892704a5500db3f95fac42a23..ad1edd9cdbc1cbf758275efc1dcc7a7e659d058a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
-#include <stdio.h>
 #include <dirent.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
 
-#include "set.h"
 #include "def.h"
+#include "hashmap.h"
+#include "macro.h"
+#include "set.h"
 
 /* An enum of well known cgroup controllers */
 typedef enum CGroupController {
@@ -36,7 +38,6 @@ typedef enum CGroupController {
         CGROUP_CONTROLLER_MEMORY,
         CGROUP_CONTROLLER_DEVICES,
         CGROUP_CONTROLLER_PIDS,
-        CGROUP_CONTROLLER_NET_CLS,
         _CGROUP_CONTROLLER_MAX,
         _CGROUP_CONTROLLER_INVALID = -1,
 } CGroupController;
@@ -51,7 +52,6 @@ typedef enum CGroupMask {
         CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
         CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
         CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS),
-        CGROUP_MASK_NET_CLS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_NET_CLS),
         _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
 } CGroupMask;
 
index d49ca0537ad6f6a394777bd5c50952e2e619f117..2896a729af3494f392100f4e128cc58a838f1d72 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <linux/fs.h>
 
 #include "chattr-util.h"
 #include "fd-util.h"
-#include "util.h"
+#include "macro.h"
 
 int chattr_fd(int fd, unsigned value, unsigned mask) {
         unsigned old_attr, new_attr;
index ba6b8eb5c17ca2039c8270f71283db5a710fcb02..960cf6d5b3f9289212e0fcde9ba752090c37a2e0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 00ee4c2796df7391876de0abf07e052f28f1c9b6..507e757ff0806af3a0f29baec414abe98c098d5a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,6 +19,9 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <time.h>
 #include <linux/rtc.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
@@ -119,7 +120,8 @@ int clock_set_timezone(int *min) {
          * have read from the RTC.
          */
         if (settimeofday(tv_null, &tz) < 0)
-                return -errno;
+                return negative_errno();
+
         if (min)
                 *min = minutesdelta;
         return 0;
@@ -142,3 +144,17 @@ int clock_reset_timewarp(void) {
 
         return 0;
 }
+
+#define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC)
+
+int clock_apply_epoch(void) {
+        struct timespec ts;
+
+        if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC)
+                return 0;
+
+        if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0)
+                return -errno;
+
+        return 1;
+}
index fef2d471a6f37f45c83d13cb7bbc1b56f8e257f5..f471f2abcfa95c1d062ae20b2c8c50cfd4b2ea41 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -28,3 +26,4 @@ int clock_set_timezone(int *min);
 int clock_reset_timewarp(void);
 int clock_get_hwclock(struct tm *tm);
 int clock_set_hwclock(const struct tm *tm);
+int clock_apply_epoch(void);
index be9972fffffe6fc054ec12f6ab790166cf10bf07..c781610e14a3e97d94b6c5327e292cf471c1a442 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,6 +19,7 @@
 
 #include <dirent.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -40,6 +39,7 @@
 static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
         _cleanup_closedir_ DIR *dir = NULL;
         const char *dirpath;
+        struct dirent *de;
         int r;
 
         assert(path);
@@ -54,18 +54,9 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char
                 return -errno;
         }
 
-        for (;;) {
-                struct dirent *de;
+        FOREACH_DIRENT(de, dir, return -errno) {
                 char *p;
 
-                errno = 0;
-                de = readdir(dir);
-                if (!de && errno != 0)
-                        return -errno;
-
-                if (!de)
-                        break;
-
                 if (!dirent_is_file_with_suffix(de, suffix))
                         continue;
 
@@ -115,17 +106,15 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
 
         STRV_FOREACH(p, dirs) {
                 r = files_add(fh, root, *p, suffix);
-                if (r == -ENOMEM) {
+                if (r == -ENOMEM)
                         return r;
-                } else if (r < 0)
-                        log_debug_errno(r, "Failed to search for files in %s: %m",
-                                        *p);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p);
         }
 
         files = hashmap_get_strv(fh);
-        if (files == NULL) {
+        if (!files)
                 return -ENOMEM;
-        }
 
         qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp);
         *strv = files;
index d8aebc5e5b8ddb5ac4e9572d3bd6ecfd59c9b24f..e00e0e81fbd3713e5a5d8d49f1285e2227c6a6a5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a187ae08fe6dd542168ffe57eb67b37f0d17fc0a..519b412941f6cb30d5521ca0f8e47df28bda6b34 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/sendfile.h>
+#include <sys/stat.h>
 #include <sys/xattr.h>
+#include <time.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "btrfs-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "macro.h"
 #include "string-util.h"
 #include "strv.h"
+#include "time-util.h"
 #include "umask-util.h"
-#include "util.h"
 #include "xattr-util.h"
 
 #define COPY_BUFFER_SIZE (16*1024)
index ba0890b44249ea764c7eaa850e9542700024b535..3e5eb525064440cca67c4a718acf600c6b041e85 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 
 #include <inttypes.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 int copy_file_fd(const char *from, int to, bool try_reflink);
index e2ec4ca83f06e1e9fb69cf65d3437f1f8c41b0ff..95ed6928fffb6fd64e0a5617e9ca23a74ccf120b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stddef.h>
+#include <syslog.h>
+
 #include "alloc-util.h"
 #include "cpu-set-util.h"
 #include "extract-word.h"
+#include "log.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "string-util.h"
-#include "util.h"
 
 cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         cpu_set_t *c;
index 19b457a684854643a53aab58abc6b61dc409109d..6f49d9afb00d2ce0ac2e9921a5c6b8d3ef505e51 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0657ac736724930a2267c2fd65d39dababca1c1e..963343eb7df548b77dda82636be2fe6a4b5ce922 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9d5af72d27da107310a6ed07de90c19c1b0f9d2d..38c0628a908798452616aa3f8b9844002d80c8de 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -19,7 +17,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "device-nodes.h"
 #include "utf8.h"
index 7db81f3d52e4e1110c5274fec8bdc196c9671ee1..94f385abcb86bc2a0a7fbd25fef23be08168eab7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
 #include <sys/types.h>
 
 int encode_devnode_name(const char *str, char *str_enc, size_t len);
index c433d5844aa15b236a9a6a343f0ea192a3eb1dfe..5fb535cb13a2a55f86170747a9d4752b4f400864 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
 
 #include "dirent-util.h"
+#include "path-util.h"
 #include "string-util.h"
 
 int dirent_ensure_type(DIR *d, struct dirent *de) {
index 5866a755f4a80423c0a4a3759dcf44cbd42e0852..6bf099b46c0a51ba6cb304aecfaf1e02d045d828 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
 
+#include "macro.h"
 #include "path-util.h"
 
 int dirent_ensure_type(DIR *d, struct dirent *de);
index 441169db311eb3118be49ff36267d26ebd168a83..7f5fddb70062395104413eafe029f8bc5e49495d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
-#include "def.h"
 #include "env-util.h"
+#include "extract-word.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "utf8.h"
-#include "util.h"
 
 #define VALID_CHARS_ENV_NAME                    \
         DIGITS LETTERS                          \
index 5efffa3dc72483952f2a44bc2f853a1e294dd1b8..b1fef704c2ae8f5a0eab7b354c1988ec91a29660 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
 
 #include "macro.h"
 
index 22869e41366724e5c6269a1ae9024eb006b15834..31b66bad5e95e5632097c0623ec501331962ce8a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <string.h>
 
 #include "errno-list.h"
-#include "util.h"
+#include "macro.h"
 
 static const struct errno_name* lookup_errno(register const char *str,
-                                                 register unsigned int len);
+                                             register unsigned int len);
 
 #include "errno-from-name.h"
 #include "errno-to-name.h"
@@ -48,8 +46,9 @@ int errno_from_name(const char *name) {
 
         sc = lookup_errno(name, strlen(name));
         if (!sc)
-                return 0;
+                return -EINVAL;
 
+        assert(sc->id > 0);
         return sc->id;
 }
 
index ba533294e648608f4d7a9882270edc616b5ac8a1..4eec0cc7869707380c5a7a44a7b6401aceb39f4e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4815161b092afb5d1d04eef1856b8db7341d6ca9..2e483880c80c53996a73c9d9816c8cbcac524b0c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "alloc-util.h"
 #include "escape.h"
 #include "hexdecoct.h"
-#include "string-util.h"
+#include "macro.h"
 #include "utf8.h"
-#include "util.h"
 
 size_t cescape_char(char c, char *buf) {
         char * buf_old = buf;
@@ -89,20 +90,20 @@ size_t cescape_char(char c, char *buf) {
         return buf - buf_old;
 }
 
-char *cescape(const char *s) {
-        char *r, *t;
+char *cescape_length(const char *s, size_t n) {
         const char *f;
+        char *r, *t;
 
-        assert(s);
+        assert(s || n == 0);
 
         /* Does C style string escaping. May be reversed with
          * cunescape(). */
 
-        r = new(char, strlen(s)*4 + 1);
+        r = new(char, n*4 + 1);
         if (!r)
                 return NULL;
 
-        for (f = s, t = r; *f; f++)
+        for (f = s, t = r; f < s + n; f++)
                 t += cescape_char(*f, t);
 
         *t = 0;
@@ -110,16 +111,24 @@ char *cescape(const char *s) {
         return r;
 }
 
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
+char *cescape(const char *s) {
+        assert(s);
+
+        return cescape_length(s, strlen(s));
+}
+
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
         int r = 1;
 
         assert(p);
         assert(*p);
         assert(ret);
 
-        /* Unescapes C style. Returns the unescaped character in ret,
-         * unless we encountered a \u sequence in which case the full
-         * unicode character is returned in ret_unicode, instead. */
+        /* Unescapes C style. Returns the unescaped character in ret.
+         * Sets *eight_bit to true if the escaped sequence either fits in
+         * one byte in UTF-8 or is a non-unicode literal byte and should
+         * instead be copied directly.
+         */
 
         if (length != (size_t) -1 && length < 1)
                 return -EINVAL;
@@ -181,7 +190,8 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (a == 0 && b == 0)
                         return -EINVAL;
 
-                *ret = (char) ((a << 4U) | b);
+                *ret = (a << 4U) | b;
+                *eight_bit = true;
                 r = 3;
                 break;
         }
@@ -208,16 +218,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (c == 0)
                         return -EINVAL;
 
-                if (c < 128)
-                        *ret = c;
-                else {
-                        if (!ret_unicode)
-                                return -EINVAL;
-
-                        *ret = 0;
-                        *ret_unicode = c;
-                }
-
+                *ret = c;
                 r = 5;
                 break;
         }
@@ -227,7 +228,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
 
                 int a[8];
                 unsigned i;
-                uint32_t c;
+                char32_t c;
 
                 if (length != (size_t) -1 && length < 9)
                         return -EINVAL;
@@ -249,16 +250,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                 if (!unichar_is_valid(c))
                         return -EINVAL;
 
-                if (c < 128)
-                        *ret = c;
-                else {
-                        if (!ret_unicode)
-                                return -EINVAL;
-
-                        *ret = 0;
-                        *ret_unicode = c;
-                }
-
+                *ret = c;
                 r = 9;
                 break;
         }
@@ -273,7 +265,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
         case '7': {
                 /* octal encoding */
                 int a, b, c;
-                uint32_t m;
+                char32_t m;
 
                 if (length != (size_t) -1 && length < 3)
                         return -EINVAL;
@@ -300,6 +292,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
                         return -EINVAL;
 
                 *ret = m;
+                *eight_bit = true;
                 r = 3;
                 break;
         }
@@ -332,8 +325,8 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
 
         for (f = s, t = r + pl; f < s + length; f++) {
                 size_t remaining;
-                uint32_t u;
-                char c;
+                bool eight_bit = false;
+                char32_t u;
                 int k;
 
                 remaining = s + length - f;
@@ -356,7 +349,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
                         return -EINVAL;
                 }
 
-                k = cunescape_one(f + 1, remaining - 1, &c, &u);
+                k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
                 if (k < 0) {
                         if (flags & UNESCAPE_RELAX) {
                                 /* Invalid escape code, let's take it literal then */
@@ -368,14 +361,13 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
                         return k;
                 }
 
-                if (c != 0)
-                        /* Non-Unicode? Let's encode this directly */
-                        *(t++) = c;
+                f += k;
+                if (eight_bit)
+                        /* One byte? Set directly as specified */
+                        *(t++) = u;
                 else
-                        /* Unicode? Then let's encode this in UTF-8 */
+                        /* Otherwise encode as multi-byte UTF-8 */
                         t += utf8_encode_unichar(t, u);
-
-                f += k;
         }
 
         *t = 0;
index 85ba9090818f3626d12787de0b4aee42f0db29f0..1b28bd10afc21e920a043f02c51d642eaef6bce5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <uchar.h>
+
+#include "string-util.h"
+#include "missing.h"
 
 /* What characters are special in the shell? */
 /* must be escaped outside and inside double-quotes */
@@ -35,12 +39,13 @@ typedef enum UnescapeFlags {
 } UnescapeFlags;
 
 char *cescape(const char *s);
+char *cescape_length(const char *s, size_t n);
 size_t cescape_char(char c, char *buf);
 
 int cunescape(const char *s, UnescapeFlags flags, char **ret);
 int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode);
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
 char *xescape(const char *s, const char *bad);
 
index 2bf3bfec1def03461544c1c2298452bdfc79e951..ded6d31f4be61a30765660b32dc85610ddf11119 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -19,7 +17,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <net/ethernet.h>
 #include <stdio.h>
+#include <sys/types.h>
 
 #include "ether-addr-util.h"
 #include "macro.h"
index 008f3b893e592a137c3dcf21ff9bdf19b60296fa..4487149efd5cd90e4199708e4ce2cee5626a4642 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4c837315405ae102de1bf89ab13bcf3965a650d5..5e0bc415c899acbed6af1293b785ca44d8af099d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7259cd1d18ae612b2679b64d89914a6427babdbf..79525d30eec945352394135d207e1e543ddbdb61 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,8 @@
 
 #include <stdbool.h>
 
+#include "hashmap.h"
+#include "macro.h"
 #include "set.h"
 
 typedef enum ExitStatus {
index fd495692faec6ea4c08fdade937cc6962fe15867..ee35d2a0ec9e177ce611fc0b05d7e32f60309033 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
 #include "alloc-util.h"
 #include "escape.h"
 #include "extract-word.h"
+#include "log.h"
+#include "macro.h"
 #include "string-util.h"
 #include "utf8.h"
-#include "util.h"
 
 int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
         _cleanup_free_ char *s = NULL;
@@ -97,9 +105,10 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                         }
 
                         if (flags & EXTRACT_CUNESCAPE) {
-                                uint32_t u;
+                                bool eight_bit = false;
+                                char32_t u;
 
-                                r = cunescape_one(*p, (size_t) -1, &c, &u);
+                                r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
                                 if (r < 0) {
                                         if (flags & EXTRACT_CUNESCAPE_RELAX) {
                                                 s[sz++] = '\\';
@@ -109,10 +118,10 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                 } else {
                                         (*p) += r - 1;
 
-                                        if (c != 0)
-                                                s[sz++] = c; /* normal explicit char */
+                                        if (eight_bit)
+                                                s[sz++] = u;
                                         else
-                                                sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
+                                                sz += utf8_encode_unichar(s + sz, u);
                                 }
                         } else
                                 s[sz++] = c;
index 9606ab64b31241b39ca5e6d0d9d4b1c35bead6e5..21db5ef33fb550bb3e34644a9f510dcf7958079a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d1b1db3a4ddc83b8c73ecf7c3ff51a19885d2fef..ec9560cd07702d80603d427d890037e6d405e1b9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "dirent-util.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include "fd-util.h"
+#include "macro.h"
+#include "missing.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "socket-util.h"
 #include "util.h"
 
index 0e9182d75be165fbc2a59892ac281ac6785f3fba..44528c6e35f97c965d8cc40e98314054eec052fa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,9 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdio.h>
 #include <dirent.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <sys/socket.h>
 
 #include "macro.h"
@@ -73,3 +71,7 @@ int same_fd(int a, int b);
 void cmsg_close_all(struct msghdr *mh);
 
 bool fdname_is_valid(const char *s);
+
+/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
+#define ERRNO_IS_DISCONNECT(r) \
+        IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
index e5452f3bb0e246a7b76032ffc6f967dbf760b573..3674d3ed9da00f179d64f08f4602675b26392245 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stddef.h>
 
 #include "sd-daemon.h"
 
-#include "dirent-util.h"
 #include "fd-util.h"
 #include "fdset.h"
+#include "log.h"
 #include "macro.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "set.h"
-#include "util.h"
 
 #define MAKE_SET(s) ((Set*) s)
 #define MAKE_FDSET(s) ((FDSet*) s)
index 70d8acbcff3434e5e0983f1a93eeaea391d5afe1..12d0cef7618d75322235bab9f04532895fb19b84 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
+#include "hashmap.h"
+#include "macro.h"
 #include "set.h"
 
 typedef struct FDSet FDSet;
index 0405822ce08c4511cadefca4e4c8d2411b823cae..66dbc0fe1e6286cede6359f21948591078116191 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/stat.h>
+
 #include "fileio-label.h"
+#include "fileio.h"
 #include "selinux-util.h"
-#include "util.h"
 
 int write_string_file_atomic_label(const char *fn, const char *line) {
         int r;
index 25fa351be276eb26475cb9f9ce16910f555b9195..fe7543013d143441ec492c98e2b8c1a1b33614d9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 ***/
 
 #include <stdio.h>
+
 #include "fileio.h"
 
 int write_string_file_atomic_label(const char *fn, const char *line);
index 10aacdc56dc11f1465034cf9c57d083b6b77bdf2..e43ca6d29e453aaa48ccc4085e050248a34e0bbf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "hexdecoct.h"
+#include "log.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "random-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
+#include "time-util.h"
 #include "umask-util.h"
 #include "utf8.h"
-#include "util.h"
 
 int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
 
@@ -154,7 +163,7 @@ int read_one_line_file(const char *fn, char **line) {
         if (!fgets(t, sizeof(t), f)) {
 
                 if (ferror(f))
-                        return errno ? -errno : -EIO;
+                        return errno > 0 ? -errno : -EIO;
 
                 t[0] = 0;
         }
@@ -1053,7 +1062,7 @@ int fflush_and_check(FILE *f) {
         fflush(f);
 
         if (ferror(f))
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
@@ -1240,3 +1249,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
         *ret = (usec_t) t;
         return 0;
 }
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
+        int r;
+
+        assert(s);
+
+        /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
+         * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
+         * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
+         * element, but not before the first one. */
+
+        if (!f)
+                f = stdout;
+
+        if (space) {
+                if (!separator)
+                        separator = " ";
+
+                if (*space) {
+                        r = fputs(separator, f);
+                        if (r < 0)
+                                return r;
+                }
+
+                *space = true;
+        }
+
+        return fputs(s, f);
+}
index 95e8698941c4d9914ae47828ecf83b67f925f58a..8084895ff32a1ee22205e7356a37edbe1265594a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -82,3 +80,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret);
 
 int write_timestamp_file_atomic(const char *fn, usec_t n);
 int read_timestamp_file(const char *fn, usec_t *ret);
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
index 2b6189ad909cbc3f7cfb24bddb2dd54423a3e450..3ef1b90eddde9088976910ad10ae70b1adfa999b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
 #include "alloc-util.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "log.h"
+#include "macro.h"
+#include "missing.h"
 #include "mkdir.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
 #include "strv.h"
+#include "time-util.h"
 #include "user-util.h"
 #include "util.h"
 
@@ -327,7 +339,8 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
         if (parents)
                 mkdir_parents(path, 0755);
 
-        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
+                        (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
         if (fd < 0)
                 return -errno;
 
@@ -467,7 +480,7 @@ int get_files_in_directory(const char *path, char ***list) {
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
                 if (!de)
                         break;
index 902c7e295b53502f7043a7d3096053e6df549a1d..0e2fcb21b959a6214ee937e16d4c126a54bae507 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
 #include <sys/inotify.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <limits.h>
 
 #include "time-util.h"
 
index 0bfbcb1d37340749d4b2c738212c773b40c40ed9..007198c269863a9f69ee4bfc8b75d3e66107770a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <glob.h>
 
 #include "glob-util.h"
-#include "string-util.h"
+#include "macro.h"
 #include "strv.h"
-#include "util.h"
 
 int glob_exists(const char *path) {
         _cleanup_globfree_ glob_t g = {};
@@ -40,7 +38,7 @@ int glob_exists(const char *path) {
         if (k == GLOB_NOSPACE)
                 return -ENOMEM;
         if (k != 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return !strv_isempty(g.gl_pathv);
 }
@@ -58,7 +56,7 @@ int glob_extend(char ***strv, const char *path) {
         if (k == GLOB_NOSPACE)
                 return -ENOMEM;
         if (k != 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
         if (strv_isempty(g.gl_pathv))
                 return -ENOENT;
 
index 793adf4a6c910978e8b2fa90d0024e1c8247a9c8..5d8fb47a268c3a265aa8290051273aa2f9d4b6bc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
 #include <string.h>
 
 #include "macro.h"
index d89a2f3ed960a9146b8c50fa97fb3bfa879524ce..542110503f7f37cd6119e0a4c0918620ea4ef330 100644 (file)
@@ -4,6 +4,8 @@
  *  Copyright 2000, 2005 Red Hat, Inc.
  */
 
+#include <stdlib.h>
+
 #include "gunicode.h"
 
 #define unichar uint32_t
index e70818fdd74757d3bbbf2fa6ca1d94cf960df8f7..b03aa431603c64a834d596a4962b9c83bdbca81e 100644 (file)
@@ -6,8 +6,8 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdlib.h>
 
 char *utf8_prev_char (const char *p);
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c
new file mode 100644 (file)
index 0000000..c3a4a01
--- /dev/null
@@ -0,0 +1,81 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2014 Michal Schmidt
+
+  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 "hash-funcs.h"
+
+void string_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, strlen(p) + 1, state);
+}
+
+int string_compare_func(const void *a, const void *b) {
+        return strcmp(a, b);
+}
+
+const struct hash_ops string_hash_ops = {
+        .hash = string_hash_func,
+        .compare = string_compare_func
+};
+
+void trivial_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(&p, sizeof(p), state);
+}
+
+int trivial_compare_func(const void *a, const void *b) {
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops trivial_hash_ops = {
+        .hash = trivial_hash_func,
+        .compare = trivial_compare_func
+};
+
+void uint64_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, sizeof(uint64_t), state);
+}
+
+int uint64_compare_func(const void *_a, const void *_b) {
+        uint64_t a, b;
+        a = *(const uint64_t*) _a;
+        b = *(const uint64_t*) _b;
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops uint64_hash_ops = {
+        .hash = uint64_hash_func,
+        .compare = uint64_compare_func
+};
+
+#if SIZEOF_DEV_T != 8
+void devt_hash_func(const void *p, struct siphash *state) {
+        siphash24_compress(p, sizeof(dev_t), state);
+}
+
+int devt_compare_func(const void *_a, const void *_b) {
+        dev_t a, b;
+        a = *(const dev_t*) _a;
+        b = *(const dev_t*) _b;
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+const struct hash_ops devt_hash_ops = {
+        .hash = devt_hash_func,
+        .compare = devt_compare_func
+};
+#endif
diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h
new file mode 100644 (file)
index 0000000..299189d
--- /dev/null
@@ -0,0 +1,65 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2014 Michal Schmidt
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+#include "siphash24.h"
+
+typedef void (*hash_func_t)(const void *p, struct siphash *state);
+typedef int (*compare_func_t)(const void *a, const void *b);
+
+struct hash_ops {
+        hash_func_t hash;
+        compare_func_t compare;
+};
+
+void string_hash_func(const void *p, struct siphash *state);
+int string_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops string_hash_ops;
+
+/* This will compare the passed pointers directly, and will not
+ * dereference them. This is hence not useful for strings or
+ * suchlike. */
+void trivial_hash_func(const void *p, struct siphash *state);
+int trivial_compare_func(const void *a, const void *b) _const_;
+extern const struct hash_ops trivial_hash_ops;
+
+/* 32bit values we can always just embed in the pointer itself, but
+ * in order to support 32bit archs we need store 64bit values
+ * indirectly, since they don't fit in a pointer. */
+void uint64_hash_func(const void *p, struct siphash *state);
+int uint64_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops uint64_hash_ops;
+
+/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
+ * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
+#if SIZEOF_DEV_T != 8
+void devt_hash_func(const void *p, struct siphash *state) _pure_;
+int devt_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops devt_hash_ops = {
+        .hash = devt_hash_func,
+        .compare = devt_compare_func
+};
+#else
+#define devt_hash_func uint64_hash_func
+#define devt_compare_func uint64_compare_func
+#define devt_hash_ops uint64_hash_ops
+#endif
index 6e501ef6ff43185145c22585f7a3ebbfd6fe6ce4..6f1a049d47041632307c8494bdddc712086a7924 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,8 +19,9 @@
 ***/
 
 #include <errno.h>
-#include <pthread.h>
+#include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "alloc-util.h"
 #include "hashmap.h"
@@ -36,6 +35,7 @@
 #include "util.h"
 
 #ifdef ENABLE_DEBUG_HASHMAP
+#include <pthread.h>
 #include "list.h"
 #endif
 
@@ -278,66 +278,6 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
         },
 };
 
-void string_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, strlen(p) + 1, state);
-}
-
-int string_compare_func(const void *a, const void *b) {
-        return strcmp(a, b);
-}
-
-const struct hash_ops string_hash_ops = {
-        .hash = string_hash_func,
-        .compare = string_compare_func
-};
-
-void trivial_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(&p, sizeof(p), state);
-}
-
-int trivial_compare_func(const void *a, const void *b) {
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops trivial_hash_ops = {
-        .hash = trivial_hash_func,
-        .compare = trivial_compare_func
-};
-
-void uint64_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, sizeof(uint64_t), state);
-}
-
-int uint64_compare_func(const void *_a, const void *_b) {
-        uint64_t a, b;
-        a = *(const uint64_t*) _a;
-        b = *(const uint64_t*) _b;
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops uint64_hash_ops = {
-        .hash = uint64_hash_func,
-        .compare = uint64_compare_func
-};
-
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) {
-        siphash24_compress(p, sizeof(dev_t), state);
-}
-
-int devt_compare_func(const void *_a, const void *_b) {
-        dev_t a, b;
-        a = *(const dev_t*) _a;
-        b = *(const dev_t*) _b;
-        return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops devt_hash_ops = {
-        .hash = devt_hash_func,
-        .compare = devt_compare_func
-};
-#endif
-
 static unsigned n_buckets(HashmapBase *h) {
         return h->has_indirect ? h->indirect.n_buckets
                                : hashmap_type_info[h->type].n_direct_buckets;
index ed6a092d82360cb10231736f5ddd87d6083aa99d..6d1ae48b213b76fbe4da1b4c01fc5ebb3d8e13e9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <limits.h>
 #include <stdbool.h>
+#include <stddef.h>
 
+#include "hash-funcs.h"
 #include "macro.h"
-#include "siphash24.h"
 #include "util.h"
 
 /*
@@ -68,47 +68,6 @@ typedef struct {
 #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
 #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
 
-typedef void (*hash_func_t)(const void *p, struct siphash *state);
-typedef int (*compare_func_t)(const void *a, const void *b);
-
-struct hash_ops {
-        hash_func_t hash;
-        compare_func_t compare;
-};
-
-void string_hash_func(const void *p, struct siphash *state);
-int string_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops string_hash_ops;
-
-/* This will compare the passed pointers directly, and will not
- * dereference them. This is hence not useful for strings or
- * suchlike. */
-void trivial_hash_func(const void *p, struct siphash *state);
-int trivial_compare_func(const void *a, const void *b) _const_;
-extern const struct hash_ops trivial_hash_ops;
-
-/* 32bit values we can always just embedd in the pointer itself, but
- * in order to support 32bit archs we need store 64bit values
- * indirectly, since they don't fit in a pointer. */
-void uint64_hash_func(const void *p, struct siphash *state);
-int uint64_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops uint64_hash_ops;
-
-/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
- * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) _pure_;
-int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
-        .hash = devt_hash_func,
-        .compare = devt_compare_func
-};
-#else
-#define devt_hash_func uint64_hash_func
-#define devt_compare_func uint64_compare_func
-#define devt_hash_ops uint64_hash_ops
-#endif
-
 /* Macros for type checking */
 #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
         (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
index 4eb566b15aadd0d5d9a2f6a6eee2fb6bed73c662..592df53cb56b9cee5e111c31ff0b7ad9092bc92d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <ctype.h>
-#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
 
 #include "alloc-util.h"
 #include "hexdecoct.h"
-#include "util.h"
+#include "macro.h"
 
 char octchar(int x) {
         return '0' + (x & 7);
@@ -512,14 +512,14 @@ int unbase64char(char c) {
         return -EINVAL;
 }
 
-char *base64mem(const void *p, size_t l) {
+ssize_t base64mem(const void *p, size_t l, char **out) {
         char *r, *z;
         const uint8_t *x;
 
         /* three input bytes makes four output bytes, padding is added so we must round up */
         z = r = malloc(4 * (l + 2) / 3 + 1);
         if (!r)
-                return NULL;
+                return -ENOMEM;
 
         for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
@@ -547,9 +547,64 @@ char *base64mem(const void *p, size_t l) {
         }
 
         *z = 0;
-        return r;
+        *out = r;
+        return z - r;
 }
 
+static int base64_append_width(char **prefix, int plen,
+                               const char *sep, int indent,
+                               const void *p, size_t l,
+                               int width) {
+
+        _cleanup_free_ char *x = NULL;
+        char *t, *s;
+        ssize_t slen, len, avail;
+        int line, lines;
+
+        len = base64mem(p, l, &x);
+        if (len <= 0)
+                return len;
+
+        lines = (len + width - 1) / width;
+
+        slen = sep ? strlen(sep) : 0;
+        t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
+        if (!t)
+                return -ENOMEM;
+
+        memcpy(t + plen, sep, slen);
+
+        for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
+                int act = MIN(width, avail);
+
+                if (line > 0 || sep) {
+                        memset(s, ' ', indent);
+                        s += indent;
+                }
+
+                memcpy(s, x + width * line, act);
+                s += act;
+                *(s++) = line < lines - 1 ? '\n' : '\0';
+                avail -= act;
+        }
+        assert(avail == 0);
+
+        *prefix = t;
+        return 0;
+}
+
+int base64_append(char **prefix, int plen,
+                  const void *p, size_t l,
+                  int indent, int width) {
+        if (plen > width / 2 || plen + indent > width)
+                /* leave indent on the left, keep last column free */
+                return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
+        else
+                /* leave plen on the left, keep last column free */
+                return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
+};
+
+
 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
         _cleanup_free_ uint8_t *r = NULL;
         int a, b, c, d;
index 4aeb4c3bdcb0672d2533d93cd3d4d582cc33b7db..1ba2f69ebd307bacb1e2ae4e6785e8e4d0915cfd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <sys/types.h>
 
@@ -48,7 +47,10 @@ int unbase64char(char c) _const_;
 char *base32hexmem(const void *p, size_t l, bool padding);
 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
 
-char *base64mem(const void *p, size_t l);
+ssize_t base64mem(const void *p, size_t l, char **out);
+int base64_append(char **prefix, int plen,
+                  const void *p, size_t l,
+                  int margin, int width);
 int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
 
 void hexdump(FILE *f, const void *p, size_t s);
index ea0528c6fcbd19dafbfcdd7d1b687151366c2199..7bb23448ed5298316a1319d17a15a195799f5966 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <ctype.h>
+#include <bits/local_lim.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
 #include <sys/utsname.h>
+#include <unistd.h>
 
 #include "fd-util.h"
 #include "fileio.h"
 #include "hostname-util.h"
+#include "macro.h"
 #include "string-util.h"
-#include "util.h"
 
 bool hostname_is_set(void) {
         struct utsname u;
@@ -72,7 +75,7 @@ static bool hostname_valid_char(char c) {
  * allow_trailing_dot is true and at least two components are present
  * in the name. Note that due to the restricted charset and length
  * this call is substantially more conservative than
- * dns_domain_is_valid().
+ * dns_name_is_valid().
  */
 bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
         unsigned n_dots = 0;
index d4f5bfe45ec41ebdc357caff073309d0812426bd..d062eddea19f6f5a5ddcea639da72e83795edc4c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f4e24121e7b80b8a0c49e1df2f81a2f45ea9dcc7..245107ebb8458c02c652e6e78d8b609f44a25086 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <arpa/inet.h>
+#include <endian.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
 
 #include "alloc-util.h"
 #include "in-addr-util.h"
+#include "macro.h"
+#include "util.h"
 
 int in_addr_is_null(int family, const union in_addr_union *u) {
         assert(u);
@@ -44,7 +48,7 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
         assert(u);
 
         if (family == AF_INET)
-                return (be32toh(u->in.s_addr) & 0xFFFF0000) == (169U << 24 | 254U << 16);
+                return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
 
         if (family == AF_INET6)
                 return IN6_IS_ADDR_LINKLOCAL(&u->in6);
@@ -52,6 +56,19 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
         return -EAFNOSUPPORT;
 }
 
+int in_addr_is_localhost(int family, const union in_addr_union *u) {
+        assert(u);
+
+        if (family == AF_INET)
+                /* All of 127.x.x.x is localhost. */
+                return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
+
+        if (family == AF_INET6)
+                return IN6_IS_ADDR_LOOPBACK(&u->in6);
+
+        return -EAFNOSUPPORT;
+}
+
 int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
         assert(a);
         assert(b);
@@ -200,7 +217,7 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
         errno = 0;
         if (!inet_ntop(family, u, x, l)) {
                 free(x);
-                return errno ? -errno : -EINVAL;
+                return errno > 0 ? -errno : -EINVAL;
         }
 
         *ret = x;
@@ -217,7 +234,7 @@ int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
 
         errno = 0;
         if (inet_pton(family, s, ret) <= 0)
-                return errno ? -errno : -EINVAL;
+                return errno > 0 ? -errno : -EINVAL;
 
         return 0;
 }
index 51af08868cda48af0db4681613a5be4b853234ac..17798ce8169fc8cd35f3b170a5fa9fc148c98ab3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,8 @@
 ***/
 
 #include <netinet/in.h>
+#include <stddef.h>
+#include <sys/socket.h>
 
 #include "macro.h"
 #include "util.h"
@@ -31,8 +31,14 @@ union in_addr_union {
         struct in6_addr in6;
 };
 
+struct in_addr_data {
+        int family;
+        union in_addr_union address;
+};
+
 int in_addr_is_null(int family, const union in_addr_union *u);
 int in_addr_is_link_local(int family, const union in_addr_union *u);
+int in_addr_is_localhost(int family, const union in_addr_union *u);
 int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
 int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
 int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
index ac8f93ff57a9b52a2775bfd57949e2208b4d2b8f..3ec8d61236922cb036ed30c7550c893ba7c0f586 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <limits.h>
 #include <poll.h>
+#include <stdio.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "io-util.h"
+#include "time-util.h"
 
 int flush_fd(int fd) {
         struct pollfd pollfd = {
index cd2aa75ad2c6859cde3a9b8f2a58fca1acb4cb6e..142c940d92692f6a2257aeba0f5786f039e483d2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 
+#include "macro.h"
 #include "time-util.h"
 
 int flush_fd(int fd);
@@ -74,3 +75,21 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
 
         return k;
 }
+
+static inline bool FILE_SIZE_VALID(uint64_t l) {
+        /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than
+         * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */
+
+        return (l >> 63) == 0;
+}
+
+static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
+
+        /* Same as above, but allows one extra value: -1 as indication for infinity. */
+
+        if (l == (uint64_t) -1)
+                return true;
+
+        return FILE_SIZE_VALID(l);
+
+}
index e5c71d0043249cff9bd8c8bdc95eba5758e0ccea..d8bb6eb4971b1332e2ba378e7beb20e21d475a05 100644 (file)
@@ -4,8 +4,8 @@
 /* This is minimal version of Linux' linux/ioprio.h header file, which
  * is licensed GPL2 */
 
-#include <unistd.h>
 #include <sys/syscall.h>
+#include <unistd.h>
 
 /*
  * Gives us 8 prio classes with 13-bits of data for each class
index 9d5dedb934c79c4dc4162dc7a719486fa6026a37..daa98fc815a870cdc5a30b7ab15f46b07e2ca925 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <math.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 
 #include "alloc-util.h"
@@ -319,7 +320,7 @@ static int json_parse_string(const char **p, char **ret) {
                         else if (*c == 't')
                                 ch = '\t';
                         else if (*c == 'u') {
-                                uint16_t x;
+                                char16_t x;
                                 int r;
 
                                 r = unhex_ucs2(c + 1, &x);
@@ -332,11 +333,11 @@ static int json_parse_string(const char **p, char **ret) {
                                         return -ENOMEM;
 
                                 if (!utf16_is_surrogate(x))
-                                        n += utf8_encode_unichar(s + n, x);
+                                        n += utf8_encode_unichar(s + n, (char32_t) x);
                                 else if (utf16_is_trailing_surrogate(x))
                                         return -EINVAL;
                                 else {
-                                        uint16_t y;
+                                        char16_t y;
 
                                         if (c[0] != '\\' || c[1] != 'u')
                                                 return -EINVAL;
index e0b4d810b5b370fa21ada8d4e10e71868e3f6f10..a4509f680fe026811e3c8c39976b821afc76a661 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "macro.h"
 #include "util.h"
 
 enum {
index f33502f90f29730f9667a37d8d37e907aaadf593..f5ab855d32709e4861261f731e540f6cfbf8d2da 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include "label.h"
+#include "macro.h"
 #include "selinux-util.h"
 #include "smack-util.h"
-#include "util.h"
 
 int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
         int r, q;
index 8070bcb021af7e000eb86dfc0827ac7427951814..3e9251aa710b952d8ea168cd6496f86f59e32245 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 760abcdab3bd087ca40f5cd5d055f5f687c60ac9..c68185f5878eaad93d4abba7bb9a1a6107d424cd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index b87fd7670bf410a58aa1bff5a2805821e37e1026..cda6b2895d6497dc237aba91001c8e74f88458d4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <langinfo.h>
+#include <libintl.h>
 #include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
 
 #include "dirent-util.h"
 #include "fd-util.h"
+#include "hashmap.h"
 #include "locale-util.h"
 #include "path-util.h"
 #include "set.h"
@@ -32,7 +40,6 @@
 #include "string-util.h"
 #include "strv.h"
 #include "utf8.h"
-#include "util.h"
 
 static int add_locales_from_archive(Set *locales) {
         /* Stolen from glibc... */
index c71d145139d06fc75866cd7179e3c983bb38b100..b0f9679286c580c0eab994b2ae6040c7ffa5a524 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0bdbae480b1c9e9902c621fb23157bd203d2c2e8..3ee4191e4dce374659d4c0a9df175b9546a803eb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
+#include <fcntl.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <sys/file.h>
+#include <sys/stat.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
-#include "fileio.h"
 #include "fs-util.h"
 #include "lockfile-util.h"
+#include "macro.h"
 #include "path-util.h"
-#include "util.h"
 
 int make_lock_file(const char *p, int operation, LockFile *ret) {
         _cleanup_close_ int fd = -1;
index 38d47094bd5179c3437cffbae5d4b6d96108327e..22491ee8e1b808679234372e4b71879b6951bf11 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
+
 #include "macro.h"
 #include "missing.h"
 
index fe29cacd9e3e6a0498aabd1279cc2659464bf26d..d89e6f72747a3ecf0754b784c9abbf9196f6fe9f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <errno.h>
 #include <fcntl.h>
-#include <printf.h>
+#include <inttypes.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <string.h>
+#include <sys/signalfd.h>
 #include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
 #include <sys/un.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "sd-messages.h"
@@ -48,6 +52,7 @@
 #include "string-util.h"
 #include "syslog-util.h"
 #include "terminal-util.h"
+#include "time-util.h"
 #include "util.h"
 
 #define SNDBUF_SIZE (8*1024*1024)
@@ -345,7 +350,7 @@ static int write_to_console(
         highlight = LOG_PRI(level) <= LOG_ERR && show_color;
 
         if (show_location) {
-                snprintf(location, sizeof(location), "(%s:%i) ", file, line);
+                xsprintf(location, "(%s:%i) ", file, line);
                 IOVEC_SET_STRING(iovec[n++], location);
         }
 
@@ -770,7 +775,7 @@ static void log_assert(
                 return;
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
-        snprintf(buffer, sizeof(buffer), format, text, file, line, func);
+        xsprintf(buffer, format, text, file, line, func);
         REENABLE_WARNING;
 
         log_abort_msg = buffer;
@@ -798,6 +803,52 @@ int log_oom_internal(const char *file, int line, const char *func) {
         return -ENOMEM;
 }
 
+int log_format_iovec(
+                struct iovec *iovec,
+                unsigned iovec_len,
+                unsigned *n,
+                bool newline_separator,
+                int error,
+                const char *format,
+                va_list ap) {
+
+        static const char nl = '\n';
+
+        while (format && *n + 1 < iovec_len) {
+                va_list aq;
+                char *m;
+                int r;
+
+                /* We need to copy the va_list structure,
+                 * since vasprintf() leaves it afterwards at
+                 * an undefined location */
+
+                if (error != 0)
+                        errno = error;
+
+                va_copy(aq, ap);
+                r = vasprintf(&m, format, aq);
+                va_end(aq);
+                if (r < 0)
+                        return -EINVAL;
+
+                /* Now, jump enough ahead, so that we point to
+                 * the next format string */
+                VA_FORMAT_ADVANCE(format, ap);
+
+                IOVEC_SET_STRING(iovec[(*n)++], m);
+
+                if (newline_separator) {
+                        iovec[*n].iov_base = (char*) &nl;
+                        iovec[*n].iov_len = 1;
+                        (*n)++;
+                }
+
+                format = va_arg(ap, char *);
+        }
+        return 0;
+}
+
 int log_struct_internal(
                 int level,
                 int error,
@@ -830,10 +881,10 @@ int log_struct_internal(
                 char header[LINE_MAX];
                 struct iovec iovec[17] = {};
                 unsigned n = 0, i;
+                int r;
                 struct msghdr mh = {
                         .msg_iov = iovec,
                 };
-                static const char nl = '\n';
                 bool fallback = false;
 
                 /* If the journal is available do structured logging */
@@ -841,43 +892,14 @@ int log_struct_internal(
                 IOVEC_SET_STRING(iovec[n++], header);
 
                 va_start(ap, format);
-                while (format && n + 1 < ELEMENTSOF(iovec)) {
-                        va_list aq;
-                        char *m;
-
-                        /* We need to copy the va_list structure,
-                         * since vasprintf() leaves it afterwards at
-                         * an undefined location */
-
-                        if (error != 0)
-                                errno = error;
-
-                        va_copy(aq, ap);
-                        if (vasprintf(&m, format, aq) < 0) {
-                                va_end(aq);
-                                fallback = true;
-                                goto finish;
-                        }
-                        va_end(aq);
-
-                        /* Now, jump enough ahead, so that we point to
-                         * the next format string */
-                        VA_FORMAT_ADVANCE(format, ap);
-
-                        IOVEC_SET_STRING(iovec[n++], m);
-
-                        iovec[n].iov_base = (char*) &nl;
-                        iovec[n].iov_len = 1;
-                        n++;
-
-                        format = va_arg(ap, char *);
+                r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
+                if (r < 0)
+                        fallback = true;
+                else {
+                        mh.msg_iovlen = n;
+                        (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
                 }
 
-                mh.msg_iovlen = n;
-
-                (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
-
-        finish:
                 va_end(ap);
                 for (i = 1; i < n; i += 2)
                         free(iovec[i].iov_base);
index cda1e45cc8d3cd491459def4795292c491e1f0e5..60ddead74cfad0082c2759fb80d259f6f5c8a56f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -26,6 +24,7 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <sys/signalfd.h>
+#include <sys/socket.h>
 #include <syslog.h>
 
 #include "sd-id128.h"
@@ -127,6 +126,15 @@ int log_oom_internal(
                 int line,
                 const char *func);
 
+int log_format_iovec(
+                struct iovec *iovec,
+                unsigned iovec_len,
+                unsigned *n,
+                bool newline_separator,
+                int error,
+                const char *format,
+                va_list ap);
+
 /* This modifies the buffer passed! */
 int log_dump_internal(
                 int level,
index 41cef14e73bba42684e1130f71213f23c914c1eb..339e94f12d88f77d6a9d7b8633552db59bd18f80 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -19,7 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "def.h"
+#include <string.h>
+
 #include "login-util.h"
 #include "string-util.h"
 
index be5bb648700febd04d84c4ceac281691ff299389..89a337d7c1fc1c39c9745268169628b3dcc032ea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5088e6720d8640e8e13c1d58e7c74a1da7ff9423..2695d0edb75ba436e645fc1f32786dde78e22bbd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -320,18 +318,47 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
 #define SET_FLAG(v, flag, b) \
         (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
 
-#define IN_SET(x, y, ...)                                               \
-        ({                                                              \
-                static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \
-                const typeof(y) _x = (x);                               \
-                unsigned _i;                                            \
-                bool _found = false;                                    \
-                for (_i = 0; _i < ELEMENTSOF(_array); _i++)             \
-                        if (_array[_i] == _x) {                         \
-                                _found = true;                          \
-                                break;                                  \
-                        }                                               \
-                _found;                                                 \
+#define CASE_F(X) case X:
+#define CASE_F_1(CASE, X) CASE_F(X)
+#define CASE_F_2(CASE, X, ...)  CASE(X) CASE_F_1(CASE, __VA_ARGS__)
+#define CASE_F_3(CASE, X, ...)  CASE(X) CASE_F_2(CASE, __VA_ARGS__)
+#define CASE_F_4(CASE, X, ...)  CASE(X) CASE_F_3(CASE, __VA_ARGS__)
+#define CASE_F_5(CASE, X, ...)  CASE(X) CASE_F_4(CASE, __VA_ARGS__)
+#define CASE_F_6(CASE, X, ...)  CASE(X) CASE_F_5(CASE, __VA_ARGS__)
+#define CASE_F_7(CASE, X, ...)  CASE(X) CASE_F_6(CASE, __VA_ARGS__)
+#define CASE_F_8(CASE, X, ...)  CASE(X) CASE_F_7(CASE, __VA_ARGS__)
+#define CASE_F_9(CASE, X, ...)  CASE(X) CASE_F_8(CASE, __VA_ARGS__)
+#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
+#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
+#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
+#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
+#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
+#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
+#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
+#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
+#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
+#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
+#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
+
+#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
+#define FOR_EACH_MAKE_CASE(...) \
+        GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
+                               CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
+                   (CASE_F,__VA_ARGS__)
+
+#define IN_SET(x, ...)                          \
+        ({                                      \
+                bool _found = false;            \
+                /* If the build breaks in the line below, you need to extend the case macros */ \
+                static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
+                switch(x) {                     \
+                FOR_EACH_MAKE_CASE(__VA_ARGS__) \
+                        _found = true;          \
+                        break;                  \
+                default:                        \
+                        break;                  \
+                }                               \
+                _found;                         \
         })
 
 /* Define C11 thread_local attribute even on older gcc compiler
index 92630f6b2591b5e226599f73f35270ef7184bd31..8c8cc78ebf9bcac2b15cbaffe86a34e4bd400376 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #ifdef HAVE_LINUX_MEMFD_H
 #include <linux/memfd.h>
 #endif
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "macro.h"
 #include "memfd-util.h"
 #include "missing.h"
 #include "string-util.h"
 #include "utf8.h"
-#include "util.h"
 
 int memfd_new(const char *name) {
         _cleanup_free_ char *g = NULL;
index 2cb404ea811099f1cdc05b5d15be44a8032aecac..46d4989e4c612e1d2b271317c0e24a6a9dcfc6e7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
 
 int memfd_new(const char *name);
 int memfd_new_and_map(const char *name, size_t sz, void **p);
index 9ee6e6a76d622b36281208b9f4ae8fd9024a4516..f95e2beb0ffd46ef08f0bc5b227e419947a2737c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -20,6 +18,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdint.h>
+#include <stdlib.h>
+
 #include "macro.h"
 #include "mempool.h"
 #include "util.h"
index 42f473bee10e0291bbef952be2abfb079ed8c117..fea7841bcff8ebe0fd097f6869bfaf59088b39db 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d539ed00e4065e576ac67bc565df97c064580013..36b060496a7b9e412a3f7211c2ff6c085b76c2a2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -36,6 +34,7 @@
 #include <stdlib.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
+#include <uchar.h>
 #include <unistd.h>
 
 #ifdef HAVE_AUDIT
 #define NETLINK_LIST_MEMBERSHIPS 9
 #endif
 
+#ifndef SOL_SCTP
+#define SOL_SCTP 132
+#endif
+
 #if !HAVE_DECL_PIVOT_ROOT
 static inline int pivot_root(const char *new_root, const char *put_old) {
         return syscall(SYS_pivot_root, new_root, put_old);
@@ -970,6 +973,10 @@ static inline int setns(int fd, int nstype) {
 #define IFA_FLAGS 8
 #endif
 
+#ifndef IFA_F_MANAGETEMPADDR
+#define IFA_F_MANAGETEMPADDR 0x100
+#endif
+
 #ifndef IFA_F_NOPREFIXROUTE
 #define IFA_F_NOPREFIXROUTE 0x200
 #endif
@@ -1125,3 +1132,39 @@ static inline key_serial_t request_key(const char *type, const char *description
 #ifndef KEY_SPEC_USER_KEYRING
 #define KEY_SPEC_USER_KEYRING -4
 #endif
+
+#ifndef PR_CAP_AMBIENT
+#define PR_CAP_AMBIENT 47
+#endif
+
+#ifndef PR_CAP_AMBIENT_IS_SET
+#define PR_CAP_AMBIENT_IS_SET 1
+#endif
+
+#ifndef PR_CAP_AMBIENT_RAISE
+#define PR_CAP_AMBIENT_RAISE 2
+#endif
+
+#ifndef PR_CAP_AMBIENT_CLEAR_ALL
+#define PR_CAP_AMBIENT_CLEAR_ALL 4
+#endif
+
+/* The following two defines are actually available in the kernel headers for longer, but we define them here anyway,
+ * since that makes it easier to use them in conjunction with the glibc net/if.h header which conflicts with
+ * linux/if.h. */
+#ifndef IF_OPER_UNKNOWN
+#define IF_OPER_UNKNOWN 0
+#endif
+
+#ifndef IF_OPER_UP
+#define IF_OPER_UP 6
+
+#ifndef HAVE_DECL_CHAR32_T
+#define char32_t uint32_t
+#endif
+
+#ifndef HAVE_DECL_CHAR16_T
+#define char16_t uint16_t
+#endif
+
+#endif
index c241ef6064e74e1a3d8eecf18bf3ebe8def54e2e..aa6878cdf07fa8fff520124a61c98bb0ded4ee07 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,6 +19,7 @@
 ***/
 
 #include <stdio.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include "label.h"
index 5d7fb9a12d9721031fd49ad99fed940b16e07315..6b1a98402ce18bb284335ea614aa007af6f75d4b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <stdbool.h>
 #include <string.h>
+#include <sys/stat.h>
 
 #include "fs-util.h"
+#include "macro.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "stat-util.h"
 #include "user-util.h"
-#include "util.h"
 
 int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
         struct stat st;
index 2392d1fd1b39fe4e05589a0822802195dfb4a46a..d564a3547f67f16332b598abe05293ccada505ee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 29997b1ce7414b5f77dc337324f51bc6f0abaca8..33f2ee96d8f9badf7e79a5db2482f0fd85a9a6dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/mount.h>
+#include <sys/stat.h>
 #include <sys/statvfs.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "hashmap.h"
 #include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "set.h"
 #include "stdio-util.h"
 #include "string-util.h"
-#include "util.h"
 
 static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
         char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
index 48954c2d67710c677eaa6ef20cc0fc14313c419b..bdb525d6b0aaa6011695047c6a957304416b0c55 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <fcntl.h>
 #include <mntent.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include "macro.h"
 #include "missing.h"
 
 int fd_is_mount_point(int fd, const char *filename, int flags);
diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h
new file mode 100644 (file)
index 0000000..df565a3
--- /dev/null
@@ -0,0 +1,156 @@
+#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 <grp.h>
+#include <netdb.h>
+#include <nss.h>
+#include <pwd.h>
+#include <resolv.h>
+
+#define NSS_SIGNALS_BLOCK SIGALRM,SIGVTALRM,SIGPIPE,SIGCHLD,SIGTSTP,SIGIO,SIGHUP,SIGUSR1,SIGUSR2,SIGPROF,SIGURG,SIGWINCH
+
+#define NSS_GETHOSTBYNAME_PROTOTYPES(module)            \
+enum nss_status _nss_##module##_gethostbyname4_r(       \
+                const char *name,                       \
+                struct gaih_addrtuple **pat,            \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop,             \
+                int32_t *ttlp) _public_;                \
+enum nss_status _nss_##module##_gethostbyname3_r(       \
+                const char *name,                       \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop,             \
+                int32_t *ttlp,                          \
+                char **canonp) _public_;                \
+enum nss_status _nss_##module##_gethostbyname2_r(       \
+                const char *name,                       \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) _public_;   \
+enum nss_status _nss_##module##_gethostbyname_r(        \
+                const char *name,                       \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) _public_
+
+#define NSS_GETHOSTBYADDR_PROTOTYPES(module)            \
+enum nss_status _nss_##module##_gethostbyaddr2_r(       \
+                const void* addr, socklen_t len,        \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop,             \
+                int32_t *ttlp) _public_;                \
+enum nss_status _nss_##module##_gethostbyaddr_r(        \
+                const void* addr, socklen_t len,        \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) _public_
+
+#define NSS_GETHOSTBYNAME_FALLBACKS(module)             \
+enum nss_status _nss_##module##_gethostbyname2_r(       \
+                const char *name,                       \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) {           \
+        return _nss_##module##_gethostbyname3_r(        \
+                        name,                           \
+                        af,                             \
+                        host,                           \
+                        buffer, buflen,                 \
+                        errnop, h_errnop,               \
+                        NULL,                           \
+                        NULL);                          \
+}                                                       \
+enum nss_status _nss_##module##_gethostbyname_r(        \
+                const char *name,                       \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) {           \
+        enum nss_status ret = NSS_STATUS_NOTFOUND;      \
+                                                        \
+        if (_res.options & RES_USE_INET6)               \
+                ret = _nss_##module##_gethostbyname3_r( \
+                        name,                           \
+                        AF_INET6,                       \
+                        host,                           \
+                        buffer, buflen,                 \
+                        errnop, h_errnop,               \
+                        NULL,                           \
+                        NULL);                          \
+        if (ret == NSS_STATUS_NOTFOUND)                 \
+                ret = _nss_##module##_gethostbyname3_r( \
+                        name,                           \
+                        AF_INET,                        \
+                        host,                           \
+                        buffer, buflen,                 \
+                        errnop, h_errnop,               \
+                        NULL,                           \
+                        NULL);                          \
+       return ret;                                      \
+}                                                       \
+struct __useless_struct_to_allow_trailing_semicolon__
+
+#define NSS_GETHOSTBYADDR_FALLBACKS(module)             \
+enum nss_status _nss_##module##_gethostbyaddr_r(        \
+                const void* addr, socklen_t len,        \
+                int af,                                 \
+                struct hostent *host,                   \
+                char *buffer, size_t buflen,            \
+                int *errnop, int *h_errnop) {           \
+        return _nss_##module##_gethostbyaddr2_r(        \
+                        addr, len,                      \
+                        af,                             \
+                        host,                           \
+                        buffer, buflen,                 \
+                        errnop, h_errnop,               \
+                        NULL);                          \
+}                                                       \
+struct __useless_struct_to_allow_trailing_semicolon__
+
+#define NSS_GETPW_PROTOTYPES(module)                    \
+enum nss_status _nss_##module##_getpwnam_r(             \
+                const char *name,                       \
+                struct passwd *pwd,                     \
+                char *buffer, size_t buflen,            \
+                int *errnop) _public_;                  \
+enum nss_status _nss_mymachines_getpwuid_r(             \
+                uid_t uid,                              \
+                struct passwd *pwd,                     \
+                char *buffer, size_t buflen,            \
+                int *errnop) _public_
+
+#define NSS_GETGR_PROTOTYPES(module)                    \
+enum nss_status _nss_##module##_getgrnam_r(             \
+                const char *name,                       \
+                struct group *gr,                       \
+                char *buffer, size_t buflen,            \
+                int *errnop) _public_;                  \
+enum nss_status _nss_##module##_getgrgid_r(             \
+                gid_t gid,                              \
+                struct group *gr,                       \
+                char *buffer, size_t buflen,            \
+                int *errnop) _public_
diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
new file mode 100644 (file)
index 0000000..2e0bdf6
--- /dev/null
@@ -0,0 +1,64 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "ordered-set.h"
+#include "strv.h"
+
+int ordered_set_consume(OrderedSet *s, void *p) {
+        int r;
+
+        r = ordered_set_put(s, p);
+        if (r <= 0)
+                free(p);
+
+        return r;
+}
+
+int ordered_set_put_strdup(OrderedSet *s, const char *p) {
+        char *c;
+        int r;
+
+        assert(s);
+        assert(p);
+
+        c = strdup(p);
+        if (!c)
+                return -ENOMEM;
+
+        r = ordered_set_consume(s, c);
+        if (r == -EEXIST)
+                return 0;
+
+        return r;
+}
+
+int ordered_set_put_strdupv(OrderedSet *s, char **l) {
+        int n = 0, r;
+        char **i;
+
+        STRV_FOREACH(i, l) {
+                r = ordered_set_put_strdup(s, *i);
+                if (r < 0)
+                        return r;
+
+                n += r;
+        }
+
+        return n;
+}
index 6c617ab3055eb02607a852c5f51e0a9b112ace64..e1dfc863809f38cb601dad0a35c6010ed6268f72 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -29,6 +27,17 @@ static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) {
         return (OrderedSet*) ordered_hashmap_new(ops);
 }
 
+static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) {
+        if (*s)
+                return 0;
+
+        *s = ordered_set_new(ops);
+        if (!*s)
+                return -ENOMEM;
+
+        return 0;
+}
+
 static inline OrderedSet* ordered_set_free(OrderedSet *s) {
         ordered_hashmap_free((OrderedHashmap*) s);
         return NULL;
@@ -51,9 +60,15 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value)
         return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
 }
 
+int ordered_set_consume(OrderedSet *s, void *p);
+int ordered_set_put_strdup(OrderedSet *s, const char *p);
+int ordered_set_put_strdupv(OrderedSet *s, char **l);
+
 #define ORDERED_SET_FOREACH(e, s, i)                                    \
         for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
 
 #define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep)
+#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep)
index 151067e91604d3a15d22184850213363af7a157f..a3cb81b040f09a5c29304821ca845dd09e70d44e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xlocale.h>
+
 #include "alloc-util.h"
 #include "extract-word.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "string-util.h"
-#include "util.h"
 
 int parse_boolean(const char *v) {
         assert(v);
@@ -73,7 +79,7 @@ int parse_mode(const char *s, mode_t *ret) {
 
         errno = 0;
         l = strtol(s, &x, 8);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -168,7 +174,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
 
                 errno = 0;
                 l = strtoull(p, &e, 10);
-                if (errno != 0)
+                if (errno > 0)
                         return -errno;
                 if (e == p)
                         return -EINVAL;
@@ -184,7 +190,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
                                 char *e2;
 
                                 l2 = strtoull(e, &e2, 10);
-                                if (errno != 0)
+                                if (errno > 0)
                                         return -errno;
 
                                 /* Ignore failure. E.g. 10.M is valid */
@@ -322,7 +328,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -344,7 +350,7 @@ int safe_atoi(const char *s, int *ret_i) {
 
         errno = 0;
         l = strtol(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -366,7 +372,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
 
         errno = 0;
         l = strtoull(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -386,7 +392,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
 
         errno = 0;
         l = strtoll(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -406,7 +412,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -430,7 +436,7 @@ int safe_atou16(const char *s, uint16_t *ret) {
 
         errno = 0;
         l = strtoul(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -452,7 +458,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
 
         errno = 0;
         l = strtol(s, &x, 0);
-        if (errno != 0)
+        if (errno > 0)
                 return -errno;
         if (!x || x == s || *x)
                 return -EINVAL;
@@ -477,7 +483,7 @@ int safe_atod(const char *s, double *ret_d) {
 
         errno = 0;
         d = strtod_l(s, &x, loc);
-        if (errno != 0) {
+        if (errno > 0) {
                 freelocale(loc);
                 return -errno;
         }
@@ -490,3 +496,39 @@ int safe_atod(const char *s, double *ret_d) {
         *ret_d = (double) d;
         return 0;
 }
+
+int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
+        size_t i;
+        unsigned val = 0;
+        const char *s;
+
+        s = *p;
+
+        /* accept any number of digits, strtoull is limted to 19 */
+        for(i=0; i < digits; i++,s++) {
+                if (*s < '0' || *s > '9') {
+                        if (i == 0)
+                                return -EINVAL;
+
+                        /* too few digits, pad with 0 */
+                        for (; i < digits; i++)
+                                val *= 10;
+
+                        break;
+                }
+
+                val *= 10;
+                val += *s - '0';
+        }
+
+        /* maybe round up */
+        if (*s >= '5' && *s <= '9')
+                val++;
+
+        s += strspn(s, DIGITS);
+
+        *p = s;
+        *res = val;
+
+        return 0;
+}
index 408690d0b3ac0bd2bbb6140c3ba00c9106a03f05..d8dc26a36e97625804cdf926d00ca5117dc0dc22 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,9 @@
 ***/
 
 #include <inttypes.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include "macro.h"
@@ -90,3 +91,5 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
 #endif
 
 int safe_atod(const char *s, double *ret_d);
+
+int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
index ec90c432a4bdb48d5a906de58adef2f0eb8fc3e2..822c09bfba7ce33a7e49f199a942a057ea3e8289 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
-#include <fcntl.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/statvfs.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 /* When we include libgen.h because we need dirname() we immediately
 #undef basename
 
 #include "alloc-util.h"
-#include "fd-util.h"
-#include "fileio.h"
+#include "extract-word.h"
 #include "fs-util.h"
 #include "log.h"
 #include "macro.h"
 #include "missing.h"
-#include "parse-util.h"
 #include "path-util.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
-#include "util.h"
+#include "time-util.h"
 
 bool path_is_absolute(const char *p) {
         return p[0] == '/';
@@ -104,7 +100,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
 
                 cwd = get_current_dir_name();
                 if (!cwd)
-                        return -errno;
+                        return negative_errno();
 
                 c = strjoin(cwd, "/", p, NULL);
         }
index 989e0f900498324103082dc5962287bd60fcd848..2c2f87a9f28b39275f9c3373f767fe889894f4e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,7 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
 #include <stdbool.h>
+#include <stddef.h>
 
 #include "macro.h"
 #include "time-util.h"
index 75906989114bc4add71ccf8cd602e06b552e4129..d2ec516d297ccaca972cb8d9d85bb36e600c8716 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
  * The underlying algorithm used in this implementation is a Heap.
  */
 
+#include <errno.h>
+#include <stdlib.h>
+
 #include "alloc-util.h"
+#include "hashmap.h"
 #include "prioq.h"
-#include "util.h"
 
 struct prioq_item {
         void *data;
index 1c044b135ce7233e099aee073ce2ade552a7004e..113c73d040e4633368ae4cc91cc67e0a4566ef5a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
 #include "hashmap.h"
+#include "macro.h"
 
 typedef struct Prioq Prioq;
 
index 4464573c5b6f55fdb29e94a89f14f07d42855a85..3505fa9c9aed44832bdaa41616912d9b5a075691 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
 #include "alloc-util.h"
 #include "extract-word.h"
 #include "fileio.h"
index ce6e84995a4e7cda45babbcfe3865dc3cd27fef8..452642a2f5f4c9bf6ded4e0b9422594ff2236410 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7631928d5f11a0ba9c73930412204edacc534c12..189ef9ab604e78081a0ab202254e8b1ac1fe3533 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
+#include <linux/oom.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <syslog.h>
 #include <unistd.h>
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
 
 #include "alloc-util.h"
 #include "escape.h"
 #include "fs-util.h"
 #include "ioprio.h"
 #include "log.h"
+#include "macro.h"
+#include "missing.h"
 #include "process-util.h"
 #include "signal-util.h"
+#include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "user-util.h"
@@ -629,6 +638,17 @@ bool pid_is_alive(pid_t pid) {
         return true;
 }
 
+int pid_from_same_root_fs(pid_t pid) {
+        const char *root;
+
+        if (pid < 0)
+                return 0;
+
+        root = procfs_file_alloca(pid, "root");
+
+        return files_same(root, "/proc/1/root");
+}
+
 bool is_main_thread(void) {
         static thread_local int cached = 0;
 
@@ -725,6 +745,23 @@ const char* personality_to_string(unsigned long p) {
         return NULL;
 }
 
+void valgrind_summary_hack(void) {
+#ifdef HAVE_VALGRIND_VALGRIND_H
+        if (getpid() == 1 && RUNNING_ON_VALGRIND) {
+                pid_t pid;
+                pid = raw_clone(SIGCHLD, NULL);
+                if (pid < 0)
+                        log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
+                else if (pid == 0)
+                        exit(EXIT_SUCCESS);
+                else {
+                        log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
+                        (void) wait_for_terminate(pid, NULL);
+                }
+        }
+#endif
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
index 72633ebf70581ff29ec5d26e5aa3c115cdfb2c6d..f5d193e76215e2c2dd5b6cc6f92d0ecb5e97c1e4 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdbool.h>
-#include <sys/types.h>
 #include <alloca.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <string.h>
-#include <signal.h>
+#include <sys/types.h>
 
 #include "formats-util.h"
 #include "macro.h"
@@ -69,6 +70,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value);
 
 bool pid_is_alive(pid_t pid);
 bool pid_is_unwaited(pid_t pid);
+int pid_from_same_root_fs(pid_t pid);
 
 bool is_main_thread(void);
 
@@ -97,3 +99,5 @@ int sched_policy_from_string(const char *s);
 
 #define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
 #define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
+
+void valgrind_summary_hack(void);
index 2f5c16e2afbdc7fc3230d7111007960ce8e7b996..2f468db770d6d24fd8fa838dc8aa5a195f34d5b1 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/time.h>
 #include <linux/random.h>
 #include <stdint.h>
+
 #ifdef HAVE_SYS_AUXV_H
 #include <sys/auxv.h>
 #endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
 
 #include "fd-util.h"
 #include "io-util.h"
 #include "missing.h"
 #include "random-util.h"
 #include "time-util.h"
-#include "util.h"
 
 int dev_urandom(void *p, size_t n) {
         static int have_syscall = -1;
@@ -94,17 +95,18 @@ void initialize_srand(void) {
         if (srand_called)
                 return;
 
-        x = 0;
-
 #ifdef HAVE_SYS_AUXV_H
-        /* The kernel provides us with a bit 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)
-                x ^= *(unsigned*) auxv;
+        if (auxv) {
+                assert_cc(sizeof(x) < 16);
+                memcpy(&x, auxv, sizeof(x));
+        } else
 #endif
+                x = 0;
+
 
         x ^= (unsigned) now(CLOCK_REALTIME);
         x ^= (unsigned) gettid();
index f7862c8c8b58cd8552743b183c527d7e730a7353..3cee4c501408e5143a485f4c095497d6a3e3b0b0 100644 (file)
@@ -19,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
 #include <stdint.h>
 
 int dev_urandom(void *p, size_t n);
index 81fc9c19ff6c30eff6d1be1c5f9df48fc7a7e90d..3ca5625e4d7c645807cbb70110bf4dc4dcf56547 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -20,6 +18,9 @@
 ***/
 
 
+#include <sys/time.h>
+
+#include "macro.h"
 #include "ratelimit.h"
 
 /* Modelled after Linux' lib/ratelimit.c by Dave Young
index 58efca7df14108884546dc16c69bb9bba5f2ad73..9c8dddf5ad0f7983bdf064111776dc3c85c93916 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
+#include "time-util.h"
 #include "util.h"
 
 typedef struct RateLimit {
index 8a39d69fe4090cd1c49823b79de11be76cc6633e..1d77a6445afa599aed07a61a80066473a90235e4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index bf757cbc48e011ec39da9356111b207700b0b2fb..6a204b9ec349d857300058e2014e56354ec815dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "macro.h"
 #include "replace-var.h"
 #include "string-util.h"
-#include "util.h"
 
 /*
  * Generic infrastructure for replacing @FOO@ style variables in
index 7eaee93a3e1764235ef7c9681b37b85ba0315c41..78412910b2c32d5671028e6c2af735b8da293c8c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 2627c813fc8c8a355d9a253f9dabe49169bbea24..7540b43215a567e22514764e47d58d7430c0cbed 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <sys/resource.h>
+
+#include "alloc-util.h"
+#include "extract-word.h"
+#include "formats-util.h"
+#include "macro.h"
 #include "missing.h"
 #include "rlimit-util.h"
 #include "string-table.h"
-#include "util.h"
+#include "time-util.h"
 
 int setrlimit_closest(int resource, const struct rlimit *rlim) {
         struct rlimit highest, fixed;
@@ -48,6 +53,202 @@ int setrlimit_closest(int resource, const struct rlimit *rlim) {
         return 0;
 }
 
+static int rlimit_parse_u64(const char *val, rlim_t *ret) {
+        uint64_t u;
+        int r;
+
+        assert(val);
+        assert(ret);
+
+        if (streq(val, "infinity")) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
+        assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
+
+        r = safe_atou64(val, &u);
+        if (r < 0)
+                return r;
+        if (u >= (uint64_t) RLIM_INFINITY)
+                return -ERANGE;
+
+        *ret = (rlim_t) u;
+        return 0;
+}
+
+static int rlimit_parse_size(const char *val, rlim_t *ret) {
+        uint64_t u;
+        int r;
+
+        assert(val);
+        assert(ret);
+
+        if (streq(val, "infinity")) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        r = parse_size(val, 1024, &u);
+        if (r < 0)
+                return r;
+        if (u >= (uint64_t) RLIM_INFINITY)
+                return -ERANGE;
+
+        *ret = (rlim_t) u;
+        return 0;
+}
+
+static int rlimit_parse_sec(const char *val, rlim_t *ret) {
+        uint64_t u;
+        usec_t t;
+        int r;
+
+        assert(val);
+        assert(ret);
+
+        if (streq(val, "infinity")) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        r = parse_sec(val, &t);
+        if (r < 0)
+                return r;
+        if (t == USEC_INFINITY) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        u = (uint64_t) DIV_ROUND_UP(t, USEC_PER_SEC);
+        if (u >= (uint64_t) RLIM_INFINITY)
+                return -ERANGE;
+
+        *ret = (rlim_t) u;
+        return 0;
+}
+
+static int rlimit_parse_usec(const char *val, rlim_t *ret) {
+        usec_t t;
+        int r;
+
+        assert(val);
+        assert(ret);
+
+        if (streq(val, "infinity")) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        r = parse_time(val, &t, 1);
+        if (r < 0)
+                return r;
+        if (t == USEC_INFINITY) {
+                *ret = RLIM_INFINITY;
+                return 0;
+        }
+
+        *ret = (rlim_t) t;
+        return 0;
+}
+
+static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = {
+        [RLIMIT_CPU] = rlimit_parse_sec,
+        [RLIMIT_FSIZE] = rlimit_parse_size,
+        [RLIMIT_DATA] = rlimit_parse_size,
+        [RLIMIT_STACK] = rlimit_parse_size,
+        [RLIMIT_CORE] = rlimit_parse_size,
+        [RLIMIT_RSS] = rlimit_parse_size,
+        [RLIMIT_NOFILE] = rlimit_parse_u64,
+        [RLIMIT_AS] = rlimit_parse_size,
+        [RLIMIT_NPROC] = rlimit_parse_u64,
+        [RLIMIT_MEMLOCK] = rlimit_parse_size,
+        [RLIMIT_LOCKS] = rlimit_parse_u64,
+        [RLIMIT_SIGPENDING] = rlimit_parse_u64,
+        [RLIMIT_MSGQUEUE] = rlimit_parse_size,
+        [RLIMIT_NICE] = rlimit_parse_u64,
+        [RLIMIT_RTPRIO] = rlimit_parse_u64,
+        [RLIMIT_RTTIME] = rlimit_parse_usec,
+};
+
+int rlimit_parse_one(int resource, const char *val, rlim_t *ret) {
+        assert(val);
+        assert(ret);
+
+        if (resource < 0)
+                return -EINVAL;
+        if (resource >= _RLIMIT_MAX)
+                return -EINVAL;
+
+        return rlimit_parse_table[resource](val, ret);
+}
+
+int rlimit_parse(int resource, const char *val, struct rlimit *ret) {
+        _cleanup_free_ char *hard = NULL, *soft = NULL;
+        rlim_t hl, sl;
+        int r;
+
+        assert(val);
+        assert(ret);
+
+        r = extract_first_word(&val, &soft, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EINVAL;
+
+        r = rlimit_parse_one(resource, soft, &sl);
+        if (r < 0)
+                return r;
+
+        r = extract_first_word(&val, &hard, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+        if (r < 0)
+                return r;
+        if (!isempty(val))
+                return -EINVAL;
+        if (r == 0)
+                hl = sl;
+        else {
+                r = rlimit_parse_one(resource, hard, &hl);
+                if (r < 0)
+                        return r;
+                if (sl > hl)
+                        return -EILSEQ;
+        }
+
+        *ret = (struct rlimit) {
+                .rlim_cur = sl,
+                .rlim_max = hl,
+        };
+
+        return 0;
+}
+
+int rlimit_format(const struct rlimit *rl, char **ret) {
+        char *s = NULL;
+
+        assert(rl);
+        assert(ret);
+
+        if (rl->rlim_cur >= RLIM_INFINITY && rl->rlim_max >= RLIM_INFINITY)
+                s = strdup("infinity");
+        else if (rl->rlim_cur >= RLIM_INFINITY)
+                (void) asprintf(&s, "infinity:" RLIM_FMT, rl->rlim_max);
+        else if (rl->rlim_max >= RLIM_INFINITY)
+                (void) asprintf(&s, RLIM_FMT ":infinity", rl->rlim_cur);
+        else if (rl->rlim_cur == rl->rlim_max)
+                (void) asprintf(&s, RLIM_FMT, rl->rlim_cur);
+        else
+                (void) asprintf(&s, RLIM_FMT ":" RLIM_FMT, rl->rlim_cur, rl->rlim_max);
+
+        if (!s)
+                return -ENOMEM;
+
+        *ret = s;
+        return 0;
+}
+
 static const char* const rlimit_table[_RLIMIT_MAX] = {
         [RLIMIT_CPU] = "LimitCPU",
         [RLIMIT_FSIZE] = "LimitFSIZE",
index 262f86dd046072d937a4a2ab2daec089237b2286..d4594eccd67d3154c74eefa09d153ab99c5081c3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -30,4 +28,9 @@ int rlimit_from_string(const char *s) _pure_;
 
 int setrlimit_closest(int resource, const struct rlimit *rlim);
 
+int rlimit_parse_one(int resource, const char *val, rlim_t *ret);
+int rlimit_parse(int resource, const char *val, struct rlimit *ret);
+
+int rlimit_format(const struct rlimit *rl, char **ret);
+
 #define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
index 8ec7dd75ee19d31d2d8c6a60974420018d4dcc68..43816fd1bbd9c4ccb6cb36cf3dca8a9450810430 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <unistd.h>
+
 #include "btrfs-util.h"
 #include "fd-util.h"
+#include "log.h"
+#include "macro.h"
 #include "mount-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
 #include "stat-util.h"
 #include "string-util.h"
-#include "util.h"
 
 int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
         _cleanup_closedir_ DIR *d = NULL;
@@ -72,7 +80,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                 errno = 0;
                 de = readdir(d);
                 if (!de) {
-                        if (errno != 0 && ret == 0)
+                        if (errno > 0 && ret == 0)
                                 ret = -errno;
                         return ret;
                 }
index 96579eb1828e6f2cc2e0af9787f9e0e116aaf914..6d032689190266f9f6429d42f0deb9558c8fc631 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index e8ce5cfd96dba201d39637aebe87f8663a65c73a..6c63b9d65250d82d00146f33f704048a26405b38 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <errno.h>
 #include <malloc.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
 #include <sys/un.h>
+#include <syslog.h>
 
 #ifdef HAVE_SELINUX
 #include <selinux/context.h>
 #endif
 
 #include "alloc-util.h"
+#include "log.h"
+#include "macro.h"
 #include "path-util.h"
 #include "selinux-util.h"
-#include "strv.h"
+#include "time-util.h"
+#include "util.h"
 
 #ifdef HAVE_SELINUX
 DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
@@ -47,7 +53,7 @@ static struct selabel_handle *label_hnd = NULL;
 #define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
 #endif
 
-bool mac_selinux_use(void) {
+bool mac_selinux_have(void) {
 #ifdef HAVE_SELINUX
         if (cached_use < 0)
                 cached_use = is_selinux_enabled() > 0;
@@ -58,6 +64,16 @@ bool mac_selinux_use(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;
@@ -197,7 +213,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
         assert(exe);
         assert(label);
 
-        if (!mac_selinux_use())
+        if (!mac_selinux_have())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(&mycon);
@@ -223,7 +239,7 @@ int mac_selinux_get_our_label(char **label) {
         assert(label);
 
 #ifdef HAVE_SELINUX
-        if (!mac_selinux_use())
+        if (!mac_selinux_have())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(label);
@@ -247,7 +263,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
         assert(exe);
         assert(label);
 
-        if (!mac_selinux_use())
+        if (!mac_selinux_have())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(&mycon);
@@ -302,7 +318,7 @@ char* mac_selinux_free(char *label) {
         if (!label)
                 return NULL;
 
-        if (!mac_selinux_use())
+        if (!mac_selinux_have())
                 return NULL;
 
 
index 2afcaec183eceba147d0f4411aab2d4ebf27080c..27e8edb41b457e1a32e502da7a004c98dbfed4aa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/socket.h>
 #include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 
 #include "macro.h"
 
 bool mac_selinux_use(void);
+bool mac_selinux_have(void);
 void mac_selinux_retest(void);
 
 int mac_selinux_init(const char *prefix);
index 4554ef2d49fae8b19191484437f578daa06c2824..2bff5062daf65ba29c2cbafbe751dedde89495e9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -27,7 +25,6 @@
 Set *internal_set_new(const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS);
 #define set_new(ops) internal_set_new(ops  HASHMAP_DEBUG_SRC_ARGS)
 
-
 static inline Set *set_free(Set *s) {
         internal_hashmap_free(HASHMAP_BASE(s));
         return NULL;
index c535c89d5280dbd141fbe2cc6b7b303d97a92043..0ce4f75684088df87190a3e7cb7ac949dad3bfc7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -19,7 +17,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <signal.h>
+#include <stddef.h>
 #include <sys/mman.h>
 
 #include "macro.h"
index 23edc6d9cbfc3b2868f1b7a47ef23b0cad6a8693..cce9eb201b5915277d4071989c706ed5a0643e61 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8038bc891d52a3e963dca591da7394db9207814b..e3047b209b65bb05af4c001e32e88bad78d070c5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "macro.h"
 #include "parse-util.h"
 #include "signal-util.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
-#include "util.h"
 
 int reset_all_signal_handlers(void) {
         static const struct sigaction sa = {
@@ -230,9 +233,9 @@ const char *signal_to_string(int signo) {
                 return name;
 
         if (signo >= SIGRTMIN && signo <= SIGRTMAX)
-                snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
+                xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
         else
-                snprintf(buf, sizeof(buf), "%d", signo);
+                xsprintf(buf, "%d", signo);
 
         return buf;
 }
index e7393e2dacaf2157cf7a34d621bca306ebc85897..72b10e8712ce89b128a78eb48da6aab064a021a3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -41,3 +39,14 @@ int signal_from_string(const char *s) _pure_;
 int signal_from_string_try_harder(const char *s);
 
 void nop_signal_handler(int sig);
+
+static inline void block_signals_reset(sigset_t *ss) {
+        assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0);
+}
+
+#define BLOCK_SIGNALS(...)                                              \
+        _cleanup_(block_signals_reset) sigset_t _saved_sigset = ({      \
+                sigset_t t;                                             \
+                assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
+                t;                                                      \
+        })
index 10fc56da6936ad984f43120cdbf54d896a9d0f64..060e8ba387049e590c5ae37ca04dc7c4c65e1689 100644 (file)
     coding style)
 */
 
+#include "macro.h"
 #include "siphash24.h"
-#include "sparse-endian.h"
 #include "unaligned.h"
-#include "util.h"
 
 static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
         assert(b < 64);
index ba4f7d01b65c3e115b2198cdf006bcc51a235a1b..54e2420cc6e94beea881250c0050746387c1ea98 100644 (file)
@@ -1,6 +1,8 @@
 #pragma once
 
 #include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 struct siphash {
@@ -14,6 +16,8 @@ struct siphash {
 
 void siphash24_init(struct siphash *state, const uint8_t k[16]);
 void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
+#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
+
 uint64_t siphash24_finalize(struct siphash *state);
 
 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
index fcc046098dcd4a8ecf83ac15cfced98660220141..3a3df987df11592938b6f0c32ced6a4d69b9127c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
 #include <sys/xattr.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "fileio.h"
+#include "log.h"
+#include "macro.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "smack-util.h"
 #include "string-table.h"
-#include "util.h"
 #include "xattr-util.h"
 
 #ifdef HAVE_SMACK
index e756dc8c2896f7f0bd06453b95f9f52c8289b7ce..f90ba0a027acc2f3c513749a9f8a34e61f921bc5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -24,6 +22,7 @@
 ***/
 
 #include <stdbool.h>
+#include <sys/types.h>
 
 #include "macro.h"
 
index e5d4efc719e61326d7dab7bafdc9f58898848215..35e9573aa4a69b8bfc41f9d20ff37676169aaba2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <netinet/in.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/un.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "log.h"
 #include "macro.h"
 #include "missing.h"
 #include "mkdir.h"
 #include "selinux-util.h"
 #include "socket-util.h"
-#include "util.h"
 
 int socket_address_listen(
                 const SocketAddress *a,
@@ -143,7 +145,7 @@ int socket_address_listen(
         return r;
 }
 
-int make_socket_fd(int log_level, const char* address, int flags) {
+int make_socket_fd(int log_level, const char* address, int type, int flags) {
         SocketAddress a;
         int fd, r;
 
@@ -151,7 +153,9 @@ int make_socket_fd(int log_level, const char* address, int flags) {
         if (r < 0)
                 return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address);
 
-        fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
+        a.type = type;
+
+        fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
                                    NULL, false, false, false, 0755, 0644, NULL);
         if (fd < 0 || log_get_max_level() >= log_level) {
                 _cleanup_free_ char *p = NULL;
index 1acab1ef95bab65534dad3bf0717a1b5e083235e..49e5f5b125a62bbbee92c92821da634ffe9f10f4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <arpa/inet.h>
 #include <errno.h>
+#include <limits.h>
 #include <net/if.h>
 #include <netdb.h>
 #include <netinet/ip.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
+#include "log.h"
 #include "macro.h"
 #include "missing.h"
 #include "parse-util.h"
@@ -437,17 +438,10 @@ const char* socket_address_get_path(const SocketAddress *a) {
 }
 
 bool socket_ipv6_is_supported(void) {
-        _cleanup_free_ char *l = NULL;
-
-        if (access("/sys/module/ipv6", F_OK) != 0)
+        if (access("/proc/net/sockstat6", F_OK) != 0)
                 return false;
 
-        /* If we can't check "disable" parameter, assume enabled */
-        if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
-                return true;
-
-        /* If module was loaded with disable=1 no IPv6 available */
-        return l[0] == '0';
+        return true;
 }
 
 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
@@ -605,7 +599,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
         return 0;
 }
 
-int getpeername_pretty(int fd, char **ret) {
+int getpeername_pretty(int fd, bool include_port, char **ret) {
         union sockaddr_union sa;
         socklen_t salen = sizeof(sa);
         int r;
@@ -635,7 +629,7 @@ int getpeername_pretty(int fd, char **ret) {
         /* For remote sockets we translate IPv6 addresses back to IPv4
          * if applicable, since that's nicer. */
 
-        return sockaddr_pretty(&sa.sa, salen, true, true, ret);
+        return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
 }
 
 int getsockname_pretty(int fd, char **ret) {
@@ -867,12 +861,19 @@ int getpeersec(int fd, char **ret) {
         return 0;
 }
 
-int send_one_fd(int transport_fd, int fd, int flags) {
+int send_one_fd_sa(
+                int transport_fd,
+                int fd,
+                const struct sockaddr *sa, socklen_t len,
+                int flags) {
+
         union {
                 struct cmsghdr cmsghdr;
                 uint8_t buf[CMSG_SPACE(sizeof(int))];
         } control = {};
         struct msghdr mh = {
+                .msg_name = (struct sockaddr*) sa,
+                .msg_namelen = len,
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
         };
index c60f2556af840e86806adbea785ce7a86a30d239..92edc1dc22d038439eca3c8107f55f4a6da3df07 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <netinet/ether.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <sys/un.h>
 #include <linux/netlink.h>
 #include <linux/if_packet.h>
@@ -86,7 +87,7 @@ int socket_address_listen(
                 mode_t directory_mode,
                 mode_t socket_mode,
                 const char *label);
-int make_socket_fd(int log_level, const char* address, int flags);
+int make_socket_fd(int log_level, const char* address, int type, int flags);
 
 bool socket_address_is(const SocketAddress *a, const char *s, int type);
 bool socket_address_is_netlink(const SocketAddress *a, const char *s);
@@ -102,7 +103,7 @@ bool socket_ipv6_is_supported(void);
 int sockaddr_port(const struct sockaddr *_sa) _pure_;
 
 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
-int getpeername_pretty(int fd, char **ret);
+int getpeername_pretty(int fd, bool include_port, char **ret);
 int getsockname_pretty(int fd, char **ret);
 
 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
@@ -125,7 +126,11 @@ int ip_tos_from_string(const char *s);
 int getpeercred(int fd, struct ucred *ucred);
 int getpeersec(int fd, char **ret);
 
-int send_one_fd(int transport_fd, int fd, int flags);
+int send_one_fd_sa(int transport_fd,
+                   int fd,
+                   const struct sockaddr *sa, socklen_t len,
+                   int flags);
+#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
 int receive_one_fd(int transport_fd, int flags);
 
 #define CMSG_FOREACH(cmsg, mh)                                          \
index f30458f25ae569548cb6ca5b3537d46de77bdd52..2fd03d9f7579757be215b3b7038c95339851a7d0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3bc66b3be79ab33b489b4bdb207beb5481e1beaf..309e84b93d33d90bc4787abc6af04677e5aaec58 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <linux/magic.h>
 #include <sys/statvfs.h>
 #include <unistd.h>
index 909b220a245c9a446e851100e25b7ad1af0f2def..56d28f791e3d0c99d32853860879d12f1db745dd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,7 +20,9 @@
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
 
@@ -52,9 +52,8 @@ int path_is_os_tree(const char *path);
 int files_same(const char *filea, const char *fileb);
 
 /* The .f_type field of struct statfs is really weird defined on
- * different archs. Let's use our own type we know is sufficiently
- * larger to store the possible values. */
-typedef long statfs_f_type_t;
+ * different archs. Let's give its type a name. */
+typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
 
 bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
 int fd_check_fstype(int fd, statfs_f_type_t magic_value);
index b36e8a947e5615a01450b745eefd849702acff13..0a675571ff6c7c238153b591264bb6c0d5d92d98 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f4f702a05abd1775b7be27bb3ea26b50bfb47321..77220c025147337e126fbe12d3a1197fb79785ac 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "strbuf.h"
-#include "util.h"
 
 /*
  * Strbuf stores given strings in a single continuous allocated memory
index fbc4e5f2a1d6c30780c8450e39f94731a0080843..a1632da0e85a583dbc0257895df1d84f61be5f21 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,7 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
 #include <stdint.h>
+#include <sys/types.h>
 
 struct strbuf {
         char *buf;
index a860324fc9883da658fa3f3ceacd5e6e0fdf7d5b..a1499ab12601b3dd542d038859fefabe50343726 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -20,6 +18,7 @@
 ***/
 
 #include "string-table.h"
+#include "string-util.h"
 
 ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
         size_t i;
index 51b6007214e467c879f7c2642d969ca028b06f2d..b180488fe86d950a78c6aef29892bb921a88b0ad 100644 (file)
@@ -1,6 +1,4 @@
 
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
@@ -46,16 +45,34 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
         }
 
+#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        scope type name##_from_string(const char *s) {                  \
+                int b;                                                  \
+                b = parse_boolean(s);                                   \
+                if (b == 0)                                             \
+                        return (type) 0;                                \
+                else if (b > 0)                                         \
+                        return yes;                                     \
+                return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
+        }
+
 #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
         _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
         _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
         struct __useless_struct_to_allow_trailing_semicolon__
 
+#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
 #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
 #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
 
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
+
 /* For string conversions where numbers are also acceptable */
 #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
         int name##_to_string_alloc(type i, char **str) {                \
index 6006767daac5b025fdb56e44fd28d82a2443f20b..0bde55f9d5749a29e2e7b4e133cfb6d2ecb7543a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
 #include "alloc-util.h"
 #include "gunicode.h"
+#include "macro.h"
 #include "string-util.h"
 #include "utf8.h"
 #include "util.h"
@@ -310,18 +315,67 @@ char *truncate_nl(char *s) {
         return s;
 }
 
+char ascii_tolower(char x) {
+
+        if (x >= 'A' && x <= 'Z')
+                return x - 'A' + 'a';
+
+        return x;
+}
+
 char *ascii_strlower(char *t) {
         char *p;
 
         assert(t);
 
         for (p = t; *p; p++)
-                if (*p >= 'A' && *p <= 'Z')
-                        *p = *p - 'A' + 'a';
+                *p = ascii_tolower(*p);
+
+        return t;
+}
+
+char *ascii_strlower_n(char *t, size_t n) {
+        size_t i;
+
+        if (n <= 0)
+                return t;
+
+        for (i = 0; i < n; i++)
+                t[i] = ascii_tolower(t[i]);
 
         return t;
 }
 
+int ascii_strcasecmp_n(const char *a, const char *b, size_t n) {
+
+        for (; n > 0; a++, b++, n--) {
+                int x, y;
+
+                x = (int) (uint8_t) ascii_tolower(*a);
+                y = (int) (uint8_t) ascii_tolower(*b);
+
+                if (x != y)
+                        return x - y;
+        }
+
+        return 0;
+}
+
+int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
+        int r;
+
+        r = ascii_strcasecmp_n(a, b, MIN(n, m));
+        if (r != 0)
+                return r;
+
+        if (n < m)
+                return -1;
+        else if (n > m)
+                return 1;
+        else
+                return 0;
+}
+
 bool chars_intersect(const char *a, const char *b) {
         const char *p;
 
@@ -394,6 +448,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
         char *e;
         const char *i, *j;
         unsigned k, len, len2;
+        int r;
 
         assert(s);
         assert(percent <= 100);
@@ -413,10 +468,10 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
 
         k = 0;
         for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
-                int c;
+                char32_t c;
 
-                c = utf8_encoded_to_unichar(i);
-                if (c < 0)
+                r = utf8_encoded_to_unichar(i, &c);
+                if (r < 0)
                         return NULL;
                 k += unichar_iswide(c) ? 2 : 1;
         }
@@ -425,11 +480,11 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
                 x ++;
 
         for (j = s + old_length; k < new_length && j > i; ) {
-                int c;
+                char32_t c;
 
                 j = utf8_prev_char(j);
-                c = utf8_encoded_to_unichar(j);
-                if (c < 0)
+                r = utf8_encoded_to_unichar(j, &c);
+                if (r < 0)
                         return NULL;
                 k += unichar_iswide(c) ? 2 : 1;
         }
index 54f9d3058cc5257595e30f2c011943c77be67e0d..ad0c813761ed9dc81dd9aa254b54421719cc0b20 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,7 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
 #include <stdbool.h>
+#include <stddef.h>
 #include <string.h>
 
 #include "macro.h"
@@ -128,7 +128,12 @@ char *strstrip(char *s);
 char *delete_chars(char *s, const char *bad);
 char *truncate_nl(char *s);
 
-char *ascii_strlower(char *path);
+char ascii_tolower(char x);
+char *ascii_strlower(char *s);
+char *ascii_strlower_n(char *s, size_t n);
+
+int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
+int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
 
 bool chars_intersect(const char *a, const char *b) _pure_;
 
index 771781f9fc764386cf772097b651e873678e6170..b5d4d8191b1c1659ad08fb8c27af085553e524bd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <fnmatch.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "escape.h"
+#include "extract-word.h"
+#include "fileio.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
@@ -868,3 +870,22 @@ rollback:
         nl[k] = NULL;
         return -ENOMEM;
 }
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
+        bool b = false;
+        char **s;
+        int r;
+
+        /* Like fputs(), but for strv, and with a less stupid argument order */
+
+        if (!space)
+                space = &b;
+
+        STRV_FOREACH(s, l) {
+                r = fputs_with_space(f, *s, separator, space);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
index e66794fc34d9f59caebf38b2c8f72f97c1547979..7bfa54408d25c5fa320e56e143536438985d92d3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <fnmatch.h>
 #include <stdarg.h>
 #include <stdbool.h>
+#include <stddef.h>
 
+#include "alloc-util.h"
 #include "extract-word.h"
+#include "macro.h"
 #include "util.h"
 
 char *strv_find(char **l, const char *name) _pure_;
@@ -166,3 +167,5 @@ char ***strv_free_free(char ***l);
 char **strv_skip(char **l, size_t n);
 
 int strv_extend_n(char ***l, const char *value, size_t n);
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space);
index 088ba53c29d1f6b3c30c7cfa603b4929b6110891..aaf11d21f6b94afeb2dbb785c89f556fd9bea463 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -25,6 +23,7 @@
  * Returns the * remaining size, and 0 if the string was truncated.
  */
 
+#include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
index ccc7e52f3757a4afb5ebbbdff6752476027cd6d0..80ff58726b90373499af2306260b9bcca50e770e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,8 @@
 ***/
 
 
+#include <stddef.h>
+
 #include "macro.h"
 
 size_t strpcpy(char **dest, size_t size, const char *src);
index 01577941a08507244d39366677410be77c7170ad..db3405154e77d101e1915904a6812667090d3e7a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <string.h>
 #include <syslog.h>
 
-#include "assert.h"
 #include "hexdecoct.h"
+#include "macro.h"
 #include "string-table.h"
 #include "syslog-util.h"
 
index eb79c6dbd85eeff048a57e9b24a06aeaf25fd5f3..5cb606a1bf20fd92f67536362685b15f09855f84 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3931b03bc2a05bbf2029bf502cdf8c52e6de6b92..0a9d2bbdef7b86f26d2bb722631d833b94ab914d 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/socket.h>
+#include <sys/sysmacros.h>
+#include <sys/time.h>
 #include <linux/kd.h>
 #include <linux/tiocl.h>
 #include <linux/vt.h>
 #include <poll.h>
 #include <signal.h>
 #include <sys/ioctl.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <termios.h>
-#include <time.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
@@ -36,8 +43,9 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "log.h"
+#include "macro.h"
 #include "parse-util.h"
-#include "path-util.h"
 #include "process-util.h"
 #include "socket-util.h"
 #include "stat-util.h"
@@ -120,7 +128,7 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
 
         errno = 0;
         if (!fgets(line, sizeof(line), f))
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         truncate_nl(line);
 
@@ -204,7 +212,7 @@ int ask_string(char **ret, const char *text, ...) {
 
                 errno = 0;
                 if (!fgets(line, sizeof(line), stdin))
-                        return errno ? -errno : -EIO;
+                        return errno > 0 ? -errno : -EIO;
 
                 if (!endswith(line, "\n"))
                         putchar('\n');
@@ -718,9 +726,7 @@ bool tty_is_vc_resolve(const char *tty) {
 }
 
 const char *default_term_for_tty(const char *tty) {
-        assert(tty);
-
-        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
+        return tty && tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
 }
 
 int fd_columns(int fd) {
@@ -1127,3 +1133,16 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
 
         return receive_one_fd(pair[0], 0);
 }
+
+bool colors_enabled(void) {
+        const char *colors;
+
+        colors = getenv("SYSTEMD_COLORS");
+        if (!colors) {
+                if (streq_ptr(getenv("TERM"), "dumb"))
+                        return false;
+                return on_tty();
+        }
+
+        return parse_boolean(colors) != 0;
+}
index f2185c1c117d876c7d3ff4287bae8928ef553b5c..a7c96a77cbbbeff924944631644d4eb722db568e 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdbool.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdio.h>
+#include <sys/types.h>
 
 #include "macro.h"
 #include "time-util.h"
@@ -78,37 +79,38 @@ unsigned lines(void);
 void columns_lines_cache_reset(int _unused_ signum);
 
 bool on_tty(void);
+bool colors_enabled(void);
 
 static inline const char *ansi_underline(void) {
-        return on_tty() ? ANSI_UNDERLINE : "";
+        return colors_enabled() ? ANSI_UNDERLINE : "";
 }
 
 static inline const char *ansi_highlight(void) {
-        return on_tty() ? ANSI_HIGHLIGHT : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT : "";
 }
 
 static inline const char *ansi_highlight_underline(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_UNDERLINE : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : "";
 }
 
 static inline const char *ansi_highlight_red(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_RED : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT_RED : "";
 }
 
 static inline const char *ansi_highlight_green(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_GREEN : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : "";
 }
 
 static inline const char *ansi_highlight_yellow(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_YELLOW : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : "";
 }
 
 static inline const char *ansi_highlight_blue(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_BLUE : "";
+        return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : "";
 }
 
 static inline const char *ansi_normal(void) {
-        return on_tty() ? ANSI_NORMAL : "";
+        return colors_enabled() ? ANSI_NORMAL : "";
 }
 
 int get_ctty_devnr(pid_t pid, dev_t *d);
index 647763a2309883517e5f56def3a21a457a13b73f..3973850b442af72367da2804de88fc6bbac53799 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
 #include <sys/timerfd.h>
 #include <sys/timex.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "log.h"
+#include "macro.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
-#include "util.h"
+
+static nsec_t timespec_load_nsec(const struct timespec *ts);
 
 usec_t now(clockid_t clock_id) {
         struct timespec ts;
@@ -70,12 +79,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 = now(CLOCK_MONOTONIC);
-
-        if ((int64_t) ts->monotonic > delta)
-                ts->monotonic -= delta;
-        else
-                ts->monotonic = 0;
+        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
 
         return ts;
 }
@@ -91,12 +95,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 = now(CLOCK_REALTIME);
-        if ((int64_t) ts->realtime > delta)
-                ts->realtime -= delta;
-        else
-                ts->realtime = 0;
+        ts->realtime = usec_sub(now(CLOCK_REALTIME), delta);
 
         return ts;
 }
@@ -108,25 +107,15 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
                 ts->realtime = ts->monotonic = USEC_INFINITY;
                 return ts;
         }
-        ts->realtime = now(CLOCK_REALTIME);
-        ts->monotonic = now(CLOCK_MONOTONIC);
 
+        dual_timestamp_get(ts);
         delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
-
-        if ((int64_t) ts->realtime > delta)
-                ts->realtime -= delta;
-        else
-                ts->realtime = 0;
-
-        if ((int64_t) ts->monotonic > delta)
-                ts->monotonic -= delta;
-        else
-                ts->monotonic = 0;
+        ts->realtime = usec_sub(ts->realtime, delta);
+        ts->monotonic = usec_sub(ts->monotonic, delta);
 
         return ts;
 }
 
-
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
@@ -142,7 +131,7 @@ usec_t timespec_load(const struct timespec *ts) {
                 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
 }
 
-nsec_t timespec_load_nsec(const struct timespec *ts) {
+static nsec_t timespec_load_nsec(const struct timespec *ts) {
         assert(ts);
 
         if (ts->tv_sec == (time_t) -1 &&
@@ -198,9 +187,11 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
         return tv;
 }
 
-static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc) {
+static char *format_timestamp_internal(char *buf, size_t l, usec_t t,
+                                       bool utc, bool us) {
         struct tm tm;
         time_t sec;
+        int k;
 
         assert(buf);
         assert(l > 0);
@@ -211,48 +202,36 @@ static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc)
         sec = (time_t) (t / USEC_PER_SEC);
         localtime_or_gmtime_r(&sec, &tm, utc);
 
-        if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm) <= 0)
+        if (us)
+                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm);
+        else
+                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm);
+
+        if (k <= 0)
                 return NULL;
+        if (us) {
+                snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
+                if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
+                        return NULL;
+        }
 
         return buf;
 }
 
 char *format_timestamp(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal(buf, l, t, false);
+        return format_timestamp_internal(buf, l, t, false, false);
 }
 
 char *format_timestamp_utc(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal(buf, l, t, true);
-}
-
-static char *format_timestamp_internal_us(char *buf, size_t l, usec_t t, bool utc) {
-        struct tm tm;
-        time_t sec;
-
-        assert(buf);
-        assert(l > 0);
-
-        if (t <= 0 || t == USEC_INFINITY)
-                return NULL;
-
-        sec = (time_t) (t / USEC_PER_SEC);
-        localtime_or_gmtime_r(&sec, &tm, utc);
-
-        if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0)
-                return NULL;
-        snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
-        if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
-                return NULL;
-
-        return buf;
+        return format_timestamp_internal(buf, l, t, true, false);
 }
 
 char *format_timestamp_us(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal_us(buf, l, t, false);
+        return format_timestamp_internal(buf, l, t, false, true);
 }
 
 char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) {
-        return format_timestamp_internal_us(buf, l, t, true);
+        return format_timestamp_internal(buf, l, t, true, true);
 }
 
 char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
@@ -658,29 +637,18 @@ int parse_timestamp(const char *t, usec_t *usec) {
 
 parse_usec:
         {
-                char *end;
-                unsigned long long val;
-                size_t l;
+                unsigned add;
 
                 k++;
-                if (*k < '0' || *k > '9')
+                r = parse_fractional_part_u(&k, 6, &add);
+                if (r < 0)
                         return -EINVAL;
 
-                /* base 10 instead of base 0, .09 is not base 8 */
-                errno = 0;
-                val = strtoull(k, &end, 10);
-                if (*end || errno)
+                if (*k)
                         return -EINVAL;
 
-                l = end-k;
-
-                /* val has l digits, make them 6 */
-                for (; l < 6; l++)
-                        val *= 10;
-                for (; l > 6; l--)
-                        val /= 10;
+                x_usec = add;
 
-                x_usec = val;
         }
 
 from_tm:
index 0417c29cddbe4b5506745a190e42f9fc1f0b5bcb..9894e626c5f9e58d43db478b7983b01806284a6f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,9 @@
 ***/
 
 #include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <time.h>
 
@@ -66,7 +67,7 @@ typedef struct dual_timestamp {
 #define FORMAT_TIMESTAMP_RELATIVE_MAX 256
 #define FORMAT_TIMESPAN_MAX 64
 
-#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
+#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
 
 #define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
 
@@ -89,8 +90,6 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u);
 usec_t timeval_load(const struct timeval *tv) _pure_;
 struct timeval *timeval_store(struct timeval *tv, usec_t u);
 
-nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
-
 char *format_timestamp(char *buf, size_t l, usec_t t);
 char *format_timestamp_utc(char *buf, size_t l, usec_t t);
 char *format_timestamp_us(char *buf, size_t l, usec_t t);
@@ -124,3 +123,29 @@ time_t mktime_or_timegm(struct tm *tm, bool utc);
 struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
 
 unsigned long usec_to_jiffies(usec_t usec);
+
+static inline usec_t usec_add(usec_t a, usec_t b) {
+        usec_t c;
+
+        /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't
+         * overflow. */
+
+        c = a + b;
+        if (c < a || c < b) /* overflow check */
+                return USEC_INFINITY;
+
+        return c;
+}
+
+static inline usec_t usec_sub(usec_t timestamp, int64_t delta) {
+        if (delta < 0)
+                return usec_add(timestamp, (usec_t) (-delta));
+
+        if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */
+                return USEC_INFINITY;
+
+        if (timestamp < (usec_t) delta)
+                return 0;
+
+        return timestamp - delta;
+}
index 8ed34658b44c58d2a228dd2d72772b3d75f2662e..359d87d27c2b4f70c667f1c666afc19f997ca04d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a8115eaa1f6d996aada4d5519e3a987f4943304f..79be645bedcab03410a35152379c892dad6d98f3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9a55eacbfb51e3204bb966ad250c12613fda77c3..fe883b95c7f7e72d094b0571638c9c1cf811474a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "bus-label.h"
-#include "def.h"
+#include "glob-util.h"
 #include "hexdecoct.h"
+#include "macro.h"
 #include "path-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unit-name.h"
-#include "util.h"
 
+/* Characters valid in a unit name. */
 #define VALID_CHARS                             \
-        DIGITS LETTERS                          \
+        DIGITS                                  \
+        LETTERS                                 \
         ":-_.\\"
 
+/* The same, but also permits the single @ character that may appear */
+#define VALID_CHARS_WITH_AT                     \
+        "@"                                     \
+        VALID_CHARS
+
+/* All chars valid in a unit name glob */
+#define VALID_CHARS_GLOB                        \
+        VALID_CHARS_WITH_AT                     \
+        "[]!-*?"
+
 bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
         const char *e, *i, *at;
 
@@ -635,7 +648,7 @@ static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t
         /* We'll only escape the obvious characters here, to play
          * safe. */
 
-        valid_chars = allow_globs == UNIT_NAME_GLOB ? "@" VALID_CHARS "[]!-*?" : "@" VALID_CHARS;
+        valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
 
         for (; *f; f++) {
                 if (*f == '/')
@@ -670,15 +683,15 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
         if (!unit_suffix_is_valid(suffix))
                 return -EINVAL;
 
-        if (unit_name_is_valid(name, UNIT_NAME_ANY)) {
-                /* No mangling necessary... */
-                s = strdup(name);
-                if (!s)
-                        return -ENOMEM;
+        /* Already a fully valid unit name? If so, no mangling is necessary... */
+        if (unit_name_is_valid(name, UNIT_NAME_ANY))
+                goto good;
 
-                *ret = s;
-                return 0;
-        }
+        /* Already a fully valid globbing expression? If so, no mangling is necessary either... */
+        if (allow_globs == UNIT_NAME_GLOB &&
+            string_is_glob(name) &&
+            in_charset(name, VALID_CHARS_GLOB))
+                goto good;
 
         if (is_device_path(name)) {
                 r = unit_name_from_path(name, ".device", ret);
@@ -703,11 +716,21 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
         t = do_escape_mangle(name, allow_globs, s);
         *t = 0;
 
-        if (unit_name_to_type(s) < 0)
+        /* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow "foo.*" as a
+         * valid glob. */
+        if ((allow_globs != UNIT_NAME_GLOB || !string_is_glob(s)) && unit_name_to_type(s) < 0)
                 strcpy(t, suffix);
 
         *ret = s;
         return 1;
+
+good:
+        s = strdup(name);
+        if (!s)
+                return -ENOMEM;
+
+        *ret = s;
+        return 0;
 }
 
 int slice_build_parent_slice(const char *slice, char **ret) {
index 03c1a6e4acd7dbe8c5ce0351421befb42df9ea32..f209a846343ac9a03354be395215716a6474eaea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 397880b0b1d605e18f98ccf158f8c36cf3885a9f..19155bce5364df556c4b08aabb03041eb9556220 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <grp.h>
 #include <pwd.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "formats-util.h"
 #include "macro.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
 #include "user-util.h"
-#include "util.h"
 
 bool uid_is_valid(uid_t uid) {
 
@@ -58,7 +66,7 @@ int parse_uid(const char *s, uid_t *ret) {
         if (!uid_is_valid(uid))
                 return -ENXIO; /* we return ENXIO instead of EINVAL
                                 * here, to make it easy to distuingish
-                                * invalid numeric uids invalid
+                                * invalid numeric uids from invalid
                                 * strings. */
 
         if (ret)
index 11ff6674cf5b7272989c9ce76b9223951e8c3691..c23f1d485d5fd42c2ad4f237ab0b3921ac76e97e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 bool uid_is_valid(uid_t uid);
 
index b4063a4ceca64966ee73cd405cf7fdeda5c61237..629db123cdda8a8e5a1408ce2d9ce935ae260ee1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
  */
 
 #include <errno.h>
-#include <inttypes.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "hexdecoct.h"
+#include "macro.h"
 #include "utf8.h"
-#include "util.h"
 
-bool unichar_is_valid(uint32_t ch) {
+bool unichar_is_valid(char32_t ch) {
 
         if (ch >= 0x110000) /* End of unicode space */
                 return false;
@@ -68,7 +65,7 @@ bool unichar_is_valid(uint32_t ch) {
         return true;
 }
 
-static bool unichar_is_control(uint32_t ch) {
+static bool unichar_is_control(char32_t ch) {
 
         /*
           0 to ' '-1 is the C0 range.
@@ -104,8 +101,9 @@ static int utf8_encoded_expected_len(const char *str) {
 }
 
 /* decode one unicode char */
-int utf8_encoded_to_unichar(const char *str) {
-        int unichar, len, i;
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
+        char32_t unichar;
+        int len, i;
 
         assert(str);
 
@@ -113,34 +111,37 @@ int utf8_encoded_to_unichar(const char *str) {
 
         switch (len) {
         case 1:
-                return (int)str[0];
+                *ret_unichar = (char32_t)str[0];
+                return 0;
         case 2:
                 unichar = str[0] & 0x1f;
                 break;
         case 3:
-                unichar = (int)str[0] & 0x0f;
+                unichar = (char32_t)str[0] & 0x0f;
                 break;
         case 4:
-                unichar = (int)str[0] & 0x07;
+                unichar = (char32_t)str[0] & 0x07;
                 break;
         case 5:
-                unichar = (int)str[0] & 0x03;
+                unichar = (char32_t)str[0] & 0x03;
                 break;
         case 6:
-                unichar = (int)str[0] & 0x01;
+                unichar = (char32_t)str[0] & 0x01;
                 break;
         default:
                 return -EINVAL;
         }
 
         for (i = 1; i < len; i++) {
-                if (((int)str[i] & 0xc0) != 0x80)
+                if (((char32_t)str[i] & 0xc0) != 0x80)
                         return -EINVAL;
                 unichar <<= 6;
-                unichar |= (int)str[i] & 0x3f;
+                unichar |= (char32_t)str[i] & 0x3f;
         }
 
-        return unichar;
+        *ret_unichar = unichar;
+
+        return 0;
 }
 
 bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
@@ -149,15 +150,16 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
         assert(str);
 
         for (p = str; length;) {
-                int encoded_len, val;
+                int encoded_len, r;
+                char32_t val;
 
                 encoded_len = utf8_encoded_valid_unichar(p);
                 if (encoded_len < 0 ||
                     (size_t) encoded_len > length)
                         return false;
 
-                val = utf8_encoded_to_unichar(p);
-                if (val < 0 ||
+                r = utf8_encoded_to_unichar(p, &val);
+                if (r < 0 ||
                     unichar_is_control(val) ||
                     (!newline && val == '\n'))
                         return false;
@@ -277,7 +279,7 @@ char *ascii_is_valid(const char *str) {
  * Returns: The length in bytes that the UTF-8 representation does or would
  *          occupy.
  */
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
+size_t utf8_encode_unichar(char *out_utf8, char32_t g) {
 
         if (g < (1 << 7)) {
                 if (out_utf8)
@@ -321,7 +323,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
         t = r;
 
         while (f < (const uint8_t*) s + length) {
-                uint16_t w1, w2;
+                char16_t w1, w2;
 
                 /* see RFC 2781 section 2.2 */
 
@@ -355,7 +357,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
 }
 
 /* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(int unichar) {
+static int utf8_unichar_to_encoded_len(char32_t unichar) {
 
         if (unichar < 0x80)
                 return 1;
@@ -373,7 +375,8 @@ static int utf8_unichar_to_encoded_len(int unichar) {
 
 /* validate one encoded unicode char and return its length */
 int utf8_encoded_valid_unichar(const char *str) {
-        int len, unichar, i;
+        int len, i, r;
+        char32_t unichar;
 
         assert(str);
 
@@ -390,7 +393,9 @@ int utf8_encoded_valid_unichar(const char *str) {
                 if ((str[i] & 0x80) != 0x80)
                         return -EINVAL;
 
-        unichar = utf8_encoded_to_unichar(str);
+        r = utf8_encoded_to_unichar(str, &unichar);
+        if (r < 0)
+                return r;
 
         /* check if encoded length matches encoded value */
         if (utf8_unichar_to_encoded_len(unichar) != len)
index e745649f06f5b06fcbe7b0869a798f068820d403..12c272d66e357da28c4e7fea9105cf1ac4fc4b7f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <uchar.h>
 
 #include "macro.h"
+#include "missing.h"
 
 #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
 
-bool unichar_is_valid(uint32_t c);
+bool unichar_is_valid(char32_t c);
 
 const char *utf8_is_valid(const char *s) _pure_;
 char *ascii_is_valid(const char *s) _pure_;
@@ -38,20 +40,20 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pu
 char *utf8_escape_invalid(const char *s);
 char *utf8_escape_non_printable(const char *str);
 
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g);
+size_t utf8_encode_unichar(char *out_utf8, char32_t g);
 char *utf16_to_utf8(const void *s, size_t length);
 
 int utf8_encoded_valid_unichar(const char *str);
-int utf8_encoded_to_unichar(const char *str);
+int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
 
-static inline bool utf16_is_surrogate(uint16_t c) {
+static inline bool utf16_is_surrogate(char16_t c) {
         return (0xd800 <= c && c <= 0xdfff);
 }
 
-static inline bool utf16_is_trailing_surrogate(uint16_t c) {
+static inline bool utf16_is_trailing_surrogate(char16_t c) {
         return (0xdc00 <= c && c <= 0xdfff);
 }
 
-static inline uint32_t utf16_surrogate_pair_to_unichar(uint16_t lead, uint16_t trail) {
+static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
                 return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
 }
index 58617b354aa6cd58224e108f6842e284449542fc..ea1bed7ceb9f8ebcf82c38600ac5fe8e99512fc3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <ctype.h>
+#include <alloca.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <grp.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <limits.h>
-#include <linux/magic.h>
-#include <linux/oom.h>
-#include <linux/sched.h>
-#include <locale.h>
-#include <poll.h>
-#include <pwd.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
 #include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/personality.h>
 #include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h>
+#include <sys/statfs.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
-#include <sys/utsname.h>
-#include <sys/vfs.h>
-#include <sys/wait.h>
-#include <syslog.h>
 #include <unistd.h>
 
-/* When we include libgen.h because we need dirname() we immediately
- * undefine basename() since libgen.h defines it as a macro to the
- * POSIX version which is really broken. We prefer GNU basename(). */
-#include <libgen.h>
-#undef basename
-
-#ifdef HAVE_SYS_AUXV_H
-#include <sys/auxv.h>
-#endif
-
-/* We include linux/fs.h as last of the system headers, as it
- * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
-#include <linux/fs.h>
-
 #include "alloc-util.h"
 #include "build.h"
 #include "def.h"
-#include "device-nodes.h"
 #include "dirent-util.h"
-#include "env-util.h"
-#include "escape.h"
-#include "exit-status.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
-#include "gunicode.h"
 #include "hashmap.h"
-#include "hexdecoct.h"
 #include "hostname-util.h"
-#include "ioprio.h"
 #include "log.h"
 #include "macro.h"
 #include "missing.h"
-#include "mkdir.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
-#include "random-util.h"
+#include "set.h"
 #include "signal-util.h"
-#include "sparse-endian.h"
 #include "stat-util.h"
-#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
-#include "terminal-util.h"
+#include "time-util.h"
 #include "user-util.h"
-#include "utf8.h"
 #include "util.h"
-#include "virt.h"
 
 /* Put this test here for a lack of better place */
 assert_cc(EAGAIN == EWOULDBLOCK);
@@ -558,7 +511,7 @@ int on_ac_power(void) {
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
 
                 if (!de)
index d9d2f72b750314afda0a039576a007b54512afa0..6f42c85a33dea8201f21b32166d36d9b1c731bdb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <alloca.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/inotify.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
index d63062d39e3bc88c9eaf5c343cb216e5cd844604..d9cdb38d651feb9194ff40b34370549bce61373c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "log.h"
+#include "macro.h"
 #include "string-util.h"
-#include "util.h"
 #include "verbs.h"
+#include "virt.h"
 
 int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
         const Verb *verb;
@@ -78,6 +83,11 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
                 return -EINVAL;
         }
 
+        if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) {
+                log_info("Running in chroot, ignoring request.");
+                return 0;
+        }
+
         if (name)
                 return verb->dispatch(left, argv + optind, userdata);
         else {
index d59e4d59b8f0b79e611ec82fcadccd8bc124f5e7..7b5e18510f1099001daeea1fc7055dec0ebe18cb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,7 +20,8 @@
 ***/
 
 #define VERB_ANY ((unsigned) -1)
-#define VERB_DEFAULT 1
+#define VERB_DEFAULT 1U
+#define VERB_NOCHROOT 2U
 
 typedef struct {
         const char *verb;
index 1e5d6eea6e8b9b340f7e03187526efc5df4b138f..19b6318e3ddba3d4a7fcf0374af7d23058281a44 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -20,6 +18,8 @@
 ***/
 
 #include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "macro.h"
 #include "process-util.h"
 #include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
-#include "util.h"
 #include "virt.h"
 
 static int detect_vm_cpuid(void) {
@@ -269,13 +269,20 @@ int detect_vm(void) {
         if (cached_found >= 0)
                 return cached_found;
 
-        r = detect_vm_cpuid();
+        /* We have to use the correct order here:
+         * Some virtualization technologies do use KVM hypervisor but are
+         * expected to be detected as something else. So detect DMI first.
+         *
+         * An example is Virtualbox since version 5.0, which uses KVM backend.
+         * Detection via DMI works corretly, the CPU ID would find KVM
+         * only. */
+        r = detect_vm_dmi();
         if (r < 0)
                 return r;
         if (r != VIRTUALIZATION_NONE)
                 goto finish;
 
-        r = detect_vm_dmi();
+        r = detect_vm_cpuid();
         if (r < 0)
                 return r;
         if (r != VIRTUALIZATION_NONE)
index aca961867c4146ce8d7f367368e71068b7db5c1b..a538f07f6b7f21ebaeccac1661dae82645137889 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 68ec04021bb8a10520d764abbd844626d8079341..595688ed933c90810c607974dbf25710057ea899 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 40c1509eb8c9eb8e868559c204195756fc2d5090..e6bb6b53f5a180a8dc3c0d3945dd6b0c1423b9b0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 6abdaedc3e7aa5e0753d1c7326093581606f7c1a..8d7f14f3827e457cf027874ec4dfa1e5c5f05323 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
 #include <sys/xattr.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "macro.h"
 #include "sparse-endian.h"
 #include "stdio-util.h"
-#include "util.h"
+#include "time-util.h"
 #include "xattr-util.h"
 
 int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
index cf4cb12a2586d2d84a41da27e87ee4060e260c2c..6fa097bf7edf4f9f360ca7cc631766f859a57377 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <sys/types.h>
 
 #include "time-util.h"
index 8126bce212622caffea5d5cc75c5e540b5aa0989..1dbeac7324948975323e2019d20b7b5911d498c6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stddef.h>
 #include <string.h>
 
+#include "macro.h"
 #include "string-util.h"
-#include "util.h"
 #include "xml.h"
 
 enum {
index b256b0ba104c583dc386826eff85c7b145de6341..41cb69f0dc6f40f1deb12887100fc7fc8660400e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 03fb413fe5e40ddfcbe8e25f6e703ada91cba503..eeef04fb1ce4da627e594ea880867983e4214be1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 4cf42d17f34b76b6dc71e317990966297af888aa..e9baf69f6a9f5cc43ecd74ad521979121970e04c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,6 +37,7 @@
 
 #include "alloc-util.h"
 #include "blkid-util.h"
+#include "dirent-util.h"
 #include "efivars.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -249,13 +248,10 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
                 return log_error_errno(errno, "Failed to read \"%s\": %m", p);
         }
 
-        while ((de = readdir(d))) {
+        FOREACH_DIRENT(de, d, break) {
                 _cleanup_close_ int fd = -1;
                 _cleanup_free_ char *v = NULL;
 
-                if (de->d_name[0] == '.')
-                        continue;
-
                 if (!endswith_no_case(de->d_name, ".efi"))
                         continue;
 
@@ -270,9 +266,9 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
                 if (r < 0)
                         return r;
                 if (r > 0)
-                        printf("         File: └─/%s/%s (%s)\n", path, de->d_name, v);
+                        printf("         File: %s/%s/%s (%s)\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name, v);
                 else
-                        printf("         File: └─/%s/%s\n", path, de->d_name);
+                        printf("         File: %s/%s/%s\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name);
                 c++;
         }
 
@@ -324,7 +320,7 @@ static int print_efi_option(uint16_t id, bool in_order) {
         printf("           ID: 0x%04X\n", id);
         printf("       Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
         printf("    Partition: /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));
-        printf("         File: └─%s\n", path);
+        printf("         File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), path);
         printf("\n");
 
         return 0;
@@ -614,12 +610,9 @@ static int install_binaries(const char *esp_path, bool force) {
         if (!d)
                 return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
 
-        while ((de = readdir(d))) {
+        FOREACH_DIRENT(de, d, break) {
                 int k;
 
-                if (de->d_name[0] == '.')
-                        continue;
-
                 if (!endswith_no_case(de->d_name, ".efi"))
                         continue;
 
@@ -797,13 +790,10 @@ static int remove_boot_efi(const char *esp_path) {
                 return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
         }
 
-        while ((de = readdir(d))) {
+        FOREACH_DIRENT(de, d, break) {
                 _cleanup_close_ int fd = -1;
                 _cleanup_free_ char *v = NULL;
 
-                if (de->d_name[0] == '.')
-                        continue;
-
                 if (!endswith_no_case(de->d_name, ".efi"))
                         continue;
 
index 6d35adc0e2f4bb287362e5a0452b6059507c57cb..893980071fd832a4f2a8f9fd749788af208b2b15 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 2151d3443202bf828bd00a95d1b951fc23a3c9df..c436f8b4769d925e25203bcc4533759ceeddfbd8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 5c7808a0676acda78795f4dc47c7829518d603d4..3fe0ce5ec432c058cdf84bbb7b8f460031da08a6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 96063fbc288bb576160b35ca5f8537c5669760d1..3e3b5b224aa3b3a909cde7d5c108a67a66f2e19e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 1b25343a00bd2723ffc5caf8c502ab8c077cb6e5..af91a9c67426b08ee13d5c36dccbb49038848ee6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index efa91fa7ac27892e785214d682043cbb541a7bd9..4854baf87405e66944aa10bd0015315f8976fe01 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 3ee4972798475b35019214c101241f936bc43f37..cf48e647e746173924b30f919826b5ca33b2f21e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index e9d097c1329cbd6ddc3f8c16aecaa6d0f4ccd640..0dc99a6c531296dafb4077ee9500bb93793a9e0b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index aff69a9778418ce445f536f4dce45c81f3fcc130..d9e6ed7955f1ec34c2a4f59a9578d606937c21c9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index efb3271ee3ca952a31371a142ba92701f70aa03d..77fff77b69fa50384398b25c439bf8bcad78dc42 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index ca2f9a2508ecc18198c8e379259386017acb0d1d..2e445ede178ec3518284ee2d9382bd45f29c79a2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index b584b5e6a91ee18df3b59f977b41e1a69bbb61b4..b1cc2c0b729d07b58d1b86dc19f00a08576a13ea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 0183e79b1677cb3cfeefc0aecd0bbda2e2d1d15b..09b543fb471327200675d9ccb0ec2c465c2a35bc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 2cd5c33cb6e085bd8605980b5cc12657899e869a..9633bc1792eb52ee32b0fe110d4bc360c7b4b5e2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /* 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
index 5e374edacfcdb0fb4ed233596b22b8c1c007d199..98c5be74ce0f08058afd1ba0aa4df7020245fd36 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 4727a34d1fd922832ccb70f6c0e40facc478468e..e673cdf9a091bea1f4dc7f824c5851d642d2713f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * 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
index 6a0e1d6b141b726f6413543d6901cba3084f7d67..77d158f5f9d3d0908899c5f69a4965bf5734a94a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bdb4b001991de011f08045d00fafb1e46191f913..1b445b954b96f3d0a69ac23c82d7f22698b334e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,6 +23,7 @@
 ***/
 
 #include <stdbool.h>
+
 #include "list.h"
 
 #define MAXCPUS        16
index c1b1e77e4476a0c1cc7a3394cc6a435622f955b9..42cb8043ced05c9e33126e48ee8c5d5fd2180a2f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bbb4796efdd628a139c7fd15df3b205bf7dd6a0c..6e9acf2a6f93fd9a2b05c13bca03779e6c17363e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,6 +23,7 @@
 ***/
 
 #include <dirent.h>
+
 #include "bootchart.h"
 
 double gettime_ns(void);
index 2bf473ffc18a2dcb4aed0133ce7834776fbbb5f8..f2af5350617ae754357a5b2a39b892e4b68c21a7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -37,6 +35,7 @@
 #include "fileio.h"
 #include "list.h"
 #include "macro.h"
+#include "stdio-util.h"
 #include "store.h"
 #include "svg.h"
 #include "utf8.h"
@@ -171,7 +170,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
 
                 strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
                 rootbdev[3] = '\0';
-                snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
+                xsprintf(filename, "/sys/block/%s/device/model", rootbdev);
 
                 r = read_one_line_file(filename, &model);
                 if (r < 0)
index 75efa226149eeab90b703661381b9847fcb9992b..6e06b5ad979d14fb39c2f8a737ed005f189dcebf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 6a7134644fda775d57bc8d3ab5d64993407777f0..b6bd6eb3904403ace80827319ebb77d8bcfd366c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index debd58ce8b565f269cc4f53ed5808e51d0073f4c..8943e0dc12521df9d381ecec4ed0b07389cb175b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8f0ab8f17ff08434f2dd30c8c012eef1b22e7119..3dcddaa0486a0d69fa29ab50a3d9c31d169e9e1d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 #include <pthread.h>
 
-#include "list.h"
 #include "hashmap.h"
+#include "list.h"
 
 typedef enum PolicyItemType {
         _POLICY_ITEM_TYPE_UNSET = 0,
index 2e8bd83efde9a8ba6c7cece46980b45c01079148..1af5c310ea1f32a020d678ec190a9d34c0414ee7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,7 +38,7 @@
 #include "util.h"
 
 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         int r;
 
         assert(bus);
@@ -75,7 +73,7 @@ static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, s
 }
 
 static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         ProxyActivation *activation = userdata;
 
         /*
@@ -239,9 +237,9 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_reply_method_return(m, NULL);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!sd_bus_message_has_signature(m, "s"))
                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
@@ -305,9 +303,9 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_driver_send(m->bus, reply);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!sd_bus_message_has_signature(m, "s"))
                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
@@ -330,8 +328,8 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_driver_send(m->bus, reply);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!sd_bus_message_has_signature(m, "s"))
                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
@@ -346,8 +344,8 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!sd_bus_message_has_signature(m, "s"))
                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
@@ -376,8 +374,8 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
                 const char *name;
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!sd_bus_message_has_signature(m, "s"))
                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
@@ -439,7 +437,7 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 };
                 struct kdbus_info *name_list, *name;
                 _cleanup_strv_free_ char **owners = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 char *arg0;
                 int err = 0;
 
@@ -610,7 +608,7 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
-                _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
                 ProxyActivation *activation;
                 const char *name;
                 uint64_t cookie;
@@ -674,7 +672,7 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return 1;
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
-                _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
                 _cleanup_strv_free_ char **args = NULL;
 
                 if (!sd_bus_message_has_signature(m, "a{ss}"))
@@ -738,7 +736,7 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m,
                 return synthetic_reply_method_return(m, NULL);
 
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
 
index da3834f8b05a707f9359cdd25999c5a25c7b1e6f..1630cdc7b91d6f60bffd797787adcfeee478cec5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "bus-xml-policy.h"
 #include "proxy.h"
 
index db399b24f26d41d7685c2210d4cba4e3dbe949c8..907d93d4c7c34a30873aa0b8fc56e297a0d15f0e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -49,7 +47,7 @@
 #include "util.h"
 
 static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
-        _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
         int r;
 
         r = sd_bus_new(&b);
@@ -491,7 +489,7 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
                 (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
 
                 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
-                        _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
+                        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *sender_creds = NULL;
 
                         /* If the message came from another legacy
                          * client, then the message creds will be
@@ -522,7 +520,7 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
         }
 
         if (to->is_kernel) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *destination_creds = NULL;
                 uid_t destination_uid = UID_INVALID;
                 gid_t destination_gid = GID_INVALID;
                 const char *destination_unique = NULL;
@@ -609,7 +607,7 @@ static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPol
 }
 
 static int process_hello(Proxy *p, sd_bus_message *m) {
-        _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
         bool is_hello;
         int r;
 
@@ -723,7 +721,7 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) {
 }
 
 static int proxy_process_destination_to_local(Proxy *p) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         bool matched, matched_synthetic;
         int r;
 
@@ -832,7 +830,7 @@ static int proxy_process_destination_to_local(Proxy *p) {
 }
 
 static int proxy_process_local_to_destination(Proxy *p) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(p);
index 7b2e5d422fe017f58b921af11b53d1ea32c66b4c..d9e75cf73b18db8f49febcb688480f2df7f896a6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 2dc5fe631bbc5ff3c8d53b127d09255bc9c3ae51..291c1b09e342f794d7ddc0a55e178edd3a18bd48 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -146,7 +144,7 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int rename_service(sd_bus *a, sd_bus *b) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         _cleanup_free_ char *p = NULL, *name = NULL;
         const char *comm;
         char **cmdline;
index 7f1f9dc28d68309ae3093b0a9abd213f3b1220fe..8eea7dc5b956d3bd49694b05ab79fa97dbdb0fd8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -50,7 +48,7 @@ int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
 }
 
 int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(call);
@@ -66,7 +64,7 @@ int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
 }
 
 int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         va_list ap;
 
         va_start(ap, format);
@@ -77,7 +75,7 @@ int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const
 }
 
 int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
 
         assert(call);
 
@@ -93,7 +91,7 @@ int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_e
 }
 
 int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) {
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
         va_list ap;
 
         assert(call);
@@ -109,7 +107,7 @@ int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *f
 }
 
 int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(call);
@@ -135,7 +133,7 @@ int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...)
 }
 
 int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(call);
@@ -155,7 +153,7 @@ int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
 }
 
 int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
-        _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
         const char *name, *old_owner, *new_owner;
         int r;
 
index ddfe2fd2663ab8ce8668c632404fa9adb9ebae7c..1b7197f8ecee3d62fad099aef2f9285584c1aa15 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 1f465edd9178ec566abb43b0fe04b330c31df916..af7c9128a29cac1ac88cfe7b896284b0b0fd0d18 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 22efc58ac9991c0fe660ede2ceefdb7768be7017..b839fadd047af917964d7bc5b7177cb0cfceaeeb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -123,15 +121,17 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int get_cgroup_root(char **ret) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *unit = NULL, *path = NULL;
         const char *m;
         int r;
 
         if (!arg_machine) {
                 r = cg_get_root_path(ret);
-                if (r < 0)
+                if (r == -ENOMEDIUM)
+                        return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup");
+                else if (r < 0)
                         return log_error_errno(r, "Failed to get root control group path: %m");
 
                 return 0;
index e48234f07562d568217d53213c5f80ffbdd8b24f..aadfba0707dfb1c029f3ee95b66f4b62229e0927 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -27,7 +25,7 @@
 #include "log.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         if (argc != 2) {
index eea8aea76bc248f3968e67d7f928e6193e585b52..60d6da3246ea6c4fcf73e87663d38635985ca3c8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,6 +38,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "stdio-util.h"
 #include "terminal-util.h"
 #include "unit-name.h"
 #include "util.h"
@@ -565,9 +564,9 @@ static void display(Hashmap *a) {
         }
 
         if (arg_cpu_type == CPU_PERCENT)
-                snprintf(buffer, sizeof(buffer), "%6s", "%CPU");
+                xsprintf(buffer, "%6s", "%CPU");
         else
-                snprintf(buffer, sizeof(buffer), "%*s", maxtcpu, "CPU Time");
+                xsprintf(buffer, "%*s", maxtcpu, "CPU Time");
 
         rows = lines();
         if (rows <= 10)
@@ -841,8 +840,8 @@ static const char* counting_what(void) {
 }
 
 static int get_cgroup_root(char **ret) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *unit = NULL, *path = NULL;
         const char *m;
         int r;
index 0a484d89fc427663993d2296942e71085ecde97b..76afe3fe15ad8aefa39bb9909172b6964e22abc7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8b58289dc5403a2fa00c956322ad5ea818930c97..0eccb592107a291e0a140851a6d556f47753e115 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 85b7b4e8426f59cc4a5db9513d327dcebc187c27..5dc6fd98e7e3ad396ce9158fef4d519090b28255 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -702,7 +700,7 @@ static int automount_start_expire(Automount *a) {
 }
 
 static void automount_enter_runnning(Automount *a) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         struct stat st;
         int r;
 
@@ -728,7 +726,15 @@ static void automount_enter_runnning(Automount *a) {
         if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
                 log_unit_info(UNIT(a), "Automount point already active?");
         else {
-                r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
+                Unit *trigger;
+
+                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;
@@ -744,6 +750,7 @@ fail:
 
 static int automount_start(Unit *u) {
         Automount *a = AUTOMOUNT(u);
+        Unit *trigger;
 
         assert(a);
         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
@@ -753,8 +760,11 @@ static int automount_start(Unit *u) {
                 return -EEXIST;
         }
 
-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+        trigger = UNIT_TRIGGER(u);
+        if (!trigger || trigger->load_state != UNIT_LOADED) {
+                log_unit_error(u, "Refusing to start, unit to trigger not loaded.");
                 return -ENOENT;
+        }
 
         a->result = AUTOMOUNT_SUCCESS;
         automount_enter_waiting(a);
@@ -897,10 +907,11 @@ static bool automount_check_gc(Unit *u) {
 }
 
 static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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;
 
         assert(a);
@@ -973,7 +984,13 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
                         break;
                 }
 
-                r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
+                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_STOP, trigger, JOB_REPLACE, &error, NULL);
                 if (r < 0) {
                         log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                         goto fail;
index 43ea9f772d7fec6dba4a8b459c42c0244677fd50..cf5b1cf99461e5e4dd24cb86f489620ff5024a8a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4a31f4c4be956157f0e3dc7f183ab94bee4831c6..f2fbc4701c63285b1614ee1c85a03c703ab49cf2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -24,8 +22,8 @@
 typedef struct BusEndpoint BusEndpoint;
 typedef struct BusEndpointPolicy BusEndpointPolicy;
 
-#include "hashmap.h"
 #include "bus-policy.h"
+#include "hashmap.h"
 
 struct BusEndpointPolicy {
         char *name;
index 3b04f5457a7179089fbce3f575604573920b484d..5b2c4d59532a939a847067ac30f6408f6d6b4bc5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,9 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "kdbus.h"
 #include "list.h"
 #include "macro.h"
-#include "kdbus.h"
 
 typedef struct BusNamePolicy BusNamePolicy;
 
index 04fa12a4da9938ec047ed8a855d8c41d4da54507..de2a21ccdec56bf0b36159bcade684059c635f6c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -112,29 +110,27 @@ static void busname_done(Unit *u) {
         n->timer_event_source = sd_event_source_unref(n->timer_event_source);
 }
 
-static int busname_arm_timer(BusName *n) {
+static int busname_arm_timer(BusName *n, usec_t usec) {
         int r;
 
         assert(n);
 
-        if (n->timeout_usec <= 0) {
-                n->timer_event_source = sd_event_source_unref(n->timer_event_source);
-                return 0;
-        }
-
         if (n->timer_event_source) {
-                r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
+                r = sd_event_source_set_time(n->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(n)->manager->event,
                         &n->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + n->timeout_usec, 0,
+                        usec, 0,
                         busname_dispatch_timer, n);
         if (r < 0)
                 return r;
@@ -372,7 +368,7 @@ static int busname_coldplug(Unit *u) {
                 if (r < 0)
                         return r;
 
-                r = busname_arm_timer(n);
+                r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec));
                 if (r < 0)
                         return r;
         }
@@ -397,7 +393,7 @@ static int busname_make_starter(BusName *n, pid_t *_pid) {
         pid_t pid;
         int r;
 
-        r = busname_arm_timer(n);
+        r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
         if (r < 0)
                 goto fail;
 
@@ -475,7 +471,7 @@ static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f
         }
 
         if (r > 0) {
-                r = busname_arm_timer(n);
+                r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
                 if (r < 0) {
                         log_unit_warning_errno(UNIT(n), r, "Failed to arm timer: %m");
                         goto fail;
@@ -557,7 +553,7 @@ fail:
 }
 
 static void busname_enter_running(BusName *n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool pending = false;
         Unit *other;
         Iterator i;
@@ -947,7 +943,6 @@ static void busname_reset_failed(Unit *u) {
 
 static void busname_trigger_notify(Unit *u, Unit *other) {
         BusName *n = BUSNAME(u);
-        Service *s;
 
         assert(n);
         assert(other);
@@ -955,36 +950,43 @@ static void busname_trigger_notify(Unit *u, Unit *other) {
         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
                 return;
 
-        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+        if (other->start_limit_hit) {
+                busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT);
                 return;
+        }
 
-        s = SERVICE(other);
+        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+                return;
 
-        if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
-                busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
-        else if (IN_SET(s->state,
-                        SERVICE_DEAD, SERVICE_FAILED,
-                        SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
-                        SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
-                        SERVICE_AUTO_RESTART))
+        if (IN_SET(SERVICE(other)->state,
+                   SERVICE_DEAD, SERVICE_FAILED,
+                   SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
+                   SERVICE_AUTO_RESTART))
                 busname_enter_listening(n);
+
+        if (SERVICE(other)->state == SERVICE_RUNNING)
+                busname_set_state(n, BUSNAME_RUNNING);
 }
 
 static int busname_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, BUSNAME(u)->control_pid, error);
 }
 
-static int busname_get_timeout(Unit *u, uint64_t *timeout) {
+static int busname_get_timeout(Unit *u, usec_t *timeout) {
         BusName *n = BUSNAME(u);
+        usec_t t;
         int r;
 
         if (!n->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(n->timer_event_source, timeout);
+        r = sd_event_source_get_time(n->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
@@ -1004,7 +1006,7 @@ static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
         [BUSNAME_FAILURE_EXIT_CODE] = "exit-code",
         [BUSNAME_FAILURE_SIGNAL] = "signal",
         [BUSNAME_FAILURE_CORE_DUMP] = "core-dump",
-        [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
+        [BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
index 46f7b6f097ab31bb688a6f984f6f58b0f1bbc4a2..6b6f6c62d4b28ed83203429332281647c376fb5c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -33,7 +31,7 @@ typedef enum BusNameResult {
         BUSNAME_FAILURE_EXIT_CODE,
         BUSNAME_FAILURE_SIGNAL,
         BUSNAME_FAILURE_CORE_DUMP,
-        BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT,
+        BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT,
         _BUSNAME_RESULT_MAX,
         _BUSNAME_RESULT_INVALID = -1
 } BusNameResult;
index d1221754171fd6f1ae07d7a9e3db4ed79c3d2978..39235a95f6029d3de96f1a37d521839fdd891511 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -53,8 +51,6 @@ void cgroup_context_init(CGroupContext *c) {
         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
 
         c->tasks_max = (uint64_t) -1;
-
-        c->netclass_type = CGROUP_NETCLASS_TYPE_NONE;
 }
 
 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
@@ -299,7 +295,7 @@ fail:
         return -errno;
 }
 
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) {
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
         bool is_root;
         int r;
 
@@ -497,17 +493,6 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, u
                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
                                        "Failed to set pids.max on %s: %m", path);
         }
-
-        if (mask & CGROUP_MASK_NET_CLS) {
-                char buf[DECIMAL_STR_MAX(uint32_t)];
-
-                sprintf(buf, "%" PRIu32, netclass);
-
-                r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
-                if (r < 0)
-                        log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
-                                       "Failed to set net_cls.classid on %s: %m", path);
-        }
 }
 
 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
@@ -540,9 +525,6 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
             c->tasks_max != (uint64_t) -1)
                 mask |= CGROUP_MASK_PIDS;
 
-        if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE)
-                mask |= CGROUP_MASK_NET_CLS;
-
         return mask;
 }
 
@@ -910,103 +892,6 @@ static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) {
         return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
 }
 
-static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) {
-
-        uint32_t start, i;
-        Manager *m;
-
-        assert(u);
-
-        m = u->manager;
-
-        i = start = m->cgroup_netclass_registry_last;
-
-        do {
-                i++;
-
-                if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) {
-                        m->cgroup_netclass_registry_last = i;
-                        *ret = i;
-                        return 0;
-                }
-
-                if (i == UINT32_MAX)
-                        i = CGROUP_NETCLASS_FIXED_MAX;
-
-        } while (i != start);
-
-        return -ENOBUFS;
-}
-
-int unit_add_to_netclass_cgroup(Unit *u) {
-
-        CGroupContext *cc;
-        Unit *first;
-        void *key;
-        int r;
-
-        assert(u);
-
-        cc = unit_get_cgroup_context(u);
-        if (!cc)
-                return 0;
-
-        switch (cc->netclass_type) {
-        case CGROUP_NETCLASS_TYPE_NONE:
-                return 0;
-
-        case CGROUP_NETCLASS_TYPE_FIXED:
-                u->cgroup_netclass_id = cc->netclass_id;
-                break;
-
-        case CGROUP_NETCLASS_TYPE_AUTO:
-                /* Allocate a new ID in case it was requested and not done yet */
-                if (u->cgroup_netclass_id == 0) {
-                        r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id);
-                        if (r < 0)
-                                return r;
-
-                        log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id);
-                }
-
-                break;
-        }
-
-        r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops);
-        if (r < 0)
-                return r;
-
-        key = UINT32_TO_PTR(u->cgroup_netclass_id);
-        first = hashmap_get(u->manager->cgroup_netclass_registry, key);
-
-        if (first) {
-                LIST_PREPEND(cgroup_netclass, first, u);
-                return hashmap_replace(u->manager->cgroup_netclass_registry, key, u);
-        }
-
-        return hashmap_put(u->manager->cgroup_netclass_registry, key, u);
-}
-
-int unit_remove_from_netclass_cgroup(Unit *u) {
-
-        Unit *head;
-        void *key;
-
-        assert(u);
-
-        key = UINT32_TO_PTR(u->cgroup_netclass_id);
-
-        LIST_FIND_HEAD(cgroup_netclass, u, head);
-        LIST_REMOVE(cgroup_netclass, head, u);
-
-        if (head)
-                return hashmap_replace(u->manager->cgroup_netclass_registry, key, head);
-
-        hashmap_remove(u->manager->cgroup_netclass_registry, key);
-
-        return 0;
-}
-
 /* Check if necessary controllers and attributes for a unit are in place.
  *
  * If so, do nothing.
@@ -1042,7 +927,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
                 return r;
 
         /* Finally, apply the necessary attributes. */
-        cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state);
+        cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state);
 
         return 0;
 }
index 457544b49f30b326dd5d5f78845b07a7bd2eee77..360bbca30ff1c1f2b1c6c1787b161952c4f84494 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include "list.h"
 #include "time-util.h"
 
-/* Maximum value for fixed (manual) net class ID assignment,
- * and also the value at which the range of automatic assignments starts
- */
-#define CGROUP_NETCLASS_FIXED_MAX UINT32_C(65535)
-
 typedef struct CGroupContext CGroupContext;
 typedef struct CGroupDeviceAllow CGroupDeviceAllow;
 typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
@@ -52,17 +45,6 @@ typedef enum CGroupDevicePolicy {
         _CGROUP_DEVICE_POLICY_INVALID = -1
 } CGroupDevicePolicy;
 
-typedef enum CGroupNetClassType {
-        /* Default - do not assign a net class */
-        CGROUP_NETCLASS_TYPE_NONE,
-
-        /* Automatically assign a net class */
-        CGROUP_NETCLASS_TYPE_AUTO,
-
-        /* Assign the net class that was provided by the user */
-        CGROUP_NETCLASS_TYPE_FIXED,
-} CGroupNetClassType;
-
 struct CGroupDeviceAllow {
         LIST_FIELDS(CGroupDeviceAllow, device_allow);
         char *path;
@@ -104,21 +86,18 @@ struct CGroupContext {
         CGroupDevicePolicy device_policy;
         LIST_HEAD(CGroupDeviceAllow, device_allow);
 
-        CGroupNetClassType netclass_type;
-        uint32_t netclass_id;
-
         uint64_t tasks_max;
 
         bool delegate;
 };
 
-#include "unit.h"
 #include "cgroup-util.h"
+#include "unit.h"
 
 void cgroup_context_init(CGroupContext *c);
 void cgroup_context_done(CGroupContext *c);
 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix);
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass_id, ManagerState state);
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state);
 
 CGroupMask cgroup_context_get_mask(CGroupContext *c);
 
@@ -146,9 +125,6 @@ int unit_watch_cgroup(Unit *u);
 
 int unit_attach_pids_to_cgroup(Unit *u);
 
-int unit_add_to_netclass_cgroup(Unit *u);
-int unit_remove_from_netclass_cgroup(Unit *u);
-
 int manager_setup_cgroup(Manager *m);
 void manager_shutdown_cgroup(Manager *m, bool delete);
 
index 54830a515b83396aedf6b63610d7fd660a41a9ec..b2806ad86f01ab5c4d4a4133cd4dba1ae6924d6f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index a2b124d756ed2898248114e600d7f8507772003b..7b51eb973a5d85b75b7706d387a2994c26a849e6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 445b237643196bf9ce9574b736a71e9f2e5a97e9..cf816ba15be48ecc7448b5619282236ab06d7d12 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ea55b6c8c9c2407d0bf302f4a82d887ad1abbb40..8643d1a4047e3be72f4fc1836d864a6079b6bfe7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3fd295baa918dcad83079ec2e0c6416683ca2a7c..859d155ec1daf375e275ab49dcd26ac962fa1a95 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 9dc187c066a25414cb2aed8beb210511beebf6d1..b2212fe44e4d35817fddf16af3c195a68cae0c07 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 97e4a4755603f33c63414faaf9d8444d1e9f0159..e1a12224d376d0657109199e8c6f8552c12dcf0f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 10e945e40214cc71d49abbc6c471cb1c16b301ce..eb1d8c3278eb2ef06fbe1ce41c4580820d48649e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 093179c003f2612af8aff284e001862a83ada58e..f2fc301f8e668007fb323d899f5e25ba75aea23b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -141,7 +139,7 @@ static int property_get_nice(
         else {
                 errno = 0;
                 n = getpriority(PRIO_PROCESS, 0);
-                if (errno != 0)
+                if (errno > 0)
                         n = 0;
         }
 
@@ -293,9 +291,25 @@ static int property_get_capability_bounding_set(
         assert(reply);
         assert(c);
 
-        /* We store this negated internally, to match the kernel, but
-         * we expose it normalized. */
-        return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
+        return sd_bus_message_append(reply, "t", c->capability_bounding_set);
+}
+
+static int property_get_ambient_capabilities(
+                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, "t", c->capability_ambient_set);
 }
 
 static int property_get_capabilities(
@@ -632,21 +646,37 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -673,6 +703,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         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),
         SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -802,7 +833,8 @@ int bus_exec_context_set_transient_property(
                 UnitSetPropertiesMode mode,
                 sd_bus_error *error) {
 
-        int r;
+        const char *soft = NULL;
+        int r, ri;
 
         assert(u);
         assert(c);
@@ -1349,7 +1381,7 @@ int bus_exec_context_set_transient_property(
                                 dirs = &c->read_write_dirs;
                         else if (streq(name, "ReadOnlyDirectories"))
                                 dirs = &c->read_only_dirs;
-                        else if (streq(name, "InaccessibleDirectories"))
+                        else /* "InaccessibleDirectories" */
                                 dirs = &c->inaccessible_dirs;
 
                         if (strv_length(l) == 0) {
@@ -1459,7 +1491,23 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
 
-        } else if (rlimit_from_string(name) >= 0) {
+        }
+
+        ri = rlimit_from_string(name);
+        if (ri < 0) {
+                soft = endswith(name, "Soft");
+                if (soft) {
+                        const char *n;
+
+                        n = strndupa(name, soft - name);
+                        ri = rlimit_from_string(n);
+                        if (ri >= 0)
+                                name = n;
+
+                }
+        }
+
+        if (ri >= 0) {
                 uint64_t rl;
                 rlim_t x;
 
@@ -1477,22 +1525,36 @@ int bus_exec_context_set_transient_property(
                 }
 
                 if (mode != UNIT_CHECK) {
-                        int z;
-
-                        z = rlimit_from_string(name);
+                        _cleanup_free_ char *f = NULL;
+                        struct rlimit nl;
+
+                        if (c->rlimit[ri]) {
+                                nl = *c->rlimit[ri];
+
+                                if (soft)
+                                        nl.rlim_cur = x;
+                                else
+                                        nl.rlim_max = x;
+                        } else
+                                /* When the resource limit is not initialized yet, then assign the value to both fields */
+                                nl = (struct rlimit) {
+                                        .rlim_cur = x,
+                                        .rlim_max = x,
+                                };
+
+                        r = rlimit_format(&nl, &f);
+                        if (r < 0)
+                                return r;
 
-                        if (!c->rlimit[z]) {
-                                c->rlimit[z] = new(struct rlimit, 1);
-                                if (!c->rlimit[z])
+                        if (c->rlimit[ri])
+                                *c->rlimit[ri] = nl;
+                        else {
+                                c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
+                                if (!c->rlimit[ri])
                                         return -ENOMEM;
                         }
 
-                        c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
-
-                        if (x == RLIM_INFINITY)
-                                unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
-                        else
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
+                        unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, f);
                 }
 
                 return 1;
index c44517ea2271a104d75c209c579f33504fb8aefd..d0aa8e1dd572ddf61e2dc722f6c09096f6694cbd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8c30d6625000a148c8f743d58434591af5f704f4..97a93fb2f1573cbb83cf53ebafde5084f49b9542 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -93,7 +91,7 @@ const sd_bus_vtable bus_job_vtable[] = {
 };
 
 static int send_new_signal(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
         Job *j = userdata;
         int r;
@@ -153,7 +151,7 @@ void bus_job_send_change_signal(Job *j) {
 }
 
 static int send_removed_signal(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
         Job *j = userdata;
         int r;
index 0f2fbe2ee2930d78466018cb84a431276deea49a..024d06719ea89311b0e898fe94cecb0c6b12c322 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index c633eb1b762bc9f17b14421dae0604d9f2b80ac7..fc50fafaad272e48c787a76b1ff7166d4055aeaf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 794c402048adf3c663cad1747e717908b40d48c0..b9b18811e3cf221f1f5c184e2abd8c8025ebd572 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 #include "sd-bus.h"
 
-#include "unit.h"
 #include "kill.h"
+#include "unit.h"
 
 extern const sd_bus_vtable bus_kill_vtable[];
 
index 4d730290b2fb008885d7c04f31039e9326b73b08..f939196397bb69bf49233e262b510da30e88eb94 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -229,7 +227,10 @@ static int property_set_log_level(
         if (r < 0)
                 return r;
 
-        return log_set_max_level_from_string(t);
+        r = log_set_max_level_from_string(t);
+        if (r == 0)
+                log_info("Setting log level to %s.", t);
+        return r;
 }
 
 static int property_get_n_names(
@@ -384,7 +385,7 @@ static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error
                 return r;
 
         if (isempty(name)) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 pid_t pid;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
@@ -436,7 +437,7 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
 
         if (pid == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -479,7 +480,7 @@ static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_erro
                 return r;
 
         if (isempty(name)) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 pid_t pid;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
@@ -630,9 +631,13 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s
         if (r < 0)
                 return r;
 
-        u = manager_get_unit(m, name);
-        if (!u)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+        r = manager_load_unit(m, name, NULL, error, &u);
+        if (r < 0)
+                return r;
+
+        r = bus_unit_check_load_state(u, error);
+        if (r < 0)
+                return r;
 
         return bus_unit_method_set_properties(message, u, error);
 }
@@ -861,7 +866,7 @@ static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_e
 }
 
 static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         const char *k;
         Iterator i;
@@ -949,7 +954,7 @@ static int method_list_units_filtered(sd_bus_message *message, void *userdata, s
 }
 
 static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Iterator i;
         Job *j;
@@ -1437,7 +1442,7 @@ static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_
 }
 
 static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         UnitFileList *item;
         Hashmap *h;
@@ -1543,7 +1548,7 @@ static int method_get_default_target(sd_bus_message *message, void *userdata, sd
 }
 
 static int send_unit_files_changed(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
         int r;
 
         assert(bus);
@@ -1562,7 +1567,7 @@ static int reply_unit_file_changes_and_free(
                 UnitFileChange *changes,
                 unsigned n_changes) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         unsigned i;
         int r;
 
@@ -1600,6 +1605,7 @@ static int reply_unit_file_changes_and_free(
         if (r < 0)
                 goto fail;
 
+        unit_file_changes_free(changes, n_changes);
         return sd_bus_send(NULL, reply, NULL);
 
 fail:
@@ -1836,8 +1842,10 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata,
         scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
         r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
-        if (r < 0)
+        if (r < 0) {
+                unit_file_changes_free(changes, n_changes);
                 return r;
+        }
 
         return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
 }
@@ -1935,21 +1943,37 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitCPUSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitDATASoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitCORESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitRSSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitASSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitNICESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
 
@@ -2019,7 +2043,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
 };
 
 static int send_finished(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
         usec_t *times = userdata;
         int r;
 
@@ -2067,7 +2091,7 @@ void bus_manager_send_finished(
 }
 
 static int send_reloading(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
         int r;
 
         assert(bus);
index 5bdf6e17ab6be4a14832258a37a90f01e0408f3b..36a2e9481b11b924219579b3158a6e2fc59a69ab 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index bc5751a10d4f5d91e3f68f8247cb514d4edd523a..935db7c48ba11c2975b650f218cd030c31e8acb1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index dd0bf51bb0afcc05f99f9d62e5b3fd9b55fe6369..ec16166d369906b851eb40b451b523ff9399832a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index e0544e9161d90eeeb823dac67c9557ac3dc92ae1..1e153e503fecad7c6035ef3460a748a087c25a3b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 389b0d7f9b8a3cb850076b20ed5165dc563d59d4..d3c19e0c2b0f57b3e1060e00948eff8f12c705bb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 16375b2311b755f8585c7d33941ccf117c990d54..34ee9a8fa995776d11fa0d0e45f175e1e8fa8140 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -205,7 +203,7 @@ int bus_scope_commit_properties(Unit *u) {
 }
 
 int bus_scope_send_request_stop(Scope *s) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
         int r;
 
index 33beda47b77d46f7043230ecafa3325890b27063..270306f5081b9b6bee3d67b0abaa983f6afd5ea7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_scope_vtable[];
index 24f611a593e8fd465913565feb1c15e72c2e02f8..03eecca911ee4a3968f677f98195e9cdbdbd399d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -49,12 +47,14 @@ const sd_bus_vtable bus_service_vtable[] = {
         SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
-        SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
+        /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
+        SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
         SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -124,6 +124,19 @@ static int bus_service_set_transient_property(
                         unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
                 }
 
+                return 1;
+        } else if (streq(name, "RuntimeMaxUSec")) {
+                usec_t u;
+
+                r = sd_bus_message_read(message, "t", &u);
+                if (r < 0)
+                        return r;
+
+                if (mode != UNIT_CHECK) {
+                        s->runtime_max_usec = u;
+                        unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us\n", u);
+                }
+
                 return 1;
 
         } else if (STR_IN_SET(name,
@@ -153,6 +166,8 @@ static int bus_service_set_transient_property(
                                 asynchronous_close(s->stderr_fd);
                                 s->stderr_fd = copy;
                         }
+
+                        s->exec_context.stdio_as_fds = true;
                 }
 
                 return 1;
index aab9f7aa264a74827c6cce5020cf530e1f74921a..769a53769ed04209872df780d2f3efcce97785ef 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_service_vtable[];
index 469e3e1c937e4dea9ce4d86180f59a2c323e0cf6..e37f50b2835d55b2c12cdbf38ba6b5d9abf7eeac 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index eadc3b1a9cb2d3998682d5dfb70726d8981f530b..52ceebb135bc01d5f76b39ffc1d95c745c842475 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_slice_vtable[];
index be5ef261a654283335f3192df513997cf138fb9a..d33e494f6bab066e67d94edb8dbd38cbf460042a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -150,6 +148,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
         SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0),
         SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0),
         SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0),
+        SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST),
         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
index 17164d98713266d0e130c3f2a3743dd9cbc5c4b7..7a792c7a895407b6ab5fb1501d8374ae14c74dc4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_socket_vtable[];
index f2a0f1d172a4eb5661642834737a5476780ac47b..292f8738c684a828c48d5556dc8ec60b7f2a8f15 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 9469f68ab89486618618978ccdafa533b3604517..5238471f981f43ed8ff8de5c5532a6584212fabc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_swap_vtable[];
index 654bcf1a297b399f171a567d8ceba41e0437cce2..6858b1ce72bf73f4f8776c89d57b187e812bf2d1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6be9c9f7084d0c4c976d14950070962e629f4bda..9be5ce06b72e89fb4bf32baa635615959c25f286 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 2e6c479c3a7cefe4bc15d90558fd61302597b1d8..bc121b83a27ac4143c864090e7481c067c8cd5bb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -180,6 +178,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
         BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -266,19 +265,33 @@ static int bus_timer_set_transient_property(
 
                 return 1;
 
-        } else if (streq(name, "AccuracySec")) {
-
+        } else if (STR_IN_SET(name, "AccuracyUSec", "AccuracySec")) {
                 usec_t u = 0;
 
+                if (streq(name, "AccuracySec"))
+                        log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
+
                 r = sd_bus_message_read(message, "t", &u);
                 if (r < 0)
                         return r;
 
                 if (mode != UNIT_CHECK) {
-                        char time[FORMAT_TIMESPAN_MAX];
-
                         t->accuracy_usec = u;
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+                        unit_write_drop_in_private_format(UNIT(t), mode, name, "AccuracySec=" USEC_FMT "us\n", u);
+                }
+
+                return 1;
+
+        } else if (streq(name, "RandomizedDelayUSec")) {
+                usec_t u = 0;
+
+                r = sd_bus_message_read(message, "t", &u);
+                if (r < 0)
+                        return r;
+
+                if (mode != UNIT_CHECK) {
+                        t->random_usec = u;
+                        unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=" USEC_FMT "us\n", u);
                 }
 
                 return 1;
index 103172f05577edcb97bb19366a0edb927ee35774..39053dc4a2320b08ae974fb285c9a4082c62c832 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_timer_vtable[];
index d9b7382c82b082b1b8913079303a7260477d5072..b351f6a2c20394468aebc71d93e8edd17a9bcded 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -399,7 +397,7 @@ static int property_get_load_error(
                 void *userdata,
                 sd_bus_error *error) {
 
-        _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
         Unit *u = userdata;
 
         assert(bus);
@@ -458,7 +456,10 @@ int bus_unit_method_start_generic(
         assert(u);
         assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
 
-        r = mac_selinux_unit_access_check(u, message, job_type == JOB_STOP ? "stop" : "start", error);
+        r = mac_selinux_unit_access_check(
+                        u, message,
+                        job_type_to_access_method(job_type),
+                        error);
         if (r < 0)
                 return r;
 
@@ -671,6 +672,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
         SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -699,7 +701,10 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
         SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("NetClass", "u", NULL, offsetof(Unit, cgroup_netclass_id), 0),
+        SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
 
         SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -846,7 +851,7 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
 };
 
 static int send_new_signal(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
         Unit *u = userdata;
         int r;
@@ -923,7 +928,7 @@ void bus_unit_send_change_signal(Unit *u) {
 }
 
 static int send_removed_signal(sd_bus *bus, void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
         Unit *u = userdata;
         int r;
@@ -983,19 +988,20 @@ int bus_unit_queue_job(
         assert(type >= 0 && type < _JOB_TYPE_MAX);
         assert(mode >= 0 && mode < _JOB_MODE_MAX);
 
+        r = mac_selinux_unit_access_check(
+                        u, message,
+                        job_type_to_access_method(type),
+                        error);
+        if (r < 0)
+                return r;
+
         if (reload_if_possible && unit_can_reload(u)) {
                 if (type == JOB_RESTART)
                         type = JOB_RELOAD_OR_START;
                 else if (type == JOB_TRY_RESTART)
-                        type = JOB_RELOAD;
+                        type = JOB_TRY_RELOAD;
         }
 
-        r = mac_selinux_unit_access_check(
-                        u, message,
-                        (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
-                        type == JOB_STOP ? "stop" : "reload", error);
-        if (r < 0)
-                return r;
 
         if (type == JOB_STOP &&
             (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
@@ -1251,3 +1257,20 @@ int bus_unit_set_properties(
 
         return n;
 }
+
+int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
+
+        if (u->load_state == UNIT_LOADED)
+                return 0;
+
+        /* Give a better description of the unit error when
+         * possible. Note that in the case of UNIT_MASKED, load_error
+         * is not set. */
+        if (u->load_state == UNIT_MASKED)
+                return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
+
+        if (u->load_state == UNIT_NOT_FOUND)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
+
+        return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id);
+}
index b622e0ae8d02de9bfcbd1fc6e2810decda07c897..07948b9cd05c9c23ca19b56539d2b7066874d4ce 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "unit.h"
 
 extern const sd_bus_vtable bus_unit_vtable[];
@@ -37,3 +36,5 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus
 int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error);
 int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
 int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error);
+
+int bus_unit_check_load_state(Unit *u, sd_bus_error *error);
index 7932130036aa8148e0351ed0806b3e1955840ef6..413489373fd5994cc44e9db21b039a4054c426b9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -74,7 +72,7 @@ int bus_send_queued_message(Manager *m) {
 }
 
 static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         const char *cgroup, *me;
         Manager *m = userdata;
         uid_t sender_uid;
@@ -146,8 +144,8 @@ static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_e
 }
 
 static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         const char *name;
         Unit *u;
@@ -245,7 +243,7 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er
         }
 
         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 pid_t pid;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
@@ -304,7 +302,7 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
         assert(path);
 
         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -617,7 +615,7 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
 }
 
 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         _cleanup_close_ int nfd = -1;
         Manager *m = userdata;
         sd_id128_t id;
@@ -734,9 +732,11 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
         return 0;
 }
 
-static int bus_list_names(Manager *m, sd_bus *bus) {
+int manager_sync_bus_names(Manager *m, sd_bus *bus) {
         _cleanup_strv_free_ char **names = NULL;
-        char **i;
+        const char *name;
+        Iterator i;
+        Unit *u;
         int r;
 
         assert(m);
@@ -746,15 +746,55 @@ static int bus_list_names(Manager *m, sd_bus *bus) {
         if (r < 0)
                 return log_error_errno(r, "Failed to get initial list of names: %m");
 
-        /* This is a bit hacky, we say the owner of the name is the
-         * name itself, because we don't want the extra traffic to
-         * figure out the real owner. */
-        STRV_FOREACH(i, names) {
-                Unit *u;
+        /* We have to synchronize the current bus names with the
+         * list of active services. To do this, walk the list of
+         * all units with bus names. */
+        HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
+                Service *s = SERVICE(u);
+
+                assert(s);
 
-                u = hashmap_get(m->watch_bus, *i);
-                if (u)
-                        UNIT_VTABLE(u)->bus_name_owner_change(u, *i, NULL, *i);
+                if (!streq_ptr(s->bus_name, name)) {
+                        log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
+                        continue;
+                }
+
+                /* Check if a service's bus name is in the list of currently
+                 * active names */
+                if (strv_contains(names, name)) {
+                        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                        const char *unique;
+
+                        /* 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);
+                                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);
+                                continue;
+                        }
+
+                        /* Now, let's compare that to the previous bus owner, and
+                         * if it's still the same, all is fine, so just don't
+                         * bother the service. Otherwise, the name has apparently
+                         * changed, so synthesize a name owner changed signal. */
+
+                        if (!streq_ptr(unique, s->bus_name_owner))
+                                UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique);
+                } else {
+                        /* So, the name we're watching is not on the bus.
+                         * This either means it simply hasn't appeared yet,
+                         * or it was lost during the daemon reload.
+                         * Check if the service has a stored name owner,
+                         * and synthesize a name loss signal in this case. */
+
+                        if (s->bus_name_owner)
+                                UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL);
+                }
         }
 
         return 0;
@@ -808,14 +848,16 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
         if (r < 0)
                 return log_error_errno(r, "Failed to register name: %m");
 
-        bus_list_names(m, bus);
+        r = manager_sync_bus_names(m, bus);
+        if (r < 0)
+                return r;
 
         log_debug("Successfully connected to API bus.");
         return 0;
 }
 
 static int bus_init_api(Manager *m) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         int r;
 
         if (m->api_bus)
@@ -883,7 +925,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) {
 }
 
 static int bus_init_system(Manager *m) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         int r;
 
         if (m->system_bus)
index 4f06ad11c41818a44948fbad97b8cd67988480ed..e16a84fbb87e88905acc4e54e2f10db960ef89e7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -34,6 +32,8 @@ void bus_track_serialize(sd_bus_track *t, FILE *f);
 int bus_track_deserialize_item(char ***l, const char *line);
 int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l);
 
+int manager_sync_bus_names(Manager *m, sd_bus *bus);
+
 int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
 
 int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
index bcd4d1146bec44bb9a44c9ebf4ad75c26e0dba63..d201dc5e4bb225023fbda06e57d951e407fdd126 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -267,7 +265,7 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
         assert(u);
         assert(dev);
 
-        property = u->manager->running_as == MANAGER_USER ? "MANAGER_USER_WANTS" : "SYSTEMD_WANTS";
+        property = u->manager->running_as == MANAGER_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
         wants = udev_device_get_property_value(dev, property);
         if (!wants)
                 return 0;
@@ -315,12 +313,19 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
 
         u = manager_get_unit(m, e);
 
-        if (u &&
-            sysfs &&
-            DEVICE(u)->sysfs &&
-            !path_equal(DEVICE(u)->sysfs, sysfs)) {
-                log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
-                return -EEXIST;
+        /* The device unit can still be present even if the device was
+         * unplugged: a mount unit can reference it hence preventing
+         * the GC to have garbaged it. That's desired since the device
+         * unit may have a dependency on the mount unit which was
+         * added during the loading of the later. */
+        if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
+                /* This unit is in plugged state: we're sure it's
+                 * attached to a device. */
+                if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
+                        log_unit_error(u, "Dev %s appeared twice with different sysfs paths %s and %s",
+                                       e, DEVICE(u)->sysfs, sysfs);
+                        return -EEXIST;
+                }
         }
 
         if (!u) {
index da8737870b00cb3b9301e6e77470cfc1a724c159..184a1a349b269904872e3d87a2d350df0e12c98d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 07979bf8b30934aa6cb245d2fbf0f93d0f162051..1e4630182dddc8c71eb02c5c34fffaa0875948de 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -183,26 +181,41 @@ static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
         return 0;
 }
 
-_pure_ static const char *tty_path(const ExecContext *context) {
+static const char *exec_context_tty_path(const ExecContext *context) {
         assert(context);
 
+        if (context->stdio_as_fds)
+                return NULL;
+
         if (context->tty_path)
                 return context->tty_path;
 
         return "/dev/console";
 }
 
-static void exec_context_tty_reset(const ExecContext *context) {
+static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
+        const char *path;
+
         assert(context);
 
-        if (context->tty_vhangup)
-                terminal_vhangup(tty_path(context));
+        path = exec_context_tty_path(context);
+
+        if (context->tty_vhangup) {
+                if (p && p->stdin_fd >= 0)
+                        (void) terminal_vhangup_fd(p->stdin_fd);
+                else if (path)
+                        (void) terminal_vhangup(path);
+        }
 
-        if (context->tty_reset)
-                reset_terminal(tty_path(context));
+        if (context->tty_reset) {
+                if (p && p->stdin_fd >= 0)
+                        (void) reset_terminal_fd(p->stdin_fd, true);
+                else if (path)
+                        (void) reset_terminal(path);
+        }
 
-        if (context->tty_vt_disallocate && context->tty_path)
-                vt_disallocate(context->tty_path);
+        if (context->tty_vt_disallocate && path)
+                (void) vt_disallocate(path);
 }
 
 static bool is_terminal_output(ExecOutput o) {
@@ -400,7 +413,7 @@ static int setup_input(
         case EXEC_INPUT_TTY_FAIL: {
                 int fd, r;
 
-                fd = acquire_terminal(tty_path(context),
+                fd = acquire_terminal(exec_context_tty_path(context),
                                       i == EXEC_INPUT_TTY_FAIL,
                                       i == EXEC_INPUT_TTY_FORCE,
                                       false,
@@ -485,7 +498,7 @@ static int setup_output(
         } else if (o == EXEC_OUTPUT_INHERIT) {
                 /* If input got downgraded, inherit the original value */
                 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
-                        return open_terminal_as(tty_path(context), O_WRONLY, fileno);
+                        return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
 
                 /* If the input is connected to anything that's not a /dev/null, inherit that... */
                 if (i != EXEC_INPUT_NULL)
@@ -509,7 +522,7 @@ static int setup_output(
                         return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
 
                 /* We don't reset the terminal if this is just about output */
-                return open_terminal_as(tty_path(context), O_WRONLY, fileno);
+                return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
 
         case EXEC_OUTPUT_SYSLOG:
         case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
@@ -737,12 +750,7 @@ static int enforce_user(const ExecContext *context, uid_t uid) {
         /* Sets (but doesn't lookup) the uid and make sure we keep the
          * capabilities while doing so. */
 
-        if (context->capabilities) {
-                _cleanup_cap_free_ cap_t d = NULL;
-                static const cap_value_t bits[] = {
-                        CAP_SETUID,   /* Necessary so that we can run setresuid() below */
-                        CAP_SETPCAP   /* Necessary so that we can set PR_SET_SECUREBITS later on */
-                };
+        if (context->capabilities || context->capability_ambient_set != 0) {
 
                 /* First step: If we need to keep capabilities but
                  * drop privileges we need to make sure we keep our
@@ -758,16 +766,24 @@ static int enforce_user(const ExecContext *context, uid_t uid) {
                 /* Second step: set the capabilities. This will reduce
                  * the capabilities to the minimum we need. */
 
-                d = cap_dup(context->capabilities);
-                if (!d)
-                        return -errno;
+                if (context->capabilities) {
+                        _cleanup_cap_free_ cap_t d = NULL;
+                        static const cap_value_t bits[] = {
+                                CAP_SETUID,   /* Necessary so that we can run setresuid() below */
+                                CAP_SETPCAP   /* Necessary so that we can set PR_SET_SECUREBITS later on */
+                        };
 
-                if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
-                    cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
-                        return -errno;
+                        d = cap_dup(context->capabilities);
+                        if (!d)
+                                return -errno;
 
-                if (cap_set_proc(d) < 0)
-                        return -errno;
+                        if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
+                            cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
+                                return -errno;
+
+                        if (cap_set_proc(d) < 0)
+                                return -errno;
+                }
         }
 
         /* Third step: actually set the uids */
@@ -811,8 +827,7 @@ static int setup_pam(
         _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
         pam_handle_t *handle = NULL;
         sigset_t old_ss;
-        int pam_code = PAM_SUCCESS;
-        int err = 0;
+        int pam_code = PAM_SUCCESS, r;
         char **e = NULL;
         bool close_session = false;
         pid_t pam_pid = 0, parent_pid;
@@ -829,8 +844,8 @@ static int setup_pam(
          * daemon. We do things this way to ensure that the main PID
          * of the daemon is the one we initially fork()ed. */
 
-        err = barrier_create(&barrier);
-        if (err < 0)
+        r = barrier_create(&barrier);
+        if (r < 0)
                 goto fail;
 
         if (log_get_max_level() < LOG_DEBUG)
@@ -872,12 +887,13 @@ static int setup_pam(
         parent_pid = getpid();
 
         pam_pid = fork();
-        if (pam_pid < 0)
+        if (pam_pid < 0) {
+                r = -errno;
                 goto fail;
+        }
 
         if (pam_pid == 0) {
-                int sig;
-                int r = EXIT_PAM;
+                int sig, ret = EXIT_PAM;
 
                 /* The child's job is to reset the PAM session on
                  * termination */
@@ -942,11 +958,11 @@ static int setup_pam(
                                 goto child_finish;
                 }
 
-                r = 0;
+                ret = 0;
 
         child_finish:
                 pam_end(handle, pam_code | flags);
-                _exit(r);
+                _exit(ret);
         }
 
         barrier_set_role(&barrier, BARRIER_PARENT);
@@ -975,10 +991,9 @@ static int setup_pam(
 fail:
         if (pam_code != PAM_SUCCESS) {
                 log_error("PAM failed: %s", pam_strerror(handle, pam_code));
-                err = -EPERM;  /* PAM errors do not map to errno */
-        } else {
-                err = log_error_errno(err < 0 ? err : errno, "PAM failed: %m");
-        }
+                r = -EPERM;  /* PAM errors do not map to errno */
+        } else
+                log_error_errno(r, "PAM failed: %m");
 
         if (handle) {
                 if (close_session)
@@ -988,15 +1003,9 @@ fail:
         }
 
         strv_free(e);
-
         closelog();
 
-        if (pam_pid > 1) {
-                kill(pam_pid, SIGTERM);
-                kill(pam_pid, SIGCONT);
-        }
-
-        return err;
+        return r;
 }
 #endif
 
@@ -1236,9 +1245,8 @@ static void do_idle_pipe_dance(int idle_pipe[4]) {
 
 static int build_environment(
                 const ExecContext *c,
+                const ExecParameters *p,
                 unsigned n_fds,
-                char ** fd_names,
-                usec_t watchdog_usec,
                 const char *home,
                 const char *username,
                 const char *shell,
@@ -1266,7 +1274,7 @@ static int build_environment(
                         return -ENOMEM;
                 our_env[n_env++] = x;
 
-                joined = strv_join(fd_names, ":");
+                joined = strv_join(p->fd_names, ":");
                 if (!joined)
                         return -ENOMEM;
 
@@ -1276,12 +1284,12 @@ static int build_environment(
                 our_env[n_env++] = x;
         }
 
-        if (watchdog_usec > 0) {
+        if (p->watchdog_usec > 0) {
                 if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0)
                         return -ENOMEM;
                 our_env[n_env++] = x;
 
-                if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, watchdog_usec) < 0)
+                if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, p->watchdog_usec) < 0)
                         return -ENOMEM;
                 our_env[n_env++] = x;
         }
@@ -1317,7 +1325,7 @@ static int build_environment(
             c->std_error == EXEC_OUTPUT_TTY ||
             c->tty_path) {
 
-                x = strdup(default_term_for_tty(tty_path(c)));
+                x = strdup(default_term_for_tty(exec_context_tty_path(c)));
                 if (!x)
                         return -ENOMEM;
                 our_env[n_env++] = x;
@@ -1494,7 +1502,7 @@ static int exec_child(
                         return -errno;
                 }
 
-        exec_context_tty_reset(context);
+        exec_context_tty_reset(context, params);
 
         if (params->confirm_spawn) {
                 char response;
@@ -1856,6 +1864,8 @@ static int exec_child(
 
         if (params->apply_permissions) {
 
+                int secure_bits = context->secure_bits;
+
                 for (i = 0; i < _RLIMIT_MAX; i++) {
                         if (!context->rlimit[i])
                                 continue;
@@ -1866,12 +1876,37 @@ static int exec_child(
                         }
                 }
 
-                if (context->capability_bounding_set_drop) {
-                        r = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
+                if (!cap_test_all(context->capability_bounding_set)) {
+                        r = capability_bounding_set_drop(context->capability_bounding_set, false);
+                        if (r < 0) {
+                                *exit_status = EXIT_CAPABILITIES;
+                                return r;
+                        }
+                }
+
+                /* This is done before enforce_user, but ambient set
+                 * does not survive over setresuid() if keep_caps is not set. */
+                if (context->capability_ambient_set != 0) {
+                        r = capability_ambient_set_apply(context->capability_ambient_set, true);
                         if (r < 0) {
                                 *exit_status = EXIT_CAPABILITIES;
                                 return r;
                         }
+
+                        if (context->capabilities) {
+
+                                /* The capabilities in ambient set need to be also in the inherited
+                                 * set. If they aren't, trying to get them will fail. Add the ambient
+                                 * set inherited capabilities to the capability set in the context.
+                                 * This is needed because if capabilities are set (using "Capabilities="
+                                 * keyword), they will override whatever we set now. */
+
+                                r = capability_update_inherited_set(context->capabilities, context->capability_ambient_set);
+                                if (r < 0) {
+                                        *exit_status = EXIT_CAPABILITIES;
+                                        return r;
+                                }
+                        }
                 }
 
                 if (context->user) {
@@ -1880,14 +1915,32 @@ static int exec_child(
                                 *exit_status = EXIT_USER;
                                 return r;
                         }
+                        if (context->capability_ambient_set != 0) {
+
+                                /* Fix the ambient capabilities after user change. */
+                                r = capability_ambient_set_apply(context->capability_ambient_set, false);
+                                if (r < 0) {
+                                        *exit_status = EXIT_CAPABILITIES;
+                                        return r;
+                                }
+
+                                /* If we were asked to change user and ambient capabilities
+                                 * were requested, we had to add keep-caps to the securebits
+                                 * so that we would maintain the inherited capability set
+                                 * through the setresuid(). Make sure that the bit is added
+                                 * also to the context secure_bits so that we don't try to
+                                 * drop the bit away next. */
+
+                                 secure_bits |= 1<<SECURE_KEEP_CAPS;
+                        }
                 }
 
                 /* PR_GET_SECUREBITS is not privileged, while
                  * PR_SET_SECUREBITS is. So to suppress
                  * potential EPERMs we'll try not to call
                  * PR_SET_SECUREBITS unless necessary. */
-                if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
-                        if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
+                if (prctl(PR_GET_SECUREBITS) != secure_bits)
+                        if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
                                 *exit_status = EXIT_SECUREBITS;
                                 return -errno;
                         }
@@ -1950,7 +2003,7 @@ static int exec_child(
 #endif
         }
 
-        r = build_environment(context, n_fds, params->fd_names, params->watchdog_usec, home, username, shell, &our_env);
+        r = build_environment(context, params, n_fds, home, username, shell, &our_env);
         if (r < 0) {
                 *exit_status = EXIT_MEMORY;
                 return r;
@@ -2056,7 +2109,7 @@ int exec_spawn(Unit *unit,
                    NULL);
         pid = fork();
         if (pid < 0)
-                return log_unit_error_errno(unit, r, "Failed to fork: %m");
+                return log_unit_error_errno(unit, errno, "Failed to fork: %m");
 
         if (pid == 0) {
                 int exit_status;
@@ -2114,6 +2167,7 @@ void exec_context_init(ExecContext *c) {
         c->timer_slack_nsec = NSEC_INFINITY;
         c->personality = PERSONALITY_INVALID;
         c->runtime_directory_mode = 0755;
+        c->capability_bounding_set = CAP_ALL;
 }
 
 void exec_context_done(ExecContext *c) {
@@ -2270,7 +2324,7 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
                                 continue;
 
                         strv_free(r);
-                        return errno ? -errno : -EINVAL;
+                        return errno > 0 ? -errno : -EINVAL;
                 }
                 count = pglob.gl_pathc;
                 if (count == 0) {
@@ -2324,6 +2378,9 @@ static bool tty_may_match_dev_console(const char *tty) {
         _cleanup_free_ char *active = NULL;
         char *console;
 
+        if (!tty)
+                return true;
+
         if (startswith(tty, "/dev/"))
                 tty += 5;
 
@@ -2341,11 +2398,14 @@ static bool tty_may_match_dev_console(const char *tty) {
 }
 
 bool exec_context_may_touch_console(ExecContext *ec) {
-        return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
+
+        return (ec->tty_reset ||
+                ec->tty_vhangup ||
+                ec->tty_vt_disallocate ||
                 is_terminal_input(ec->std_input) ||
                 is_terminal_output(ec->std_output) ||
                 is_terminal_output(ec->std_error)) &&
-               tty_may_match_dev_console(tty_path(ec));
+               tty_may_match_dev_console(exec_context_tty_path(ec));
 }
 
 static void strv_fprintf(FILE *f, char **l) {
@@ -2413,9 +2473,12 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                         prefix, c->oom_score_adjust);
 
         for (i = 0; i < RLIM_NLIMITS; i++)
-                if (c->rlimit[i])
-                        fprintf(f, "%s%s: "RLIM_FMT"\n",
+                if (c->rlimit[i]) {
+                        fprintf(f, "%s%s: " RLIM_FMT "\n",
                                 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
+                        fprintf(f, "%s%sSoft: " RLIM_FMT "\n",
+                                prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
+                }
 
         if (c->ioprio_set) {
                 _cleanup_free_ char *class_str = NULL;
@@ -2514,12 +2577,23 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                         (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
                         (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
 
-        if (c->capability_bounding_set_drop) {
+        if (c->capability_bounding_set != CAP_ALL) {
                 unsigned long l;
                 fprintf(f, "%sCapabilityBoundingSet:", prefix);
 
                 for (l = 0; l <= cap_last_cap(); l++)
-                        if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l)))
+                        if (c->capability_bounding_set & (UINT64_C(1) << l))
+                                fprintf(f, " %s", strna(capability_to_name(l)));
+
+                fputs("\n", f);
+        }
+
+        if (c->capability_ambient_set != 0) {
+                unsigned long l;
+                fprintf(f, "%sAmbientCapabilities:", prefix);
+
+                for (l = 0; l <= cap_last_cap(); l++)
+                        if (c->capability_ambient_set & (UINT64_C(1) << l))
                                 fprintf(f, " %s", strna(capability_to_name(l)));
 
                 fputs("\n", f);
@@ -2620,7 +2694,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                 fputc('\n', f);
         }
 
-        if (c->syscall_errno != 0)
+        if (c->syscall_errno > 0)
                 fprintf(f,
                         "%sSystemCallErrorNumber: %s\n",
                         prefix, strna(errno_to_name(c->syscall_errno)));
@@ -2670,7 +2744,7 @@ void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code,
                 if (context->utmp_id)
                         utmp_put_dead_process(context->utmp_id, pid, code, status);
 
-                exec_context_tty_reset(context);
+                exec_context_tty_reset(context, NULL);
         }
 }
 
index 1faff160cbea58d115938ba56ddf004872b85dea..578f85b6bc29baa4238dd72137c61d4e8f1e414f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -27,16 +25,16 @@ typedef struct ExecContext ExecContext;
 typedef struct ExecRuntime ExecRuntime;
 typedef struct ExecParameters ExecParameters;
 
-#include <sys/capability.h>
+#include <sched.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include <sched.h>
+#include <sys/capability.h>
 
-#include "list.h"
+#include "bus-endpoint.h"
 #include "fdset.h"
+#include "list.h"
 #include "missing.h"
 #include "namespace.h"
-#include "bus-endpoint.h"
 
 typedef enum ExecUtmpMode {
         EXEC_UTMP_INIT,
@@ -122,6 +120,8 @@ struct ExecContext {
 
         nsec_t timer_slack_nsec;
 
+        bool stdio_as_fds;
+
         char *tty_path;
 
         bool tty_reset;
@@ -155,7 +155,9 @@ struct ExecContext {
         char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
         unsigned long mount_flags;
 
-        uint64_t capability_bounding_set_drop;
+        uint64_t capability_bounding_set;
+
+        uint64_t capability_ambient_set;
 
         cap_t capabilities;
         int secure_bits;
@@ -204,8 +206,8 @@ struct ExecContext {
         BusEndpoint *bus_endpoint;
 };
 
-#include "cgroup.h"
 #include "cgroup-util.h"
+#include "cgroup.h"
 
 struct ExecParameters {
         char **argv;
index f67fb05af0b84bb73e636d0a6d280d52a86635ba..39f5519ca1cd0ce83e089b533d3d7a12247848a0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1af4dd987babd08ed6f376491764eb4c0030a9b5..1adac4ad5c621f8a0f91cab3ed781c58f3c527e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d92a9a764f6302b6981098211a0b3f774a1360c0..68be52856b3f9e5f161cbae6441d4d4b96df34a9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8dc3a9e1d87d66b6e4fe991622dffd0b84c4d469..73e8c75c7189734287fe6177a29a5c09adf02a31 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4f42ae6f31b62606ef42684df68b4bb8a19122fc..ff7558d500b1dfe9dc2478fb41f51ee1f93910ca 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 14b56d1fc2db4f5c3828cf2e8e25fad4b6eae0c1..3bad74b24631f8229be89dbf7ec9459e2c8353fb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9654590635dfc05488267f6109a59e90d0103857..97304c4d05911bac59749eda4b30930fab7d4220 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -35,6 +33,7 @@
 #include "parse-util.h"
 #include "set.h"
 #include "special.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -404,6 +403,13 @@ JobType job_type_collapse(JobType t, Unit *u) {
 
                 return JOB_RESTART;
 
+        case JOB_TRY_RELOAD:
+                s = unit_active_state(u);
+                if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
+                        return JOB_NOP;
+
+                return JOB_RELOAD;
+
         case JOB_RELOAD_OR_START:
                 s = unit_active_state(u);
                 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
@@ -754,7 +760,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
                 return;
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
-        snprintf(buf, sizeof(buf), format, unit_description(u));
+        xsprintf(buf, format, unit_description(u));
         REENABLE_WARNING;
 
         switch (t) {
@@ -924,14 +930,14 @@ int job_start_timer(Job *j) {
 
         j->begin_usec = now(CLOCK_MONOTONIC);
 
-        if (j->unit->job_timeout <= 0)
+        if (j->unit->job_timeout == USEC_INFINITY)
                 return 0;
 
         r = sd_event_add_time(
                         j->manager->event,
                         &j->timer_event_source,
                         CLOCK_MONOTONIC,
-                        j->begin_usec + j->unit->job_timeout, 0,
+                        usec_add(j->begin_usec, j->unit->job_timeout), 0,
                         job_dispatch_timer, j);
         if (r < 0)
                 return r;
@@ -1109,17 +1115,16 @@ int job_coldplug(Job *j) {
         if (j->state == JOB_WAITING)
                 job_add_to_run_queue(j);
 
-        if (j->begin_usec == 0 || j->unit->job_timeout == 0)
+        if (j->begin_usec == 0 || j->unit->job_timeout == USEC_INFINITY)
                 return 0;
 
-        if (j->timer_event_source)
-                j->timer_event_source = sd_event_source_unref(j->timer_event_source);
+        j->timer_event_source = sd_event_source_unref(j->timer_event_source);
 
         r = sd_event_add_time(
                         j->manager->event,
                         &j->timer_event_source,
                         CLOCK_MONOTONIC,
-                        j->begin_usec + j->unit->job_timeout, 0,
+                        usec_add(j->begin_usec, j->unit->job_timeout), 0,
                         job_dispatch_timer, j);
         if (r < 0)
                 log_debug_errno(r, "Failed to restart timeout for job: %m");
@@ -1158,10 +1163,10 @@ void job_shutdown_magic(Job *j) {
         asynchronous_sync();
 }
 
-int job_get_timeout(Job *j, uint64_t *timeout) {
+int job_get_timeout(Job *j, usec_t *timeout) {
+        usec_t x = USEC_INFINITY, y = USEC_INFINITY;
         Unit *u = j->unit;
-        uint64_t x = -1, y = -1;
-        int r = 0, q = 0;
+        int r;
 
         assert(u);
 
@@ -1169,20 +1174,18 @@ int job_get_timeout(Job *j, uint64_t *timeout) {
                 r = sd_event_source_get_time(j->timer_event_source, &x);
                 if (r < 0)
                         return r;
-                r = 1;
         }
 
         if (UNIT_VTABLE(u)->get_timeout) {
-                q = UNIT_VTABLE(u)->get_timeout(u, &y);
-                if (q < 0)
-                        return q;
+                r = UNIT_VTABLE(u)->get_timeout(u, &y);
+                if (r < 0)
+                        return r;
         }
 
-        if (r == 0 && q == 0)
+        if (x == USEC_INFINITY && y == USEC_INFINITY)
                 return 0;
 
         *timeout = MIN(x, y);
-
         return 1;
 }
 
@@ -1201,6 +1204,7 @@ static const char* const job_type_table[_JOB_TYPE_MAX] = {
         [JOB_RELOAD_OR_START] = "reload-or-start",
         [JOB_RESTART] = "restart",
         [JOB_TRY_RESTART] = "try-restart",
+        [JOB_TRY_RELOAD] = "try-reload",
         [JOB_NOP] = "nop",
 };
 
@@ -1231,3 +1235,15 @@ static const char* const job_result_table[_JOB_RESULT_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
+
+const char* job_type_to_access_method(JobType t) {
+        assert(t >= 0);
+        assert(t < _JOB_TYPE_MAX);
+
+        if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART))
+                return "start";
+        else if (t == JOB_STOP)
+                return "stop";
+        else
+                return "reload";
+}
index 60d8bd4f3e5e09e0487fe41de1af8fccc3ad1847..856b0ce82935a43376ee55dcc1f55afaf1a353e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -26,6 +24,7 @@
 #include "sd-event.h"
 
 #include "list.h"
+#include "unit-name.h"
 
 typedef struct Job Job;
 typedef struct JobDependency JobDependency;
@@ -65,6 +64,9 @@ enum JobType {
          * Thus we never need to merge it with anything. */
         JOB_TRY_RESTART = _JOB_TYPE_MAX_IN_TRANSACTION, /* if running, stop and then start */
 
+        /* Similar to JOB_TRY_RESTART but collapses to JOB_RELOAD or JOB_NOP */
+        JOB_TRY_RELOAD,
+
         /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result
          * from transaction merging (there's no way for JOB_RELOAD and
          * JOB_START to meet in one transaction). It can result from a merge
@@ -223,6 +225,8 @@ char *job_dbus_path(Job *j);
 
 void job_shutdown_magic(Job *j);
 
+int job_get_timeout(Job *j, usec_t *timeout) _pure_;
+
 const char* job_type_to_string(JobType t) _const_;
 JobType job_type_from_string(const char *s) _pure_;
 
@@ -235,4 +239,4 @@ JobMode job_mode_from_string(const char *s) _pure_;
 const char* job_result_to_string(JobResult t) _const_;
 JobResult job_result_from_string(const char *s) _pure_;
 
-int job_get_timeout(Job *j, uint64_t *timeout) _pure_;
+const char* job_type_to_access_method(JobType t);
index 1466d5ce64335021b30738875b3c658beb7e8755..6854587d54d4ec25ed0dd8800a092cc51243b9d8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5d97abb104ad20f7bf051a3d96e0ac1ba583d29d..b3d2056cb02ada40c229a41bb91d1c84de66d67b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 77f145b4d1a006057b9415f1f097c2ef26d7d712..09378f7085bd9d1bb77eafc88f796070a3bd373f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -37,7 +35,7 @@
 
 #define TIMEOUT_USEC (10 * USEC_PER_SEC)
 
-static bool ignore_proc(pid_t pid) {
+static bool ignore_proc(pid_t pid, bool warn_rootfs) {
         _cleanup_fclose_ FILE *f = NULL;
         char c;
         const char *p;
@@ -72,7 +70,22 @@ static bool ignore_proc(pid_t pid) {
          * spree.
          *
          * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
-        if (count == 1 && c == '@')
+        if (c == '@' && warn_rootfs) {
+                _cleanup_free_ char *comm = NULL;
+
+                r = pid_from_same_root_fs(pid);
+                if (r < 0)
+                        return true;
+
+                get_process_comm(pid, &comm);
+
+                if (r)
+                        log_notice("Process " PID_FMT " (%s) has been been marked to be excluded from killing. It is "
+                                   "running from the root file system, and thus likely to block re-mounting of the "
+                                   "root file system to read-only. Please consider moving it into an initrd file "
+                                   "system instead.", pid, strna(comm));
+                return true;
+        } else if (c == '@')
                 return true;
 
         return false;
@@ -171,7 +184,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
                 if (parse_pid(d->d_name, &pid) < 0)
                         continue;
 
-                if (ignore_proc(pid))
+                if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
                         continue;
 
                 if (sig == SIGKILL) {
index 986cf432cbc4f3a4d4ae776b99ff2e019b3d0000..acc2439f0082d6b310718e63419400efe5616758 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a6ab8cf4b38b556b882792c5f1de924cd2a9517d..3503db52edceebcba9bc9059a7b177328e3eefbf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 24dcdddfa45f7aeb4578714f9479b0f3e4143370..685f4df301bfdecd3f26822b96fbcaca53ef911e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3fa66f91aad61e464f062744a5e9fa7495b13284..22b71b6f5e5c04837fe7e8708e18f5c6a662c254 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -65,6 +63,7 @@ int unit_load_dropin(Unit *u) {
                 }
         }
 
+        u->dropin_paths = strv_free(u->dropin_paths);
         r = unit_find_dropin_paths(u, &u->dropin_paths);
         if (r <= 0)
                 return 0;
index 1e018c45253f6d03d0036527aa6698c614c8c157..d8a4aefbb3805a8118943f6f3e37bab46ac475ed 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "unit.h"
 #include "dropin.h"
+#include "unit.h"
 
 /* Read service data supplementary drop-in directories */
 
index 74ef72de8842bf69dd1db9089435fef8309f613e..5024fd19a5bec9c94ec5194833de81120fd03343 100644 (file)
@@ -47,7 +47,8 @@ $1.SyslogLevel,                  config_parse_log_level,             0,
 $1.SyslogLevelPrefix,            config_parse_bool,                  0,                             offsetof($1, exec_context.syslog_level_prefix)
 $1.Capabilities,                 config_parse_exec_capabilities,     0,                             offsetof($1, exec_context)
 $1.SecureBits,                   config_parse_exec_secure_bits,      0,                             offsetof($1, exec_context)
-$1.CapabilityBoundingSet,        config_parse_bounding_set,          0,                             offsetof($1, exec_context.capability_bounding_set_drop)
+$1.CapabilityBoundingSet,        config_parse_capability_set,        0,                             offsetof($1, exec_context.capability_bounding_set)
+$1.AmbientCapabilities,          config_parse_capability_set,        0,                             offsetof($1, exec_context.capability_ambient_set)
 $1.TimerSlackNSec,               config_parse_nsec,                  0,                             offsetof($1, exec_context.timer_slack_nsec)
 $1.NoNewPrivileges,              config_parse_no_new_privileges,     0,                             offsetof($1, exec_context)
 m4_ifdef(`HAVE_SECCOMP',
@@ -59,22 +60,22 @@ $1.RestrictAddressFamilies,      config_parse_address_families,      0,
 $1.SystemCallArchitectures,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
 $1.SystemCallErrorNumber,        config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
 $1.RestrictAddressFamilies,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0')
-$1.LimitCPU,                     config_parse_sec_limit,             RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE,                   config_parse_bytes_limit,           RLIMIT_FSIZE,                  offsetof($1, exec_context.rlimit)
-$1.LimitDATA,                    config_parse_bytes_limit,           RLIMIT_DATA,                   offsetof($1, exec_context.rlimit)
-$1.LimitSTACK,                   config_parse_bytes_limit,           RLIMIT_STACK,                  offsetof($1, exec_context.rlimit)
-$1.LimitCORE,                    config_parse_bytes_limit,           RLIMIT_CORE,                   offsetof($1, exec_context.rlimit)
-$1.LimitRSS,                     config_parse_bytes_limit,           RLIMIT_RSS,                    offsetof($1, exec_context.rlimit)
+$1.LimitCPU,                     config_parse_limit,                 RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
+$1.LimitFSIZE,                   config_parse_limit,                 RLIMIT_FSIZE,                  offsetof($1, exec_context.rlimit)
+$1.LimitDATA,                    config_parse_limit,                 RLIMIT_DATA,                   offsetof($1, exec_context.rlimit)
+$1.LimitSTACK,                   config_parse_limit,                 RLIMIT_STACK,                  offsetof($1, exec_context.rlimit)
+$1.LimitCORE,                    config_parse_limit,                 RLIMIT_CORE,                   offsetof($1, exec_context.rlimit)
+$1.LimitRSS,                     config_parse_limit,                 RLIMIT_RSS,                    offsetof($1, exec_context.rlimit)
 $1.LimitNOFILE,                  config_parse_limit,                 RLIMIT_NOFILE,                 offsetof($1, exec_context.rlimit)
-$1.LimitAS,                      config_parse_bytes_limit,           RLIMIT_AS,                     offsetof($1, exec_context.rlimit)
+$1.LimitAS,                      config_parse_limit,                 RLIMIT_AS,                     offsetof($1, exec_context.rlimit)
 $1.LimitNPROC,                   config_parse_limit,                 RLIMIT_NPROC,                  offsetof($1, exec_context.rlimit)
-$1.LimitMEMLOCK,                 config_parse_bytes_limit,           RLIMIT_MEMLOCK,                offsetof($1, exec_context.rlimit)
+$1.LimitMEMLOCK,                 config_parse_limit,                 RLIMIT_MEMLOCK,                offsetof($1, exec_context.rlimit)
 $1.LimitLOCKS,                   config_parse_limit,                 RLIMIT_LOCKS,                  offsetof($1, exec_context.rlimit)
 $1.LimitSIGPENDING,              config_parse_limit,                 RLIMIT_SIGPENDING,             offsetof($1, exec_context.rlimit)
-$1.LimitMSGQUEUE,                config_parse_bytes_limit,           RLIMIT_MSGQUEUE,               offsetof($1, exec_context.rlimit)
+$1.LimitMSGQUEUE,                config_parse_limit,                 RLIMIT_MSGQUEUE,               offsetof($1, exec_context.rlimit)
 $1.LimitNICE,                    config_parse_limit,                 RLIMIT_NICE,                   offsetof($1, exec_context.rlimit)
 $1.LimitRTPRIO,                  config_parse_limit,                 RLIMIT_RTPRIO,                 offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME,                  config_parse_usec_limit,            RLIMIT_RTTIME,                 offsetof($1, exec_context.rlimit)
+$1.LimitRTTIME,                  config_parse_limit,                 RLIMIT_RTTIME,                 offsetof($1, exec_context.rlimit)
 $1.ReadWriteDirectories,         config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.read_write_dirs)
 $1.ReadOnlyDirectories,          config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.read_only_dirs)
 $1.InaccessibleDirectories,      config_parse_namespace_path_strv,   0,                             offsetof($1, exec_context.inaccessible_dirs)
@@ -128,7 +129,7 @@ $1.BlockIOWriteBandwidth,        config_parse_blockio_bandwidth,     0,
 $1.TasksAccounting,              config_parse_bool,                  0,                             offsetof($1, cgroup_context.tasks_accounting)
 $1.TasksMax,                     config_parse_tasks_max,             0,                             offsetof($1, cgroup_context.tasks_max)
 $1.Delegate,                     config_parse_bool,                  0,                             offsetof($1, cgroup_context.delegate)
-$1.NetClass,                     config_parse_netclass,              0,                             offsetof($1, cgroup_context)'
+$1.NetClass,                     config_parse_warn_compat,           DISABLED_LEGACY,               0'
 )m4_dnl
 Unit.Description,                config_parse_unit_string_printf,    0,                             offsetof(Unit, description)
 Unit.Documentation,              config_parse_documentation,         0,                             offsetof(Unit, documentation)
@@ -160,9 +161,13 @@ Unit.OnFailureJobMode,           config_parse_job_mode,              0,
 Unit.OnFailureIsolate,           config_parse_job_mode_isolate,      0,                             offsetof(Unit, on_failure_job_mode)
 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,                   0,                             offsetof(Unit, job_timeout)
+Unit.JobTimeoutSec,              config_parse_sec_fix_0,             0,                             offsetof(Unit, job_timeout)
 Unit.JobTimeoutAction,           config_parse_failure_action,        0,                             offsetof(Unit, job_timeout_action)
 Unit.JobTimeoutRebootArgument,   config_parse_string,                0,                             offsetof(Unit, job_timeout_reboot_arg)
+Unit.StartLimitInterval,         config_parse_sec,                   0,                             offsetof(Unit, start_limit.interval)
+Unit.StartLimitBurst,            config_parse_unsigned,              0,                             offsetof(Unit, start_limit.burst)
+Unit.StartLimitAction,           config_parse_failure_action,        0,                             offsetof(Unit, start_limit_action)
+Unit.RebootArgument,             config_parse_string,                0,                             offsetof(Unit, reboot_arg)
 Unit.ConditionPathExists,        config_parse_unit_condition_path,   CONDITION_PATH_EXISTS,         offsetof(Unit, conditions)
 Unit.ConditionPathExistsGlob,    config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB,    offsetof(Unit, conditions)
 Unit.ConditionPathIsDirectory,   config_parse_unit_condition_path,   CONDITION_PATH_IS_DIRECTORY,   offsetof(Unit, conditions)
@@ -210,14 +215,15 @@ Service.ExecReload,              config_parse_exec,                  SERVICE_EXE
 Service.ExecStop,                config_parse_exec,                  SERVICE_EXEC_STOP,             offsetof(Service, exec_command)
 Service.ExecStopPost,            config_parse_exec,                  SERVICE_EXEC_STOP_POST,        offsetof(Service, exec_command)
 Service.RestartSec,              config_parse_sec,                   0,                             offsetof(Service, restart_usec)
-Service.TimeoutSec,              config_parse_service_timeout,       0,                             offsetof(Service, timeout_start_usec)
-Service.TimeoutStartSec,         config_parse_service_timeout,       0,                             offsetof(Service, timeout_start_usec)
-Service.TimeoutStopSec,          config_parse_service_timeout,       0,                             offsetof(Service, timeout_stop_usec)
+Service.TimeoutSec,              config_parse_service_timeout,       0,                             0
+Service.TimeoutStartSec,         config_parse_service_timeout,       0,                             0
+Service.TimeoutStopSec,          config_parse_service_timeout,       0,                             0
+Service.RuntimeMaxSec,           config_parse_sec,                   0,                             offsetof(Service, runtime_max_usec)
 Service.WatchdogSec,             config_parse_sec,                   0,                             offsetof(Service, watchdog_usec)
-Service.StartLimitInterval,      config_parse_sec,                   0,                             offsetof(Service, start_limit.interval)
-Service.StartLimitBurst,         config_parse_unsigned,              0,                             offsetof(Service, start_limit.burst)
-Service.StartLimitAction,        config_parse_failure_action,        0,                             offsetof(Service, start_limit_action)
-Service.RebootArgument,          config_parse_string,                0,                             offsetof(Service, reboot_arg)
+Service.StartLimitInterval,      config_parse_sec,                   0,                             offsetof(Unit, start_limit.interval)
+Service.StartLimitBurst,         config_parse_unsigned,              0,                             offsetof(Unit, start_limit.burst)
+Service.StartLimitAction,        config_parse_failure_action,        0,                             offsetof(Unit, start_limit_action)
+Service.RebootArgument,          config_parse_string,                0,                             offsetof(Unit, reboot_arg)
 Service.FailureAction,           config_parse_failure_action,        0,                             offsetof(Service, failure_action)
 Service.Type,                    config_parse_service_type,          0,                             offsetof(Service, type)
 Service.Restart,                 config_parse_service_restart,       0,                             offsetof(Service, restart)
@@ -249,6 +255,7 @@ Socket.ListenNetlink,            config_parse_socket_listen,         SOCKET_SOCK
 Socket.ListenSpecial,            config_parse_socket_listen,         SOCKET_SPECIAL,                0
 Socket.ListenMessageQueue,       config_parse_socket_listen,         SOCKET_MQUEUE,                 0
 Socket.ListenUSBFunction,        config_parse_socket_listen,         SOCKET_USB_FUNCTION,           0
+Socket.SocketProtocol,           config_parse_socket_protocol,       0,                             0
 Socket.BindIPv6Only,             config_parse_socket_bind,           0,                             0,
 Socket.Backlog,                  config_parse_unsigned,              0,                             offsetof(Socket, backlog)
 Socket.BindToDevice,             config_parse_socket_bindtodevice,   0,                             0
@@ -346,6 +353,7 @@ Timer.Persistent,                config_parse_bool,                  0,
 Timer.WakeSystem,                config_parse_bool,                  0,                             offsetof(Timer, wake_system)
 Timer.RemainAfterElapse,         config_parse_bool,                  0,                             offsetof(Timer, remain_after_elapse)
 Timer.AccuracySec,               config_parse_sec,                   0,                             offsetof(Timer, accuracy_usec)
+Timer.RandomizedDelaySec,        config_parse_sec,                   0,                             offsetof(Timer, random_usec)
 Timer.Unit,                      config_parse_trigger_unit,          0,                             0
 m4_dnl
 Path.PathExists,                 config_parse_path_spec,             0,                             0
index dda79267f7083ea47b17ed40f9d96fb567c6a69a..b3dec7b8ccb58544b30c7d32e244eee5fb57f106 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -38,6 +36,7 @@
 #include "bus-internal.h"
 #include "bus-util.h"
 #include "cap-list.h"
+#include "capability-util.h"
 #include "cgroup.h"
 #include "conf-parser.h"
 #include "cpu-set-util.h"
@@ -53,6 +52,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
 #endif
@@ -421,6 +421,37 @@ int config_parse_socket_listen(const char *unit,
         return 0;
 }
 
+int config_parse_socket_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) {
+        Socket *s;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        s = SOCKET(data);
+
+        if (streq(rvalue, "udplite"))
+                s->socket_protocol = IPPROTO_UDPLITE;
+        else if (streq(rvalue, "sctp"))
+                s->socket_protocol = IPPROTO_SCTP;
+        else {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        return 0;
+}
+
 int config_parse_socket_bind(const char *unit,
                              const char *filename,
                              unsigned line,
@@ -543,7 +574,9 @@ int config_parse_exec(
                 void *data,
                 void *userdata) {
 
+        _cleanup_free_ char *cmd = NULL;
         ExecCommand **e = data;
+        Unit *u = userdata;
         const char *p;
         bool semicolon;
         int r;
@@ -552,6 +585,7 @@ int config_parse_exec(
         assert(lvalue);
         assert(rvalue);
         assert(e);
+        assert(u);
 
         e += ltype;
         rvalue += strspn(rvalue, WHITESPACE);
@@ -562,7 +596,13 @@ int config_parse_exec(
                 return 0;
         }
 
-        p = rvalue;
+        r = unit_full_printf(u, rvalue, &cmd);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+                return 0;
+        }
+
+        p = cmd;
         do {
                 _cleanup_free_ char *path = NULL, *firstword = NULL;
                 bool separate_argv0 = false, ignore = false;
@@ -993,7 +1033,7 @@ int config_parse_exec_secure_bits(const char *unit,
         return 0;
 }
 
-int config_parse_bounding_set(
+int config_parse_capability_set(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -1005,8 +1045,8 @@ int config_parse_bounding_set(
                 void *data,
                 void *userdata) {
 
-        uint64_t *capability_bounding_set_drop = data;
-        uint64_t capability_bounding_set, sum = 0;
+        uint64_t *capability_set = data;
+        uint64_t sum = 0, initial = 0;
         bool invert = false;
         const char *p;
 
@@ -1020,10 +1060,9 @@ int config_parse_bounding_set(
                 rvalue++;
         }
 
-        /* Note that we store this inverted internally, since the
-         * kernel wants it like this. But we actually expose it
-         * non-inverted everywhere to have a fully normalized
-         * interface. */
+        if (strcmp(lvalue, "CapabilityBoundingSet") == 0)
+                initial = CAP_ALL; /* initialized to all bits on */
+        /* else "AmbientCapabilities" initialized to all bits off */
 
         p = rvalue;
         for (;;) {
@@ -1042,18 +1081,21 @@ int config_parse_bounding_set(
 
                 cap = capability_from_name(word);
                 if (cap < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word);
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding/ambient set, ignoring: %s", word);
                         continue;
                 }
 
                 sum |= ((uint64_t) UINT64_C(1)) << (uint64_t) cap;
         }
 
-        capability_bounding_set = invert ? ~sum : sum;
-        if (*capability_bounding_set_drop != 0 && capability_bounding_set != 0)
-                *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set);
+        sum = invert ? ~sum : sum;
+
+        if (sum == 0 || *capability_set == initial)
+                /* "" or uninitialized data -> replace */
+                *capability_set = sum;
         else
-                *capability_bounding_set_drop = ~capability_bounding_set;
+                /* previous data -> merge */
+                *capability_set |= sum;
 
         return 0;
 }
@@ -1070,8 +1112,7 @@ int config_parse_limit(
                 void *data,
                 void *userdata) {
 
-        struct rlimit **rl = data;
-        rlim_t v;
+        struct rlimit **rl = data, d = {};
         int r;
 
         assert(filename);
@@ -1079,184 +1120,24 @@ int config_parse_limit(
         assert(rvalue);
         assert(data);
 
-        rl += ltype;
-
-        if (streq(rvalue, "infinity"))
-                v = RLIM_INFINITY;
-        else {
-                uint64_t u;
-
-                /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
-                assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
-
-                r = safe_atou64(rvalue, &u);
-                if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
-                        r = -ERANGE;
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                v = (rlim_t) u;
-        }
-
-        if (!*rl) {
-                *rl = new(struct rlimit, 1);
-                if (!*rl)
-                        return log_oom();
-        }
-
-        (*rl)->rlim_cur = (*rl)->rlim_max = v;
-        return 0;
-}
-
-int config_parse_bytes_limit(
-                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) {
-
-        struct rlimit **rl = data;
-        rlim_t bytes;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        rl += ltype;
-
-        if (streq(rvalue, "infinity"))
-                bytes = RLIM_INFINITY;
-        else {
-                uint64_t u;
-
-                r = parse_size(rvalue, 1024, &u);
-                if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
-                        r = -ERANGE;
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                bytes = (rlim_t) u;
+        r = rlimit_parse(ltype, rvalue, &d);
+        if (r == -EILSEQ) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
+                return 0;
         }
-
-        if (!*rl) {
-                *rl = new(struct rlimit, 1);
-                if (!*rl)
-                        return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+                return 0;
         }
 
-        (*rl)->rlim_cur = (*rl)->rlim_max = bytes;
-        return 0;
-}
-
-int config_parse_sec_limit(
-                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) {
-
-        struct rlimit **rl = data;
-        rlim_t seconds;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        rl += ltype;
-
-        if (streq(rvalue, "infinity"))
-                seconds = RLIM_INFINITY;
+        if (rl[ltype])
+                *rl[ltype] = d;
         else {
-                usec_t t;
-
-                r = parse_sec(rvalue, &t);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                if (t == USEC_INFINITY)
-                        seconds = RLIM_INFINITY;
-                else
-                        seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
-        }
-
-        if (!*rl) {
-                *rl = new(struct rlimit, 1);
-                if (!*rl)
+                rl[ltype] = newdup(struct rlimit, &d, 1);
+                if (!rl[ltype])
                         return log_oom();
         }
 
-        (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
-        return 0;
-}
-
-
-int config_parse_usec_limit(
-                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) {
-
-        struct rlimit **rl = data;
-        rlim_t useconds;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        rl += ltype;
-
-        if (streq(rvalue, "infinity"))
-                useconds = RLIM_INFINITY;
-        else {
-                usec_t t;
-
-                r = parse_time(rvalue, &t, 1);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                if (t == USEC_INFINITY)
-                        useconds = RLIM_INFINITY;
-                else
-                        useconds = (rlim_t) t;
-        }
-
-        if (!*rl) {
-                *rl = new(struct rlimit, 1);
-                if (!*rl)
-                        return log_oom();
-        }
-
-        (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
         return 0;
 }
 
@@ -1305,38 +1186,28 @@ int config_parse_exec_mount_flags(const char *unit,
                                   void *data,
                                   void *userdata) {
 
-        ExecContext *c = data;
-        const char *word, *state;
-        size_t l;
+
         unsigned long flags = 0;
+        ExecContext *c = data;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
-                _cleanup_free_ char *t;
-
-                t = strndup(word, l);
-                if (!t)
-                        return log_oom();
-
-                if (streq(t, "shared"))
-                        flags = MS_SHARED;
-                else if (streq(t, "slave"))
-                        flags = MS_SLAVE;
-                else if (streq(t, "private"))
-                        flags = MS_PRIVATE;
-                else {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
-                        return 0;
-                }
+        if (streq(rvalue, "shared"))
+                flags = MS_SHARED;
+        else if (streq(rvalue, "slave"))
+                flags = MS_SLAVE;
+        else if (streq(rvalue, "private"))
+                flags = MS_PRIVATE;
+        else {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
+                return 0;
         }
-        if (!isempty(state))
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
 
         c->mount_flags = flags;
+
         return 0;
 }
 
@@ -1670,7 +1541,7 @@ int config_parse_socket_service(
                 void *data,
                 void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *p = NULL;
         Socket *s = data;
         Unit *x;
@@ -1840,18 +1711,20 @@ int config_parse_bus_name(
         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
 }
 
-int config_parse_service_timeout(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_service_timeout(
+                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) {
 
         Service *s = userdata;
+        usec_t usec;
         int r;
 
         assert(filename);
@@ -1859,16 +1732,63 @@ int config_parse_service_timeout(const char *unit,
         assert(rvalue);
         assert(s);
 
-        r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
-                             rvalue, data, userdata);
-        if (r < 0)
-                return r;
+        /* This is called for three cases: TimeoutSec=, TimeoutStopSec= and TimeoutStartSec=. */
 
-        if (streq(lvalue, "TimeoutSec")) {
-                s->start_timeout_defined = true;
-                s->timeout_stop_usec = s->timeout_start_usec;
-        } else if (streq(lvalue, "TimeoutStartSec"))
+        r = parse_sec(rvalue, &usec);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
+         * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
+         * all other timeouts. */
+        if (usec <= 0)
+                usec = USEC_INFINITY;
+
+        if (!streq(lvalue, "TimeoutStopSec")) {
                 s->start_timeout_defined = true;
+                s->timeout_start_usec = usec;
+        }
+
+        if (!streq(lvalue, "TimeoutStartSec"))
+                s->timeout_stop_usec = usec;
+
+        return 0;
+}
+
+int config_parse_sec_fix_0(
+                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) {
+
+        usec_t *usec = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(usec);
+
+        /* This is pretty much like config_parse_sec(), except that this treats a time of 0 as infinity, for
+         * 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);
+        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;
 }
@@ -1885,7 +1805,7 @@ int config_parse_busname_service(
                 void *data,
                 void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         BusName *n = data;
         int r;
         Unit *x;
@@ -3242,47 +3162,6 @@ int config_parse_blockio_bandwidth(
         return 0;
 }
 
-int config_parse_netclass(
-                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) {
-
-        CGroupContext *c = data;
-        unsigned v;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        if (streq(rvalue, "auto")) {
-                c->netclass_type = CGROUP_NETCLASS_TYPE_AUTO;
-                return 0;
-        }
-
-        r = safe_atou32(rvalue, &v);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Netclass '%s' invalid. Ignoring.", rvalue);
-                return 0;
-        }
-
-        if (v > CGROUP_NETCLASS_FIXED_MAX)
-                log_syntax(unit, LOG_ERR, filename, line, 0,
-                           "Fixed netclass %" PRIu32 " out of allowed range (0-%d). Applying anyway.", v, (uint32_t) CGROUP_NETCLASS_FIXED_MAX);
-
-        c->netclass_id = v;
-        c->netclass_type = CGROUP_NETCLASS_TYPE_FIXED;
-
-        return 0;
-}
-
 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
 
 int config_parse_job_mode_isolate(
@@ -3973,7 +3852,7 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_log_level,             "LEVEL" },
                 { config_parse_exec_capabilities,     "CAPABILITIES" },
                 { config_parse_exec_secure_bits,      "SECUREBITS" },
-                { config_parse_bounding_set,          "BOUNDINGSET" },
+                { config_parse_capability_set,        "BOUNDINGSET" },
                 { config_parse_limit,                 "LIMIT" },
                 { config_parse_unit_deps,             "UNIT [...]" },
                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
index 62300c10f9fb192abc6e78ae813cda1b6e67da39..5fb591091962c65ff909b362807a30853fdc49e4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -38,6 +36,7 @@ int config_parse_unit_path_printf(const char *unit, const char *filename, unsign
 int config_parse_unit_path_strv_printf(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_documentation(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_socket_listen(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_socket_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);
 int config_parse_socket_bind(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_exec_nice(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_exec_oom_score_adjust(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);
@@ -55,11 +54,8 @@ int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, uns
 int config_parse_exec_cpu_affinity(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_exec_capabilities(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_exec_secure_bits(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_bounding_set(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_capability_set(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_limit(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_bytes_limit(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_sec_limit(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_usec_limit(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_sysv_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_kill_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_exec_mount_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);
@@ -113,6 +109,7 @@ int config_parse_bus_name(const char* unit, const char *filename, unsigned line,
 int config_parse_exec_utmp_mode(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_working_directory(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_fdname(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_sec_fix_0(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);
 
 /* gperf prototypes */
 const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
index 4c8d920389fc8c6c5fb954f94d8e7526ec6e92df..ccf61d29fbe4387e328b43173a5fe16f2b043ade 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 62c654c37ce358ee5cc290571a5d4d5e06e41b3d..3b97497afed99c16d6165e22142ca52136d5b16d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4a57793104e075ea9985a4d2f6c6b47c36bc55d5..04062a7910a47db0d10884f8c10837574531e716 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -29,7 +27,7 @@
 #include "netlink-util.h"
 
 static int start_loopback(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, LOOPBACK_IFINDEX);
@@ -48,7 +46,7 @@ static int start_loopback(sd_netlink *rtnl) {
 }
 
 static bool check_loopback(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         unsigned flags;
         int r;
 
@@ -68,7 +66,7 @@ static bool check_loopback(sd_netlink *rtnl) {
 }
 
 int loopback_setup(void) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         int r;
 
         r = sd_netlink_open(&rtnl);
index dd83cf13a7d1c55e8ceb2a501bfbf4c5d34c281e..e7547b8a2638dddeae8513d32a780edc16cc9ee0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 145ba2a28df62f98bf6c6334d419b746b64866e7..9e6b3d3292c6ee6f9c9650d42befc86be7e5d2aa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -198,7 +196,7 @@ static int generate_machine_id(char id[34], const char *root) {
         return 0;
 }
 
-int machine_id_setup(const char *root) {
+int machine_id_setup(const char *root, sd_id128_t machine_id) {
         const char *etc_machine_id, *run_machine_id;
         _cleanup_close_ int fd = -1;
         bool writable = true;
@@ -248,15 +246,22 @@ int machine_id_setup(const char *root) {
                 }
         }
 
-        if (read_machine_id(fd, id) >= 0)
-                return 0;
+        /* A machine id argument overrides all other machined-ids */
+        if (!sd_id128_is_null(machine_id)) {
+                sd_id128_to_string(machine_id, id);
+                id[32] = '\n';
+                id[33] = 0;
+        } else {
+                if (read_machine_id(fd, id) >= 0)
+                        return 0;
 
-        /* Hmm, so, the id currently stored is not useful, then let's
-         * generate one */
+                /* Hmm, so, the id currently stored is not useful, then let's
+                 * generate one */
 
-        r = generate_machine_id(id, root);
-        if (r < 0)
-                return r;
+                r = generate_machine_id(id, root);
+                if (r < 0)
+                        return r;
+        }
 
         if (writable)
                 if (write_machine_id(fd, id) >= 0)
index f7707c3bf9f6d6d2959e0af88d222b289d37854c..a7e7678ed9133a6fc84408aeb8412cc4eb3f0c85 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,4 +20,4 @@
 ***/
 
 int machine_id_commit(const char *root);
-int machine_id_setup(const char *root);
+int machine_id_setup(const char *root, sd_id128_t machine_id);
index 8a0e44b58c9c48b3e51a43ff5a3c11a690750816..2cace3d3ba5f6463fdc95bec07f50b7ab6dadc89 100644 (file)
@@ -43,7 +43,7 @@ if [ $1 -eq 1 ] ; then \
 fi \
 %{nil}
 
-%systemd_user_post() %systemd_post --user --global %{?*}
+%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}}
 
 %systemd_preun() \
 if [ $1 -eq 0 ] ; then \
index 97f904b031618c229b972ae6d466cc4027a5df32..e2088574c05a656cbfc8bceaece519364fb66887 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -117,7 +115,7 @@ static usec_t arg_runtime_watchdog = 0;
 static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
 static char **arg_default_environment = NULL;
 static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
-static uint64_t arg_capability_bounding_set_drop = 0;
+static uint64_t arg_capability_bounding_set = CAP_ALL;
 static nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
 static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
 static Set* arg_syscall_archs = NULL;
@@ -127,6 +125,7 @@ static bool arg_default_blockio_accounting = false;
 static bool arg_default_memory_accounting = false;
 static bool arg_default_tasks_accounting = true;
 static uint64_t arg_default_tasks_max = UINT64_C(512);
+static sd_id128_t arg_machine_id = {};
 
 static void pager_open_if_enabled(void) {
 
@@ -173,19 +172,15 @@ noreturn static void crash(int sig) {
                 if (pid < 0)
                         log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig));
                 else if (pid == 0) {
-                        struct rlimit rl = {
-                                .rlim_cur = RLIM_INFINITY,
-                                .rlim_max = RLIM_INFINITY,
-                        };
-
                         /* Enable default signal handler for core dump */
+
                         sa = (struct sigaction) {
                                 .sa_handler = SIG_DFL,
                         };
                         (void) sigaction(sig, &sa, NULL);
 
-                        /* Don't limit the core dump size */
-                        (void) setrlimit(RLIMIT_CORE, &rl);
+                        /* Don't limit the coredump size */
+                        (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY));
 
                         /* Just to be sure... */
                         (void) chdir("/");
@@ -300,6 +295,17 @@ static int parse_crash_chvt(const char *value) {
         return 0;
 }
 
+static int set_machine_id(const char *m) {
+
+        if (sd_id128_from_string(m, &arg_machine_id) < 0)
+                return -EINVAL;
+
+        if (sd_id128_is_null(arg_machine_id))
+                return -EINVAL;
+
+        return 0;
+}
+
 static int parse_proc_cmdline_item(const char *key, const char *value) {
 
         int r;
@@ -388,6 +394,12 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
                 } else
                         log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
 
+        } else if (streq(key, "systemd.machine_id") && value) {
+
+               r = set_machine_id(value);
+               if (r < 0)
+                       log_warning("MachineID '%s' is not valid. Ignoring.", value);
+
         } else if (streq(key, "quiet") && !value) {
 
                 if (arg_show_status == _SHOW_STATUS_UNSET)
@@ -644,7 +656,7 @@ static int parse_config_file(void) {
                 { "Manager", "JoinControllers",           config_parse_join_controllers, 0, &arg_join_controllers                  },
                 { "Manager", "RuntimeWatchdogSec",        config_parse_sec,              0, &arg_runtime_watchdog                  },
                 { "Manager", "ShutdownWatchdogSec",       config_parse_sec,              0, &arg_shutdown_watchdog                 },
-                { "Manager", "CapabilityBoundingSet",     config_parse_bounding_set,     0, &arg_capability_bounding_set_drop      },
+                { "Manager", "CapabilityBoundingSet",     config_parse_capability_set,   0, &arg_capability_bounding_set           },
 #ifdef HAVE_SECCOMP
                 { "Manager", "SystemCallArchitectures",   config_parse_syscall_archs,    0, &arg_syscall_archs                     },
 #endif
@@ -658,22 +670,22 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultStartLimitInterval", config_parse_sec,              0, &arg_default_start_limit_interval      },
                 { "Manager", "DefaultStartLimitBurst",    config_parse_unsigned,         0, &arg_default_start_limit_burst         },
                 { "Manager", "DefaultEnvironment",        config_parse_environ,          0, &arg_default_environment               },
-                { "Manager", "DefaultLimitCPU",           config_parse_sec_limit,        0, &arg_default_rlimit[RLIMIT_CPU]        },
-                { "Manager", "DefaultLimitFSIZE",         config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_FSIZE]      },
-                { "Manager", "DefaultLimitDATA",          config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_DATA]       },
-                { "Manager", "DefaultLimitSTACK",         config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_STACK]      },
-                { "Manager", "DefaultLimitCORE",          config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_CORE]       },
-                { "Manager", "DefaultLimitRSS",           config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_RSS]        },
-                { "Manager", "DefaultLimitNOFILE",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NOFILE]     },
-                { "Manager", "DefaultLimitAS",            config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_AS]         },
-                { "Manager", "DefaultLimitNPROC",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NPROC]      },
-                { "Manager", "DefaultLimitMEMLOCK",       config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_MEMLOCK]    },
-                { "Manager", "DefaultLimitLOCKS",         config_parse_limit,            0, &arg_default_rlimit[RLIMIT_LOCKS]      },
-                { "Manager", "DefaultLimitSIGPENDING",    config_parse_limit,            0, &arg_default_rlimit[RLIMIT_SIGPENDING] },
-                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_bytes_limit,      0, &arg_default_rlimit[RLIMIT_MSGQUEUE]   },
-                { "Manager", "DefaultLimitNICE",          config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NICE]       },
-                { "Manager", "DefaultLimitRTPRIO",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RTPRIO]     },
-                { "Manager", "DefaultLimitRTTIME",        config_parse_usec_limit,       0, &arg_default_rlimit[RLIMIT_RTTIME]     },
+                { "Manager", "DefaultLimitCPU",           config_parse_limit,            RLIMIT_CPU, arg_default_rlimit            },
+                { "Manager", "DefaultLimitFSIZE",         config_parse_limit,            RLIMIT_FSIZE, arg_default_rlimit          },
+                { "Manager", "DefaultLimitDATA",          config_parse_limit,            RLIMIT_DATA, arg_default_rlimit           },
+                { "Manager", "DefaultLimitSTACK",         config_parse_limit,            RLIMIT_STACK, arg_default_rlimit          },
+                { "Manager", "DefaultLimitCORE",          config_parse_limit,            RLIMIT_CORE, arg_default_rlimit           },
+                { "Manager", "DefaultLimitRSS",           config_parse_limit,            RLIMIT_RSS, arg_default_rlimit            },
+                { "Manager", "DefaultLimitNOFILE",        config_parse_limit,            RLIMIT_NOFILE, arg_default_rlimit         },
+                { "Manager", "DefaultLimitAS",            config_parse_limit,            RLIMIT_AS, arg_default_rlimit             },
+                { "Manager", "DefaultLimitNPROC",         config_parse_limit,            RLIMIT_NPROC, arg_default_rlimit          },
+                { "Manager", "DefaultLimitMEMLOCK",       config_parse_limit,            RLIMIT_MEMLOCK, arg_default_rlimit        },
+                { "Manager", "DefaultLimitLOCKS",         config_parse_limit,            RLIMIT_LOCKS, arg_default_rlimit          },
+                { "Manager", "DefaultLimitSIGPENDING",    config_parse_limit,            RLIMIT_SIGPENDING, arg_default_rlimit     },
+                { "Manager", "DefaultLimitMSGQUEUE",      config_parse_limit,            RLIMIT_MSGQUEUE, arg_default_rlimit       },
+                { "Manager", "DefaultLimitNICE",          config_parse_limit,            RLIMIT_NICE, arg_default_rlimit           },
+                { "Manager", "DefaultLimitRTPRIO",        config_parse_limit,            RLIMIT_RTPRIO, arg_default_rlimit         },
+                { "Manager", "DefaultLimitRTTIME",        config_parse_limit,            RLIMIT_RTTIME, arg_default_rlimit         },
                 { "Manager", "DefaultCPUAccounting",      config_parse_bool,             0, &arg_default_cpu_accounting            },
                 { "Manager", "DefaultBlockIOAccounting",  config_parse_bool,             0, &arg_default_blockio_accounting        },
                 { "Manager", "DefaultMemoryAccounting",   config_parse_bool,             0, &arg_default_memory_accounting         },
@@ -692,8 +704,14 @@ static int parse_config_file(void) {
                 CONF_PATHS_NULSTR("systemd/system.conf.d") :
                 CONF_PATHS_NULSTR("systemd/user.conf.d");
 
-        config_parse_many(fn, conf_dirs_nulstr, "Manager\0",
-                          config_item_table_lookup, items, false, NULL);
+        config_parse_many(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, false, NULL);
+
+        /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY
+         * like everywhere else. */
+        if (arg_default_timeout_start_usec <= 0)
+                arg_default_timeout_start_usec = USEC_INFINITY;
+        if (arg_default_timeout_stop_usec <= 0)
+                arg_default_timeout_stop_usec = USEC_INFINITY;
 
         return 0;
 }
@@ -743,7 +761,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DESERIALIZE,
                 ARG_SWITCHED_ROOT,
                 ARG_DEFAULT_STD_OUTPUT,
-                ARG_DEFAULT_STD_ERROR
+                ARG_DEFAULT_STD_ERROR,
+                ARG_MACHINE_ID
         };
 
         static const struct option options[] = {
@@ -769,6 +788,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "switched-root",            no_argument,       NULL, ARG_SWITCHED_ROOT            },
                 { "default-standard-output",  required_argument, NULL, ARG_DEFAULT_STD_OUTPUT,      },
                 { "default-standard-error",   required_argument, NULL, ARG_DEFAULT_STD_ERROR,       },
+                { "machine-id",               required_argument, NULL, ARG_MACHINE_ID               },
                 {}
         };
 
@@ -964,6 +984,14 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_switched_root = true;
                         break;
 
+                case ARG_MACHINE_ID:
+                        r = set_machine_id(optarg);
+                        if (r < 0) {
+                                log_error("MachineID '%s' is not valid.", optarg);
+                                return r;
+                        }
+                        break;
+
                 case 'h':
                         arg_action = ACTION_HELP;
                         if (arg_no_pager < 0)
@@ -1335,7 +1363,11 @@ int main(int argc, char *argv[]) {
                         initrd_timestamp = userspace_timestamp;
 
                 if (!skip_setup) {
-                        mount_setup_early();
+                        r = mount_setup_early();
+                        if (r < 0) {
+                                error_message = "Failed to early mount API filesystems";
+                                goto finish;
+                        }
                         dual_timestamp_get(&security_start_timestamp);
                         if (mac_selinux_setup(&loaded_policy) < 0) {
                                 error_message = "Failed to load SELinux policy";
@@ -1386,8 +1418,14 @@ int main(int argc, char *argv[]) {
                                  * saving time change. All kernel local time concepts will be treated
                                  * as UTC that way.
                                  */
-                                clock_reset_timewarp();
+                                (void) clock_reset_timewarp();
                         }
+
+                        r = clock_apply_epoch();
+                        if (r < 0)
+                                log_error_errno(r, "Current system time is before build time, but cannot correct: %m");
+                        else if (r > 0)
+                                log_info("System time before build time, advancing clock.");
                 }
 
                 /* Set the default for later on, but don't actually
@@ -1424,6 +1462,17 @@ int main(int argc, char *argv[]) {
                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
         }
 
+        if (getpid() == 1) {
+                /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit)
+                 * will process core dumps for system services by default. */
+                (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY));
+
+                /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
+                 * until the systemd-coredump tool is enabled via sysctl. */
+                if (!skip_setup)
+                        (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
+        }
+
         /* Initialize default unit */
         r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
         if (r < 0) {
@@ -1617,7 +1666,7 @@ int main(int argc, char *argv[]) {
                         status_welcome();
 
                 hostname_setup();
-                machine_id_setup(NULL);
+                machine_id_setup(NULL, arg_machine_id);
                 loopback_setup();
                 bump_unix_max_dgram_qlen();
 
@@ -1631,14 +1680,14 @@ 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 (arg_capability_bounding_set_drop) {
-                r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
+        if (!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");
                         error_message = "Failed to drop capability bounding set of usermode helpers";
                         goto finish;
                 }
-                r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
+                r = capability_bounding_set_drop(arg_capability_bounding_set, true);
                 if (r < 0) {
                         log_emergency_errno(r, "Failed to drop capability bounding set: %m");
                         error_message = "Failed to drop capability bounding set";
@@ -1665,7 +1714,7 @@ int main(int argc, char *argv[]) {
                 if (empty_etc) {
                         r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0);
                         if (r < 0)
-                                log_warning_errno(r, "Failed to populate /etc with preset unit settings, ignoring: %m");
+                                log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r, "Failed to populate /etc with preset unit settings, ignoring: %m");
                         else
                                 log_info("Populated /etc with preset unit settings.");
                 }
@@ -1707,7 +1756,7 @@ int main(int argc, char *argv[]) {
         arg_serialization = safe_fclose(arg_serialization);
 
         if (queue_default_job) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 Unit *target = NULL;
                 Job *default_unit_job;
 
@@ -1940,6 +1989,15 @@ finish:
                                 (void) clearenv();
 
                         assert(i <= args_size);
+
+                        /*
+                         * We want valgrind to print its memory usage summary before reexecution.
+                         * Valgrind won't do this is on its own on exec(), but it will do it on exit().
+                         * Hence, to ensure we get a summary here, fork() off a child, let it exit() cleanly,
+                         * so that it prints the summary, and wait() for it in the parent, before proceeding into the exec().
+                         */
+                        valgrind_summary_hack();
+
                         (void) execv(args[0], (char* const*) args);
                 }
 
index edff6758c501c3a359f4bd3e8e52a1ab1bb6582a..f36cf5e320b8a7bfe3e4b27d0d342592fdd2f6e1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -233,7 +231,7 @@ static int have_ask_password(void) {
 
                 errno = 0;
                 de = readdir(dir);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
                 if (!de)
                         return false;
@@ -380,6 +378,9 @@ static int enable_special_signals(Manager *m) {
 
         assert(m);
 
+        if (m->test_run)
+                return 0;
+
         /* Enable that we get SIGINT on control-alt-del. In containers
          * this will fail with EPERM (older) or EINVAL (newer), so
          * ignore that. */
@@ -595,8 +596,6 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
         m->have_ask_password = -EINVAL; /* we don't know */
         m->first_boot = -1;
 
-        m->cgroup_netclass_registry_last = CGROUP_NETCLASS_FIXED_MAX;
-
         m->test_run = test_run;
 
         /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */
@@ -980,13 +979,11 @@ Manager* manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
-        hashmap_free(m->cgroup_netclass_registry);
-
         free(m->switch_root);
         free(m->switch_root_init);
 
         for (i = 0; i < _RLIMIT_MAX; i++)
-                free(m->rlimit[i]);
+                m->rlimit[i] = mfree(m->rlimit[i]);
 
         assert(hashmap_isempty(m->units_requiring_mounts_for));
         hashmap_free(m->units_requiring_mounts_for);
@@ -1257,7 +1254,7 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode
 }
 
 int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(m);
@@ -1700,7 +1697,7 @@ static int manager_dispatch_sigchld(Manager *m) {
 }
 
 static int manager_start_target(Manager *m, const char *name, JobMode mode) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         log_debug("Activating special unit %s", name);
@@ -1885,23 +1882,21 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
                         switch (sfsi.ssi_signo - SIGRTMIN) {
 
                         case 20:
-                                log_debug("Enabling showing of status.");
                                 manager_set_show_status(m, SHOW_STATUS_YES);
                                 break;
 
                         case 21:
-                                log_debug("Disabling showing of status.");
                                 manager_set_show_status(m, SHOW_STATUS_NO);
                                 break;
 
                         case 22:
                                 log_set_max_level(LOG_DEBUG);
-                                log_notice("Setting log level to debug.");
+                                log_info("Setting log level to debug.");
                                 break;
 
                         case 23:
                                 log_set_max_level(LOG_INFO);
-                                log_notice("Setting log level to info.");
+                                log_info("Setting log level to info.");
                                 break;
 
                         case 24:
@@ -2576,6 +2571,10 @@ int manager_reload(Manager *m) {
         /* Third, fire things up! */
         manager_coldplug(m);
 
+        /* Sync current state of bus names with our set of listening units */
+        if (m->api_bus)
+                manager_sync_bus_names(m, m->api_bus);
+
         assert(m->n_reloading > 0);
         m->n_reloading--;
 
@@ -2918,6 +2917,8 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
         assert(m);
 
         for (i = 0; i < _RLIMIT_MAX; i++) {
+                m->rlimit[i] = mfree(m->rlimit[i]);
+
                 if (!default_rlimit[i])
                         continue;
 
@@ -2961,6 +2962,9 @@ void manager_set_show_status(Manager *m, ShowStatus mode) {
         if (m->running_as != MANAGER_SYSTEM)
                 return;
 
+        if (m->show_status != mode)
+                log_debug("%s showing of status.",
+                          mode == SHOW_STATUS_NO ? "Disabling" : "Enabling");
         m->show_status = mode;
 
         if (mode > 0)
@@ -3087,18 +3091,18 @@ ManagerState manager_state(Manager *m) {
 
         /* Is the special shutdown target queued? If so, we are in shutdown state */
         u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
-        if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))
+        if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START))
                 return MANAGER_STOPPING;
 
         /* Are the rescue or emergency targets active or queued? If so we are in maintenance state */
         u = manager_get_unit(m, SPECIAL_RESCUE_TARGET);
         if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
-                  (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
+                  (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START))))
                 return MANAGER_MAINTENANCE;
 
         u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET);
         if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
-                  (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
+                  (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START))))
                 return MANAGER_MAINTENANCE;
 
         /* Are there any failed units? If so, we are in degraded mode */
index b5b258f909105d38b914a9ca74505f34d982a98b..9803f731295b9759eccebb30e0d2a987492160b9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <libmount.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include <libmount.h>
 
 #include "sd-bus.h"
 #include "sd-event.h"
+
 #include "cgroup-util.h"
 #include "fdset.h"
 #include "hashmap.h"
@@ -306,10 +305,6 @@ struct Manager {
         const char *unit_log_format_string;
 
         int first_boot;
-
-        /* Used for NetClass=auto units */
-        Hashmap *cgroup_netclass_registry;
-        uint32_t cgroup_netclass_registry_last;
 };
 
 int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m);
index 2b8d590ed1f94dbffbbc65df1e25f7e2b9f2c313..de1a361cc4c554dc290c5078fb4c07e8f641279a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -158,11 +156,13 @@ static int mount_one(const MountPoint *p, bool relabel) {
 
         /* Relabel first, just in case */
         if (relabel)
-                label_fix(p->where, true, true);
+                (void) label_fix(p->where, true, true);
 
         r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
-        if (r < 0 && r != -ENOENT)
-                return r;
+        if (r < 0 && r != -ENOENT) {
+                log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, r, "Failed to determine whether %s is a mount point: %m", p->where);
+                return (p->mode & MNT_FATAL) ? r : 0;
+        }
         if (r > 0)
                 return 0;
 
@@ -173,9 +173,9 @@ static int mount_one(const MountPoint *p, bool relabel) {
         /* The access mode here doesn't really matter too much, since
          * the mounted file system will take precedence anyway. */
         if (relabel)
-                mkdir_p_label(p->where, 0755);
+                (void) mkdir_p_label(p->where, 0755);
         else
-                mkdir_p(p->where, 0755);
+                (void) mkdir_p(p->where, 0755);
 
         log_debug("Mounting %s to %s of type %s with options %s.",
                   p->what,
@@ -188,29 +188,25 @@ static int mount_one(const MountPoint *p, bool relabel) {
                   p->type,
                   p->flags,
                   p->options) < 0) {
-                log_full((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, "Failed to mount %s at %s: %m", p->type, p->where);
+                log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, errno, "Failed to mount %s at %s: %m", p->type, p->where);
                 return (p->mode & MNT_FATAL) ? -errno : 0;
         }
 
         /* Relabel again, since we now mounted something fresh here */
         if (relabel)
-                label_fix(p->where, false, false);
+                (void) label_fix(p->where, false, false);
 
         return 1;
 }
 
-int mount_setup_early(void) {
+static int mount_points_setup(unsigned n, bool loaded_policy) {
         unsigned i;
         int r = 0;
 
-        assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table));
-
-        /* Do a minimal mount of /proc and friends to enable the most
-         * basic stuff, such as SELinux */
-        for (i = 0; i < N_EARLY_MOUNT; i ++)  {
+        for (i = 0; i < n; i ++) {
                 int j;
 
-                j = mount_one(mount_table + i, false);
+                j = mount_one(mount_table + i, loaded_policy);
                 if (j != 0 && r >= 0)
                         r = j;
         }
@@ -218,6 +214,14 @@ int mount_setup_early(void) {
         return r;
 }
 
+int mount_setup_early(void) {
+        assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table));
+
+        /* Do a minimal mount of /proc and friends to enable the most
+         * basic stuff, such as SELinux */
+        return mount_points_setup(N_EARLY_MOUNT, false);
+}
+
 int mount_cgroup_controllers(char ***join_controllers) {
         _cleanup_set_free_free_ Set *controllers = NULL;
         int r;
@@ -304,13 +308,18 @@ int mount_cgroup_controllers(char ***join_controllers) {
                                         return log_oom();
 
                                 r = symlink(options, t);
-                                if (r < 0 && errno != EEXIST)
-                                        return log_error_errno(errno, "Failed to create symlink %s: %m", t);
+                                if (r >= 0) {
 #ifdef SMACK_RUN_LABEL
-                                r = mac_smack_copy(t, options);
-                                if (r < 0 && r != -EOPNOTSUPP)
-                                        return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t);
+                                        _cleanup_free_ char *src;
+                                        src = strappend("/sys/fs/cgroup/", options);
+                                        if (!src)
+                                                return log_oom();
+                                        r = mac_smack_copy(t, src);
+                                        if (r < 0 && r != -EOPNOTSUPP)
+                                                return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", src, t);
 #endif
+                                } else if (errno != EEXIST)
+                                        return log_error_errno(errno, "Failed to create symlink %s: %m", t);
                         }
                 }
         }
@@ -347,16 +356,9 @@ static int nftw_cb(
 #endif
 
 int mount_setup(bool loaded_policy) {
-        unsigned i;
         int r = 0;
 
-        for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
-                int j;
-
-                j = mount_one(mount_table + i, loaded_policy);
-                if (j != 0 && r >= 0)
-                        r = j;
-        }
+        r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy);
 
         if (r < 0)
                 return r;
index b32fbc5a529ffeaf1b676bb5617ae4df5d786469..647bd770ae41ccd37a65c4f252675d4a0c62a7a7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9b44357e905f26895e571f90df5736ad2209630d..de1075d3a0677224f05faff70efee13ad97d40be 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -152,29 +150,27 @@ static void mount_init(Unit *u) {
         u->ignore_on_isolate = true;
 }
 
-static int mount_arm_timer(Mount *m) {
+static int mount_arm_timer(Mount *m, usec_t usec) {
         int r;
 
         assert(m);
 
-        if (m->timeout_usec <= 0) {
-                m->timer_event_source = sd_event_source_unref(m->timer_event_source);
-                return 0;
-        }
-
         if (m->timer_event_source) {
-                r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
+                r = sd_event_source_set_time(m->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(m)->manager->event,
                         &m->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + m->timeout_usec, 0,
+                        usec, 0,
                         mount_dispatch_timer, m);
         if (r < 0)
                 return r;
@@ -335,7 +331,7 @@ static int mount_add_device_links(Mount *m) {
         if (mount_is_auto(p) && UNIT(m)->manager->running_as == MANAGER_SYSTEM)
                 device_wants_mount = true;
 
-        r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
+        r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
         if (r < 0)
                 return r;
 
@@ -653,7 +649,7 @@ static int mount_coldplug(Unit *u) {
                 if (r < 0)
                         return r;
 
-                r = mount_arm_timer(m);
+                r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec));
                 if (r < 0)
                         return r;
         }
@@ -725,11 +721,11 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
 
         r = unit_setup_exec_runtime(UNIT(m));
         if (r < 0)
-                goto fail;
+                return r;
 
-        r = mount_arm_timer(m);
+        r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
         if (r < 0)
-                goto fail;
+                return r;
 
         exec_params.environment = UNIT(m)->manager->environment;
         exec_params.confirm_spawn = UNIT(m)->manager->confirm_spawn;
@@ -745,21 +741,16 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                        m->exec_runtime,
                        &pid);
         if (r < 0)
-                goto fail;
+                return r;
 
         r = unit_watch_pid(UNIT(m), pid);
         if (r < 0)
                 /* FIXME: we need to do something here */
-                goto fail;
+                return r;
 
         *_pid = pid;
 
         return 0;
-
-fail:
-        m->timer_event_source = sd_event_source_unref(m->timer_event_source);
-
-        return r;
 }
 
 static void mount_enter_dead(Mount *m, MountResult f) {
@@ -805,7 +796,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = mount_arm_timer(m);
+                r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
                 if (r < 0)
                         goto fail;
 
@@ -1563,17 +1554,21 @@ static void mount_shutdown(Manager *m) {
         m->mount_monitor = NULL;
 }
 
-static int mount_get_timeout(Unit *u, uint64_t *timeout) {
+static int mount_get_timeout(Unit *u, usec_t *timeout) {
         Mount *m = MOUNT(u);
+        usec_t t;
         int r;
 
         if (!m->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(m->timer_event_source, timeout);
+        r = sd_event_source_get_time(m->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
index 83d14ae71383c2c3e82748783bfd6587264cfef8..3b343c6b1f361612454264dc061898857b5198fe 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 typedef struct Mount Mount;
 
-#include "kill.h"
 #include "execute.h"
+#include "kill.h"
 
 typedef enum MountExecCommand {
         MOUNT_EXEC_MOUNT,
index 81ba09ea5ddf9166e493455ae030e9013a710d4a..4fa381db5bcf6c31ea3ce3326d0f0c10ee06a257 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 00ab22bf2e6982090c8e86309b7cb140d5381f93..40bee74e2caa523d143e764b29138d2f9fdbe280 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 02fb134bb934361dbc20823dc430970c086f1c01..460c1d3bf2f42d9227a6d9a68c02402a6848edfa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -465,7 +463,8 @@ static void path_enter_dead(Path *p, PathResult f) {
 }
 
 static void path_enter_running(Path *p) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *trigger;
         int r;
 
         assert(p);
@@ -474,7 +473,14 @@ static void path_enter_running(Path *p) {
         if (unit_stop_pending(UNIT(p)))
                 return;
 
-        r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)), JOB_REPLACE, &error, NULL);
+        trigger = UNIT_TRIGGER(UNIT(p));
+        if (!trigger) {
+                log_unit_error(UNIT(p), "Unit to trigger vanished.");
+                path_enter_dead(p, TIMER_FAILURE_RESOURCES);
+                return;
+        }
+
+        r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
         if (r < 0)
                 goto fail;
 
@@ -555,12 +561,16 @@ static void path_mkdir(Path *p) {
 
 static int path_start(Unit *u) {
         Path *p = PATH(u);
+        Unit *trigger;
 
         assert(p);
         assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
 
-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+        trigger = UNIT_TRIGGER(u);
+        if (!trigger || trigger->load_state != UNIT_LOADED) {
+                log_unit_error(u, "Refusing to start, unit to trigger not loaded.");
                 return -ENOENT;
+        }
 
         path_mkdir(p);
 
index deb9bab1e5040a277a43f47146985c065c326a8c..bbbcebd78e4090750f549be2d8bf6f392174cc1b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 1953af1f88a58e1a8e72e4c8c3ab756f68d431e6..c5d0ecef04416936fe38dc30775ffacdec50b4ad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -66,29 +64,27 @@ static void scope_done(Unit *u) {
         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 }
 
-static int scope_arm_timer(Scope *s) {
+static int scope_arm_timer(Scope *s, usec_t usec) {
         int r;
 
         assert(s);
 
-        if (s->timeout_stop_usec <= 0) {
-                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-                return 0;
-        }
-
         if (s->timer_event_source) {
-                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
+                r = sd_event_source_set_time(s->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(s)->manager->event,
                         &s->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0,
+                        usec, 0,
                         scope_dispatch_timer, s);
         if (r < 0)
                 return r;
@@ -190,20 +186,19 @@ static int scope_coldplug(Unit *u) {
         assert(s);
         assert(s->state == SCOPE_DEAD);
 
-        if (s->deserialized_state != s->state) {
-
-                if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
-                        r = scope_arm_timer(s);
-                        if (r < 0)
-                                return r;
-                }
-
-                if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
-                        unit_watch_all_pids(UNIT(s));
+        if (s->deserialized_state == s->state)
+                return 0;
 
-                scope_set_state(s, s->deserialized_state);
+        if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
+                r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec));
+                if (r < 0)
+                        return r;
         }
 
+        if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
+                unit_watch_all_pids(UNIT(s));
+
+        scope_set_state(s, s->deserialized_state);
         return 0;
 }
 
@@ -261,7 +256,7 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
                 r = 1;
 
         if (r > 0) {
-                r = scope_arm_timer(s);
+                r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
                 if (r < 0)
                         goto fail;
 
@@ -348,17 +343,21 @@ static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, -1, error);
 }
 
-static int scope_get_timeout(Unit *u, uint64_t *timeout) {
+static int scope_get_timeout(Unit *u, usec_t *timeout) {
         Scope *s = SCOPE(u);
+        usec_t t;
         int r;
 
         if (!s->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(s->timer_event_source, timeout);
+        r = sd_event_source_get_time(s->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
index f838ee535728d29b1a8fa7d320af739cd3a7b2aa..2dc86325c5667828332d701118520e9b9de1389c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8856927c88f62664bc4f34eb3ccda60a4dd8a3f5..2cdfcf7b5d1ab3ef52308b979f1fe37b8e769305 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -134,52 +132,45 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
 #endif
 
         va_start(ap, fmt);
-        log_internalv(LOG_AUTH | callback_type_to_priority(type),
-                      0, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
+        log_internalv(LOG_AUTH | callback_type_to_priority(type), 0, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
         va_end(ap);
 
         return 0;
 }
 
-/*
-   Function must be called once to initialize the SELinux AVC environment.
-   Sets up callbacks.
-   If you want to cleanup memory you should need to call selinux_access_finish.
-*/
-static int access_init(void) {
-        int r = 0;
+static int access_init(sd_bus_error *error) {
 
-        if (avc_open(NULL, 0))
-                return log_error_errno(errno, "avc_open() failed: %m");
+        if (!mac_selinux_use())
+                return 0;
 
-        selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
-        selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
+        if (initialized)
+                return 1;
 
-        if (security_getenforce() < 0){
-                r = -errno;
-                avc_destroy();
-        }
+        if (avc_open(NULL, 0) != 0) {
+                int enforce, saved_errno = errno;
 
-        return r;
-}
-
-static int mac_selinux_access_init(sd_bus_error *error) {
-        int r;
+                enforce = security_getenforce();
+                log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m");
 
-        if (initialized)
-                return 0;
+                /* If enforcement isn't on, then let's suppress this
+                 * error, and just don't do any AVC checks. The
+                 * warning we printed is hence all the admin will
+                 * see. */
+                if (enforce == 0)
+                        return 0;
 
-        if (!mac_selinux_use())
-                return 0;
+                /* Return an access denied error, if we couldn't load
+                 * the AVC but enforcing mode was on, or we couldn't
+                 * determine whether it is one. */
+                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror(saved_errno));
+        }
 
-        r = access_init();
-        if (r < 0)
-                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
+        selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
+        selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
 
         initialized = true;
-        return 0;
+        return 1;
 }
-#endif
 
 /*
    This function communicates with the kernel to check whether or not it should
@@ -193,8 +184,7 @@ int mac_selinux_generic_access_check(
                 const char *permission,
                 sd_bus_error *error) {
 
-#ifdef HAVE_SELINUX
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         const char *tclass = NULL, *scon = NULL;
         struct audit_info audit_info = {};
         _cleanup_free_ char *cl = NULL;
@@ -206,11 +196,8 @@ int mac_selinux_generic_access_check(
         assert(permission);
         assert(error);
 
-        if (!mac_selinux_use())
-                return 0;
-
-        r = mac_selinux_access_init(error);
-        if (r < 0)
+        r = access_init(error);
+        if (r <= 0)
                 return r;
 
         r = sd_bus_query_sender_creds(
@@ -277,7 +264,17 @@ finish:
         }
 
         return r;
+}
+
 #else
+
+int mac_selinux_generic_access_check(
+                sd_bus_message *message,
+                const char *path,
+                const char *permission,
+                sd_bus_error *error) {
+
         return 0;
-#endif
 }
+
+#endif
index 30725521cb34d4a77a3def35410d2fb7aa1bd938..8f1f058a32faef9c248436d1e12ad4591031b5ff 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "bus-util.h"
 #include "manager.h"
 
index d4757e08530ace7fa59c7b59bf265732f1b52bbe..9a115a4387ec429bce5398d59d743f4671d827bd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 9ac2276576e9507e0ae7d1919ee1b507ce506d99..7b613249b068476d8df5c216866bc45d73667c25 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index c27b70fa3ca208c9ab151db80a537991f6d386f4..ac7e41d77788f3fed4e05138819dad9bb56f06c6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -112,14 +110,13 @@ static void service_init(Unit *u) {
         s->timeout_start_usec = u->manager->default_timeout_start_usec;
         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
         s->restart_usec = u->manager->default_restart_usec;
+        s->runtime_max_usec = USEC_INFINITY;
         s->type = _SERVICE_TYPE_INVALID;
         s->socket_fd = -1;
         s->bus_endpoint_fd = -1;
         s->stdin_fd = s->stdout_fd = s->stderr_fd = -1;
         s->guess_main_pid = true;
 
-        RATELIMIT_INIT(s->start_limit, u->manager->default_start_limit_interval, u->manager->default_start_limit_burst);
-
         s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
 }
 
@@ -216,7 +213,7 @@ static void service_start_watchdog(Service *s) {
                 return;
 
         if (s->watchdog_event_source) {
-                r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
+                r = sd_event_source_set_time(s->watchdog_event_source, usec_add(s->watchdog_timestamp.monotonic, s->watchdog_usec));
                 if (r < 0) {
                         log_unit_warning_errno(UNIT(s), r, "Failed to reset watchdog timer: %m");
                         return;
@@ -228,7 +225,7 @@ static void service_start_watchdog(Service *s) {
                                 UNIT(s)->manager->event,
                                 &s->watchdog_event_source,
                                 CLOCK_MONOTONIC,
-                                s->watchdog_timestamp.monotonic + s->watchdog_usec, 0,
+                                usec_add(s->watchdog_timestamp.monotonic, s->watchdog_usec), 0,
                                 service_dispatch_watchdog, s);
                 if (r < 0) {
                         log_unit_warning_errno(UNIT(s), r, "Failed to add watchdog timer: %m");
@@ -301,7 +298,6 @@ static void service_done(Unit *u) {
 
         s->pid_file = mfree(s->pid_file);
         s->status_text = mfree(s->status_text);
-        s->reboot_arg = mfree(s->reboot_arg);
 
         s->exec_runtime = exec_runtime_unref(s->exec_runtime);
         exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
@@ -323,6 +319,8 @@ static void service_done(Unit *u) {
                 s->bus_name = mfree(s->bus_name);
         }
 
+        s->bus_name_owner = mfree(s->bus_name_owner);
+
         s->bus_endpoint_fd = safe_close(s->bus_endpoint_fd);
         service_close_socket_fd(s);
         service_connection_unref(s);
@@ -431,18 +429,21 @@ static int service_arm_timer(Service *s, usec_t usec) {
         assert(s);
 
         if (s->timer_event_source) {
-                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + usec);
+                r = sd_event_source_set_time(s->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(s)->manager->event,
                         &s->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + usec, 0,
+                        usec, 0,
                         service_dispatch_timer, s);
         if (r < 0)
                 return r;
@@ -507,6 +508,9 @@ static int service_verify(Service *s) {
         if (!s->usb_function_descriptors && s->usb_function_strings)
                 log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring.");
 
+        if (s->runtime_max_usec != USEC_INFINITY && s->type == SERVICE_ONESHOT)
+                log_unit_warning(UNIT(s), "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring.");
+
         return 0;
 }
 
@@ -622,7 +626,7 @@ static int service_add_extras(Service *s) {
 
         /* Oneshot services have disabled start timeout by default */
         if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
-                s->timeout_start_usec = 0;
+                s->timeout_start_usec = USEC_INFINITY;
 
         service_fix_output(s);
 
@@ -880,6 +884,7 @@ static void service_set_state(Service *s, ServiceState state) {
 
         if (!IN_SET(state,
                     SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+                    SERVICE_RUNNING,
                     SERVICE_RELOAD,
                     SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
                     SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
@@ -952,6 +957,37 @@ static void service_set_state(Service *s, ServiceState state) {
         unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
 }
 
+static usec_t service_coldplug_timeout(Service *s) {
+        assert(s);
+
+        switch (s->deserialized_state) {
+
+        case SERVICE_START_PRE:
+        case SERVICE_START:
+        case SERVICE_START_POST:
+        case SERVICE_RELOAD:
+                return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec);
+
+        case SERVICE_RUNNING:
+                return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec);
+
+        case SERVICE_STOP:
+        case SERVICE_STOP_SIGABRT:
+        case SERVICE_STOP_SIGTERM:
+        case SERVICE_STOP_SIGKILL:
+        case SERVICE_STOP_POST:
+        case SERVICE_FINAL_SIGTERM:
+        case SERVICE_FINAL_SIGKILL:
+                return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec);
+
+        case SERVICE_AUTO_RESTART:
+                return usec_add(UNIT(s)->inactive_enter_timestamp.monotonic, s->restart_usec);
+
+        default:
+                return USEC_INFINITY;
+        }
+}
+
 static int service_coldplug(Unit *u) {
         Service *s = SERVICE(u);
         int r;
@@ -962,31 +998,9 @@ static int service_coldplug(Unit *u) {
         if (s->deserialized_state == s->state)
                 return 0;
 
-        if (IN_SET(s->deserialized_state,
-                   SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
-                   SERVICE_RELOAD,
-                   SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
-                   SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
-
-                usec_t k;
-
-                k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec;
-
-                /* For the start/stop timeouts 0 means off */
-                if (k > 0) {
-                        r = service_arm_timer(s, k);
-                        if (r < 0)
-                                return r;
-                }
-        }
-
-        if (s->deserialized_state == SERVICE_AUTO_RESTART) {
-
-                /* The restart timeouts 0 means immediately */
-                r = service_arm_timer(s, s->restart_usec);
-                if (r < 0)
-                        return r;
-        }
+        r = service_arm_timer(s, service_coldplug_timeout(s));
+        if (r < 0)
+                return r;
 
         if (s->main_pid > 0 &&
             pid_is_unwaited(s->main_pid) &&
@@ -1173,7 +1187,7 @@ static int service_spawn(
 
         r = unit_setup_exec_runtime(UNIT(s));
         if (r < 0)
-                goto fail;
+                return r;
 
         if (pass_fds ||
             s->exec_context.std_input == EXEC_INPUT_SOCKET ||
@@ -1182,55 +1196,42 @@ static int service_spawn(
 
                 r = service_collect_fds(s, &fds, &fd_names);
                 if (r < 0)
-                        goto fail;
+                        return r;
 
                 n_fds = r;
         }
 
-        if (timeout > 0) {
-                r = service_arm_timer(s, timeout);
-                if (r < 0)
-                        goto fail;
-        } else
-                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+        r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout));
+        if (r < 0)
+                return r;
 
         r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
         if (r < 0)
-                goto fail;
+                return r;
 
         our_env = new0(char*, 6);
-        if (!our_env) {
-                r = -ENOMEM;
-                goto fail;
-        }
+        if (!our_env)
+                return -ENOMEM;
 
         if (is_control ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE)
-                if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
+                if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0)
+                        return -ENOMEM;
 
         if (s->main_pid > 0)
-                if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
+                if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0)
+                        return -ENOMEM;
 
         if (UNIT(s)->manager->running_as != MANAGER_SYSTEM)
-                if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
+                if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0)
+                        return -ENOMEM;
 
         if (s->socket_fd >= 0) {
                 union sockaddr_union sa;
                 socklen_t salen = sizeof(sa);
 
                 r = getpeername(s->socket_fd, &sa.sa, &salen);
-                if (r < 0) {
-                        r = -errno;
-                        goto fail;
-                }
+                if (r < 0)
+                        return -errno;
 
                 if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) {
                         _cleanup_free_ char *addr = NULL;
@@ -1239,34 +1240,26 @@ static int service_spawn(
 
                         r = sockaddr_pretty(&sa.sa, salen, true, false, &addr);
                         if (r < 0)
-                                goto fail;
+                                return r;
 
                         t = strappend("REMOTE_ADDR=", addr);
-                        if (!t) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
+                        if (!t)
+                                return -ENOMEM;
                         our_env[n_env++] = t;
 
                         port = sockaddr_port(&sa.sa);
-                        if (port < 0) {
-                                r = port;
-                                goto fail;
-                        }
+                        if (port < 0)
+                                return port;
 
-                        if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
+                        if (asprintf(&t, "REMOTE_PORT=%u", port) < 0)
+                                return -ENOMEM;
                         our_env[n_env++] = t;
                 }
         }
 
         final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
-        if (!final_env) {
-                r = -ENOMEM;
-                goto fail;
-        }
+        if (!final_env)
+                return -ENOMEM;
 
         if (is_control && UNIT(s)->cgroup_path) {
                 path = strjoina(UNIT(s)->cgroup_path, "/control");
@@ -1278,7 +1271,7 @@ static int service_spawn(
                 r = bus_kernel_create_endpoint(UNIT(s)->manager->running_as == MANAGER_SYSTEM ? "system" : "user",
                                                UNIT(s)->id, &bus_endpoint_path);
                 if (r < 0)
-                        goto fail;
+                        return r;
 
                 /* Pass the fd to the exec_params so that the child process can upload the policy.
                  * Keep a reference to the fd in the service, so the endpoint is kept alive as long
@@ -1312,22 +1305,16 @@ static int service_spawn(
                        s->exec_runtime,
                        &pid);
         if (r < 0)
-                goto fail;
+                return r;
 
         r = unit_watch_pid(UNIT(s), pid);
         if (r < 0)
                 /* FIXME: we need to do something here */
-                goto fail;
+                return r;
 
         *_pid = pid;
 
         return 0;
-
-fail:
-        if (timeout)
-                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-
-        return r;
 }
 
 static int main_pid_good(Service *s) {
@@ -1430,12 +1417,12 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
 
         if (s->result != SERVICE_SUCCESS) {
                 log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result));
-                failure_action(UNIT(s)->manager, s->failure_action, s->reboot_arg);
+                failure_action(UNIT(s)->manager, s->failure_action, UNIT(s)->reboot_arg);
         }
 
         if (allow_restart && service_shall_restart(s)) {
 
-                r = service_arm_timer(s, s->restart_usec);
+                r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
                 if (r < 0)
                         goto fail;
 
@@ -1456,7 +1443,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
          * out-of-date, and some software might be confused by it, so
          * let's remove it. */
         if (s->pid_file)
-                unlink_noerrno(s->pid_file);
+                (void) unlink(s->pid_file);
 
         return;
 
@@ -1543,11 +1530,9 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
                 goto fail;
 
         if (r > 0) {
-                if (s->timeout_stop_usec > 0) {
-                        r = service_arm_timer(s, s->timeout_stop_usec);
-                        if (r < 0)
-                                goto fail;
-                }
+                r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
+                if (r < 0)
+                        goto fail;
 
                 service_set_state(s, state);
         } else if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM) && s->kill_context.send_sigkill)
@@ -1575,8 +1560,7 @@ static void service_enter_stop_by_notify(Service *s) {
 
         unit_watch_all_pids(UNIT(s));
 
-        if (s->timeout_stop_usec > 0)
-                service_arm_timer(s, s->timeout_stop_usec);
+        service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
 
         /* The service told us it's stopping, so it's as if we SIGTERM'd it. */
         service_set_state(s, SERVICE_STOP_SIGTERM);
@@ -1646,6 +1630,8 @@ static void service_enter_running(Service *s, ServiceResult f) {
         if (f != SERVICE_SUCCESS)
                 s->result = f;
 
+        service_unwatch_control_pid(s);
+
         if (service_good(s)) {
 
                 /* If there are any queued up sd_notify()
@@ -1654,8 +1640,10 @@ static void service_enter_running(Service *s, ServiceResult f) {
                         service_enter_reload_by_notify(s);
                 else if (s->notify_state == NOTIFY_STOPPING)
                         service_enter_stop_by_notify(s);
-                else
+                else {
                         service_set_state(s, SERVICE_RUNNING);
+                        service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec));
+                }
 
         } else if (s->remain_after_exit)
                 service_set_state(s, SERVICE_EXITED);
@@ -1709,6 +1697,7 @@ static void service_kill_control_processes(Service *s) {
 
 static void service_enter_start(Service *s) {
         ExecCommand *c;
+        usec_t timeout;
         pid_t pid;
         int r;
 
@@ -1740,9 +1729,16 @@ static void service_enter_start(Service *s) {
                 return;
         }
 
+        if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE))
+                /* For simple + idle this is the main process. We don't apply any timeout here, but
+                 * service_enter_running() will later apply the .runtime_max_usec timeout. */
+                timeout = USEC_INFINITY;
+        else
+                timeout = s->timeout_start_usec;
+
         r = service_spawn(s,
                           c,
-                          IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_ONESHOT) ? s->timeout_start_usec : 0,
+                          timeout,
                           true,
                           true,
                           true,
@@ -1752,7 +1748,7 @@ static void service_enter_start(Service *s) {
         if (r < 0)
                 goto fail;
 
-        if (s->type == SERVICE_SIMPLE || s->type == SERVICE_IDLE) {
+        if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) {
                 /* For simple services we immediately start
                  * the START_POST binaries. */
 
@@ -1767,9 +1763,7 @@ static void service_enter_start(Service *s) {
                 s->control_pid = pid;
                 service_set_state(s, SERVICE_START);
 
-        } else if (s->type == SERVICE_ONESHOT ||
-                   s->type == SERVICE_DBUS ||
-                   s->type == SERVICE_NOTIFY) {
+        } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY)) {
 
                 /* For oneshot services we wait until the start
                  * process exited, too, but it is our main process. */
@@ -1829,7 +1823,7 @@ fail:
 }
 
 static void service_enter_restart(Service *s) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(s);
@@ -1838,7 +1832,7 @@ static void service_enter_restart(Service *s) {
                 /* Don't restart things if we are going down anyway */
                 log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart.");
 
-                r = service_arm_timer(s, s->restart_usec);
+                r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
                 if (r < 0)
                         goto fail;
 
@@ -1868,9 +1862,7 @@ fail:
 static void service_enter_reload_by_notify(Service *s) {
         assert(s);
 
-        if (s->timeout_start_usec > 0)
-                service_arm_timer(s, s->timeout_start_usec);
-
+        service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec));
         service_set_state(s, SERVICE_RELOAD);
 }
 
@@ -1911,6 +1903,7 @@ fail:
 }
 
 static void service_run_next_control(Service *s) {
+        usec_t timeout;
         int r;
 
         assert(s);
@@ -1922,9 +1915,14 @@ static void service_run_next_control(Service *s) {
         s->control_command = s->control_command->command_next;
         service_unwatch_control_pid(s);
 
+        if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
+                timeout = s->timeout_start_usec;
+        else
+                timeout = s->timeout_stop_usec;
+
         r = service_spawn(s,
                           s->control_command,
-                          IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec,
+                          timeout,
                           false,
                           !s->permissions_start_only,
                           !s->root_directory_start_only,
@@ -1986,20 +1984,8 @@ fail:
         service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
 }
 
-static int service_start_limit_test(Service *s) {
-        assert(s);
-
-        if (ratelimit_test(&s->start_limit))
-                return 0;
-
-        log_unit_warning(UNIT(s), "Start request repeated too quickly.");
-
-        return failure_action(UNIT(s)->manager, s->start_limit_action, s->reboot_arg);
-}
-
 static int service_start(Unit *u) {
         Service *s = SERVICE(u);
-        int r;
 
         assert(s);
 
@@ -2026,13 +2012,6 @@ static int service_start(Unit *u) {
 
         assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
 
-        /* Make sure we don't enter a busy loop of some kind. */
-        r = service_start_limit_test(s);
-        if (r < 0) {
-                service_enter_dead(s, SERVICE_FAILURE_START_LIMIT, false);
-                return r;
-        }
-
         s->result = SERVICE_SUCCESS;
         s->reload_result = SERVICE_SUCCESS;
         s->main_pid_known = false;
@@ -2122,6 +2101,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
 
         unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
         unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
+        unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner);
 
         r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
         if (r < 0)
@@ -2249,6 +2229,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                         log_unit_debug(u, "Failed to parse bus-name-good value: %s", value);
                 else
                         s->bus_name_good = b;
+        } else if (streq(key, "bus-name-owner")) {
+                r = free_and_strdup(&s->bus_name_owner, value);
+                if (r < 0)
+                        log_unit_error_errno(u, r, "Unable to deserialize current bus owner %s: %m", value);
         } else if (streq(key, "status-text")) {
                 char *t;
 
@@ -2356,6 +2340,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                 else {
                         asynchronous_close(s->stdin_fd);
                         s->stdin_fd = fdset_remove(fds, fd);
+                        s->exec_context.stdio_as_fds = true;
                 }
         } else if (streq(key, "stdout-fd")) {
                 int fd;
@@ -2365,6 +2350,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                 else {
                         asynchronous_close(s->stdout_fd);
                         s->stdout_fd = fdset_remove(fds, fd);
+                        s->exec_context.stdio_as_fds = true;
                 }
         } else if (streq(key, "stderr-fd")) {
                 int fd;
@@ -2374,6 +2360,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                 else {
                         asynchronous_close(s->stderr_fd);
                         s->stderr_fd = fdset_remove(fds, fd);
+                        s->exec_context.stdio_as_fds = true;
                 }
         } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
@@ -2779,7 +2766,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                         case SERVICE_START_POST:
                                 if (f != SERVICE_SUCCESS) {
-                                        service_enter_stop(s, f);
+                                        service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
                                         break;
                                 }
 
@@ -2869,12 +2856,16 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
 
         case SERVICE_START_POST:
                 log_unit_warning(UNIT(s), "Start-post operation timed out. Stopping.");
+                service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
+                break;
+
+        case SERVICE_RUNNING:
+                log_unit_warning(UNIT(s), "Service reached runtime time limit. Stopping.");
                 service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_RELOAD:
-                log_unit_warning(UNIT(s), "Reload operation timed out. Stopping.");
-                service_unwatch_control_pid(s);
+                log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process.");
                 service_kill_control_processes(s);
                 s->reload_result = SERVICE_FAILURE_TIMEOUT;
                 service_enter_running(s, SERVICE_SUCCESS);
@@ -3096,17 +3087,21 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
                 unit_add_to_dbus_queue(u);
 }
 
-static int service_get_timeout(Unit *u, uint64_t *timeout) {
+static int service_get_timeout(Unit *u, usec_t *timeout) {
         Service *s = SERVICE(u);
+        uint64_t t;
         int r;
 
         if (!s->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(s->timer_event_source, timeout);
+        r = sd_event_source_get_time(s->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
@@ -3134,6 +3129,13 @@ static void service_bus_name_owner_change(
 
         s->bus_name_good = !!new_owner;
 
+        /* Track the current owner, so we can reconstruct changes after a daemon reload */
+        r = free_and_strdup(&s->bus_name_owner, new_owner);
+        if (r < 0) {
+                log_unit_error_errno(u, r, "Unable to set new bus name owner %s: %m", new_owner);
+                return;
+        }
+
         if (s->type == SERVICE_DBUS) {
 
                 /* service_enter_running() will figure out what to
@@ -3150,7 +3152,7 @@ static void service_bus_name_owner_change(
                     s->state == SERVICE_RUNNING ||
                     s->state == SERVICE_RELOAD)) {
 
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 pid_t pid;
 
                 /* Try to acquire PID from bus service */
@@ -3187,7 +3189,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
         if (s->state != SERVICE_DEAD)
                 return -EAGAIN;
 
-        if (getpeername_pretty(fd, &peer) >= 0) {
+        if (getpeername_pretty(fd, true, &peer) >= 0) {
 
                 if (UNIT(s)->description) {
                         _cleanup_free_ char *a;
@@ -3222,8 +3224,6 @@ static void service_reset_failed(Unit *u) {
 
         s->result = SERVICE_SUCCESS;
         s->reload_result = SERVICE_SUCCESS;
-
-        RATELIMIT_RESET(s->start_limit);
 }
 
 static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
@@ -3291,7 +3291,6 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
         [SERVICE_FAILURE_SIGNAL] = "signal",
         [SERVICE_FAILURE_CORE_DUMP] = "core-dump",
         [SERVICE_FAILURE_WATCHDOG] = "watchdog",
-        [SERVICE_FAILURE_START_LIMIT] = "start-limit"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
index e7656682476c803a198809a9df2179276ddc8bec..d342e000bb578c59ea6f7543ede9b29fbb93fa56 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 typedef struct Service Service;
 typedef struct ServiceFDStore ServiceFDStore;
 
+#include "exit-status.h"
+#include "kill.h"
 #include "path.h"
 #include "ratelimit.h"
-#include "kill.h"
-#include "exit-status.h"
 
 typedef enum ServiceRestart {
         SERVICE_RESTART_NO,
@@ -88,7 +86,6 @@ typedef enum ServiceResult {
         SERVICE_FAILURE_SIGNAL,
         SERVICE_FAILURE_CORE_DUMP,
         SERVICE_FAILURE_WATCHDOG,
-        SERVICE_FAILURE_START_LIMIT,
         _SERVICE_RESULT_MAX,
         _SERVICE_RESULT_INVALID = -1
 } ServiceResult;
@@ -118,6 +115,7 @@ struct Service {
         usec_t restart_usec;
         usec_t timeout_start_usec;
         usec_t timeout_stop_usec;
+        usec_t runtime_max_usec;
 
         dual_timestamp watchdog_timestamp;
         usec_t watchdog_usec;
@@ -172,14 +170,12 @@ struct Service {
         bool reset_cpu_usage:1;
 
         char *bus_name;
+        char *bus_name_owner; /* unique name of the current owner */
 
         char *status_text;
         int status_errno;
 
-        RateLimit start_limit;
-        FailureAction start_limit_action;
         FailureAction failure_action;
-        char *reboot_arg;
 
         UnitRef accept_socket;
 
index e4e12a33650c01aa34a42c98a07a98c5baad78a3..59ebdc72191cf72d28fdfc938977e6c939e1c513 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c79d4acb66bc605727abbea93176925458954977..9a29e72645c9d824f814e32416d25e9f2820a5b2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3a95b5fd72c859a5d31f3b6199dc780556acf885..6296b4c94a16999ad1a8e6e063d4b849fcc7732f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 06ac6f84502f9a9eb50d56d3a8982161ae4dd93f..d65364c6f4dbcf49a6f3892c9e9ba6c5fcedd61a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 0c356651e3f0d919ad6dde6df8e9d748c27a57f4..c9f3f61067bca14da53622d8f55934ebddec9ca6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0661ff9ecd5214f95010c21c3d73d4b6727e1fca..0c26e85460d68d495b78538799ad8acc6700d7c0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -197,6 +195,75 @@ static int write_cipso2_rules(const char* srcdir) {
         return r;
 }
 
+static int write_netlabel_rules(const char* srcdir) {
+        _cleanup_fclose_ FILE *dst = NULL;
+        _cleanup_closedir_ DIR *dir = NULL;
+        struct dirent *entry;
+        char buf[NAME_MAX];
+        int dfd = -1;
+        int r = 0;
+
+        dst = fopen("/sys/fs/smackfs/netlabel", "we");
+        if (!dst)  {
+                if (errno != ENOENT)
+                        log_warning_errno(errno, "Failed to open /sys/fs/smackfs/netlabel: %m");
+                return -errno; /* negative error */
+        }
+
+        /* write rules to dst from every file in the directory */
+        dir = opendir(srcdir);
+        if (!dir) {
+                if (errno != ENOENT)
+                        log_warning_errno(errno, "Failed to opendir %s: %m", srcdir);
+                return errno; /* positive on purpose */
+        }
+
+        dfd = dirfd(dir);
+        assert(dfd >= 0);
+
+        FOREACH_DIRENT(entry, dir, return 0) {
+                int fd;
+                _cleanup_fclose_ FILE *policy = NULL;
+
+                fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC);
+                if (fd < 0) {
+                        if (r == 0)
+                                r = -errno;
+                        log_warning_errno(errno, "Failed to open %s: %m", entry->d_name);
+                        continue;
+                }
+
+                policy = fdopen(fd, "re");
+                if (!policy) {
+                        if (r == 0)
+                                r = -errno;
+                        safe_close(fd);
+                        log_error_errno(errno, "Failed to open %s: %m", entry->d_name);
+                        continue;
+                }
+
+                /* load2 write rules in the kernel require a line buffered stream */
+                FOREACH_LINE(buf, policy,
+                             log_error_errno(errno, "Failed to read line from %s: %m",
+                                       entry->d_name)) {
+                        if (!fputs(buf, dst)) {
+                                if (r == 0)
+                                        r = -EINVAL;
+                                log_error_errno(errno, "Failed to write line to /sys/fs/smackfs/netlabel");
+                                break;
+                        }
+                        if (fflush(dst)) {
+                                if (r == 0)
+                                        r = -errno;
+                                log_error_errno(errno, "Failed to flush writes to /sys/fs/smackfs/netlabel: %m");
+                                break;
+                        }
+                }
+        }
+
+       return r;
+}
+
 #endif
 
 int mac_smack_setup(bool *loaded_policy) {
@@ -225,8 +292,18 @@ int mac_smack_setup(bool *loaded_policy) {
 
 #ifdef SMACK_RUN_LABEL
         r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
-        if (r)
-                log_warning_errno(r, "Failed to set SMACK label \"%s\" on self: %m", SMACK_RUN_LABEL);
+        if (r < 0)
+                log_warning_errno(r, "Failed to set SMACK label \"" SMACK_RUN_LABEL "\" on self: %m");
+        r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0);
+        if (r < 0)
+                log_warning_errno(r, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL "\": %m");
+        r = write_string_file("/sys/fs/smackfs/netlabel",
+                              "0.0.0.0/0 " SMACK_RUN_LABEL, 0);
+        if (r < 0)
+                log_warning_errno(r, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL "\": %m");
+        r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0);
+        if (r < 0)
+                log_warning_errno(r, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m");
 #endif
 
         r = write_cipso2_rules("/etc/smack/cipso.d/");
@@ -236,13 +313,29 @@ int mac_smack_setup(bool *loaded_policy) {
                 return 0;
         case ENOENT:
                 log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found");
-                return 0;
+                break;
         case 0:
                 log_info("Successfully loaded Smack/CIPSO policies.");
                 break;
         default:
                 log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m");
+                break;
+        }
+
+        r = write_netlabel_rules("/etc/smack/netlabel.d/");
+        switch(r) {
+        case -ENOENT:
+                log_debug("Smack/CIPSO is not enabled in the kernel.");
                 return 0;
+        case ENOENT:
+                log_debug("Smack network host rules directory '/etc/smack/netlabel.d/' not found");
+                break;
+        case 0:
+                log_info("Successfully loaded Smack network host rules.");
+                break;
+        default:
+                log_warning_errno(r, "Failed to load Smack network host rules: %m, ignoring.");
+                break;
         }
 
         *loaded_policy = true;
index 1cab7718ffd6c796dd9e81d63876bee0f046e865..78164c85e6ae48cb107fec64b516c92df3052215 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 5b9e32ce9dc98ab8875fa48c17b3363a31e5a989..976687af416dd526c107c58b1150a73fdd59a22f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -28,9 +26,9 @@
 #include <sys/epoll.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <linux/sctp.h>
 
 #include "sd-event.h"
-
 #include "alloc-util.h"
 #include "bus-error.h"
 #include "bus-util.h"
@@ -156,41 +154,41 @@ static void socket_done(Unit *u) {
         s->tcp_congestion = mfree(s->tcp_congestion);
         s->bind_to_device = mfree(s->bind_to_device);
 
-        free(s->smack);
-        free(s->smack_ip_in);
-        free(s->smack_ip_out);
+        s->smack = mfree(s->smack);
+        s->smack_ip_in = mfree(s->smack_ip_in);
+        s->smack_ip_out = mfree(s->smack_ip_out);
 
         strv_free(s->symlinks);
 
-        free(s->user);
-        free(s->group);
+        s->user = mfree(s->user);
+        s->group = mfree(s->group);
+
+        s->fdname = mfree(s->fdname);
 
         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 }
 
-static int socket_arm_timer(Socket *s) {
+static int socket_arm_timer(Socket *s, usec_t usec) {
         int r;
 
         assert(s);
 
-        if (s->timeout_usec <= 0) {
-                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-                return 0;
-        }
-
         if (s->timer_event_source) {
-                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                r = sd_event_source_set_time(s->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(s)->manager->event,
                         &s->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
+                        usec, 0,
                         socket_dispatch_timer, s);
         if (r < 0)
                 return r;
@@ -289,7 +287,7 @@ static int socket_add_device_link(Socket *s) {
                 return 0;
 
         t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device);
-        return unit_add_node_link(UNIT(s), t, false);
+        return unit_add_node_link(UNIT(s), t, false, UNIT_BINDS_TO);
 }
 
 static int socket_add_default_dependencies(Socket *s) {
@@ -875,8 +873,14 @@ static void socket_apply_socket_options(Socket *s, int fd) {
 
         if (s->no_delay) {
                 int b = s->no_delay;
-                if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
-                        log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m");
+
+                if (s->socket_protocol == IPPROTO_SCTP) {
+                        if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &b, sizeof(b)) < 0)
+                                log_unit_warning_errno(UNIT(s), errno, "SCTP_NODELAY failed: %m");
+                } else {
+                        if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
+                                log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m");
+                }
         }
 
         if (s->broadcast) {
@@ -1266,6 +1270,19 @@ static int socket_open_fds(Socket *s) {
                                 know_label = true;
                         }
 
+                        /* Apply the socket protocol */
+                        switch(p->address.type) {
+                        case SOCK_STREAM:
+                        case SOCK_SEQPACKET:
+                                if (p->socket->socket_protocol == IPPROTO_SCTP)
+                                        p->address.protocol = p->socket->socket_protocol;
+                                break;
+                        case SOCK_DGRAM:
+                                if (p->socket->socket_protocol == IPPROTO_UDPLITE)
+                                        p->address.protocol = p->socket->socket_protocol;
+                                break;
+                        }
+
                         r = socket_address_listen(
                                         &p->address,
                                         SOCK_CLOEXEC|SOCK_NONBLOCK,
@@ -1473,7 +1490,7 @@ static int socket_coldplug(Unit *u) {
                 if (r < 0)
                         return r;
 
-                r = socket_arm_timer(s);
+                r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
                 if (r < 0)
                         return r;
         }
@@ -1486,6 +1503,7 @@ static int socket_coldplug(Unit *u) {
                    SOCKET_STOP_PRE,
                    SOCKET_STOP_PRE_SIGTERM,
                    SOCKET_STOP_PRE_SIGKILL)) {
+
                 r = socket_open_fds(s);
                 if (r < 0)
                         return r;
@@ -1527,15 +1545,15 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
 
         r = unit_setup_exec_runtime(UNIT(s));
         if (r < 0)
-                goto fail;
+                return r;
 
-        r = socket_arm_timer(s);
+        r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
         if (r < 0)
-                goto fail;
+                return r;
 
         r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
         if (r < 0)
-                goto fail;
+                return r;
 
         exec_params.argv = argv;
         exec_params.environment = UNIT(s)->manager->environment;
@@ -1552,26 +1570,22 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        s->exec_runtime,
                        &pid);
         if (r < 0)
-                goto fail;
+                return r;
 
         r = unit_watch_pid(UNIT(s), pid);
         if (r < 0)
                 /* FIXME: we need to do something here */
-                goto fail;
+                return r;
 
         *_pid = pid;
         return 0;
-
-fail:
-        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-        return r;
 }
 
 static int socket_chown(Socket *s, pid_t *_pid) {
         pid_t pid;
         int r;
 
-        r = socket_arm_timer(s);
+        r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
         if (r < 0)
                 goto fail;
 
@@ -1714,7 +1728,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = socket_arm_timer(s);
+                r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
                 if (r < 0)
                         goto fail;
 
@@ -1867,7 +1881,7 @@ fail:
 }
 
 static void socket_enter_running(Socket *s, int cfd) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(s);
@@ -2686,23 +2700,6 @@ static void socket_reset_failed(Unit *u) {
         s->result = SOCKET_SUCCESS;
 }
 
-static void socket_notify_service_dead(Socket *s, bool failed_permanent) {
-        assert(s);
-
-        /* The service is dead. Dang!
-         *
-         * This is strictly for one-instance-for-all-connections
-         * services. */
-
-        if (s->state == SOCKET_RUNNING) {
-                log_unit_debug(UNIT(s), "Got notified about service death (failed permanently: %s)", yes_no(failed_permanent));
-                if (failed_permanent)
-                        socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_FAILED_PERMANENT);
-                else
-                        socket_enter_listening(s);
-        }
-}
-
 void socket_connection_unref(Socket *s) {
         assert(s);
 
@@ -2719,34 +2716,30 @@ void socket_connection_unref(Socket *s) {
 
 static void socket_trigger_notify(Unit *u, Unit *other) {
         Socket *s = SOCKET(u);
-        Service *se;
 
         assert(u);
         assert(other);
 
         /* Don't propagate state changes from the service if we are
            already down or accepting connections */
-        if ((s->state != SOCKET_RUNNING &&
-            s->state != SOCKET_LISTENING) ||
-            s->accept)
+        if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING) || s->accept)
                 return;
 
-        if (other->load_state != UNIT_LOADED ||
-            other->type != UNIT_SERVICE)
+        if (other->start_limit_hit) {
+                socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT);
                 return;
+        }
 
-        se = SERVICE(other);
-
-        if (se->state == SERVICE_FAILED)
-                socket_notify_service_dead(s, se->result == SERVICE_FAILURE_START_LIMIT);
+        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+                return;
 
-        if (se->state == SERVICE_DEAD ||
-            se->state == SERVICE_FINAL_SIGTERM ||
-            se->state == SERVICE_FINAL_SIGKILL ||
-            se->state == SERVICE_AUTO_RESTART)
-                socket_notify_service_dead(s, false);
+        if (IN_SET(SERVICE(other)->state,
+                   SERVICE_DEAD, SERVICE_FAILED,
+                   SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
+                   SERVICE_AUTO_RESTART))
+               socket_enter_listening(s);
 
-        if (se->state == SERVICE_RUNNING)
+        if (SERVICE(other)->state == SERVICE_RUNNING)
                 socket_set_state(s, SOCKET_RUNNING);
 }
 
@@ -2754,17 +2747,21 @@ static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
 }
 
-static int socket_get_timeout(Unit *u, uint64_t *timeout) {
+static int socket_get_timeout(Unit *u, usec_t *timeout) {
         Socket *s = SOCKET(u);
+        usec_t t;
         int r;
 
         if (!s->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(s->timer_event_source, timeout);
+        r = sd_event_source_get_time(s->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
@@ -2798,7 +2795,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
         [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
         [SOCKET_FAILURE_SIGNAL] = "signal",
         [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
-        [SOCKET_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent"
+        [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
index 94cda8a90d1536638ab853fcf7c4f6f4730a8dd7..b537b026a7b41e3d73c281677e62800d031e5004 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,9 +21,9 @@
 
 typedef struct Socket Socket;
 
-#include "socket-util.h"
 #include "mount.h"
 #include "service.h"
+#include "socket-util.h"
 
 typedef enum SocketExecCommand {
         SOCKET_EXEC_START_PRE,
@@ -54,7 +52,7 @@ typedef enum SocketResult {
         SOCKET_FAILURE_EXIT_CODE,
         SOCKET_FAILURE_SIGNAL,
         SOCKET_FAILURE_CORE_DUMP,
-        SOCKET_FAILURE_SERVICE_FAILED_PERMANENT,
+        SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
         _SOCKET_RESULT_MAX,
         _SOCKET_RESULT_INVALID = -1
 } SocketResult;
@@ -120,6 +118,8 @@ struct Socket {
         bool remove_on_stop;
         bool writable;
 
+        int socket_protocol;
+
         /* Socket options */
         bool keep_alive;
         bool no_delay;
index ee0838e6762faf7a3435c3b5b9824b9cf90d9409..1bf0c0a8089dc6f1356a19470989e6565386e16d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -160,29 +158,27 @@ static void swap_done(Unit *u) {
         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 }
 
-static int swap_arm_timer(Swap *s) {
+static int swap_arm_timer(Swap *s, usec_t usec) {
         int r;
 
         assert(s);
 
-        if (s->timeout_usec <= 0) {
-                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
-                return 0;
-        }
-
         if (s->timer_event_source) {
-                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                r = sd_event_source_set_time(s->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(s)->manager->event,
                         &s->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
+                        usec, 0,
                         swap_dispatch_timer, s);
         if (r < 0)
                 return r;
@@ -202,7 +198,7 @@ static int swap_add_device_links(Swap *s) {
                 return 0;
 
         if (is_device_path(s->what))
-                return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == MANAGER_SYSTEM);
+                return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == MANAGER_SYSTEM, UNIT_BINDS_TO);
         else
                 /* File based swap devices need to be ordered after
                  * systemd-remount-fs.service, since they might need a
@@ -211,6 +207,8 @@ static int swap_add_device_links(Swap *s) {
 }
 
 static int swap_add_default_dependencies(Swap *s) {
+        int r;
+
         assert(s);
 
         if (!UNIT(s)->default_dependencies)
@@ -222,6 +220,12 @@ static int swap_add_default_dependencies(Swap *s) {
         if (detect_container() > 0)
                 return 0;
 
+        /* swap units generated for the swap dev links are missing the
+         * ordering dep against the swap target. */
+        r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, true);
+        if (r < 0)
+                return r;
+
         return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
 }
 
@@ -544,7 +548,7 @@ static int swap_coldplug(Unit *u) {
                 if (r < 0)
                         return r;
 
-                r = swap_arm_timer(s);
+                r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
                 if (r < 0)
                         return r;
         }
@@ -625,7 +629,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        r = swap_arm_timer(s);
+        r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
         if (r < 0)
                 goto fail;
 
@@ -702,7 +706,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = swap_arm_timer(s);
+                r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
                 if (r < 0)
                         goto fail;
 
@@ -1390,17 +1394,21 @@ static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
 }
 
-static int swap_get_timeout(Unit *u, uint64_t *timeout) {
+static int swap_get_timeout(Unit *u, usec_t *timeout) {
         Swap *s = SWAP(u);
+        usec_t t;
         int r;
 
         if (!s->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(s->timer_event_source, timeout);
+        r = sd_event_source_get_time(s->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
index 303b926568298efbabea55b61a66beb21edd094c..ac7a63d81b55aec0a57bd464c5f06ea0d0bd6dfc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 14f9b2e26a56dc72b3c5f6a691fa9148ae01d404..61a91aad07c1cb06ffa8a3d3c1d7e556614d9e7e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3cc6c07bfa15907106a8fc109f02e2e3d1f1e549..339aea154e38370aaa1c791aaba636d2b113d57b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0587452cfb3ae1d393883e308156160516c4f92d..6f3e6a8db3e6950718e4dd561c2c0d5f9b886f73 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -27,6 +25,7 @@
 #include "dbus-timer.h"
 #include "fs-util.h"
 #include "parse-util.h"
+#include "random-util.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -330,14 +329,46 @@ static usec_t monotonic_to_boottime(usec_t t) {
                 return 0;
 }
 
+static void add_random(Timer *t, usec_t *v) {
+        char s[FORMAT_TIMESPAN_MAX];
+        usec_t add;
+
+        assert(t);
+        assert(*v);
+
+        if (t->random_usec == 0)
+                return;
+        if (*v == USEC_INFINITY)
+                return;
+
+        add = random_u64() % t->random_usec;
+
+        if (*v + add < *v) /* overflow */
+                *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
+        else
+                *v += add;
+
+        log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
+}
+
 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;
         TimerValue *v;
+        Unit *trigger;
         int r;
 
+        assert(t);
+
+        trigger = UNIT_TRIGGER(UNIT(t));
+        if (!trigger) {
+                log_unit_error(UNIT(t), "Unit to trigger vanished.");
+                timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
+                return;
+        }
+
         /* If we shall wake the system we use the boottime clock
          * rather than the monotonic clock. */
 
@@ -396,7 +427,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
 
                         case TIMER_UNIT_ACTIVE:
                                 leave_around = true;
-                                base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
+                                base = trigger->inactive_exit_timestamp.monotonic;
 
                                 if (base <= 0)
                                         base = t->last_trigger.monotonic;
@@ -408,7 +439,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
 
                         case TIMER_UNIT_INACTIVE:
                                 leave_around = true;
-                                base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
+                                base = trigger->inactive_enter_timestamp.monotonic;
 
                                 if (base <= 0)
                                         base = t->last_trigger.monotonic;
@@ -452,6 +483,8 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                 char buf[FORMAT_TIMESPAN_MAX];
                 usec_t left;
 
+                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;
                 log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
 
@@ -486,6 +519,9 @@ static void timer_enter_waiting(Timer *t, bool initial) {
 
         if (found_realtime) {
                 char buf[FORMAT_TIMESTAMP_MAX];
+
+                add_random(t, &t->next_elapse_realtime);
+
                 log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
 
                 if (t->realtime_event_source) {
@@ -525,7 +561,8 @@ fail:
 }
 
 static void timer_enter_running(Timer *t) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *trigger;
         int r;
 
         assert(t);
@@ -534,7 +571,14 @@ static void timer_enter_running(Timer *t) {
         if (unit_stop_pending(UNIT(t)))
                 return;
 
-        r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)), JOB_REPLACE, &error, NULL);
+        trigger = UNIT_TRIGGER(UNIT(t));
+        if (!trigger) {
+                log_unit_error(UNIT(t), "Unit to trigger vanished.");
+                timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
+                return;
+        }
+
+        r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
         if (r < 0)
                 goto fail;
 
@@ -554,12 +598,16 @@ fail:
 static int timer_start(Unit *u) {
         Timer *t = TIMER(u);
         TimerValue *v;
+        Unit *trigger;
 
         assert(t);
         assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
 
-        if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
+        trigger = UNIT_TRIGGER(u);
+        if (!trigger || trigger->load_state != UNIT_LOADED) {
+                log_unit_error(u, "Refusing to start, unit to trigger not loaded.");
                 return -ENOENT;
+        }
 
         t->last_trigger = DUAL_TIMESTAMP_NULL;
 
index 6bc9fbed3dbb74c1f8123ba50ac7f405835b2adf..698e6da2f5e0b454604d2b2b0b16d560fefdcc24 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -58,6 +56,7 @@ struct Timer {
         Unit meta;
 
         usec_t accuracy_usec;
+        usec_t random_usec;
 
         LIST_HEAD(TimerValue, values);
         usec_t next_elapse_realtime;
index 15e79d00b30c15c24e629fa5f7c985134a8b8096..b28fc7678576f24eefaf3cfacc39bcc176af6f66 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -27,6 +25,7 @@
 #include "bus-error.h"
 #include "terminal-util.h"
 #include "transaction.h"
+#include "dbus-unit.h"
 
 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
 
@@ -860,30 +859,12 @@ int transaction_add_job_and_dependencies(
         if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
 
-        if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
-                if (unit->load_error == -ENOENT || unit->manager->test_run)
-                        return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
-                                                 "Unit %s failed to load: %s.",
-                                                 unit->id,
-                                                 strerror(-unit->load_error));
-                else
-                        return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
-                                                 "Unit %s failed to load: %s. "
-                                                 "See system logs and 'systemctl status %s' for details.",
-                                                 unit->id,
-                                                 strerror(-unit->load_error),
-                                                 unit->id);
+        if (type != JOB_STOP) {
+                r = bus_unit_check_load_state(unit, e);
+                if (r < 0)
+                        return r;
         }
 
-        if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
-                return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
-                                         "Unit %s failed to load: %s.",
-                                         unit->id, strerror(-unit->load_error));
-
-        if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
-                return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
-                                         "Unit %s is masked.", unit->id);
-
         if (!unit_job_is_applicable(unit, type))
                 return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
                                          "Job type %s is not applicable for unit %s.",
@@ -929,7 +910,7 @@ int transaction_add_job_and_dependencies(
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
                                 if (r < 0) {
-                                        if (r != -EBADR)
+                                        if (r != -EBADR) /* job type not applicable */
                                                 goto fail;
 
                                         sd_bus_error_free(e);
@@ -939,7 +920,7 @@ int transaction_add_job_and_dependencies(
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
                                 if (r < 0) {
-                                        if (r != -EBADR)
+                                        if (r != -EBADR) /* job type not applicable */
                                                 goto fail;
 
                                         sd_bus_error_free(e);
@@ -949,9 +930,10 @@ int transaction_add_job_and_dependencies(
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e);
                                 if (r < 0) {
+                                        /* unit masked, job type not applicable and unit not found are not considered as errors. */
                                         log_unit_full(dep,
-                                                      r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, r,
-                                                      "Cannot add dependency job, ignoring: %s",
+                                                      IN_SET(r, -ESHUTDOWN, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING,
+                                                      r, "Cannot add dependency job, ignoring: %s",
                                                       bus_error_message(e, r));
                                         sd_bus_error_free(e);
                                 }
@@ -960,7 +942,7 @@ int transaction_add_job_and_dependencies(
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e);
                                 if (r < 0) {
-                                        if (r != -EBADR)
+                                        if (r != -EBADR) /* job type not applicable */
                                                 goto fail;
 
                                         sd_bus_error_free(e);
@@ -970,7 +952,7 @@ int transaction_add_job_and_dependencies(
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e);
                                 if (r < 0) {
-                                        if (r != -EBADR)
+                                        if (r != -EBADR) /* job type not applicable */
                                                 goto fail;
 
                                         sd_bus_error_free(e);
@@ -1015,7 +997,7 @@ int transaction_add_job_and_dependencies(
 
                                         r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e);
                                         if (r < 0) {
-                                                if (r != -EBADR)
+                                                if (r != -EBADR) /* job type not applicable */
                                                         goto fail;
 
                                                 sd_bus_error_free(e);
@@ -1026,7 +1008,13 @@ int transaction_add_job_and_dependencies(
                 if (type == JOB_RELOAD) {
 
                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
-                                r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, false, false, ignore_order, e);
+                                JobType nt;
+
+                                nt = job_type_collapse(JOB_TRY_RELOAD, dep);
+                                if (nt == JOB_NOP)
+                                        continue;
+
+                                r = transaction_add_job_and_dependencies(tr, nt, dep, ret, false, false, false, ignore_order, e);
                                 if (r < 0) {
                                         log_unit_warning(dep,
                                                          "Cannot add dependency reload job, ignoring: %s",
index f7aa3df085e2008f9b7fd498ebb0769977fc44b3..6a3f927b0f3986350054a52702f532df1d8be2d7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 typedef struct Transaction Transaction;
 
-#include "unit.h"
-#include "manager.h"
-#include "job.h"
 #include "hashmap.h"
+#include "job.h"
+#include "manager.h"
+#include "unit.h"
 
 struct Transaction {
         /* Jobs to be added */
index 141f42dbcfd0c818bd65894f1b29e4da8adc0632..9e18a39a674877ec52f001f46e4db24a69589e84 100644 (file)
 
 # The contents of this are an example to be copied into systemd.spec.
 
-%transfiletriggerin -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+%transfiletriggerin -P 900900 -p <lua> -- @systemunitdir@ /etc/systemd/system
+-- This script will run after any package is initially installed or
+-- upgraded. We care about the case where a package is initially
+-- installed, because other cases are covered by the *un scriptlets,
+-- so sometimes we will reload needlessly.
 
-%transfiletriggerun -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+pid = posix.fork()
+if pid == 0 then
+    assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+elseif pid > 0 then
+    posix.wait(pid)
+end
+
+%transfiletriggerun -p <lua> -- @systemunitdir@ /etc/systemd/system
+-- On removal, we need to run daemon-reload after any units have been
+-- removed. %transfiletriggerpostun would be ideal, but it does not get
+-- executed for some reason.
+-- On upgrade, we need to run daemon-reload after any new unit files
+-- have been installed, but before %postun scripts in packages get
+-- executed. %transfiletriggerun gets the right list of files
+-- but it is invoked too early (before changes happen).
+-- %filetriggerpostun happens at the right time, but it fires for
+-- every package.
+-- To execute the reload at the right time, we create a state
+-- file in %transfiletriggerun and execute the daemon-reload in
+-- the first %filetriggerpostun.
+
+posix.mkdir("%{_localstatedir}/lib")
+posix.mkdir("%{_localstatedir}/lib/rpm-state")
+posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd")
+io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w")
+
+%filetriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system
+if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then
+    posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload")
+    posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd")
+    pid = posix.fork()
+    if pid == 0 then
+        assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+    elseif pid > 0 then
+        posix.wait(pid)
+    end
+end
index 9d1f7660db7bc11569cb87b2b9886775a305f4fd..a458768e7d9f6c4e2230e9471a71b69483eca53b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8439ffe58ff82a4233caaacc8f94b7e1bde835a8..4e2215a47d3221f674c96f521ef3281669d08d32 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f587a5a14121523b45d718785f3f13ccd356c75e..fc057d965c636ce52d0cf49d895434c1c2607ef5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 51acad63e954ea4feb139f19bb12a267df22c0d4..4fc8531228043cfe0fabfc91d107db137c265cfd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0a02e38aa8bfb86c4f3732c49e242fba0e894b35..d39e3dcaeb91a9a6c906929371412b5fa064d209 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -51,6 +49,7 @@
 #include "set.h"
 #include "special.h"
 #include "stat-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unit-name.h"
@@ -98,7 +97,9 @@ Unit *unit_new(Manager *m, size_t size) {
         u->unit_file_preset = -1;
         u->on_failure_job_mode = JOB_REPLACE;
         u->cgroup_inotify_wd = -1;
+        u->job_timeout = USEC_INFINITY;
 
+        RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst);
         RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16);
 
         return u;
@@ -457,7 +458,6 @@ static void unit_free_requires_mounts_for(Unit *u) {
 static void unit_done(Unit *u) {
         ExecContext *ec;
         CGroupContext *cc;
-        int r;
 
         assert(u);
 
@@ -474,10 +474,6 @@ static void unit_done(Unit *u) {
         cc = unit_get_cgroup_context(u);
         if (cc)
                 cgroup_context_done(cc);
-
-        r = unit_remove_from_netclass_cgroup(u);
-        if (r < 0)
-                log_warning_errno(r, "Unable to remove unit from netclass group: %m");
 }
 
 void unit_free(Unit *u) {
@@ -557,6 +553,8 @@ void unit_free(Unit *u) {
         condition_free_list(u->conditions);
         condition_free_list(u->asserts);
 
+        free(u->reboot_arg);
+
         unit_ref_unset(&u->slice);
 
         while (u->refs)
@@ -868,6 +866,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
         Iterator i;
         const char *prefix2;
         char
+                timestamp0[FORMAT_TIMESTAMP_MAX],
                 timestamp1[FORMAT_TIMESTAMP_MAX],
                 timestamp2[FORMAT_TIMESTAMP_MAX],
                 timestamp3[FORMAT_TIMESTAMP_MAX],
@@ -889,6 +888,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 "%s\tInstance: %s\n"
                 "%s\tUnit Load State: %s\n"
                 "%s\tUnit Active State: %s\n"
+                "%s\nState Change Timestamp: %s\n"
                 "%s\tInactive Exit Timestamp: %s\n"
                 "%s\tActive Enter Timestamp: %s\n"
                 "%s\tActive Exit Timestamp: %s\n"
@@ -906,6 +906,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, strna(u->instance),
                 prefix, unit_load_state_to_string(u->load_state),
                 prefix, unit_active_state_to_string(unit_active_state(u)),
+                prefix, strna(format_timestamp(timestamp0, sizeof(timestamp0), u->state_change_timestamp.realtime)),
                 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
                 prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
                 prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
@@ -946,7 +947,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
         STRV_FOREACH(j, u->dropin_paths)
                 fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
 
-        if (u->job_timeout > 0)
+        if (u->job_timeout != USEC_INFINITY)
                 fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
 
         if (u->job_timeout_action != FAILURE_ACTION_NONE)
@@ -1257,14 +1258,6 @@ int unit_load(Unit *u) {
                 }
 
                 unit_update_cgroup_members_masks(u);
-
-                /* If we are reloading, we need to wait for the deserializer
-                 * to restore the net_cls ids that have been set previously */
-                if (u->manager->n_reloading <= 0) {
-                        r = unit_add_to_netclass_cgroup(u);
-                        if (r < 0)
-                                return r;
-                }
         }
 
         assert((u->load_state != UNIT_MERGED) == !u->merged_into);
@@ -1412,7 +1405,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
         format = unit_get_status_message_format(u, t);
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
-        snprintf(buf, sizeof(buf), format, unit_description(u));
+        xsprintf(buf, format, unit_description(u));
         REENABLE_WARNING;
 
         mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
@@ -1441,23 +1434,36 @@ void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
         unit_status_print_starting_stopping(u, t);
 }
 
+static int unit_start_limit_test(Unit *u) {
+        assert(u);
+
+        if (ratelimit_test(&u->start_limit)) {
+                u->start_limit_hit = false;
+                return 0;
+        }
+
+        log_unit_warning(u, "Start request repeated too quickly.");
+        u->start_limit_hit = true;
+
+        return failure_action(u->manager, u->start_limit_action, u->reboot_arg);
+}
+
 /* Errors:
- *         -EBADR:     This unit type does not support starting.
- *         -EALREADY:  Unit is already started.
- *         -EAGAIN:    An operation is already in progress. Retry later.
- *         -ECANCELED: Too many requests for now.
- *         -EPROTO:    Assert failed
+ *         -EBADR:      This unit type does not support starting.
+ *         -EALREADY:   Unit is already started.
+ *         -EAGAIN:     An operation is already in progress. Retry later.
+ *         -ECANCELED:  Too many requests for now.
+ *         -EPROTO:     Assert failed
+ *         -EINVAL:     Unit not loaded
+ *         -EOPNOTSUPP: Unit type not supported
  */
 int unit_start(Unit *u) {
         UnitActiveState state;
         Unit *following;
+        int r;
 
         assert(u);
 
-        /* Units that aren't loaded cannot be started */
-        if (u->load_state != UNIT_LOADED)
-                return -EINVAL;
-
         /* If this is already started, then this will succeed. Note
          * that this will even succeed if this unit is not startable
          * by the user. This is relied on to detect when we need to
@@ -1466,6 +1472,15 @@ int unit_start(Unit *u) {
         if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                 return -EALREADY;
 
+        /* Make sure we don't enter a busy loop of some kind. */
+        r = unit_start_limit_test(u);
+        if (r < 0)
+                return r;
+
+        /* Units that aren't loaded cannot be started */
+        if (u->load_state != UNIT_LOADED)
+                return -EINVAL;
+
         /* If the conditions failed, don't do anything at all. If we
          * already are activating this call might still be useful to
          * speed up activation in case there is some hold-off time,
@@ -1613,7 +1628,7 @@ bool unit_can_reload(Unit *u) {
 
 static void unit_check_unneeded(Unit *u) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
         static const UnitDependency needed_dependencies[] = {
                 UNIT_REQUIRED_BY,
@@ -1660,7 +1675,7 @@ static void unit_check_unneeded(Unit *u) {
 }
 
 static void unit_check_binds_to(Unit *u) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool stop = false;
         Unit *other;
         Iterator i;
@@ -1820,19 +1835,17 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
 
         /* Update timestamps for state changes */
         if (m->n_reloading <= 0) {
-                dual_timestamp ts;
-
-                dual_timestamp_get(&ts);
+                dual_timestamp_get(&u->state_change_timestamp);
 
                 if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
-                        u->inactive_exit_timestamp = ts;
+                        u->inactive_exit_timestamp = u->state_change_timestamp;
                 else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns))
-                        u->inactive_enter_timestamp = ts;
+                        u->inactive_enter_timestamp = u->state_change_timestamp;
 
                 if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
-                        u->active_enter_timestamp = ts;
+                        u->active_enter_timestamp = u->state_change_timestamp;
                 else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
-                        u->active_exit_timestamp = ts;
+                        u->active_exit_timestamp = u->state_change_timestamp;
         }
 
         /* Keep track of failed units */
@@ -1893,6 +1906,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
 
                 case JOB_RELOAD:
                 case JOB_RELOAD_OR_START:
+                case JOB_TRY_RELOAD:
 
                         if (u->job->state == JOB_RUNNING) {
                                 if (ns == UNIT_ACTIVE)
@@ -2106,6 +2120,7 @@ bool unit_job_is_applicable(Unit *u, JobType j) {
                 return unit_can_start(u);
 
         case JOB_RELOAD:
+        case JOB_TRY_RELOAD:
                 return unit_can_reload(u);
 
         case JOB_RELOAD_OR_START:
@@ -2550,10 +2565,13 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
                 }
         }
 
+        dual_timestamp_serialize(f, "state-change-timestamp", &u->state_change_timestamp);
+
         dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
         dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
         dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
         dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
+
         dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
         dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp);
 
@@ -2570,9 +2588,6 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
                 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
         unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
 
-        if (u->cgroup_netclass_id)
-                unit_serialize_item_format(u, f, "netclass-id", "%" PRIu32, u->cgroup_netclass_id);
-
         if (serialize_jobs) {
                 if (u->job) {
                         fprintf(f, "job\n");
@@ -2692,7 +2707,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
 
                 /* End marker */
                 if (isempty(l))
-                        return 0;
+                        break;
 
                 k = strcspn(l, "=");
 
@@ -2732,6 +2747,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                         } else  /* legacy for pre-44 */
                                 log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
                         continue;
+                } else if (streq(l, "state-change-timestamp")) {
+                        dual_timestamp_deserialize(v, &u->state_change_timestamp);
+                        continue;
                 } else if (streq(l, "inactive-exit-timestamp")) {
                         dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
                         continue;
@@ -2806,17 +2824,6 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                         else
                                 u->cgroup_realized = b;
 
-                        continue;
-                } else if (streq(l, "netclass-id")) {
-                        r = safe_atou32(v, &u->cgroup_netclass_id);
-                        if (r < 0)
-                                log_unit_debug(u, "Failed to parse netclass ID %s, ignoring.", v);
-                        else {
-                                r = unit_add_to_netclass_cgroup(u);
-                                if (r < 0)
-                                        log_unit_debug_errno(u, r, "Failed to add unit to netclass cgroup, ignoring: %m");
-                        }
-
                         continue;
                 }
 
@@ -2838,9 +2845,18 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                                 log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
                 }
         }
+
+        /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is
+         * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from
+         * before 228 where the base for timeouts was not persistent across reboots. */
+
+        if (!dual_timestamp_is_set(&u->state_change_timestamp))
+                dual_timestamp_get(&u->state_change_timestamp);
+
+        return 0;
 }
 
-int unit_add_node_link(Unit *u, const char *what, bool wants) {
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) {
         Unit *device;
         _cleanup_free_ char *e = NULL;
         int r;
@@ -2867,7 +2883,9 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
         if (r < 0)
                 return r;
 
-        r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == MANAGER_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
+        r = unit_add_two_dependencies(u, UNIT_AFTER,
+                                      u->manager->running_as == MANAGER_SYSTEM ? dep : UNIT_WANTS,
+                                      device, true);
         if (r < 0)
                 return r;
 
@@ -2966,6 +2984,9 @@ void unit_reset_failed(Unit *u) {
 
         if (UNIT_VTABLE(u)->reset_failed)
                 UNIT_VTABLE(u)->reset_failed(u);
+
+        RATELIMIT_RESET(u->start_limit);
+        u->start_limit_hit = false;
 }
 
 Unit *unit_following(Unit *u) {
@@ -3117,7 +3138,7 @@ int unit_kill_common(
                         killed = true;
         }
 
-        if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_ALL_FAIL))
+        if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL))
                 return -ESRCH;
 
         return r;
@@ -3229,7 +3250,7 @@ int unit_patch_contexts(Unit *u) {
                         ec->no_new_privileges = true;
 
                 if (ec->private_devices)
-                        ec->capability_bounding_set_drop |= (uint64_t) 1ULL << (uint64_t) CAP_MKNOD;
+                        ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD);
         }
 
         cc = unit_get_cgroup_context(u);
index a69d624fad333423b1b845a25639f3e0dcd0abcc..601e763ce2f8ea886293b43aa81a454c3d154f2a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -30,11 +28,11 @@ typedef struct UnitVTable UnitVTable;
 typedef struct UnitRef UnitRef;
 typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
 
-#include "list.h"
 #include "condition.h"
+#include "failure-action.h"
 #include "install.h"
+#include "list.h"
 #include "unit-name.h"
-#include "failure-action.h"
 
 typedef enum KillOperation {
         KILL_TERMINATE,
@@ -121,6 +119,10 @@ struct Unit {
         dual_timestamp condition_timestamp;
         dual_timestamp assert_timestamp;
 
+        /* Updated whenever the low-level state changes */
+        dual_timestamp state_change_timestamp;
+
+        /* Updated whenever the (high-level) active state enters or leaves the active or inactive states */
         dual_timestamp inactive_exit_timestamp;
         dual_timestamp active_enter_timestamp;
         dual_timestamp active_exit_timestamp;
@@ -163,6 +165,11 @@ struct Unit {
         /* Error code when we didn't manage to load the unit (negative) */
         int load_error;
 
+        /* Put a ratelimit on unit starting */
+        RateLimit start_limit;
+        FailureAction start_limit_action;
+        char *reboot_arg;
+
         /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */
         RateLimit auto_stop_ratelimit;
 
@@ -226,6 +233,8 @@ struct Unit {
         bool cgroup_members_mask_valid:1;
         bool cgroup_subtree_mask_valid:1;
 
+        bool start_limit_hit:1;
+
         /* Did we already invoke unit_coldplug() for this unit? */
         bool coldplugged:1;
 };
@@ -242,16 +251,16 @@ typedef enum UnitSetPropertiesMode {
         UNIT_PERSISTENT = 2,
 } UnitSetPropertiesMode;
 
-#include "socket.h"
+#include "automount.h"
 #include "busname.h"
-#include "target.h"
 #include "device.h"
-#include "automount.h"
-#include "swap.h"
-#include "timer.h"
-#include "slice.h"
 #include "path.h"
 #include "scope.h"
+#include "slice.h"
+#include "socket.h"
+#include "swap.h"
+#include "target.h"
+#include "timer.h"
 
 struct UnitVTable {
         /* How much memory does an object of this unit type need */
@@ -375,7 +384,8 @@ struct UnitVTable {
         /* Called whenever CLOCK_REALTIME made a jump */
         void (*time_change)(Unit *u);
 
-        int (*get_timeout)(Unit *u, uint64_t *timeout);
+        /* Returns the next timeout of a unit */
+        int (*get_timeout)(Unit *u, usec_t *timeout);
 
         /* This is called for each unit type and should be used to
          * enumerate existing devices and load them. However,
@@ -528,7 +538,7 @@ int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *v
 int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd);
 void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
 
-int unit_add_node_link(Unit *u, const char *what, bool wants);
+int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency d);
 
 int unit_coldplug(Unit *u);
 
diff --git a/src/coredump/Makefile b/src/coredump/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/coredump/coredump-vacuum.c b/src/coredump/coredump-vacuum.c
new file mode 100644 (file)
index 0000000..f02b6db
--- /dev/null
@@ -0,0 +1,268 @@
+/***
+  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 <sys/statvfs.h>
+
+#include "alloc-util.h"
+#include "coredump-vacuum.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "hashmap.h"
+#include "macro.h"
+#include "string-util.h"
+#include "time-util.h"
+#include "user-util.h"
+#include "util.h"
+
+#define DEFAULT_MAX_USE_LOWER (uint64_t) (1ULL*1024ULL*1024ULL)           /* 1 MiB */
+#define DEFAULT_MAX_USE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL)   /* 4 GiB */
+#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
+#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL)                    /* 1 MB */
+
+struct vacuum_candidate {
+        unsigned n_files;
+        char *oldest_file;
+        usec_t oldest_mtime;
+};
+
+static void vacuum_candidate_free(struct vacuum_candidate *c) {
+        if (!c)
+                return;
+
+        free(c->oldest_file);
+        free(c);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free);
+
+static void vacuum_candidate_hasmap_free(Hashmap *h) {
+        struct vacuum_candidate *c;
+
+        while ((c = hashmap_steal_first(h)))
+                vacuum_candidate_free(c);
+
+        hashmap_free(h);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hasmap_free);
+
+static int uid_from_file_name(const char *filename, uid_t *uid) {
+        const char *p, *e, *u;
+
+        p = startswith(filename, "core.");
+        if (!p)
+                return -EINVAL;
+
+        /* Skip the comm field */
+        p = strchr(p, '.');
+        if (!p)
+                return -EINVAL;
+        p++;
+
+        /* Find end up UID */
+        e = strchr(p, '.');
+        if (!e)
+                return -EINVAL;
+
+        u = strndupa(p, e-p);
+        return parse_uid(u, uid);
+}
+
+static bool vacuum_necessary(int fd, uint64_t sum, uint64_t keep_free, uint64_t max_use) {
+        uint64_t fs_size = 0, fs_free = (uint64_t) -1;
+        struct statvfs sv;
+
+        assert(fd >= 0);
+
+        if (fstatvfs(fd, &sv) >= 0) {
+                fs_size = sv.f_frsize * sv.f_blocks;
+                fs_free = sv.f_frsize * sv.f_bfree;
+        }
+
+        if (max_use == (uint64_t) -1) {
+
+                if (fs_size > 0) {
+                        max_use = PAGE_ALIGN(fs_size / 10); /* 10% */
+
+                        if (max_use > DEFAULT_MAX_USE_UPPER)
+                                max_use = DEFAULT_MAX_USE_UPPER;
+
+                        if (max_use < DEFAULT_MAX_USE_LOWER)
+                                max_use = DEFAULT_MAX_USE_LOWER;
+                } else
+                        max_use = DEFAULT_MAX_USE_LOWER;
+        } else
+                max_use = PAGE_ALIGN(max_use);
+
+        if (max_use > 0 && sum > max_use)
+                return true;
+
+        if (keep_free == (uint64_t) -1) {
+
+                if (fs_size > 0) {
+                        keep_free = PAGE_ALIGN((fs_size * 3) / 20); /* 15% */
+
+                        if (keep_free > DEFAULT_KEEP_FREE_UPPER)
+                                keep_free = DEFAULT_KEEP_FREE_UPPER;
+                } else
+                        keep_free = DEFAULT_KEEP_FREE;
+        } else
+                keep_free = PAGE_ALIGN(keep_free);
+
+        if (keep_free > 0 && fs_free < keep_free)
+                return true;
+
+        return false;
+}
+
+int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
+        _cleanup_closedir_ DIR *d = NULL;
+        struct stat exclude_st;
+        int r;
+
+        if (keep_free == 0 && max_use == 0)
+                return 0;
+
+        if (exclude_fd >= 0) {
+                if (fstat(exclude_fd, &exclude_st) < 0)
+                        return log_error_errno(errno, "Failed to fstat(): %m");
+        }
+
+        /* This algorithm will keep deleting the oldest file of the
+         * user with the most coredumps until we are back in the size
+         * limits. Note that vacuuming for journal files is different,
+         * because we rely on rate-limiting of the messages there,
+         * to avoid being flooded. */
+
+        d = opendir("/var/lib/systemd/coredump");
+        if (!d) {
+                if (errno == ENOENT)
+                        return 0;
+
+                return log_error_errno(errno, "Can't open coredump directory: %m");
+        }
+
+        for (;;) {
+                _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL;
+                struct vacuum_candidate *worst = NULL;
+                struct dirent *de;
+                uint64_t sum = 0;
+
+                rewinddir(d);
+
+                FOREACH_DIRENT(de, d, goto fail) {
+                        struct vacuum_candidate *c;
+                        struct stat st;
+                        uid_t uid;
+                        usec_t t;
+
+                        r = uid_from_file_name(de->d_name, &uid);
+                        if (r < 0)
+                                continue;
+
+                        if (fstatat(dirfd(d), de->d_name, &st, AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW) < 0) {
+                                if (errno == ENOENT)
+                                        continue;
+
+                                log_warning_errno(errno, "Failed to stat /var/lib/systemd/coredump/%s: %m", de->d_name);
+                                continue;
+                        }
+
+                        if (!S_ISREG(st.st_mode))
+                                continue;
+
+                        if (exclude_fd >= 0 &&
+                            exclude_st.st_dev == st.st_dev &&
+                            exclude_st.st_ino == st.st_ino)
+                                continue;
+
+                        r = hashmap_ensure_allocated(&h, NULL);
+                        if (r < 0)
+                                return log_oom();
+
+                        t = timespec_load(&st.st_mtim);
+
+                        c = hashmap_get(h, UID_TO_PTR(uid));
+                        if (c) {
+
+                                if (t < c->oldest_mtime) {
+                                        char *n;
+
+                                        n = strdup(de->d_name);
+                                        if (!n)
+                                                return log_oom();
+
+                                        free(c->oldest_file);
+                                        c->oldest_file = n;
+                                        c->oldest_mtime = t;
+                                }
+
+                        } else {
+                                _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL;
+
+                                n = new0(struct vacuum_candidate, 1);
+                                if (!n)
+                                        return log_oom();
+
+                                n->oldest_file = strdup(de->d_name);
+                                if (!n->oldest_file)
+                                        return log_oom();
+
+                                n->oldest_mtime = t;
+
+                                r = hashmap_put(h, UID_TO_PTR(uid), n);
+                                if (r < 0)
+                                        return log_oom();
+
+                                c = n;
+                                n = NULL;
+                        }
+
+                        c->n_files++;
+
+                        if (!worst ||
+                            worst->n_files < c->n_files ||
+                            (worst->n_files == c->n_files && c->oldest_mtime < worst->oldest_mtime))
+                                worst = c;
+
+                        sum += st.st_blocks * 512;
+                }
+
+                if (!worst)
+                        break;
+
+                r = vacuum_necessary(dirfd(d), sum, keep_free, max_use);
+                if (r <= 0)
+                        return r;
+
+                if (unlinkat(dirfd(d), worst->oldest_file, 0) < 0) {
+
+                        if (errno == ENOENT)
+                                continue;
+
+                        return log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file);
+                } else
+                        log_info("Removed old coredump %s.", worst->oldest_file);
+        }
+
+        return 0;
+
+fail:
+        return log_error_errno(errno, "Failed to read directory: %m");
+}
diff --git a/src/coredump/coredump-vacuum.h b/src/coredump/coredump-vacuum.h
new file mode 100644 (file)
index 0000000..4b7b9f2
--- /dev/null
@@ -0,0 +1,25 @@
+#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 <inttypes.h>
+#include <sys/types.h>
+
+int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use);
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
new file mode 100644 (file)
index 0000000..085909c
--- /dev/null
@@ -0,0 +1,1148 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2012 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 <errno.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#ifdef HAVE_ELFUTILS
+#include <dwarf.h>
+#include <elfutils/libdwfl.h>
+#endif
+
+#include "sd-journal.h"
+#include "sd-login.h"
+#include "sd-daemon.h"
+
+#include "acl-util.h"
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "cgroup-util.h"
+#include "compress.h"
+#include "conf-parser.h"
+#include "copy.h"
+#include "coredump-vacuum.h"
+#include "dirent-util.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "io-util.h"
+#include "journald-native.h"
+#include "log.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "socket-util.h"
+#include "special.h"
+#include "stacktrace.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
+
+/* The maximum size up to which we process coredumps */
+#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU))
+
+/* The maximum size up to which we leave the coredump around on disk */
+#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
+
+/* The maximum size up to which we store the coredump in the journal */
+#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
+
+/* Make sure to not make this larger than the maximum journal entry
+ * size. See DATA_SIZE_MAX in journald-native.c. */
+assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
+
+enum {
+        /* We use this as array indexes for a couple of special fields we use for naming coredumping files, and
+         * attaching xattrs */
+        CONTEXT_PID,
+        CONTEXT_UID,
+        CONTEXT_GID,
+        CONTEXT_SIGNAL,
+        CONTEXT_TIMESTAMP,
+        CONTEXT_RLIMIT,
+        CONTEXT_COMM,
+        CONTEXT_EXE,
+        _CONTEXT_MAX
+};
+
+typedef enum CoredumpStorage {
+        COREDUMP_STORAGE_NONE,
+        COREDUMP_STORAGE_EXTERNAL,
+        COREDUMP_STORAGE_JOURNAL,
+        COREDUMP_STORAGE_BOTH,
+        _COREDUMP_STORAGE_MAX,
+        _COREDUMP_STORAGE_INVALID = -1
+} CoredumpStorage;
+
+static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
+        [COREDUMP_STORAGE_NONE] = "none",
+        [COREDUMP_STORAGE_EXTERNAL] = "external",
+        [COREDUMP_STORAGE_JOURNAL] = "journal",
+        [COREDUMP_STORAGE_BOTH] = "both",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting");
+
+static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL;
+static bool arg_compress = true;
+static uint64_t arg_process_size_max = PROCESS_SIZE_MAX;
+static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX;
+static size_t arg_journal_size_max = JOURNAL_SIZE_MAX;
+static uint64_t arg_keep_free = (uint64_t) -1;
+static uint64_t arg_max_use = (uint64_t) -1;
+
+static int parse_config(void) {
+        static const ConfigTableItem items[] = {
+                { "Coredump", "Storage",          config_parse_coredump_storage,  0, &arg_storage           },
+                { "Coredump", "Compress",         config_parse_bool,              0, &arg_compress          },
+                { "Coredump", "ProcessSizeMax",   config_parse_iec_uint64,        0, &arg_process_size_max  },
+                { "Coredump", "ExternalSizeMax",  config_parse_iec_uint64,        0, &arg_external_size_max },
+                { "Coredump", "JournalSizeMax",   config_parse_iec_size,          0, &arg_journal_size_max  },
+                { "Coredump", "KeepFree",         config_parse_iec_uint64,        0, &arg_keep_free         },
+                { "Coredump", "MaxUse",           config_parse_iec_uint64,        0, &arg_max_use           },
+                {}
+        };
+
+        return config_parse_many(PKGSYSCONFDIR "/coredump.conf",
+                                 CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
+                                 "Coredump\0",
+                                 config_item_table_lookup, items,
+                                 false, NULL);
+}
+
+static int fix_acl(int fd, uid_t uid) {
+
+#ifdef HAVE_ACL
+        _cleanup_(acl_freep) acl_t acl = NULL;
+        acl_entry_t entry;
+        acl_permset_t permset;
+        int r;
+
+        assert(fd >= 0);
+
+        if (uid <= SYSTEM_UID_MAX)
+                return 0;
+
+        /* Make sure normal users can read (but not write or delete)
+         * their own coredumps */
+
+        acl = acl_get_fd(fd);
+        if (!acl)
+                return log_error_errno(errno, "Failed to get ACL: %m");
+
+        if (acl_create_entry(&acl, &entry) < 0 ||
+            acl_set_tag_type(entry, ACL_USER) < 0 ||
+            acl_set_qualifier(entry, &uid) < 0) {
+                log_error_errno(errno, "Failed to patch ACL: %m");
+                return -errno;
+        }
+
+        if (acl_get_permset(entry, &permset) < 0 ||
+            acl_add_perm(permset, ACL_READ) < 0)
+                return log_warning_errno(errno, "Failed to patch ACL: %m");
+
+        r = calc_acl_mask_if_needed(&acl);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to patch ACL: %m");
+
+        if (acl_set_fd(fd, acl) < 0)
+                return log_error_errno(errno, "Failed to apply ACL: %m");
+#endif
+
+        return 0;
+}
+
+static int fix_xattr(int fd, const char *context[_CONTEXT_MAX]) {
+
+        static const char * const xattrs[_CONTEXT_MAX] = {
+                [CONTEXT_PID] = "user.coredump.pid",
+                [CONTEXT_UID] = "user.coredump.uid",
+                [CONTEXT_GID] = "user.coredump.gid",
+                [CONTEXT_SIGNAL] = "user.coredump.signal",
+                [CONTEXT_TIMESTAMP] = "user.coredump.timestamp",
+                [CONTEXT_COMM] = "user.coredump.comm",
+                [CONTEXT_EXE] = "user.coredump.exe",
+        };
+
+        int r = 0;
+        unsigned i;
+
+        assert(fd >= 0);
+
+        /* Attach some metadata to coredumps via extended
+         * attributes. Just because we can. */
+
+        for (i = 0; i < _CONTEXT_MAX; i++) {
+                int k;
+
+                if (isempty(context[i]) || !xattrs[i])
+                        continue;
+
+                k = fsetxattr(fd, xattrs[i], context[i], strlen(context[i]), XATTR_CREATE);
+                if (k < 0 && r == 0)
+                        r = -errno;
+        }
+
+        return r;
+}
+
+#define filename_escape(s) xescape((s), "./ ")
+
+static int fix_permissions(
+                int fd,
+                const char *filename,
+                const char *target,
+                const char *context[_CONTEXT_MAX],
+                uid_t uid) {
+
+        assert(fd >= 0);
+        assert(filename);
+        assert(target);
+        assert(context);
+
+        /* Ignore errors on these */
+        (void) fchmod(fd, 0640);
+        (void) fix_acl(fd, uid);
+        (void) fix_xattr(fd, context);
+
+        if (fsync(fd) < 0)
+                return log_error_errno(errno, "Failed to sync coredump %s: %m", filename);
+
+        if (rename(filename, target) < 0)
+                return log_error_errno(errno, "Failed to rename coredump %s -> %s: %m", filename, target);
+
+        return 0;
+}
+
+static int maybe_remove_external_coredump(const char *filename, uint64_t size) {
+
+        /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */
+
+        if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) &&
+            size <= arg_external_size_max)
+                return 0;
+
+        if (!filename)
+                return 1;
+
+        if (unlink(filename) < 0 && errno != ENOENT)
+                return log_error_errno(errno, "Failed to unlink %s: %m", filename);
+
+        return 1;
+}
+
+static int make_filename(const char *context[_CONTEXT_MAX], char **ret) {
+        _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
+        sd_id128_t boot = {};
+        int r;
+
+        assert(context);
+
+        c = filename_escape(context[CONTEXT_COMM]);
+        if (!c)
+                return -ENOMEM;
+
+        u = filename_escape(context[CONTEXT_UID]);
+        if (!u)
+                return -ENOMEM;
+
+        r = sd_id128_get_boot(&boot);
+        if (r < 0)
+                return r;
+
+        p = filename_escape(context[CONTEXT_PID]);
+        if (!p)
+                return -ENOMEM;
+
+        t = filename_escape(context[CONTEXT_TIMESTAMP]);
+        if (!t)
+                return -ENOMEM;
+
+        if (asprintf(ret,
+                     "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
+                     c,
+                     u,
+                     SD_ID128_FORMAT_VAL(boot),
+                     p,
+                     t) < 0)
+                return -ENOMEM;
+
+        return 0;
+}
+
+static int save_external_coredump(
+                const char *context[_CONTEXT_MAX],
+                int input_fd,
+                char **ret_filename,
+                int *ret_node_fd,
+                int *ret_data_fd,
+                uint64_t *ret_size) {
+
+        _cleanup_free_ char *fn = NULL, *tmp = NULL;
+        _cleanup_close_ int fd = -1;
+        uint64_t rlimit, max_size;
+        struct stat st;
+        uid_t uid;
+        int r;
+
+        assert(context);
+        assert(ret_filename);
+        assert(ret_node_fd);
+        assert(ret_data_fd);
+        assert(ret_size);
+
+        r = parse_uid(context[CONTEXT_UID], &uid);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse UID: %m");
+
+        r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse resource limit: %s", context[CONTEXT_RLIMIT]);
+        if (rlimit <= 0) {
+                /* Is coredumping disabled? Then don't bother saving/processing the coredump */
+                log_info("Core Dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]);
+                return -EBADSLT;
+        }
+
+        /* Never store more than the process configured, or than we actually shall keep or process */
+        max_size = MIN(rlimit, MAX(arg_process_size_max, arg_external_size_max));
+
+        r = make_filename(context, &fn);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine coredump file name: %m");
+
+        r = tempfn_random(fn, NULL, &tmp);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine temporary file name: %m");
+
+        mkdir_p_label("/var/lib/systemd/coredump", 0755);
+
+        fd = open(tmp, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
+        if (fd < 0)
+                return log_error_errno(errno, "Failed to create coredump file %s: %m", tmp);
+
+        r = copy_bytes(input_fd, fd, max_size, false);
+        if (r == -EFBIG) {
+                log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]);
+                goto fail;
+        } else if (IN_SET(r, -EDQUOT, -ENOSPC)) {
+                log_error("Not enough disk space for coredump of %s (%s), refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]);
+                goto fail;
+        } else if (r < 0) {
+                log_error_errno(r, "Failed to dump coredump to file: %m");
+                goto fail;
+        }
+
+        if (fstat(fd, &st) < 0) {
+                log_error_errno(errno, "Failed to fstat coredump %s: %m", tmp);
+                goto fail;
+        }
+
+        if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
+                log_error_errno(errno, "Failed to seek on %s: %m", tmp);
+                goto fail;
+        }
+
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+        /* If we will remove the coredump anyway, do not compress. */
+        if (maybe_remove_external_coredump(NULL, st.st_size) == 0
+            && arg_compress) {
+
+                _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL;
+                _cleanup_close_ int fd_compressed = -1;
+
+                fn_compressed = strappend(fn, COMPRESSED_EXT);
+                if (!fn_compressed) {
+                        log_oom();
+                        goto uncompressed;
+                }
+
+                r = tempfn_random(fn_compressed, NULL, &tmp_compressed);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to determine temporary file name for %s: %m", fn_compressed);
+                        goto uncompressed;
+                }
+
+                fd_compressed = open(tmp_compressed, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
+                if (fd_compressed < 0) {
+                        log_error_errno(errno, "Failed to create file %s: %m", tmp_compressed);
+                        goto uncompressed;
+                }
+
+                r = compress_stream(fd, fd_compressed, -1);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to compress %s: %m", tmp_compressed);
+                        goto fail_compressed;
+                }
+
+                r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
+                if (r < 0)
+                        goto fail_compressed;
+
+                /* OK, this worked, we can get rid of the uncompressed version now */
+                unlink_noerrno(tmp);
+
+                *ret_filename = fn_compressed;     /* compressed */
+                *ret_node_fd = fd_compressed;      /* compressed */
+                *ret_data_fd = fd;                 /* uncompressed */
+                *ret_size = (uint64_t) st.st_size; /* uncompressed */
+
+                fn_compressed = NULL;
+                fd = fd_compressed = -1;
+
+                return 0;
+
+        fail_compressed:
+                (void) unlink(tmp_compressed);
+        }
+
+uncompressed:
+#endif
+
+        r = fix_permissions(fd, tmp, fn, context, uid);
+        if (r < 0)
+                goto fail;
+
+        *ret_filename = fn;
+        *ret_data_fd = fd;
+        *ret_node_fd = -1;
+        *ret_size = (uint64_t) st.st_size;
+
+        fn = NULL;
+        fd = -1;
+
+        return 0;
+
+fail:
+        (void) unlink(tmp);
+        return r;
+}
+
+static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) {
+        _cleanup_free_ char *field = NULL;
+        ssize_t n;
+
+        assert(fd >= 0);
+        assert(ret);
+        assert(ret_size);
+
+        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+                return log_warning_errno(errno, "Failed to seek: %m");
+
+        field = malloc(9 + size);
+        if (!field) {
+                log_warning("Failed to allocate memory for coredump, coredump will not be stored.");
+                return -ENOMEM;
+        }
+
+        memcpy(field, "COREDUMP=", 9);
+
+        n = read(fd, field + 9, size);
+        if (n < 0)
+                return log_error_errno((int) n, "Failed to read core data: %m");
+        if ((size_t) n < size) {
+                log_error("Core data too short.");
+                return -EIO;
+        }
+
+        *ret = field;
+        *ret_size = size + 9;
+
+        field = NULL;
+
+        return 0;
+}
+
+/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines:
+ * 0:/dev/pts/23
+ * pos:    0
+ * flags:  0100002
+ *
+ * 1:/dev/pts/23
+ * pos:    0
+ * flags:  0100002
+ *
+ * 2:/dev/pts/23
+ * pos:    0
+ * flags:  0100002
+ * EOF
+ */
+static int compose_open_fds(pid_t pid, char **open_fds) {
+        _cleanup_closedir_ DIR *proc_fd_dir = NULL;
+        _cleanup_close_ int proc_fdinfo_fd = -1;
+        _cleanup_free_ char *buffer = NULL;
+        _cleanup_fclose_ FILE *stream = NULL;
+        const char *fddelim = "", *path;
+        struct dirent *dent = NULL;
+        size_t size = 0;
+        int r = 0;
+
+        assert(pid >= 0);
+        assert(open_fds != NULL);
+
+        path = procfs_file_alloca(pid, "fd");
+        proc_fd_dir = opendir(path);
+        if (!proc_fd_dir)
+                return -errno;
+
+        proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH);
+        if (proc_fdinfo_fd < 0)
+                return -errno;
+
+        stream = open_memstream(&buffer, &size);
+        if (!stream)
+                return -ENOMEM;
+
+        FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
+                _cleanup_fclose_ FILE *fdinfo = NULL;
+                _cleanup_free_ char *fdname = NULL;
+                char line[LINE_MAX];
+                int fd;
+
+                r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
+                if (r < 0)
+                        return r;
+
+                fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname);
+                fddelim = "\n";
+
+                /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */
+                fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY);
+                if (fd < 0)
+                        continue;
+
+                fdinfo = fdopen(fd, "re");
+                if (fdinfo == NULL) {
+                        close(fd);
+                        continue;
+                }
+
+                FOREACH_LINE(line, fdinfo, break) {
+                        fputs(line, stream);
+                        if (!endswith(line, "\n"))
+                                fputc('\n', stream);
+                }
+        }
+
+        errno = 0;
+        stream = safe_fclose(stream);
+
+        if (errno > 0)
+                return -errno;
+
+        *open_fds = buffer;
+        buffer = NULL;
+
+        return 0;
+}
+
+static int change_uid_gid(const char *context[]) {
+        uid_t uid;
+        gid_t gid;
+        int r;
+
+        r = parse_uid(context[CONTEXT_UID], &uid);
+        if (r < 0)
+                return r;
+
+        if (uid <= SYSTEM_UID_MAX) {
+                const char *user = "systemd-coredump";
+
+                r = get_user_creds(&user, &uid, &gid, NULL, NULL);
+                if (r < 0) {
+                        log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user);
+                        uid = gid = 0;
+                }
+        } else {
+                r = parse_gid(context[CONTEXT_GID], &gid);
+                if (r < 0)
+                        return r;
+        }
+
+        return drop_privileges(uid, gid, 0);
+}
+
+static int submit_coredump(
+                const char *context[_CONTEXT_MAX],
+                struct iovec *iovec,
+                size_t n_iovec_allocated,
+                size_t n_iovec,
+                int input_fd) {
+
+        _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
+        _cleanup_free_ char *core_message = NULL, *filename = NULL, *coredump_data = NULL;
+        uint64_t coredump_size;
+        int r;
+
+        assert(context);
+        assert(iovec);
+        assert(n_iovec_allocated >= n_iovec + 3);
+        assert(input_fd >= 0);
+
+        /* Vacuum before we write anything again */
+        (void) coredump_vacuum(-1, arg_keep_free, arg_max_use);
+
+        /* Always stream the coredump to disk, if that's possible */
+        r = save_external_coredump(context, input_fd, &filename, &coredump_node_fd, &coredump_fd, &coredump_size);
+        if (r < 0)
+                /* Skip whole core dumping part */
+                goto log;
+
+        /* If we don't want to keep the coredump on disk, remove it now, as later on we will lack the privileges for
+         * it. However, we keep the fd to it, so that we can still process it and log it. */
+        r = maybe_remove_external_coredump(filename, coredump_size);
+        if (r < 0)
+                return r;
+        if (r == 0) {
+                const char *coredump_filename;
+
+                coredump_filename = strjoina("COREDUMP_FILENAME=", filename);
+                IOVEC_SET_STRING(iovec[n_iovec++], coredump_filename);
+        }
+
+        /* Vacuum again, but exclude the coredump we just created */
+        (void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use);
+
+        /* Now, let's drop privileges to become the user who owns the segfaulted process and allocate the coredump
+         * memory under the user's uid. This also ensures that the credentials journald will see are the ones of the
+         * coredumping user, thus making sure the user gets access to the core dump. Let's also get rid of all
+         * capabilities, if we run as root, we won't need them anymore. */
+        r = change_uid_gid(context);
+        if (r < 0)
+                return log_error_errno(r, "Failed to drop privileges: %m");
+
+#ifdef HAVE_ELFUTILS
+        /* Try to get a strack trace if we can */
+        if (coredump_size <= arg_process_size_max) {
+                _cleanup_free_ char *stacktrace = NULL;
+
+                r = coredump_make_stack_trace(coredump_fd, context[CONTEXT_EXE], &stacktrace);
+                if (r >= 0)
+                        core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", context[CONTEXT_COMM], ") of user ", context[CONTEXT_UID], " dumped core.\n\n", stacktrace, NULL);
+                else if (r == -EINVAL)
+                        log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno()));
+                else
+                        log_warning_errno(r, "Failed to generate stack trace: %m");
+        }
+
+        if (!core_message)
+#endif
+log:
+        core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", context[CONTEXT_COMM], ") of user ", context[CONTEXT_UID], " dumped core.", NULL);
+        if (core_message)
+                IOVEC_SET_STRING(iovec[n_iovec++], core_message);
+
+        /* Optionally store the entire coredump in the journal */
+        if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
+            coredump_size <= arg_journal_size_max) {
+                size_t sz = 0;
+
+                /* Store the coredump itself in the journal */
+
+                r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz);
+                if (r >= 0) {
+                        iovec[n_iovec].iov_base = coredump_data;
+                        iovec[n_iovec].iov_len = sz;
+                        n_iovec++;
+                }
+        }
+
+        assert(n_iovec <= n_iovec_allocated);
+
+        r = sd_journal_sendv(iovec, n_iovec);
+        if (r < 0)
+                return log_error_errno(r, "Failed to log coredump: %m");
+
+        return 0;
+}
+
+static void map_context_fields(const struct iovec *iovec, const char *context[]) {
+
+        static const char * const context_field_names[_CONTEXT_MAX] = {
+                [CONTEXT_PID] = "COREDUMP_PID=",
+                [CONTEXT_UID] = "COREDUMP_UID=",
+                [CONTEXT_GID] = "COREDUMP_GID=",
+                [CONTEXT_SIGNAL] = "COREDUMP_SIGNAL=",
+                [CONTEXT_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
+                [CONTEXT_COMM] = "COREDUMP_COMM=",
+                [CONTEXT_EXE] = "COREDUMP_EXE=",
+                [CONTEXT_RLIMIT] = "COREDUMP_RLIMIT=",
+        };
+
+        unsigned i;
+
+        assert(iovec);
+        assert(context);
+
+        for (i = 0; i < _CONTEXT_MAX; i++) {
+                size_t l;
+
+                l = strlen(context_field_names[i]);
+                if (iovec->iov_len < l)
+                        continue;
+
+                if (memcmp(iovec->iov_base, context_field_names[i], l) != 0)
+                        continue;
+
+                /* Note that these strings are NUL terminated, because we made sure that a trailing NUL byte is in the
+                 * buffer, though not included in the iov_len count. (see below) */
+                context[i] = (char*) iovec->iov_base + l;
+                break;
+        }
+}
+
+static int process_socket(int fd) {
+        _cleanup_close_ int coredump_fd = -1;
+        struct iovec *iovec = NULL;
+        size_t n_iovec = 0, n_iovec_allocated = 0, i;
+        const char *context[_CONTEXT_MAX] = {};
+        int r;
+
+        assert(fd >= 0);
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        for (;;) {
+                union {
+                        struct cmsghdr cmsghdr;
+                        uint8_t buf[CMSG_SPACE(sizeof(int))];
+                } control = {};
+                struct msghdr mh = {
+                        .msg_control = &control,
+                        .msg_controllen = sizeof(control),
+                        .msg_iovlen = 1,
+                };
+                ssize_t n;
+                int l;
+
+                if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) {
+                        r = log_oom();
+                        goto finish;
+                }
+
+                if (ioctl(fd, FIONREAD, &l) < 0) {
+                        r = log_error_errno(errno, "FIONREAD failed: %m");
+                        goto finish;
+                }
+
+                assert(l >= 0);
+
+                iovec[n_iovec].iov_len = l;
+                iovec[n_iovec].iov_base = malloc(l + 1);
+
+                if (!iovec[n_iovec].iov_base) {
+                        r = log_oom();
+                        goto finish;
+                }
+
+                mh.msg_iov = iovec + n_iovec;
+
+                n = recvmsg(fd, &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+                if (n < 0)  {
+                        free(iovec[n_iovec].iov_base);
+                        r = log_error_errno(errno, "Failed to receive datagram: %m");
+                        goto finish;
+                }
+
+                if (n == 0) {
+                        struct cmsghdr *cmsg, *found = NULL;
+                        /* The final zero-length datagram carries the file descriptor and tells us that we're done. */
+
+                        free(iovec[n_iovec].iov_base);
+
+                        CMSG_FOREACH(cmsg, &mh) {
+                                if (cmsg->cmsg_level == SOL_SOCKET &&
+                                    cmsg->cmsg_type == SCM_RIGHTS &&
+                                    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+                                        assert(!found);
+                                        found = cmsg;
+                                }
+                        }
+
+                        if (!found) {
+                                log_error("Coredump file descriptor missing.");
+                                r = -EBADMSG;
+                                goto finish;
+                        }
+
+                        assert(coredump_fd < 0);
+                        coredump_fd = *(int*) CMSG_DATA(found);
+                        break;
+                }
+
+                /* Add trailing NUL byte, in case these are strings */
+                ((char*) iovec[n_iovec].iov_base)[n] = 0;
+                iovec[n_iovec].iov_len = (size_t) n;
+
+                cmsg_close_all(&mh);
+                map_context_fields(iovec + n_iovec, context);
+                n_iovec++;
+        }
+
+        if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) {
+                r = log_oom();
+                goto finish;
+        }
+
+        /* Make sure we we got all data we really need */
+        assert(context[CONTEXT_PID]);
+        assert(context[CONTEXT_UID]);
+        assert(context[CONTEXT_GID]);
+        assert(context[CONTEXT_SIGNAL]);
+        assert(context[CONTEXT_TIMESTAMP]);
+        assert(context[CONTEXT_RLIMIT]);
+        assert(context[CONTEXT_COMM]);
+        assert(coredump_fd >= 0);
+
+        r = submit_coredump(context, iovec, n_iovec_allocated, n_iovec, coredump_fd);
+
+finish:
+        for (i = 0; i < n_iovec; i++)
+                free(iovec[i].iov_base);
+        free(iovec);
+
+        return r;
+}
+
+static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd) {
+
+        static const union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX,
+                .un.sun_path = "/run/systemd/coredump",
+        };
+        _cleanup_close_ int fd = -1;
+        size_t i;
+        int r;
+
+        assert(iovec || n_iovec <= 0);
+        assert(input_fd >= 0);
+
+        fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
+        if (fd < 0)
+                return log_error_errno(errno, "Failed to create coredump socket: %m");
+
+        if (connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0)
+                return log_error_errno(errno, "Failed to connect to coredump service: %m");
+
+        for (i = 0; i < n_iovec; i++) {
+                ssize_t n;
+                assert(iovec[i].iov_len > 0);
+
+                n = send(fd, iovec[i].iov_base, iovec[i].iov_len, MSG_NOSIGNAL);
+                if (n < 0)
+                        return log_error_errno(errno, "Failed to send coredump datagram: %m");
+        }
+
+        r = send_one_fd(fd, input_fd, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to send coredump fd: %m");
+
+        return 0;
+}
+
+static int process_journald_crash(const char *context[], int input_fd) {
+        _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
+        _cleanup_free_ char *filename = NULL;
+        uint64_t coredump_size;
+        int r;
+
+        assert(context);
+        assert(input_fd >= 0);
+
+        /* If we are journald, we cut things short, don't write to the journal, but still create a coredump. */
+
+        if (arg_storage != COREDUMP_STORAGE_NONE)
+                arg_storage = COREDUMP_STORAGE_EXTERNAL;
+
+        r = save_external_coredump(context, input_fd, &filename, &coredump_node_fd, &coredump_fd, &coredump_size);
+        if (r < 0)
+                return r;
+
+        r = maybe_remove_external_coredump(filename, coredump_size);
+        if (r < 0)
+                return r;
+
+        log_info("Detected coredump of the journal daemon itself, diverted to %s.", filename);
+        return 0;
+}
+
+static int process_kernel(int argc, char* argv[]) {
+
+        /* The small core field we allocate on the stack, to keep things simple */
+        char
+                *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
+                *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL,
+                *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL,
+                *core_user_unit = NULL, *core_slice = NULL, *core_timestamp = NULL, *core_rlimit = NULL;
+
+        /* The larger ones we allocate on the heap */
+        _cleanup_free_ char
+                *core_owner_uid = NULL, *core_open_fds = NULL, *core_proc_status = NULL,
+                *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL;
+
+        _cleanup_free_ char *exe = NULL, *comm = NULL;
+        const char *context[_CONTEXT_MAX];
+        struct iovec iovec[25];
+        size_t n_iovec = 0;
+        uid_t owner_uid;
+        const char *p;
+        pid_t pid;
+        char *t;
+        int r;
+
+        if (argc < CONTEXT_COMM + 1) {
+                log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1);
+                return -EINVAL;
+        }
+
+        r = parse_pid(argv[CONTEXT_PID + 1], &pid);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse PID.");
+
+        r = get_process_comm(pid, &comm);
+        if (r < 0) {
+                log_warning_errno(r, "Failed to get COMM, falling back to the command line: %m");
+                comm = strv_join(argv + CONTEXT_COMM + 1, " ");
+                if (!comm)
+                        return log_oom();
+        }
+
+        r = get_process_exe(pid, &exe);
+        if (r < 0)
+                log_warning_errno(r, "Failed to get EXE, ignoring: %m");
+
+        context[CONTEXT_PID] = argv[CONTEXT_PID + 1];
+        context[CONTEXT_UID] = argv[CONTEXT_UID + 1];
+        context[CONTEXT_GID] = argv[CONTEXT_GID + 1];
+        context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 1];
+        context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1];
+        context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1];
+        context[CONTEXT_COMM] = comm;
+        context[CONTEXT_EXE] = exe;
+
+        if (cg_pid_get_unit(pid, &t) >= 0) {
+
+                if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
+                        free(t);
+                        return process_journald_crash(context, STDIN_FILENO);
+                }
+
+                core_unit = strjoina("COREDUMP_UNIT=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_unit);
+        }
+
+        /* OK, now we know it's not the journal, hence we can make use of it now. */
+        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+        log_open();
+
+        if (cg_pid_get_user_unit(pid, &t) >= 0) {
+                core_user_unit = strjoina("COREDUMP_USER_UNIT=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_user_unit);
+        }
+
+        core_pid = strjoina("COREDUMP_PID=", context[CONTEXT_PID]);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_pid);
+
+        core_uid = strjoina("COREDUMP_UID=", context[CONTEXT_UID]);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_uid);
+
+        core_gid = strjoina("COREDUMP_GID=", context[CONTEXT_GID]);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_gid);
+
+        core_signal = strjoina("COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_signal);
+
+        core_rlimit = strjoina("COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_rlimit);
+
+        if (sd_pid_get_session(pid, &t) >= 0) {
+                core_session = strjoina("COREDUMP_SESSION=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_session);
+        }
+
+        if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
+                r = asprintf(&core_owner_uid, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
+                if (r > 0)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_owner_uid);
+        }
+
+        if (sd_pid_get_slice(pid, &t) >= 0) {
+                core_slice = strjoina("COREDUMP_SLICE=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_slice);
+        }
+
+        if (comm) {
+                core_comm = strjoina("COREDUMP_COMM=", comm);
+                IOVEC_SET_STRING(iovec[n_iovec++], core_comm);
+        }
+
+        if (exe) {
+                core_exe = strjoina("COREDUMP_EXE=", exe);
+                IOVEC_SET_STRING(iovec[n_iovec++], core_exe);
+        }
+
+        if (get_process_cmdline(pid, 0, false, &t) >= 0) {
+                core_cmdline = strjoina("COREDUMP_CMDLINE=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_cmdline);
+        }
+
+        if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) {
+                core_cgroup = strjoina("COREDUMP_CGROUP=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_cgroup);
+        }
+
+        if (compose_open_fds(pid, &t) >= 0) {
+                core_open_fds = strappend("COREDUMP_OPEN_FDS=", t);
+                free(t);
+
+                if (core_open_fds)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_open_fds);
+        }
+
+        p = procfs_file_alloca(pid, "status");
+        if (read_full_file(p, &t, NULL) >= 0) {
+                core_proc_status = strappend("COREDUMP_PROC_STATUS=", t);
+                free(t);
+
+                if (core_proc_status)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_proc_status);
+        }
+
+        p = procfs_file_alloca(pid, "maps");
+        if (read_full_file(p, &t, NULL) >= 0) {
+                core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t);
+                free(t);
+
+                if (core_proc_maps)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_proc_maps);
+        }
+
+        p = procfs_file_alloca(pid, "limits");
+        if (read_full_file(p, &t, NULL) >= 0) {
+                core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t);
+                free(t);
+
+                if (core_proc_limits)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_proc_limits);
+        }
+
+        p = procfs_file_alloca(pid, "cgroup");
+        if (read_full_file(p, &t, NULL) >=0) {
+                core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t);
+                free(t);
+
+                if (core_proc_cgroup)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_proc_cgroup);
+        }
+
+        if (get_process_cwd(pid, &t) >= 0) {
+                core_cwd = strjoina("COREDUMP_CWD=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_cwd);
+        }
+
+        if (get_process_root(pid, &t) >= 0) {
+                core_root = strjoina("COREDUMP_ROOT=", t);
+                free(t);
+
+                IOVEC_SET_STRING(iovec[n_iovec++], core_root);
+        }
+
+        if (get_process_environ(pid, &t) >= 0) {
+                core_environ = strappend("COREDUMP_ENVIRON=", t);
+                free(t);
+
+                if (core_environ)
+                        IOVEC_SET_STRING(iovec[n_iovec++], core_environ);
+        }
+
+        core_timestamp = strjoina("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000", NULL);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_timestamp);
+
+        IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
+
+        assert_cc(2 == LOG_CRIT);
+        IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2");
+
+        assert(n_iovec <= ELEMENTSOF(iovec));
+
+        return send_iovec(iovec, n_iovec, STDIN_FILENO);
+}
+
+int main(int argc, char *argv[]) {
+        int r;
+
+        /* First, log to a safe place, since we don't know what crashed and it might be journald which we'd rather not
+         * log to then. */
+
+        log_set_target(LOG_TARGET_KMSG);
+        log_open();
+
+        /* Make sure we never enter a loop */
+        (void) prctl(PR_SET_DUMPABLE, 0);
+
+        /* Ignore all parse errors */
+        (void) parse_config();
+
+        log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
+        log_debug("Selected compression %s.", yes_no(arg_compress));
+
+        r = sd_listen_fds(false);
+        if (r < 0) {
+                log_error_errno(r, "Failed to determine number of file descriptor: %m");
+                goto finish;
+        }
+
+        /* If we got an fd passed, we are running in coredumpd mode. Otherwise we are invoked from the kernel as
+         * coredump handler */
+        if (r == 0)
+                r = process_kernel(argc, argv);
+        else if (r == 1)
+                r = process_socket(SD_LISTEN_FDS_START);
+        else {
+                log_error("Received unexpected number of file descriptors.");
+                r = -EINVAL;
+        }
+
+finish:
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/coredump/coredump.conf b/src/coredump/coredump.conf
new file mode 100644 (file)
index 0000000..c2f0643
--- /dev/null
@@ -0,0 +1,21 @@
+#  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.
+#
+# Entries in this file show the compile time defaults.
+# You can change settings by editing this file.
+# Defaults can be restored by simply deleting this file.
+#
+# See coredump.conf(5) for details.
+
+[Coredump]
+#Storage=external
+#Compress=yes
+#ProcessSizeMax=2G
+#ExternalSizeMax=2G
+#JournalSizeMax=767M
+#MaxUse=
+#KeepFree=
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
new file mode 100644 (file)
index 0000000..0034a1a
--- /dev/null
@@ -0,0 +1,880 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2012 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 <fcntl.h>
+#include <getopt.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sd-journal.h"
+
+#include "alloc-util.h"
+#include "compress.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "journal-internal.h"
+#include "log.h"
+#include "macro.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "set.h"
+#include "sigbus.h"
+#include "signal-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "user-util.h"
+#include "util.h"
+
+static enum {
+        ACTION_NONE,
+        ACTION_INFO,
+        ACTION_LIST,
+        ACTION_DUMP,
+        ACTION_GDB,
+} arg_action = ACTION_LIST;
+static const char* arg_field = NULL;
+static const char *arg_directory = NULL;
+static int arg_no_pager = false;
+static int arg_no_legend = false;
+static int arg_one = false;
+static FILE* arg_output = NULL;
+
+static Set *new_matches(void) {
+        Set *set;
+        char *tmp;
+        int r;
+
+        set = set_new(NULL);
+        if (!set) {
+                log_oom();
+                return NULL;
+        }
+
+        tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
+        if (!tmp) {
+                log_oom();
+                set_free(set);
+                return NULL;
+        }
+
+        r = set_consume(set, tmp);
+        if (r < 0) {
+                log_error_errno(r, "failed to add to set: %m");
+                set_free(set);
+                return NULL;
+        }
+
+        return set;
+}
+
+static int add_match(Set *set, const char *match) {
+        _cleanup_free_ char *p = NULL;
+        char *pattern = NULL;
+        const char* prefix;
+        pid_t pid;
+        int r;
+
+        if (strchr(match, '='))
+                prefix = "";
+        else if (strchr(match, '/')) {
+                r = path_make_absolute_cwd(match, &p);
+                if (r < 0)
+                        goto fail;
+                match = p;
+                prefix = "COREDUMP_EXE=";
+        } else if (parse_pid(match, &pid) >= 0)
+                prefix = "COREDUMP_PID=";
+        else
+                prefix = "COREDUMP_COMM=";
+
+        pattern = strjoin(prefix, match, NULL);
+        if (!pattern) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        log_debug("Adding pattern: %s", pattern);
+        r = set_consume(set, pattern);
+        if (r < 0)
+                goto fail;
+
+        return 0;
+fail:
+        return log_error_errno(r, "Failed to add match: %m");
+}
+
+static void help(void) {
+        printf("%s [OPTIONS...]\n\n"
+               "List or retrieve coredumps from the journal.\n\n"
+               "Flags:\n"
+               "  -h --help          Show this help\n"
+               "     --version       Print version string\n"
+               "     --no-pager      Do not pipe output into a pager\n"
+               "     --no-legend     Do not print the column headers.\n"
+               "  -1                 Show information about most recent entry only\n"
+               "  -F --field=FIELD   List all values a certain field takes\n"
+               "  -o --output=FILE   Write output to FILE\n\n"
+               "  -D --directory=DIR Use journal files from directory\n\n"
+
+               "Commands:\n"
+               "  list [MATCHES...]  List available coredumps (default)\n"
+               "  info [MATCHES...]  Show detailed information about one or more coredumps\n"
+               "  dump [MATCHES...]  Print first matching coredump to stdout\n"
+               "  gdb [MATCHES...]   Start gdb for the first matching coredump\n"
+               , program_invocation_short_name);
+}
+
+static int parse_argv(int argc, char *argv[], Set *matches) {
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_NO_PAGER,
+                ARG_NO_LEGEND,
+        };
+
+        int r, c;
+
+        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 },
+                { "output",       required_argument, NULL, 'o'           },
+                { "field",        required_argument, NULL, 'F'           },
+                { "directory",    required_argument, NULL, 'D'           },
+                {}
+        };
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "ho:F:1D:", options, NULL)) >= 0)
+                switch(c) {
+
+                case 'h':
+                        arg_action = ACTION_NONE;
+                        help();
+                        return 0;
+
+                case ARG_VERSION:
+                        arg_action = ACTION_NONE;
+                        return version();
+
+                case ARG_NO_PAGER:
+                        arg_no_pager = true;
+                        break;
+
+                case ARG_NO_LEGEND:
+                        arg_no_legend = true;
+                        break;
+
+                case 'o':
+                        if (arg_output) {
+                                log_error("cannot set output more than once");
+                                return -EINVAL;
+                        }
+
+                        arg_output = fopen(optarg, "we");
+                        if (!arg_output)
+                                return log_error_errno(errno, "writing to '%s': %m", optarg);
+
+                        break;
+
+                case 'F':
+                        if (arg_field) {
+                                log_error("cannot use --field/-F more than once");
+                                return -EINVAL;
+                        }
+                        arg_field = optarg;
+                        break;
+
+                case '1':
+                        arg_one = true;
+                        break;
+
+                case 'D':
+                        arg_directory = optarg;
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unhandled option");
+                }
+
+        if (optind < argc) {
+                const char *cmd = argv[optind++];
+                if (streq(cmd, "list"))
+                        arg_action = ACTION_LIST;
+                else if (streq(cmd, "dump"))
+                        arg_action = ACTION_DUMP;
+                else if (streq(cmd, "gdb"))
+                        arg_action = ACTION_GDB;
+                else if (streq(cmd, "info"))
+                        arg_action = ACTION_INFO;
+                else {
+                        log_error("Unknown action '%s'", cmd);
+                        return -EINVAL;
+                }
+        }
+
+        if (arg_field && arg_action != ACTION_LIST) {
+                log_error("Option --field/-F only makes sense with list");
+                return -EINVAL;
+        }
+
+        while (optind < argc) {
+                r = add_match(matches, argv[optind]);
+                if (r != 0)
+                        return r;
+                optind++;
+        }
+
+        return 0;
+}
+
+static int retrieve(const void *data,
+                    size_t len,
+                    const char *name,
+                    char **var) {
+
+        size_t ident;
+        char *v;
+
+        ident = strlen(name) + 1; /* name + "=" */
+
+        if (len < ident)
+                return 0;
+
+        if (memcmp(data, name, ident - 1) != 0)
+                return 0;
+
+        if (((const char*) data)[ident - 1] != '=')
+                return 0;
+
+        v = strndup((const char*)data + ident, len - ident);
+        if (!v)
+                return log_oom();
+
+        free(*var);
+        *var = v;
+
+        return 0;
+}
+
+static void print_field(FILE* file, sd_journal *j) {
+        _cleanup_free_ char *value = NULL;
+        const void *d;
+        size_t l;
+
+        assert(file);
+        assert(j);
+
+        assert(arg_field);
+
+        SD_JOURNAL_FOREACH_DATA(j, d, l)
+                retrieve(d, l, arg_field, &value);
+
+        if (value)
+                fprintf(file, "%s\n", value);
+}
+
+static int print_list(FILE* file, sd_journal *j, int had_legend) {
+        _cleanup_free_ char
+                *pid = NULL, *uid = NULL, *gid = NULL,
+                *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
+                *filename = NULL;
+        const void *d;
+        size_t l;
+        usec_t t;
+        char buf[FORMAT_TIMESTAMP_MAX];
+        int r;
+        bool present;
+
+        assert(file);
+        assert(j);
+
+        SD_JOURNAL_FOREACH_DATA(j, d, l) {
+                retrieve(d, l, "COREDUMP_PID", &pid);
+                retrieve(d, l, "COREDUMP_UID", &uid);
+                retrieve(d, l, "COREDUMP_GID", &gid);
+                retrieve(d, l, "COREDUMP_SIGNAL", &sgnl);
+                retrieve(d, l, "COREDUMP_EXE", &exe);
+                retrieve(d, l, "COREDUMP_COMM", &comm);
+                retrieve(d, l, "COREDUMP_CMDLINE", &cmdline);
+                retrieve(d, l, "COREDUMP_FILENAME", &filename);
+        }
+
+        if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) {
+                log_warning("Empty coredump log entry");
+                return -EINVAL;
+        }
+
+        r = sd_journal_get_realtime_usec(j, &t);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get realtime timestamp: %m");
+
+        format_timestamp(buf, sizeof(buf), t);
+        present = filename && access(filename, F_OK) == 0;
+
+        if (!had_legend && !arg_no_legend)
+                fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n",
+                        FORMAT_TIMESTAMP_WIDTH, "TIME",
+                        6, "PID",
+                        5, "UID",
+                        5, "GID",
+                        3, "SIG",
+                        1, "PRESENT",
+                           "EXE");
+
+        fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n",
+                FORMAT_TIMESTAMP_WIDTH, buf,
+                6, strna(pid),
+                5, strna(uid),
+                5, strna(gid),
+                3, strna(sgnl),
+                1, present ? "*" : "",
+                strna(exe ?: (comm ?: cmdline)));
+
+        return 0;
+}
+
+static int print_info(FILE *file, sd_journal *j, bool need_space) {
+        _cleanup_free_ char
+                *pid = NULL, *uid = NULL, *gid = NULL,
+                *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
+                *unit = NULL, *user_unit = NULL, *session = NULL,
+                *boot_id = NULL, *machine_id = NULL, *hostname = NULL,
+                *slice = NULL, *cgroup = NULL, *owner_uid = NULL,
+                *message = NULL, *timestamp = NULL, *filename = NULL;
+        const void *d;
+        size_t l;
+        int r;
+
+        assert(file);
+        assert(j);
+
+        SD_JOURNAL_FOREACH_DATA(j, d, l) {
+                retrieve(d, l, "COREDUMP_PID", &pid);
+                retrieve(d, l, "COREDUMP_UID", &uid);
+                retrieve(d, l, "COREDUMP_GID", &gid);
+                retrieve(d, l, "COREDUMP_SIGNAL", &sgnl);
+                retrieve(d, l, "COREDUMP_EXE", &exe);
+                retrieve(d, l, "COREDUMP_COMM", &comm);
+                retrieve(d, l, "COREDUMP_CMDLINE", &cmdline);
+                retrieve(d, l, "COREDUMP_UNIT", &unit);
+                retrieve(d, l, "COREDUMP_USER_UNIT", &user_unit);
+                retrieve(d, l, "COREDUMP_SESSION", &session);
+                retrieve(d, l, "COREDUMP_OWNER_UID", &owner_uid);
+                retrieve(d, l, "COREDUMP_SLICE", &slice);
+                retrieve(d, l, "COREDUMP_CGROUP", &cgroup);
+                retrieve(d, l, "COREDUMP_TIMESTAMP", &timestamp);
+                retrieve(d, l, "COREDUMP_FILENAME", &filename);
+                retrieve(d, l, "_BOOT_ID", &boot_id);
+                retrieve(d, l, "_MACHINE_ID", &machine_id);
+                retrieve(d, l, "_HOSTNAME", &hostname);
+                retrieve(d, l, "MESSAGE", &message);
+        }
+
+        if (need_space)
+                fputs("\n", file);
+
+        if (comm)
+                fprintf(file,
+                        "           PID: %s%s%s (%s)\n",
+                        ansi_highlight(), strna(pid), ansi_normal(), comm);
+        else
+                fprintf(file,
+                        "           PID: %s%s%s\n",
+                        ansi_highlight(), strna(pid), ansi_normal());
+
+        if (uid) {
+                uid_t n;
+
+                if (parse_uid(uid, &n) >= 0) {
+                        _cleanup_free_ char *u = NULL;
+
+                        u = uid_to_name(n);
+                        fprintf(file,
+                                "           UID: %s (%s)\n",
+                                uid, u);
+                } else {
+                        fprintf(file,
+                                "           UID: %s\n",
+                                uid);
+                }
+        }
+
+        if (gid) {
+                gid_t n;
+
+                if (parse_gid(gid, &n) >= 0) {
+                        _cleanup_free_ char *g = NULL;
+
+                        g = gid_to_name(n);
+                        fprintf(file,
+                                "           GID: %s (%s)\n",
+                                gid, g);
+                } else {
+                        fprintf(file,
+                                "           GID: %s\n",
+                                gid);
+                }
+        }
+
+        if (sgnl) {
+                int sig;
+
+                if (safe_atoi(sgnl, &sig) >= 0)
+                        fprintf(file, "        Signal: %s (%s)\n", sgnl, signal_to_string(sig));
+                else
+                        fprintf(file, "        Signal: %s\n", sgnl);
+        }
+
+        if (timestamp) {
+                usec_t u;
+
+                r = safe_atou64(timestamp, &u);
+                if (r >= 0) {
+                        char absolute[FORMAT_TIMESTAMP_MAX], relative[FORMAT_TIMESPAN_MAX];
+
+                        fprintf(file,
+                                "     Timestamp: %s (%s)\n",
+                                format_timestamp(absolute, sizeof(absolute), u),
+                                format_timestamp_relative(relative, sizeof(relative), u));
+
+                } else
+                        fprintf(file, "     Timestamp: %s\n", timestamp);
+        }
+
+        if (cmdline)
+                fprintf(file, "  Command Line: %s\n", cmdline);
+        if (exe)
+                fprintf(file, "    Executable: %s%s%s\n", ansi_highlight(), exe, ansi_normal());
+        if (cgroup)
+                fprintf(file, " Control Group: %s\n", cgroup);
+        if (unit)
+                fprintf(file, "          Unit: %s\n", unit);
+        if (user_unit)
+                fprintf(file, "     User Unit: %s\n", unit);
+        if (slice)
+                fprintf(file, "         Slice: %s\n", slice);
+        if (session)
+                fprintf(file, "       Session: %s\n", session);
+        if (owner_uid) {
+                uid_t n;
+
+                if (parse_uid(owner_uid, &n) >= 0) {
+                        _cleanup_free_ char *u = NULL;
+
+                        u = uid_to_name(n);
+                        fprintf(file,
+                                "     Owner UID: %s (%s)\n",
+                                owner_uid, u);
+                } else {
+                        fprintf(file,
+                                "     Owner UID: %s\n",
+                                owner_uid);
+                }
+        }
+        if (boot_id)
+                fprintf(file, "       Boot ID: %s\n", boot_id);
+        if (machine_id)
+                fprintf(file, "    Machine ID: %s\n", machine_id);
+        if (hostname)
+                fprintf(file, "      Hostname: %s\n", hostname);
+
+        if (filename && access(filename, F_OK) == 0)
+                fprintf(file, "      Coredump: %s\n", filename);
+
+        if (message) {
+                _cleanup_free_ char *m = NULL;
+
+                m = strreplace(message, "\n", "\n                ");
+
+                fprintf(file, "       Message: %s\n", strstrip(m ?: message));
+        }
+
+        return 0;
+}
+
+static int focus(sd_journal *j) {
+        int r;
+
+        r = sd_journal_seek_tail(j);
+        if (r == 0)
+                r = sd_journal_previous(j);
+        if (r < 0)
+                return log_error_errno(r, "Failed to search journal: %m");
+        if (r == 0) {
+                log_error("No match found.");
+                return -ESRCH;
+        }
+        return r;
+}
+
+static void print_entry(sd_journal *j, unsigned n_found) {
+        assert(j);
+
+        if (arg_action == ACTION_INFO)
+                print_info(stdout, j, n_found);
+        else if (arg_field)
+                print_field(stdout, j);
+        else
+                print_list(stdout, j, n_found);
+}
+
+static int dump_list(sd_journal *j) {
+        unsigned n_found = 0;
+        int r;
+
+        assert(j);
+
+        /* The coredumps are likely to compressed, and for just
+         * listing them we don't need to decompress them, so let's
+         * pick a fairly low data threshold here */
+        sd_journal_set_data_threshold(j, 4096);
+
+        if (arg_one) {
+                r = focus(j);
+                if (r < 0)
+                        return r;
+
+                print_entry(j, 0);
+        } else {
+                SD_JOURNAL_FOREACH(j)
+                        print_entry(j, n_found++);
+
+                if (!arg_field && n_found <= 0) {
+                        log_notice("No coredumps found.");
+                        return -ESRCH;
+                }
+        }
+
+        return 0;
+}
+
+static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
+        const char *data;
+        _cleanup_free_ char *filename = NULL;
+        size_t len;
+        int r;
+
+        assert((fd >= 0) != !!path);
+        assert(!!path == !!unlink_temp);
+
+        /* Prefer uncompressed file to journal (probably cached) to
+         * compressed file (probably uncached). */
+        r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
+        if (r < 0 && r != -ENOENT)
+                log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m");
+        else if (r == 0)
+                retrieve(data, len, "COREDUMP_FILENAME", &filename);
+
+        if (filename && access(filename, R_OK) < 0) {
+                log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+                         "File %s is not readable: %m", filename);
+                filename = mfree(filename);
+        }
+
+        if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
+                if (path) {
+                        *path = filename;
+                        filename = NULL;
+                }
+
+                return 0;
+        } else {
+                _cleanup_close_ int fdt = -1;
+                char *temp = NULL;
+
+                if (fd < 0) {
+                        temp = strdup("/var/tmp/coredump-XXXXXX");
+                        if (!temp)
+                                return log_oom();
+
+                        fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
+                        if (fdt < 0)
+                                return log_error_errno(fdt, "Failed to create temporary file: %m");
+                        log_debug("Created temporary file %s", temp);
+
+                        fd = fdt;
+                }
+
+                r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
+                if (r == 0) {
+                        ssize_t sz;
+
+                        assert(len >= 9);
+                        data += 9;
+                        len -= 9;
+
+                        sz = write(fdt, data, len);
+                        if (sz < 0) {
+                                r = log_error_errno(errno,
+                                                    "Failed to write temporary file: %m");
+                                goto error;
+                        }
+                        if (sz != (ssize_t) len) {
+                                log_error("Short write to temporary file.");
+                                r = -EIO;
+                                goto error;
+                        }
+                } else if (filename) {
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+                        _cleanup_close_ int fdf;
+
+                        fdf = open(filename, O_RDONLY | O_CLOEXEC);
+                        if (fdf < 0) {
+                                r = log_error_errno(errno,
+                                                    "Failed to open %s: %m",
+                                                    filename);
+                                goto error;
+                        }
+
+                        r = decompress_stream(filename, fdf, fd, -1);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to decompress %s: %m", filename);
+                                goto error;
+                        }
+#else
+                        log_error("Cannot decompress file. Compiled without compression support.");
+                        r = -EOPNOTSUPP;
+                        goto error;
+#endif
+                } else {
+                        if (r == -ENOENT)
+                                log_error("Cannot retrieve coredump from journal nor disk.");
+                        else
+                                log_error_errno(r, "Failed to retrieve COREDUMP field: %m");
+                        goto error;
+                }
+
+                if (temp) {
+                        *path = temp;
+                        *unlink_temp = true;
+                }
+
+                return 0;
+
+error:
+                if (temp) {
+                        unlink(temp);
+                        log_debug("Removed temporary file %s", temp);
+                }
+                return r;
+        }
+}
+
+static int dump_core(sd_journal* j) {
+        int r;
+
+        assert(j);
+
+        r = focus(j);
+        if (r < 0)
+                return r;
+
+        print_info(arg_output ? stdout : stderr, j, false);
+
+        if (on_tty() && !arg_output) {
+                log_error("Refusing to dump core to tty.");
+                return -ENOTTY;
+        }
+
+        r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Coredump retrieval failed: %m");
+
+        r = sd_journal_previous(j);
+        if (r >= 0)
+                log_warning("More than one entry matches, ignoring rest.");
+
+        return 0;
+}
+
+static int run_gdb(sd_journal *j) {
+        _cleanup_free_ char *exe = NULL, *path = NULL;
+        bool unlink_path = false;
+        const char *data;
+        siginfo_t st;
+        size_t len;
+        pid_t pid;
+        int r;
+
+        assert(j);
+
+        r = focus(j);
+        if (r < 0)
+                return r;
+
+        print_info(stdout, j, false);
+        fputs("\n", stdout);
+
+        r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m");
+
+        assert(len > strlen("COREDUMP_EXE="));
+        data += strlen("COREDUMP_EXE=");
+        len -= strlen("COREDUMP_EXE=");
+
+        exe = strndup(data, len);
+        if (!exe)
+                return log_oom();
+
+        if (endswith(exe, " (deleted)")) {
+                log_error("Binary already deleted.");
+                return -ENOENT;
+        }
+
+        if (!path_is_absolute(exe)) {
+                log_error("Binary is not an absolute path.");
+                return -ENOENT;
+        }
+
+        r = save_core(j, -1, &path, &unlink_path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve core: %m");
+
+        pid = fork();
+        if (pid < 0) {
+                r = log_error_errno(errno, "Failed to fork(): %m");
+                goto finish;
+        }
+        if (pid == 0) {
+                (void) reset_all_signal_handlers();
+                (void) reset_signal_mask();
+
+                execlp("gdb", "gdb", exe, path, NULL);
+
+                log_error_errno(errno, "Failed to invoke gdb: %m");
+                _exit(1);
+        }
+
+        r = wait_for_terminate(pid, &st);
+        if (r < 0) {
+                log_error_errno(r, "Failed to wait for gdb: %m");
+                goto finish;
+        }
+
+        r = st.si_code == CLD_EXITED ? st.si_status : 255;
+
+finish:
+        if (unlink_path) {
+                log_debug("Removed temporary file %s", path);
+                unlink(path);
+        }
+
+        return r;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(sd_journal_closep) sd_journal*j = NULL;
+        const char* match;
+        Iterator it;
+        int r = 0;
+        _cleanup_set_free_free_ Set *matches = NULL;
+
+        setlocale(LC_ALL, "");
+        log_parse_environment();
+        log_open();
+
+        matches = new_matches();
+        if (!matches) {
+                r = -ENOMEM;
+                goto end;
+        }
+
+        r = parse_argv(argc, argv, matches);
+        if (r < 0)
+                goto end;
+
+        if (arg_action == ACTION_NONE)
+                goto end;
+
+        sigbus_install();
+
+        if (arg_directory) {
+                r = sd_journal_open_directory(&j, arg_directory, 0);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
+                        goto end;
+                }
+        } else {
+                r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to open journal: %m");
+                        goto end;
+                }
+        }
+
+        /* We want full data, nothing truncated. */
+        sd_journal_set_data_threshold(j, 0);
+
+        SET_FOREACH(match, matches, it) {
+                r = sd_journal_add_match(j, match, strlen(match));
+                if (r != 0) {
+                        log_error_errno(r, "Failed to add match '%s': %m",
+                                        match);
+                        goto end;
+                }
+        }
+
+        if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
+                _cleanup_free_ char *filter;
+
+                filter = journal_make_match_string(j);
+                log_debug("Journal filter: %s", filter);
+        }
+
+        switch(arg_action) {
+
+        case ACTION_LIST:
+        case ACTION_INFO:
+                if (!arg_no_pager)
+                        pager_open(false);
+
+                r = dump_list(j);
+                break;
+
+        case ACTION_DUMP:
+                r = dump_core(j);
+                break;
+
+        case  ACTION_GDB:
+                r = run_gdb(j);
+                break;
+
+        default:
+                assert_not_reached("Shouldn't be here");
+        }
+
+end:
+        pager_close();
+
+        if (arg_output)
+                fclose(arg_output);
+
+        return r >= 0 ? r : EXIT_FAILURE;
+}
diff --git a/src/coredump/stacktrace.c b/src/coredump/stacktrace.c
new file mode 100644 (file)
index 0000000..6880699
--- /dev/null
@@ -0,0 +1,200 @@
+/***
+  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 <dwarf.h>
+#include <elfutils/libdwfl.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "formats-util.h"
+#include "macro.h"
+#include "stacktrace.h"
+#include "string-util.h"
+#include "util.h"
+
+#define FRAMES_MAX 64
+#define THREADS_MAX 64
+
+struct stack_context {
+        FILE *f;
+        Dwfl *dwfl;
+        Elf *elf;
+        unsigned n_thread;
+        unsigned n_frame;
+};
+
+static int frame_callback(Dwfl_Frame *frame, void *userdata) {
+        struct stack_context *c = userdata;
+        Dwarf_Addr pc, pc_adjusted, bias = 0;
+        _cleanup_free_ Dwarf_Die *scopes = NULL;
+        const char *fname = NULL, *symbol = NULL;
+        Dwfl_Module *module;
+        bool is_activation;
+
+        assert(frame);
+        assert(c);
+
+        if (c->n_frame >= FRAMES_MAX)
+                return DWARF_CB_ABORT;
+
+        if (!dwfl_frame_pc(frame, &pc, &is_activation))
+                return DWARF_CB_ABORT;
+
+        pc_adjusted = pc - (is_activation ? 0 : 1);
+
+        module = dwfl_addrmodule(c->dwfl, pc_adjusted);
+        if (module) {
+                Dwarf_Die *s, *cudie;
+                int n;
+
+                cudie = dwfl_module_addrdie(module, pc_adjusted, &bias);
+                if (cudie) {
+                        n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes);
+                        for (s = scopes; s < scopes + n; s++) {
+                                if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) {
+                                        Dwarf_Attribute *a, space;
+
+                                        a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space);
+                                        if (!a)
+                                                a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space);
+                                        if (a)
+                                                symbol = dwarf_formstring(a);
+                                        if (!symbol)
+                                                symbol = dwarf_diename(s);
+
+                                        if (symbol)
+                                                break;
+                                }
+                        }
+                }
+
+                if (!symbol)
+                        symbol = dwfl_module_addrname(module, pc_adjusted);
+
+                fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        }
+
+        fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname));
+        c->n_frame ++;
+
+        return DWARF_CB_OK;
+}
+
+static int thread_callback(Dwfl_Thread *thread, void *userdata) {
+        struct stack_context *c = userdata;
+        pid_t tid;
+
+        assert(thread);
+        assert(c);
+
+        if (c->n_thread >= THREADS_MAX)
+                return DWARF_CB_ABORT;
+
+        if (c->n_thread != 0)
+                fputc('\n', c->f);
+
+        c->n_frame = 0;
+
+        tid = dwfl_thread_tid(thread);
+        fprintf(c->f, "Stack trace of thread " PID_FMT ":\n", tid);
+
+        if (dwfl_thread_getframes(thread, frame_callback, c) < 0)
+                return DWARF_CB_ABORT;
+
+        c->n_thread ++;
+
+        return DWARF_CB_OK;
+}
+
+int coredump_make_stack_trace(int fd, const char *executable, char **ret) {
+
+        static const Dwfl_Callbacks callbacks = {
+                .find_elf = dwfl_build_id_find_elf,
+                .find_debuginfo = dwfl_standard_find_debuginfo,
+        };
+
+        struct stack_context c = {};
+        char *buf = NULL;
+        size_t sz = 0;
+        int r;
+
+        assert(fd >= 0);
+        assert(ret);
+
+        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+                return -errno;
+
+        c.f = open_memstream(&buf, &sz);
+        if (!c.f)
+                return -ENOMEM;
+
+        elf_version(EV_CURRENT);
+
+        c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+        if (!c.elf) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        c.dwfl = dwfl_begin(&callbacks);
+        if (!c.dwfl) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        c.f = safe_fclose(c.f);
+
+        *ret = buf;
+        buf = NULL;
+
+        r = 0;
+
+finish:
+        if (c.dwfl)
+                dwfl_end(c.dwfl);
+
+        if (c.elf)
+                elf_end(c.elf);
+
+        safe_fclose(c.f);
+
+        free(buf);
+
+        return r;
+}
diff --git a/src/coredump/stacktrace.h b/src/coredump/stacktrace.h
new file mode 100644 (file)
index 0000000..15e9c04
--- /dev/null
@@ -0,0 +1,22 @@
+#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/>.
+***/
+
+int coredump_make_stack_trace(int fd, const char *executable, char **ret);
diff --git a/src/coredump/test-coredump-vacuum.c b/src/coredump/test-coredump-vacuum.c
new file mode 100644 (file)
index 0000000..70a57f1
--- /dev/null
@@ -0,0 +1,30 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2012 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 <stdlib.h>
+
+#include "coredump-vacuum.h"
+
+int main(int argc, char *argv[]) {
+
+        if (coredump_vacuum(-1, (uint64_t) -1, 70 * 1024) < 0)
+                return EXIT_FAILURE;
+
+        return EXIT_SUCCESS;
+}
index ae53bac60094f78dbef6a3b8c5338d7c74e0bdac..8ac5ab730afe081d7fc1218ed89a5ff92694352b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 98fe52a81bbe81de5b715b8351920e2a1c031d75..2ef966257a9d3e2615c06082d306688f765c3879 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -268,7 +266,7 @@ static char* disk_description(const char *path) {
                 "ID_MODEL_FROM_DATABASE\0"
                 "ID_MODEL\0";
 
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         struct stat st;
         const char *i;
         int r;
index 6861a592fe76f28ba59c042008e67905df0c5e59..717cb9558e09a3afe44b955311d1e664b6595f73 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 413cfd03889e7566bcc02bf2504dcf3c42f108d8..7e80af78e79212a29e7d9fe20e853c5cae0b74e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8bf678c28fb793062f53f57d6a06dd295e79aa46..a54fc89de65eaaa4c26a7398585a5d8829c0a462 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -430,18 +428,16 @@ static int process_suffix(const char *suffix, const char *onlyprefix) {
         }
 
 finish:
-        if (top)
-                hashmap_free_free(top);
-        if (bottom)
-                hashmap_free_free(bottom);
-        if (drops) {
-                HASHMAP_FOREACH_KEY(h, key, drops, i){
-                        hashmap_free_free(hashmap_remove(drops, key));
-                        hashmap_remove(drops, key);
-                        free(key);
-                }
-                hashmap_free(drops);
+        hashmap_free_free(top);
+        hashmap_free_free(bottom);
+
+        HASHMAP_FOREACH_KEY(h, key, drops, i){
+                hashmap_free_free(hashmap_remove(drops, key));
+                hashmap_remove(drops, key);
+                free(key);
         }
+        hashmap_free(drops);
+
         return r < 0 ? r : n_found;
 }
 
@@ -453,9 +449,10 @@ static int process_suffixes(const char *onlyprefix) {
                 r = process_suffix(n, onlyprefix);
                 if (r < 0)
                         return r;
-                else
-                        n_found += r;
+
+                n_found += r;
         }
+
         return n_found;
 }
 
@@ -469,7 +466,9 @@ static int process_suffix_chop(const char *arg) {
 
         /* Strip prefix from the suffix */
         NULSTR_FOREACH(p, prefixes) {
-                const char *suffix = startswith(arg, p);
+                const char *suffix;
+
+                suffix = startswith(arg, p);
                 if (suffix) {
                         suffix += strspn(suffix, "/");
                         if (*suffix)
@@ -577,10 +576,9 @@ static int parse_argv(int argc, char *argv[]) {
                                 if (b < 0) {
                                         log_error("Failed to parse diff boolean.");
                                         return -EINVAL;
-                                } else if (b)
-                                        arg_diff = 1;
-                                else
-                                        arg_diff = 0;
+                                }
+
+                                arg_diff = b;
                         }
                         break;
 
@@ -595,8 +593,7 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-        int r = 0, k;
-        int n_found = 0;
+        int r, k, n_found = 0;
 
         log_parse_environment();
         log_open();
@@ -620,6 +617,7 @@ int main(int argc, char *argv[]) {
 
                 for (i = optind; i < argc; i++) {
                         path_kill_slashes(argv[i]);
+
                         k = process_suffix_chop(argv[i]);
                         if (k < 0)
                                 r = k;
@@ -636,8 +634,7 @@ int main(int argc, char *argv[]) {
         }
 
         if (r >= 0)
-                printf("%s%i overridden configuration files found.\n",
-                       n_found ? "\n" : "", n_found);
+                printf("%s%i overridden configuration files found.\n", n_found ? "\n" : "", n_found);
 
 finish:
         pager_close();
index 0a256c29be1da7abb25450677c5d35a7a59ad125..5d51589a3171d458596e36a9f58ba7a79a3afe8e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e857affbc423830b4d2d76b785d9e2d430be9e09..9f39049577f27116bb221cf097e74b3612be0f71 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 469ee7af681d30490ca4b6515b4708f91aa3e8f7..7790ab865d04eefaf73508c95bcecbd39e28532c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -502,7 +500,7 @@ static int write_root_shadow(const char *path, const struct spwd *p) {
 
         errno = 0;
         if (putspent(p, f) != 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return fflush_and_check(f);
 }
index e0436d794ce8dd896b4b712e141f310b5495bbb1..6f56066da8226352281c347295338e701c55c73c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -67,8 +65,8 @@ static bool arg_show_progress = false;
 static const char *arg_repair = "-a";
 
 static void start_target(const char *target, const char *mode) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         assert(target);
@@ -276,7 +274,7 @@ static int fsck_progress_socket(void) {
 
 int main(int argc, char *argv[]) {
         _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
-        _cleanup_device_unref_ sd_device *dev = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         const char *device, *type;
         bool root_directory;
         siginfo_t status;
index f7c8d11ace19b3a05e244de34425a8d24d80ba1f..97a48764ae7d635c6af202685917dce867423638 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -248,6 +246,7 @@ static int add_mount(
         assert(what);
         assert(where);
         assert(opts);
+        assert(post);
         assert(source);
 
         if (streq_ptr(fstype, "autofs"))
@@ -297,7 +296,7 @@ static int add_mount(
                 "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
                 source);
 
-        if (post && !noauto && !nofail && !automount)
+        if (!noauto && !nofail && !automount)
                 fprintf(f, "Before=%s\n", post);
 
         if (!automount && opts) {
@@ -337,7 +336,7 @@ static int add_mount(
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
 
-        if (!noauto && post) {
+        if (!noauto) {
                 lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
                 if (!lnk)
                         return log_oom();
@@ -368,10 +367,7 @@ static int add_mount(
                         "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
                         source);
 
-                if (post)
-                        fprintf(f,
-                                "Before=%s\n",
-                                post);
+                fprintf(f, "Before=%s\n", post);
 
                 if (opts) {
                         r = write_requires_after(f, opts);
@@ -465,8 +461,6 @@ static int parse_fstab(bool initrd) {
                                                       "x-systemd.automount\0");
                         if (initrd)
                                 post = SPECIAL_INITRD_FS_TARGET;
-                        else if (mount_in_initrd(me))
-                                post = SPECIAL_INITRD_ROOT_FS_TARGET;
                         else if (mount_is_network(me))
                                 post = SPECIAL_REMOTE_FS_TARGET;
                         else
@@ -578,7 +572,7 @@ static int add_sysroot_usr_mount(void) {
                          false,
                          false,
                          false,
-                         SPECIAL_INITRD_ROOT_FS_TARGET,
+                         SPECIAL_INITRD_FS_TARGET,
                          "/proc/cmdline");
 }
 
index 03df7365b56d2683a0cf8cef5a23b10b11929c7d..b15c76b5b8f2954879f7250aab7167e21feeb826 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -112,7 +110,7 @@ static int verify_tty(const char *name) {
 
         errno = 0;
         if (isatty(fd) <= 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
index ce8cecc5cbbfdceb7fe0eece71aff2c4a2240aee..af96adec0689b960ad9a5090c57452cb1617f847 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -515,14 +513,15 @@ static int add_boot(const char *what) {
                 return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
 
         (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
-        if (!streq(fstype, "vfat")) {
+        if (!streq_ptr(fstype, "vfat")) {
                 log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
                 return 0;
         }
 
+        errno = 0;
         r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
         if (r != 0) {
-                log_debug_errno(r, "Partition for /boot does not have a UUID, ignoring. %m");
+                log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring.");
                 return 0;
         }
 
@@ -635,16 +634,19 @@ static int enumerate_partitions(dev_t devnum) {
         if (r == 1)
                 return 0; /* no results */
         else if (r == -2) {
-                log_warning("%s: probe gave ambiguous results, ignoring", node);
+                log_warning("%s: probe gave ambiguous results, ignoring.", node);
                 return 0;
         } else if (r != 0)
                 return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);
 
         errno = 0;
         r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
-        if (r != 0)
-                return log_error_errno(errno ?: EIO,
-                                       "%s: failed to determine partition table type: %m", node);
+        if (r != 0) {
+                if (errno == 0)
+                        return 0; /* No partition table found. */
+
+                return log_error_errno(errno, "%s: failed to determine partition table type: %m", node);
+        }
 
         /* We only do this all for GPT... */
         if (!streq_ptr(pttype, "gpt")) {
index da719f2a3064e1a096b3a4b911108908f5731944..d7ee80d58f6ea40f9eb5a0288e500124adc4deb3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 2e1259ef6833f9b0561d933cc190f3470b2c95fb..21df3c44619ff0544561bfa71aa6eb9cf96255c6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bf09fb8fbb31f7635f11d3154b00262a05101cb2..c16a324232f00bc2f20f8f2ca20cc98ed303422a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -127,8 +125,8 @@ static void print_status_info(StatusInfo *i) {
 }
 
 static int show_one_name(sd_bus *bus, const char* attr) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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 *s;
         int r;
 
@@ -233,7 +231,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_simple_string(sd_bus *bus, const char *method, const char *value) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r = 0;
 
         polkit_agent_open_if_enabled();
@@ -507,7 +505,7 @@ static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
index dde2baf66172043efaad36fa45405658c5ab6fa5..c37e32e96b7bfa3e633a04d93d2b2c57efd173da 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -28,7 +26,6 @@
 #include "bus-util.h"
 #include "def.h"
 #include "env-util.h"
-#include "event-util.h"
 #include "fileio-label.h"
 #include "hostname-util.h"
 #include "parse-util.h"
@@ -213,10 +210,10 @@ try_dmi:
            unreliable enough, so let's not do any additional guesswork
            on top of that.
 
-           See the SMBIOS Specification 2.7.1 section 7.4.1 for
+           See the SMBIOS Specification 3.0 section 7.4.1 for
            details about the values listed here:
 
-           http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
+           https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
          */
 
         switch (t) {
@@ -238,7 +235,11 @@ try_dmi:
 
         case 0x11:
         case 0x1C:
+        case 0x1D:
                 return "server";
+
+        case 0x1E:
+                return "tablet";
         }
 
         return NULL;
@@ -665,7 +666,7 @@ static const sd_bus_vtable hostname_vtable[] = {
 };
 
 static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         assert(c);
@@ -696,8 +697,8 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
 
 int main(int argc, char *argv[]) {
         Context context = {};
-        _cleanup_event_unref_ sd_event *event = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         log_set_target(LOG_TARGET_AUTO);
index de59b797a6e80288c09db2b2deecf1e3c21f7ab8..1160dacdf1f97c31b9c6d4a757f6411c82508ac8 100644 (file)
@@ -571,7 +571,7 @@ static int import_file(struct trie *trie, const char *filename) {
 }
 
 static int hwdb_query(int argc, char *argv[], void *userdata) {
-        _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+        _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
         const char *key, *value;
         const char *modalias;
         int r;
index 82f519958cc83a9cacd56d7735ef21b94f537d63..44aa6e217027ad6b9dbcbe4fcc924629b61d3d24 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -69,7 +67,7 @@ int aufs_resolve(const char *path) {
         errno = 0;
         r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
         if (r == FTW_STOP)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
index 712fb81ceef92ef6b7b53ee63c4c9ca14bc7f3b2..e474a508973600c5cb0f1112b67cd4b950d53e7b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8e531a64fa99f0a615b8ce0d26b1c6b0968e6546..a04c8c49ff0b0f7954f236ed41118f4a3cf4f8dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6a2aa81c76c056ec7344c4ea670d3974b3d07d68..a758cc56407f8c1dc7f8f4171af195fd4743074d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <curl/curl.h>
+#include <sys/types.h>
 
 #include "sd-event.h"
 
index 28c87594d68dcde59873205bf4c8261cdd97fc3c..db06e11b87b4f78213098f9a7b5af6a866bad2f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b71de6cb82fca356453aa589be6c312384146eec..8e723d4908e106e3921e8d0a08c7205620a7c256 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-compress.h"
+#include "macro.h"
 
 typedef struct RawExport RawExport;
 
index 2bbec661e66be4e7ebf9aa450fc8a5af9db18e5a..d79c27f2d061d8ee8574b326ead06f62439c668b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ce27a9fc1e0401001803a0e31fdbfb315adeb5b0..1e3c8bb80c93446dfcd0a4cd3ace570c730f2c4d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-compress.h"
+#include "macro.h"
 
 typedef struct TarExport TarExport;
 
index 2b33d778d3b4d8ef36f88e68a604ef5656f234cc..cc98c33ef696c3ff22080298e289d8295a96237a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -24,7 +22,6 @@
 #include "sd-event.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "export-raw.h"
 #include "export-tar.h"
 #include "fd-util.h"
@@ -76,7 +73,7 @@ static void on_tar_finished(TarExport *export, int error, void *userdata) {
 
 static int export_tar(int argc, char *argv[], void *userdata) {
         _cleanup_(tar_export_unrefp) TarExport *export = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_(image_unrefp) Image *image = NULL;
         const char *path = NULL, *local = NULL;
         _cleanup_close_ int open_fd = -1;
@@ -155,7 +152,7 @@ static void on_raw_finished(RawExport *export, int error, void *userdata) {
 
 static int export_raw(int argc, char *argv[], void *userdata) {
         _cleanup_(raw_export_unrefp) RawExport *export = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_(image_unrefp) Image *image = NULL;
         const char *path = NULL, *local = NULL;
         _cleanup_close_ int open_fd = -1;
index a8551ca9e8630a33499398136175ab94b00ff173..18a30be36d86fee10a775ba83b425f4a78842d72 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -134,7 +132,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
                 if (unshare(CLONE_NEWNET) < 0)
                         log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
 
-                r = capability_bounding_set_drop(~retain, true);
+                r = capability_bounding_set_drop(retain, true);
                 if (r < 0)
                         log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
 
@@ -208,7 +206,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
                 if (unshare(CLONE_NEWNET) < 0)
                         log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
 
-                r = capability_bounding_set_drop(~retain, true);
+                r = capability_bounding_set_drop(retain, true);
                 if (r < 0)
                         log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
 
index 7b60de80c2962430b61e20a8ee33c5df58e75408..07d3250e7175fdfa06059c11920f681190065867 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d4ff178f60bbc68fc607999667467744b800d375..f1766bbe3b0f747c5fd4d5553db0ea6cc6f4ecfd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 50d91f732c79563973a716e43c758a36e02a7bba..6b59d0724b349f00d05b2d4ed23496258df6f221 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
-
+#include <bzlib.h>
 #include <lzma.h>
+#include <sys/types.h>
 #include <zlib.h>
-#include <bzlib.h>
 
 #include "macro.h"
 
index 7593f064fc1d81cad85f2c89780dd7a533655994..fd6b9f77030e29f7bc3b666e4044800c47d5744d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bf7c7703408f0623e7930cf186cabc00a85ff873..4f543e08834c02e8e0f47b422e7d6e4a9bf50e28 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-util.h"
+#include "macro.h"
 
 typedef struct RawImport RawImport;
 
index c7983c04bed0ed614bb2f5875698f1f0ba46f9b4..8b81324fdef3e7b1e9a8b3d93b9ce63e7c8be1a6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index aaecb51398e2c867645a382af8ee3752ea05d831..24abe06c8fd30b95c48e56e9c25f97c0ccc56625 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-util.h"
+#include "macro.h"
 
 typedef struct TarImport TarImport;
 
index 018b94d4c43a3fe09c9f744f532824ada7e181c9..4e442ee84aad7e18c897faea8ab90f209c75e750 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -24,7 +22,6 @@
 #include "sd-event.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
 #include "hostname-util.h"
@@ -58,7 +55,7 @@ static void on_tar_finished(TarImport *import, int error, void *userdata) {
 
 static int import_tar(int argc, char *argv[], void *userdata) {
         _cleanup_(tar_import_unrefp) TarImport *import = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         const char *path = NULL, *local = NULL;
         _cleanup_free_ char *ll = NULL;
         _cleanup_close_ int open_fd = -1;
@@ -153,7 +150,7 @@ static void on_raw_finished(RawImport *import, int error, void *userdata) {
 
 static int import_raw(int argc, char *argv[], void *userdata) {
         _cleanup_(raw_import_unrefp) RawImport *import = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         const char *path = NULL, *local = NULL;
         _cleanup_free_ char *ll = NULL;
         _cleanup_close_ int open_fd = -1;
index 4228681ceae3e17a2dd48e77a04b8e3dbd13cc02..d2a5867a6edefd2b22f25c70166e7e9897dbf1d1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -55,7 +53,6 @@ typedef enum TransferType {
         TRANSFER_EXPORT_RAW,
         TRANSFER_PULL_TAR,
         TRANSFER_PULL_RAW,
-        TRANSFER_PULL_DKR,
         _TRANSFER_TYPE_MAX,
         _TRANSFER_TYPE_INVALID = -1,
 } TransferType;
@@ -74,7 +71,6 @@ struct Transfer {
         bool force_local;
         bool read_only;
 
-        char *dkr_index_url;
         char *format;
 
         pid_t pid;
@@ -117,7 +113,6 @@ static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = {
         [TRANSFER_EXPORT_RAW] = "export-raw",
         [TRANSFER_PULL_TAR] = "pull-tar",
         [TRANSFER_PULL_RAW] = "pull-raw",
-        [TRANSFER_PULL_DKR] = "pull-dkr",
 };
 
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
@@ -134,7 +129,6 @@ static Transfer *transfer_unref(Transfer *t) {
 
         free(t->remote);
         free(t->local);
-        free(t->dkr_index_url);
         free(t->format);
         free(t->object_path);
 
@@ -383,12 +377,11 @@ static int transfer_start(Transfer *t) {
         if (t->pid == 0) {
                 const char *cmd[] = {
                         NULL, /* systemd-import, systemd-export or systemd-pull */
-                        NULL, /* tar, raw, dkr */
+                        NULL, /* tar, raw  */
                         NULL, /* --verify= */
                         NULL, /* verify argument */
                         NULL, /* maybe --force */
                         NULL, /* maybe --read-only */
-                        NULL, /* maybe --dkr-index-url */
                         NULL, /* if so: the actual URL */
                         NULL, /* maybe --format= */
                         NULL, /* if so: the actual format */
@@ -471,10 +464,8 @@ static int transfer_start(Transfer *t) {
 
                 if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR))
                         cmd[k++] = "tar";
-                else if (IN_SET(t->type, TRANSFER_IMPORT_RAW, TRANSFER_EXPORT_RAW, TRANSFER_PULL_RAW))
-                        cmd[k++] = "raw";
                 else
-                        cmd[k++] = "dkr";
+                        cmd[k++] = "raw";
 
                 if (t->verify != _IMPORT_VERIFY_INVALID) {
                         cmd[k++] = "--verify";
@@ -486,11 +477,6 @@ static int transfer_start(Transfer *t) {
                 if (t->read_only)
                         cmd[k++] = "--read-only";
 
-                if (t->dkr_index_url) {
-                        cmd[k++] = "--dkr-index-url";
-                        cmd[k++] = t->dkr_index_url;
-                }
-
                 if (t->format) {
                         cmd[k++] = "--format";
                         cmd[k++] = t->format;
@@ -707,7 +693,7 @@ static int manager_new(Manager **ret) {
         return 0;
 }
 
-static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_index_url, const char *remote) {
+static Transfer *manager_find(Manager *m, TransferType type, const char *remote) {
         Transfer *t;
         Iterator i;
 
@@ -718,8 +704,7 @@ static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_ind
         HASHMAP_FOREACH(t, m->transfers, i) {
 
                 if (t->type == type &&
-                    streq_ptr(t->remote, remote) &&
-                    streq_ptr(t->dkr_index_url, dkr_index_url))
+                    streq_ptr(t->remote, remote))
                         return t;
         }
 
@@ -907,7 +892,7 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
 
         type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
 
-        if (manager_find(m, type, NULL, remote))
+        if (manager_find(m, type, remote))
                 return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
 
         r = transfer_new(m, &t);
@@ -939,107 +924,8 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
         return sd_bus_reply_method_return(msg, "uo", id, object);
 }
 
-static int method_pull_dkr(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
-        _cleanup_(transfer_unrefp) Transfer *t = NULL;
-        const char *index_url, *remote, *tag, *local, *verify, *object;
-        Manager *m = userdata;
-        ImportVerify v;
-        int force, r;
-        uint32_t id;
-
-        assert(msg);
-        assert(m);
-
-        r = bus_verify_polkit_async(
-                        msg,
-                        CAP_SYS_ADMIN,
-                        "org.freedesktop.import1.pull",
-                        NULL,
-                        false,
-                        UID_INVALID,
-                        &m->polkit_registry,
-                        error);
-        if (r < 0)
-                return r;
-        if (r == 0)
-                return 1; /* Will call us back */
-
-        r = sd_bus_message_read(msg, "sssssb", &index_url, &remote, &tag, &local, &verify, &force);
-        if (r < 0)
-                return r;
-
-        if (isempty(index_url))
-                index_url = DEFAULT_DKR_INDEX_URL;
-        if (!index_url)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL must be specified.");
-        if (!http_url_is_valid(index_url))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL %s is invalid", index_url);
-
-        if (!dkr_name_is_valid(remote))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Remote name %s is not valid", remote);
-
-        if (isempty(tag))
-                tag = "latest";
-        else if (!dkr_tag_is_valid(tag))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Tag %s is not valid", tag);
-
-        if (isempty(local))
-                local = NULL;
-        else if (!machine_name_is_valid(local))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local);
-
-        if (isempty(verify))
-                v = IMPORT_VERIFY_SIGNATURE;
-        else
-                v = import_verify_from_string(verify);
-        if (v < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify);
-
-        if (v != IMPORT_VERIFY_NO)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "DKR does not support verification.");
-
-        r = setup_machine_directory((uint64_t) -1, error);
-        if (r < 0)
-                return r;
-
-        if (manager_find(m, TRANSFER_PULL_DKR, index_url, remote))
-                return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
-
-        r = transfer_new(m, &t);
-        if (r < 0)
-                return r;
-
-        t->type = TRANSFER_PULL_DKR;
-        t->verify = v;
-        t->force_local = force;
-
-        t->dkr_index_url = strdup(index_url);
-        if (!t->dkr_index_url)
-                return -ENOMEM;
-
-        t->remote = strjoin(remote, ":", tag, NULL);
-        if (!t->remote)
-                return -ENOMEM;
-
-        if (local) {
-                t->local = strdup(local);
-                if (!t->local)
-                        return -ENOMEM;
-        }
-
-        r = transfer_start(t);
-        if (r < 0)
-                return r;
-
-        object = t->object_path;
-        id = t->id;
-        t = NULL;
-
-        return sd_bus_reply_method_return(msg, "uo", id, object);
-}
-
 static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Transfer *t;
         Iterator i;
@@ -1188,7 +1074,6 @@ static const sd_bus_vtable manager_vtable[] = {
         SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("PullDkr", "sssssb", "uo", method_pull_dkr, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_SIGNAL("TransferNew", "uo", 0),
index ae36af422f7ab2ee76398ea47965728e3c423cc2..ed2539a03b6ee9dd904134f6ee683eef04e04d64 100644 (file)
                        send_interface="org.freedesktop.import1.Manager"
                        send_member="PullRaw"/>
 
-                <allow send_destination="org.freedesktop.import1"
-                       send_interface="org.freedesktop.import1.Manager"
-                       send_member="PullDkr"/>
-
                 <allow send_destination="org.freedesktop.import1"
                        send_interface="org.freedesktop.import1.Transfer"
                        send_member="Cancel"/>
index a83cffffa0103d4bd9f41ce60d5387dd219625d7..d301d4d79e60bf4434e6d2e088eb346e2605de3a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7e6db1862ca62d7c0b3cc4e98b5deaaefdded63c..929a131c88f69f3c6d5fc476bb9be9c891f9f645 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 #include <stdbool.h>
 
-#include "pull-job.h"
 #include "import-util.h"
+#include "pull-job.h"
 
 int pull_make_local_copy(const char *final, const char *root, const char *local, bool force_local);
 
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
deleted file mode 100644 (file)
index 831470f..0000000
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  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 <curl/curl.h>
-#include <sys/prctl.h>
-
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "aufs-util.h"
-#include "btrfs-util.h"
-#include "curl-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "hostname-util.h"
-#include "import-common.h"
-#include "import-util.h"
-#include "json.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "pull-common.h"
-#include "pull-dkr.h"
-#include "pull-job.h"
-#include "rm-rf.h"
-#include "string-util.h"
-#include "strv.h"
-#include "utf8.h"
-#include "web-util.h"
-
-typedef enum DkrProgress {
-        DKR_SEARCHING,
-        DKR_RESOLVING,
-        DKR_METADATA,
-        DKR_DOWNLOADING,
-        DKR_COPYING,
-} DkrProgress;
-
-struct DkrPull {
-        sd_event *event;
-        CurlGlue *glue;
-
-        char *index_protocol;
-        char *index_address;
-
-        char *index_url;
-        char *image_root;
-
-        PullJob *images_job;
-        PullJob *tags_job;
-        PullJob *ancestry_job;
-        PullJob *json_job;
-        PullJob *layer_job;
-
-        char *name;
-        char *reference;
-        char *id;
-
-        char *response_digest;
-        char *response_token;
-        char **response_registries;
-
-        char **ancestry;
-        unsigned n_ancestry;
-        unsigned current_ancestry;
-
-        DkrPullFinished on_finished;
-        void *userdata;
-
-        char *local;
-        bool force_local;
-        bool grow_machine_directory;
-
-        char *temp_path;
-        char *final_path;
-
-        pid_t tar_pid;
-};
-
-#define PROTOCOL_PREFIX "https://"
-
-#define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:"
-#define HEADER_REGISTRY "X-Do" /* the HTTP header for the registry */ "cker-Endpoints:"
-#define HEADER_DIGEST "Do" /* the HTTP header for the manifest digest */ "cker-Content-Digest:"
-#define LAYERS_MAX 127
-
-static void dkr_pull_job_on_finished(PullJob *j);
-
-DkrPull* dkr_pull_unref(DkrPull *i) {
-        if (!i)
-                return NULL;
-
-        if (i->tar_pid > 1) {
-                (void) kill_and_sigcont(i->tar_pid, SIGKILL);
-                (void) wait_for_terminate(i->tar_pid, NULL);
-        }
-
-        pull_job_unref(i->images_job);
-        pull_job_unref(i->tags_job);
-        pull_job_unref(i->ancestry_job);
-        pull_job_unref(i->json_job);
-        pull_job_unref(i->layer_job);
-
-        curl_glue_unref(i->glue);
-        sd_event_unref(i->event);
-
-        if (i->temp_path) {
-                (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
-                free(i->temp_path);
-        }
-
-        free(i->name);
-        free(i->reference);
-        free(i->id);
-        free(i->response_token);
-        strv_free(i->ancestry);
-        free(i->final_path);
-        free(i->index_address);
-        free(i->index_protocol);
-        free(i->index_url);
-        free(i->image_root);
-        free(i->local);
-        free(i);
-
-        return NULL;
-}
-
-int dkr_pull_new(
-                DkrPull **ret,
-                sd_event *event,
-                const char *index_url,
-                const char *image_root,
-                DkrPullFinished on_finished,
-                void *userdata) {
-
-        _cleanup_(dkr_pull_unrefp) DkrPull *i = NULL;
-        char *e;
-        int r;
-
-        assert(ret);
-        assert(index_url);
-
-        if (!http_url_is_valid(index_url))
-                return -EINVAL;
-
-        i = new0(DkrPull, 1);
-        if (!i)
-                return -ENOMEM;
-
-        i->on_finished = on_finished;
-        i->userdata = userdata;
-
-        i->image_root = strdup(image_root ?: "/var/lib/machines");
-        if (!i->image_root)
-                return -ENOMEM;
-
-        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
-
-        i->index_url = strdup(index_url);
-        if (!i->index_url)
-                return -ENOMEM;
-
-        e = endswith(i->index_url, "/");
-        if (e)
-                *e = 0;
-
-        if (event)
-                i->event = sd_event_ref(event);
-        else {
-                r = sd_event_default(&i->event);
-                if (r < 0)
-                        return r;
-        }
-
-        r = curl_glue_new(&i->glue, i->event);
-        if (r < 0)
-                return r;
-
-        i->glue->on_finished = pull_job_curl_on_finished;
-        i->glue->userdata = i;
-
-        *ret = i;
-        i = NULL;
-
-        return 0;
-}
-
-static void dkr_pull_report_progress(DkrPull *i, DkrProgress p) {
-        unsigned percent;
-
-        assert(i);
-
-        switch (p) {
-
-        case DKR_SEARCHING:
-                percent = 0;
-                if (i->images_job)
-                        percent += i->images_job->progress_percent * 5 / 100;
-                break;
-
-        case DKR_RESOLVING:
-                percent = 5;
-                if (i->tags_job)
-                        percent += i->tags_job->progress_percent * 5 / 100;
-                break;
-
-        case DKR_METADATA:
-                percent = 10;
-                if (i->ancestry_job)
-                        percent += i->ancestry_job->progress_percent * 5 / 100;
-                if (i->json_job)
-                        percent += i->json_job->progress_percent * 5 / 100;
-                break;
-
-        case DKR_DOWNLOADING:
-                percent = 20;
-                percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry);
-                if (i->layer_job)
-                        percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100;
-
-                break;
-
-        case DKR_COPYING:
-                percent = 95;
-                break;
-
-        default:
-                assert_not_reached("Unknown progress state");
-        }
-
-        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
-        log_debug("Combined progress %u%%", percent);
-}
-
-static int parse_id(const void *payload, size_t size, char **ret) {
-        _cleanup_free_ char *buf = NULL, *id = NULL, *other = NULL;
-        union json_value v = {};
-        void *json_state = NULL;
-        const char *p;
-        int t;
-
-        assert(payload);
-        assert(ret);
-
-        if (size <= 0)
-                return -EBADMSG;
-
-        if (memchr(payload, 0, size))
-                return -EBADMSG;
-
-        buf = strndup(payload, size);
-        if (!buf)
-                return -ENOMEM;
-
-        p = buf;
-        t = json_tokenize(&p, &id, &v, &json_state, NULL);
-        if (t < 0)
-                return t;
-        if (t != JSON_STRING)
-                return -EBADMSG;
-
-        t = json_tokenize(&p, &other, &v, &json_state, NULL);
-        if (t < 0)
-                return t;
-        if (t != JSON_END)
-                return -EBADMSG;
-
-        if (!dkr_id_is_valid(id))
-                return -EBADMSG;
-
-        *ret = id;
-        id = NULL;
-
-        return 0;
-}
-
-static int parse_ancestry(const void *payload, size_t size, char ***ret) {
-        _cleanup_free_ char *buf = NULL;
-        void *json_state = NULL;
-        const char *p;
-        enum {
-                STATE_BEGIN,
-                STATE_ITEM,
-                STATE_COMMA,
-                STATE_END,
-        } state = STATE_BEGIN;
-        _cleanup_strv_free_ char **l = NULL;
-        size_t n = 0, allocated = 0;
-
-        if (size <= 0)
-                return -EBADMSG;
-
-        if (memchr(payload, 0, size))
-                return -EBADMSG;
-
-        buf = strndup(payload, size);
-        if (!buf)
-                return -ENOMEM;
-
-        p = buf;
-        for (;;) {
-                _cleanup_free_ char *str;
-                union json_value v = {};
-                int t;
-
-                t = json_tokenize(&p, &str, &v, &json_state, NULL);
-                if (t < 0)
-                        return t;
-
-                switch (state) {
-
-                case STATE_BEGIN:
-                        if (t == JSON_ARRAY_OPEN)
-                                state = STATE_ITEM;
-                        else
-                                return -EBADMSG;
-
-                        break;
-
-                case STATE_ITEM:
-                        if (t == JSON_STRING) {
-                                if (!dkr_id_is_valid(str))
-                                        return -EBADMSG;
-
-                                if (n+1 > LAYERS_MAX)
-                                        return -EFBIG;
-
-                                if (!GREEDY_REALLOC(l, allocated, n + 2))
-                                        return -ENOMEM;
-
-                                l[n++] = str;
-                                str = NULL;
-                                l[n] = NULL;
-
-                                state = STATE_COMMA;
-
-                        } else if (t == JSON_ARRAY_CLOSE)
-                                state = STATE_END;
-                        else
-                                return -EBADMSG;
-
-                        break;
-
-                case STATE_COMMA:
-                        if (t == JSON_COMMA)
-                                state = STATE_ITEM;
-                        else if (t == JSON_ARRAY_CLOSE)
-                                state = STATE_END;
-                        else
-                                return -EBADMSG;
-                        break;
-
-                case STATE_END:
-                        if (t == JSON_END) {
-
-                                if (strv_isempty(l))
-                                        return -EBADMSG;
-
-                                if (!strv_is_uniq(l))
-                                        return -EBADMSG;
-
-                                l = strv_reverse(l);
-
-                                *ret = l;
-                                l = NULL;
-                                return 0;
-                        } else
-                                return -EBADMSG;
-                }
-
-        }
-}
-
-static const char *dkr_pull_current_layer(DkrPull *i) {
-        assert(i);
-
-        if (strv_isempty(i->ancestry))
-                return NULL;
-
-        return i->ancestry[i->current_ancestry];
-}
-
-static const char *dkr_pull_current_base_layer(DkrPull *i) {
-        assert(i);
-
-        if (strv_isempty(i->ancestry))
-                return NULL;
-
-        if (i->current_ancestry <= 0)
-                return NULL;
-
-        return i->ancestry[i->current_ancestry-1];
-}
-
-static int dkr_pull_add_token(DkrPull *i, PullJob *j) {
-        const char *t;
-
-        assert(i);
-        assert(j);
-
-        if (i->response_token)
-                t = strjoina("Authorization: Token ", i->response_token);
-        else
-                t = HEADER_TOKEN " true";
-
-        j->request_header = curl_slist_new("Accept: application/json", t, NULL);
-        if (!j->request_header)
-                return -ENOMEM;
-
-        return 0;
-}
-
-static int dkr_pull_add_bearer_token(DkrPull *i, PullJob *j) {
-        const char *t = NULL;
-
-        assert(i);
-        assert(j);
-
-        if (i->response_token)
-                t = strjoina("Authorization: Bearer ", i->response_token);
-        else
-                return -EINVAL;
-
-        j->request_header = curl_slist_new("Accept: application/json", t, NULL);
-        if (!j->request_header)
-                return -ENOMEM;
-
-        return 0;
-}
-
-static bool dkr_pull_is_done(DkrPull *i) {
-        assert(i);
-        assert(i->images_job);
-        if (i->images_job->state != PULL_JOB_DONE)
-                return false;
-
-        if (!i->tags_job || i->tags_job->state != PULL_JOB_DONE)
-                return false;
-
-        if (!i->ancestry_job || i->ancestry_job->state != PULL_JOB_DONE)
-                return false;
-
-        if (i->json_job && i->json_job->state != PULL_JOB_DONE)
-                return false;
-
-        if (i->layer_job && i->layer_job->state != PULL_JOB_DONE)
-                return false;
-
-        if (dkr_pull_current_layer(i))
-                return false;
-
-        return true;
-}
-
-static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) {
-        int r;
-        _cleanup_free_ char *p = NULL;
-
-        assert(i);
-
-        if (!i->local)
-                return 0;
-
-        if (!i->final_path) {
-                i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL);
-                if (!i->final_path)
-                        return -ENOMEM;
-        }
-
-        if (version == DKR_PULL_V2) {
-                p = dirname_malloc(i->image_root);
-                if (!p)
-                        return -ENOMEM;
-        }
-
-        r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local);
-        if (r < 0)
-                return r;
-
-        if (version == DKR_PULL_V2) {
-                char **k;
-
-                STRV_FOREACH(k, i->ancestry) {
-                        _cleanup_free_ char *d;
-
-                        d = strjoin(i->image_root, "/.dkr-", *k, NULL);
-                        if (!d)
-                                return -ENOMEM;
-
-                        r = btrfs_subvol_remove(d, BTRFS_REMOVE_QUOTA);
-                        if (r < 0)
-                               return r;
-                }
-
-                r = rmdir(i->image_root);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-static int dkr_pull_job_on_open_disk(PullJob *j) {
-        const char *base;
-        DkrPull *i;
-        int r;
-
-        assert(j);
-        assert(j->userdata);
-
-        i = j->userdata;
-        assert(i->layer_job == j);
-        assert(i->final_path);
-        assert(!i->temp_path);
-        assert(i->tar_pid <= 0);
-
-        r = tempfn_random(i->final_path, NULL, &i->temp_path);
-        if (r < 0)
-                return log_oom();
-
-        mkdir_parents_label(i->temp_path, 0700);
-
-        base = dkr_pull_current_base_layer(i);
-        if (base) {
-                const char *base_path;
-
-                base_path = strjoina(i->image_root, "/.dkr-", base);
-                r = btrfs_subvol_snapshot(base_path, i->temp_path, BTRFS_SNAPSHOT_FALLBACK_COPY|BTRFS_SNAPSHOT_QUOTA);
-        } else
-                r = btrfs_subvol_make(i->temp_path);
-        if (r < 0)
-                return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path);
-
-        (void) import_assign_pool_quota_and_warn(i->temp_path);
-
-        j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
-        if (j->disk_fd < 0)
-                return j->disk_fd;
-
-        return 0;
-}
-
-static void dkr_pull_job_on_progress(PullJob *j) {
-        DkrPull *i;
-
-        assert(j);
-        assert(j->userdata);
-
-        i = j->userdata;
-
-        dkr_pull_report_progress(
-                        i,
-                        j == i->images_job                       ? DKR_SEARCHING :
-                        j == i->tags_job                         ? DKR_RESOLVING :
-                        j == i->ancestry_job || j == i->json_job ? DKR_METADATA :
-                                                                   DKR_DOWNLOADING);
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j);
-
-static int dkr_pull_pull_layer_v2(DkrPull *i) {
-        _cleanup_free_ char *path = NULL;
-        const char *url, *layer = NULL;
-        int r;
-
-        assert(i);
-        assert(!i->layer_job);
-        assert(!i->temp_path);
-        assert(!i->final_path);
-
-        for (;;) {
-                layer = dkr_pull_current_layer(i);
-                if (!layer)
-                        return 0; /* no more layers */
-
-                path = strjoin(i->image_root, "/.dkr-", layer, NULL);
-                if (!path)
-                        return log_oom();
-
-                if (laccess(path, F_OK) < 0) {
-                        if (errno == ENOENT)
-                                break;
-
-                        return log_error_errno(errno, "Failed to check for container: %m");
-                }
-
-                log_info("Layer %s already exists, skipping.", layer);
-
-                i->current_ancestry++;
-
-                path = mfree(path);
-        }
-
-        log_info("Pulling layer %s...", layer);
-
-        i->final_path = path;
-        path = NULL;
-
-        url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/blobs/", layer);
-        r = pull_job_new(&i->layer_job, url, i->glue, i);
-        if (r < 0)
-                return log_error_errno(r, "Failed to allocate layer job: %m");
-
-        r = dkr_pull_add_bearer_token(i, i->layer_job);
-        if (r < 0)
-                return log_oom();
-
-        i->layer_job->on_finished = dkr_pull_job_on_finished_v2;
-        i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
-        i->layer_job->on_progress = dkr_pull_job_on_progress;
-        i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
-        r = pull_job_begin(i->layer_job);
-        if (r < 0)
-                return log_error_errno(r, "Failed to start layer job: %m");
-
-        return 0;
-}
-
-static int dkr_pull_pull_layer(DkrPull *i) {
-        _cleanup_free_ char *path = NULL;
-        const char *url, *layer = NULL;
-        int r;
-
-        assert(i);
-        assert(!i->layer_job);
-        assert(!i->temp_path);
-        assert(!i->final_path);
-
-        for (;;) {
-                layer = dkr_pull_current_layer(i);
-                if (!layer)
-                        return 0; /* no more layers */
-
-                path = strjoin(i->image_root, "/.dkr-", layer, NULL);
-                if (!path)
-                        return log_oom();
-
-                if (laccess(path, F_OK) < 0) {
-                        if (errno == ENOENT)
-                                break;
-
-                        return log_error_errno(errno, "Failed to check for container: %m");
-                }
-
-                log_info("Layer %s already exists, skipping.", layer);
-
-                i->current_ancestry++;
-
-                path = mfree(path);
-        }
-
-        log_info("Pulling layer %s...", layer);
-
-        i->final_path = path;
-        path = NULL;
-
-        url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", layer, "/layer");
-        r = pull_job_new(&i->layer_job, url, i->glue, i);
-        if (r < 0)
-                return log_error_errno(r, "Failed to allocate layer job: %m");
-
-        r = dkr_pull_add_token(i, i->layer_job);
-        if (r < 0)
-                return log_oom();
-
-        i->layer_job->on_finished = dkr_pull_job_on_finished;
-        i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
-        i->layer_job->on_progress = dkr_pull_job_on_progress;
-        i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
-        r = pull_job_begin(i->layer_job);
-        if (r < 0)
-                return log_error_errno(r, "Failed to start layer job: %m");
-
-        return 0;
-}
-
-static int dkr_pull_job_on_header(PullJob *j, const char *header, size_t sz)  {
-        _cleanup_free_ char *registry = NULL;
-        char *token, *digest;
-        DkrPull *i;
-        int r;
-
-        assert(j);
-        assert(j->userdata);
-
-        i = j->userdata;
-        r = curl_header_strdup(header, sz, HEADER_TOKEN, &token);
-        if (r < 0)
-                return log_oom();
-        if (r > 0) {
-                free(i->response_token);
-                i->response_token = token;
-                return 0;
-        }
-
-        r = curl_header_strdup(header, sz, HEADER_DIGEST, &digest);
-        if (r < 0)
-                return log_oom();
-        if (r > 0) {
-                free(i->response_digest);
-                i->response_digest = digest;
-                return 0;
-        }
-
-        r = curl_header_strdup(header, sz, HEADER_REGISTRY, &registry);
-        if (r < 0)
-                return log_oom();
-        if (r > 0) {
-                char **l, **k;
-
-                l = strv_split(registry, ",");
-                if (!l)
-                        return log_oom();
-
-                STRV_FOREACH(k, l) {
-                        if (!hostname_is_valid(*k, false)) {
-                                log_error("Registry hostname is not valid.");
-                                strv_free(l);
-                                return -EBADMSG;
-                        }
-                }
-
-                strv_free(i->response_registries);
-                i->response_registries = l;
-        }
-
-        return 0;
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j) {
-        DkrPull *i;
-        int r;
-
-        assert(j);
-        assert(j->userdata);
-
-        i = j->userdata;
-        if (j->error != 0) {
-                if (j == i->images_job)
-                        log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
-                else if (j == i->ancestry_job)
-                        log_error_errno(j->error, "Failed to retrieve manifest.");
-                else if (j == i->json_job)
-                        log_error_errno(j->error, "Failed to retrieve json data.");
-                else
-                        log_error_errno(j->error, "Failed to retrieve layer data.");
-
-                r = j->error;
-                goto finish;
-        }
-
-        if (i->images_job == j) {
-                const char *url;
-
-                assert(!i->tags_job);
-                assert(!i->ancestry_job);
-                assert(!i->json_job);
-                assert(!i->layer_job);
-
-                if (strv_isempty(i->response_registries)) {
-                        r = -EBADMSG;
-                        log_error("Didn't get registry information.");
-                        goto finish;
-                }
-
-                log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
-                dkr_pull_report_progress(i, DKR_RESOLVING);
-
-                url = strjoina(i->index_protocol, "auth.", i->index_address, "/v2/token/?scope=repository:",
-                               i->name, ":pull&service=registry.", i->index_address);
-                r = pull_job_new(&i->tags_job, url, i->glue, i);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate tags job: %m");
-                        goto finish;
-                }
-
-                i->tags_job->on_finished = dkr_pull_job_on_finished_v2;
-                i->tags_job->on_progress = dkr_pull_job_on_progress;
-
-                r = pull_job_begin(i->tags_job);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to start tags job: %m");
-                        goto finish;
-                }
-
-        } else if (i->tags_job == j) {
-                const char *url;
-                _cleanup_free_ char *buf;
-                _cleanup_json_variant_unref_ JsonVariant *doc = NULL;
-                JsonVariant *e = NULL;
-
-                assert(!i->ancestry_job);
-                assert(!i->json_job);
-                assert(!i->layer_job);
-
-                buf = strndup((const char *)j->payload, j->payload_size);
-                if (!buf) {
-                        r = -ENOMEM;
-                        log_oom();
-                        goto finish;
-                }
-
-                r = json_parse(buf, &doc);
-                if (r < 0) {
-                        log_error("Unable to parse bearer token\n%s", j->payload);
-                        goto finish;
-                }
-
-                e = json_variant_value(doc, "token");
-                if (!e || e->type != JSON_VARIANT_STRING) {
-                        r = -EBADMSG;
-                        log_error("Invalid JSON format for Bearer token");
-                        goto finish;
-                }
-
-                r = free_and_strdup(&i->response_token, json_variant_string(e));
-                if (r < 0) {
-                        log_oom();
-                        goto finish;
-                }
-
-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/manifests/", i->reference);
-                r = pull_job_new(&i->ancestry_job, url, i->glue, i);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate ancestry job: %m");
-                        goto finish;
-                }
-
-                r = dkr_pull_add_bearer_token(i, i->ancestry_job);
-                if (r < 0)
-                        goto finish;
-
-                i->ancestry_job->on_finished = dkr_pull_job_on_finished_v2;
-                i->ancestry_job->on_progress = dkr_pull_job_on_progress;
-                i->ancestry_job->on_header = dkr_pull_job_on_header;
-
-
-                r = pull_job_begin(i->ancestry_job);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to start ancestry job: %m");
-                        goto finish;
-                }
-
-        } else if (i->ancestry_job == j) {
-
-                _cleanup_json_variant_unref_ JsonVariant *doc = NULL, *compat = NULL;
-                JsonVariant *e = NULL;
-                _cleanup_strv_free_ char **ancestry = NULL;
-                size_t allocated = 0, size = 0;
-                char *path = NULL, **k = NULL;
-
-                r = json_parse((const char *)j->payload, &doc);
-                if (r < 0) {
-                        log_error("Invalid JSON Manifest");
-                        goto finish;
-                }
-
-                e = json_variant_value(doc, "fsLayers");
-                if (!e || e->type != JSON_VARIANT_ARRAY || e->size == 0) {
-                        r = -EBADMSG;
-                        goto finish;
-                }
-
-                log_info("JSON manifest with schema v%"PRIi64" for %s parsed!",
-                                json_variant_integer(json_variant_value(doc, "schemaVersion")),
-                                json_variant_string(json_variant_value(doc, "name")));
-
-                for (unsigned z = 0; z < e->size; z++) {
-                        JsonVariant *f = json_variant_element(e, z), *g = NULL;
-                        const char *layer;
-                        if (f->type != JSON_VARIANT_OBJECT) {
-                                r = -EBADMSG;
-                                goto finish;
-                        }
-
-                        g = json_variant_value(f, "blobSum");
-
-                        layer = json_variant_string(g);
-                        if (!dkr_digest_is_valid(layer)) {
-                                r = -EBADMSG;
-                                goto finish;
-                        }
-
-                        if (!GREEDY_REALLOC(ancestry, allocated, size + 2)) {
-                                r = -ENOMEM;
-                                log_oom();
-                                goto finish;
-                        }
-
-                        ancestry[size] = strdup(layer);
-                        if (!ancestry[size]) {
-                                r = -ENOMEM;
-                                log_oom();
-                                goto finish;
-                        }
-
-                        ancestry[size+1] = NULL;
-                        size += 1;
-                }
-
-                e = json_variant_value(doc, "history");
-                if (!e || e->type != JSON_VARIANT_ARRAY) {
-                        r = -EBADMSG;
-                        goto finish;
-                }
-
-                e = json_variant_element(e, 0);
-                e = json_variant_value(e, "v1Compatibility");
-                r = json_parse(json_variant_string(e), &compat);
-                if (r < 0) {
-                        log_error("Invalid v1Compatibility JSON");
-                        goto finish;
-                }
-
-                e = json_variant_value(compat, "id");
-
-                strv_free(i->ancestry);
-                i->ancestry = strv_reverse(strv_uniq(ancestry));
-                i->n_ancestry = strv_length(i->ancestry);
-                i->current_ancestry = 0;
-                i->id = strdup(i->ancestry[i->n_ancestry - 1]);
-                if (!i->id) {
-                        r = -ENOMEM;
-                        log_oom();
-                        goto finish;
-                }
-                path = strjoin(i->image_root, "/.dkr-", json_variant_string(e), NULL);
-                if (!path) {
-                        r = -ENOMEM;
-                        log_oom();
-                        goto finish;
-                }
-                free(i->image_root);
-                i->image_root = path;
-                ancestry = NULL;
-
-                log_info("Required layers:\n");
-                STRV_FOREACH(k, i->ancestry)
-                        log_info("\t%s", *k);
-                log_info("\nProvenance:\n\tImageID: %s\n\tDigest:  %s", json_variant_string(e), i->response_digest);
-
-                dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
-                r = dkr_pull_pull_layer_v2(i);
-                if (r < 0)
-                        goto finish;
-
-        } else if (i->layer_job == j) {
-                assert(i->temp_path);
-                assert(i->final_path);
-
-                j->disk_fd = safe_close(j->disk_fd);
-
-                if (i->tar_pid > 0) {
-                        r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
-                        i->tar_pid = 0;
-                        if (r < 0)
-                                goto finish;
-                }
-
-                r = aufs_resolve(i->temp_path);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
-                        goto finish;
-                }
-
-                r = btrfs_subvol_set_read_only(i->temp_path, true);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to mark snapshot read-only: %m");
-                        goto finish;
-                }
-
-                if (rename(i->temp_path, i->final_path) < 0) {
-                        log_error_errno(errno, "Failed to rename snaphsot: %m");
-                        goto finish;
-                }
-
-                log_info("Completed writing to layer %s.", i->final_path);
-
-                i->layer_job = pull_job_unref(i->layer_job);
-                free(i->temp_path);
-                i->temp_path = NULL;
-                free(i->final_path);
-                i->final_path = NULL;
-
-                i->current_ancestry ++;
-                r = dkr_pull_pull_layer_v2(i);
-                if (r < 0)
-                        goto finish;
-
-        } else if (i->json_job != j)
-                assert_not_reached("Got finished event for unknown curl object");
-
-        if (!dkr_pull_is_done(i))
-                return;
-
-        dkr_pull_report_progress(i, DKR_COPYING);
-
-        r = dkr_pull_make_local_copy(i, DKR_PULL_V2);
-        if (r < 0)
-                goto finish;
-
-        r = 0;
-
-finish:
-        if (i->on_finished)
-                i->on_finished(i, r, i->userdata);
-        else
-                sd_event_exit(i->event, r);
-
-}
-
-static void dkr_pull_job_on_finished(PullJob *j) {
-        DkrPull *i;
-        int r;
-
-        assert(j);
-        assert(j->userdata);
-
-        i = j->userdata;
-        if (j->error != 0) {
-                if (j == i->images_job)
-                        log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
-                else if (j == i->tags_job)
-                        log_error_errno(j->error, "Failed to retrieve tags list.");
-                else if (j == i->ancestry_job)
-                        log_error_errno(j->error, "Failed to retrieve ancestry list.");
-                else if (j == i->json_job)
-                        log_error_errno(j->error, "Failed to retrieve json data.");
-                else
-                        log_error_errno(j->error, "Failed to retrieve layer data.");
-
-                r = j->error;
-                goto finish;
-        }
-
-        if (i->images_job == j) {
-                const char *url;
-
-                assert(!i->tags_job);
-                assert(!i->ancestry_job);
-                assert(!i->json_job);
-                assert(!i->layer_job);
-
-                if (strv_isempty(i->response_registries)) {
-                        r = -EBADMSG;
-                        log_error("Didn't get registry information.");
-                        goto finish;
-                }
-
-                log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
-                dkr_pull_report_progress(i, DKR_RESOLVING);
-
-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->reference);
-                r = pull_job_new(&i->tags_job, url, i->glue, i);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate tags job: %m");
-                        goto finish;
-                }
-
-                r = dkr_pull_add_token(i, i->tags_job);
-                if (r < 0) {
-                        log_oom();
-                        goto finish;
-                }
-
-                i->tags_job->on_finished = dkr_pull_job_on_finished;
-                i->tags_job->on_progress = dkr_pull_job_on_progress;
-
-                r = pull_job_begin(i->tags_job);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to start tags job: %m");
-                        goto finish;
-                }
-
-        } else if (i->tags_job == j) {
-                const char *url;
-                char *id = NULL;
-
-                assert(!i->ancestry_job);
-                assert(!i->json_job);
-                assert(!i->layer_job);
-
-                r = parse_id(j->payload, j->payload_size, &id);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to parse JSON id.");
-                        goto finish;
-                }
-
-                free(i->id);
-                i->id = id;
-
-                log_info("Tag lookup succeeded, resolved to layer %s.", i->id);
-                dkr_pull_report_progress(i, DKR_METADATA);
-
-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry");
-                r = pull_job_new(&i->ancestry_job, url, i->glue, i);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate ancestry job: %m");
-                        goto finish;
-                }
-
-                r = dkr_pull_add_token(i, i->ancestry_job);
-                if (r < 0) {
-                        log_oom();
-                        goto finish;
-                }
-
-                i->ancestry_job->on_finished = dkr_pull_job_on_finished;
-                i->ancestry_job->on_progress = dkr_pull_job_on_progress;
-
-                url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json");
-                r = pull_job_new(&i->json_job, url, i->glue, i);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate json job: %m");
-                        goto finish;
-                }
-
-                r = dkr_pull_add_token(i, i->json_job);
-                if (r < 0) {
-                        log_oom();
-                        goto finish;
-                }
-
-                i->json_job->on_finished = dkr_pull_job_on_finished;
-                i->json_job->on_progress = dkr_pull_job_on_progress;
-
-                r = pull_job_begin(i->ancestry_job);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to start ancestry job: %m");
-                        goto finish;
-                }
-
-                r = pull_job_begin(i->json_job);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to start json job: %m");
-                        goto finish;
-                }
-
-        } else if (i->ancestry_job == j) {
-                char **ancestry = NULL, **k;
-                unsigned n;
-
-                assert(!i->layer_job);
-
-                r = parse_ancestry(j->payload, j->payload_size, &ancestry);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to parse JSON id.");
-                        goto finish;
-                }
-
-                n = strv_length(ancestry);
-                if (n <= 0 || !streq(ancestry[n-1], i->id)) {
-                        log_error("Ancestry doesn't end in main layer.");
-                        strv_free(ancestry);
-                        r = -EBADMSG;
-                        goto finish;
-                }
-
-                log_info("Ancestor lookup succeeded, requires layers:\n");
-                STRV_FOREACH(k, ancestry)
-                        log_info("\t%s", *k);
-
-                strv_free(i->ancestry);
-                i->ancestry = ancestry;
-                i->n_ancestry = n;
-                i->current_ancestry = 0;
-
-                dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
-                r = dkr_pull_pull_layer(i);
-                if (r < 0)
-                        goto finish;
-
-        } else if (i->layer_job == j) {
-                assert(i->temp_path);
-                assert(i->final_path);
-
-                j->disk_fd = safe_close(j->disk_fd);
-
-                if (i->tar_pid > 0) {
-                        r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
-                        i->tar_pid = 0;
-                        if (r < 0)
-                                goto finish;
-                }
-
-                r = aufs_resolve(i->temp_path);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
-                        goto finish;
-                }
-
-                r = btrfs_subvol_set_read_only(i->temp_path, true);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to mark snapshot read-only: %m");
-                        goto finish;
-                }
-
-                if (rename(i->temp_path, i->final_path) < 0) {
-                        log_error_errno(errno, "Failed to rename snaphsot: %m");
-                        goto finish;
-                }
-
-                log_info("Completed writing to layer %s.", i->final_path);
-
-                i->layer_job = pull_job_unref(i->layer_job);
-                i->temp_path = mfree(i->temp_path);
-                i->final_path = mfree(i->final_path);
-
-                i->current_ancestry ++;
-                r = dkr_pull_pull_layer(i);
-                if (r < 0)
-                        goto finish;
-
-        } else if (i->json_job != j)
-                assert_not_reached("Got finished event for unknown curl object");
-
-        if (!dkr_pull_is_done(i))
-                return;
-
-        dkr_pull_report_progress(i, DKR_COPYING);
-
-        r = dkr_pull_make_local_copy(i, DKR_PULL_V1);
-        if (r < 0)
-                goto finish;
-
-        r = 0;
-finish:
-        if (i->on_finished)
-                i->on_finished(i, r, i->userdata);
-        else
-                sd_event_exit(i->event, r);
-}
-
-static int get_protocol_address(char **protocol, char **address, const char *url) {
-        const char *sep, *dot;
-        _cleanup_free_ char *a = NULL, *p = NULL;
-
-        sep = strstr(url, "://");
-        if (!sep)
-                return -EINVAL;
-
-        dot = strrchr(url, '.');
-        if (!dot)
-                return -EINVAL;
-        dot--;
-
-        p = strndup(url, (sep - url) + 3);
-        if (!p)
-                return log_oom();
-
-        while (dot > (sep + 3) && *dot != '.')
-                dot--;
-
-        a = strdup(dot + 1);
-        if (!a)
-                return log_oom();
-
-        *address = a;
-        *protocol = p;
-        a = p = NULL;
-
-        return 0;
-}
-
-int dkr_pull_start(DkrPull *i, const char *name, const char *reference, const char *local, bool force_local, DkrPullVersion version) {
-        const char *url;
-        int r;
-
-        assert(i);
-
-        if (!dkr_name_is_valid(name))
-                return -EINVAL;
-
-        if (reference && !dkr_ref_is_valid(reference))
-                return -EINVAL;
-
-        if (local && !machine_name_is_valid(local))
-                return -EINVAL;
-
-        if (i->images_job)
-                return -EBUSY;
-
-        if (!reference)
-                reference = "latest";
-
-        free(i->index_protocol);
-        free(i->index_address);
-        r = get_protocol_address(&i->index_protocol, &i->index_address, i->index_url);
-        if (r < 0)
-                return r;
-
-        r = free_and_strdup(&i->local, local);
-        if (r < 0)
-                return r;
-        i->force_local = force_local;
-
-        r = free_and_strdup(&i->name, name);
-        if (r < 0)
-                return r;
-        r = free_and_strdup(&i->reference, reference);
-        if (r < 0)
-                return r;
-
-        url = strjoina(i->index_url, "/v1/repositories/", name, "/images");
-
-        r = pull_job_new(&i->images_job, url, i->glue, i);
-        if (r < 0)
-                return r;
-
-        r = dkr_pull_add_token(i, i->images_job);
-        if (r < 0)
-                return r;
-
-        if (version == DKR_PULL_V1)
-                i->images_job->on_finished = dkr_pull_job_on_finished;
-        else
-                i->images_job->on_finished = dkr_pull_job_on_finished_v2;
-
-        i->images_job->on_header = dkr_pull_job_on_header;
-        i->images_job->on_progress = dkr_pull_job_on_progress;
-
-        return pull_job_begin(i->images_job);
-}
diff --git a/src/import/pull-dkr.h b/src/import/pull-dkr.h
deleted file mode 100644 (file)
index 33d18cb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  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/>.
-***/
-
-#pragma once
-
-#include "sd-event.h"
-#include "util.h"
-
-typedef enum { DKR_PULL_V1, DKR_PULL_V2 } DkrPullVersion;
-typedef struct DkrPull DkrPull;
-
-typedef void (*DkrPullFinished)(DkrPull *pull, int error, void *userdata);
-
-int dkr_pull_new(DkrPull **pull, sd_event *event, const char *index_url, const char *image_root, DkrPullFinished on_finished, void *userdata);
-DkrPull* dkr_pull_unref(DkrPull *pull);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DkrPull*, dkr_pull_unref);
-
-int dkr_pull_start(DkrPull *pull, const char *name, const char *tag, const char *local, bool force_local, DkrPullVersion version);
index 824fa246ec5486bab7c6e2129e11d7b5b93d4c64..6bcf35ef4e2562d90abb329cc813d2638faffc86 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1777bf1c337c25bda9607d71f399b256a8122079..998857035a5e26b3ca479bc22e090cf76c8a9f84 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,9 +21,9 @@
 
 #include <gcrypt.h>
 
-#include "macro.h"
 #include "curl-util.h"
 #include "import-compress.h"
+#include "macro.h"
 
 typedef struct PullJob PullJob;
 
index 03bfb5175699c1af36c26d16fc69496b5a1f6bb9..8a16602c3e896b45f9ed1d85896a3c22f28ced63 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b03b4f5c92de9e61298b0b141b4f8657da2dd8bd..8f6d16eb3a5adebcb91df81abe2cb756bba1e7d3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-util.h"
+#include "macro.h"
 
 typedef struct RawPull RawPull;
 
index 2e48167c5442d1c0808b5dd029784c4d23907495..afb13366f03e0c12ccad3fdc07e44587d30c915b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 420845ae508e7f8f4e61b7b2d53ac18b09a9bd7d..7e63e496d8554d36693e7ebdb5d177647ec0a22c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "macro.h"
+
 #include "import-util.h"
+#include "macro.h"
 
 typedef struct TarPull TarPull;
 
index 39f5b2d8e4415c93e7b8668730a1721ba84d205a..72604a6a7449db5c982a80674e93649dd317a6bb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "sd-event.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "hostname-util.h"
 #include "import-util.h"
 #include "machine-image.h"
 #include "parse-util.h"
-#include "pull-dkr.h"
 #include "pull-raw.h"
 #include "pull-tar.h"
 #include "signal-util.h"
@@ -40,7 +36,6 @@
 static bool arg_force = false;
 static const char *arg_image_root = "/var/lib/machines";
 static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
 static bool arg_settings = true;
 
 static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
@@ -61,7 +56,7 @@ static void on_tar_finished(TarPull *pull, int error, void *userdata) {
 
 static int pull_tar(int argc, char *argv[], void *userdata) {
         _cleanup_(tar_pull_unrefp) TarPull *pull = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         const char *url, *local;
         _cleanup_free_ char *l = NULL, *ll = NULL;
         int r;
@@ -147,7 +142,7 @@ static void on_raw_finished(RawPull *pull, int error, void *userdata) {
 
 static int pull_raw(int argc, char *argv[], void *userdata) {
         _cleanup_(raw_pull_unrefp) RawPull *pull = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         const char *url, *local;
         _cleanup_free_ char *l = NULL, *ll = NULL;
         int r;
@@ -221,114 +216,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
         return -r;
 }
 
-static void on_dkr_finished(DkrPull *pull, int error, void *userdata) {
-        sd_event *event = userdata;
-        assert(pull);
-
-        if (error == 0)
-                log_info("Operation completed successfully.");
-
-        sd_event_exit(event, abs(error));
-}
-
-static int pull_dkr(int argc, char *argv[], void *userdata) {
-        _cleanup_(dkr_pull_unrefp) DkrPull *pull = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
-        const char *name, *reference, *local, *digest;
-        int r;
-
-        if (!arg_dkr_index_url) {
-                log_error("Please specify an index URL with --dkr-index-url=");
-                return -EINVAL;
-        }
-
-        if (arg_verify != IMPORT_VERIFY_NO) {
-                log_error("Pulls from dkr do not support image verification, please pass --verify=no.");
-                return -EINVAL;
-        }
-
-        digest = strchr(argv[1], '@');
-        if (digest) {
-                reference = digest + 1;
-                name = strndupa(argv[1], digest - argv[1]);
-        } else {
-                reference = strchr(argv[1], ':');
-                if (reference) {
-                        name = strndupa(argv[1], reference - argv[1]);
-                        reference++;
-                } else {
-                        name = argv[1];
-                        reference = "latest";
-                }
-        }
-
-        if (!dkr_name_is_valid(name)) {
-                log_error("Remote name '%s' is not valid.", name);
-                return -EINVAL;
-        }
-
-        if (!dkr_ref_is_valid(reference)) {
-                log_error("Tag name '%s' is not valid.", reference);
-                return -EINVAL;
-        }
-
-        if (argc >= 3)
-                local = argv[2];
-        else {
-                local = strchr(name, '/');
-                if (local)
-                        local++;
-                else
-                        local = name;
-        }
-
-        if (isempty(local) || streq(local, "-"))
-                local = NULL;
-
-        if (local) {
-                if (!machine_name_is_valid(local)) {
-                        log_error("Local image name '%s' is not valid.", local);
-                        return -EINVAL;
-                }
-
-                if (!arg_force) {
-                        r = image_find(local, NULL);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
-                        else if (r > 0) {
-                                log_error_errno(EEXIST, "Image '%s' already exists.", local);
-                                return -EEXIST;
-                        }
-                }
-
-                log_info("Pulling '%s' with reference '%s', saving as '%s'.", name, reference, local);
-        } else
-                log_info("Pulling '%s' with reference '%s'.", name, reference);
-
-        r = sd_event_default(&event);
-        if (r < 0)
-                return log_error_errno(r, "Failed to allocate event loop: %m");
-
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
-        (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
-        (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
-
-        r = dkr_pull_new(&pull, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event);
-        if (r < 0)
-                return log_error_errno(r, "Failed to allocate puller: %m");
-
-        r = dkr_pull_start(pull, name, reference, local, arg_force, DKR_PULL_V2);
-        if (r < 0)
-                return log_error_errno(r, "Failed to pull image: %m");
-
-        r = sd_event_loop(event);
-        if (r < 0)
-                return log_error_errno(r, "Failed to run event loop: %m");
-
-        log_info("Exiting.");
-        return -r;
-}
-
 static int help(int argc, char *argv[], void *userdata) {
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
@@ -339,12 +226,10 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --verify=MODE            Verify downloaded image, one of: 'no',\n"
                "                              'checksum', 'signature'\n"
                "     --settings=BOOL          Download settings file with image\n"
-               "     --image-root=PATH        Image root directory\n"
-               "     --dkr-index-url=URL      Specify index URL to use for downloads\n\n"
+               "     --image-root=PATH        Image root directory\n\n"
                "Commands:\n"
                "  tar URL [NAME]              Download a TAR image\n"
-               "  raw URL [NAME]              Download a RAW image\n"
-               "  dkr REMOTE [NAME]           Download a DKR image\n",
+               "  raw URL [NAME]              Download a RAW image\n",
                program_invocation_short_name);
 
         return 0;
@@ -355,7 +240,6 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_FORCE,
-                ARG_DKR_INDEX_URL,
                 ARG_IMAGE_ROOT,
                 ARG_VERIFY,
                 ARG_SETTINGS,
@@ -365,7 +249,6 @@ static int parse_argv(int argc, char *argv[]) {
                 { "help",            no_argument,       NULL, 'h'                 },
                 { "version",         no_argument,       NULL, ARG_VERSION         },
                 { "force",           no_argument,       NULL, ARG_FORCE           },
-                { "dkr-index-url",   required_argument, NULL, ARG_DKR_INDEX_URL   },
                 { "image-root",      required_argument, NULL, ARG_IMAGE_ROOT      },
                 { "verify",          required_argument, NULL, ARG_VERIFY          },
                 { "settings",        required_argument, NULL, ARG_SETTINGS        },
@@ -391,15 +274,6 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_force = true;
                         break;
 
-                case ARG_DKR_INDEX_URL:
-                        if (!http_url_is_valid(optarg)) {
-                                log_error("Index URL is not valid: %s", optarg);
-                                return -EINVAL;
-                        }
-
-                        arg_dkr_index_url = optarg;
-                        break;
-
                 case ARG_IMAGE_ROOT:
                         arg_image_root = optarg;
                         break;
@@ -437,7 +311,6 @@ static int pull_main(int argc, char *argv[]) {
                 { "help", VERB_ANY, VERB_ANY, 0, help     },
                 { "tar",  2,        3,        0, pull_tar },
                 { "raw",  2,        3,        0, pull_raw },
-                { "dkr",  2,        3,        0, pull_dkr },
                 {}
         };
 
index 47dabaa86efaee93e0028a08ac4bba6aaf505d95..ee2121cc36b7768ecc77cd30f6b9269c0888a70c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index be7fd1d0c9a8bda2007e476a20221d6d2fb3ae68..6dddac8cdf84a44e9734a9e26a17a976b45f84cc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4b600796194b74dda29032f6725ff196f8f8e3f5..b820253d715a3f3183b2aa9bfe1bf9984bdec903 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index a35f2b541cc0603eb435128df96e3a20c2ac5070..3e57afb9971c02e124270e0678adf033aff8db7e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -101,7 +99,7 @@ static const char *translate_runlevel(int runlevel, bool *isolate) {
 
 static void change_runlevel(Server *s, int runlevel) {
         const char *target;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *mode;
         bool isolate = false;
         int r;
index 6b93a758f65b3deb77630f710235b1285ad9d743..60d897758be8bcefd085327de9e3cef2afdb47a9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -45,6 +43,8 @@
 #include "sigbus.h"
 #include "util.h"
 
+#define JOURNAL_WAIT_TIMEOUT (10*USEC_PER_SEC)
+
 static char *arg_key_pem = NULL;
 static char *arg_cert_pem = NULL;
 static char *arg_trust_pem = NULL;
@@ -181,11 +181,13 @@ static ssize_t request_reader_entries(
                 } else if (r == 0) {
 
                         if (m->follow) {
-                                r = sd_journal_wait(m->journal, (uint64_t) -1);
+                                r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT);
                                 if (r < 0) {
                                         log_error_errno(r, "Couldn't wait for journal event: %m");
                                         return MHD_CONTENT_READER_END_WITH_ERROR;
                                 }
+                                if (r == SD_JOURNAL_NOP)
+                                        break;
 
                                 continue;
                         }
@@ -241,6 +243,8 @@ static ssize_t request_reader_entries(
         }
 
         n = m->size - pos;
+        if (n < 1)
+                return 0;
         if (n > max)
                 n = max;
 
@@ -694,7 +698,7 @@ static int request_handler_file(
         if (fstat(fd, &st) < 0)
                 return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n");
 
-        response = MHD_create_response_from_fd_at_offset(st.st_size, fd, 0);
+        response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
         if (!response)
                 return respond_oom(connection);
 
@@ -709,7 +713,7 @@ static int request_handler_file(
 }
 
 static int get_virtualization(char **v) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         char *b = NULL;
         int r;
 
@@ -834,7 +838,7 @@ static int request_handler(
         assert(method);
 
         if (!streq(method, "GET"))
-                return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+                return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE,
                                    "Unsupported method.\n");
 
 
index 3ff40228a0d3f6a395d5084099dea958349f3671..3864647eb7020e37e2581c955fd91b78d1b401b2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 14bfadc1328ec578d7f10e3d3cadaa386c7e2e0b..0b8b6af736a9999937140290961fbcad0cacd6a8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,6 +20,7 @@
 #pragma once
 
 #include "sd-event.h"
+
 #include "journal-remote-write.h"
 
 typedef enum {
index d8250378b09508be738d83c00b2a5e4318cfedd3..5fab74e5ccda1594fcf98eb8f2988efaa0a1ebcc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7f47f8b014b076b6fcb56c196cd079e76a15190b..6b645a353c492cd89c16c0ee47d9a74b648a8d5f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b2f5fbf6b4caddaad2e0182893807ff563bf4594..3ce6fe27b3354a3362a7172ff99a4d5f80d477ad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -150,7 +148,7 @@ static int spawn_curl(const char* url) {
         return r;
 }
 
-static int spawn_getter(const char *getter, const char *url) {
+static int spawn_getter(const char *getter) {
         int r;
         _cleanup_strv_free_ char **words = NULL;
 
@@ -159,10 +157,6 @@ static int spawn_getter(const char *getter, const char *url) {
         if (r < 0)
                 return log_error_errno(r, "Failed to split getter option: %m");
 
-        r = strv_extend(&words, url);
-        if (r < 0)
-                return log_error_errno(r, "Failed to create command line: %m");
-
         r = spawn_child(words[0], words);
         if (r < 0)
                 log_error_errno(r, "Failed to spawn getter %s: %m", getter);
@@ -447,7 +441,7 @@ static int add_raw_socket(RemoteServer *s, int fd) {
 static int setup_raw_socket(RemoteServer *s, const char *address) {
         int fd;
 
-        fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
+        fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC);
         if (fd < 0)
                 return fd;
 
@@ -587,7 +581,7 @@ static int request_handler(
                                            *connection_cls);
 
         if (!streq(method, "POST"))
-                return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+                return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE,
                                    "Unsupported method.\n");
 
         if (!streq(url, "/upload"))
@@ -621,7 +615,7 @@ static int request_handler(
                 if (r < 0)
                         return code;
         } else {
-                r = getnameinfo_pretty(fd, &hostname);
+                r = getpeername_pretty(fd, false, &hostname);
                 if (r < 0)
                         return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
                                            "Cannot check remote hostname");
@@ -649,7 +643,7 @@ static int setup_microhttpd_server(RemoteServer *s,
                 { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
                 { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
                 { MHD_OPTION_LISTEN_SOCKET, fd},
-                { MHD_OPTION_CONNECTION_MEMORY_LIMIT, DATA_SIZE_MAX},
+                { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024},
                 { MHD_OPTION_END},
                 { MHD_OPTION_END},
                 { MHD_OPTION_END},
@@ -765,7 +759,7 @@ static int setup_microhttpd_socket(RemoteServer *s,
                                    const char *trust) {
         int fd;
 
-        fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
+        fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC);
         if (fd < 0)
                 return fd;
 
@@ -879,7 +873,7 @@ static int remoteserver_init(RemoteServer *s,
                 } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
                         char *hostname;
 
-                        r = getnameinfo_pretty(fd, &hostname);
+                        r = getpeername_pretty(fd, false, &hostname);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to retrieve remote name: %m");
 
@@ -897,18 +891,32 @@ static int remoteserver_init(RemoteServer *s,
                                                fd);
         }
 
-        if (arg_url) {
-                const char *url, *hostname;
+        if (arg_getter) {
+                log_info("Spawning getter %s...", arg_getter);
+                fd = spawn_getter(arg_getter);
+                if (fd < 0)
+                        return fd;
 
-                url = strjoina(arg_url, "/entries");
+                r = add_source(s, fd, (char*) arg_output, false);
+                if (r < 0)
+                        return r;
+        }
 
-                if (arg_getter) {
-                        log_info("Spawning getter %s...", url);
-                        fd = spawn_getter(arg_getter, url);
-                } else {
-                        log_info("Spawning curl %s...", url);
-                        fd = spawn_curl(url);
+        if (arg_url) {
+                const char *url;
+                char *hostname, *p;
+
+                if (!strstr(arg_url, "/entries")) {
+                        if (endswith(arg_url, "/"))
+                                url = strjoina(arg_url, "entries");
+                        else
+                                url = strjoina(arg_url, "/entries");
                 }
+                else
+                        url = strdupa(arg_url);
+
+                log_info("Spawning curl %s...", url);
+                fd = spawn_curl(url);
                 if (fd < 0)
                         return fd;
 
@@ -917,7 +925,13 @@ static int remoteserver_init(RemoteServer *s,
                         startswith(arg_url, "http://") ?:
                         arg_url;
 
-                r = add_source(s, fd, (char*) hostname, false);
+                hostname = strdupa(hostname);
+                if ((p = strchr(hostname, '/')))
+                        *p = '\0';
+                if ((p = strchr(hostname, ':')))
+                        *p = '\0';
+
+                r = add_source(s, fd, hostname, false);
                 if (r < 0)
                         return r;
         }
@@ -1181,6 +1195,7 @@ static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
 
 static int parse_config(void) {
         const ConfigTableItem items[] = {
+                { "Remote",  "Seal",                   config_parse_bool,             0, &arg_seal       },
                 { "Remote",  "SplitMode",              config_parse_write_split_mode, 0, &arg_split_mode },
                 { "Remote",  "ServerKeyFile",          config_parse_path,             0, &arg_key        },
                 { "Remote",  "ServerCertificateFile",  config_parse_path,             0, &arg_cert       },
index 3e32f34def6f661768005273b78033304234e0a2..7122d633625d81f7d7bf70eb14bbfc47eb5e107c 100644 (file)
@@ -1,4 +1,5 @@
 [Remote]
+# Seal=false
 # SplitMode=host
 # ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem
 # ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem
index 6c2ccb9735cb6cdf31ffd085457302fab49efb11..6466a1c101fcf3d1cac86242ea8e8f493a8eeb27 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 
 #include "sd-event.h"
-#include "hashmap.h"
-#include "microhttpd-util.h"
 
+#include "hashmap.h"
 #include "journal-remote-parse.h"
 #include "journal-remote-write.h"
+#include "microhttpd-util.h"
 
 typedef struct MHDDaemonWrapper MHDDaemonWrapper;
 
index a6d7c3b7e8c8d9fffbf49c4c1935f31e18b6d35d..fc8f63c9e3b79a61c89b2c4d2398d8659645812c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -312,6 +310,9 @@ void close_journal_input(Uploader *u) {
 static int process_journal_input(Uploader *u, int skip) {
         int r;
 
+        if (u->uploading)
+                return 0;
+
         r = sd_journal_next_skip(u->journal, skip);
         if (r < 0)
                 return log_error_errno(r, "Failed to skip to next entry: %m");
@@ -349,10 +350,8 @@ static int dispatch_journal_input(sd_event_source *event,
 
         assert(u);
 
-        if (u->uploading) {
-                log_warning("dispatch_journal_input called when uploading, ignoring.");
+        if (u->uploading)
                 return 0;
-        }
 
         log_debug("Detected journal input, checking for new data.");
         return check_journal_input(u);
index 6302266ccbf5c3faaa57043fc96e1e802c8e6971..440563e7d3a56e151543d4ffedd38a37e42cc970 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3b46fa8cbf0d34e52ddfb6353c33686fc7a01fd5..b8cd04d5275f6e5b42572445a97ae157e8b18e47 100644 (file)
@@ -2,8 +2,8 @@
 
 #include <inttypes.h>
 
-#include "sd-journal.h"
 #include "sd-event.h"
+#include "sd-journal.h"
 
 typedef enum {
         ENTRY_CURSOR = 0,           /* Nothing actually written yet. */
index 09e6da0031d66c5f66af27c16edf212494875f02..c65c43186f8a6cfb40b4493aa802bcddb57505e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b2feb9180a6578b5644f38bbfdda402438759e2c..70c4d29c0f93f1631d2cf9572d16026fcb83d18c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #pragma once
 
-#include <stdarg.h>
 #include <microhttpd.h>
+#include <stdarg.h>
 
 #include "macro.h"
 
+/* Compatiblity with libmicrohttpd < 0.9.38 */
+#ifndef MHD_HTTP_NOT_ACCEPTABLE
+#define MHD_HTTP_NOT_ACCEPTABLE MHD_HTTP_METHOD_NOT_ACCEPTABLE
+#endif
+
+#if MHD_VERSION < 0x00094203
+#define MHD_create_response_from_fd_at_offset64 MHD_create_response_from_fd_at_offset
+#endif
+
 void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0);
 
 /* respond_oom() must be usable with return, hence this form. */
index 086bf7e7e3ecd52852e7e8ab3fd82ea19557be22..71e8790ca82004b873eec9f0cad4b59629f0e27d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index fa5284e0274f85bfebdb931cd3aabf8bd6661b6d..1dd2163707ae3f47c85dba7c5042ff5d474b5337 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7fd4198df88b16efb46a0f24e59c8ba7a89fd599..08c844d44f37786b2bada1165d3716c361661ef9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -34,7 +32,7 @@
 #include "syslog-util.h"
 #include "util.h"
 
-static char *arg_identifier = NULL;
+static const char *arg_identifier = NULL;
 static int arg_priority = LOG_INFO;
 static bool arg_level_prefix = true;
 
@@ -82,14 +80,10 @@ static int parse_argv(int argc, char *argv[]) {
                         return version();
 
                 case 't':
-                        free(arg_identifier);
                         if (isempty(optarg))
                                 arg_identifier = NULL;
-                        else {
-                                arg_identifier = strdup(optarg);
-                                if (!arg_identifier)
-                                        return log_oom();
-                        }
+                        else
+                                arg_identifier = optarg;
                         break;
 
                 case 'p':
index fcaa54aa0c9b2e8235535a52f9793aad64dfdd5b..164a3a15f2189e168759b1a02c9c0ab7c49e9489 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -94,25 +92,87 @@ const struct hash_ops catalog_hash_ops = {
         .compare = catalog_compare_func
 };
 
+static bool next_header(const char **s) {
+        const char *e;
+
+        e = strchr(*s, '\n');
+
+        /* Unexpected end */
+        if (!e)
+                return false;
+
+        /* End of headers */
+        if (e == *s)
+                return false;
+
+        *s = e + 1;
+        return true;
+}
+
+static const char *skip_header(const char *s) {
+        while (next_header(&s))
+                ;
+        return s;
+}
+
+static char *combine_entries(const char *one, const char *two) {
+        const char *b1, *b2;
+        size_t l1, l2, n;
+        char *dest, *p;
+
+        /* Find split point of headers to body */
+        b1 = skip_header(one);
+        b2 = skip_header(two);
+
+        l1 = strlen(one);
+        l2 = strlen(two);
+        dest = new(char, l1 + l2 + 1);
+        if (!dest) {
+                log_oom();
+                return NULL;
+        }
+
+        p = dest;
+
+        /* Headers from @one */
+        n = b1 - one;
+        p = mempcpy(p, one, n);
+
+        /* Headers from @two, these will only be found if not present above */
+        n = b2 - two;
+        p = mempcpy(p, two, n);
+
+        /* Body from @one */
+        n = l1 - (b1 - one);
+        if (n > 0) {
+                memcpy(p, b1, n);
+                p += n;
+
+        /* Body from @two */
+        } else {
+                n = l2 - (b2 - two);
+                memcpy(p, b2, n);
+                p += n;
+        }
+
+        assert(p - dest <= (ptrdiff_t)(l1 + l2));
+        p[0] = '\0';
+        return dest;
+}
+
 static int finish_item(
                 Hashmap *h,
-                struct strbuf *sb,
                 sd_id128_t id,
                 const char *language,
-                const char *payload) {
+                char *payload) {
 
-        ssize_t offset;
         _cleanup_free_ CatalogItem *i = NULL;
+        _cleanup_free_ char *combined = NULL, *prev = NULL;
         int r;
 
         assert(h);
-        assert(sb);
         assert(payload);
 
-        offset = strbuf_add_string(sb, payload, strlen(payload));
-        if (offset < 0)
-                return log_oom();
-
         i = new0(CatalogItem, 1);
         if (!i)
                 return log_oom();
@@ -122,17 +182,27 @@ static int finish_item(
                 assert(strlen(language) > 1 && strlen(language) < 32);
                 strcpy(i->language, language);
         }
-        i->offset = htole64((uint64_t) offset);
 
-        r = hashmap_put(h, i, i);
-        if (r == -EEXIST) {
-                log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.",
-                            SD_ID128_FORMAT_VAL(id), language ? language : "C");
-                return 0;
-        } else if (r < 0)
-                return r;
+        prev = hashmap_get(h, i);
+
+        /* Already have such an item, combine them */
+        if (prev) {
+                combined = combine_entries(payload, prev);
+                if (!combined)
+                        return log_oom();
+                r = hashmap_update(h, i, combined);
+                if (r < 0)
+                        return r;
+                combined = NULL;
+
+        /* A new item */
+        } else {
+                r = hashmap_put(h, i, payload);
+                if (r < 0)
+                        return r;
+                i = NULL;
+        }
 
-        i = NULL;
         return 0;
 }
 
@@ -189,7 +259,7 @@ static int catalog_entry_lang(const char* filename, int line,
         return 0;
 }
 
-int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
+int catalog_import_file(Hashmap *h, const char *path) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *payload = NULL;
         unsigned n = 0;
@@ -199,7 +269,6 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
         int r;
 
         assert(h);
-        assert(sb);
         assert(path);
 
         f = fopen(path, "re");
@@ -254,10 +323,11 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
                         if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
 
                                 if (got_id) {
-                                        r = finish_item(h, sb, id, lang ?: deflang, payload);
+                                        r = finish_item(h, id, lang ?: deflang, payload);
                                         if (r < 0)
                                                 return r;
 
+                                        payload = NULL;
                                         lang = mfree(lang);
                                 }
 
@@ -310,9 +380,10 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
         }
 
         if (got_id) {
-                r = finish_item(h, sb, id, lang ?: deflang, payload);
+                r = finish_item(h, id, lang ?: deflang, payload);
                 if (r < 0)
                         return r;
+                payload = NULL;
         }
 
         return 0;
@@ -389,8 +460,10 @@ int catalog_update(const char* database, const char* root, const char* const* di
         _cleanup_strv_free_ char **files = NULL;
         char **f;
         struct strbuf *sb = NULL;
-        _cleanup_hashmap_free_free_ Hashmap *h = NULL;
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
         _cleanup_free_ CatalogItem *items = NULL;
+        ssize_t offset;
+        char *payload;
         CatalogItem *i;
         Iterator j;
         unsigned n;
@@ -413,7 +486,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
 
         STRV_FOREACH(f, files) {
                 log_debug("Reading file '%s'", *f);
-                r = catalog_import_file(h, sb, *f);
+                r = catalog_import_file(h, *f);
                 if (r < 0) {
                         log_error_errno(r, "Failed to import file '%s': %m", *f);
                         goto finish;
@@ -426,8 +499,6 @@ int catalog_update(const char* database, const char* root, const char* const* di
         } else
                 log_debug("Found %u items in catalog.", hashmap_size(h));
 
-        strbuf_complete(sb);
-
         items = new(CatalogItem, hashmap_size(h));
         if (!items) {
                 r = log_oom();
@@ -435,16 +506,25 @@ int catalog_update(const char* database, const char* root, const char* const* di
         }
 
         n = 0;
-        HASHMAP_FOREACH(i, h, j) {
+        HASHMAP_FOREACH_KEY(payload, i, h, j) {
                 log_debug("Found " SD_ID128_FORMAT_STR ", language %s",
                           SD_ID128_FORMAT_VAL(i->id),
                           isempty(i->language) ? "C" : i->language);
+
+                offset = strbuf_add_string(sb, payload, strlen(payload));
+                if (offset < 0) {
+                        r = log_oom();
+                        goto finish;
+                }
+                i->offset = htole64((uint64_t) offset);
                 items[n++] = *i;
         }
 
         assert(n == hashmap_size(h));
         qsort_safe(items, n, sizeof(CatalogItem), catalog_compare_func);
 
+        strbuf_complete(sb);
+
         sz = write_catalog(database, sb, items, n);
         if (sz < 0)
                 r = log_error_errno(sz, "Failed to write %s: %m", database);
@@ -587,7 +667,7 @@ finish:
 static char *find_header(const char *s, const char *header) {
 
         for (;;) {
-                const char *v, *e;
+                const char *v;
 
                 v = startswith(s, header);
                 if (v) {
@@ -595,16 +675,8 @@ static char *find_header(const char *s, const char *header) {
                         return strndup(v, strcspn(v, NEWLINE));
                 }
 
-                /* End of text */
-                e = strchr(s, '\n');
-                if (!e)
+                if (!next_header(&s))
                         return NULL;
-
-                /* End of header */
-                if (e == s)
-                        return NULL;
-
-                s = e + 1;
         }
 }
 
index a72ecf6de7d04a630d8805976989041b5585bbbf..1b1014b335c2368e39debce44c37c498ce7a434c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <stdbool.h>
 
 #include "sd-id128.h"
+
 #include "hashmap.h"
 #include "strbuf.h"
 
-int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path);
+int catalog_import_file(Hashmap *h, const char *path);
 int catalog_update(const char* database, const char* root, const char* const* dirs);
 int catalog_get(const char* database, sd_id128_t id, char **data);
 int catalog_list(FILE *f, const char* database, bool oneline);
index e1ca0a8818edd6cbc6394e2ac1e8735b58f366cb..1933b87b009dce16578d4094e036f9df77ab25b7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -58,7 +56,8 @@ static const char* const object_compressed_table[_OBJECT_COMPRESSED_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(object_compressed, int);
 
-int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_size) {
+int compress_blob_xz(const void *src, uint64_t src_size,
+                     void *dst, size_t dst_alloc_size, size_t *dst_size) {
 #ifdef HAVE_XZ
         static const lzma_options_lzma opt = {
                 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT,
@@ -74,6 +73,7 @@ int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_
         assert(src);
         assert(src_size > 0);
         assert(dst);
+        assert(dst_alloc_size > 0);
         assert(dst_size);
 
         /* Returns < 0 if we couldn't compress the data or the
@@ -83,7 +83,7 @@ int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_
                 return -ENOBUFS;
 
         ret = lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL,
-                                        src, src_size, dst, &out_pos, src_size - 1);
+                                        src, src_size, dst, &out_pos, dst_alloc_size);
         if (ret != LZMA_OK)
                 return -ENOBUFS;
 
@@ -94,13 +94,15 @@ int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_
 #endif
 }
 
-int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst_size) {
+int compress_blob_lz4(const void *src, uint64_t src_size,
+                      void *dst, size_t dst_alloc_size, size_t *dst_size) {
 #ifdef HAVE_LZ4
         int r;
 
         assert(src);
         assert(src_size > 0);
         assert(dst);
+        assert(dst_alloc_size > 0);
         assert(dst_size);
 
         /* Returns < 0 if we couldn't compress the data or the
@@ -109,7 +111,7 @@ int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst
         if (src_size < 9)
                 return -ENOBUFS;
 
-        r = LZ4_compress_limitedOutput(src, dst + 8, src_size, src_size - 8 - 1);
+        r = LZ4_compress_limitedOutput(src, dst + 8, src_size, (int) dst_alloc_size - 8);
         if (r <= 0)
                 return -ENOBUFS;
 
@@ -201,7 +203,7 @@ int decompress_blob_lz4(const void *src, uint64_t src_size,
                 return -EBADMSG;
 
         size = le64toh( *(le64_t*)src );
-        if (size < 0 || (le64_t) size != *(le64_t*)src)
+        if (size < 0 || (unsigned) size != le64toh(*(le64_t*)src))
                 return -EFBIG;
         if ((size_t) size > *dst_alloc_size) {
                 out = realloc(*dst, size);
@@ -306,6 +308,7 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
          * prefix */
 
         int r;
+        size_t size;
 
         assert(src);
         assert(src_size > 0);
@@ -322,10 +325,18 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
 
         r = LZ4_decompress_safe_partial(src + 8, *buffer, src_size - 8,
                                         prefix_len + 1, *buffer_size);
+        if (r >= 0)
+                size = (unsigned) r;
+        else {
+                /* lz4 always tries to decode full "sequence", so in
+                 * pathological cases might need to decompress the
+                 * full field. */
+                r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0);
+                if (r < 0)
+                        return r;
+        }
 
-        if (r < 0)
-                return -EBADMSG;
-        if ((unsigned) r >= prefix_len + 1)
+        if (size >= prefix_len + 1)
                 return memcmp(*buffer, prefix, prefix_len) == 0 &&
                         ((const uint8_t*) *buffer)[prefix_len] == extra;
         else
@@ -438,7 +449,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
         _cleanup_(LZ4F_freeCompressionContextp) LZ4F_compressionContext_t ctx = NULL;
         _cleanup_free_ char *buf = NULL;
         char *src = NULL;
-        size_t size, n, total_in = 0, total_out = 0, offset = 0, frame_size;
+        size_t size, n, total_in = 0, total_out, offset = 0, frame_size;
         struct stat st;
         int r;
         static const LZ4F_compressOptions_t options = {
@@ -461,7 +472,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
         if (!buf)
                 return -ENOMEM;
 
-        n = offset = LZ4F_compressBegin(ctx, buf, size, &preferences);
+        n = offset = total_out = LZ4F_compressBegin(ctx, buf, size, &preferences);
         if (LZ4F_isError(n))
                 return -EINVAL;
 
@@ -599,80 +610,8 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
 #endif
 }
 
+int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
 #ifdef HAVE_LZ4
-static int decompress_stream_lz4_v1(int fdf, int fdt, uint64_t max_bytes) {
-
-        _cleanup_free_ char *buf = NULL, *out = NULL;
-        size_t buf_size = 0;
-        LZ4_streamDecode_t lz4_data = {};
-        le32_t header;
-        size_t total_in = sizeof(header), total_out = 0;
-
-        assert(fdf >= 0);
-        assert(fdt >= 0);
-
-        out = malloc(4*LZ4_BUFSIZE);
-        if (!out)
-                return -ENOMEM;
-
-        for (;;) {
-                ssize_t m;
-                int r;
-
-                r = loop_read_exact(fdf, &header, sizeof(header), false);
-                if (r < 0)
-                        return r;
-
-                m = le32toh(header);
-                if (m == 0)
-                        break;
-
-                /* We refuse to use a bigger decompression buffer than
-                 * the one used for compression by 4 times. This means
-                 * that compression buffer size can be enlarged 4
-                 * times. This can be changed, but old binaries might
-                 * not accept buffers compressed by newer binaries then.
-                 */
-                if (m > LZ4_COMPRESSBOUND(LZ4_BUFSIZE * 4)) {
-                        log_debug("Compressed stream block too big: %zd bytes", m);
-                        return -ENOBUFS;
-                }
-
-                total_in += sizeof(header) + m;
-
-                if (!GREEDY_REALLOC(buf, buf_size, m))
-                        return -ENOMEM;
-
-                r = loop_read_exact(fdf, buf, m, false);
-                if (r < 0)
-                        return r;
-
-                r = LZ4_decompress_safe_continue(&lz4_data, buf, out, m, 4*LZ4_BUFSIZE);
-                if (r <= 0) {
-                        log_debug("LZ4 decompression failed (legacy format).");
-                        return -EBADMSG;
-                }
-
-                total_out += r;
-
-                if (max_bytes != (uint64_t) -1 && (uint64_t) total_out > max_bytes) {
-                        log_debug("Decompressed stream longer than %" PRIu64 " bytes", max_bytes);
-                        return -EFBIG;
-                }
-
-                r = loop_write(fdt, out, r, false);
-                if (r < 0)
-                        return r;
-        }
-
-        log_debug("LZ4 decompression finished (legacy format, %zu -> %zu bytes, %.1f%%)",
-                  total_in, total_out,
-                  (double) total_out / total_in * 100);
-
-        return 0;
-}
-
-static int decompress_stream_lz4_v2(int in, int out, uint64_t max_bytes) {
         size_t c;
         _cleanup_(LZ4F_freeDecompressionContextp) LZ4F_decompressionContext_t ctx = NULL;
         _cleanup_free_ char *buf = NULL;
@@ -726,17 +665,6 @@ static int decompress_stream_lz4_v2(int in, int out, uint64_t max_bytes) {
  cleanup:
         munmap(src, st.st_size);
         return r;
-}
-#endif
-
-int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
-#ifdef HAVE_LZ4
-        int r;
-
-        r = decompress_stream_lz4_v2(fdf, fdt, max_bytes);
-        if (r == -EBADMSG)
-                r = decompress_stream_lz4_v1(fdf, fdt, max_bytes);
-        return r;
 #else
         log_debug("Cannot decompress file. Compiled without LZ4 support.");
         return -EPROTONOSUPPORT;
index 9a065eb763baca54721e9950bb72260518d72a30..c138099d9a84dee4f15f1777a925e2266054fab1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 const char* object_compressed_to_string(int compression);
 int object_compressed_from_string(const char *compression);
 
-int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
-int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
+int compress_blob_xz(const void *src, uint64_t src_size,
+                     void *dst, size_t dst_alloc_size, size_t *dst_size);
+int compress_blob_lz4(const void *src, uint64_t src_size,
+                      void *dst, size_t dst_alloc_size, size_t *dst_size);
 
-static inline int compress_blob(const void *src, uint64_t src_size, void *dst, size_t *dst_size) {
+static inline int compress_blob(const void *src, uint64_t src_size,
+                                void *dst, size_t dst_alloc_size, size_t *dst_size) {
         int r;
 #ifdef HAVE_LZ4
-        r = compress_blob_lz4(src, src_size, dst, dst_size);
+        r = compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size);
         if (r == 0)
                 return OBJECT_COMPRESSED_LZ4;
 #else
-        r = compress_blob_xz(src, src_size, dst, dst_size);
+        r = compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size);
         if (r == 0)
                 return OBJECT_COMPRESSED_XZ;
 #endif
diff --git a/src/journal/coredump-vacuum.c b/src/journal/coredump-vacuum.c
deleted file mode 100644 (file)
index 09ab60c..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  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 <sys/statvfs.h>
-
-#include "alloc-util.h"
-#include "coredump-vacuum.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "hashmap.h"
-#include "macro.h"
-#include "string-util.h"
-#include "time-util.h"
-#include "user-util.h"
-#include "util.h"
-
-#define DEFAULT_MAX_USE_LOWER (uint64_t) (1ULL*1024ULL*1024ULL)           /* 1 MiB */
-#define DEFAULT_MAX_USE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL)   /* 4 GiB */
-#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
-#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL)                    /* 1 MB */
-
-struct vacuum_candidate {
-        unsigned n_files;
-        char *oldest_file;
-        usec_t oldest_mtime;
-};
-
-static void vacuum_candidate_free(struct vacuum_candidate *c) {
-        if (!c)
-                return;
-
-        free(c->oldest_file);
-        free(c);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free);
-
-static void vacuum_candidate_hasmap_free(Hashmap *h) {
-        struct vacuum_candidate *c;
-
-        while ((c = hashmap_steal_first(h)))
-                vacuum_candidate_free(c);
-
-        hashmap_free(h);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hasmap_free);
-
-static int uid_from_file_name(const char *filename, uid_t *uid) {
-        const char *p, *e, *u;
-
-        p = startswith(filename, "core.");
-        if (!p)
-                return -EINVAL;
-
-        /* Skip the comm field */
-        p = strchr(p, '.');
-        if (!p)
-                return -EINVAL;
-        p++;
-
-        /* Find end up UID */
-        e = strchr(p, '.');
-        if (!e)
-                return -EINVAL;
-
-        u = strndupa(p, e-p);
-        return parse_uid(u, uid);
-}
-
-static bool vacuum_necessary(int fd, uint64_t sum, uint64_t keep_free, uint64_t max_use) {
-        uint64_t fs_size = 0, fs_free = (uint64_t) -1;
-        struct statvfs sv;
-
-        assert(fd >= 0);
-
-        if (fstatvfs(fd, &sv) >= 0) {
-                fs_size = sv.f_frsize * sv.f_blocks;
-                fs_free = sv.f_frsize * sv.f_bfree;
-        }
-
-        if (max_use == (uint64_t) -1) {
-
-                if (fs_size > 0) {
-                        max_use = PAGE_ALIGN(fs_size / 10); /* 10% */
-
-                        if (max_use > DEFAULT_MAX_USE_UPPER)
-                                max_use = DEFAULT_MAX_USE_UPPER;
-
-                        if (max_use < DEFAULT_MAX_USE_LOWER)
-                                max_use = DEFAULT_MAX_USE_LOWER;
-                } else
-                        max_use = DEFAULT_MAX_USE_LOWER;
-        } else
-                max_use = PAGE_ALIGN(max_use);
-
-        if (max_use > 0 && sum > max_use)
-                return true;
-
-        if (keep_free == (uint64_t) -1) {
-
-                if (fs_size > 0) {
-                        keep_free = PAGE_ALIGN((fs_size * 3) / 20); /* 15% */
-
-                        if (keep_free > DEFAULT_KEEP_FREE_UPPER)
-                                keep_free = DEFAULT_KEEP_FREE_UPPER;
-                } else
-                        keep_free = DEFAULT_KEEP_FREE;
-        } else
-                keep_free = PAGE_ALIGN(keep_free);
-
-        if (keep_free > 0 && fs_free < keep_free)
-                return true;
-
-        return false;
-}
-
-int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
-        _cleanup_closedir_ DIR *d = NULL;
-        struct stat exclude_st;
-        int r;
-
-        if (keep_free == 0 && max_use == 0)
-                return 0;
-
-        if (exclude_fd >= 0) {
-                if (fstat(exclude_fd, &exclude_st) < 0)
-                        return log_error_errno(errno, "Failed to fstat(): %m");
-        }
-
-        /* This algorithm will keep deleting the oldest file of the
-         * user with the most coredumps until we are back in the size
-         * limits. Note that vacuuming for journal files is different,
-         * because we rely on rate-limiting of the messages there,
-         * to avoid being flooded. */
-
-        d = opendir("/var/lib/systemd/coredump");
-        if (!d) {
-                if (errno == ENOENT)
-                        return 0;
-
-                return log_error_errno(errno, "Can't open coredump directory: %m");
-        }
-
-        for (;;) {
-                _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL;
-                struct vacuum_candidate *worst = NULL;
-                struct dirent *de;
-                uint64_t sum = 0;
-
-                rewinddir(d);
-
-                FOREACH_DIRENT(de, d, goto fail) {
-                        struct vacuum_candidate *c;
-                        struct stat st;
-                        uid_t uid;
-                        usec_t t;
-
-                        r = uid_from_file_name(de->d_name, &uid);
-                        if (r < 0)
-                                continue;
-
-                        if (fstatat(dirfd(d), de->d_name, &st, AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW) < 0) {
-                                if (errno == ENOENT)
-                                        continue;
-
-                                log_warning_errno(errno, "Failed to stat /var/lib/systemd/coredump/%s: %m", de->d_name);
-                                continue;
-                        }
-
-                        if (!S_ISREG(st.st_mode))
-                                continue;
-
-                        if (exclude_fd >= 0 &&
-                            exclude_st.st_dev == st.st_dev &&
-                            exclude_st.st_ino == st.st_ino)
-                                continue;
-
-                        r = hashmap_ensure_allocated(&h, NULL);
-                        if (r < 0)
-                                return log_oom();
-
-                        t = timespec_load(&st.st_mtim);
-
-                        c = hashmap_get(h, UID_TO_PTR(uid));
-                        if (c) {
-
-                                if (t < c->oldest_mtime) {
-                                        char *n;
-
-                                        n = strdup(de->d_name);
-                                        if (!n)
-                                                return log_oom();
-
-                                        free(c->oldest_file);
-                                        c->oldest_file = n;
-                                        c->oldest_mtime = t;
-                                }
-
-                        } else {
-                                _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL;
-
-                                n = new0(struct vacuum_candidate, 1);
-                                if (!n)
-                                        return log_oom();
-
-                                n->oldest_file = strdup(de->d_name);
-                                if (!n->oldest_file)
-                                        return log_oom();
-
-                                n->oldest_mtime = t;
-
-                                r = hashmap_put(h, UID_TO_PTR(uid), n);
-                                if (r < 0)
-                                        return log_oom();
-
-                                c = n;
-                                n = NULL;
-                        }
-
-                        c->n_files++;
-
-                        if (!worst ||
-                            worst->n_files < c->n_files ||
-                            (worst->n_files == c->n_files && c->oldest_mtime < worst->oldest_mtime))
-                                worst = c;
-
-                        sum += st.st_blocks * 512;
-                }
-
-                if (!worst)
-                        break;
-
-                r = vacuum_necessary(dirfd(d), sum, keep_free, max_use);
-                if (r <= 0)
-                        return r;
-
-                if (unlinkat(dirfd(d), worst->oldest_file, 0) < 0) {
-
-                        if (errno == ENOENT)
-                                continue;
-
-                        return log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file);
-                } else
-                        log_info("Removed old coredump %s.", worst->oldest_file);
-        }
-
-        return 0;
-
-fail:
-        return log_error_errno(errno, "Failed to read directory: %m");
-}
diff --git a/src/journal/coredump-vacuum.h b/src/journal/coredump-vacuum.h
deleted file mode 100644 (file)
index 7779c97..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use);
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
deleted file mode 100644 (file)
index f750ddf..0000000
+++ /dev/null
@@ -1,875 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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 <errno.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-#include <sys/xattr.h>
-#include <unistd.h>
-
-#ifdef HAVE_ELFUTILS
-#  include <dwarf.h>
-#  include <elfutils/libdwfl.h>
-#endif
-
-#include "sd-journal.h"
-#include "sd-login.h"
-
-#include "acl-util.h"
-#include "alloc-util.h"
-#include "capability-util.h"
-#include "cgroup-util.h"
-#include "compress.h"
-#include "conf-parser.h"
-#include "copy.h"
-#include "coredump-vacuum.h"
-#include "dirent-util.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "io-util.h"
-#include "journald-native.h"
-#include "log.h"
-#include "macro.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "process-util.h"
-#include "special.h"
-#include "stacktrace.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "util.h"
-
-/* The maximum size up to which we process coredumps */
-#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU))
-
-/* The maximum size up to which we leave the coredump around on
- * disk */
-#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
-
-/* The maximum size up to which we store the coredump in the
- * journal */
-#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
-
-/* Make sure to not make this larger than the maximum journal entry
- * size. See DATA_SIZE_MAX in journald-native.c. */
-assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
-
-enum {
-        INFO_PID,
-        INFO_UID,
-        INFO_GID,
-        INFO_SIGNAL,
-        INFO_TIMESTAMP,
-        INFO_COMM,
-        INFO_EXE,
-        _INFO_LEN
-};
-
-typedef enum CoredumpStorage {
-        COREDUMP_STORAGE_NONE,
-        COREDUMP_STORAGE_EXTERNAL,
-        COREDUMP_STORAGE_JOURNAL,
-        COREDUMP_STORAGE_BOTH,
-        _COREDUMP_STORAGE_MAX,
-        _COREDUMP_STORAGE_INVALID = -1
-} CoredumpStorage;
-
-static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
-        [COREDUMP_STORAGE_NONE] = "none",
-        [COREDUMP_STORAGE_EXTERNAL] = "external",
-        [COREDUMP_STORAGE_JOURNAL] = "journal",
-        [COREDUMP_STORAGE_BOTH] = "both",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
-static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting");
-
-static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL;
-static bool arg_compress = true;
-static uint64_t arg_process_size_max = PROCESS_SIZE_MAX;
-static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX;
-static size_t arg_journal_size_max = JOURNAL_SIZE_MAX;
-static uint64_t arg_keep_free = (uint64_t) -1;
-static uint64_t arg_max_use = (uint64_t) -1;
-
-static int parse_config(void) {
-        static const ConfigTableItem items[] = {
-                { "Coredump", "Storage",          config_parse_coredump_storage,  0, &arg_storage           },
-                { "Coredump", "Compress",         config_parse_bool,              0, &arg_compress          },
-                { "Coredump", "ProcessSizeMax",   config_parse_iec_uint64,        0, &arg_process_size_max  },
-                { "Coredump", "ExternalSizeMax",  config_parse_iec_uint64,        0, &arg_external_size_max },
-                { "Coredump", "JournalSizeMax",   config_parse_iec_size,          0, &arg_journal_size_max  },
-                { "Coredump", "KeepFree",         config_parse_iec_uint64,        0, &arg_keep_free         },
-                { "Coredump", "MaxUse",           config_parse_iec_uint64,        0, &arg_max_use           },
-                {}
-        };
-
-        return config_parse_many(PKGSYSCONFDIR "/coredump.conf",
-                                 CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
-                                 "Coredump\0",
-                                 config_item_table_lookup, items,
-                                 false, NULL);
-}
-
-static int fix_acl(int fd, uid_t uid) {
-
-#ifdef HAVE_ACL
-        _cleanup_(acl_freep) acl_t acl = NULL;
-        acl_entry_t entry;
-        acl_permset_t permset;
-        int r;
-
-        assert(fd >= 0);
-
-        if (uid <= SYSTEM_UID_MAX)
-                return 0;
-
-        /* Make sure normal users can read (but not write or delete)
-         * their own coredumps */
-
-        acl = acl_get_fd(fd);
-        if (!acl)
-                return log_error_errno(errno, "Failed to get ACL: %m");
-
-        if (acl_create_entry(&acl, &entry) < 0 ||
-            acl_set_tag_type(entry, ACL_USER) < 0 ||
-            acl_set_qualifier(entry, &uid) < 0) {
-                log_error_errno(errno, "Failed to patch ACL: %m");
-                return -errno;
-        }
-
-        if (acl_get_permset(entry, &permset) < 0 ||
-            acl_add_perm(permset, ACL_READ) < 0)
-                return log_warning_errno(errno, "Failed to patch ACL: %m");
-
-        r = calc_acl_mask_if_needed(&acl);
-        if (r < 0)
-                return log_warning_errno(r, "Failed to patch ACL: %m");
-
-        if (acl_set_fd(fd, acl) < 0)
-                return log_error_errno(errno, "Failed to apply ACL: %m");
-#endif
-
-        return 0;
-}
-
-static int fix_xattr(int fd, const char *info[_INFO_LEN]) {
-
-        static const char * const xattrs[_INFO_LEN] = {
-                [INFO_PID] = "user.coredump.pid",
-                [INFO_UID] = "user.coredump.uid",
-                [INFO_GID] = "user.coredump.gid",
-                [INFO_SIGNAL] = "user.coredump.signal",
-                [INFO_TIMESTAMP] = "user.coredump.timestamp",
-                [INFO_COMM] = "user.coredump.comm",
-                [INFO_EXE] = "user.coredump.exe",
-        };
-
-        int r = 0;
-        unsigned i;
-
-        assert(fd >= 0);
-
-        /* Attach some metadata to coredumps via extended
-         * attributes. Just because we can. */
-
-        for (i = 0; i < _INFO_LEN; i++) {
-                int k;
-
-                if (isempty(info[i]) || !xattrs[i])
-                        continue;
-
-                k = fsetxattr(fd, xattrs[i], info[i], strlen(info[i]), XATTR_CREATE);
-                if (k < 0 && r == 0)
-                        r = -errno;
-        }
-
-        return r;
-}
-
-#define filename_escape(s) xescape((s), "./ ")
-
-static int fix_permissions(
-                int fd,
-                const char *filename,
-                const char *target,
-                const char *info[_INFO_LEN],
-                uid_t uid) {
-
-        assert(fd >= 0);
-        assert(filename);
-        assert(target);
-        assert(info);
-
-        /* Ignore errors on these */
-        fchmod(fd, 0640);
-        fix_acl(fd, uid);
-        fix_xattr(fd, info);
-
-        if (fsync(fd) < 0)
-                return log_error_errno(errno, "Failed to sync coredump %s: %m", filename);
-
-        if (rename(filename, target) < 0)
-                return log_error_errno(errno, "Failed to rename coredump %s -> %s: %m", filename, target);
-
-        return 0;
-}
-
-static int maybe_remove_external_coredump(const char *filename, uint64_t size) {
-
-        /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */
-
-        if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) &&
-            size <= arg_external_size_max)
-                return 0;
-
-        if (!filename)
-                return 1;
-
-        if (unlink(filename) < 0 && errno != ENOENT)
-                return log_error_errno(errno, "Failed to unlink %s: %m", filename);
-
-        return 1;
-}
-
-static int make_filename(const char *info[_INFO_LEN], char **ret) {
-        _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
-        sd_id128_t boot = {};
-        int r;
-
-        assert(info);
-
-        c = filename_escape(info[INFO_COMM]);
-        if (!c)
-                return -ENOMEM;
-
-        u = filename_escape(info[INFO_UID]);
-        if (!u)
-                return -ENOMEM;
-
-        r = sd_id128_get_boot(&boot);
-        if (r < 0)
-                return r;
-
-        p = filename_escape(info[INFO_PID]);
-        if (!p)
-                return -ENOMEM;
-
-        t = filename_escape(info[INFO_TIMESTAMP]);
-        if (!t)
-                return -ENOMEM;
-
-        if (asprintf(ret,
-                     "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
-                     c,
-                     u,
-                     SD_ID128_FORMAT_VAL(boot),
-                     p,
-                     t) < 0)
-                return -ENOMEM;
-
-        return 0;
-}
-
-static int save_external_coredump(
-                const char *info[_INFO_LEN],
-                uid_t uid,
-                char **ret_filename,
-                int *ret_fd,
-                uint64_t *ret_size) {
-
-        _cleanup_free_ char *fn = NULL, *tmp = NULL;
-        _cleanup_close_ int fd = -1;
-        struct stat st;
-        int r;
-
-        assert(info);
-        assert(ret_filename);
-        assert(ret_fd);
-        assert(ret_size);
-
-        r = make_filename(info, &fn);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine coredump file name: %m");
-
-        r = tempfn_random(fn, NULL, &tmp);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine temporary file name: %m");
-
-        mkdir_p_label("/var/lib/systemd/coredump", 0755);
-
-        fd = open(tmp, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
-        if (fd < 0)
-                return log_error_errno(errno, "Failed to create coredump file %s: %m", tmp);
-
-        r = copy_bytes(STDIN_FILENO, fd, arg_process_size_max, false);
-        if (r == -EFBIG) {
-                log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", info[INFO_PID], info[INFO_COMM]);
-                goto fail;
-        } else if (IN_SET(r, -EDQUOT, -ENOSPC)) {
-                log_error("Not enough disk space for coredump of %s (%s), refusing.", info[INFO_PID], info[INFO_COMM]);
-                goto fail;
-        } else if (r < 0) {
-                log_error_errno(r, "Failed to dump coredump to file: %m");
-                goto fail;
-        }
-
-        if (fstat(fd, &st) < 0) {
-                log_error_errno(errno, "Failed to fstat coredump %s: %m", tmp);
-                goto fail;
-        }
-
-        if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
-                log_error_errno(errno, "Failed to seek on %s: %m", tmp);
-                goto fail;
-        }
-
-#if defined(HAVE_XZ) || defined(HAVE_LZ4)
-        /* If we will remove the coredump anyway, do not compress. */
-        if (maybe_remove_external_coredump(NULL, st.st_size) == 0
-            && arg_compress) {
-
-                _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL;
-                _cleanup_close_ int fd_compressed = -1;
-
-                fn_compressed = strappend(fn, COMPRESSED_EXT);
-                if (!fn_compressed) {
-                        log_oom();
-                        goto uncompressed;
-                }
-
-                r = tempfn_random(fn_compressed, NULL, &tmp_compressed);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to determine temporary file name for %s: %m", fn_compressed);
-                        goto uncompressed;
-                }
-
-                fd_compressed = open(tmp_compressed, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640);
-                if (fd_compressed < 0) {
-                        log_error_errno(errno, "Failed to create file %s: %m", tmp_compressed);
-                        goto uncompressed;
-                }
-
-                r = compress_stream(fd, fd_compressed, -1);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to compress %s: %m", tmp_compressed);
-                        goto fail_compressed;
-                }
-
-                r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, info, uid);
-                if (r < 0)
-                        goto fail_compressed;
-
-                /* OK, this worked, we can get rid of the uncompressed version now */
-                unlink_noerrno(tmp);
-
-                *ret_filename = fn_compressed;     /* compressed */
-                *ret_fd = fd;                      /* uncompressed */
-                *ret_size = (uint64_t) st.st_size; /* uncompressed */
-
-                fn_compressed = NULL;
-                fd = -1;
-
-                return 0;
-
-        fail_compressed:
-                unlink_noerrno(tmp_compressed);
-        }
-
-uncompressed:
-#endif
-        r = fix_permissions(fd, tmp, fn, info, uid);
-        if (r < 0)
-                goto fail;
-
-        *ret_filename = fn;
-        *ret_fd = fd;
-        *ret_size = (uint64_t) st.st_size;
-
-        fn = NULL;
-        fd = -1;
-
-        return 0;
-
-fail:
-        unlink_noerrno(tmp);
-        return r;
-}
-
-static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) {
-        _cleanup_free_ char *field = NULL;
-        ssize_t n;
-
-        assert(fd >= 0);
-        assert(ret);
-        assert(ret_size);
-
-        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
-                return log_warning_errno(errno, "Failed to seek: %m");
-
-        field = malloc(9 + size);
-        if (!field) {
-                log_warning("Failed to allocate memory for coredump, coredump will not be stored.");
-                return -ENOMEM;
-        }
-
-        memcpy(field, "COREDUMP=", 9);
-
-        n = read(fd, field + 9, size);
-        if (n < 0)
-                return log_error_errno((int) n, "Failed to read core data: %m");
-        if ((size_t) n < size) {
-                log_error("Core data too short.");
-                return -EIO;
-        }
-
-        *ret = field;
-        *ret_size = size + 9;
-
-        field = NULL;
-
-        return 0;
-}
-
-/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines:
- * 0:/dev/pts/23
- * pos:    0
- * flags:  0100002
- *
- * 1:/dev/pts/23
- * pos:    0
- * flags:  0100002
- *
- * 2:/dev/pts/23
- * pos:    0
- * flags:  0100002
- * EOF
- */
-static int compose_open_fds(pid_t pid, char **open_fds) {
-        _cleanup_closedir_ DIR *proc_fd_dir = NULL;
-        _cleanup_close_ int proc_fdinfo_fd = -1;
-        _cleanup_free_ char *buffer = NULL;
-        _cleanup_fclose_ FILE *stream = NULL;
-        const char *fddelim = "", *path;
-        struct dirent *dent = NULL;
-        size_t size = 0;
-        int r = 0;
-
-        assert(pid >= 0);
-        assert(open_fds != NULL);
-
-        path = procfs_file_alloca(pid, "fd");
-        proc_fd_dir = opendir(path);
-        if (!proc_fd_dir)
-                return -errno;
-
-        proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH);
-        if (proc_fdinfo_fd < 0)
-                return -errno;
-
-        stream = open_memstream(&buffer, &size);
-        if (!stream)
-                return -ENOMEM;
-
-        FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
-                _cleanup_fclose_ FILE *fdinfo = NULL;
-                _cleanup_free_ char *fdname = NULL;
-                char line[LINE_MAX];
-                int fd;
-
-                r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
-                if (r < 0)
-                        return r;
-
-                fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname);
-                fddelim = "\n";
-
-                /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */
-                fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY);
-                if (fd < 0)
-                        continue;
-
-                fdinfo = fdopen(fd, "re");
-                if (fdinfo == NULL) {
-                        close(fd);
-                        continue;
-                }
-
-                FOREACH_LINE(line, fdinfo, break) {
-                        fputs(line, stream);
-                        if (!endswith(line, "\n"))
-                                fputc('\n', stream);
-                }
-        }
-
-        errno = 0;
-        stream = safe_fclose(stream);
-
-        if (errno != 0)
-                return -errno;
-
-        *open_fds = buffer;
-        buffer = NULL;
-
-        return 0;
-}
-
-int main(int argc, char* argv[]) {
-
-        /* The small core field we allocate on the stack, to keep things simple */
-        char
-                *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
-                *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL,
-                *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL,
-                *core_slice = NULL;
-
-        /* The larger ones we allocate on the heap */
-        _cleanup_free_ char
-                *core_timestamp = NULL,  *core_message = NULL, *coredump_data = NULL, *core_owner_uid = NULL,
-                *core_open_fds = NULL, *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL,
-                *core_proc_cgroup = NULL, *core_environ = NULL;
-
-        _cleanup_free_ char *exe = NULL, *comm = NULL, *filename = NULL;
-        const char *info[_INFO_LEN];
-
-        _cleanup_close_ int coredump_fd = -1;
-
-        struct iovec iovec[26];
-        uint64_t coredump_size;
-        int r, j = 0;
-        uid_t uid, owner_uid;
-        gid_t gid;
-        pid_t pid;
-        char *t;
-        const char *p;
-
-        /* Make sure we never enter a loop */
-        prctl(PR_SET_DUMPABLE, 0);
-
-        /* First, log to a safe place, since we don't know what
-         * crashed and it might be journald which we'd rather not log
-         * to then. */
-        log_set_target(LOG_TARGET_KMSG);
-        log_open();
-
-        if (argc < INFO_COMM + 1) {
-                log_error("Not enough arguments passed from kernel (%d, expected %d).",
-                          argc - 1, INFO_COMM + 1 - 1);
-                r = -EINVAL;
-                goto finish;
-        }
-
-        /* Ignore all parse errors */
-        parse_config();
-
-        log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
-        log_debug("Selected compression %s.", yes_no(arg_compress));
-
-        r = parse_uid(argv[INFO_UID + 1], &uid);
-        if (r < 0) {
-                log_error("Failed to parse UID.");
-                goto finish;
-        }
-
-        r = parse_pid(argv[INFO_PID + 1], &pid);
-        if (r < 0) {
-                log_error("Failed to parse PID.");
-                goto finish;
-        }
-
-        r = parse_gid(argv[INFO_GID + 1], &gid);
-        if (r < 0) {
-                log_error("Failed to parse GID.");
-                goto finish;
-        }
-
-        if (get_process_comm(pid, &comm) < 0) {
-                log_warning("Failed to get COMM, falling back to the command line.");
-                comm = strv_join(argv + INFO_COMM + 1, " ");
-        }
-
-        if (get_process_exe(pid, &exe) < 0)
-                log_warning("Failed to get EXE.");
-
-        info[INFO_PID] = argv[INFO_PID + 1];
-        info[INFO_UID] = argv[INFO_UID + 1];
-        info[INFO_GID] = argv[INFO_GID + 1];
-        info[INFO_SIGNAL] = argv[INFO_SIGNAL + 1];
-        info[INFO_TIMESTAMP] = argv[INFO_TIMESTAMP + 1];
-        info[INFO_COMM] = comm;
-        info[INFO_EXE] = exe;
-
-        if (cg_pid_get_unit(pid, &t) >= 0) {
-
-                if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
-                        free(t);
-
-                        /* If we are journald, we cut things short,
-                         * don't write to the journal, but still
-                         * create a coredump. */
-
-                        if (arg_storage != COREDUMP_STORAGE_NONE)
-                                arg_storage = COREDUMP_STORAGE_EXTERNAL;
-
-                        r = save_external_coredump(info, uid, &filename, &coredump_fd, &coredump_size);
-                        if (r < 0)
-                                goto finish;
-
-                        r = maybe_remove_external_coredump(filename, coredump_size);
-                        if (r < 0)
-                                goto finish;
-
-                        log_info("Detected coredump of the journal daemon itself, diverted to %s.", filename);
-                        goto finish;
-                }
-
-                core_unit = strjoina("COREDUMP_UNIT=", t);
-                free(t);
-
-        } else if (cg_pid_get_user_unit(pid, &t) >= 0) {
-                core_unit = strjoina("COREDUMP_USER_UNIT=", t);
-                free(t);
-        }
-
-        if (core_unit)
-                IOVEC_SET_STRING(iovec[j++], core_unit);
-
-        /* OK, now we know it's not the journal, hence we can make use
-         * of it now. */
-        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
-        log_open();
-
-        core_pid = strjoina("COREDUMP_PID=", info[INFO_PID]);
-        IOVEC_SET_STRING(iovec[j++], core_pid);
-
-        core_uid = strjoina("COREDUMP_UID=", info[INFO_UID]);
-        IOVEC_SET_STRING(iovec[j++], core_uid);
-
-        core_gid = strjoina("COREDUMP_GID=", info[INFO_GID]);
-        IOVEC_SET_STRING(iovec[j++], core_gid);
-
-        core_signal = strjoina("COREDUMP_SIGNAL=", info[INFO_SIGNAL]);
-        IOVEC_SET_STRING(iovec[j++], core_signal);
-
-        if (sd_pid_get_session(pid, &t) >= 0) {
-                core_session = strjoina("COREDUMP_SESSION=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_session);
-        }
-
-        if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
-                r = asprintf(&core_owner_uid,
-                             "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
-                if (r > 0)
-                        IOVEC_SET_STRING(iovec[j++], core_owner_uid);
-        }
-
-        if (sd_pid_get_slice(pid, &t) >= 0) {
-                core_slice = strjoina("COREDUMP_SLICE=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_slice);
-        }
-
-        if (comm) {
-                core_comm = strjoina("COREDUMP_COMM=", comm);
-                IOVEC_SET_STRING(iovec[j++], core_comm);
-        }
-
-        if (exe) {
-                core_exe = strjoina("COREDUMP_EXE=", exe);
-                IOVEC_SET_STRING(iovec[j++], core_exe);
-        }
-
-        if (get_process_cmdline(pid, 0, false, &t) >= 0) {
-                core_cmdline = strjoina("COREDUMP_CMDLINE=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_cmdline);
-        }
-
-        if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) {
-                core_cgroup = strjoina("COREDUMP_CGROUP=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_cgroup);
-        }
-
-        if (compose_open_fds(pid, &t) >= 0) {
-                core_open_fds = strappend("COREDUMP_OPEN_FDS=", t);
-                free(t);
-
-                if (core_open_fds)
-                        IOVEC_SET_STRING(iovec[j++], core_open_fds);
-        }
-
-        p = procfs_file_alloca(pid, "status");
-        if (read_full_file(p, &t, NULL) >= 0) {
-                core_proc_status = strappend("COREDUMP_PROC_STATUS=", t);
-                free(t);
-
-                if (core_proc_status)
-                        IOVEC_SET_STRING(iovec[j++], core_proc_status);
-        }
-
-        p = procfs_file_alloca(pid, "maps");
-        if (read_full_file(p, &t, NULL) >= 0) {
-                core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t);
-                free(t);
-
-                if (core_proc_maps)
-                        IOVEC_SET_STRING(iovec[j++], core_proc_maps);
-        }
-
-        p = procfs_file_alloca(pid, "limits");
-        if (read_full_file(p, &t, NULL) >= 0) {
-                core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t);
-                free(t);
-
-                if (core_proc_limits)
-                        IOVEC_SET_STRING(iovec[j++], core_proc_limits);
-        }
-
-        p = procfs_file_alloca(pid, "cgroup");
-        if (read_full_file(p, &t, NULL) >=0) {
-                core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t);
-                free(t);
-
-                if (core_proc_cgroup)
-                        IOVEC_SET_STRING(iovec[j++], core_proc_cgroup);
-        }
-
-        if (get_process_cwd(pid, &t) >= 0) {
-                core_cwd = strjoina("COREDUMP_CWD=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_cwd);
-        }
-
-        if (get_process_root(pid, &t) >= 0) {
-                core_root = strjoina("COREDUMP_ROOT=", t);
-                free(t);
-
-                IOVEC_SET_STRING(iovec[j++], core_root);
-        }
-
-        if (get_process_environ(pid, &t) >= 0) {
-                core_environ = strappend("COREDUMP_ENVIRON=", t);
-                free(t);
-
-                if (core_environ)
-                        IOVEC_SET_STRING(iovec[j++], core_environ);
-        }
-
-        core_timestamp = strjoin("COREDUMP_TIMESTAMP=", info[INFO_TIMESTAMP], "000000", NULL);
-        if (core_timestamp)
-                IOVEC_SET_STRING(iovec[j++], core_timestamp);
-
-        IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
-        IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
-
-        /* Vacuum before we write anything again */
-        coredump_vacuum(-1, arg_keep_free, arg_max_use);
-
-        /* Always stream the coredump to disk, if that's possible */
-        r = save_external_coredump(info, uid, &filename, &coredump_fd, &coredump_size);
-        if (r < 0)
-                /* skip whole core dumping part */
-                goto log;
-
-        /* If we don't want to keep the coredump on disk, remove it
-         * now, as later on we will lack the privileges for
-         * it. However, we keep the fd to it, so that we can still
-         * process it and log it. */
-        r = maybe_remove_external_coredump(filename, coredump_size);
-        if (r < 0)
-                goto finish;
-        if (r == 0) {
-                const char *coredump_filename;
-
-                coredump_filename = strjoina("COREDUMP_FILENAME=", filename);
-                IOVEC_SET_STRING(iovec[j++], coredump_filename);
-        }
-
-        /* Vacuum again, but exclude the coredump we just created */
-        coredump_vacuum(coredump_fd, arg_keep_free, arg_max_use);
-
-        /* Now, let's drop privileges to become the user who owns the
-         * segfaulted process and allocate the coredump memory under
-         * the user's uid. This also ensures that the credentials
-         * journald will see are the ones of the coredumping user,
-         * thus making sure the user gets access to the core
-         * dump. Let's also get rid of all capabilities, if we run as
-         * root, we won't need them anymore. */
-        r = drop_privileges(uid, gid, 0);
-        if (r < 0) {
-                log_error_errno(r, "Failed to drop privileges: %m");
-                goto finish;
-        }
-
-#ifdef HAVE_ELFUTILS
-        /* Try to get a strack trace if we can */
-        if (coredump_size <= arg_process_size_max) {
-                _cleanup_free_ char *stacktrace = NULL;
-
-                r = coredump_make_stack_trace(coredump_fd, exe, &stacktrace);
-                if (r >= 0)
-                        core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.\n\n", stacktrace, NULL);
-                else if (r == -EINVAL)
-                        log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno()));
-                else
-                        log_warning_errno(r, "Failed to generate stack trace: %m");
-        }
-
-        if (!core_message)
-#endif
-log:
-        core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.", NULL);
-        if (core_message)
-                IOVEC_SET_STRING(iovec[j++], core_message);
-
-        /* Optionally store the entire coredump in the journal */
-        if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
-            coredump_size <= arg_journal_size_max) {
-                size_t sz = 0;
-
-                /* Store the coredump itself in the journal */
-
-                r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz);
-                if (r >= 0) {
-                        iovec[j].iov_base = coredump_data;
-                        iovec[j].iov_len = sz;
-                        j++;
-                }
-        }
-
-        r = sd_journal_sendv(iovec, j);
-        if (r < 0)
-                log_error_errno(r, "Failed to log coredump: %m");
-
-finish:
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/journal/coredump.conf b/src/journal/coredump.conf
deleted file mode 100644 (file)
index c2f0643..0000000
+++ /dev/null
@@ -1,21 +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.
-#
-# Entries in this file show the compile time defaults.
-# You can change settings by editing this file.
-# Defaults can be restored by simply deleting this file.
-#
-# See coredump.conf(5) for details.
-
-[Coredump]
-#Storage=external
-#Compress=yes
-#ProcessSizeMax=2G
-#ExternalSizeMax=2G
-#JournalSizeMax=767M
-#MaxUse=
-#KeepFree=
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
deleted file mode 100644 (file)
index 1df28d7..0000000
+++ /dev/null
@@ -1,882 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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 <fcntl.h>
-#include <getopt.h>
-#include <locale.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "sd-journal.h"
-
-#include "alloc-util.h"
-#include "compress.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "journal-internal.h"
-#include "log.h"
-#include "macro.h"
-#include "pager.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "set.h"
-#include "sigbus.h"
-#include "signal-util.h"
-#include "string-util.h"
-#include "terminal-util.h"
-#include "user-util.h"
-#include "util.h"
-
-static enum {
-        ACTION_NONE,
-        ACTION_INFO,
-        ACTION_LIST,
-        ACTION_DUMP,
-        ACTION_GDB,
-} arg_action = ACTION_LIST;
-static const char* arg_field = NULL;
-static const char *arg_directory = NULL;
-static int arg_no_pager = false;
-static int arg_no_legend = false;
-static int arg_one = false;
-static FILE* arg_output = NULL;
-
-static Set *new_matches(void) {
-        Set *set;
-        char *tmp;
-        int r;
-
-        set = set_new(NULL);
-        if (!set) {
-                log_oom();
-                return NULL;
-        }
-
-        tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
-        if (!tmp) {
-                log_oom();
-                set_free(set);
-                return NULL;
-        }
-
-        r = set_consume(set, tmp);
-        if (r < 0) {
-                log_error_errno(r, "failed to add to set: %m");
-                set_free(set);
-                return NULL;
-        }
-
-        return set;
-}
-
-static int add_match(Set *set, const char *match) {
-        _cleanup_free_ char *p = NULL;
-        char *pattern = NULL;
-        const char* prefix;
-        pid_t pid;
-        int r;
-
-        if (strchr(match, '='))
-                prefix = "";
-        else if (strchr(match, '/')) {
-                r = path_make_absolute_cwd(match, &p);
-                if (r < 0)
-                        goto fail;
-                match = p;
-                prefix = "COREDUMP_EXE=";
-        } else if (parse_pid(match, &pid) >= 0)
-                prefix = "COREDUMP_PID=";
-        else
-                prefix = "COREDUMP_COMM=";
-
-        pattern = strjoin(prefix, match, NULL);
-        if (!pattern) {
-                r = -ENOMEM;
-                goto fail;
-        }
-
-        log_debug("Adding pattern: %s", pattern);
-        r = set_consume(set, pattern);
-        if (r < 0)
-                goto fail;
-
-        return 0;
-fail:
-        return log_error_errno(r, "Failed to add match: %m");
-}
-
-static void help(void) {
-        printf("%s [OPTIONS...]\n\n"
-               "List or retrieve coredumps from the journal.\n\n"
-               "Flags:\n"
-               "  -h --help          Show this help\n"
-               "     --version       Print version string\n"
-               "     --no-pager      Do not pipe output into a pager\n"
-               "     --no-legend     Do not print the column headers.\n"
-               "  -1                 Show information about most recent entry only\n"
-               "  -F --field=FIELD   List all values a certain field takes\n"
-               "  -o --output=FILE   Write output to FILE\n\n"
-               "  -D --directory=DIR Use journal files from directory\n\n"
-
-               "Commands:\n"
-               "  list [MATCHES...]  List available coredumps (default)\n"
-               "  info [MATCHES...]  Show detailed information about one or more coredumps\n"
-               "  dump [MATCHES...]  Print first matching coredump to stdout\n"
-               "  gdb [MATCHES...]   Start gdb for the first matching coredump\n"
-               , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[], Set *matches) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_NO_PAGER,
-                ARG_NO_LEGEND,
-        };
-
-        int r, c;
-
-        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 },
-                { "output",       required_argument, NULL, 'o'           },
-                { "field",        required_argument, NULL, 'F'           },
-                { "directory",    required_argument, NULL, 'D'           },
-                {}
-        };
-
-        assert(argc >= 0);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "ho:F:1D:", options, NULL)) >= 0)
-                switch(c) {
-
-                case 'h':
-                        arg_action = ACTION_NONE;
-                        help();
-                        return 0;
-
-                case ARG_VERSION:
-                        arg_action = ACTION_NONE;
-                        return version();
-
-                case ARG_NO_PAGER:
-                        arg_no_pager = true;
-                        break;
-
-                case ARG_NO_LEGEND:
-                        arg_no_legend = true;
-                        break;
-
-                case 'o':
-                        if (arg_output) {
-                                log_error("cannot set output more than once");
-                                return -EINVAL;
-                        }
-
-                        arg_output = fopen(optarg, "we");
-                        if (!arg_output)
-                                return log_error_errno(errno, "writing to '%s': %m", optarg);
-
-                        break;
-
-                case 'F':
-                        if (arg_field) {
-                                log_error("cannot use --field/-F more than once");
-                                return -EINVAL;
-                        }
-                        arg_field = optarg;
-                        break;
-
-                case '1':
-                        arg_one = true;
-                        break;
-
-                case 'D':
-                        arg_directory = optarg;
-                        break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option");
-                }
-
-        if (optind < argc) {
-                const char *cmd = argv[optind++];
-                if (streq(cmd, "list"))
-                        arg_action = ACTION_LIST;
-                else if (streq(cmd, "dump"))
-                        arg_action = ACTION_DUMP;
-                else if (streq(cmd, "gdb"))
-                        arg_action = ACTION_GDB;
-                else if (streq(cmd, "info"))
-                        arg_action = ACTION_INFO;
-                else {
-                        log_error("Unknown action '%s'", cmd);
-                        return -EINVAL;
-                }
-        }
-
-        if (arg_field && arg_action != ACTION_LIST) {
-                log_error("Option --field/-F only makes sense with list");
-                return -EINVAL;
-        }
-
-        while (optind < argc) {
-                r = add_match(matches, argv[optind]);
-                if (r != 0)
-                        return r;
-                optind++;
-        }
-
-        return 0;
-}
-
-static int retrieve(const void *data,
-                    size_t len,
-                    const char *name,
-                    char **var) {
-
-        size_t ident;
-        char *v;
-
-        ident = strlen(name) + 1; /* name + "=" */
-
-        if (len < ident)
-                return 0;
-
-        if (memcmp(data, name, ident - 1) != 0)
-                return 0;
-
-        if (((const char*) data)[ident - 1] != '=')
-                return 0;
-
-        v = strndup((const char*)data + ident, len - ident);
-        if (!v)
-                return log_oom();
-
-        free(*var);
-        *var = v;
-
-        return 0;
-}
-
-static void print_field(FILE* file, sd_journal *j) {
-        _cleanup_free_ char *value = NULL;
-        const void *d;
-        size_t l;
-
-        assert(file);
-        assert(j);
-
-        assert(arg_field);
-
-        SD_JOURNAL_FOREACH_DATA(j, d, l)
-                retrieve(d, l, arg_field, &value);
-
-        if (value)
-                fprintf(file, "%s\n", value);
-}
-
-static int print_list(FILE* file, sd_journal *j, int had_legend) {
-        _cleanup_free_ char
-                *pid = NULL, *uid = NULL, *gid = NULL,
-                *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
-                *filename = NULL;
-        const void *d;
-        size_t l;
-        usec_t t;
-        char buf[FORMAT_TIMESTAMP_MAX];
-        int r;
-        bool present;
-
-        assert(file);
-        assert(j);
-
-        SD_JOURNAL_FOREACH_DATA(j, d, l) {
-                retrieve(d, l, "COREDUMP_PID", &pid);
-                retrieve(d, l, "COREDUMP_UID", &uid);
-                retrieve(d, l, "COREDUMP_GID", &gid);
-                retrieve(d, l, "COREDUMP_SIGNAL", &sgnl);
-                retrieve(d, l, "COREDUMP_EXE", &exe);
-                retrieve(d, l, "COREDUMP_COMM", &comm);
-                retrieve(d, l, "COREDUMP_CMDLINE", &cmdline);
-                retrieve(d, l, "COREDUMP_FILENAME", &filename);
-        }
-
-        if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) {
-                log_warning("Empty coredump log entry");
-                return -EINVAL;
-        }
-
-        r = sd_journal_get_realtime_usec(j, &t);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get realtime timestamp: %m");
-
-        format_timestamp(buf, sizeof(buf), t);
-        present = filename && access(filename, F_OK) == 0;
-
-        if (!had_legend && !arg_no_legend)
-                fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n",
-                        FORMAT_TIMESTAMP_WIDTH, "TIME",
-                        6, "PID",
-                        5, "UID",
-                        5, "GID",
-                        3, "SIG",
-                        1, "PRESENT",
-                           "EXE");
-
-        fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n",
-                FORMAT_TIMESTAMP_WIDTH, buf,
-                6, strna(pid),
-                5, strna(uid),
-                5, strna(gid),
-                3, strna(sgnl),
-                1, present ? "*" : "",
-                strna(exe ?: (comm ?: cmdline)));
-
-        return 0;
-}
-
-static int print_info(FILE *file, sd_journal *j, bool need_space) {
-        _cleanup_free_ char
-                *pid = NULL, *uid = NULL, *gid = NULL,
-                *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
-                *unit = NULL, *user_unit = NULL, *session = NULL,
-                *boot_id = NULL, *machine_id = NULL, *hostname = NULL,
-                *slice = NULL, *cgroup = NULL, *owner_uid = NULL,
-                *message = NULL, *timestamp = NULL, *filename = NULL;
-        const void *d;
-        size_t l;
-        int r;
-
-        assert(file);
-        assert(j);
-
-        SD_JOURNAL_FOREACH_DATA(j, d, l) {
-                retrieve(d, l, "COREDUMP_PID", &pid);
-                retrieve(d, l, "COREDUMP_UID", &uid);
-                retrieve(d, l, "COREDUMP_GID", &gid);
-                retrieve(d, l, "COREDUMP_SIGNAL", &sgnl);
-                retrieve(d, l, "COREDUMP_EXE", &exe);
-                retrieve(d, l, "COREDUMP_COMM", &comm);
-                retrieve(d, l, "COREDUMP_CMDLINE", &cmdline);
-                retrieve(d, l, "COREDUMP_UNIT", &unit);
-                retrieve(d, l, "COREDUMP_USER_UNIT", &user_unit);
-                retrieve(d, l, "COREDUMP_SESSION", &session);
-                retrieve(d, l, "COREDUMP_OWNER_UID", &owner_uid);
-                retrieve(d, l, "COREDUMP_SLICE", &slice);
-                retrieve(d, l, "COREDUMP_CGROUP", &cgroup);
-                retrieve(d, l, "COREDUMP_TIMESTAMP", &timestamp);
-                retrieve(d, l, "COREDUMP_FILENAME", &filename);
-                retrieve(d, l, "_BOOT_ID", &boot_id);
-                retrieve(d, l, "_MACHINE_ID", &machine_id);
-                retrieve(d, l, "_HOSTNAME", &hostname);
-                retrieve(d, l, "MESSAGE", &message);
-        }
-
-        if (need_space)
-                fputs("\n", file);
-
-        if (comm)
-                fprintf(file,
-                        "           PID: %s%s%s (%s)\n",
-                        ansi_highlight(), strna(pid), ansi_normal(), comm);
-        else
-                fprintf(file,
-                        "           PID: %s%s%s\n",
-                        ansi_highlight(), strna(pid), ansi_normal());
-
-        if (uid) {
-                uid_t n;
-
-                if (parse_uid(uid, &n) >= 0) {
-                        _cleanup_free_ char *u = NULL;
-
-                        u = uid_to_name(n);
-                        fprintf(file,
-                                "           UID: %s (%s)\n",
-                                uid, u);
-                } else {
-                        fprintf(file,
-                                "           UID: %s\n",
-                                uid);
-                }
-        }
-
-        if (gid) {
-                gid_t n;
-
-                if (parse_gid(gid, &n) >= 0) {
-                        _cleanup_free_ char *g = NULL;
-
-                        g = gid_to_name(n);
-                        fprintf(file,
-                                "           GID: %s (%s)\n",
-                                gid, g);
-                } else {
-                        fprintf(file,
-                                "           GID: %s\n",
-                                gid);
-                }
-        }
-
-        if (sgnl) {
-                int sig;
-
-                if (safe_atoi(sgnl, &sig) >= 0)
-                        fprintf(file, "        Signal: %s (%s)\n", sgnl, signal_to_string(sig));
-                else
-                        fprintf(file, "        Signal: %s\n", sgnl);
-        }
-
-        if (timestamp) {
-                usec_t u;
-
-                r = safe_atou64(timestamp, &u);
-                if (r >= 0) {
-                        char absolute[FORMAT_TIMESTAMP_MAX], relative[FORMAT_TIMESPAN_MAX];
-
-                        fprintf(file,
-                                "     Timestamp: %s (%s)\n",
-                                format_timestamp(absolute, sizeof(absolute), u),
-                                format_timestamp_relative(relative, sizeof(relative), u));
-
-                } else
-                        fprintf(file, "     Timestamp: %s\n", timestamp);
-        }
-
-        if (cmdline)
-                fprintf(file, "  Command Line: %s\n", cmdline);
-        if (exe)
-                fprintf(file, "    Executable: %s%s%s\n", ansi_highlight(), exe, ansi_normal());
-        if (cgroup)
-                fprintf(file, " Control Group: %s\n", cgroup);
-        if (unit)
-                fprintf(file, "          Unit: %s\n", unit);
-        if (user_unit)
-                fprintf(file, "     User Unit: %s\n", unit);
-        if (slice)
-                fprintf(file, "         Slice: %s\n", slice);
-        if (session)
-                fprintf(file, "       Session: %s\n", session);
-        if (owner_uid) {
-                uid_t n;
-
-                if (parse_uid(owner_uid, &n) >= 0) {
-                        _cleanup_free_ char *u = NULL;
-
-                        u = uid_to_name(n);
-                        fprintf(file,
-                                "     Owner UID: %s (%s)\n",
-                                owner_uid, u);
-                } else {
-                        fprintf(file,
-                                "     Owner UID: %s\n",
-                                owner_uid);
-                }
-        }
-        if (boot_id)
-                fprintf(file, "       Boot ID: %s\n", boot_id);
-        if (machine_id)
-                fprintf(file, "    Machine ID: %s\n", machine_id);
-        if (hostname)
-                fprintf(file, "      Hostname: %s\n", hostname);
-
-        if (filename && access(filename, F_OK) == 0)
-                fprintf(file, "      Coredump: %s\n", filename);
-
-        if (message) {
-                _cleanup_free_ char *m = NULL;
-
-                m = strreplace(message, "\n", "\n                ");
-
-                fprintf(file, "       Message: %s\n", strstrip(m ?: message));
-        }
-
-        return 0;
-}
-
-static int focus(sd_journal *j) {
-        int r;
-
-        r = sd_journal_seek_tail(j);
-        if (r == 0)
-                r = sd_journal_previous(j);
-        if (r < 0)
-                return log_error_errno(r, "Failed to search journal: %m");
-        if (r == 0) {
-                log_error("No match found.");
-                return -ESRCH;
-        }
-        return r;
-}
-
-static void print_entry(sd_journal *j, unsigned n_found) {
-        assert(j);
-
-        if (arg_action == ACTION_INFO)
-                print_info(stdout, j, n_found);
-        else if (arg_field)
-                print_field(stdout, j);
-        else
-                print_list(stdout, j, n_found);
-}
-
-static int dump_list(sd_journal *j) {
-        unsigned n_found = 0;
-        int r;
-
-        assert(j);
-
-        /* The coredumps are likely to compressed, and for just
-         * listing them we don't need to decompress them, so let's
-         * pick a fairly low data threshold here */
-        sd_journal_set_data_threshold(j, 4096);
-
-        if (arg_one) {
-                r = focus(j);
-                if (r < 0)
-                        return r;
-
-                print_entry(j, 0);
-        } else {
-                SD_JOURNAL_FOREACH(j)
-                        print_entry(j, n_found++);
-
-                if (!arg_field && n_found <= 0) {
-                        log_notice("No coredumps found.");
-                        return -ESRCH;
-                }
-        }
-
-        return 0;
-}
-
-static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
-        const char *data;
-        _cleanup_free_ char *filename = NULL;
-        size_t len;
-        int r;
-
-        assert((fd >= 0) != !!path);
-        assert(!!path == !!unlink_temp);
-
-        /* Prefer uncompressed file to journal (probably cached) to
-         * compressed file (probably uncached). */
-        r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
-        if (r < 0 && r != -ENOENT)
-                log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m");
-        else if (r == 0)
-                retrieve(data, len, "COREDUMP_FILENAME", &filename);
-
-        if (filename && access(filename, R_OK) < 0) {
-                log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
-                         "File %s is not readable: %m", filename);
-                filename = mfree(filename);
-        }
-
-        if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
-                if (path) {
-                        *path = filename;
-                        filename = NULL;
-                }
-
-                return 0;
-        } else {
-                _cleanup_close_ int fdt = -1;
-                char *temp = NULL;
-
-                if (fd < 0) {
-                        temp = strdup("/var/tmp/coredump-XXXXXX");
-                        if (!temp)
-                                return log_oom();
-
-                        fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
-                        if (fdt < 0)
-                                return log_error_errno(fdt, "Failed to create temporary file: %m");
-                        log_debug("Created temporary file %s", temp);
-
-                        fd = fdt;
-                }
-
-                r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
-                if (r == 0) {
-                        ssize_t sz;
-
-                        assert(len >= 9);
-                        data += 9;
-                        len -= 9;
-
-                        sz = write(fdt, data, len);
-                        if (sz < 0) {
-                                r = log_error_errno(errno,
-                                                    "Failed to write temporary file: %m");
-                                goto error;
-                        }
-                        if (sz != (ssize_t) len) {
-                                log_error("Short write to temporary file.");
-                                r = -EIO;
-                                goto error;
-                        }
-                } else if (filename) {
-#if defined(HAVE_XZ) || defined(HAVE_LZ4)
-                        _cleanup_close_ int fdf;
-
-                        fdf = open(filename, O_RDONLY | O_CLOEXEC);
-                        if (fdf < 0) {
-                                r = log_error_errno(errno,
-                                                    "Failed to open %s: %m",
-                                                    filename);
-                                goto error;
-                        }
-
-                        r = decompress_stream(filename, fdf, fd, -1);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to decompress %s: %m", filename);
-                                goto error;
-                        }
-#else
-                        log_error("Cannot decompress file. Compiled without compression support.");
-                        r = -EOPNOTSUPP;
-                        goto error;
-#endif
-                } else {
-                        if (r == -ENOENT)
-                                log_error("Cannot retrieve coredump from journal nor disk.");
-                        else
-                                log_error_errno(r, "Failed to retrieve COREDUMP field: %m");
-                        goto error;
-                }
-
-                if (temp) {
-                        *path = temp;
-                        *unlink_temp = true;
-                }
-
-                return 0;
-
-error:
-                if (temp) {
-                        unlink(temp);
-                        log_debug("Removed temporary file %s", temp);
-                }
-                return r;
-        }
-}
-
-static int dump_core(sd_journal* j) {
-        int r;
-
-        assert(j);
-
-        r = focus(j);
-        if (r < 0)
-                return r;
-
-        print_info(arg_output ? stdout : stderr, j, false);
-
-        if (on_tty() && !arg_output) {
-                log_error("Refusing to dump core to tty.");
-                return -ENOTTY;
-        }
-
-        r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Coredump retrieval failed: %m");
-
-        r = sd_journal_previous(j);
-        if (r >= 0)
-                log_warning("More than one entry matches, ignoring rest.");
-
-        return 0;
-}
-
-static int run_gdb(sd_journal *j) {
-        _cleanup_free_ char *exe = NULL, *path = NULL;
-        bool unlink_path = false;
-        const char *data;
-        siginfo_t st;
-        size_t len;
-        pid_t pid;
-        int r;
-
-        assert(j);
-
-        r = focus(j);
-        if (r < 0)
-                return r;
-
-        print_info(stdout, j, false);
-        fputs("\n", stdout);
-
-        r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
-        if (r < 0)
-                return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m");
-
-        assert(len > strlen("COREDUMP_EXE="));
-        data += strlen("COREDUMP_EXE=");
-        len -= strlen("COREDUMP_EXE=");
-
-        exe = strndup(data, len);
-        if (!exe)
-                return log_oom();
-
-        if (endswith(exe, " (deleted)")) {
-                log_error("Binary already deleted.");
-                return -ENOENT;
-        }
-
-        if (!path_is_absolute(exe)) {
-                log_error("Binary is not an absolute path.");
-                return -ENOENT;
-        }
-
-        r = save_core(j, -1, &path, &unlink_path);
-        if (r < 0)
-                return log_error_errno(r, "Failed to retrieve core: %m");
-
-        pid = fork();
-        if (pid < 0) {
-                r = log_error_errno(errno, "Failed to fork(): %m");
-                goto finish;
-        }
-        if (pid == 0) {
-                (void) reset_all_signal_handlers();
-                (void) reset_signal_mask();
-
-                execlp("gdb", "gdb", exe, path, NULL);
-
-                log_error_errno(errno, "Failed to invoke gdb: %m");
-                _exit(1);
-        }
-
-        r = wait_for_terminate(pid, &st);
-        if (r < 0) {
-                log_error_errno(r, "Failed to wait for gdb: %m");
-                goto finish;
-        }
-
-        r = st.si_code == CLD_EXITED ? st.si_status : 255;
-
-finish:
-        if (unlink_path) {
-                log_debug("Removed temporary file %s", path);
-                unlink(path);
-        }
-
-        return r;
-}
-
-int main(int argc, char *argv[]) {
-        _cleanup_journal_close_ sd_journal*j = NULL;
-        const char* match;
-        Iterator it;
-        int r = 0;
-        _cleanup_set_free_free_ Set *matches = NULL;
-
-        setlocale(LC_ALL, "");
-        log_parse_environment();
-        log_open();
-
-        matches = new_matches();
-        if (!matches) {
-                r = -ENOMEM;
-                goto end;
-        }
-
-        r = parse_argv(argc, argv, matches);
-        if (r < 0)
-                goto end;
-
-        if (arg_action == ACTION_NONE)
-                goto end;
-
-        sigbus_install();
-
-        if (arg_directory) {
-                r = sd_journal_open_directory(&j, arg_directory, 0);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
-                        goto end;
-                }
-        } else {
-                r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to open journal: %m");
-                        goto end;
-                }
-        }
-
-        /* We want full data, nothing truncated. */
-        sd_journal_set_data_threshold(j, 0);
-
-        SET_FOREACH(match, matches, it) {
-                r = sd_journal_add_match(j, match, strlen(match));
-                if (r != 0) {
-                        log_error_errno(r, "Failed to add match '%s': %m",
-                                        match);
-                        goto end;
-                }
-        }
-
-        if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
-                _cleanup_free_ char *filter;
-
-                filter = journal_make_match_string(j);
-                log_debug("Journal filter: %s", filter);
-        }
-
-        switch(arg_action) {
-
-        case ACTION_LIST:
-        case ACTION_INFO:
-                if (!arg_no_pager)
-                        pager_open(false);
-
-                r = dump_list(j);
-                break;
-
-        case ACTION_DUMP:
-                r = dump_core(j);
-                break;
-
-        case  ACTION_GDB:
-                r = run_gdb(j);
-                break;
-
-        default:
-                assert_not_reached("Shouldn't be here");
-        }
-
-end:
-        pager_close();
-
-        if (arg_output)
-                fclose(arg_output);
-
-        return r >= 0 ? r : EXIT_FAILURE;
-}
index a9f564c249f1940ba19e812766cbd522a80c5ad2..8f7e137e74a4b6586d1460a15211337af90510e7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /*
  * fsprg v0.1  -  (seekable) forward-secure pseudorandom generator
  * Copyright (C) 2012 B. Poettering
index 5959b1fed2f8e6a83d21567faf7afc26325801b4..829b56e240e2d7e786db102d779451feb0ad8773 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef __fsprgh__
 #define __fsprgh__
 
@@ -25,8 +23,8 @@
  *
  */
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
 #include "macro.h"
 #include "util.h"
index aeec83da1ed4901910e12062e30f9fa905e6e0b4..49f3c8f0f40742b695176ad5bc48855b38bd4b15 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 118bb1367b7b467915ffafc67395f224f46638a0..6c87319edee844d28d277ee42499eaa3b9cb8374 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index c003ac05dd027eeefaa2a1fe1688b31644ef7f2e..67edb4396000bb1a847d06d6d56bb555bdeabb04 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f9ff9545dddd7493e500ff32b2060ff53bfa3a7a..912eb94d0af7226c5a97f7add2341759048e60ea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,6 +37,7 @@
 #include "lookup3.h"
 #include "parse-util.h"
 #include "random-util.h"
+#include "sd-event.h"
 #include "string-util.h"
 #include "xattr-util.h"
 
@@ -99,7 +98,7 @@ static int journal_file_set_online(JournalFile *f) {
         if (mmap_cache_got_sigbus(f->mmap, f->fd))
                 return -EIO;
 
-        switch(f->header->state) {
+        switch (f->header->state) {
                 case STATE_ONLINE:
                         return 0;
 
@@ -149,6 +148,17 @@ JournalFile* journal_file_close(JournalFile *f) {
                 journal_file_append_tag(f);
 #endif
 
+        if (f->post_change_timer) {
+                int enabled;
+
+                if (sd_event_source_get_enabled(f->post_change_timer, &enabled) >= 0)
+                        if (enabled == SD_EVENT_ONESHOT)
+                                journal_file_post_change(f);
+
+                (void) sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_OFF);
+                sd_event_source_unref(f->post_change_timer);
+        }
+
         journal_file_set_offline(f);
 
         if (f->mmap && f->fd >= 0)
@@ -169,8 +179,7 @@ JournalFile* journal_file_close(JournalFile *f) {
         safe_close(f->fd);
         free(f->path);
 
-        if (f->mmap)
-                mmap_cache_unref(f->mmap);
+        mmap_cache_unref(f->mmap);
 
         ordered_hashmap_free_free(f->chain_cache);
 
@@ -236,6 +245,7 @@ static int journal_file_refresh_header(JournalFile *f) {
         int r;
 
         assert(f);
+        assert(f->header);
 
         r = sd_id128_get_machine(&f->header->machine_id);
         if (r < 0)
@@ -262,6 +272,7 @@ static int journal_file_verify_header(JournalFile *f) {
         uint32_t flags;
 
         assert(f);
+        assert(f->header);
 
         if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
                 return -EBADMSG;
@@ -370,6 +381,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
         int r;
 
         assert(f);
+        assert(f->header);
 
         /* We assume that this file is not sparse, and we know that
          * for sure, since we always call posix_fallocate()
@@ -533,6 +545,7 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
         uint64_t r;
 
         assert(f);
+        assert(f->header);
 
         r = le64toh(f->header->tail_entry_seqnum) + 1;
 
@@ -562,6 +575,7 @@ int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, O
         void *t;
 
         assert(f);
+        assert(f->header);
         assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX);
         assert(size >= sizeof(ObjectHeader));
         assert(offset);
@@ -611,6 +625,7 @@ static int journal_file_setup_data_hash_table(JournalFile *f) {
         int r;
 
         assert(f);
+        assert(f->header);
 
         /* We estimate that we need 1 hash table entry per 768 bytes
            of journal file and we want to make sure we never get
@@ -644,6 +659,7 @@ static int journal_file_setup_field_hash_table(JournalFile *f) {
         int r;
 
         assert(f);
+        assert(f->header);
 
         /* We use a fixed size hash table for the fields as this
          * number should grow very slowly only */
@@ -670,6 +686,7 @@ int journal_file_map_data_hash_table(JournalFile *f) {
         int r;
 
         assert(f);
+        assert(f->header);
 
         if (f->data_hash_table)
                 return 0;
@@ -695,6 +712,7 @@ int journal_file_map_field_hash_table(JournalFile *f) {
         int r;
 
         assert(f);
+        assert(f->header);
 
         if (f->field_hash_table)
                 return 0;
@@ -724,6 +742,8 @@ static int journal_file_link_field(
         int r;
 
         assert(f);
+        assert(f->header);
+        assert(f->field_hash_table);
         assert(o);
         assert(offset > 0);
 
@@ -767,6 +787,8 @@ static int journal_file_link_data(
         int r;
 
         assert(f);
+        assert(f->header);
+        assert(f->data_hash_table);
         assert(o);
         assert(offset > 0);
 
@@ -815,6 +837,7 @@ int journal_file_find_field_object_with_hash(
         int r;
 
         assert(f);
+        assert(f->header);
         assert(field && size > 0);
 
         /* If the field hash table is empty, we can't find anything */
@@ -886,6 +909,7 @@ int journal_file_find_data_object_with_hash(
         int r;
 
         assert(f);
+        assert(f->header);
         assert(data || size == 0);
 
         /* If there's no data hash table, then there's no entry. */
@@ -1085,7 +1109,7 @@ static int journal_file_append_data(
         if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
                 size_t rsize = 0;
 
-                compression = compress_blob(data, size, o->data.payload, &rsize);
+                compression = compress_blob(data, size, o->data.payload, size - 1, &rsize);
 
                 if (compression >= 0) {
                         o->object.size = htole64(offsetof(Object, data.payload) + rsize);
@@ -1182,6 +1206,7 @@ static int link_entry_into_array(JournalFile *f,
         Object *o;
 
         assert(f);
+        assert(f->header);
         assert(first);
         assert(idx);
         assert(p > 0);
@@ -1302,6 +1327,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
         int r;
 
         assert(f);
+        assert(f->header);
         assert(o);
         assert(offset > 0);
 
@@ -1352,6 +1378,7 @@ static int journal_file_append_entry_internal(
         int r;
 
         assert(f);
+        assert(f->header);
         assert(items || n_items == 0);
         assert(ts);
 
@@ -1398,7 +1425,84 @@ void journal_file_post_change(JournalFile *f) {
         __sync_synchronize();
 
         if (ftruncate(f->fd, f->last_stat.st_size) < 0)
-                log_error_errno(errno, "Failed to truncate file to its own size: %m");
+                log_debug_errno(errno, "Failed to truncate file to its own size: %m");
+}
+
+static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userdata) {
+        assert(userdata);
+
+        journal_file_post_change(userdata);
+
+        return 1;
+}
+
+static void schedule_post_change(JournalFile *f) {
+        sd_event_source *timer;
+        int enabled, r;
+        uint64_t now;
+
+        assert(f);
+        assert(f->post_change_timer);
+
+        timer = f->post_change_timer;
+
+        r = sd_event_source_get_enabled(timer, &enabled);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to get ftruncate timer state: %m");
+                goto fail;
+        }
+
+        if (enabled == SD_EVENT_ONESHOT)
+                return;
+
+        r = sd_event_now(sd_event_source_get_event(timer), CLOCK_MONOTONIC, &now);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m");
+                goto fail;
+        }
+
+        r = sd_event_source_set_time(timer, now+f->post_change_timer_period);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m");
+                goto fail;
+        }
+
+        r = sd_event_source_set_enabled(timer, SD_EVENT_ONESHOT);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to enable scheduled ftruncate: %m");
+                goto fail;
+        }
+
+        return;
+
+fail:
+        /* On failure, let's simply post the change immediately. */
+        journal_file_post_change(f);
+}
+
+/* Enable coalesced change posting in a timer on the provided sd_event instance */
+int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
+        int r;
+
+        assert(f);
+        assert_return(!f->post_change_timer, -EINVAL);
+        assert(e);
+        assert(t);
+
+        r = sd_event_add_time(e, &timer, CLOCK_MONOTONIC, 0, 0, post_change_thunk, f);
+        if (r < 0)
+                return r;
+
+        r = sd_event_source_set_enabled(timer, SD_EVENT_OFF);
+        if (r < 0)
+                return r;
+
+        f->post_change_timer = timer;
+        timer = NULL;
+        f->post_change_timer_period = t;
+
+        return r;
 }
 
 static int entry_item_cmp(const void *_a, const void *_b) {
@@ -1419,6 +1523,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
         struct dual_timestamp _ts;
 
         assert(f);
+        assert(f->header);
         assert(iovec || n_iovec == 0);
 
         if (!ts) {
@@ -1426,10 +1531,6 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
                 ts = &_ts;
         }
 
-        if (f->tail_entry_monotonic_valid &&
-            ts->monotonic < le64toh(f->header->tail_entry_monotonic))
-                return -EINVAL;
-
 #ifdef HAVE_GCRYPT
         r = journal_file_maybe_append_tag(f, ts->realtime);
         if (r < 0)
@@ -1466,7 +1567,10 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
         if (mmap_cache_got_sigbus(f->mmap, f->fd))
                 r = -EIO;
 
-        journal_file_post_change(f);
+        if (f->post_change_timer)
+                schedule_post_change(f);
+        else
+                journal_file_post_change(f);
 
         return r;
 }
@@ -1931,6 +2035,8 @@ int journal_file_move_to_entry_by_seqnum(
                 direction_t direction,
                 Object **ret,
                 uint64_t *offset) {
+        assert(f);
+        assert(f->header);
 
         return generic_array_bisect(f,
                                     le64toh(f->header->entry_array_offset),
@@ -1966,6 +2072,8 @@ int journal_file_move_to_entry_by_realtime(
                 direction_t direction,
                 Object **ret,
                 uint64_t *offset) {
+        assert(f);
+        assert(f->header);
 
         return generic_array_bisect(f,
                                     le64toh(f->header->entry_array_offset),
@@ -2058,7 +2166,9 @@ void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
 
 int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
         assert(af);
+        assert(af->header);
         assert(bf);
+        assert(bf->header);
         assert(af->location_type == LOCATION_SEEK);
         assert(bf->location_type == LOCATION_SEEK);
 
@@ -2118,6 +2228,7 @@ int journal_file_next_entry(
         int r;
 
         assert(f);
+        assert(f->header);
 
         n = le64toh(f->header->n_entries);
         if (n <= 0)
@@ -2400,6 +2511,7 @@ void journal_file_dump(JournalFile *f) {
         uint64_t p;
 
         assert(f);
+        assert(f->header);
 
         journal_file_print_header(f);
 
@@ -2484,6 +2596,7 @@ void journal_file_print_header(JournalFile *f) {
         char bytes[FORMAT_BYTES_MAX];
 
         assert(f);
+        assert(f->header);
 
         printf("File Path: %s\n"
                "File ID: %s\n"
@@ -2768,6 +2881,16 @@ int journal_file_open(
                 goto fail;
         }
 
+        if (template && template->post_change_timer) {
+                r = journal_file_enable_post_change_timer(
+                                f,
+                                sd_event_source_get_event(template->post_change_timer),
+                                template->post_change_timer_period);
+
+                if (r < 0)
+                        goto fail;
+        }
+
         *ret = f;
         return 0;
 
@@ -3079,6 +3202,7 @@ void journal_default_metrics(JournalMetrics *m, int fd) {
 
 int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) {
         assert(f);
+        assert(f->header);
         assert(from || to);
 
         if (from) {
@@ -3142,6 +3266,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u
 
 bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
         assert(f);
+        assert(f->header);
 
         /* If we gained new header fields we gained new features,
          * hence suggest a rotation */
index 898d12d9924d331a0f70b4c5eebbb9d17727252f..07b9561b8ace8f1bce78d1c5e3dd8b75e80ed6a9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include "sd-id128.h"
 
-#include "sparse-endian.h"
+#include "hashmap.h"
 #include "journal-def.h"
 #include "macro.h"
 #include "mmap-cache.h"
-#include "hashmap.h"
+#include "sd-event.h"
+#include "sparse-endian.h"
 
 typedef struct JournalMetrics {
         /* For all these: -1 means "pick automatically", and 0 means "no limit enforced" */
@@ -101,6 +100,9 @@ typedef struct JournalFile {
         JournalMetrics metrics;
         MMapCache *mmap;
 
+        sd_event_source *post_change_timer;
+        usec_t post_change_timer_period;
+
         OrderedHashmap *chain_cache;
 
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
@@ -224,6 +226,7 @@ void journal_file_print_header(JournalFile *f);
 int journal_file_rotate(JournalFile **f, bool compress, bool seal);
 
 void journal_file_post_change(JournalFile *f);
+int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t);
 
 void journal_reset_metrics(JournalMetrics *m);
 void journal_default_metrics(JournalMetrics *m, int fd);
index 06847402e0c79216b2d9c35fc374e026f9b7afd0..7639325acff413103d669268395ed5006dc4af85 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,9 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 #include "sd-id128.h"
 #include "sd-journal.h"
@@ -103,18 +101,29 @@ struct sd_journal {
         unsigned current_invalidate_counter, last_invalidate_counter;
         usec_t last_process_usec;
 
+        /* Iterating through unique fields and their data values */
         char *unique_field;
         JournalFile *unique_file;
         uint64_t unique_offset;
 
+        /* Iterating through known fields */
+        JournalFile *fields_file;
+        uint64_t fields_offset;
+        uint64_t fields_hash_table_index;
+        char *fields_buffer;
+        size_t fields_buffer_allocated;
+
         int flags;
 
-        bool on_network;
-        bool no_new_files;
-        bool unique_file_lost; /* File we were iterating over got
-                                  removed, and there were no more
-                                  files, so sd_j_enumerate_unique
-                                  will return a value equal to 0. */
+        bool on_network:1;
+        bool no_new_files:1;
+        bool unique_file_lost:1; /* File we were iterating over got
+                                    removed, and there were no more
+                                    files, so sd_j_enumerate_unique
+                                    will return a value equal to 0. */
+        bool fields_file_lost:1;
+        bool has_runtime_files:1;
+        bool has_persistent_files:1;
 
         size_t data_threshold;
 
@@ -127,8 +136,5 @@ struct sd_journal {
 char *journal_make_match_string(sd_journal *j);
 void journal_print_header(sd_journal *j);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_journal*, sd_journal_close);
-#define _cleanup_journal_close_ _cleanup_(sd_journal_closep)
-
 #define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval)                     \
         for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
index 257ddb302b774bc1abddfe08dc31349f32af43f3..e38730d65c1207f28bf9fdecf6709dfee0aa315f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7d14e8754b3526a4957aa0c3c48b55e1ffd4387e..ef3908556161fb06e0356153685ec532f3541824 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index fa5dee73c31f027b58a8ac16feb9ec7482bca107..c7d670f4fff912430d0d4f32b7ab45cfbad19086 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -225,8 +223,8 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
         assert_return(iov, -EINVAL);
         assert_return(n > 0, -EINVAL);
 
-        w = alloca(sizeof(struct iovec) * n * 5 + 3);
-        l = alloca(sizeof(uint64_t) * n);
+        w = newa(struct iovec, n * 5 + 3);
+        l = newa(uint64_t, n);
 
         for (i = 0; i < n; i++) {
                 char *c, *nl;
@@ -337,7 +335,11 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
                         return r;
         }
 
-        return send_one_fd(fd, buffer_fd, 0);
+        r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0);
+        if (r == -ENOENT)
+                /* Fail silently if the journal is not available */
+                return 0;
+        return r;
 }
 
 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
@@ -368,6 +370,7 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
 
                         xsprintf(error, "ERRNO=%i", _saved_errno_);
 
+                        assert_cc(3 == LOG_ERR);
                         IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
                         IOVEC_SET_STRING(iov[skip+1], buffer);
                         IOVEC_SET_STRING(iov[skip+2], error);
index 4b5fc76eb14f8ad9a62aee52ba88000eff428209..05e97620aee61c744ff6a42c28339238632968db 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 49ab90af9172c07af50470b8aca6719817c1c4fc..1e750a217049be0f54d3a3cd55a38a576951c27b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 715847e0184c243db69f9921380913c30325d458..b968e89bb8db8383add452cb6bbb4da42dcec8c8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e392ab61d7aec5fe42890c8cf168dd723803e157..8f0eaf6daa0b17e434b8a47693d8f8d6c36d58b3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d9a8063d31bbdd110ff1fa03482341bbfe452014..273242bea60e3b78d2a63501cc5a72bcea662a8a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -69,6 +67,8 @@
 #include "strv.h"
 #include "syslog-util.h"
 #include "terminal-util.h"
+#include "udev.h"
+#include "udev-util.h"
 #include "unit-name.h"
 #include "user-util.h"
 
@@ -136,6 +136,8 @@ static enum {
         ACTION_SYNC,
         ACTION_ROTATE,
         ACTION_VACUUM,
+        ACTION_LIST_FIELDS,
+        ACTION_LIST_FIELD_NAMES,
 } arg_action = ACTION_SHOW;
 
 typedef struct BootId {
@@ -145,6 +147,84 @@ typedef struct BootId {
         LIST_FIELDS(struct BootId, boot_list);
 } BootId;
 
+static int add_matches_for_device(sd_journal *j, const char *devpath) {
+        int r;
+        _cleanup_udev_unref_ struct udev *udev = NULL;
+        _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+        struct udev_device *d = NULL;
+        struct stat st;
+
+        assert(j);
+        assert(devpath);
+
+        if (!path_startswith(devpath, "/dev/")) {
+                log_error("Devpath does not start with /dev/");
+                return -EINVAL;
+        }
+
+        udev = udev_new();
+        if (!udev)
+                return log_oom();
+
+        r = stat(devpath, &st);
+        if (r < 0)
+                log_error_errno(errno, "Couldn't stat file: %m");
+
+        d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
+        if (!device)
+                return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+
+        while (d) {
+                _cleanup_free_ char *match = NULL;
+                const char *subsys, *sysname, *devnode;
+
+                subsys = udev_device_get_subsystem(d);
+                if (!subsys) {
+                        d = udev_device_get_parent(d);
+                        continue;
+                }
+
+                sysname = udev_device_get_sysname(d);
+                if (!sysname) {
+                        d = udev_device_get_parent(d);
+                        continue;
+                }
+
+                match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname, NULL);
+                if (!match)
+                        return log_oom();
+
+                r = sd_journal_add_match(j, match, 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to add match: %m");
+
+                devnode = udev_device_get_devnode(d);
+                if (devnode) {
+                        _cleanup_free_ char *match1 = NULL;
+
+                        r = stat(devnode, &st);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode);
+
+                        r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev));
+                        if (r < 0)
+                                return log_oom();
+
+                        r = sd_journal_add_match(j, match1, 0);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to add match: %m");
+                }
+
+                d = udev_device_get_parent(d);
+        }
+
+        r = add_match_this_boot(j, arg_machine);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add match for the current boot: %m");
+
+        return 0;
+}
+
 static void pager_open_if_enabled(void) {
 
         if (arg_no_pager)
@@ -244,6 +324,7 @@ static void help(void) {
                "\nCommands:\n"
                "  -h --help                Show this help text\n"
                "     --version             Show package version\n"
+               "  -N --fields              List all field names currently used\n"
                "  -F --field=FIELD         List all values that a specified field takes\n"
                "     --disk-usage          Show total disk usage of all journal files\n"
                "     --vacuum-size=BYTES   Reduce disk usage below specified size\n"
@@ -340,6 +421,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "unit",           required_argument, NULL, 'u'                },
                 { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
                 { "field",          required_argument, NULL, 'F'                },
+                { "fields",         no_argument,       NULL, 'N'                },
                 { "catalog",        no_argument,       NULL, 'x'                },
                 { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
                 { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
@@ -361,7 +443,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:F:xrM:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -698,9 +780,14 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'F':
+                        arg_action = ACTION_LIST_FIELDS;
                         arg_field = optarg;
                         break;
 
+                case 'N':
+                        arg_action = ACTION_LIST_FIELD_NAMES;
+                        break;
+
                 case 'x':
                         arg_catalog = true;
                         break;
@@ -825,13 +912,12 @@ static int add_matches(sd_journal *j, char **args) {
                         have_term = false;
 
                 } else if (path_is_absolute(*i)) {
-                        _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
+                        _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL;
                         const char *path;
-                        _cleanup_free_ char *interpreter = NULL;
                         struct stat st;
 
                         p = canonicalize_file_name(*i);
-                        path = p ? p : *i;
+                        path = p ?: *i;
 
                         if (lstat(path, &st) < 0)
                                 return log_error_errno(errno, "Couldn't stat file: %m");
@@ -845,34 +931,37 @@ static int add_matches(sd_journal *j, char **args) {
                                                 return log_oom();
 
                                         t = strappend("_COMM=", comm);
+                                        if (!t)
+                                                return log_oom();
 
                                         /* Append _EXE only if the interpreter is not a link.
                                            Otherwise, it might be outdated often. */
-                                        if (lstat(interpreter, &st) == 0 &&
-                                            !S_ISLNK(st.st_mode)) {
+                                        if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
                                                 t2 = strappend("_EXE=", interpreter);
                                                 if (!t2)
                                                         return log_oom();
                                         }
-                                } else
+                                } else {
                                         t = strappend("_EXE=", path);
-                        } else if (S_ISCHR(st.st_mode))
-                                (void) asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
-                        else if (S_ISBLK(st.st_mode))
-                                (void) asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
-                        else {
+                                        if (!t)
+                                                return log_oom();
+                                }
+
+                                r = sd_journal_add_match(j, t, 0);
+
+                                if (r >=0 && t2)
+                                        r = sd_journal_add_match(j, t2, 0);
+
+                        } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
+                                r = add_matches_for_device(j, path);
+                                if (r < 0)
+                                        return r;
+                        } else {
                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
                                 return -EINVAL;
                         }
 
-                        if (!t)
-                                return log_oom();
-
-                        r = sd_journal_add_match(j, t, 0);
-                        if (t2)
-                                r = sd_journal_add_match(j, t2, 0);
                         have_term = true;
-
                 } else {
                         r = sd_journal_add_match(j, *i, 0);
                         have_term = true;
@@ -1136,10 +1225,11 @@ static int add_boot(sd_journal *j) {
                 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
 
                 if (sd_id128_is_null(arg_boot_id))
-                        log_error("Failed to look up boot %+i: %s", arg_boot_offset, reason);
+                        log_error("Data from the specified boot (%+i) is not available: %s",
+                                  arg_boot_offset, reason);
                 else
-                        log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
-                                  SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, reason);
+                        log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s",
+                                  SD_ID128_FORMAT_VAL(arg_boot_id), reason);
 
                 return r == 0 ? -ENODATA : r;
         }
@@ -1766,8 +1856,8 @@ static int access_check(sd_journal *j) {
 }
 
 static int flush_to_var(void) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_close_ int watch_fd = -1;
         int r;
 
@@ -1828,7 +1918,7 @@ static int flush_to_var(void) {
 }
 
 static int send_signal_and_wait(int sig, const char *watch_path) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_close_ int watch_fd = -1;
         usec_t start;
         int r;
@@ -1857,7 +1947,7 @@ static int send_signal_and_wait(int sig, const char *watch_path) {
 
                 /* Let's ask for a sync, but only once. */
                 if (!bus) {
-                        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                         r = bus_connect_system_systemd(&bus);
                         if (r < 0)
@@ -1920,7 +2010,7 @@ static int sync_journal(void) {
 
 int main(int argc, char *argv[]) {
         int r;
-        _cleanup_journal_close_ sd_journal *j = NULL;
+        _cleanup_(sd_journal_closep) sd_journal *j = NULL;
         bool need_seek = false;
         sd_id128_t previous_boot_id;
         bool previous_boot_id_valid = false, first_line = true;
@@ -2002,6 +2092,8 @@ int main(int argc, char *argv[]) {
         case ACTION_DISK_USAGE:
         case ACTION_LIST_BOOTS:
         case ACTION_VACUUM:
+        case ACTION_LIST_FIELDS:
+        case ACTION_LIST_FIELD_NAMES:
                 /* These ones require access to the journal files, continue below. */
                 break;
 
@@ -2084,13 +2176,33 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        case ACTION_LIST_FIELD_NAMES: {
+                const char *field;
+
+                SD_JOURNAL_FOREACH_FIELD(j, field) {
+                        printf("%s\n", field);
+                        n_shown ++;
+                }
+
+                r = 0;
+                goto finish;
+        }
+
         case ACTION_SHOW:
+        case ACTION_LIST_FIELDS:
                 break;
 
         default:
                 assert_not_reached("Unknown action");
         }
 
+        if (arg_boot_offset != 0 &&
+            sd_journal_has_runtime_files(j) > 0 &&
+            sd_journal_has_persistent_files(j) == 0) {
+                log_info("Specifying boot ID has no effect, no persistent journal was found");
+                r = 0;
+                goto finish;
+        }
         /* add_boot() must be called first!
          * It may need to seek the journal to find parent boot IDs. */
         r = add_boot(j);
@@ -2131,10 +2243,12 @@ int main(int argc, char *argv[]) {
                 log_debug("Journal filter: %s", filter);
         }
 
-        if (arg_field) {
+        if (arg_action == ACTION_LIST_FIELDS) {
                 const void *data;
                 size_t size;
 
+                assert(arg_field);
+
                 r = sd_journal_set_data_threshold(j, 0);
                 if (r < 0) {
                         log_error_errno(r, "Failed to unset data size threshold: %m");
@@ -2336,7 +2450,7 @@ int main(int argc, char *argv[]) {
                         flags =
                                 arg_all * OUTPUT_SHOW_ALL |
                                 arg_full * OUTPUT_FULL_WIDTH |
-                                on_tty() * OUTPUT_COLOR |
+                                colors_enabled() * OUTPUT_COLOR |
                                 arg_catalog * OUTPUT_CATALOG |
                                 arg_utc * OUTPUT_UTC;
 
index 3c13fe0d675c56a654709ba9b64348d0d376977c..b2eb8a33ef627b038775fd70beeb137fb9376617 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -397,8 +395,8 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
         sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
         IOVEC_SET_STRING(iov[n_iov++], id_field);
 
-        assert_cc(32 == LOG_AUTH);
-        IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=32");
+        assert_cc(4 == LOG_FAC(LOG_AUTH));
+        IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=4");
         IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_IDENTIFIER=audit");
 
         type_name = audit_type_name_alloca(type);
index 68cdfb3410a91ce5416feadc599e73197c66cc83..8c7457778c189ec2d67fed477da9d8ed8d4aba44 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "socket-util.h"
 #include "journald-server.h"
+#include "socket-util.h"
 
 void server_process_audit_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const union sockaddr_union *sa, socklen_t salen);
 
index 04487c29b5a5217cd751d3c809c6219c3b90e977..fcc9f25814daaf5dec2e5685e7105378ed99dcd5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d8af2267e119fc7cd8364a52a91949da982e6577..dda07e2c289df50c5e1b0edf0d4fb683851793f8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index e048e04716b4cbda59722f4bd4afd00fa38f79de..eb1ac90e98b2956a2becc179cb2c79204a686af6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -158,8 +156,10 @@ static void dev_kmsg_record(Server *s, const char *p, size_t l) {
 
                 /* Did we lose any? */
                 if (serial > *s->kernel_seqnum)
-                        server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages",
-                                              serial - *s->kernel_seqnum);
+                        server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED,
+                                              LOG_MESSAGE("Missed %"PRIu64" kernel messages",
+                                                          serial - *s->kernel_seqnum),
+                                              NULL);
 
                 /* Make sure we never read this one again. Note that
                  * we always store the next message serial we expect
index 9a9d089967dc53411b304bbab05cdf25ec0a14e8..dab49f1e8cce174d11e99851fa1630b6db920468 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 69a685c06f26201139049ff9c295375595de6722..3d8f05996b5280ea53bf4fae5de947a0f2d78bb4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -480,7 +478,7 @@ int server_open_native_socket(Server*s) {
                 return log_error_errno(errno, "SO_PASSCRED failed: %m");
 
 #ifdef HAVE_SELINUX
-        if (mac_selinux_use()) {
+        if (mac_selinux_have()) {
                 r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
                 if (r < 0)
                         log_warning_errno(errno, "SO_PASSSEC failed: %m");
@@ -495,5 +493,9 @@ int server_open_native_socket(Server*s) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add native server fd to event loop: %m");
 
+        r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5);
+        if (r < 0)
+                return log_error_errno(r, "Failed to adjust native event source priority: %m");
+
         return 0;
 }
index 2f9d458fb5b3d60948a5845ba5374c34286ec02a..c13b80aa4f710f50c2d7a03572e18b454998d072 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 1c406aef8ebd2e5e9bcc6351e03ad2ff7757d228..6f6a90fe4e21b44f977cda9903cc8a14d20ba869 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 466239d3c6807d2e03cf728ec7a1e0dd2621c220..bb0abb7ee94bdaac43834c41dadbfe35f5b38fa2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7d11a568aa1ce42463317e7550667f5eedf807d2..ee2db8d29fe5e17c70f75c5f04ecfd81d4dc7780 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "selinux-util.h"
 #include "signal-util.h"
 #include "socket-util.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "user-util.h"
+#include "log.h"
 
 #define USER_JOURNALS_MAX 1024
 
@@ -82,6 +82,9 @@
 
 #define NOTIFY_SNDBUF_SIZE (8*1024*1024)
 
+/* The period to insert between posting changes for coalescing */
+#define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC)
+
 static int determine_space_for(
                 Server *s,
                 JournalMetrics *metrics,
@@ -142,7 +145,7 @@ static int determine_space_for(
                 sum += (uint64_t) st.st_blocks * 512UL;
         }
 
-        /* If request, then let's bump the min_use limit to the
+        /* If requested, then let's bump the min_use limit to the
          * current usage on disk. We do this when starting up and
          * first opening the journal files. This way sudden spikes in
          * disk usage will not cause journald to vacuum files without
@@ -162,19 +165,31 @@ static int determine_space_for(
         if (verbose) {
                 char    fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
                         fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX];
+                format_bytes(fb1, sizeof(fb1), sum);
+                format_bytes(fb2, sizeof(fb2), metrics->max_use);
+                format_bytes(fb3, sizeof(fb3), metrics->keep_free);
+                format_bytes(fb4, sizeof(fb4), ss_avail);
+                format_bytes(fb5, sizeof(fb5), s->cached_space_limit);
+                format_bytes(fb6, sizeof(fb6), s->cached_space_available);
 
                 server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
-                                      "%s (%s) is currently using %s.\n"
-                                      "Maximum allowed usage is set to %s.\n"
-                                      "Leaving at least %s free (of currently available %s of space).\n"
-                                      "Enforced usage limit is thus %s, of which %s are still available.",
-                                      name, path,
-                                      format_bytes(fb1, sizeof(fb1), sum),
-                                      format_bytes(fb2, sizeof(fb2), metrics->max_use),
-                                      format_bytes(fb3, sizeof(fb3), metrics->keep_free),
-                                      format_bytes(fb4, sizeof(fb4), ss_avail),
-                                      format_bytes(fb5, sizeof(fb5), s->cached_space_limit),
-                                      format_bytes(fb6, sizeof(fb6), s->cached_space_available));
+                                      LOG_MESSAGE("%s (%s) is %s, max %s, %s free.",
+                                                  name, path, fb1, fb5, fb6),
+                                      "JOURNAL_NAME=%s", name,
+                                      "JOURNAL_PATH=%s", path,
+                                      "CURRENT_USE=%"PRIu64, sum,
+                                      "CURRENT_USE_PRETTY=%s", fb1,
+                                      "MAX_USE=%"PRIu64, metrics->max_use,
+                                      "MAX_USE_PRETTY=%s", fb2,
+                                      "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free,
+                                      "DISK_KEEP_FREE_PRETTY=%s", fb3,
+                                      "DISK_AVAILABLE=%"PRIu64, ss_avail,
+                                      "DISK_AVAILABLE_PRETTY=%s", fb4,
+                                      "LIMIT=%"PRIu64, s->cached_space_limit,
+                                      "LIMIT_PRETTY=%s", fb5,
+                                      "AVAILABLE=%"PRIu64, s->cached_space_available,
+                                      "AVAILABLE_PRETTY=%s", fb6,
+                                      NULL);
         }
 
         if (available)
@@ -204,59 +219,52 @@ static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t
         return determine_space_for(s, metrics, path, name, verbose, patch_min_use, available, limit);
 }
 
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
-        int r;
+static void server_add_acls(JournalFile *f, uid_t uid) {
 #ifdef HAVE_ACL
-        _cleanup_(acl_freep) acl_t acl = NULL;
-        acl_entry_t entry;
-        acl_permset_t permset;
+        int r;
 #endif
-
         assert(f);
 
-        r = fchmod(f->fd, 0640);
-        if (r < 0)
-                log_warning_errno(errno, "Failed to fix access mode on %s, ignoring: %m", f->path);
-
 #ifdef HAVE_ACL
         if (uid <= SYSTEM_UID_MAX)
                 return;
 
-        acl = acl_get_fd(f->fd);
-        if (!acl) {
-                log_warning_errno(errno, "Failed to read ACL on %s, ignoring: %m", f->path);
-                return;
-        }
+        r = add_acls_for_user(f->fd, uid);
+        if (r < 0)
+                log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->path);
+#endif
+}
 
-        r = acl_find_uid(acl, uid, &entry);
-        if (r <= 0) {
+static int open_journal(
+                Server *s,
+                bool reliably,
+                const char *fname,
+                int flags,
+                bool seal,
+                JournalMetrics *metrics,
+                JournalFile **ret) {
+        int r;
+        JournalFile *f;
 
-                if (acl_create_entry(&acl, &entry) < 0 ||
-                    acl_set_tag_type(entry, ACL_USER) < 0 ||
-                    acl_set_qualifier(entry, &uid) < 0) {
-                        log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
-                        return;
-                }
-        }
+        assert(s);
+        assert(fname);
+        assert(ret);
 
-        /* We do not recalculate the mask unconditionally here,
-         * so that the fchmod() mask above stays intact. */
-        if (acl_get_permset(entry, &permset) < 0 ||
-            acl_add_perm(permset, ACL_READ) < 0) {
-                log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
-                return;
-        }
+        if (reliably)
+                r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f);
+        else
+                r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f);
+        if (r < 0)
+                return r;
 
-        r = calc_acl_mask_if_needed(&acl);
+        r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
         if (r < 0) {
-                log_warning_errno(r, "Failed to patch ACL on %s, ignoring: %m", f->path);
-                return;
+                journal_file_close(f);
+                return r;
         }
 
-        if (acl_set_fd(f->fd, acl) < 0)
-                log_warning_errno(errno, "Failed to set ACL on %s, ignoring: %m", f->path);
-
-#endif
+        *ret = f;
+        return r;
 }
 
 static JournalFile* find_journal(Server *s, uid_t uid) {
@@ -297,11 +305,11 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
                 journal_file_close(f);
         }
 
-        r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
+        r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &f);
         if (r < 0)
                 return s->system_journal;
 
-        server_fix_perms(s, f, uid);
+        server_add_acls(f, uid);
 
         r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f);
         if (r < 0) {
@@ -332,7 +340,7 @@ static int do_rotate(
                 else
                         log_error_errno(r, "Failed to create new %s journal: %m", name);
         else
-                server_fix_perms(s, *f, uid);
+                server_add_acls(*f, uid);
 
         return r;
 }
@@ -707,7 +715,7 @@ static void dispatch_message_real(
                 }
 
 #ifdef HAVE_SELINUX
-                if (mac_selinux_use()) {
+                if (mac_selinux_have()) {
                         if (label) {
                                 x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
 
@@ -847,37 +855,56 @@ static void dispatch_message_real(
 
 void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
         char mid[11 + 32 + 1];
-        char buffer[16 + LINE_MAX + 1];
-        struct iovec iovec[N_IOVEC_META_FIELDS + 6];
-        int n = 0;
+        struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS];
+        unsigned n = 0, m;
+        int r;
         va_list ap;
         struct ucred ucred = {};
 
         assert(s);
         assert(format);
 
+        assert_cc(3 == LOG_FAC(LOG_DAEMON));
         IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3");
         IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald");
 
-        IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
         IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
-
-        memcpy(buffer, "MESSAGE=", 8);
-        va_start(ap, format);
-        vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
-        va_end(ap);
-        IOVEC_SET_STRING(iovec[n++], buffer);
+        assert_cc(6 == LOG_INFO);
+        IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
 
         if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
                 snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id));
                 IOVEC_SET_STRING(iovec[n++], mid);
         }
 
+        m = n;
+
+        va_start(ap, format);
+        r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, false, 0, format, ap);
+        /* Error handling below */
+        va_end(ap);
+
         ucred.pid = getpid();
         ucred.uid = getuid();
         ucred.gid = getgid();
 
-        dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
+        if (r >= 0)
+                dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
+
+        while (m < n)
+                free(iovec[m++].iov_base);
+
+        if (r < 0) {
+                /* We failed to format the message. Emit a warning instead. */
+                char buf[LINE_MAX];
+
+                xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r));
+
+                n = 3;
+                IOVEC_SET_STRING(iovec[n++], "PRIORITY=4");
+                IOVEC_SET_STRING(iovec[n++], buf);
+                dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
+        }
 }
 
 void server_dispatch_message(
@@ -940,7 +967,8 @@ void server_dispatch_message(
         /* Write a suppression message if we suppressed something */
         if (rl > 1)
                 server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
-                                      "Suppressed %u messages from %s", rl - 1, path);
+                                      LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, path),
+                                      NULL);
 
 finish:
         dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
@@ -969,9 +997,9 @@ static int system_journal_open(Server *s, bool flush_requested) {
                 (void) mkdir(fn, 0755);
 
                 fn = strjoina(fn, "/system.journal");
-                r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
+                r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal);
                 if (r >= 0) {
-                        server_fix_perms(s, s->system_journal, 0);
+                        server_add_acls(s->system_journal, 0);
                         (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL);
                 } else if (r < 0) {
                         if (r != -ENOENT && r != -EROFS)
@@ -992,7 +1020,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
                          * if it already exists, so that we can flush
                          * it into the system journal */
 
-                        r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+                        r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal);
                         if (r < 0) {
                                 if (r != -ENOENT)
                                         log_warning_errno(r, "Failed to open runtime journal: %m");
@@ -1009,13 +1037,13 @@ static int system_journal_open(Server *s, bool flush_requested) {
                         (void) mkdir("/run/log/journal", 0755);
                         (void) mkdir_parents(fn, 0750);
 
-                        r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
+                        r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to open runtime journal: %m");
                 }
 
                 if (s->runtime_journal) {
-                        server_fix_perms(s, s->runtime_journal, 0);
+                        server_add_acls(s->runtime_journal, 0);
                         (void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL);
                 }
         }
@@ -1112,7 +1140,11 @@ finish:
 
         sd_journal_close(j);
 
-        server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n);
+        server_driver_message(s, SD_ID128_NULL,
+                              LOG_MESSAGE("Time spent on flushing to /var is %s for %u entries.",
+                                          format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0),
+                                          n),
+                              NULL);
 
         return r;
 }
@@ -1369,7 +1401,7 @@ static int server_parse_proc_cmdline(Server *s) {
 
         p = line;
         for(;;) {
-                _cleanup_free_ char *word;
+                _cleanup_free_ char *word = NULL;
 
                 r = extract_first_word(&p, &word, NULL, 0);
                 if (r < 0)
index dcc21bb7c3db57f4a6c161665d610888c7b8ddf0..b9551dda1bea4b8287ca63f0868aa27927fab018 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -157,9 +155,10 @@ struct Server {
 #define N_IOVEC_KERNEL_FIELDS 64
 #define N_IOVEC_UDEV_FIELDS 32
 #define N_IOVEC_OBJECT_FIELDS 12
+#define N_IOVEC_PAYLOAD_FIELDS 15
 
 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid);
-void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,4);
+void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_;
 
 /* gperf lookup function */
 const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length);
@@ -174,7 +173,6 @@ int config_parse_split_mode(const char *unit, const char *filename, unsigned lin
 const char *split_mode_to_string(SplitMode s) _const_;
 SplitMode split_mode_from_string(const char *s) _pure_;
 
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid);
 int server_init(Server *s);
 void server_done(Server *s);
 void server_sync(Server *s);
index fb800782fb688eab716663e20f398ee7370e6570..6e8b405b538e5a9d0e64ae3319c3af4b8a660405 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -239,14 +237,14 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
         assert(s);
         assert(p);
 
-        if (isempty(p))
-                return 0;
-
         priority = s->priority;
 
         if (s->level_prefix)
                 syslog_parse_priority(&p, &priority, false);
 
+        if (isempty(p))
+                return 0;
+
         if (s->forward_to_syslog || s->server->forward_to_syslog)
                 server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
 
@@ -286,10 +284,12 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
 
 static int stdout_stream_line(StdoutStream *s, char *p) {
         int r;
+        char *orig;
 
         assert(s);
         assert(p);
 
+        orig = p;
         p = strstrip(p);
 
         switch (s->state) {
@@ -378,7 +378,7 @@ static int stdout_stream_line(StdoutStream *s, char *p) {
                 return 0;
 
         case STDOUT_STREAM_RUNNING:
-                return stdout_stream_log(s, p);
+                return stdout_stream_log(s, orig);
         }
 
         assert_not_reached("Unknown stream state");
@@ -491,7 +491,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_use()) {
+        if (mac_selinux_have()) {
                 r = getpeersec(fd, &stream->label);
                 if (r < 0 && r != -EOPNOTSUPP)
                         (void) log_warning_errno(r, "Failed to determine peer security context: %m");
@@ -731,7 +731,7 @@ int server_open_stdout_socket(Server *s) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
 
-        r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+10);
+        r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
         if (r < 0)
                 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
 
index e3497f0dedb02c64209030a338cc1628bc77f32e..db4c67fae3154a972069eeded52273f350e9d4cb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f3ac1a7ae061b4a9315e2e8c891517fef1cf21ec..5153fd0cce16d8748c072bf768450ef7378c0d27 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -326,7 +324,7 @@ void server_process_syslog_message(
         size_t label_len) {
 
         char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
-             syslog_facility[sizeof("SYSLOG_FACILITY") + DECIMAL_STR_MAX(int)];
+             syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
         const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
         struct iovec iovec[N_IOVEC_META_FIELDS + 6];
         unsigned n = 0;
@@ -357,11 +355,11 @@ void server_process_syslog_message(
 
         IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
 
-        sprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
+        xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK);
         IOVEC_SET_STRING(iovec[n++], syslog_priority);
 
         if (priority & LOG_FACMASK) {
-                sprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
+                xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
                 IOVEC_SET_STRING(iovec[n++], syslog_facility);
         }
 
@@ -415,7 +413,7 @@ int server_open_syslog_socket(Server *s) {
                 return log_error_errno(errno, "SO_PASSCRED failed: %m");
 
 #ifdef HAVE_SELINUX
-        if (mac_selinux_use()) {
+        if (mac_selinux_have()) {
                 r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
                 if (r < 0)
                         log_warning_errno(errno, "SO_PASSSEC failed: %m");
@@ -430,6 +428,10 @@ int server_open_syslog_socket(Server *s) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add syslog server fd to event loop: %m");
 
+        r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5);
+        if (r < 0)
+                return log_error_errno(r, "Failed to adjust syslog event source priority: %m");
+
         return 0;
 }
 
@@ -444,7 +446,10 @@ void server_maybe_warn_forward_syslog_missed(Server *s) {
         if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n)
                 return;
 
-        server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed);
+        server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED,
+                              LOG_MESSAGE("Forwarding to syslog missed %u messages.",
+                                          s->n_forward_syslog_missed),
+                              NULL);
 
         s->n_forward_syslog_missed = 0;
         s->last_warn_forward_syslog_missed = n;
index 3774ebdf0562f1d773c880ea84251bc6b9a692df..46ad7153145c64be2d04658ad4f7833f5887b299 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 88bea3b86e07e9ac8ae63fa98b35711a5a9cfd92..4d91fafffebb3de911c4e4d997491c1aa185eb8e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 45c52854a0c6f8c9fae78f8d80760ec74bf7b4ad..ebc2b89fa88cbeb9e8747721545b2d294c732818 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index b9f5c099e1c31fd3ae9f895fb2d4ff712664ea97..272acb71c44db5c291bcaed315e3263bd632fd80 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -58,7 +56,9 @@ int main(int argc, char *argv[]) {
         server_flush_dev_kmsg(&server);
 
         log_debug("systemd-journald running as pid "PID_FMT, getpid());
-        server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
+        server_driver_message(&server, SD_MESSAGE_JOURNAL_START,
+                              LOG_MESSAGE("Journal started"),
+                              NULL);
 
         for (;;) {
                 usec_t t = USEC_INFINITY, n;
@@ -109,7 +109,9 @@ int main(int argc, char *argv[]) {
         }
 
         log_debug("systemd-journald stopped as pid "PID_FMT, getpid());
-        server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
+        server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP,
+                              LOG_MESSAGE("Journal stopped"),
+                              NULL);
 
 finish:
         server_done(&server);
index 3224473a6a857637f2a929359373d0be9a6d7db3..787921ffbf767c56053c373f8723bd8488823f7e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 #include <inttypes.h>
index 5a07ddda764552df5f4275ec273d71b5e1d4a858..9c0ce8ccbff9e3477a52cabc1241f27de460232c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,9 +38,9 @@ typedef struct FileDescriptor FileDescriptor;
 struct Window {
         MMapCache *cache;
 
-        bool invalidated;
-        bool keep_always;
-        bool in_unused;
+        bool invalidated:1;
+        bool keep_always:1;
+        bool in_unused:1;
 
         int prot;
         void *ptr;
@@ -78,7 +76,6 @@ struct MMapCache {
 
         unsigned n_hit, n_missed;
 
-
         Hashmap *fds;
         Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
 
@@ -174,10 +171,11 @@ _pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset,
                 offset + size <= w->offset + w->size;
 }
 
-static Window *window_add(MMapCache *m) {
+static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) {
         Window *w;
 
         assert(m);
+        assert(fd);
 
         if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
 
@@ -195,6 +193,15 @@ static Window *window_add(MMapCache *m) {
         }
 
         w->cache = m;
+        w->fd = fd;
+        w->prot = prot;
+        w->keep_always = keep_always;
+        w->offset = offset;
+        w->size = size;
+        w->ptr = ptr;
+
+        LIST_PREPEND(by_fd, fd->windows, w);
+
         return w;
 }
 
@@ -348,7 +355,10 @@ static void mmap_cache_free(MMapCache *m) {
 }
 
 MMapCache* mmap_cache_unref(MMapCache *m) {
-        assert(m);
+
+        if (!m)
+                return NULL;
+
         assert(m->n_ref > 0);
 
         m->n_ref --;
@@ -405,7 +415,7 @@ static int try_context(
         if (c->window->fd->sigbus)
                 return -EIO;
 
-        c->window->keep_always |= keep_always;
+        c->window->keep_always = c->window->keep_always || keep_always;
 
         *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
         return 1;
@@ -451,12 +461,39 @@ static int find_mmap(
                 return -ENOMEM;
 
         context_attach_window(c, w);
-        w->keep_always += keep_always;
+        w->keep_always = w->keep_always || keep_always;
 
         *ret = (uint8_t*) w->ptr + (offset - w->offset);
         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) {
+        void *ptr;
+
+        assert(m);
+        assert(fd >= 0);
+        assert(res);
+
+        for (;;) {
+                int r;
+
+                ptr = mmap(addr, size, prot, flags, fd, offset);
+                if (ptr != MAP_FAILED)
+                        break;
+                if (errno != ENOMEM)
+                        return -errno;
+
+                r = make_room(m);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -ENOMEM;
+        }
+
+        *res = ptr;
+        return 0;
+}
+
 static int add_mmap(
                 MMapCache *m,
                 int fd,
@@ -510,19 +547,9 @@ static int add_mmap(
                         wsize = PAGE_ALIGN(st->st_size - woffset);
         }
 
-        for (;;) {
-                d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
-                if (d != MAP_FAILED)
-                        break;
-                if (errno != ENOMEM)
-                        return -errno;
-
-                r = make_room(m);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        return -ENOMEM;
-        }
+        r = mmap_try_harder(m, NULL, fd, prot, MAP_SHARED, woffset, wsize, &d);
+        if (r < 0)
+                return r;
 
         c = context_add(m, context);
         if (!c)
@@ -532,19 +559,10 @@ static int add_mmap(
         if (!f)
                 goto outofmem;
 
-        w = window_add(m);
+        w = window_add(m, f, prot, keep_always, woffset, wsize, d);
         if (!w)
                 goto outofmem;
 
-        w->keep_always = keep_always;
-        w->ptr = d;
-        w->offset = woffset;
-        w->prot = prot;
-        w->size = wsize;
-        w->fd = f;
-
-        LIST_PREPEND(by_fd, f->windows, w);
-
         context_detach_window(c);
         c->window = w;
         LIST_PREPEND(by_window, w->contexts, c);
index 37ea7b4a9c839b604f63e09d8e395b34730dd54b..199d944647938199167b1209317032047680f968 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 5cde7f17f7d34dad34879a607cf941241cfc7aa1..5a2a28a8d425aff7be6d1fc55fbf31ba8fa62a10 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -1292,6 +1290,12 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
                 return 0;
 
         path = strjoina(prefix, "/", filename);
+
+        if (!j->has_runtime_files && path_startswith(path, "/run/log/journal"))
+                j->has_runtime_files = true;
+        else if (!j->has_persistent_files && path_startswith(path, "/var/log/journal"))
+                j->has_persistent_files = true;
+
         return add_any_file(j, path);
 }
 
@@ -1332,6 +1336,13 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
                         j->unique_file_lost = true;
         }
 
+        if (j->fields_file == f) {
+                j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path);
+                j->fields_offset = 0;
+                if (!j->fields_file)
+                        j->fields_file_lost = true;
+        }
+
         journal_file_close(f);
 
         j->current_invalidate_counter ++;
@@ -1800,6 +1811,7 @@ _public_ void sd_journal_close(sd_journal *j) {
         free(j->path);
         free(j->prefix);
         free(j->unique_field);
+        free(j->fields_buffer);
         free(j);
 }
 
@@ -1940,10 +1952,14 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
                 compression = o->object.flags & OBJECT_COMPRESSION_MASK;
                 if (compression) {
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
-                        if (decompress_startswith(compression,
+                        r = decompress_startswith(compression,
                                                   o->data.payload, l,
                                                   &f->compress_buffer, &f->compress_buffer_size,
-                                                  field, field_length, '=')) {
+                                                  field, field_length, '=');
+                        if (r < 0)
+                                log_debug_errno(r, "Cannot decompress %s object of length %zu at offset "OFSfmt": %m",
+                                                object_compressed_to_string(compression), l, p);
+                        else if (r > 0) {
 
                                 size_t rsize;
 
@@ -2502,24 +2518,20 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
                  * traversed files. */
                 found = false;
                 ORDERED_HASHMAP_FOREACH(of, j->files, i) {
-                        Object *oo;
-                        uint64_t op;
-
                         if (of == j->unique_file)
                                 break;
 
-                        /* Skip this file it didn't have any fields
-                         * indexed */
-                        if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) &&
-                            le64toh(of->header->n_fields) <= 0)
+                        /* Skip this file it didn't have any fields indexed */
+                        if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
                                 continue;
 
-                        r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), &oo, &op);
+                        r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), NULL, NULL);
                         if (r < 0)
                                 return r;
-
-                        if (r > 0)
+                        if (r > 0) {
                                 found = true;
+                                break;
+                        }
                 }
 
                 if (found)
@@ -2542,6 +2554,154 @@ _public_ void sd_journal_restart_unique(sd_journal *j) {
         j->unique_file_lost = false;
 }
 
+_public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) {
+        int r;
+
+        assert_return(j, -EINVAL);
+        assert_return(!journal_pid_changed(j), -ECHILD);
+        assert_return(field, -EINVAL);
+
+        if (!j->fields_file) {
+                if (j->fields_file_lost)
+                        return 0;
+
+                j->fields_file = ordered_hashmap_first(j->files);
+                if (!j->fields_file)
+                        return 0;
+
+                j->fields_hash_table_index = 0;
+                j->fields_offset = 0;
+        }
+
+        for (;;) {
+                JournalFile *f, *of;
+                Iterator i;
+                uint64_t m;
+                Object *o;
+                size_t sz;
+                bool found;
+
+                f = j->fields_file;
+
+                if (j->fields_offset == 0) {
+                        bool eof = false;
+
+                        /* We are not yet positioned at any field. Let's pick the first one */
+                        r = journal_file_map_field_hash_table(f);
+                        if (r < 0)
+                                return r;
+
+                        m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
+                        for (;;) {
+                                if (j->fields_hash_table_index >= m) {
+                                        /* Reached the end of the hash table, go to the next file. */
+                                        eof = true;
+                                        break;
+                                }
+
+                                j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset);
+
+                                if (j->fields_offset != 0)
+                                        break;
+
+                                /* Empty hash table bucket, go to next one */
+                                j->fields_hash_table_index++;
+                        }
+
+                        if (eof) {
+                                /* Proceed with next file */
+                                j->fields_file = ordered_hashmap_next(j->files, f->path);
+                                if (!j->fields_file) {
+                                        *field = NULL;
+                                        return 0;
+                                }
+
+                                j->fields_offset = 0;
+                                j->fields_hash_table_index = 0;
+                                continue;
+                        }
+
+                } else {
+                        /* We are already positioned at a field. If so, let's figure out the next field from it */
+
+                        r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o);
+                        if (r < 0)
+                                return r;
+
+                        j->fields_offset = le64toh(o->field.next_hash_offset);
+                        if (j->fields_offset == 0) {
+                                /* Reached the end of the hash table chain */
+                                j->fields_hash_table_index++;
+                                continue;
+                        }
+                }
+
+                /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */
+                r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o);
+                if (r < 0)
+                        return r;
+
+                /* Because we used OBJECT_UNUSED above, we need to do our type check manually */
+                if (o->object.type != OBJECT_FIELD) {
+                        log_debug("%s:offset " OFSfmt ": object has type %i, expected %i", f->path, j->fields_offset, o->object.type, OBJECT_FIELD);
+                        return -EBADMSG;
+                }
+
+                sz = le64toh(o->object.size) - offsetof(Object, field.payload);
+
+                /* Let's see if we already returned this field name before. */
+                found = false;
+                ORDERED_HASHMAP_FOREACH(of, j->files, i) {
+                        if (of == f)
+                                break;
+
+                        /* Skip this file it didn't have any fields indexed */
+                        if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
+                                continue;
+
+                        r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                found = true;
+                                break;
+                        }
+                }
+
+                if (found)
+                        continue;
+
+                /* Check if this is really a valid string containing no NUL byte */
+                if (memchr(o->field.payload, 0, sz))
+                        return -EBADMSG;
+
+                if (sz > j->data_threshold)
+                        sz = j->data_threshold;
+
+                if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1))
+                        return -ENOMEM;
+
+                memcpy(j->fields_buffer, o->field.payload, sz);
+                j->fields_buffer[sz] = 0;
+
+                if (!field_is_valid(j->fields_buffer))
+                        return -EBADMSG;
+
+                *field = j->fields_buffer;
+                return 1;
+        }
+}
+
+_public_ void sd_journal_restart_fields(sd_journal *j) {
+        if (!j)
+                return;
+
+        j->fields_file = NULL;
+        j->fields_hash_table_index = 0;
+        j->fields_offset = 0;
+        j->fields_file_lost = false;
+}
+
 _public_ int sd_journal_reliable_fd(sd_journal *j) {
         assert_return(j, -EINVAL);
         assert_return(!journal_pid_changed(j), -ECHILD);
@@ -2626,3 +2786,15 @@ _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
         *sz = j->data_threshold;
         return 0;
 }
+
+_public_ int sd_journal_has_runtime_files(sd_journal *j) {
+        assert_return(j, -EINVAL);
+
+        return j->has_runtime_files;
+}
+
+_public_ int sd_journal_has_persistent_files(sd_journal *j) {
+        assert_return(j, -EINVAL);
+
+        return j->has_persistent_files;
+}
diff --git a/src/journal/stacktrace.c b/src/journal/stacktrace.c
deleted file mode 100644 (file)
index 4305462..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  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 <dwarf.h>
-#include <elfutils/libdwfl.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "macro.h"
-#include "stacktrace.h"
-#include "string-util.h"
-#include "util.h"
-
-#define FRAMES_MAX 64
-#define THREADS_MAX 64
-
-struct stack_context {
-        FILE *f;
-        Dwfl *dwfl;
-        Elf *elf;
-        unsigned n_thread;
-        unsigned n_frame;
-};
-
-static int frame_callback(Dwfl_Frame *frame, void *userdata) {
-        struct stack_context *c = userdata;
-        Dwarf_Addr pc, pc_adjusted, bias = 0;
-        _cleanup_free_ Dwarf_Die *scopes = NULL;
-        const char *fname = NULL, *symbol = NULL;
-        Dwfl_Module *module;
-        bool is_activation;
-
-        assert(frame);
-        assert(c);
-
-        if (c->n_frame >= FRAMES_MAX)
-                return DWARF_CB_ABORT;
-
-        if (!dwfl_frame_pc(frame, &pc, &is_activation))
-                return DWARF_CB_ABORT;
-
-        pc_adjusted = pc - (is_activation ? 0 : 1);
-
-        module = dwfl_addrmodule(c->dwfl, pc_adjusted);
-        if (module) {
-                Dwarf_Die *s, *cudie;
-                int n;
-
-                cudie = dwfl_module_addrdie(module, pc_adjusted, &bias);
-                if (cudie) {
-                        n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes);
-                        for (s = scopes; s < scopes + n; s++) {
-                                if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) {
-                                        Dwarf_Attribute *a, space;
-
-                                        a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space);
-                                        if (!a)
-                                                a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space);
-                                        if (a)
-                                                symbol = dwarf_formstring(a);
-                                        if (!symbol)
-                                                symbol = dwarf_diename(s);
-
-                                        if (symbol)
-                                                break;
-                                }
-                        }
-                }
-
-                if (!symbol)
-                        symbol = dwfl_module_addrname(module, pc_adjusted);
-
-                fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-        }
-
-        fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname));
-        c->n_frame ++;
-
-        return DWARF_CB_OK;
-}
-
-static int thread_callback(Dwfl_Thread *thread, void *userdata) {
-        struct stack_context *c = userdata;
-        pid_t tid;
-
-        assert(thread);
-        assert(c);
-
-        if (c->n_thread >= THREADS_MAX)
-                return DWARF_CB_ABORT;
-
-        if (c->n_thread != 0)
-                fputc('\n', c->f);
-
-        c->n_frame = 0;
-
-        tid = dwfl_thread_tid(thread);
-        fprintf(c->f, "Stack trace of thread " PID_FMT ":\n", tid);
-
-        if (dwfl_thread_getframes(thread, frame_callback, c) < 0)
-                return DWARF_CB_ABORT;
-
-        c->n_thread ++;
-
-        return DWARF_CB_OK;
-}
-
-int coredump_make_stack_trace(int fd, const char *executable, char **ret) {
-
-        static const Dwfl_Callbacks callbacks = {
-                .find_elf = dwfl_build_id_find_elf,
-                .find_debuginfo = dwfl_standard_find_debuginfo,
-        };
-
-        struct stack_context c = {};
-        char *buf = NULL;
-        size_t sz = 0;
-        int r;
-
-        assert(fd >= 0);
-        assert(ret);
-
-        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
-                return -errno;
-
-        c.f = open_memstream(&buf, &sz);
-        if (!c.f)
-                return -ENOMEM;
-
-        elf_version(EV_CURRENT);
-
-        c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
-        if (!c.elf) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        c.dwfl = dwfl_begin(&callbacks);
-        if (!c.dwfl) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) {
-                r = -EINVAL;
-                goto finish;
-        }
-
-        c.f = safe_fclose(c.f);
-
-        *ret = buf;
-        buf = NULL;
-
-        r = 0;
-
-finish:
-        if (c.dwfl)
-                dwfl_end(c.dwfl);
-
-        if (c.elf)
-                elf_end(c.elf);
-
-        safe_fclose(c.f);
-
-        free(buf);
-
-        return r;
-}
diff --git a/src/journal/stacktrace.h b/src/journal/stacktrace.h
deleted file mode 100644 (file)
index 189e5c4..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-int coredump_make_stack_trace(int fd, const char *executable, char **ret);
index 7946cf3c419cab843e1432543ee4c6e6e32529c0..88a2e6d9d9242825e5fd55f79963c6329ee2dc6e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 25980b7744e794d70a9ae6072bb2ec2558f6b7b2..da6fcbca4d267867a6aabfd14e1b83ed092d19dd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -46,61 +44,135 @@ static const char *no_catalog_dirs[] = {
         NULL
 };
 
-static void test_import(Hashmap *h, struct strbuf *sb,
-                        const char* contents, ssize_t size, int code) {
+static Hashmap * test_import(const char* contents, ssize_t size, int code) {
         int r;
         char name[] = "/tmp/test-catalog.XXXXXX";
         _cleanup_close_ int fd;
+        Hashmap *h;
+
+        if (size < 0)
+                size = strlen(contents);
+
+        assert_se(h = hashmap_new(&catalog_hash_ops));
 
         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
         assert_se(fd >= 0);
         assert_se(write(fd, contents, size) == size);
 
-        r = catalog_import_file(h, sb, name);
+        r = catalog_import_file(h, name);
         assert_se(r == code);
 
         unlink(name);
+
+        return h;
 }
 
-static void test_catalog_importing(void) {
-        Hashmap *h;
-        struct strbuf *sb;
+static void test_catalog_import_invalid(void) {
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
 
-        assert_se(h = hashmap_new(&catalog_hash_ops));
-        assert_se(sb = strbuf_new());
-
-#define BUF "xxx"
-        test_import(h, sb, BUF, sizeof(BUF), -EINVAL);
-#undef BUF
+        h = test_import("xxx", -1, -EINVAL);
         assert_se(hashmap_isempty(h));
-        log_debug("----------------------------------------");
+}
 
-#define BUF \
+static void test_catalog_import_badid(void) {
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
+        const char *input =
 "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \
 "Subject: message\n" \
 "\n" \
-"payload\n"
-        test_import(h, sb, BUF, sizeof(BUF), -EINVAL);
-#undef BUF
+"payload\n";
+        h = test_import(input, -1, -EINVAL);
+}
 
-        log_debug("----------------------------------------");
+static void test_catalog_import_one(void) {
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
+        char *payload;
+        Iterator j;
 
-#define BUF \
+        const char *input =
 "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
 "Subject: message\n" \
 "\n" \
-"payload\n"
-        test_import(h, sb, BUF, sizeof(BUF), 0);
-#undef BUF
+"payload\n";
+        const char *expect =
+"Subject: message\n" \
+"\n" \
+"payload\n";
 
+        h = test_import(input, -1, 0);
         assert_se(hashmap_size(h) == 1);
 
-        log_debug("----------------------------------------");
+        HASHMAP_FOREACH(payload, h, j) {
+                assert_se(streq(expect, payload));
+        }
+}
+
+static void test_catalog_import_merge(void) {
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
+        char *payload;
+        Iterator j;
+
+        const char *input =
+"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
+"Subject: message\n" \
+"Defined-By: me\n" \
+"\n" \
+"payload\n" \
+"\n" \
+"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
+"Subject: override subject\n" \
+"X-Header: hello\n" \
+"\n" \
+"override payload\n";
+
+        const char *combined =
+"Subject: override subject\n" \
+"X-Header: hello\n" \
+"Subject: message\n" \
+"Defined-By: me\n" \
+"\n" \
+"override payload\n";
+
+        h = test_import(input, -1, 0);
+        assert_se(hashmap_size(h) == 1);
 
-        hashmap_free_free(h);
-        strbuf_cleanup(sb);
+        HASHMAP_FOREACH(payload, h, j) {
+                assert_se(streq(combined, payload));
+        }
 }
 
+static void test_catalog_import_merge_no_body(void) {
+        _cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
+        char *payload;
+        Iterator j;
+
+        const char *input =
+"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
+"Subject: message\n" \
+"Defined-By: me\n" \
+"\n" \
+"payload\n" \
+"\n" \
+"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \
+"Subject: override subject\n" \
+"X-Header: hello\n" \
+"\n";
+
+        const char *combined =
+"Subject: override subject\n" \
+"X-Header: hello\n" \
+"Subject: message\n" \
+"Defined-By: me\n" \
+"\n" \
+"payload\n";
+
+        h = test_import(input, -1, 0);
+        assert_se(hashmap_size(h) == 1);
+
+        HASHMAP_FOREACH(payload, h, j) {
+                assert_se(streq(combined, payload));
+        }
+}
 
 static const char* database = NULL;
 
@@ -166,7 +238,11 @@ int main(int argc, char *argv[]) {
 
         test_catalog_file_lang();
 
-        test_catalog_importing();
+        test_catalog_import_invalid();
+        test_catalog_import_badid();
+        test_catalog_import_one();
+        test_catalog_import_merge();
+        test_catalog_import_merge_no_body();
 
         test_catalog_update();
 
index 93ea9c6318fb4437b7ee7f2a2fa17d492cbe64c8..5b2d130cd6a685653bead43dfd2adceabda1ef8c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd
 
@@ -27,7 +25,8 @@
 #include "string-util.h"
 #include "util.h"
 
-typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
+typedef int (compress_t)(const void *src, uint64_t src_size, void *dst,
+                         size_t dst_alloc_size, size_t *dst_size);
 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);
 
@@ -111,8 +110,8 @@ static void test_compress_decompress(const char* label, const char* type,
 
                 memzero(buf, MIN(size + 1000, MAX_SIZE));
 
-                r = compress(text, size, buf, &j);
-                /* assume compression must be successful except for small inputs */
+                r = compress(text, size, buf, size, &j);
+                /* assume compression must be successful except for small or random inputs */
                 assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random"));
 
                 /* check for overwrites */
index b9d90a89887f976d8cf685600187ca060bd4615d..68c9a4d76c0a76a289a29ffd1f622b5b7b2187e7 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#ifdef HAVE_LZ4
+#include <lz4.h>
+#endif
+
 #include "alloc-util.h"
 #include "compress.h"
 #include "fd-util.h"
@@ -38,7 +42,7 @@
 #endif
 
 typedef int (compress_blob_t)(const void *src, uint64_t src_size,
-                              void *dst, size_t *dst_size);
+                              void *dst, size_t dst_alloc_size, size_t *dst_size);
 typedef int (decompress_blob_t)(const void *src, uint64_t src_size,
                                 void **dst, size_t *dst_alloc_size,
                                 size_t* dst_size, size_t dst_max);
@@ -57,15 +61,14 @@ static void test_compress_decompress(int compression,
                                      size_t data_len,
                                      bool may_fail) {
         char compressed[512];
-        size_t csize = 512;
-        size_t usize = 0;
+        size_t csize, usize = 0;
         _cleanup_free_ char *decompressed = NULL;
         int r;
 
         log_info("/* testing %s %s blob compression/decompression */",
                  object_compressed_to_string(compression), data);
 
-        r = compress(data, data_len, compressed, &csize);
+        r = compress(data, data_len, compressed, sizeof(compressed), &csize);
         if (r == -ENOBUFS) {
                 log_info_errno(r, "compression failed: %m");
                 assert_se(may_fail);
@@ -101,43 +104,45 @@ static void test_decompress_startswith(int compression,
                                        size_t data_len,
                                        bool may_fail) {
 
-        char compressed[512];
-        size_t csize = 512;
-        size_t usize = 0;
-        _cleanup_free_ char *decompressed = NULL;
+        char *compressed;
+        _cleanup_free_ char *compressed1 = NULL, *compressed2 = NULL, *decompressed = NULL;
+        size_t csize, usize = 0, len;
         int r;
 
-        log_info("/* testing decompress_startswith with %s on %s text*/",
+        log_info("/* testing decompress_startswith with %s on %.20s text*/",
                  object_compressed_to_string(compression), data);
 
-        r = compress(data, data_len, compressed, &csize);
+#define BUFSIZE_1 512
+#define BUFSIZE_2 20000
+
+        compressed = compressed1 = malloc(BUFSIZE_1);
+        assert_se(compressed1);
+        r = compress(data, data_len, compressed, BUFSIZE_1, &csize);
         if (r == -ENOBUFS) {
                 log_info_errno(r, "compression failed: %m");
                 assert_se(may_fail);
-                return;
+
+                compressed = compressed2 = malloc(BUFSIZE_2);
+                assert_se(compressed2);
+                r = compress(data, data_len, compressed, BUFSIZE_2, &csize);
+                assert(r == 0);
         }
         assert_se(r == 0);
 
-        assert_se(decompress_sw(compressed,
-                                csize,
-                                (void **) &decompressed,
-                                &usize,
-                                data, strlen(data), '\0') > 0);
-        assert_se(decompress_sw(compressed,
-                                csize,
-                                (void **) &decompressed,
-                                &usize,
-                                data, strlen(data), 'w') == 0);
-        assert_se(decompress_sw(compressed,
-                                csize,
-                                (void **) &decompressed,
-                                &usize,
-                                "barbarbar", 9, ' ') == 0);
-        assert_se(decompress_sw(compressed,
-                                csize,
-                                (void **) &decompressed,
-                                &usize,
-                                data, strlen(data), '\0') > 0);
+        len = strlen(data);
+
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0');
+        assert_se(r > 0);
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, 'w');
+        assert_se(r == 0);
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, "barbarbar", 9, ' ');
+        assert_se(r == 0);
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, data[len-1]);
+        assert_se(r > 0);
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, 'w');
+        assert_se(r == 0);
+        r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0');
+        assert_se(r > 0);
 }
 
 static void test_compress_stream(int compression,
@@ -199,6 +204,44 @@ static void test_compress_stream(int compression,
         assert_se(unlink(pattern2) == 0);
 }
 
+#ifdef HAVE_LZ4
+static void test_lz4_decompress_partial(void) {
+        char buf[20000];
+        size_t buf_size = sizeof(buf), compressed;
+        int r;
+        _cleanup_free_ char *huge = NULL;
+
+#define HUGE_SIZE (4096*1024)
+        huge = malloc(HUGE_SIZE);
+        memset(huge, 'x', HUGE_SIZE);
+        memcpy(huge, "HUGE=", 5);
+
+        r = LZ4_compress_limitedOutput(huge, buf, HUGE_SIZE, buf_size);
+        assert_se(r >= 0);
+        compressed = r;
+        log_info("Compressed %i → %zu", HUGE_SIZE, compressed);
+
+        r = LZ4_decompress_safe(buf, huge, r, HUGE_SIZE);
+        assert_se(r >= 0);
+        log_info("Decompressed → %i", r);
+
+        r = LZ4_decompress_safe_partial(buf, huge,
+                                        compressed,
+                                        12, HUGE_SIZE);
+        assert_se(r >= 0);
+        log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE, r);
+
+        /* We expect this to fail, because that's how current lz4 works. If this
+         * call succeeds, then lz4 has been fixed, and we need to change our code.
+         */
+        r = LZ4_decompress_safe_partial(buf, huge,
+                                        compressed,
+                                        12, HUGE_SIZE-1);
+        assert_se(r < 0);
+        log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE-1, r);
+}
+#endif
+
 int main(int argc, char *argv[]) {
         const char text[] =
                 "text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"
@@ -206,6 +249,11 @@ int main(int argc, char *argv[]) {
 
         char data[512] = "random\0";
 
+        char huge[4096*1024];
+        memset(huge, 'x', sizeof(huge));
+        memcpy(huge, "HUGE=", 5);
+        char_array_0(huge);
+
         log_set_max_level(LOG_DEBUG);
 
         random_bytes(data + 7, sizeof(data) - 7);
@@ -215,12 +263,17 @@ int main(int argc, char *argv[]) {
                                  text, sizeof(text), false);
         test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz,
                                  data, sizeof(data), true);
+
         test_decompress_startswith(OBJECT_COMPRESSED_XZ,
                                    compress_blob_xz, decompress_startswith_xz,
                                    text, sizeof(text), false);
         test_decompress_startswith(OBJECT_COMPRESSED_XZ,
                                    compress_blob_xz, decompress_startswith_xz,
                                    data, sizeof(data), true);
+        test_decompress_startswith(OBJECT_COMPRESSED_XZ,
+                                   compress_blob_xz, decompress_startswith_xz,
+                                   huge, sizeof(huge), true);
+
         test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat",
                              compress_stream_xz, decompress_stream_xz, argv[0]);
 #else
@@ -232,15 +285,21 @@ int main(int argc, char *argv[]) {
                                  text, sizeof(text), false);
         test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4,
                                  data, sizeof(data), true);
+
         test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
                                    compress_blob_lz4, decompress_startswith_lz4,
                                    text, sizeof(text), false);
         test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
                                    compress_blob_lz4, decompress_startswith_lz4,
                                    data, sizeof(data), true);
+        test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
+                                   compress_blob_lz4, decompress_startswith_lz4,
+                                   huge, sizeof(huge), true);
 
         test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat",
                              compress_stream_lz4, decompress_stream_lz4, argv[0]);
+
+        test_lz4_decompress_partial();
 #else
         log_info("/* LZ4 test skipped */");
 #endif
diff --git a/src/journal/test-coredump-vacuum.c b/src/journal/test-coredump-vacuum.c
deleted file mode 100644 (file)
index 514dadc..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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 <stdlib.h>
-
-#include "coredump-vacuum.h"
-
-int main(int argc, char *argv[]) {
-
-        if (coredump_vacuum(-1, (uint64_t) -1, 70 * 1024) < 0)
-                return EXIT_FAILURE;
-
-        return EXIT_SUCCESS;
-}
index 8f56ea19072c1268f36c533a72e484f99e9dc744..e5e9d9dcb3a6a32ffaf72a6ce51a394b121dfa5c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -29,7 +27,7 @@
 
 int main(int argc, char *argv[]) {
         unsigned n = 0;
-        _cleanup_journal_close_ sd_journal*j = NULL;
+        _cleanup_(sd_journal_closep) sd_journal*j = NULL;
 
         log_set_max_level(LOG_DEBUG);
 
index 03d1522e235b2536ac37ab156d1a3f23f0285647..7bd9c403668c0e8a4ca0f0721b4dc0214bd2fabc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 142da85041f6df4fe6e32cd880f015832fc26a43..ef21e2d05f781e61b07191a7d410c9f0d6de6c95 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5c055ef748ae5ada10dc2f7c463628633b4e2b2e..7f94990888e001f52ee9d4543df6ca0bd87ed0fb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index abefedb992f1a07a4f1e6d705150add83a018752..3ab554b9b0a9853907c68ceb32192198d0bd8ca0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,7 +28,7 @@
 #include "util.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_journal_close_ sd_journal*j;
+        _cleanup_(sd_journal_closep) sd_journal*j = NULL;
         _cleanup_free_ char *t;
 
         log_set_max_level(LOG_DEBUG);
index 694376670d069750a604417141d5dcea5083eb9a..d70f0b0bc845189ab1da0a95a1299c927d8b9ac8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "sd-journal.h"
 
-#include "log.h"
+#include "macro.h"
 
 int main(int argc, char *argv[]) {
         char huge[4096*1024];
 
-        log_set_max_level(LOG_DEBUG);
-
-        sd_journal_print(LOG_INFO, "piepapo");
-
-        sd_journal_send("MESSAGE=foobar",
-                        "VALUE=%i", 7,
-                        NULL);
+        /* utf-8 and non-utf-8, message-less and message-ful iovecs */
+        struct iovec graph1[] = {
+                {(char*) "GRAPH=graph", strlen("GRAPH=graph")}
+        };
+        struct iovec graph2[] = {
+                {(char*) "GRAPH=graph\n", strlen("GRAPH=graph\n")}
+        };
+        struct iovec message1[] = {
+                {(char*) "MESSAGE=graph", strlen("MESSAGE=graph")}
+        };
+        struct iovec message2[] = {
+                {(char*) "MESSAGE=graph\n", strlen("MESSAGE=graph\n")}
+        };
+
+        assert_se(sd_journal_print(LOG_INFO, "piepapo") == 0);
+
+        assert_se(sd_journal_send("MESSAGE=foobar",
+                                  "VALUE=%i", 7,
+                                  NULL) == 0);
 
         errno = ENOENT;
-        sd_journal_perror("Foobar");
+        assert_se(sd_journal_perror("Foobar") == 0);
 
-        sd_journal_perror("");
+        assert_se(sd_journal_perror("") == 0);
 
         memset(huge, 'x', sizeof(huge));
         memcpy(huge, "HUGE=", 5);
         char_array_0(huge);
 
-        sd_journal_send("MESSAGE=Huge field attached",
-                        huge,
-                        NULL);
+        assert_se(sd_journal_send("MESSAGE=Huge field attached",
+                                  huge,
+                                  NULL) == 0);
 
-        sd_journal_send("MESSAGE=uiui",
-                        "VALUE=A",
-                        "VALUE=B",
-                        "VALUE=C",
-                        "SINGLETON=1",
-                        "OTHERVALUE=X",
-                        "OTHERVALUE=Y",
-                        "WITH_BINARY=this is a binary value \a",
-                        NULL);
+        assert_se(sd_journal_send("MESSAGE=uiui",
+                                  "VALUE=A",
+                                  "VALUE=B",
+                                  "VALUE=C",
+                                  "SINGLETON=1",
+                                  "OTHERVALUE=X",
+                                  "OTHERVALUE=Y",
+                                  "WITH_BINARY=this is a binary value \a",
+                                  NULL) == 0);
 
         syslog(LOG_NOTICE, "Hello World!");
 
-        sd_journal_print(LOG_NOTICE, "Hello World");
-
-        sd_journal_send("MESSAGE=Hello World!",
-                        "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555",
-                        "PRIORITY=5",
-                        "HOME=%s", getenv("HOME"),
-                        "TERM=%s", getenv("TERM"),
-                        "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE),
-                        "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN),
-                        NULL);
+        assert_se(sd_journal_print(LOG_NOTICE, "Hello World") == 0);
+
+        assert_se(sd_journal_send("MESSAGE=Hello World!",
+                                  "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555",
+                                  "PRIORITY=5",
+                                  "HOME=%s", getenv("HOME"),
+                                  "TERM=%s", getenv("TERM"),
+                                  "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE),
+                                  "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN),
+                                  NULL) == 0);
+
+        assert_se(sd_journal_sendv(graph1, 1) == 0);
+        assert_se(sd_journal_sendv(graph2, 1) == 0);
+        assert_se(sd_journal_sendv(message1, 1) == 0);
+        assert_se(sd_journal_sendv(message2, 1) == 0);
+
+        /* test without location fields */
+#undef sd_journal_sendv
+        assert_se(sd_journal_sendv(graph1, 1) == 0);
+        assert_se(sd_journal_sendv(graph2, 1) == 0);
+        assert_se(sd_journal_sendv(message1, 1) == 0);
+        assert_se(sd_journal_sendv(message2, 1) == 0);
 
         sleep(1);
 
index 0cbef4b8c56c70297bfce1af743fe8b9bb96f569..4e6f8c0f7b451237812f670f288fe252af64c4f7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -79,7 +77,7 @@ int main(int argc, char *argv[]) {
         JournalFile *one, *two, *three;
         char t[] = "/tmp/journal-stream-XXXXXX";
         unsigned i;
-        _cleanup_journal_close_ sd_journal *j = NULL;
+        _cleanup_(sd_journal_closep) sd_journal *j = NULL;
         char *z;
         const void *data;
         size_t l;
index 1784187fe9317be0c720c23195b81450820373b0..4ff7f3ec2ef251c69002b839d028598298de0cde 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index a7abb11fba8721d5fd25f23d52af1d174e09f198..a26c624f41eb4d9cfb0f4f79357a7890b21309f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 266e0d547380690d478f756b24bd296b92fef4cf..0334b1cd1a26268988e17ff0d143f63080fa9040 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index fdd48e531c16be16b4f3782149f9b7f953910e9d..009aabf55e8e80a32f7ce29e55f75859323de844 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 44e5c893a7bc2aa66468bb8ef2f95bf1e24e5b41..3ef56b002a76586f24b22854c8e71fea0580c70d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 #include <netinet/if_ether.h>
 
-#include "sparse-endian.h"
 #include "socket-util.h"
+#include "sparse-endian.h"
 
 int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac);
 
index d7ae8655573f7124d179b7457945a5412c279fb4..1d9ec7be827086ddb23641b7eae7c3f39b7fb022 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 2291736f8b05f6af3a9863bc925613748e1250fd..93f06f5938bed5d4732d067d586596345e1645f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a5daaa543a8ee8040cd3ea8308ebbc1e3cfcaa4f..a3b842cda3b05a11542b2625f1546ecfdf4e06a7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -47,8 +45,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_
 typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
                                 const void *option, void *userdata);
 
-int dhcp_option_parse(DHCPMessage *message, size_t len,
-                      dhcp_option_cb_t cb, void *userdata);
+int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **error_message);
 
 int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
                       uint8_t type, uint16_t arp_type, size_t optlen,
@@ -62,13 +59,10 @@ void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
 
 int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_client*, sd_dhcp_client_unref);
-#define _cleanup_dhcp_client_unref_ _cleanup_(sd_dhcp_client_unrefp)
-
 /* If we are invoking callbacks of a dhcp-client, ensure unreffing the
  * client from the callback doesn't destroy the object we are working
  * on */
 #define DHCP_CLIENT_DONT_DESTROY(client) \
-        _cleanup_dhcp_client_unref_ _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client)
+        _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client)
 
 #define log_dhcp_client(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__)
index c6b97ca8f7924e6acf097c25873e36774f224a00..82cae2300ac72ba72cf438bb471a95cd853a9124 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <stdint.h>
 #include <linux/if_packet.h>
 
-#include "util.h"
-#include "list.h"
+#include "sd-dhcp-client.h"
 
 #include "dhcp-protocol.h"
-
-#include "sd-dhcp-client.h"
+#include "list.h"
+#include "util.h"
 
 struct sd_dhcp_route {
         struct in_addr dst_addr;
@@ -103,6 +100,3 @@ int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t
 
 int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
 int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
-#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
index a6c410ba9118bac4d65428fa2acc713c8e42220a..df1996c8ce442c2e1d7ce7b5c56929d2f784e138 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -24,6 +22,9 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "alloc-util.h"
+#include "utf8.h"
+
 #include "dhcp-internal.h"
 
 static int option_append(uint8_t options[], size_t size, size_t *offset,
@@ -31,14 +32,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
         assert(options);
         assert(offset);
 
-        if (code != DHCP_OPTION_END)
+        if (code != SD_DHCP_OPTION_END)
                 /* always make sure there is space for an END option */
                 size --;
 
         switch (code) {
 
-        case DHCP_OPTION_PAD:
-        case DHCP_OPTION_END:
+        case SD_DHCP_OPTION_PAD:
+        case SD_DHCP_OPTION_END:
                 if (size < *offset + 1)
                         return -ENOBUFS;
 
@@ -88,7 +89,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
                 else if (r == -ENOBUFS && (file || sname)) {
                         /* did not fit, but we have more buffers to try
                            close the options array and move the offset to its end */
-                        r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL);
+                        r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
                         if (r < 0)
                                 return r;
 
@@ -109,7 +110,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
                         } else if (r == -ENOBUFS && sname) {
                                 /* did not fit, but we have more buffers to try
                                    close the file array and move the offset to its end */
-                                r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL);
+                                r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
                                 if (r < 0)
                                         return r;
 
@@ -139,72 +140,84 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
 }
 
 static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
-                         uint8_t *message_type, dhcp_option_cb_t cb,
+                         uint8_t *message_type, char **error_message, dhcp_option_cb_t cb,
                          void *userdata) {
         uint8_t code, len;
+        const uint8_t *option;
         size_t offset = 0;
 
         while (offset < buflen) {
-                switch (options[offset]) {
-                case DHCP_OPTION_PAD:
-                        offset++;
+                code = options[offset ++];
 
-                        break;
+                switch (code) {
+                case SD_DHCP_OPTION_PAD:
+                        continue;
 
-                case DHCP_OPTION_END:
+                case SD_DHCP_OPTION_END:
                         return 0;
+                }
+
+                if (buflen < offset + 1)
+                        return -ENOBUFS;
+
+                len = options[offset ++];
 
-                case DHCP_OPTION_MESSAGE_TYPE:
-                        if (buflen < offset + 3)
-                                return -ENOBUFS;
+                if (buflen < offset + len)
+                        return -EINVAL;
 
-                        len = options[++offset];
+                option = &options[offset];
+
+                switch (code) {
+                case SD_DHCP_OPTION_MESSAGE_TYPE:
                         if (len != 1)
                                 return -EINVAL;
 
                         if (message_type)
-                                *message_type = options[++offset];
-                        else
-                                offset++;
-
-                        offset++;
+                                *message_type = *option;
 
                         break;
 
-                case DHCP_OPTION_OVERLOAD:
-                        if (buflen < offset + 3)
-                                return -ENOBUFS;
-
-                        len = options[++offset];
-                        if (len != 1)
+                case SD_DHCP_OPTION_ERROR_MESSAGE:
+                        if (len == 0)
                                 return -EINVAL;
 
-                        if (overload)
-                                *overload = options[++offset];
-                        else
-                                offset++;
+                        if (error_message) {
+                                _cleanup_free_ char *string = NULL;
 
-                        offset++;
+                                /* Accept a trailing NUL byte */
+                                if (memchr(option, 0, len - 1))
+                                        return -EINVAL;
 
-                        break;
+                                string = strndup((const char *) option, len);
+                                if (!string)
+                                        return -ENOMEM;
 
-                default:
-                        if (buflen < offset + 3)
-                                return -ENOBUFS;
+                                if (!ascii_is_valid(string))
+                                        return -EINVAL;
 
-                        code = options[offset];
-                        len = options[++offset];
+                                free(*error_message);
+                                *error_message = string;
+                                string = NULL;
+                        }
 
-                        if (buflen < ++offset + len)
+                        break;
+                case SD_DHCP_OPTION_OVERLOAD:
+                        if (len != 1)
                                 return -EINVAL;
 
-                        if (cb)
-                                cb(code, len, &options[offset], userdata);
+                        if (overload)
+                                *overload = *option;
 
-                        offset += len;
+                        break;
+
+                default:
+                        if (cb)
+                                cb(code, len, option, userdata);
 
                         break;
                 }
+
+                offset += len;
         }
 
         if (offset < buflen)
@@ -213,8 +226,8 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
         return 0;
 }
 
-int dhcp_option_parse(DHCPMessage *message, size_t len,
-                      dhcp_option_cb_t cb, void *userdata) {
+int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **_error_message) {
+        _cleanup_free_ char *error_message = NULL;
         uint8_t overload = 0;
         uint8_t message_type = 0;
         int r;
@@ -227,27 +240,29 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
 
         len -= sizeof(DHCPMessage);
 
-        r = parse_options(message->options, len, &overload, &message_type,
-                          cb, userdata);
+        r = parse_options(message->options, len, &overload, &message_type, &error_message, cb, userdata);
         if (r < 0)
                 return r;
 
         if (overload & DHCP_OVERLOAD_FILE) {
-                r = parse_options(message->file, sizeof(message->file),
-                                NULL, &message_type, cb, userdata);
+                r = parse_options(message->file, sizeof(message->file), NULL, &message_type, &error_message, cb, userdata);
                 if (r < 0)
                         return r;
         }
 
         if (overload & DHCP_OVERLOAD_SNAME) {
-                r = parse_options(message->sname, sizeof(message->sname),
-                                NULL, &message_type, cb, userdata);
+                r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata);
                 if (r < 0)
                         return r;
         }
 
-        if (message_type)
-                return message_type;
+        if (message_type == 0)
+                return -ENOMSG;
+
+        if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) {
+                *_error_message = error_message;
+                error_message = NULL;
+        }
 
-        return -ENOMSG;
+        return message_type;
 }
index 9ff42b155ebdc3646adcfa3bc3b41776c278c3c1..8d75d4969179d06e76a20f0feb8341d49a280b47 100644 (file)
@@ -44,7 +44,7 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
         message->magic = htobe32(DHCP_MAGIC_COOKIE);
 
         r = dhcp_option_append(message, optlen, &offset, 0,
-                               DHCP_OPTION_MESSAGE_TYPE, 1, &type);
+                               SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
         if (r < 0)
                 return r;
 
index 88a81d2866a7312d04198b9f23342aff47c5c586..3e32484c1d6d21461090b83154baa8618c914f41 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <netinet/udp.h>
 #include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <stdint.h>
 
 #include "macro.h"
@@ -105,42 +103,11 @@ enum {
         DHCP_OVERLOAD_SNAME                     = 2,
 };
 
+#define DHCP_MAX_FQDN_LENGTH 255
+
 enum {
-        DHCP_OPTION_PAD                         = 0,
-        DHCP_OPTION_SUBNET_MASK                 = 1,
-        DHCP_OPTION_TIME_OFFSET                 = 2,
-        DHCP_OPTION_ROUTER                      = 3,
-        DHCP_OPTION_DOMAIN_NAME_SERVER          = 6,
-        DHCP_OPTION_HOST_NAME                   = 12,
-        DHCP_OPTION_BOOT_FILE_SIZE              = 13,
-        DHCP_OPTION_DOMAIN_NAME                 = 15,
-        DHCP_OPTION_ROOT_PATH                   = 17,
-        DHCP_OPTION_ENABLE_IP_FORWARDING        = 19,
-        DHCP_OPTION_ENABLE_IP_FORWARDING_NL     = 20,
-        DHCP_OPTION_POLICY_FILTER               = 21,
-        DHCP_OPTION_INTERFACE_MDR               = 22,
-        DHCP_OPTION_INTERFACE_TTL               = 23,
-        DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
-        DHCP_OPTION_INTERFACE_MTU               = 26,
-        DHCP_OPTION_BROADCAST                   = 28,
-        DHCP_OPTION_STATIC_ROUTE                = 33,
-        DHCP_OPTION_NTP_SERVER                  = 42,
-        DHCP_OPTION_VENDOR_SPECIFIC             = 43,
-        DHCP_OPTION_REQUESTED_IP_ADDRESS        = 50,
-        DHCP_OPTION_IP_ADDRESS_LEASE_TIME       = 51,
-        DHCP_OPTION_OVERLOAD                    = 52,
-        DHCP_OPTION_MESSAGE_TYPE                = 53,
-        DHCP_OPTION_SERVER_IDENTIFIER           = 54,
-        DHCP_OPTION_PARAMETER_REQUEST_LIST      = 55,
-        DHCP_OPTION_MAXIMUM_MESSAGE_SIZE        = 57,
-        DHCP_OPTION_RENEWAL_T1_TIME             = 58,
-        DHCP_OPTION_REBINDING_T2_TIME           = 59,
-        DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,
-        DHCP_OPTION_CLIENT_IDENTIFIER           = 61,
-        DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
-        DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
-        DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
-        DHCP_OPTION_PRIVATE_BASE                = 224,
-        DHCP_OPTION_PRIVATE_LAST                = 254,
-        DHCP_OPTION_END                         = 255,
+        DHCP_FQDN_FLAG_S = (1 << 0),
+        DHCP_FQDN_FLAG_O = (1 << 1),
+        DHCP_FQDN_FLAG_E = (1 << 2),
+        DHCP_FQDN_FLAG_N = (1 << 3),
 };
index 3b88b93d9a5b1ab3a8db7ee259fe56647f465915..bf123f14399dc4d6039f0c7a793a209922a376f0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #pragma once
 
-#include "sd-event.h"
 #include "sd-dhcp-server.h"
+#include "sd-event.h"
 
+#include "dhcp-internal.h"
 #include "hashmap.h"
-#include "util.h"
 #include "log.h"
-
-#include "dhcp-internal.h"
+#include "util.h"
 
 typedef struct DHCPClientId {
         size_t length;
@@ -85,9 +82,6 @@ typedef struct DHCPRequest {
         uint32_t lifetime;
 } DHCPRequest;
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_server*, sd_dhcp_server_unref);
-#define _cleanup_dhcp_server_unref_ _cleanup_(sd_dhcp_server_unrefp)
-
 #define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__)
 
 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
index ecc220f2f67616805ece792197fc0fee2bfccaf9..749086d33a99e4c04d47611f28c6e6bc75cb2a00 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4edecf7711b8fa56bf8f32f7fc23022a229f839e..14e708ef638e90c665ba49037d45e9791857541e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,6 +23,7 @@
 #include <stdint.h>
 
 #include "sd-dhcp6-lease.h"
+
 #include "dhcp6-internal.h"
 
 struct sd_dhcp6_lease {
@@ -73,6 +72,3 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval,
                          size_t optlen) ;
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
-#define _cleanup_dhcp6_lease_free_ _cleanup_(sd_dhcp6_lease_unrefp)
index 62023a9e490354b7f6d3704603aae8f82268547f..b0739066608e2692c527dbeb15b3807842540ac1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,6 +21,8 @@
 #include <netinet/in.h>
 #include <string.h>
 
+#include "sd-dhcp6-client.h"
+
 #include "alloc-util.h"
 #include "dhcp6-internal.h"
 #include "dhcp6-protocol.h"
@@ -90,11 +90,11 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
         assert_return(buf && *buf && buflen && ia, -EINVAL);
 
         switch (ia->type) {
-        case DHCP6_OPTION_IA_NA:
+        case SD_DHCP6_OPTION_IA_NA:
                 len = DHCP6_OPTION_IA_NA_LEN;
                 break;
 
-        case DHCP6_OPTION_IA_TA:
+        case SD_DHCP6_OPTION_IA_TA:
                 len = DHCP6_OPTION_IA_TA_LEN;
                 break;
 
@@ -117,7 +117,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
         *buflen -= len;
 
         LIST_FOREACH(addresses, addr, ia->addresses) {
-                r = option_append_hdr(buf, buflen, DHCP6_OPTION_IAADDR,
+                r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR,
                                       sizeof(addr->iaaddr));
                 if (r < 0)
                         return r;
@@ -196,7 +196,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
         assert_return(!ia->addresses, -EINVAL);
 
         switch (iatype) {
-        case DHCP6_OPTION_IA_NA:
+        case SD_DHCP6_OPTION_IA_NA:
 
                 if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
                     sizeof(addr->iaaddr)) {
@@ -219,7 +219,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
 
                 break;
 
-        case DHCP6_OPTION_IA_TA:
+        case SD_DHCP6_OPTION_IA_TA:
                 if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
                     sizeof(addr->iaaddr)) {
                         r = -ENOBUFS;
@@ -247,7 +247,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
         while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) {
 
                 switch (opt) {
-                case DHCP6_OPTION_IAADDR:
+                case SD_DHCP6_OPTION_IAADDR:
 
                         addr = new0(DHCP6Address, 1);
                         if (!addr) {
@@ -274,7 +274,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
 
                         break;
 
-                case DHCP6_OPTION_STATUS_CODE:
+                case SD_DHCP6_OPTION_STATUS_CODE:
                         if (optlen < sizeof(status))
                                 break;
 
@@ -360,7 +360,6 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
                                 /* End of name */
                                 break;
                         else if (c <= 63) {
-                                _cleanup_free_ char *t = NULL;
                                 const char *label;
 
                                 /* Literal label */
@@ -369,21 +368,20 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
                                 if (pos > optlen)
                                         return -EMSGSIZE;
 
-                                r = dns_label_escape(label, c, &t);
-                                if (r < 0)
-                                        goto fail;
-
-                                if (!GREEDY_REALLOC0(ret, allocated, n + !first + strlen(t) + 1)) {
+                                if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
                                         r = -ENOMEM;
                                         goto fail;
                                 }
 
-                                if (!first)
-                                        ret[n++] = '.';
-                                else
+                                if (first)
                                         first = false;
+                                else
+                                        ret[n++] = '.';
+
+                                r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+                                if (r < 0)
+                                        goto fail;
 
-                                memcpy(ret + n, t, r);
                                 n += r;
                                 continue;
                         } else {
index b3a28f88b4f8df112ab78605518c57cff0125b68..ee4bdfb07ff4e1fdcbc8d4302dbf743d57af5350 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -98,41 +96,6 @@ enum {
         _DHCP6_MESSAGE_MAX                      = 14,
 };
 
-enum {
-        DHCP6_OPTION_CLIENTID                   = 1,
-        DHCP6_OPTION_SERVERID                   = 2,
-        DHCP6_OPTION_IA_NA                      = 3,
-        DHCP6_OPTION_IA_TA                      = 4,
-        DHCP6_OPTION_IAADDR                     = 5,
-        DHCP6_OPTION_ORO                        = 6,
-        DHCP6_OPTION_PREFERENCE                 = 7,
-        DHCP6_OPTION_ELAPSED_TIME               = 8,
-        DHCP6_OPTION_RELAY_MSG                  = 9,
-        /* option code 10 is unassigned */
-        DHCP6_OPTION_AUTH                       = 11,
-        DHCP6_OPTION_UNICAST                    = 12,
-        DHCP6_OPTION_STATUS_CODE                = 13,
-        DHCP6_OPTION_RAPID_COMMIT               = 14,
-        DHCP6_OPTION_USER_CLASS                 = 15,
-        DHCP6_OPTION_VENDOR_CLASS               = 16,
-        DHCP6_OPTION_VENDOR_OPTS                = 17,
-        DHCP6_OPTION_INTERFACE_ID               = 18,
-        DHCP6_OPTION_RECONF_MSG                 = 19,
-        DHCP6_OPTION_RECONF_ACCEPT              = 20,
-
-        DHCP6_OPTION_DNS_SERVERS                = 23,  /* RFC 3646 */
-        DHCP6_OPTION_DOMAIN_LIST                = 24,  /* RFC 3646 */
-
-        DHCP6_OPTION_SNTP_SERVERS               = 31,  /* RFC 4075, deprecated */
-
-        /* option code 35 is unassigned */
-
-        DHCP6_OPTION_NTP_SERVER                 = 56,  /* RFC 5908 */
-
-        /* option codes 89-142 are unassigned */
-        /* option codes 144-65535 are unassigned */
-};
-
 enum {
         DHCP6_NTP_SUBOPTION_SRV_ADDR            = 1,
         DHCP6_NTP_SUBOPTION_MC_ADDR             = 2,
index 91308bf6c33ccadf0e14e3346cd6a1ce9cef1295..acad9d7d6a89a7aa442750a1114584e8f212fcc7 100644 (file)
@@ -47,17 +47,15 @@ int icmp6_bind_router_solicitation(int index) {
                 .ipv6mr_interface = index,
         };
         _cleanup_close_ int s = -1;
-        int r, zero = 0, hops = 255;
+        int r, zero = 0, one = 1, hops = 255;
 
-        s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                   IPPROTO_ICMPV6);
+        s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
         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;
 
@@ -65,23 +63,23 @@ int icmp6_bind_router_solicitation(int index) {
            IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
            Empirical experiments indicates otherwise and therefore an
            IPV6_MULTICAST_IF socket option is used here instead */
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index,
-                       sizeof(index));
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index));
         if (r < 0)
                 return -errno;
 
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero,
-                       sizeof(zero));
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero));
         if (r < 0)
                 return -errno;
 
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,
-                       sizeof(hops));
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops));
         if (r < 0)
                 return -errno;
 
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
-                       sizeof(mreq));
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+        if (r < 0)
+                return -errno;
+
+        r = setsockopt(s, SOL_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
         if (r < 0)
                 return -errno;
 
@@ -101,25 +99,25 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
                 struct ether_addr rs_opt_mac;
         } _packed_ rs = {
                 .rs.nd_rs_type = ND_ROUTER_SOLICIT,
+                .rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR,
+                .rs_opt.nd_opt_len = 1,
         };
-        struct iovec iov[1] = {
-                { &rs, },
+        struct iovec iov = {
+                .iov_base = &rs,
+                .iov_len = sizeof(rs),
         };
         struct msghdr msg = {
                 .msg_name = &dst,
                 .msg_namelen = sizeof(dst),
-                .msg_iov = iov,
+                .msg_iov = &iov,
                 .msg_iovlen = 1,
         };
         int r;
 
-        if (ether_addr) {
-                memcpy(&rs.rs_opt_mac, ether_addr, ETH_ALEN);
-                rs.rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
-                rs.rs_opt.nd_opt_len = 1;
-                iov[0].iov_len = sizeof(rs);
-        } else
-                iov[0].iov_len = sizeof(rs.rs);
+        assert(s >= 0);
+        assert(ether_addr);
+
+        rs.rs_opt_mac = *ether_addr;
 
         r = sendmsg(s, &msg, 0);
         if (r < 0)
index 4eb17e152ef12c634aa87dc742a8723ac9912b59..2b4dbc76cee5fe98fbfb08d685b72925a8bc45aa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 583be2f55d9b0adcf82d44684ce91bf1b322b19b..c8740ce5f0cae92609f1422ff9085747ac748373 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -335,7 +333,7 @@ int lldp_chassis_new(tlv_packet *tlv,
 }
 
 int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        _cleanup_lldp_packet_unref_ tlv_packet *packet = NULL;
+        _cleanup_(sd_lldp_packet_unrefp) tlv_packet *packet = NULL;
         tlv_packet *p;
         uint16_t length;
         int r;
index 5d19fa0fea3a1ded1ff71fd239470695fe8ef21d..15b4a11b151be20611f48b1c987af188c3316e5f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f483cd9c8ec2692263b7fadba07299cfa8559656..42058c4449afa6561e9d6720e4762414626544ae 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 74ee13a4147baf6d13226f344f48d0862aa580b6..dcf31faa956ecf6f8e9f4ccdd4722573b105fd71 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1f1a49adbf80aaf41e12da60015d1213083b0323..c86f62a6c2ed006dc373e0d21faa41782fd8bad8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 517b162a67083bb44428bce449f240545ec369a6..96092f8df93980088f5f36184628ffedf56571a3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 66343147a1ca3963b392166ad5ff90df4d93952a..9170b506911cec5f3f57eecab347d0e95664f87f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ca1da113d59c44620261fd32b674cd97a0c22e4c..8e7706c61282cbb0aad18767a1a82a3b56d1e37b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <net/ethernet.h>
 
-#include "util.h"
-#include "lldp.h"
-#include "list.h"
-
 #include "sd-lldp.h"
 
+#include "list.h"
+#include "lldp.h"
+#include "util.h"
+
 typedef struct sd_lldp_packet tlv_packet;
 typedef struct sd_lldp_section tlv_section;
 
@@ -74,9 +72,6 @@ struct sd_lldp_packet {
 
 int tlv_packet_new(tlv_packet **ret);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_lldp_packet*, sd_lldp_packet_unref);
-#define _cleanup_lldp_packet_unref_ _cleanup_(sd_lldp_packet_unrefp)
-
 int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type);
 int lldp_tlv_packet_close_container(tlv_packet *m);
 
diff --git a/src/libsystemd-network/lldp-util.h b/src/libsystemd-network/lldp-util.h
deleted file mode 100644 (file)
index 112001e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 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/>.
-***/
-
-#pragma once
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_lldp *, sd_lldp_free);
-#define _cleanup_lldp_free_ _cleanup_(sd_lldp_freep)
index 19e5cc5f416a818e301b3ee82d36ae686771c84c..d2c71646333784c3a054f0cb6b07dd47093f5587 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index a4d4f1ae2f596a8358a85417745c2791ab2bc5d5..fdafcd84d82a67af2e6641cdf1883d550afdaadb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
@@ -437,7 +435,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
         return size;
 }
 
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
+void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
         unsigned i;
 
         assert(f);
@@ -448,10 +446,15 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
         fprintf(f, "%s=", key);
 
         for (i = 0; i < size; i++) {
-                fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
-                        routes[i].dst_prefixlen);
-                fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
-                        (i < (size - 1)) ? " ": "");
+                struct in_addr dest, gw;
+                uint8_t length;
+
+                assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0);
+                assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
+                assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
+
+                fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length);
+                fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": "");
         }
 
         fputs("\n", f);
index d516f2dafd55218ae0e61e87902b03ee2054e256..c8a531ab0f7ff7a331d1c938ffbccfda3af169d2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include <stdbool.h>
 
-#include "udev.h"
+#include "sd-dhcp-lease.h"
+
 #include "condition.h"
+#include "udev.h"
 
 bool net_match_config(const struct ether_addr *match_mac,
                       char * const *match_path,
@@ -74,7 +74,7 @@ int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
 /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
 struct sd_dhcp_route;
 
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size);
+void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
 
 int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
index 137537253a4aad9a9cfb034c31a11050204f429d..cad1a52c098e617af9133a211ed75eed3aee6c82 100644 (file)
@@ -34,6 +34,8 @@
 #include "dhcp-internal.h"
 #include "dhcp-lease-internal.h"
 #include "dhcp-protocol.h"
+#include "dns-domain.h"
+#include "hostname-util.h"
 #include "random-util.h"
 #include "string-util.h"
 #include "util.h"
@@ -41,6 +43,9 @@
 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
 
+#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
+#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
+
 struct sd_dhcp_client {
         unsigned n_ref;
 
@@ -99,14 +104,15 @@ struct sd_dhcp_client {
         sd_dhcp_client_cb_t cb;
         void *userdata;
         sd_dhcp_lease *lease;
+        usec_t start_delay;
 };
 
 static const uint8_t default_req_opts[] = {
-        DHCP_OPTION_SUBNET_MASK,
-        DHCP_OPTION_ROUTER,
-        DHCP_OPTION_HOST_NAME,
-        DHCP_OPTION_DOMAIN_NAME,
-        DHCP_OPTION_DOMAIN_NAME_SERVER,
+        SD_DHCP_OPTION_SUBNET_MASK,
+        SD_DHCP_OPTION_ROUTER,
+        SD_DHCP_OPTION_HOST_NAME,
+        SD_DHCP_OPTION_DOMAIN_NAME,
+        SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
 };
 
 static int client_receive_message_raw(sd_event_source *s, int fd,
@@ -141,11 +147,11 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
                               DHCP_STATE_STOPPED), -EBUSY);
 
         switch(option) {
-        case DHCP_OPTION_PAD:
-        case DHCP_OPTION_OVERLOAD:
-        case DHCP_OPTION_MESSAGE_TYPE:
-        case DHCP_OPTION_PARAMETER_REQUEST_LIST:
-        case DHCP_OPTION_END:
+        case SD_DHCP_OPTION_PAD:
+        case SD_DHCP_OPTION_OVERLOAD:
+        case SD_DHCP_OPTION_MESSAGE_TYPE:
+        case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
+        case SD_DHCP_OPTION_END:
                 return -EINVAL;
 
         default:
@@ -298,6 +304,9 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
 
         assert_return(client, -EINVAL);
 
+        if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
+                return -EINVAL;
+
         if (streq_ptr(client->hostname, hostname))
                 return 0;
 
@@ -481,7 +490,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            Identifier option is not set */
         if (client->client_id_len) {
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_CLIENT_IDENTIFIER,
+                                       SD_DHCP_OPTION_CLIENT_IDENTIFIER,
                                        client->client_id_len,
                                        &client->client_id);
                 if (r < 0)
@@ -497,7 +506,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            messages.
          */
         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_PARAMETER_REQUEST_LIST,
+                               SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
                                client->req_opts_size, client->req_opts);
         if (r < 0)
                 return r;
@@ -526,7 +535,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
          */
         max_size = htobe16(size);
         r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
-                               DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
+                               SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
                                2, &max_size);
         if (r < 0)
                 return r;
@@ -539,6 +548,24 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
         return 0;
 }
 
+static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
+                                     const char *fqdn) {
+        uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
+        int r;
+
+        buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
+                    DHCP_FQDN_FLAG_E;  /* Canonical wire format */
+        buffer[1] = 0;                 /* RCODE1 (deprecated) */
+        buffer[2] = 0;                 /* RCODE2 (deprecated) */
+
+        r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
+        if (r > 0)
+                r = dhcp_option_append(message, optlen, optoffset, 0,
+                                       SD_DHCP_OPTION_FQDN, 3 + r, buffer);
+
+        return r;
+}
+
 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
                                 size_t len) {
         dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
@@ -570,26 +597,34 @@ static int client_send_discover(sd_dhcp_client *client) {
          */
         if (client->last_addr != INADDR_ANY) {
                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->last_addr);
                 if (r < 0)
                         return r;
         }
 
-        /* it is unclear from RFC 2131 if client should send hostname in
-           DHCPDISCOVER but dhclient does and so we do as well
-        */
         if (client->hostname) {
-                r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_HOST_NAME,
-                                       strlen(client->hostname), client->hostname);
+                /* According to RFC 4702 "clients that send the Client FQDN option in
+                   their messages MUST NOT also send the Host Name option". Just send
+                   one of the two depending on the hostname type.
+                */
+                if (dns_name_is_single_label(client->hostname)) {
+                        /* it is unclear from RFC 2131 if client should send hostname in
+                           DHCPDISCOVER but dhclient does and so we do as well
+                        */
+                        r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+                                               SD_DHCP_OPTION_HOST_NAME,
+                                               strlen(client->hostname), client->hostname);
+                } else
+                        r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
+                                                      client->hostname);
                 if (r < 0)
                         return r;
         }
 
         if (client->vendor_class_identifier) {
                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
+                                       SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
                                        strlen(client->vendor_class_identifier),
                                        client->vendor_class_identifier);
                 if (r < 0)
@@ -597,7 +632,7 @@ static int client_send_discover(sd_dhcp_client *client) {
         }
 
         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_END, 0, NULL);
+                               SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -636,13 +671,13 @@ static int client_send_request(sd_dhcp_client *client) {
                  */
 
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_SERVER_IDENTIFIER,
+                                       SD_DHCP_OPTION_SERVER_IDENTIFIER,
                                        4, &client->lease->server_address);
                 if (r < 0)
                         return r;
 
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->lease->address);
                 if (r < 0)
                         return r;
@@ -655,7 +690,7 @@ static int client_send_request(sd_dhcp_client *client) {
                    assigned address. ’ciaddr’ MUST be zero.
                  */
                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                        4, &client->last_addr);
                 if (r < 0)
                         return r;
@@ -688,15 +723,19 @@ static int client_send_request(sd_dhcp_client *client) {
         }
 
         if (client->hostname) {
-                r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       DHCP_OPTION_HOST_NAME,
-                                       strlen(client->hostname), client->hostname);
+                if (dns_name_is_single_label(client->hostname))
+                        r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
+                                               SD_DHCP_OPTION_HOST_NAME,
+                                               strlen(client->hostname), client->hostname);
+                else
+                        r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
+                                                      client->hostname);
                 if (r < 0)
                         return r;
         }
 
         r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                               DHCP_OPTION_END, 0, NULL);
+                               SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -910,6 +949,7 @@ error:
 }
 
 static int client_initialize_time_events(sd_dhcp_client *client) {
+        uint64_t usec = 0;
         int r;
 
         assert(client);
@@ -917,10 +957,15 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
 
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
+        if (client->start_delay) {
+                sd_event_now(client->event, clock_boottime_or_monotonic(), &usec);
+                usec += client->start_delay;
+        }
+
         r = sd_event_add_time(client->event,
                               &client->timeout_resend,
                               clock_boottime_or_monotonic(),
-                              0, 0,
+                              usec, 0,
                               client_timeout_resend, client);
         if (r < 0)
                 goto error;
@@ -950,7 +995,7 @@ static int client_initialize_events(sd_dhcp_client *client,
         return 0;
 }
 
-static int client_start(sd_dhcp_client *client) {
+static int client_start_delayed(sd_dhcp_client *client) {
         int r;
 
         assert_return(client, -EINVAL);
@@ -978,6 +1023,11 @@ static int client_start(sd_dhcp_client *client) {
         return client_initialize_events(client, client_receive_message_raw);
 }
 
+static int client_start(sd_dhcp_client *client) {
+        client->start_delay = 0;
+        return client_start_delayed(client);
+}
+
 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
                                  void *userdata) {
         sd_dhcp_client *client = userdata;
@@ -1032,7 +1082,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
 
 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
                                size_t len) {
-        _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
         int r;
 
         r = dhcp_lease_new(&lease);
@@ -1047,7 +1097,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
                         return r;
         }
 
-        r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
+        r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL);
         if (r != DHCP_OFFER) {
                 log_dhcp_client(client, "received message was not an OFFER, ignoring");
                 return -ENOMSG;
@@ -1086,7 +1136,7 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
                                     size_t len) {
         int r;
 
-        r = dhcp_option_parse(force, len, NULL, NULL);
+        r = dhcp_option_parse(force, len, NULL, NULL, NULL);
         if (r != DHCP_FORCERENEW)
                 return -ENOMSG;
 
@@ -1097,7 +1147,8 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
 
 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
                              size_t len) {
-        _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
+        _cleanup_free_ char *error_message = NULL;
         int r;
 
         r = dhcp_lease_new(&lease);
@@ -1112,9 +1163,9 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
                         return r;
         }
 
-        r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
+        r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
         if (r == DHCP_NAK) {
-                log_dhcp_client(client, "NAK");
+                log_dhcp_client(client, "NAK: %s", strna(error_message));
                 return -EADDRNOTAVAIL;
         }
 
@@ -1326,6 +1377,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                                  int len) {
         DHCP_CLIENT_DONT_DESTROY(client);
+        char time_string[FORMAT_TIMESPAN_MAX];
         int r = 0, notify_event = 0;
 
         assert(client);
@@ -1373,6 +1425,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                 r = client_handle_ack(client, message, len);
                 if (r >= 0) {
+                        client->start_delay = 0;
                         client->timeout_resend =
                                 sd_event_source_unref(client->timeout_resend);
                         client->receive_message =
@@ -1422,11 +1475,15 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                         if (r < 0)
                                 goto error;
 
-                        r = client_start(client);
+                        r = client_start_delayed(client);
                         if (r < 0)
                                 goto error;
 
-                        log_dhcp_client(client, "REBOOTED");
+                        log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX,
+                                                                                client->start_delay, USEC_PER_SEC));
+
+                        client->start_delay = CLAMP(client->start_delay * 2,
+                                                    RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC);
 
                         return 0;
                 } else if (r == -ENOMSG)
@@ -1478,9 +1535,8 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
 
         r = ioctl(fd, FIONREAD, &buflen);
         if (r < 0)
-                return r;
-
-        if (buflen < 0)
+                return -errno;
+        else if (buflen < 0)
                 /* this can't be right */
                 return -EIO;
 
@@ -1490,26 +1546,28 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
 
         len = read(fd, message, buflen);
         if (len < 0) {
-                log_dhcp_client(client, "could not receive message from UDP "
-                                "socket: %m");
-                return 0;
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                log_dhcp_client(client, "Could not receive message from UDP socket: %m");
+                return -errno;
         } else if ((size_t)len < sizeof(DHCPMessage)) {
-                log_dhcp_client(client, "too small to be a DHCP message: ignoring");
+                log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
                 return 0;
         }
 
         if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
-                log_dhcp_client(client, "not a DHCP message: ignoring");
+                log_dhcp_client(client, "Not a DHCP message: ignoring");
                 return 0;
         }
 
         if (message->op != BOOTREPLY) {
-                log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
+                log_dhcp_client(client, "Not a BOOTREPLY message: ignoring");
                 return 0;
         }
 
         if (message->htype != client->arp_type) {
-                log_dhcp_client(client, "packet type does not match client type");
+                log_dhcp_client(client, "Packet type does not match client type");
                 return 0;
         }
 
@@ -1523,13 +1581,12 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
         }
 
         if (message->hlen != expected_hlen) {
-                log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
+                log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen);
                 return 0;
         }
 
         if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
-                log_dhcp_client(client, "received chaddr does not match "
-                                "expected: ignoring");
+                log_dhcp_client(client, "Received chaddr does not match expected: ignoring");
                 return 0;
         }
 
@@ -1537,8 +1594,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
             be32toh(message->xid) != client->xid) {
                 /* in BOUND state, we may receive FORCERENEW with xid set by server,
                    so ignore the xid in this case */
-                log_dhcp_client(client, "received xid (%u) does not match "
-                                "expected (%u): ignoring",
+                log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring",
                                 be32toh(message->xid), client->xid);
                 return 0;
         }
@@ -1567,9 +1623,8 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
 
         r = ioctl(fd, FIONREAD, &buflen);
         if (r < 0)
-                return r;
-
-        if (buflen < 0)
+                return -errno;
+        else if (buflen < 0)
                 /* this can't be right */
                 return -EIO;
 
@@ -1582,9 +1637,12 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
 
         len = recvmsg(fd, &msg, 0);
         if (len < 0) {
-                log_dhcp_client(client, "could not receive message from raw "
-                                "socket: %m");
-                return 0;
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                log_dhcp_client(client, "Could not receive message from raw socket: %m");
+
+                return -errno;
         } else if ((size_t)len < sizeof(DHCPPacket))
                 return 0;
 
@@ -1714,7 +1772,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
 }
 
 int sd_dhcp_client_new(sd_dhcp_client **ret) {
-        _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
+        _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
 
         assert_return(ret, -EINVAL);
 
index 8befedc5002cacc57e9ef792912211da9201f08f..7a119fd4887cc45342992b715f4e2e9853b6d925 100644 (file)
@@ -37,6 +37,7 @@
 #include "in-addr-util.h"
 #include "network-internal.h"
 #include "parse-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "unaligned.h"
 
@@ -205,14 +206,28 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
         return 0;
 }
 
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
+/*
+ * The returned routes array must be freed by the caller.
+ * Route objects have the same lifetime of the lease and must not be freed.
+ */
+int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
+        sd_dhcp_route **ret;
+        unsigned i;
+
         assert_return(lease, -EINVAL);
         assert_return(routes, -EINVAL);
 
         if (lease->static_route_size <= 0)
                 return -ENODATA;
 
-        *routes = lease->static_route;
+        ret = new(sd_dhcp_route *, lease->static_route_size);
+        if (!ret)
+                return -ENOMEM;
+
+        for (i = 0; i < lease->static_route_size; i++)
+                ret[i] = &lease->static_route[i];
+
+        *routes = ret;
         return (int) lease->static_route_size;
 }
 
@@ -338,6 +353,38 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
         return 0;
 }
 
+static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
+        _cleanup_free_ char *name = NULL, *normalized = NULL;
+        int r;
+
+        assert(option);
+        assert(ret);
+
+        r = lease_parse_string(option, len, &name);
+        if (r < 0)
+                return r;
+        if (!name) {
+                *ret = mfree(*ret);
+                return 0;
+        }
+
+        r = dns_name_normalize(name, &normalized);
+        if (r < 0)
+                return r;
+
+        if (is_localhost(normalized))
+                return -EINVAL;
+
+        if (dns_name_is_root(normalized))
+                return -EINVAL;
+
+        free(*ret);
+        *ret = normalized;
+        normalized = NULL;
+
+        return 0;
+}
+
 static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
         assert(option);
         assert(ret);
@@ -452,7 +499,7 @@ static int lease_parse_classless_routes(
                 if (len < 4)
                         return -EINVAL;
 
-                lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+                assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
                 option += 4;
                 len -= 4;
 
@@ -470,21 +517,21 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
 
         switch(code) {
 
-        case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
+        case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
                 r = lease_parse_u32(option, len, &lease->lifetime, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
 
                 break;
 
-        case DHCP_OPTION_SERVER_IDENTIFIER:
+        case SD_DHCP_OPTION_SERVER_IDENTIFIER:
                 r = lease_parse_be32(option, len, &lease->server_address);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
 
                 break;
 
-        case DHCP_OPTION_SUBNET_MASK:
+        case SD_DHCP_OPTION_SUBNET_MASK:
                 r = lease_parse_be32(option, len, &lease->subnet_mask);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
@@ -492,7 +539,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         lease->have_subnet_mask = true;
                 break;
 
-        case DHCP_OPTION_BROADCAST:
+        case SD_DHCP_OPTION_BROADCAST:
                 r = lease_parse_be32(option, len, &lease->broadcast);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
@@ -500,7 +547,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         lease->have_broadcast = true;
                 break;
 
-        case DHCP_OPTION_ROUTER:
+        case SD_DHCP_OPTION_ROUTER:
                 if (len >= 4) {
                         r = lease_parse_be32(option, 4, &lease->router);
                         if (r < 0)
@@ -508,103 +555,67 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 }
                 break;
 
-        case DHCP_OPTION_DOMAIN_NAME_SERVER:
+        case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
                 r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_NTP_SERVER:
+        case SD_DHCP_OPTION_NTP_SERVER:
                 r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_STATIC_ROUTE:
+        case SD_DHCP_OPTION_STATIC_ROUTE:
                 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_INTERFACE_MTU:
+        case SD_DHCP_OPTION_INTERFACE_MTU:
                 r = lease_parse_u16(option, len, &lease->mtu, 68);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_DOMAIN_NAME: {
-                _cleanup_free_ char *domainname = NULL, *normalized = NULL;
-
-                r = lease_parse_string(option, len, &domainname);
+        case SD_DHCP_OPTION_DOMAIN_NAME:
+                r = lease_parse_domain(option, len, &lease->domainname);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
                         return 0;
                 }
 
-                r = dns_name_normalize(domainname, &normalized);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
-                        return 0;
-                }
-
-                if (is_localhost(normalized)) {
-                        log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
-                        break;
-                }
-
-                free(lease->domainname);
-                lease->domainname = normalized;
-                normalized = NULL;
-
                 break;
-        }
-
-        case DHCP_OPTION_HOST_NAME: {
-                _cleanup_free_ char *hostname = NULL, *normalized = NULL;
 
-                r = lease_parse_string(option, len, &hostname);
+        case SD_DHCP_OPTION_HOST_NAME:
+                r = lease_parse_domain(option, len, &lease->hostname);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to parse host name, ignoring: %m");
                         return 0;
                 }
 
-                r = dns_name_normalize(hostname, &normalized);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
-                        return 0;
-                }
-
-                if (is_localhost(normalized)) {
-                        log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
-                        return 0;
-                }
-
-                free(lease->hostname);
-                lease->hostname = normalized;
-                normalized = NULL;
-
                 break;
-        }
 
-        case DHCP_OPTION_ROOT_PATH:
+        case SD_DHCP_OPTION_ROOT_PATH:
                 r = lease_parse_string(option, len, &lease->root_path);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse root path, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_RENEWAL_T1_TIME:
+        case SD_DHCP_OPTION_RENEWAL_T1_TIME:
                 r = lease_parse_u32(option, len, &lease->t1, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_REBINDING_T2_TIME:
+        case SD_DHCP_OPTION_REBINDING_T2_TIME:
                 r = lease_parse_u32(option, len, &lease->t2, 1);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+        case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
                 r = lease_parse_classless_routes(
                                 option, len,
                                 &lease->static_route,
@@ -614,7 +625,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
                 break;
 
-        case DHCP_OPTION_NEW_TZDB_TIMEZONE: {
+        case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: {
                 _cleanup_free_ char *tz = NULL;
 
                 r = lease_parse_string(option, len, &tz);
@@ -635,7 +646,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 break;
         }
 
-        case DHCP_OPTION_VENDOR_SPECIFIC:
+        case SD_DHCP_OPTION_VENDOR_SPECIFIC:
 
                 if (len <= 0)
                         lease->vendor_specific = mfree(lease->vendor_specific);
@@ -653,7 +664,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 lease->vendor_specific_len = len;
                 break;
 
-        case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST:
+        case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
                 r = dhcp_lease_insert_private_option(lease, code, option, len);
                 if (r < 0)
                         return r;
@@ -661,7 +672,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 break;
 
         default:
-                log_debug("Ignoring option DHCP option %i while parsing.", code);
+                log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code);
                 break;
         }
 
@@ -722,7 +733,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         size_t client_id_len, data_len;
         const char *string;
         uint16_t mtu;
-        struct sd_dhcp_route *routes;
+        _cleanup_free_ sd_dhcp_route **routes = NULL;
         uint32_t t1, t2, lifetime;
         int r;
 
@@ -839,7 +850,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         LIST_FOREACH(options, option, lease->private_options) {
                 char key[strlen("OPTION_000")+1];
 
-                snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag);
+                xsprintf(key, "OPTION_%" PRIu8, option->tag);
                 r = serialize_dhcp_option(f, key, option->data, option->length);
                 if (r < 0)
                         goto fail;
@@ -865,7 +876,7 @@ fail:
 
 int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
 
-        _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
+        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
         _cleanup_free_ char
                 *address = NULL,
                 *router = NULL,
@@ -882,7 +893,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                 *lifetime = NULL,
                 *t1 = NULL,
                 *t2 = NULL,
-                *options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {};
+                *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {};
 
         int r, i;
 
@@ -1050,7 +1061,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
         }
 
-        for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) {
+        for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
                 _cleanup_free_ void *data = NULL;
                 size_t len;
 
@@ -1063,7 +1074,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         continue;
                 }
 
-                r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len);
+                r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
                 if (r < 0)
                         return r;
         }
@@ -1141,3 +1152,27 @@ int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
         *tz = lease->timezone;
         return 0;
 }
+
+int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
+        assert_return(route, -EINVAL);
+        assert_return(destination, -EINVAL);
+
+        *destination = route->dst_addr;
+        return 0;
+}
+
+int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
+        assert_return(route, -EINVAL);
+        assert_return(length, -EINVAL);
+
+        *length = route->dst_prefixlen;
+        return 0;
+}
+
+int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
+        assert_return(route, -EINVAL);
+        assert_return(gateway, -EINVAL);
+
+        *gateway = route->gw_addr;
+        return 0;
+}
index 277c88e2b98360f91ef28b9ec31acdfece3b6073..ad3a37b722977d68685e0e11aee95c0baea5e17d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -185,7 +183,7 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
 }
 
 int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
-        _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
 
         assert_return(ret, -EINVAL);
         assert_return(ifindex > 0, -EINVAL);
@@ -354,13 +352,13 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
         assert(packet);
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
-                               DHCP_OPTION_SERVER_IDENTIFIER,
+                               SD_DHCP_OPTION_SERVER_IDENTIFIER,
                                4, &server->address);
         if (r < 0)
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
-                               DHCP_OPTION_END, 0, NULL);
+                               SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -457,18 +455,18 @@ static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req,
 
         lease_time = htobe32(req->lifetime);
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
+                               SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
                                &lease_time);
         if (r < 0)
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+                               SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
         if (r < 0)
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_ROUTER, 4, &server->address);
+                               SD_DHCP_OPTION_ROUTER, 4, &server->address);
         if (r < 0)
                 return r;
 
@@ -494,25 +492,25 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
 
         lease_time = htobe32(req->lifetime);
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
+                               SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
                                &lease_time);
         if (r < 0)
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+                               SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
         if (r < 0)
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
-                               DHCP_OPTION_ROUTER, 4, &server->address);
+                               SD_DHCP_OPTION_ROUTER, 4, &server->address);
         if (r < 0)
                 return r;
 
         if (server->n_dns > 0) {
                 r = dhcp_option_append(
                                 &packet->dhcp, req->max_optlen, &offset, 0,
-                                DHCP_OPTION_DOMAIN_NAME_SERVER,
+                                SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
                                 sizeof(struct in_addr) * server->n_dns, server->dns);
                 if (r < 0)
                         return r;
@@ -521,7 +519,7 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
         if (server->n_ntp > 0) {
                 r = dhcp_option_append(
                                 &packet->dhcp, req->max_optlen, &offset, 0,
-                                DHCP_OPTION_NTP_SERVER,
+                                SD_DHCP_OPTION_NTP_SERVER,
                                 sizeof(struct in_addr) * server->n_ntp, server->ntp);
                 if (r < 0)
                         return r;
@@ -530,7 +528,7 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
         if (server->timezone) {
                 r = dhcp_option_append(
                                 &packet->dhcp, req->max_optlen, &offset, 0,
-                                DHCP_OPTION_NEW_TZDB_TIMEZONE,
+                                SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
                                 strlen(server->timezone), server->timezone);
                 if (r < 0)
                         return r;
@@ -576,7 +574,7 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
                 return r;
 
         r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
-                               &optoffset, 0, DHCP_OPTION_END, 0, NULL);
+                               &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
                 return r;
 
@@ -596,22 +594,22 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
         assert(req);
 
         switch(code) {
-        case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
+        case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
                 if (len == 4)
                         req->lifetime = be32toh(*(be32_t*)option);
 
                 break;
-        case DHCP_OPTION_REQUESTED_IP_ADDRESS:
+        case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS:
                 if (len == 4)
                         req->requested_ip = *(be32_t*)option;
 
                 break;
-        case DHCP_OPTION_SERVER_IDENTIFIER:
+        case SD_DHCP_OPTION_SERVER_IDENTIFIER:
                 if (len == 4)
                         req->server_id = *(be32_t*)option;
 
                 break;
-        case DHCP_OPTION_CLIENT_IDENTIFIER:
+        case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
                 if (len >= 2) {
                         uint8_t *data;
 
@@ -625,7 +623,7 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
                 }
 
                 break;
-        case DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
+        case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
                 if (len == 2)
                         req->max_optlen = be16toh(*(be16_t*)option) -
                                           - sizeof(DHCPPacket);
@@ -699,6 +697,7 @@ static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                size_t length) {
         _cleanup_dhcp_request_free_ DHCPRequest *req = NULL;
+        _cleanup_free_ char *error_message = NULL;
         DHCPLease *existing_lease;
         int type, r;
 
@@ -714,7 +713,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
         if (!req)
                 return -ENOMEM;
 
-        type = dhcp_option_parse(message, length, parse_request, req);
+        type = dhcp_option_parse(message, length, parse_request, req, &error_message);
         if (type < 0)
                 return 0;
 
@@ -784,8 +783,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                 break;
         }
         case DHCP_DECLINE:
-                log_dhcp_server(server, "DECLINE (0x%x)",
-                                be32toh(req->message->xid));
+                log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message));
 
                 /* TODO: make sure we don't offer this address again */
 
@@ -963,10 +961,10 @@ static int server_receive_message(sd_event_source *s, int fd,
 
         if (ioctl(fd, FIONREAD, &buflen) < 0)
                 return -errno;
-        if (buflen < 0)
+        else if (buflen < 0)
                 return -EIO;
 
-        message = malloc0(buflen);
+        message = malloc(buflen);
         if (!message)
                 return -ENOMEM;
 
@@ -974,9 +972,12 @@ static int server_receive_message(sd_event_source *s, int fd,
         iov.iov_len = buflen;
 
         len = recvmsg(fd, &msg, 0);
-        if (len < buflen)
-                return 0;
-        else if ((size_t)len < sizeof(DHCPMessage))
+        if (len < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                return -errno;
+        } else if ((size_t)len < sizeof(DHCPMessage))
                 return 0;
 
         CMSG_FOREACH(cmsg, &msg) {
index 801331d270ba61824b75c8b6fdc71d9d8e85d0f5..5b6b9cbcaca901e245606cb1e57fa3e9e7f9b583 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -72,10 +70,10 @@ struct sd_dhcp6_client {
 };
 
 static const uint16_t default_req_opts[] = {
-        DHCP6_OPTION_DNS_SERVERS,
-        DHCP6_OPTION_DOMAIN_LIST,
-        DHCP6_OPTION_NTP_SERVER,
-        DHCP6_OPTION_SNTP_SERVERS,
+        SD_DHCP6_OPTION_DNS_SERVERS,
+        SD_DHCP6_OPTION_DOMAIN_LIST,
+        SD_DHCP6_OPTION_NTP_SERVER,
+        SD_DHCP6_OPTION_SNTP_SERVERS,
 };
 
 const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
@@ -107,11 +105,8 @@ const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
-#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
-
 #define DHCP6_CLIENT_DONT_DESTROY(client) \
-        _cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
+        _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
 
 static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
 
@@ -248,10 +243,10 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
         assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         switch(option) {
-        case DHCP6_OPTION_DNS_SERVERS:
-        case DHCP6_OPTION_DOMAIN_LIST:
-        case DHCP6_OPTION_SNTP_SERVERS:
-        case DHCP6_OPTION_NTP_SERVER:
+        case SD_DHCP6_OPTION_DNS_SERVERS:
+        case SD_DHCP6_OPTION_DOMAIN_LIST:
+        case SD_DHCP6_OPTION_SNTP_SERVERS:
+        case SD_DHCP6_OPTION_NTP_SERVER:
                 break;
 
         default:
@@ -365,7 +360,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 message->type = DHCP6_SOLICIT;
 
                 r = dhcp6_option_append(&opt, &optlen,
-                                        DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+                                        SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
                 if (r < 0)
                         return r;
 
@@ -383,7 +378,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 else
                         message->type = DHCP6_RENEW;
 
-                r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
+                r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
                                         client->lease->serverid_len,
                                         client->lease->serverid);
                 if (r < 0)
@@ -409,14 +404,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
                 return -EINVAL;
         }
 
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
                                 client->req_opts_len * sizeof(be16_t),
                                 client->req_opts);
         if (r < 0)
                 return r;
 
         assert (client->duid_len);
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
                                 client->duid_len, &client->duid);
         if (r < 0)
                 return r;
@@ -427,7 +422,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
         else
                 elapsed_time = 0xffff;
 
-        r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
+        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME,
                                 sizeof(elapsed_time), &elapsed_time);
         if (r < 0)
                 return r;
@@ -690,7 +685,7 @@ static int client_parse_message(sd_dhcp6_client *client,
         while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
                                        &optval)) >= 0) {
                 switch (optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         if (clientid) {
                                 log_dhcp6_client(client, "%s contains multiple clientids",
                                                  dhcp6_message_type_to_string(message->type));
@@ -708,7 +703,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_SERVERID:
+                case SD_DHCP6_OPTION_SERVERID:
                         r = dhcp6_lease_get_serverid(lease, &id, &id_len);
                         if (r >= 0 && id) {
                                 log_dhcp6_client(client, "%s contains multiple serverids",
@@ -722,7 +717,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_PREFERENCE:
+                case SD_DHCP6_OPTION_PREFERENCE:
                         if (optlen != 1)
                                 return -EINVAL;
 
@@ -732,7 +727,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_STATUS_CODE:
+                case SD_DHCP6_OPTION_STATUS_CODE:
                         if (optlen < 2)
                                 return -EINVAL;
 
@@ -746,7 +741,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
                                 log_dhcp6_client(client, "Information request ignoring IA NA option");
 
@@ -770,35 +765,35 @@ static int client_parse_message(sd_dhcp6_client *client,
 
                         break;
 
-                case DHCP6_OPTION_RAPID_COMMIT:
+                case SD_DHCP6_OPTION_RAPID_COMMIT:
                         r = dhcp6_lease_set_rapid_commit(lease);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_DNS_SERVERS:
+                case SD_DHCP6_OPTION_DNS_SERVERS:
                         r = dhcp6_lease_set_dns(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_DOMAIN_LIST:
+                case SD_DHCP6_OPTION_DOMAIN_LIST:
                         r = dhcp6_lease_set_domains(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_NTP_SERVER:
+                case SD_DHCP6_OPTION_NTP_SERVER:
                         r = dhcp6_lease_set_ntp(lease, optval, optlen);
                         if (r < 0)
                                 return r;
 
                         break;
 
-                case DHCP6_OPTION_SNTP_SERVERS:
+                case SD_DHCP6_OPTION_SNTP_SERVERS:
                         r = dhcp6_lease_set_sntp(lease, optval, optlen);
                         if (r < 0)
                                 return r;
@@ -829,7 +824,7 @@ static int client_parse_message(sd_dhcp6_client *client,
 
 static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
         int r;
-        _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         bool rapid_commit;
 
         if (reply->type != DHCP6_REPLY)
@@ -860,7 +855,7 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
 
 static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
         int r;
-        _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t pref_advertise = 0, pref_lease = 0;
 
         if (advertise->type != DHCP6_ADVERTISE)
@@ -895,7 +890,7 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
 static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         sd_dhcp6_client *client = userdata;
         DHCP6_CLIENT_DONT_DESTROY(client);
-        _cleanup_free_ DHCP6Message *message;
+        _cleanup_free_ DHCP6Message *message = NULL;
         int r, buflen, len;
 
         assert(s);
@@ -903,18 +898,26 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
         assert(client->event);
 
         r = ioctl(fd, FIONREAD, &buflen);
-        if (r < 0 || buflen <= 0)
-                buflen = DHCP6_MIN_OPTIONS_SIZE;
+        if (r < 0)
+                return -errno;
+        else if (buflen < 0)
+                /* This really should not happen */
+                return -EIO;
 
-        message = malloc0(buflen);
+        message = malloc(buflen);
         if (!message)
                 return -ENOMEM;
 
         len = read(fd, message, buflen);
-        if ((size_t)len < sizeof(DHCP6Message)) {
-                log_dhcp6_client(client, "could not receive message from UDP socket: %m");
+        if (len < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                log_dhcp6_client(client, "Could not receive message from UDP socket: %m");
+
+                return -errno;
+        } else if ((size_t)len < sizeof(DHCP6Message))
                 return 0;
-        }
 
         switch(message->type) {
         case DHCP6_SOLICIT:
@@ -1269,7 +1272,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
 }
 
 int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
-        _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
+        _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
         size_t t;
 
         assert_return(ret, -EINVAL);
@@ -1280,7 +1283,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
 
         client->n_ref = 1;
 
-        client->ia_na.type = DHCP6_OPTION_IA_NA;
+        client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
 
         client->index = -1;
 
index 3f32ba35e7f300ed68ee2042f4e4f40b92ba35be..5c10a6326a3711b5feeab584d91338ea73340ea8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -256,7 +254,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
         assert_return(lease, -EINVAL);
         assert_return(optval, -EINVAL);
 
-        free(lease->ntp);
+        lease->ntp = mfree(lease->ntp);
         lease->ntp_count = 0;
         lease->ntp_allocated = 0;
 
index 5340fdc0c1f70317c60ea5ed577233dd345362c5..f7880a891c78bc4f91afb7b18a2c6625e5e1be84 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "alloc-util.h"
 #include "arp-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "in-addr-util.h"
 #include "list.h"
@@ -120,11 +119,8 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) {
         return NULL;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4acd*, sd_ipv4acd_unref);
-#define _cleanup_ipv4acd_unref_ _cleanup_(sd_ipv4acd_unrefp)
-
 int sd_ipv4acd_new(sd_ipv4acd **ret) {
-        _cleanup_ipv4acd_unref_ sd_ipv4acd *ll = NULL;
+        _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL;
 
         assert_return(ret, -EINVAL);
 
@@ -189,7 +185,7 @@ int sd_ipv4acd_stop(sd_ipv4acd *ll) {
 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
 
 static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) {
-        _cleanup_event_source_unref_ sd_event_source *timer = NULL;
+        _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
         usec_t next_timeout;
         usec_t time_now;
         int r;
index 30a7ef57857df73cbccbbfb1343f746e0b9ef32c..db6cf22aaa47015de7cc3c31f20be93fa6f26208 100644 (file)
@@ -28,7 +28,6 @@
 #include "sd-ipv4ll.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "in-addr-util.h"
 #include "list.h"
 #include "random-util.h"
@@ -41,7 +40,7 @@
 #define IPV4LL_NETMASK 0xFFFF0000L
 
 #define IPV4LL_DONT_DESTROY(ll) \
-        _cleanup_ipv4ll_unref_ _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
+        _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
 
 struct sd_ipv4ll {
         unsigned n_ref;
@@ -86,13 +85,10 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
         return NULL;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
-#define _cleanup_ipv4ll_unref_ _cleanup_(sd_ipv4ll_unrefp)
-
 static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
 
 int sd_ipv4ll_new(sd_ipv4ll **ret) {
-        _cleanup_ipv4ll_unref_ sd_ipv4ll *ll = NULL;
+        _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
index 4ebe8053fa2e61cd0254757e289a3cf2966df847..885ca62425d8e03b836c890b2bb76b18334066c2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
@@ -31,7 +29,6 @@
 #include "lldp-internal.h"
 #include "lldp-port.h"
 #include "lldp-tlv.h"
-#include "lldp-util.h"
 #include "prioq.h"
 #include "siphash24.h"
 #include "string-util.h"
@@ -146,12 +143,9 @@ static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) {
 
 /* 10.3.2 LLDPDU validation: rxProcessFrame() */
 int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
+        bool system_description = false, system_name = false, chassis_id = false;
+        bool malformed = false, port_id = false, ttl = false, end = false;
         uint16_t type, len, i, l, t;
-        bool chassis_id = false;
-        bool malformed = false;
-        bool port_id = false;
-        bool ttl = false;
-        bool end = false;
         lldp_port *port;
         uint8_t *p, *q;
         sd_lldp *lldp;
@@ -164,8 +158,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
         lldp = (sd_lldp *) port->userdata;
 
         if (lldp->port->status == LLDP_PORT_STATUS_DISABLED) {
-                log_lldp("Port is disabled : %s . Dropping ...",
-                         lldp->port->ifname);
+                log_lldp("Port: %s is disabled. Dropping.", lldp->port->ifname);
                 goto out;
         }
 
@@ -183,8 +176,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
 
                 if (type == LLDP_TYPE_END) {
                         if (len != 0) {
-                                log_lldp("TLV type end is not length 0. Length:%d received . Dropping ...",
-                                         len);
+                                log_lldp("TLV type end must be length 0 (not %d). Dropping.", len);
 
                                 malformed = true;
                                 goto out;
@@ -194,8 +186,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
 
                         break;
                 } else if (type >=_LLDP_TYPE_MAX) {
-                        log_lldp("TLV type not recognized %d . Dropping ...",
-                                 type);
+                        log_lldp("TLV type: %d not recognized. Dropping.", type);
 
                         malformed = true;
                         goto out;
@@ -210,7 +201,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
 
                 if (i <= 3) {
                         if (i != type) {
-                                log_lldp("TLV missing or out of order. Dropping ...");
+                                log_lldp("TLV missing or out of order. Dropping.");
 
                                 malformed = true;
                                 goto out;
@@ -221,25 +212,22 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
                 case LLDP_TYPE_CHASSIS_ID:
 
                         if (len < 2) {
-                                log_lldp("Received malformed Chassis ID TLV len = %d. Dropping",
-                                         len);
+                                log_lldp("Received malformed Chassis ID TLV length: %d. Dropping.", len);
 
                                 malformed = true;
                                 goto out;
                         }
 
                         if (chassis_id) {
-                                log_lldp("Duplicate Chassis ID TLV found. Dropping ...");
+                                log_lldp("Duplicate Chassis ID TLV found. Dropping.");
 
                                 malformed = true;
                                 goto out;
                         }
 
                         /* Look what subtype it has */
-                        if (*q == LLDP_CHASSIS_SUBTYPE_RESERVED ||
-                            *q > LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED) {
-                                log_lldp("Unknown subtype: %d found in Chassis ID TLV . Dropping ...",
-                                         *q);
+                        if (*q == LLDP_CHASSIS_SUBTYPE_RESERVED || *q > LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED) {
+                                log_lldp("Unknown subtype: %d found in Chassis ID TLV. Dropping.", *q);
 
                                 malformed = true;
                                 goto out;
@@ -252,25 +240,22 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
                 case LLDP_TYPE_PORT_ID:
 
                         if (len < 2) {
-                                log_lldp("Received malformed Port ID TLV len = %d. Dropping",
-                                         len);
+                                log_lldp("Received malformed Port ID TLV length: %d. Dropping.", len);
 
                                 malformed = true;
                                 goto out;
                         }
 
                         if (port_id) {
-                                log_lldp("Duplicate Port ID TLV found. Dropping ...");
+                                log_lldp("Duplicate Port ID TLV found. Dropping.");
 
                                 malformed = true;
                                 goto out;
                         }
 
                         /* Look what subtype it has */
-                        if (*q == LLDP_PORT_SUBTYPE_RESERVED ||
-                            *q > LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED) {
-                                log_lldp("Unknown subtype: %d found in Port ID TLV . Dropping ...",
-                                         *q);
+                        if (*q == LLDP_PORT_SUBTYPE_RESERVED || *q > LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED) {
+                                log_lldp("Unknown subtype: %d found in Port ID TLV. Dropping.", *q);
 
                                 malformed = true;
                                 goto out;
@@ -283,16 +268,14 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
                 case LLDP_TYPE_TTL:
 
                         if(len != 2) {
-                                log_lldp(
-                                         "Received invalid lenth: %d TTL TLV. Dropping ...",
-                                         len);
+                                log_lldp("Received invalid TTL TLV lenth: %d. Dropping.", len);
 
                                 malformed = true;
                                 goto out;
                         }
 
                         if (ttl) {
-                                log_lldp("Duplicate TTL TLV found. Dropping ...");
+                                log_lldp("Duplicate TTL TLV found. Dropping.");
 
                                 malformed = true;
                                 goto out;
@@ -300,12 +283,46 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
 
                         ttl = true;
 
+                        break;
+                case LLDP_TYPE_SYSTEM_NAME:
+
+                        /* According to RFC 1035 the length of a FQDN is limited to 255 characters */
+                        if (len > 255) {
+                                log_lldp("Received invalid system name length: %d. Dropping.", len);
+                                malformed = true;
+                                goto out;
+                        }
+
+                        if (system_name) {
+                                log_lldp("Duplicate system name found. Dropping.");
+                                malformed = true;
+                                goto out;
+                        }
+
+                        system_name = true;
+
+                        break;
+                case LLDP_TYPE_SYSTEM_DESCRIPTION:
+
+                        /* 0 <= n <= 255 octets */
+                        if (len > 255) {
+                                log_lldp("Received invalid system description length: %d. Dropping.", len);
+                                malformed = true;
+                                goto out;
+                        }
+
+                        if (system_description) {
+                                log_lldp("Duplicate system description found. Dropping.");
+                                malformed = true;
+                                goto out;
+                        }
+
+                        system_description = true;
                         break;
                 default:
 
                         if (len == 0) {
-                                log_lldp("TLV type = %d's, length 0 received . Dropping ...",
-                                         type);
+                                log_lldp("TLV type: %d length 0 received. Dropping.", type);
 
                                 malformed = true;
                                 goto out;
@@ -315,7 +332,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
         }
 
         if(!chassis_id || !port_id || !ttl || !end) {
-                log_lldp( "One or more mandotory TLV missing . Dropping ...");
+                log_lldp("One or more mandatory TLV missing. Dropping.");
 
                 malformed = true;
                 goto out;
@@ -324,7 +341,7 @@ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) {
 
         r = tlv_packet_parse_pdu(tlv, length);
         if (r < 0) {
-                log_lldp( "Failed to parse the TLV. Dropping ...");
+                log_lldp("Failed to parse the TLV. Dropping.");
 
                 malformed = true;
                 goto out;
@@ -652,10 +669,10 @@ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata) {
         return 0;
 }
 
-void sd_lldp_free(sd_lldp *lldp) {
+sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
 
         if (!lldp)
-                return;
+                return NULL;
 
         /* Drop all packets */
         lldp_mib_objects_flush(lldp);
@@ -666,13 +683,14 @@ void sd_lldp_free(sd_lldp *lldp) {
         prioq_free(lldp->by_expiry);
 
         free(lldp);
+        return NULL;
 }
 
 int sd_lldp_new(int ifindex,
                 const char *ifname,
                 const struct ether_addr *mac,
                 sd_lldp **ret) {
-        _cleanup_lldp_free_ sd_lldp *lldp = NULL;
+        _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
index 6703d87bc4173da04e56e65dab0daa75b175ba7b..519d2aa36b3f0dc7f32ce98fc8844b77663c9a90 100644 (file)
@@ -32,6 +32,7 @@
 #include "in-addr-util.h"
 #include "list.h"
 #include "socket-util.h"
+#include "string-util.h"
 
 #define NDISC_ROUTER_SOLICITATION_INTERVAL      4 * USEC_PER_SEC
 #define NDISC_MAX_ROUTER_SOLICITATIONS          3
@@ -111,7 +112,7 @@ static NDiscPrefix *ndisc_prefix_unref(NDiscPrefix *prefix) {
 }
 
 static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
-        _cleanup_free_ NDiscPrefix *prefix = NULL;
+        NDiscPrefix *prefix;
 
         assert(ret);
 
@@ -124,8 +125,6 @@ static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
         prefix->nd = nd;
 
         *ret = prefix;
-        prefix = NULL;
-
         return 0;
 }
 
@@ -244,11 +243,8 @@ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) {
         return NULL;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ndisc*, sd_ndisc_unref);
-#define _cleanup_sd_ndisc_free_ _cleanup_(sd_ndisc_unrefp)
-
 int sd_ndisc_new(sd_ndisc **ret) {
-        _cleanup_sd_ndisc_free_ sd_ndisc *nd = NULL;
+        _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL;
 
         assert(ret);
 
@@ -316,7 +312,6 @@ static int ndisc_prefix_match(sd_ndisc *nd, const struct in6_addr *addr,
         LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
                 if (prefix->valid_until < time_now) {
                         prefix = ndisc_prefix_unref(prefix);
-
                         continue;
                 }
 
@@ -357,14 +352,13 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
 
         r = ndisc_prefix_match(nd, &prefix_opt->nd_opt_pi_prefix,
                                prefix_opt->nd_opt_pi_prefix_len, &prefix);
+        if (r < 0) {
+                if (r != -EADDRNOTAVAIL)
+                        return r;
 
-        if (r < 0 && r != -EADDRNOTAVAIL)
-                return r;
-
-        /* if router advertisment prefix valid timeout is zero, the timeout
-           callback will be called immediately to clean up the prefix */
+                /* if router advertisment prefix valid timeout is zero, the timeout
+                   callback will be called immediately to clean up the prefix */
 
-        if (r == -EADDRNOTAVAIL) {
                 r = ndisc_prefix_new(nd, &prefix);
                 if (r < 0)
                         return r;
@@ -375,9 +369,9 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
                         sizeof(prefix->addr));
 
                 log_ndisc(nd, "New prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
-                             SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
-                             prefix->len, lifetime_valid,
-                             format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
+                          SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
+                          prefix->len, lifetime_valid,
+                          format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
 
                 LIST_PREPEND(prefixes, nd->prefixes, prefix);
 
@@ -388,17 +382,17 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
                         prefixlen = MIN(prefix->len, prefix_opt->nd_opt_pi_prefix_len);
 
                         log_ndisc(nd, "Prefix length mismatch %d/%d using %d",
-                                     prefix->len,
-                                     prefix_opt->nd_opt_pi_prefix_len,
-                                     prefixlen);
+                                  prefix->len,
+                                  prefix_opt->nd_opt_pi_prefix_len,
+                                  prefixlen);
 
                         prefix->len = prefixlen;
                 }
 
                 log_ndisc(nd, "Update prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
-                             SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
-                             prefix->len, lifetime_valid,
-                             format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
+                          SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
+                          prefix->len, lifetime_valid,
+                          format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
         }
 
         r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
@@ -417,8 +411,7 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
         return 0;
 }
 
-static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
-                          ssize_t len) {
+static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra, ssize_t len) {
         void *opt;
         struct nd_opt_hdr *opt_hdr;
 
@@ -453,7 +446,7 @@ static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
                                 nd->mtu = MAX(mtu, IP6_MIN_MTU);
 
                                 log_ndisc(nd, "Router Advertisement link MTU %d using %d",
-                                             mtu, nd->mtu);
+                                          mtu, nd->mtu);
                         }
 
                         break;
@@ -481,30 +474,86 @@ static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
 static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         _cleanup_free_ struct nd_router_advert *ra = NULL;
         sd_ndisc *nd = userdata;
-        int r, buflen = 0, pref, stateful;
-        union sockaddr_union router = {};
-        socklen_t router_len = sizeof(router);
+        union {
+                struct cmsghdr cmsghdr;
+                uint8_t buf[CMSG_LEN(sizeof(int))];
+        } 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;
+        struct in6_addr *gw;
         unsigned lifetime;
         ssize_t len;
+        int r, pref, stateful, buflen = 0;
 
         assert(s);
         assert(nd);
         assert(nd->event);
 
         r = ioctl(fd, FIONREAD, &buflen);
-        if (r < 0 || buflen <= 0)
-                buflen = ICMP6_RECV_SIZE;
+        if (r < 0)
+                return -errno;
+        else if (buflen < 0)
+                /* This really should not happen */
+                return -EIO;
+
+        iov.iov_len = buflen;
 
-        ra = malloc(buflen);
+        ra = malloc(iov.iov_len);
         if (!ra)
                 return -ENOMEM;
 
-        len = recvfrom(fd, ra, buflen, 0, &router.sa, &router_len);
+        iov.iov_base = ra;
+
+        len = recvmsg(fd, &msg, 0);
         if (len < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
                 log_ndisc(nd, "Could not receive message from ICMPv6 socket: %m");
+                return -errno;
+        } else if ((size_t)len < sizeof(struct nd_router_advert)) {
                 return 0;
-        } else if (router_len != sizeof(router.in6) && router_len != 0) {
-                log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)router_len);
+        } else if (msg.msg_namelen == 0)
+                gw = NULL; /* only happens when running the test-suite over a socketpair */
+        else if (msg.msg_namelen != sizeof(sa.in6)) {
+                log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)msg.msg_namelen);
+                return 0;
+        } else
+                gw = &sa.in6.sin6_addr;
+
+        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(nd, "Received RA with invalid hop limit %d. Ignoring.", hops);
+                                return 0;
+                        }
+
+                        break;
+                }
+        }
+
+        if (gw && !in_addr_is_link_local(AF_INET6, (const union in_addr_union*) gw)) {
+                _cleanup_free_ char *addr = NULL;
+
+                (void)in_addr_to_string(AF_INET6, (const union in_addr_union*) gw, &addr);
+
+                log_ndisc(nd, "Received RA from non-link-local address %s. Ignoring.", strna(addr));
                 return 0;
         }
 
@@ -544,7 +593,7 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
         }
 
         if (nd->router_callback)
-                nd->router_callback(nd, stateful, router_len != 0 ? &router.in6.sin6_addr : NULL, lifetime, pref, nd->userdata);
+                nd->router_callback(nd, stateful, gw, lifetime, pref, nd->userdata);
 
         return 0;
 }
@@ -552,8 +601,6 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
 static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_ndisc *nd = userdata;
         uint64_t time_now, next_timeout;
-        struct ether_addr unset = { };
-        struct ether_addr *addr = NULL;
         int r;
 
         assert(s);
@@ -567,10 +614,7 @@ static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
                         nd->callback(nd, SD_NDISC_EVENT_TIMEOUT, nd->userdata);
                 nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
         } else {
-                if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
-                        addr = &nd->mac_addr;
-
-                r = icmp6_send_router_solicitation(nd->fd, addr);
+                r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
                 if (r < 0)
                         log_ndisc(nd, "Error sending Router Solicitation");
                 else {
index 69eff5116f5eeecfa2bcf6833aa8573ac7a8f080..75564615b97bea16ebcbe8ae66d593d68ccb178f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,7 +28,6 @@
 #include "sd-ipv4acd.h"
 #include "sd-netlink.h"
 
-#include "event-util.h"
 #include "in-addr-util.h"
 #include "netlink-util.h"
 #include "util.h"
@@ -76,9 +73,9 @@ static int client_run(int ifindex, const struct in_addr *pa, const struct ether_
 }
 
 static int test_acd(const char *ifname, const char *address) {
-        _cleanup_event_unref_ sd_event *e = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
         union in_addr_union pa;
         struct ether_addr ha;
         int ifindex;
index 1200a7c251a526aef0189051dfd94a238847e5e5..c3c08fef5e8cb67a5c825e0ed2acdd3cb55c3b34 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -31,7 +29,6 @@
 #include "dhcp-identifier.h"
 #include "dhcp-internal.h"
 #include "dhcp-protocol.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "util.h"
 
@@ -78,26 +75,26 @@ static void test_request_basic(sd_event *e) {
         assert_se(sd_dhcp_client_set_index(client, 1) == 0);
 
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_SUBNET_MASK) == -EEXIST);
+                                        SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_ROUTER) == -EEXIST);
+                                        SD_DHCP_OPTION_ROUTER) == -EEXIST);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_HOST_NAME) == -EEXIST);
+                                        SD_DHCP_OPTION_HOST_NAME) == -EEXIST);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
+                                        SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
+                                        SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
 
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_PAD) == -EINVAL);
+                                        SD_DHCP_OPTION_PAD) == -EINVAL);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_END) == -EINVAL);
+                                        SD_DHCP_OPTION_END) == -EINVAL);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
+                                        SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_OVERLOAD) == -EINVAL);
+                                        SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
         assert_se(sd_dhcp_client_set_request_option(client,
-                                        DHCP_OPTION_PARAMETER_REQUEST_LIST)
+                                        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
                         == -EINVAL);
 
         assert_se(sd_dhcp_client_set_request_option(client, 33) == 0);
@@ -123,7 +120,7 @@ static void test_checksum(void) {
 
 static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
         switch(code) {
-        case DHCP_OPTION_CLIENT_IDENTIFIER:
+        case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
         {
                 uint32_t iaid;
                 struct duid duid;
@@ -223,7 +220,7 @@ int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const voi
 static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
         int res;
 
-        res = dhcp_option_parse(dhcp, size, check_options, NULL);
+        res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
         assert_se(res == DHCP_DISCOVER);
 
         if (verbose)
@@ -390,11 +387,11 @@ static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
         uint8_t *msg_bytes = (uint8_t *)request;
         int res;
 
-        res = dhcp_option_parse(request, size, check_options, NULL);
+        res = dhcp_option_parse(request, size, check_options, NULL, NULL);
         assert_se(res == DHCP_REQUEST);
         assert_se(xid == request->xid);
 
-        assert_se(msg_bytes[size - 1] == DHCP_OPTION_END);
+        assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
 
         if (verbose)
                 printf("  recv DHCP Request  0x%08x\n", be32toh(xid));
@@ -420,10 +417,10 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
         uint8_t *msg_bytes = (uint8_t *)discover;
         int res;
 
-        res = dhcp_option_parse(discover, size, check_options, NULL);
+        res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
         assert_se(res == DHCP_DISCOVER);
 
-        assert_se(msg_bytes[size - 1] == DHCP_OPTION_END);
+        assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
 
         xid = discover->xid;
 
@@ -491,7 +488,7 @@ static void test_addr_acq(sd_event *e) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_event_unref_ sd_event *e;
+        _cleanup_(sd_event_unrefp) sd_event *e;
 
         log_set_max_level(LOG_DEBUG);
         log_parse_environment();
index 3607df63af99814cc793deebe67bdb6f8ded179c..7d8a95722796f52d4d5d744a3c45dc2652020e81 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -29,7 +27,7 @@ static bool verbose = false;
 static struct option_desc option_tests[] = {
         { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, },
         { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0,
-                          DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
+                          SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, },
         { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, },
         { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8,
                           0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01,
@@ -37,17 +35,17 @@ static struct option_desc option_tests[] = {
                           0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00,
                           0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
           40, true, },
-        { {}, 0, {}, 0, { DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
+        { {}, 0, {}, 0, { SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER,
                           42, 3, 0, 0, 0 }, 8, true, },
         { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, },
 
         { {}, 0,
-          { 222, 3, 1, 2, 3, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
-          { DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
+          { 222, 3, 1, 2, 3, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8,
+          { SD_DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, },
 
-        { { 1, 4, 1, 2, 3, 4, DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
+        { { 1, 4, 1, 2, 3, 4, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9,
           { 222, 3, 1, 2, 3 }, 5,
-          { DHCP_OPTION_OVERLOAD, 1,
+          { SD_DHCP_OPTION_OVERLOAD, 1,
             DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, },
 };
 
@@ -75,9 +73,8 @@ static const char *dhcp_type(int type) {
 static void test_invalid_buffer_length(void) {
         DHCPMessage message;
 
-        assert_se(dhcp_option_parse(&message, 0, NULL, NULL) == -EINVAL);
-        assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL)
-               == -EINVAL);
+        assert_se(dhcp_option_parse(&message, 0, NULL, NULL, NULL) == -EINVAL);
+        assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL, NULL) == -EINVAL);
 }
 
 static void test_message_init(void) {
@@ -101,7 +98,7 @@ static void test_message_init(void) {
         assert_se(magic[2] == 83);
         assert_se(magic[3] == 99);
 
-        assert_se(dhcp_option_parse(message, len, NULL, NULL) >= 0);
+        assert_se(dhcp_option_parse(message, len, NULL, NULL, NULL) >= 0);
 }
 
 static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
@@ -130,12 +127,12 @@ static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) {
 
         while (*descpos < *desclen) {
                 switch(descoption[*descpos]) {
-                case DHCP_OPTION_PAD:
+                case SD_DHCP_OPTION_PAD:
                         *descpos += 1;
                         break;
 
-                case DHCP_OPTION_MESSAGE_TYPE:
-                case DHCP_OPTION_OVERLOAD:
+                case SD_DHCP_OPTION_MESSAGE_TYPE:
+                case SD_DHCP_OPTION_OVERLOAD:
                         *descpos += 3;
                         break;
 
@@ -158,10 +155,10 @@ static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *
         if (!desc)
                 return -EINVAL;
 
-        assert_se(code != DHCP_OPTION_PAD);
-        assert_se(code != DHCP_OPTION_END);
-        assert_se(code != DHCP_OPTION_MESSAGE_TYPE);
-        assert_se(code != DHCP_OPTION_OVERLOAD);
+        assert_se(code != SD_DHCP_OPTION_PAD);
+        assert_se(code != SD_DHCP_OPTION_END);
+        assert_se(code != SD_DHCP_OPTION_MESSAGE_TYPE);
+        assert_se(code != SD_DHCP_OPTION_OVERLOAD);
 
         while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) {
 
@@ -264,19 +261,12 @@ static void test_options(struct option_desc *desc) {
         buflen = sizeof(DHCPMessage) + optlen;
 
         if (!desc) {
-                assert_se((res = dhcp_option_parse(message, buflen,
-                                                test_options_cb,
-                                                NULL)) == -ENOMSG);
+                assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, NULL, NULL)) == -ENOMSG);
         } else if (desc->success) {
-                assert_se((res = dhcp_option_parse(message, buflen,
-                                                test_options_cb,
-                                                desc)) >= 0);
-                assert_se(desc->pos == -1 && desc->filepos == -1 &&
-                                desc->snamepos == -1);
+                assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) >= 0);
+                assert_se(desc->pos == -1 && desc->filepos == -1 && desc->snamepos == -1);
         } else
-                assert_se((res = dhcp_option_parse(message, buflen,
-                                                test_options_cb,
-                                                desc)) < 0);
+                assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) < 0);
 
         if (verbose)
                 printf("DHCP type %s\n", dhcp_type(res));
@@ -306,27 +296,27 @@ static void test_option_set(void) {
         result->options[2] = 'C';
         result->options[3] = 'D';
 
-        assert_se(dhcp_option_append(result, 0, &offset, 0, DHCP_OPTION_PAD,
+        assert_se(dhcp_option_append(result, 0, &offset, 0, SD_DHCP_OPTION_PAD,
                                      0, NULL) == -ENOBUFS);
         assert_se(offset == 0);
 
         offset = 4;
-        assert_se(dhcp_option_append(result, 5, &offset, 0, DHCP_OPTION_PAD,
+        assert_se(dhcp_option_append(result, 5, &offset, 0, SD_DHCP_OPTION_PAD,
                                      0, NULL) == -ENOBUFS);
         assert_se(offset == 4);
-        assert_se(dhcp_option_append(result, 6, &offset, 0, DHCP_OPTION_PAD,
+        assert_se(dhcp_option_append(result, 6, &offset, 0, SD_DHCP_OPTION_PAD,
                                      0, NULL) >= 0);
         assert_se(offset == 5);
 
         offset = pos = 4;
         len = 11;
-        while (pos < len && options[pos] != DHCP_OPTION_END) {
+        while (pos < len && options[pos] != SD_DHCP_OPTION_END) {
                 assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME,
                                              options[pos],
                                              options[pos + 1],
                                              &options[pos + 2]) >= 0);
 
-                if (options[pos] == DHCP_OPTION_PAD)
+                if (options[pos] == SD_DHCP_OPTION_PAD)
                         pos++;
                 else
                         pos += 2 + options[pos + 1];
@@ -344,15 +334,15 @@ static void test_option_set(void) {
 
         if (verbose)
                 printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9],
-                       DHCP_OPTION_END);
+                       SD_DHCP_OPTION_END);
 
-        assert_se(result->options[9] == DHCP_OPTION_END);
+        assert_se(result->options[9] == SD_DHCP_OPTION_END);
 
         if (verbose)
                 printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10],
-                       DHCP_OPTION_PAD);
+                       SD_DHCP_OPTION_PAD);
 
-        assert_se(result->options[10] == DHCP_OPTION_PAD);
+        assert_se(result->options[10] == SD_DHCP_OPTION_PAD);
 
         for (i = 0; i < pos - 8; i++) {
                 if (verbose)
index 2b5f59e4d66b528cae77665c9a7038477f96f5b5..e81c508c7ff1e1f712b7f6d1cf2f5756d35608d6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "sd-event.h"
 
 #include "dhcp-server-internal.h"
-#include "event-util.h"
 
 static void test_pool(struct in_addr *address, unsigned size, int ret) {
-        _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
 
         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
 
@@ -37,7 +34,7 @@ static void test_pool(struct in_addr *address, unsigned size, int ret) {
 }
 
 static int test_basic(sd_event *event) {
-        _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
         struct in_addr address_lo = {
                 .s_addr = htonl(INADDR_LOOPBACK),
         };
@@ -86,7 +83,7 @@ static int test_basic(sd_event *event) {
 }
 
 static void test_message_handler(void) {
-        _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
+        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
         struct {
                 DHCPMessage message;
                 struct {
@@ -116,10 +113,10 @@ static void test_message_handler(void) {
                 .message.hlen = ETHER_ADDR_LEN,
                 .message.xid = htobe32(0x12345678),
                 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
-                .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
+                .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE,
                 .option_type.length = 1,
                 .option_type.type = DHCP_DISCOVER,
-                .end = DHCP_OPTION_END,
+                .end = SD_DHCP_OPTION_END,
         };
         struct in_addr address_lo = {
                 .s_addr = htonl(INADDR_LOOPBACK),
@@ -135,14 +132,14 @@ static void test_message_handler(void) {
         test.end = 0;
         /* TODO, shouldn't this fail? */
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
-        test.end = DHCP_OPTION_END;
+        test.end = SD_DHCP_OPTION_END;
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
 
         test.option_type.code = 0;
         test.option_type.length = 0;
         test.option_type.type = 0;
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
-        test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
+        test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE;
         test.option_type.length = 1;
         test.option_type.type = DHCP_DISCOVER;
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
@@ -164,11 +161,11 @@ static void test_message_handler(void) {
 
         test.option_type.type = DHCP_REQUEST;
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
-        test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
+        test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS;
         test.option_requested_ip.length = 4;
         test.option_requested_ip.address = htobe32(0x12345678);
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
-        test.option_server_id.code = DHCP_OPTION_SERVER_IDENTIFIER;
+        test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER;
         test.option_server_id.length = 4;
         test.option_server_id.address = htobe32(INADDR_LOOPBACK);
         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
@@ -183,7 +180,7 @@ static void test_message_handler(void) {
         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
 
-        test.option_client_id.code = DHCP_OPTION_CLIENT_IDENTIFIER;
+        test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER;
         test.option_client_id.length = 7;
         test.option_client_id.id[0] = 0x01;
         test.option_client_id.id[1] = 'A';
@@ -244,7 +241,7 @@ static void test_client_id_hash(void) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_event_unref_ sd_event *e;
+        _cleanup_(sd_event_unrefp) sd_event *e;
         int r;
 
         log_set_max_level(LOG_DEBUG);
index 9e05fde8f6848032982f0fc74f8cbff3bb0aaf54..e74c8c72db1dbba550a56da85bb51d5c32344537 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -32,7 +30,6 @@
 #include "dhcp6-internal.h"
 #include "dhcp6-lease-internal.h"
 #include "dhcp6-protocol.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "macro.h"
 #include "socket-util.h"
@@ -71,11 +68,11 @@ static int test_client_basic(sd_event *e) {
                                           sizeof (mac_addr),
                                           ARPHRD_ETHER) >= 0);
 
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_CLIENTID) == -EINVAL);
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_NTP_SERVER) == -EEXIST);
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
         assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
 
         assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
@@ -89,9 +86,9 @@ static int test_client_basic(sd_event *e) {
 static int test_option(sd_event *e) {
         uint8_t packet[] = {
                 'F', 'O', 'O',
-                0x00, DHCP6_OPTION_ORO, 0x00, 0x07,
+                0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
                 'A', 'B', 'C', 'D', 'E', 'F', 'G',
-                0x00, DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
+                0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
                 '1', '2', '3', '4', '5', '6', '7', '8', '9',
                 'B', 'A', 'R',
         };
@@ -125,7 +122,7 @@ static int test_option(sd_event *e) {
                                      &optval) >= 0);
         pos += 4 + optlen;
         assert_se(buf == &packet[pos]);
-        assert_se(optcode == DHCP6_OPTION_ORO);
+        assert_se(optcode == SD_DHCP6_OPTION_ORO);
         assert_se(optlen == 7);
         assert_se(buflen + pos == sizeof(packet));
 
@@ -138,7 +135,7 @@ static int test_option(sd_event *e) {
                                      &optval) >= 0);
         pos += 4 + optlen;
         assert_se(buf == &packet[pos]);
-        assert_se(optcode == DHCP6_OPTION_VENDOR_CLASS);
+        assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
         assert_se(optlen == 9);
         assert_se(buflen + pos == sizeof(packet));
 
@@ -206,7 +203,7 @@ static uint8_t msg_reply[173] = {
 };
 
 static int test_advertise_option(sd_event *e) {
-        _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
         uint8_t *optval, *opt = msg_advertise + sizeof(DHCP6Message);
         uint16_t optcode;
@@ -233,13 +230,13 @@ static int test_advertise_option(sd_event *e) {
                                        &optval)) >= 0) {
 
                 switch(optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         assert_se(optlen == 14);
 
                         opt_clientid = true;
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         assert_se(optlen == 94);
                         assert_se(!memcmp(optval, &msg_advertise[26], optlen));
 
@@ -258,7 +255,7 @@ static int test_advertise_option(sd_event *e) {
 
                         break;
 
-                case DHCP6_OPTION_SERVERID:
+                case SD_DHCP6_OPTION_SERVERID:
                         assert_se(optlen == 14);
                         assert_se(!memcmp(optval, &msg_advertise[179], optlen));
 
@@ -266,7 +263,7 @@ static int test_advertise_option(sd_event *e) {
                                                            optlen) >= 0);
                         break;
 
-                case DHCP6_OPTION_PREFERENCE:
+                case SD_DHCP6_OPTION_PREFERENCE:
                         assert_se(optlen == 1);
                         assert_se(!*optval);
 
@@ -274,24 +271,24 @@ static int test_advertise_option(sd_event *e) {
                                                              *optval) >= 0);
                         break;
 
-                case DHCP6_OPTION_ELAPSED_TIME:
+                case SD_DHCP6_OPTION_ELAPSED_TIME:
                         assert_se(optlen == 2);
 
                         break;
 
-                case DHCP6_OPTION_DNS_SERVERS:
+                case SD_DHCP6_OPTION_DNS_SERVERS:
                         assert_se(optlen == 16);
                         assert_se(dhcp6_lease_set_dns(lease, optval,
                                                       optlen) >= 0);
                         break;
 
-                case DHCP6_OPTION_DOMAIN_LIST:
+                case SD_DHCP6_OPTION_DOMAIN_LIST:
                         assert_se(optlen == 11);
                         assert_se(dhcp6_lease_set_domains(lease, optval,
                                                           optlen) >= 0);
                         break;
 
-                case DHCP6_OPTION_SNTP_SERVERS:
+                case SD_DHCP6_OPTION_SNTP_SERVERS:
                         assert_se(optlen == 16);
                         assert_se(dhcp6_lease_set_sntp(lease, optval,
                                                        optlen) >= 0);
@@ -380,7 +377,7 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
         assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
         assert_se(!memcmp(addrs, &msg_advertise[159], 16));
 
-        assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
+        assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
 
         if (verbose)
                 printf("  got DHCPv6 event %d\n", event);
@@ -408,7 +405,7 @@ static int test_client_send_reply(DHCP6Message *request) {
 
 static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
                                       size_t len) {
-        _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t *optval;
         uint16_t optcode;
         size_t optlen;
@@ -426,7 +423,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
         while ((r = dhcp6_option_parse(&option, &len,
                                        &optcode, &optlen, &optval)) >= 0) {
                 switch(optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         assert_se(!found_clientid);
                         found_clientid = true;
 
@@ -435,7 +432,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
 
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         assert_se(!found_iana);
                         found_iana = true;
 
@@ -454,7 +451,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
 
                         break;
 
-                case DHCP6_OPTION_SERVERID:
+                case SD_DHCP6_OPTION_SERVERID:
                         assert_se(!found_serverid);
                         found_serverid = true;
 
@@ -463,7 +460,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
 
                         break;
 
-                case DHCP6_OPTION_ELAPSED_TIME:
+                case SD_DHCP6_OPTION_ELAPSED_TIME:
                         assert_se(!found_elapsed_time);
                         found_elapsed_time = true;
 
@@ -522,7 +519,7 @@ static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
         while ((r = dhcp6_option_parse(&option, &len,
                                        &optcode, &optlen, &optval)) >= 0) {
                 switch(optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         assert_se(!found_clientid);
                         found_clientid = true;
 
@@ -531,7 +528,7 @@ static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
 
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         assert_se(!found_iana);
                         found_iana = true;
 
@@ -541,7 +538,7 @@ static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
 
                         break;
 
-                case DHCP6_OPTION_ELAPSED_TIME:
+                case SD_DHCP6_OPTION_ELAPSED_TIME:
                         assert_se(!found_elapsed_time);
                         found_elapsed_time = true;
 
@@ -599,7 +596,7 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event,
 static int test_client_verify_information_request(DHCP6Message *information_request,
                                                   uint8_t *option, size_t len) {
 
-        _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t *optval;
         uint16_t optcode;
         size_t optlen;
@@ -615,7 +612,7 @@ static int test_client_verify_information_request(DHCP6Message *information_requ
         while ((r = dhcp6_option_parse(&option, &len,
                                        &optcode, &optlen, &optval)) >= 0) {
                 switch(optcode) {
-                case DHCP6_OPTION_CLIENTID:
+                case SD_DHCP6_OPTION_CLIENTID:
                         assert_se(!found_clientid);
                         found_clientid = true;
 
@@ -624,17 +621,17 @@ static int test_client_verify_information_request(DHCP6Message *information_requ
 
                         break;
 
-                case DHCP6_OPTION_IA_NA:
+                case SD_DHCP6_OPTION_IA_NA:
                         assert_not_reached("IA TA option must not be present");
 
                         break;
 
-                case DHCP6_OPTION_SERVERID:
+                case SD_DHCP6_OPTION_SERVERID:
                         assert_not_reached("Server ID option must not be present");
 
                         break;
 
-                case DHCP6_OPTION_ELAPSED_TIME:
+                case SD_DHCP6_OPTION_ELAPSED_TIME:
                         assert_se(!found_elapsed_time);
                         found_elapsed_time = true;
 
@@ -749,7 +746,7 @@ static int test_client_solicit(sd_event *e) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_event_unref_ sd_event *e;
+        _cleanup_(sd_event_unrefp) sd_event *e;
 
         assert_se(sd_event_new(&e) >= 0);
 
index 913a929069980f833c0beeda3b70aa590132dca3..85dd61470d995b735d2c04af1653ad01c2108175 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,7 +28,6 @@
 #include "sd-netlink.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "in-addr-util.h"
 #include "netlink-util.h"
 #include "parse-util.h"
@@ -91,9 +88,9 @@ static int client_run(int ifindex, const char *seed_str, const struct ether_addr
 }
 
 static int test_ll(const char *ifname, const char *seed) {
-        _cleanup_event_unref_ sd_event *e = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
         struct ether_addr ha;
         int ifindex;
 
index 6f416c51e4359d06fa228b8f7f80ca3caecda223..a233e0378c4415efd923861ab23f92d6709cb93c 100644 (file)
@@ -1,4 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 /***
   This file is part of systemd.
 
@@ -29,7 +28,6 @@
 #include "sd-ipv4ll.h"
 
 #include "arp-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "socket-util.h"
 #include "util.h"
@@ -207,7 +205,7 @@ static void test_basic_request(sd_event *e) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_event_unref_ sd_event *e = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
 
         log_set_max_level(LOG_DEBUG);
         log_parse_environment();
index 99545d0b8bfd70d7e060eff3bd5e572eb62171e2..b8490073ddedddd643907ca16e27598b1a01757d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -29,7 +27,6 @@
 #include "sd-lldp.h"
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "lldp-network.h"
 #include "lldp-tlv.h"
@@ -48,7 +45,7 @@ static struct ether_addr mac_addr = {
 };
 
 static int lldp_build_tlv_packet(tlv_packet **ret) {
-        _cleanup_lldp_packet_unref_ tlv_packet *m = NULL;
+        _cleanup_(sd_lldp_packet_unrefp) tlv_packet *m = NULL;
         const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR;
         struct ether_header ether = {
                 .ether_type = htons(ETHERTYPE_LLDP),
@@ -237,7 +234,7 @@ static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
 }
 
 static void test_parser(void) {
-        _cleanup_lldp_packet_unref_ tlv_packet *tlv = NULL;
+        _cleanup_(sd_lldp_packet_unrefp) tlv_packet *tlv = NULL;
 
         /* form a packet */
         lldp_build_tlv_packet(&tlv);
@@ -292,7 +289,7 @@ static int stop_lldp(sd_lldp *lldp) {
         if (r)
                 return r;
 
-        sd_lldp_free(lldp);
+        sd_lldp_unref(lldp);
         safe_close(test_fd[1]);
 
         return 0;
@@ -457,7 +454,7 @@ static void test_receive_oui_packet(sd_event *e) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_event_unref_ sd_event *e = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
 
         test_parser();
 
index a485be704ede73b39932023b4ae03847092b2fad..f7b2eb8050378ead92ceff338606829b4b73c2c6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 043ff13e6f8f3acac9c032e2cfc4d4c5b501df6a..4ab637b686c52d9f4562637cc866723252407fe5 100644 (file)
@@ -481,3 +481,11 @@ global:
         sd_bus_path_encode_many;
         sd_listen_fds_with_names;
 } LIBSYSTEMD_226;
+
+LIBSYSTEMD_229 {
+global:
+        sd_journal_has_runtime_files;
+        sd_journal_has_persistent_files;
+        sd_journal_enumerate_fields;
+        sd_journal_restart_fields;
+} LIBSYSTEMD_227;
index c0c5d445eb265566d869625d402ed78841390890..112769fcb6d964299e94606f5a1cdb34f37b199f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 38892044f1e13c3d546f914c4d12ec96d253bde9..c824622b95fa54e973607fe9cad22534d5143540 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8d486fcbbdd62a3297df74f9490bbe8ba4366c9e..3c19f2b108e4f26ebaaa01dbfa57b40907bc3e92 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,7 +37,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,  EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,   EDEADLK),
-        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED,                  EBADR),
+        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED,                  ESHUTDOWN),
         SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,      EBADR),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION,                 EPERM),
         SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN,                ECANCELED),
@@ -67,12 +65,20 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS,              ESRCH),
 
-        SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS,              EIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS,              ESRCH),
         SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY,                EINVAL),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR,                   ENOENT),
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES,                 ENOMEM),
         SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP,                   EDEADLK),
         SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED,                      ECANCELED),
+        SD_BUS_ERROR_MAP(BUS_ERROR_CONNECTION_FAILURE,           ECONNREFUSED),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE,              EUNATCH),
+        SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED,                EHOSTUNREACH),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR,              EHOSTUNREACH),
+        SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED,          EOPNOTSUPP),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK,                 ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY,                    EBUSY),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN,                 ENETDOWN),
 
         SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER,             ENXIO),
         SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS,         EBUSY),
index f2092795f410b40c3142338bbc8d2495980040b2..fab8748f46169b6df8f95089b9160d567ecb31aa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #define BUS_ERROR_NO_RESOURCES "org.freedesktop.resolve1.NoResources"
 #define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
 #define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
+#define BUS_ERROR_CONNECTION_FAILURE "org.freedesktop.resolve1.ConnectionFailure"
+#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
+#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
+#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
+#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
+#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
+#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
+#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
 #define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
 
 #define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
index 7da6ba990382f4da5e86a8545920d50f51a306ef..3191d27ded7f7e854953eb5bd457aa895d87ffff 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c6f757a99bcc431a0f1d14409d70fb8d06406e09..509ef4562414b32c81ae26b14fe7397515604cc0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 94251fe87c018bf2313d766c2878aa1c1709d952..05222b8d308f9da42c7b4bf778943c95bc681e16 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -91,7 +89,7 @@ static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags
 }
 
 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         uint32_t ret, param = 0;
         int r;
 
@@ -187,7 +185,7 @@ static int bus_release_name_kernel(sd_bus *bus, const char *name) {
 }
 
 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         uint32_t ret;
         int r;
 
@@ -326,7 +324,7 @@ static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activata
 }
 
 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **x = NULL, **y = NULL;
         int r;
 
@@ -647,7 +645,7 @@ int bus_get_name_creds_kdbus(
                 bool allow_activator,
                 sd_bus_creds **creds) {
 
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         struct kdbus_cmd_info *cmd;
         struct kdbus_info *conn_info;
         size_t size, l;
@@ -753,8 +751,8 @@ static int bus_get_name_creds_dbus1(
                 uint64_t mask,
                 sd_bus_creds **creds) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         const char *unique = NULL;
         pid_t pid = 0;
         int r;
@@ -858,7 +856,7 @@ static int bus_get_name_creds_dbus1(
                 }
 
                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
-                        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                         const void *p = NULL;
                         size_t sz = 0;
 
@@ -930,7 +928,7 @@ _public_ int sd_bus_get_name_creds(
 }
 
 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         struct kdbus_cmd_info cmd = {
                 .size = sizeof(struct kdbus_cmd_info),
         };
@@ -979,7 +977,7 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **
 }
 
 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         pid_t pid = 0;
         bool do_label;
         int r;
@@ -1543,7 +1541,7 @@ int bus_remove_match_internal(
 }
 
 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
         const char *mid;
         int r;
 
index 5009ca8e619567011cb6ee31255c2b4047411784..c181aa7959c754d88be716af81841dfdd17a8f30 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "bus-match.h"
 
 int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
index 0afafc2942de9031a6d9feae62b605f0624b11bc..2d06bf541f7df9a4963d499f09f062c365e9ad72 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -33,7 +31,7 @@ _public_ int sd_bus_emit_signal(
                 const char *member,
                 const char *types, ...) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert_return(bus, -EINVAL);
@@ -70,7 +68,7 @@ _public_ int sd_bus_call_method_async(
                 void *userdata,
                 const char *types, ...) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert_return(bus, -EINVAL);
@@ -106,7 +104,7 @@ _public_ int sd_bus_call_method(
                 sd_bus_message **reply,
                 const char *types, ...) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         bus_assert_return(bus, -EINVAL, error);
@@ -141,7 +139,7 @@ _public_ int sd_bus_reply_method_return(
                 sd_bus_message *call,
                 const char *types, ...) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert_return(call, -EINVAL);
@@ -177,7 +175,7 @@ _public_ int sd_bus_reply_method_error(
                 sd_bus_message *call,
                 const sd_bus_error *e) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert_return(call, -EINVAL);
@@ -206,7 +204,7 @@ _public_ int sd_bus_reply_method_errorf(
                 const char *format,
                 ...) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         va_list ap;
 
         assert_return(call, -EINVAL);
@@ -233,7 +231,7 @@ _public_ int sd_bus_reply_method_errno(
                 int error,
                 const sd_bus_error *p) {
 
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
 
         assert_return(call, -EINVAL);
         assert_return(call->sealed, -EPERM);
@@ -261,7 +259,7 @@ _public_ int sd_bus_reply_method_errnof(
                 const char *format,
                 ...) {
 
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
         va_list ap;
 
         assert_return(call, -EINVAL);
@@ -334,7 +332,7 @@ _public_ int sd_bus_get_property_trivial(
                 sd_bus_error *error,
                 char type, void *ptr) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         bus_assert_return(bus, -EINVAL, error);
@@ -376,7 +374,7 @@ _public_ int sd_bus_get_property_string(
                 sd_bus_error *error,
                 char **ret) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *s;
         char *n;
         int r;
@@ -426,7 +424,7 @@ _public_ int sd_bus_get_property_strv(
                 sd_bus_error *error,
                 char ***ret) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         bus_assert_return(bus, -EINVAL, error);
@@ -467,7 +465,7 @@ _public_ int sd_bus_set_property(
                 sd_bus_error *error,
                 const char *type, ...) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         va_list ap;
         int r;
 
@@ -555,7 +553,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
 }
 
 _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         uid_t our_uid;
         bool know_caps = false;
         int r;
index 2922da3763e63d3f7047e8affdbce0ea08b869ea..c4f693dee9dea8b37b8d5b78301160d78a00de1b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -75,7 +73,9 @@ void bus_creds_done(sd_bus_creds *c) {
 }
 
 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
-        assert_return(c, NULL);
+
+        if (!c)
+                return NULL;
 
         if (c->allocated) {
                 assert(c->n_ref > 0);
@@ -1118,7 +1118,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
 }
 
 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
         int r;
 
         assert(c);
index 209d2161233726374dc5e7ec17b869e58e86be58..df8a1f1005d0c4278e1d4881902efd5024ff9e1f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 43a7e67a6d542e64bb9eb1c73191bbdac3c9b933..7c81e7a25dbaacbb97764b1ad0ae7c9df2833f49 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d2522edebad8848dfa7d41c7963e747fc56258f7..874e86d09c9874f0a7a5267b861f4599b112319b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdio.h>
 #include <stdbool.h>
+#include <stdio.h>
 
 #include "sd-bus.h"
 
index 404eaa3c895bbb65aa8d3071e3276b02219d0223..26219bdeed514c51c7804a15800063572d75073e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -93,14 +91,14 @@ static int bus_error_name_to_errno(const char *name) {
         p = startswith(name, "System.Error.");
         if (p) {
                 r = errno_from_name(p);
-                if (r <= 0)
+                if (r < 0)
                         return EIO;
 
                 return r;
         }
 
-        if (additional_error_maps) {
-                for (map = additional_error_maps; *map; map++) {
+        if (additional_error_maps)
+                for (map = additional_error_maps; *map; map++)
                         for (m = *map;; m++) {
                                 /* For additional error maps the end marker is actually the end marker */
                                 if (m->code == BUS_ERROR_MAP_END_MARKER)
@@ -109,15 +107,13 @@ static int bus_error_name_to_errno(const char *name) {
                                 if (streq(m->name, name))
                                         return m->code;
                         }
-                }
-        }
 
         m = __start_BUS_ERROR_MAP;
         while (m < __stop_BUS_ERROR_MAP) {
                 /* For magic ELF error maps, the end marker might
                  * appear in the middle of things, since multiple maps
                  * might appear in the same section. Hence, let's skip
-                 * over it, but realign the pointer to the netx 8byte
+                 * over it, but realign the pointer to the next 8 byte
                  * boundary, which is the selected alignment for the
                  * arrays. */
                 if (m->code == BUS_ERROR_MAP_END_MARKER) {
@@ -258,25 +254,24 @@ int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_li
 
         if (!name)
                 return 0;
-        if (!e)
-                goto finish;
 
-        assert_return(!bus_error_is_dirty(e), -EINVAL);
+        if (e) {
+                assert_return(!bus_error_is_dirty(e), -EINVAL);
 
-        e->name = strdup(name);
-        if (!e->name) {
-                *e = BUS_ERROR_OOM;
-                return -ENOMEM;
-        }
+                e->name = strdup(name);
+                if (!e->name) {
+                        *e = BUS_ERROR_OOM;
+                        return -ENOMEM;
+                }
 
-        /* If we hit OOM on formatting the pretty message, we ignore
-         * this, since we at least managed to write the error name */
-        if (format)
-                (void) vasprintf((char**) &e->message, format, ap);
+                /* If we hit OOM on formatting the pretty message, we ignore
+                 * this, since we at least managed to write the error name */
+                if (format)
+                        (void) vasprintf((char**) &e->message, format, ap);
 
-        e->_need_free = 1;
+                e->_need_free = 1;
+        }
 
-finish:
         return -bus_error_name_to_errno(name);
 }
 
@@ -582,27 +577,29 @@ const char *bus_error_message(const sd_bus_error *e, int error) {
         return strerror(error);
 }
 
+static bool map_ok(const sd_bus_error_map *map) {
+        for (; map->code != BUS_ERROR_MAP_END_MARKER; map++)
+                if (!map->name || map->code <=0)
+                        return false;
+        return true;
+}
+
 _public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
         const sd_bus_error_map **maps = NULL;
         unsigned n = 0;
 
         assert_return(map, -EINVAL);
+        assert_return(map_ok(map), -EINVAL);
 
-        if (additional_error_maps) {
-                for (;; n++) {
-                        if (additional_error_maps[n] == NULL)
-                                break;
-
+        if (additional_error_maps)
+                for (; additional_error_maps[n] != NULL; n++)
                         if (additional_error_maps[n] == map)
                                 return 0;
-                }
-        }
 
         maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
         if (!maps)
                 return -ENOMEM;
 
-
         maps[n] = map;
         maps[n+1] = NULL;
 
index fb0199c948f677ba4e13bc4207c0d2b9936bee29..e2c4cf4b3f61ae82198771f0fcada9d99a0239e1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -24,6 +22,7 @@
 #include <stdbool.h>
 
 #include "sd-bus.h"
+
 #include "macro.h"
 
 bool bus_error_is_dirty(sd_bus_error *e);
index ec027590b206c50f553ab4fa259125ad4b72cf98..58782767faea16fcce09e5b2f7bf8f81a971f65f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 875d34b59ba87a309bd300d871af8516d0447872..6da637fb05450ce61332890374b13e03f4adf42c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d9f9cd1c5e24e14a9a8bdfd400fcbcf14b630612..caca679086afa91fc89f7d6de517471b958d5ed6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5fc0926f06f406046568ac991a3ce5a42406cc1f..216d9f62bc79759d225c3f00ea40a5ec2f24557b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -381,7 +379,7 @@ char *bus_address_escape(const char *v);
  * bus from the callback doesn't destroy the object we are working
  * on */
 #define BUS_DONT_DESTROY(bus) \
-        _cleanup_bus_unref_ _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
+        _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
 
 int bus_set_address_system(sd_bus *bus);
 int bus_set_address_user(sd_bus *bus);
index a90536bac9d0086d01c8b640f03fc7bbb9bd0e0f..8f93edb8dae317c30f1cdb9393da6f7273ed0b32 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1914e6cb8b35c04c509147f0a35eb3e39d1495b0..8e2f3800cab54abc889ce47a573c91ce42e6a521 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -24,6 +22,7 @@
 #include <stdio.h>
 
 #include "sd-bus.h"
+
 #include "set.h"
 
 struct introspect {
index 6716f6daca8967745fcdc599daf6062ef9ed20bc..0896eeb177581f09bd489437258dd5b3bac843ed 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -47,6 +45,7 @@
 #include "formats-util.h"
 #include "memfd-util.h"
 #include "parse-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "user-util.h"
@@ -269,8 +268,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
         struct bus_body_part *part;
         struct kdbus_item *d;
         const char *destination;
-        bool well_known;
-        uint64_t unique;
+        bool well_known = false;
+        uint64_t dst_id;
         size_t sz, dl;
         unsigned i;
         int r;
@@ -287,13 +286,21 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
         destination = m->destination ?: m->destination_ptr;
 
         if (destination) {
-                r = bus_kernel_parse_unique_name(destination, &unique);
+                r = bus_kernel_parse_unique_name(destination, &dst_id);
                 if (r < 0)
                         return r;
-
-                well_known = r == 0;
+                if (r == 0) {
+                        well_known = true;
+
+                        /* verify_destination_id will usually be 0, which makes the kernel
+                         * driver only look at the provided well-known name. Otherwise,
+                         * the kernel will make sure the provided destination id matches
+                         * the owner of the provided well-known-name, and fail if they
+                         * differ. Currently, this is only needed for bus-proxyd. */
+                        dst_id = m->verify_destination_id;
+                }
         } else
-                well_known = false;
+                dst_id = KDBUS_DST_ID_BROADCAST;
 
         sz = offsetof(struct kdbus_msg, items);
 
@@ -331,15 +338,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
                 ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
                 ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
 
-        if (well_known)
-                /* verify_destination_id will usually be 0, which makes the kernel driver only look
-                 * at the provided well-known name. Otherwise, the kernel will make sure the provided
-                 * destination id matches the owner of the provided weel-known-name, and fail if they
-                 * differ. Currently, this is only needed for bus-proxyd. */
-                m->kdbus->dst_id = m->verify_destination_id;
-        else
-                m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
-
+        m->kdbus->dst_id = dst_id;
         m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
         m->kdbus->cookie = m->header->dbus2.cookie;
         m->kdbus->priority = m->priority;
@@ -849,7 +848,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
         if (k->src_id == KDBUS_SRC_ID_KERNEL)
                 bus_message_set_sender_driver(bus, m);
         else {
-                snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
+                xsprintf(m->sender_buffer, ":1.%llu",
+                         (unsigned long long)k->src_id);
                 m->sender = m->creds.unique_name = m->sender_buffer;
         }
 
@@ -860,7 +860,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
         else if (k->dst_id == KDBUS_DST_ID_NAME)
                 m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
         else {
-                snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
+                xsprintf(m->destination_buffer, ":1.%llu",
+                         (unsigned long long)k->dst_id);
                 m->destination = m->destination_buffer;
         }
 
@@ -1142,7 +1143,7 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call
 
         r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
         if (r < 0) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 sd_bus_message *reply;
 
                 if (errno == EAGAIN || errno == EINTR)
@@ -1221,7 +1222,7 @@ static int push_name_owner_changed(
                 const char *new_owner,
                 const struct kdbus_timestamp *ts) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(bus);
@@ -1308,7 +1309,7 @@ static int translate_reply(
                 const struct kdbus_item *d,
                 const struct kdbus_timestamp *ts) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(bus);
index bb4dff6d8262a00407ce88cb92efc415ce862371..53ba3bdcf3e57ffe32b25063160d7d23de5ddff4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 55dc7caa53012c2870a0ea852bfa4c36f01ba1d3..397baf6f33cd722e98f27e15e836458f9d999d28 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -317,7 +315,7 @@ int bus_match_run(
 
                 /* Run the callback. And then invoke siblings. */
                 if (node->leaf.callback->callback) {
-                        _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+                        _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
                         sd_bus_slot *slot;
 
                         slot = container_of(node->leaf.callback, sd_bus_slot, match_callback);
index bc85af3ec09e628c14d054f7478ff10d3b4bdcd5..8cbbb63b114a6722959a9e5b493a098862ff3dbd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 5c80095bf09b222c5a2d72b0deb2cb0e9db1518b..7be28c509b3c4eaf14c453eefce0e6f412bffed0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -802,7 +800,7 @@ _public_ int sd_bus_message_new_method_errorf(
                 const char *format,
                 ...) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         va_list ap;
 
         assert_return(name, -EINVAL);
@@ -821,7 +819,7 @@ _public_ int sd_bus_message_new_method_errno(
                 int error,
                 const sd_bus_error *p) {
 
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
 
         if (sd_bus_error_is_set(p))
                 return sd_bus_message_new_method_error(call, m, p);
@@ -838,7 +836,7 @@ _public_ int sd_bus_message_new_method_errnof(
                 const char *format,
                 ...) {
 
-        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
         va_list ap;
 
         va_start(ap, format);
@@ -919,7 +917,9 @@ fail:
 }
 
 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
-        assert_return(m, NULL);
+
+        if (!m)
+                return NULL;
 
         assert(m->n_ref > 0);
         m->n_ref++;
@@ -5838,7 +5838,7 @@ _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
 }
 
 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
-        _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
         usec_t timeout;
         int r;
 
index 4c91dbae09b0083de2f6f3d09385a4b83fe44188..4710c106b95293e054396aa9df400a4bb0239809 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 303e49fa847174c931c96a7b4c68d34e70cab1a9..1f285ae8a667de7b6408495536a90a94804575a3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -272,7 +270,7 @@ static int node_callbacks_run(
         assert(found_object);
 
         LIST_FOREACH(callbacks, c, first) {
-                _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
                 sd_bus_slot *slot;
 
                 if (bus->nodes_modified)
@@ -357,7 +355,7 @@ static int method_callbacks_run(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *signature;
         void *u;
         int r;
@@ -580,8 +578,8 @@ static int property_get_set_callbacks_run(
                 bool is_get,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         sd_bus_slot *slot;
         void *u = NULL;
         int r;
@@ -781,7 +779,7 @@ static int property_get_all_callbacks_run(
                 const char *iface,
                 bool *found_object) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         struct node_vtable *c;
         bool found_interface;
         int r;
@@ -804,7 +802,7 @@ static int property_get_all_callbacks_run(
                 streq(iface, "org.freedesktop.DBus.Introspectable");
 
         LIST_FOREACH(vtables, c, first) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u;
 
                 if (require_fallback && !c->is_fallback)
@@ -881,7 +879,7 @@ static int bus_node_exists(
         }
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (require_fallback && !c->is_fallback)
                         continue;
@@ -903,8 +901,8 @@ static int process_introspect(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_set_free_free_ Set *s = NULL;
         const char *previous_interface = NULL;
         struct introspect intro;
@@ -1164,8 +1162,8 @@ static int process_get_managed_objects(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_set_free_free_ Set *s = NULL;
         Iterator i;
         char *path;
@@ -1881,8 +1879,8 @@ static int emit_properties_changed_on_interface(
                 bool *found_interface,
                 char **names) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         bool has_invalidating = false, has_changing = false;
         struct vtable_member key = {};
         struct node_vtable *c;
@@ -2176,7 +2174,7 @@ static int object_added_append_all_prefix(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u = NULL;
 
                 if (require_fallback && !c->is_fallback)
@@ -2305,7 +2303,7 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
 _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
@@ -2389,7 +2387,7 @@ static int object_removed_append_all_prefix(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u = NULL;
 
                 if (require_fallback && !c->is_fallback)
@@ -2475,7 +2473,7 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
 _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
@@ -2543,7 +2541,7 @@ static int interfaces_added_append_one_prefix(
                 const char *interface,
                 bool require_fallback) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool found_interface = false;
         struct node_vtable *c;
         struct node *n;
@@ -2638,7 +2636,7 @@ static int interfaces_added_append_one(
 _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         char **i;
         int r;
@@ -2722,7 +2720,7 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
 }
 
 _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
index 4373fae89c97667d4cc8561fb6bb76e6fa8ef938..e0b8c534ed6dcba02b43d33e7bbae56fd9a9e809 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 183af89a63a07fa1892df0e7eb25a77d9f2ffd9c..9d180cb284cb2e86c6b1e1141005a12e357542d0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 1e5bf4821d9526da05478c92cfe2785acd611b08..7bc243494a3f940bf45260f58ec03812f0cbf121 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c4fed0b53dcde510740b61ad073e3298ba7a3fef..1e0cd7f587d06a3e71cb7a8ceb8888b15ad9f260 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index e405a04c53d5a50adb2bb8f4c09876abd7c024d0..a8c74011bf9baa6b4ed22ffb1d7c506612879f06 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -57,7 +55,9 @@ sd_bus_slot *bus_slot_allocate(
 }
 
 _public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
-        assert_return(slot, NULL);
+
+        if (!slot)
+                return NULL;
 
         assert(slot->n_ref > 0);
 
index 23a15e4d024ee7d0f45fb34adf6b1f69a9ec36d5..3b8b94dc6bc62455b21135bdfee9148e434730e4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include "sd-bus.h"
+
 #include "bus-internal.h"
 
 sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
index 25873dea1ecd30ad5111000a1e7408e614759fa2..a2fb3912393b78b9a2175398ced956355d46f036 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -609,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_use()) {
+        if (mac_selinux_have()) {
                 r = getpeersec(b->input_fd, &b->label);
                 if (r < 0 && r != -EOPNOTSUPP)
                         log_debug_errno(r, "Failed to determine peer security context: %m");
index 5a1c7d4cf2c9d6eccfa189f8c5acb64c4fb3efe0..684feead74322165b590f6d17a6ca386247cff5f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index fd7e58fcfacb0b15bb58a36ad5d1fbec28cbdbd5..bdbf7d4a85af2a9c01c326e2d2373068403dd32c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -111,7 +109,9 @@ _public_ int sd_bus_track_new(
 }
 
 _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
-        assert_return(track, NULL);
+
+        if (!track)
+                return NULL;
 
         assert(track->n_ref > 0);
 
@@ -161,7 +161,7 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus
 }
 
 _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
-        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
         _cleanup_free_ char *n = NULL;
         const char *match;
         int r;
@@ -207,7 +207,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
 }
 
 _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
-        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
         _cleanup_free_ char *n = NULL;
 
         assert_return(name, -EINVAL);
index f8690a52393afd84695ba9d26ff5e2e1f7fa75c3..7d93a727d6a7222f8e839924c8bf1da68c01695b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 6bc7b880a624f2cd23d1a6bd5d361512c19244d4..c692afc580b932c349c9c2febaaed3abc7b4ceb8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ad89e6c91171067b2bbc249d5348a532e4e2201d..5c87eb5f081a837a086ab210a3d9539ada1a73d7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 71f962b00cd7ecfcce7947cef59f46b48eb0ff27..b09509f8e1211fcb493425769c06839a30c0b61f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ea807d5973753d49da3b66fb15282e6ed7f0d2fc..d922e352db9a41153cbe6dc73234eb3339bda4c0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 452ac7c407ece57bac3f3e6f622bd708e11c307f..35fabf038ce9f7ee9554d430fbd1a0ad6381c510 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -137,7 +135,7 @@ static int list_bus_names(sd_bus *bus, char **argv) {
         }
 
         STRV_FOREACH(i, merged) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_id128_t mid;
 
                 if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
@@ -334,8 +332,8 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
                 .on_path = on_path,
         };
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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;
 
@@ -867,8 +865,8 @@ static int introspect(sd_bus *bus, char **argv) {
                 .on_property = on_property,
         };
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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;
@@ -1132,7 +1130,7 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
         log_info("Monitoring bus message stream.");
 
         for (;;) {
-                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
                 r = sd_bus_process(bus, &m);
                 if (r < 0)
@@ -1182,7 +1180,7 @@ static int capture(sd_bus *bus, char *argv[]) {
 }
 
 static int status(sd_bus *bus, char *argv[]) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         pid_t pid;
         int r;
 
@@ -1489,8 +1487,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
 }
 
 static int call(sd_bus *bus, char *argv[]) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _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);
@@ -1576,7 +1574,7 @@ static int call(sd_bus *bus, char *argv[]) {
 }
 
 static int get_property(sd_bus *bus, char *argv[]) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         unsigned n;
         char **i;
         int r;
@@ -1590,7 +1588,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
         }
 
         STRV_FOREACH(i, argv + 4) {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 const char *contents = NULL;
                 char type;
 
@@ -1634,8 +1632,8 @@ static int get_property(sd_bus *bus, char *argv[]) {
 }
 
 static int set_property(sd_bus *bus, char *argv[]) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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;
@@ -1976,7 +1974,7 @@ static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         log_parse_environment();
index 99780c8cceb97e804f50bd65e1a656ca4e77f1cc..c6f626d8aac203dea2fd25fb33fb534398fa4a66 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -419,7 +417,7 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
 }
 
 static int bus_send_hello(sd_bus *bus) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(bus);
@@ -1480,7 +1478,9 @@ static void bus_enter_closing(sd_bus *bus) {
 }
 
 _public_ sd_bus *sd_bus_ref(sd_bus *bus) {
-        assert_return(bus, NULL);
+
+        if (!bus)
+                return NULL;
 
         assert_se(REFCNT_INC(bus->n_ref) >= 2);
 
@@ -1734,7 +1734,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
 }
 
 static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
         int r;
 
         assert_return(m, -EINVAL);
@@ -1882,8 +1882,8 @@ _public_ int sd_bus_call_async(
                 void *userdata,
                 uint64_t usec) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
-        _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL;
         int r;
 
         assert_return(m, -EINVAL);
@@ -1981,7 +1981,7 @@ _public_ int sd_bus_call(
                 sd_bus_error *error,
                 sd_bus_message **reply) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
         usec_t timeout;
         uint64_t cookie;
         unsigned i;
@@ -2220,8 +2220,8 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
 }
 
 static int process_timeout(sd_bus *bus) {
-        _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
         struct reply_callback *c;
         sd_bus_slot *slot;
         usec_t n;
@@ -2302,8 +2302,8 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int process_reply(sd_bus *bus, sd_bus_message *m) {
-        _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
         struct reply_callback *c;
         sd_bus_slot *slot;
         int r;
@@ -2382,7 +2382,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int process_filter(sd_bus *bus, sd_bus_message *m) {
-        _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
         struct filter_callback *l;
         int r;
 
@@ -2448,7 +2448,7 @@ static int process_match(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int process_builtin(sd_bus *bus, sd_bus_message *m) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(bus);
@@ -2580,7 +2580,7 @@ static int dispatch_track(sd_bus *bus) {
 }
 
 static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
         assert(bus);
@@ -2644,7 +2644,7 @@ null_message:
 }
 
 static int process_closing(sd_bus *bus, sd_bus_message **ret) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct reply_callback *c;
         int r;
 
@@ -2653,7 +2653,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
 
         c = ordered_hashmap_first(bus->reply_callbacks);
         if (c) {
-                _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
                 sd_bus_slot *slot;
 
                 /* First, fail all outstanding method calls */
index 96a0929a14ca7494a0bffbffc74de6f46ac649cc..56ac2ab3dd54b408def3c1279846cd13ec7ba5d5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -46,7 +44,7 @@ static void server(sd_bus *b, size_t *result) {
         int r;
 
         for (;;) {
-                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
                 r = sd_bus_process(b, &m);
                 assert_se(r >= 0);
@@ -80,7 +78,7 @@ static void server(sd_bus *b, size_t *result) {
 }
 
 static void transaction(sd_bus *b, size_t sz, const char *server_name) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         uint8_t *p;
 
         assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0);
@@ -92,7 +90,7 @@ static void transaction(sd_bus *b, size_t sz, const char *server_name) {
 }
 
 static void client_bisect(const char *address, const char *server_name) {
-        _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
         size_t lsize, rsize, csize;
         sd_bus *b;
         int r;
@@ -166,7 +164,7 @@ static void client_bisect(const char *address, const char *server_name) {
 }
 
 static void client_chart(Type type, const char *address, const char *server_name, int fd) {
-        _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
         size_t csize;
         sd_bus *b;
         int r;
index f20eced4ac438261211fb4a4ca38eae2cce53dbe..048c0d19e2a537bc05da35edbb372be94b6da280 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -130,7 +128,7 @@ static int server(sd_bus *bus) {
         bool client1_gone = false, client2_gone = false;
 
         while (!client1_gone || !client2_gone) {
-                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
                 pid_t pid = 0;
                 const char *label = NULL;
 
@@ -261,9 +259,9 @@ fail:
 }
 
 static void* client1(void*p) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *hello;
         int r;
         _cleanup_close_pair_ int pp[2] = { -1, -1 };
@@ -331,7 +329,7 @@ static void* client1(void*p) {
 
 finish:
         if (bus) {
-                _cleanup_bus_message_unref_ sd_bus_message *q;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
 
                 r = sd_bus_message_new_method_call(
                                 bus,
@@ -360,9 +358,9 @@ static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_er
 }
 
 static void* client2(void*p) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool quit = false;
         const char *mid;
         int r;
@@ -499,7 +497,7 @@ static void* client2(void*p) {
 
 finish:
         if (bus) {
-                _cleanup_bus_message_unref_ sd_bus_message *q;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
 
                 r = sd_bus_message_new_method_call(
                                 bus,
index 51aa0a9ad0e8a21a5d2660f13f78e05112b89a4b..250a5b29087de05f5a81dcf90bc261bd6cbc10e2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "refcnt.h"
 
 static void test_bus_new(void) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
 
         assert_se(sd_bus_new(&bus) == 0);
         printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref));
 }
 
 static int test_bus_open(void) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         r = sd_bus_open_system(&bus);
@@ -51,7 +49,7 @@ static int test_bus_open(void) {
 
 static void test_bus_new_method_call(void) {
         sd_bus *bus = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
         assert_se(sd_bus_open_system(&bus) >= 0);
 
@@ -59,13 +57,13 @@ static void test_bus_new_method_call(void) {
 
         printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
 
-        sd_bus_unref(bus);
-        printf("after bus_unref: refcount %u\n", m->n_ref);
+        sd_bus_flush_close_unref(bus);
+        printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
 }
 
 static void test_bus_new_signal(void) {
         sd_bus *bus = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 
         assert_se(sd_bus_open_system(&bus) >= 0);
 
@@ -73,8 +71,8 @@ static void test_bus_new_signal(void) {
 
         printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
 
-        sd_bus_unref(bus);
-        printf("after bus_unref: refcount %u\n", m->n_ref);
+        sd_bus_flush_close_unref(bus);
+        printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
 }
 
 int main(int argc, char **argv) {
index bd0101af9e2d8a22ddf6900f3285fd762e4e5437..e9ef483bddd7e11c17fd5d7b57cbc582138cb562 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "cgroup-util.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         int r;
 
-        if (cg_unified() == -ENOEXEC) {
+        if (cg_unified() == -ENOMEDIUM) {
                 puts("Skipping test: /sys/fs/cgroup/ not available");
                 return EXIT_TEST_SKIP;
         }
index 9d6c221eb0a79413ab7702d1759bac277c810fc5..46d18abd29d61c2351ddd622d2ae5f229925381e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -27,7 +25,7 @@
 #include "errno-list.h"
 
 static void test_error(void) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
         const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
         const sd_bus_error temporarily_const_error = {
                 .name = SD_BUS_ERROR_ACCESS_DENIED,
@@ -44,7 +42,15 @@ static void test_error(void) {
         assert_se(sd_bus_error_is_set(&error));
         sd_bus_error_free(&error);
 
+        /* Check with no error */
+        assert_se(!sd_bus_error_is_set(&error));
+        assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0);
+        assert_se(error.name == NULL);
+        assert_se(error.message == NULL);
+        assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
+        assert_se(sd_bus_error_get_errno(&error) == 0);
         assert_se(!sd_bus_error_is_set(&error));
+
         assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
         assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
         assert_se(streq(error.message, "yyy -1"));
@@ -112,6 +118,16 @@ static void test_error(void) {
         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
         assert_se(sd_bus_error_get_errno(&error) == EIO);
         assert_se(sd_bus_error_is_set(&error));
+        sd_bus_error_free(&error);
+
+        /* Check with no error */
+        assert_se(!sd_bus_error_is_set(&error));
+        assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0);
+        assert_se(error.name == NULL);
+        assert_se(error.message == NULL);
+        assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
+        assert_se(sd_bus_error_get_errno(&error) == 0);
+        assert_se(!sd_bus_error_is_set(&error));
 }
 
 extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
@@ -167,6 +183,16 @@ static const sd_bus_error_map test_errors4[] = {
         SD_BUS_ERROR_MAP_END
 };
 
+static const sd_bus_error_map test_errors_bad1[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0),
+        SD_BUS_ERROR_MAP_END
+};
+
+static const sd_bus_error_map test_errors_bad2[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1),
+        SD_BUS_ERROR_MAP_END
+};
+
 static void test_errno_mapping_custom(void) {
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
@@ -190,6 +216,9 @@ static void test_errno_mapping_custom(void) {
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO);
 
         assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT);
+
+        assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL);
+        assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
 }
 
 int main(int argc, char *argv[]) {
index 931c001788d3e0ecf4e641c062a15709205b1591..83f114a0fe78d34a3b0b15962fb8cff617faa3dd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -133,8 +131,8 @@ static void test_bus_gvariant_get_alignment(void) {
 }
 
 static void test_marshal(void) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ void *blob;
         size_t sz;
         int r;
index 26ba16d119a454c4d01a5b90775f7c90984f005c..4425cfae26a9a8db91f3c746477c7fcac74f9d88 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index dbdaa69fbe782e63923bbb8633d5a40056cad5ab..eb6179d7d213fa19053041f5af9fe8a44783bd5f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -47,7 +45,7 @@ static void test_one(
 
         _cleanup_close_ int bus_ref = -1;
         _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         sd_bus *a, *b;
         int r, found = 0;
 
index 0080f71d3bf34519e2526a6617047debc0d6a6f0..22148173122cf5d7835207e401b12162e830878b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -34,8 +32,8 @@
 int main(int argc, char *argv[]) {
         _cleanup_close_ int bus_ref = -1;
         _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *ua = NULL, *ub = NULL, *the_string = NULL;
         sd_bus *a, *b;
         int r, pipe_fds[2];
index 0a6093e78be8137d7da7cb1b4e1d95e4eda3223e..a28cc5b79e69c41c7637012f76d446b608991f4f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -123,7 +121,7 @@ static void test_bus_label_escape(void) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
         int r, boolean;
         const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
         uint8_t u, v;
@@ -135,7 +133,7 @@ int main(int argc, char *argv[]) {
         _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
         _cleanup_fclose_ FILE *ms = NULL;
         size_t first_size = 0, second_size = 0, third_size = 0;
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         double dbl;
         uint64_t u64;
 
@@ -246,6 +244,8 @@ int main(int argc, char *argv[]) {
                         log_error("%s", error.message);
                 else
                         dbus_message_unref(w);
+
+                dbus_error_free(&error);
         }
 #endif
 
index 94896c196a3a796ecc2d83efc03c5e60645fb5b0..29c4529f95e0766a142e6f3441ee2510c71e18ee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -90,8 +88,8 @@ int main(int argc, char *argv[]) {
                 .type = BUS_MATCH_ROOT,
         };
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         enum bus_match_node_type i;
         sd_bus_slot slots[19];
         int r;
index edd63f9ea73c91dbbd19bf672f0866d2903ff1ea..f11cafd8881f891ed92ce9da459dea9a5d68742a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -297,9 +295,9 @@ fail:
 }
 
 static int client(struct context *c) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *s;
         int r;
 
index 428e18576946ed85e04e12da323f33d030e80ce8..45d0a5ffce6acdaba64889755b3da5983c9c5887 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -53,7 +51,7 @@ static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *
 }
 
 static void test_proxy_matched(void) {
-        _cleanup_bus_flush_close_unref_ sd_bus *a = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL;
         _cleanup_free_ char *matchstr = NULL;
         TestProxyMatch match = {};
         const char *me;
index 5bf2c1ecf85354700fa4a58a99d713670f9d2594..b6272efc30b1018cfbf17a404cc7aa84151a00ae 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -57,7 +55,7 @@ static void *server(void *p) {
         assert_se(sd_bus_start(bus) >= 0);
 
         while (!quit) {
-                _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
 
                 r = sd_bus_process(bus, &m);
                 if (r < 0) {
@@ -124,8 +122,8 @@ fail:
 }
 
 static int client(struct context *c) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
index 949d16e6e972f11c1b8e45094f7c72b08a89a6f6..4f4fd093bf80c846bda55ccbd70c21d373f47529 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1cf8416fa4f3bb7d08272fd0361286e24fc8a7ed..3380e8500a8671d44bc293d4190ff22d151fb418 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f1e9b7ed1b21ad450f745a73038e4d9544cb467d..4e50b61979a0b74c41ad210e5094ffa7bbf274c8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8d04640dc76fc7939c80602ccfffc2e5eff1cb97..eb06f9542d6efedaada81a9b59e1e30def7486ac 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index ae3157ee5ee30856c774ac53dd50a9c59a81e9a4..4a7a8b1f9e55569706b9cfaf9da7600a0f99ef8c 100644 (file)
@@ -59,7 +59,7 @@ struct sd_device_enumerator {
 };
 
 _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
-        _cleanup_device_enumerator_unref_ sd_device_enumerator *enumerator = NULL;
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL;
 
         assert(ret);
 
@@ -487,7 +487,7 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
                 return -errno;
 
         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
-                _cleanup_device_unref_ sd_device *device = NULL;
+                _cleanup_(sd_device_unrefp) sd_device *device = NULL;
                 char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1];
                 dev_t devnum;
                 int ifindex, initialized, k;
@@ -640,7 +640,7 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c
         /* TODO: filter away subsystems? */
 
         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
-                _cleanup_device_unref_ sd_device *device = NULL;
+                _cleanup_(sd_device_unrefp) sd_device *device = NULL;
                 const char *subsystem, *sysname;
                 int k;
 
@@ -710,7 +710,7 @@ static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) {
 }
 
 static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         const char *subsystem, *sysname;
         int r;
 
index a13477e75330afed4150a0ed67ca9d8ae5e82633..f2af3ab3ae3a7878b771ba132c9acd787edd86f6 100644 (file)
@@ -553,7 +553,7 @@ static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum
 }
 
 int device_new_from_strv(sd_device **ret, char **strv) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         char **key;
         const char *major = NULL, *minor = NULL;
         DeviceAction action = _DEVICE_ACTION_INVALID;
@@ -590,7 +590,7 @@ int device_new_from_strv(sd_device **ret, char **strv) {
 }
 
 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         const char *major = NULL, *minor = NULL;
         DeviceAction action = _DEVICE_ACTION_INVALID;
         uint64_t seqnum;
@@ -793,7 +793,7 @@ int device_rename(sd_device *device, const char *name) {
 }
 
 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
-        _cleanup_device_unref_ sd_device *ret = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
         int r;
 
         assert(old_device);
@@ -820,7 +820,7 @@ int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
 }
 
 int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
-        _cleanup_device_unref_ sd_device *ret = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
         int r;
 
         assert(old_device);
@@ -843,7 +843,7 @@ int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
 }
 
 int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
-        _cleanup_device_unref_ sd_device *ret = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
         int r;
 
         assert(new_device);
index d1f34efc2d6bce605465941610addc6380049e7a..29b3e155fb0e95a6b0e0b802c3c01a3965acbe5a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9b05a2498daf0272d6460b9f508a27f3fe03ab15..5b42e11de60e0f19da7f9efd62ba2f9b8679a52c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include "util.h"
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_device*, sd_device_unref);
-#define _cleanup_device_unref_ _cleanup_(sd_device_unrefp)
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_device_enumerator*, sd_device_enumerator_unref);
-#define _cleanup_device_enumerator_unref_ _cleanup_(sd_device_enumerator_unrefp)
-
 #define FOREACH_DEVICE_PROPERTY(device, key, value)                \
         for (key = sd_device_get_property_first(device, &(value)); \
              key;                                                  \
index 0e4926208784dc9b53bd5460073ecfdf36d4bf2a..9633e46ce08b5c9f196c7e3019c49b3246170acd 100644 (file)
@@ -43,7 +43,7 @@
 #include "util.h"
 
 int device_new_aux(sd_device **ret) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
 
         assert(ret);
 
@@ -222,7 +222,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
 }
 
 _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
@@ -494,7 +494,7 @@ static int handle_uevent_line(sd_device *device, const char *key, const char *va
 
 int device_read_uevent_file(sd_device *device) {
         _cleanup_free_ char *uevent = NULL;
-        const char *syspath, *key, *value, *major = NULL, *minor = NULL;
+        const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
         char *path;
         size_t uevent_len;
         unsigned i;
@@ -624,7 +624,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
         }
         case 'n':
         {
-                _cleanup_device_unref_ sd_device *device = NULL;
+                _cleanup_(sd_device_unrefp) sd_device *device = NULL;
                 _cleanup_close_ int sk = -1;
                 struct ifreq ifr = {};
                 int ifindex;
diff --git a/src/libsystemd/sd-event/event-util.h b/src/libsystemd/sd-event/event-util.h
deleted file mode 100644 (file)
index ae02034..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  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 "sd-event.h"
-
-#include "util.h"
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event*, sd_event_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, sd_event_source_unref);
-
-#define _cleanup_event_unref_ _cleanup_(sd_event_unrefp)
-#define _cleanup_event_source_unref_ _cleanup_(sd_event_source_unrefp)
index 700ac691b5ba0710a3e67ba2fed4220c62b0c558..deef6ba9d36b7e50c4615e77a4dad3b7af6e249c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -37,6 +35,7 @@
 #include "process-util.h"
 #include "set.h"
 #include "signal-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "time-util.h"
 #include "util.h"
@@ -60,6 +59,23 @@ typedef enum EventSourceType {
         _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
 } EventSourceType;
 
+static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
+        [SOURCE_IO] = "io",
+        [SOURCE_TIME_REALTIME] = "realtime",
+        [SOURCE_TIME_BOOTTIME] = "bootime",
+        [SOURCE_TIME_MONOTONIC] = "monotonic",
+        [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
+        [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
+        [SOURCE_SIGNAL] = "signal",
+        [SOURCE_CHILD] = "child",
+        [SOURCE_DEFER] = "defer",
+        [SOURCE_POST] = "post",
+        [SOURCE_EXIT] = "exit",
+        [SOURCE_WATCHDOG] = "watchdog",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
+
 /* All objects we use in epoll events start with this value, so that
  * we know how to dispatch it */
 typedef enum WakeupType {
@@ -207,6 +223,7 @@ struct sd_event {
         bool exit_requested:1;
         bool need_process_child:1;
         bool watchdog:1;
+        bool profile_delays:1;
 
         int exit_code;
 
@@ -218,6 +235,9 @@ struct sd_event {
         unsigned n_sources;
 
         LIST_HEAD(sd_event_source, sources);
+
+        usec_t last_run, last_log;
+        unsigned delays[sizeof(usec_t) * 8];
 };
 
 static void source_disconnect(sd_event_source *s);
@@ -305,6 +325,10 @@ static int earliest_time_prioq_compare(const void *a, const void *b) {
         return 0;
 }
 
+static usec_t time_event_source_latest(const sd_event_source *s) {
+        return usec_add(s->time.next, s->time.accuracy);
+}
+
 static int latest_time_prioq_compare(const void *a, const void *b) {
         const sd_event_source *x = a, *y = b;
 
@@ -324,9 +348,9 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
                 return 1;
 
         /* Order by time */
-        if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
+        if (time_event_source_latest(x) < time_event_source_latest(y))
                 return -1;
-        if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
+        if (time_event_source_latest(x) > time_event_source_latest(y))
                 return 1;
 
         return 0;
@@ -416,11 +440,9 @@ _public_ int sd_event_new(sd_event** ret) {
         e->original_pid = getpid();
         e->perturb = USEC_INFINITY;
 
-        e->pending = prioq_new(pending_prioq_compare);
-        if (!e->pending) {
-                r = -ENOMEM;
+        r = prioq_ensure_allocated(&e->pending, pending_prioq_compare);
+        if (r < 0)
                 goto fail;
-        }
 
         e->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
         if (e->epoll_fd < 0) {
@@ -428,6 +450,11 @@ _public_ int sd_event_new(sd_event** ret) {
                 goto fail;
         }
 
+        if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) {
+                log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s.");
+                e->profile_delays = true;
+        }
+
         *ret = e;
         return 0;
 
@@ -437,7 +464,9 @@ fail:
 }
 
 _public_ sd_event* sd_event_ref(sd_event *e) {
-        assert_return(e, NULL);
+
+        if (!e)
+                return NULL;
 
         assert(e->n_ref >= 1);
         e->n_ref++;
@@ -482,7 +511,8 @@ static void source_io_unregister(sd_event_source *s) {
 
         r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL);
         if (r < 0)
-                log_debug_errno(errno, "Failed to remove source %s from epoll: %m", strna(s->description));
+                log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m",
+                                strna(s->description), event_source_type_to_string(s->type));
 
         s->io.registered = false;
 }
@@ -633,8 +663,10 @@ static int event_make_signal_data(
                 d->priority = priority;
 
                 r = hashmap_put(e->signal_data, &d->priority, d);
-                if (r < 0)
+                if (r < 0) {
+                        free(d);
                         return r;
+                }
 
                 added = true;
         }
@@ -1036,7 +1068,6 @@ _public_ int sd_event_add_time(
         int r;
 
         assert_return(e, -EINVAL);
-        assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(accuracy != (uint64_t) -1, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
@@ -1050,17 +1081,13 @@ _public_ int sd_event_add_time(
         d = event_get_clock_data(e, type);
         assert(d);
 
-        if (!d->earliest) {
-                d->earliest = prioq_new(earliest_time_prioq_compare);
-                if (!d->earliest)
-                        return -ENOMEM;
-        }
+        r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare);
+        if (r < 0)
+                return r;
 
-        if (!d->latest) {
-                d->latest = prioq_new(latest_time_prioq_compare);
-                if (!d->latest)
-                        return -ENOMEM;
-        }
+        r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare);
+        if (r < 0)
+                return r;
 
         if (d->fd < 0) {
                 r = event_setup_timer_fd(e, d, clock);
@@ -1311,11 +1338,9 @@ _public_ int sd_event_add_exit(
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
-        if (!e->exit) {
-                e->exit = prioq_new(exit_prioq_compare);
-                if (!e->exit)
-                        return -ENOMEM;
-        }
+        r = prioq_ensure_allocated(&e->exit, exit_prioq_compare);
+        if (r < 0)
+                return r;
 
         s = source_new(e, !ret, SOURCE_EXIT);
         if (!s)
@@ -1339,7 +1364,9 @@ _public_ int sd_event_add_exit(
 }
 
 _public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
-        assert_return(s, NULL);
+
+        if (!s)
+                return NULL;
 
         assert(s->n_ref >= 1);
         s->n_ref++;
@@ -1730,7 +1757,6 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         struct clock_data *d;
 
         assert_return(s, -EINVAL);
-        assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
@@ -1860,6 +1886,8 @@ static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
 
         if (a <= 0)
                 return 0;
+        if (a >= USEC_INFINITY)
+                return USEC_INFINITY;
 
         if (b <= a + 1)
                 return a;
@@ -1949,7 +1977,7 @@ static int event_arm_timer(
                 d->needs_rearm = false;
 
         a = prioq_peek(d->earliest);
-        if (!a || a->enabled == SD_EVENT_OFF) {
+        if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) {
 
                 if (d->fd < 0)
                         return 0;
@@ -1969,7 +1997,7 @@ static int event_arm_timer(
         b = prioq_peek(d->latest);
         assert_se(b && b->enabled != SD_EVENT_OFF);
 
-        t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
+        t = sleep_between(e, a->time.next, time_event_source_latest(b));
         if (d->next == t)
                 return 0;
 
@@ -2285,12 +2313,9 @@ static int source_dispatch(sd_event_source *s) {
 
         s->dispatching = false;
 
-        if (r < 0) {
-                if (s->description)
-                        log_debug_errno(r, "Event source '%s' returned error, disabling: %m", s->description);
-                else
-                        log_debug_errno(r, "Event source %p returned error, disabling: %m", s);
-        }
+        if (r < 0)
+                log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m",
+                                strna(s->description), event_source_type_to_string(s->type));
 
         if (s->n_ref == 0)
                 source_free(s);
@@ -2323,12 +2348,9 @@ static int event_prepare(sd_event *e) {
                 r = s->prepare(s, s->userdata);
                 s->dispatching = false;
 
-                if (r < 0) {
-                        if (s->description)
-                                log_debug_errno(r, "Prepare callback of event source '%s' returned error, disabling: %m", s->description);
-                        else
-                                log_debug_errno(r, "Prepare callback of event source %p returned error, disabling: %m", s);
-                }
+                if (r < 0)
+                        log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m",
+                                        strna(s->description), event_source_type_to_string(s->type));
 
                 if (s->n_ref == 0)
                         source_free(s);
@@ -2433,7 +2455,9 @@ _public_ int sd_event_prepare(sd_event *e) {
 
         e->iteration++;
 
+        e->state = SD_EVENT_PREPARING;
         r = event_prepare(e);
+        e->state = SD_EVENT_INITIAL;
         if (r < 0)
                 return r;
 
@@ -2611,6 +2635,18 @@ _public_ int sd_event_dispatch(sd_event *e) {
         return 1;
 }
 
+static void event_log_delays(sd_event *e) {
+        char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1];
+        unsigned i;
+        int o;
+
+        for (i = o = 0; i < ELEMENTSOF(e->delays); i++) {
+                o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]);
+                e->delays[i] = 0;
+        }
+        log_debug("Event loop iterations: %.*s", o, b);
+}
+
 _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         int r;
 
@@ -2619,11 +2655,30 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
 
+        if (e->profile_delays && e->last_run) {
+                usec_t this_run;
+                unsigned l;
+
+                this_run = now(CLOCK_MONOTONIC);
+
+                l = u64log2(this_run - e->last_run);
+                assert(l < sizeof(e->delays));
+                e->delays[l]++;
+
+                if (this_run - e->last_log >= 5*USEC_PER_SEC) {
+                        event_log_delays(e);
+                        e->last_log = this_run;
+                }
+        }
+
         r = sd_event_prepare(e);
         if (r == 0)
                 /* There was nothing? Then wait... */
                 r = sd_event_wait(e, timeout);
 
+        if (e->profile_delays)
+                e->last_run = now(CLOCK_MONOTONIC);
+
         if (r > 0) {
                 /* There's something now, then let's dispatch it */
                 r = sd_event_dispatch(e);
@@ -2700,6 +2755,12 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
+        assert_return(IN_SET(clock,
+                             CLOCK_REALTIME,
+                             CLOCK_REALTIME_ALARM,
+                             CLOCK_MONOTONIC,
+                             CLOCK_BOOTTIME,
+                             CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
 
         if (!dual_timestamp_is_set(&e->timestamp)) {
                 /* Implicitly fall back to now() if we never ran
@@ -2719,8 +2780,7 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
                 *usec = e->timestamp.monotonic;
                 break;
 
-        case CLOCK_BOOTTIME:
-        case CLOCK_BOOTTIME_ALARM:
+        default:
                 *usec = e->timestamp_boottime;
                 break;
         }
index c1a3b494836e7dc658a8f96fd35798797b5336b8..daea4126f863b6981347ddeb75197d222cfa2935 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -158,11 +156,22 @@ static int exit_handler(sd_event_source *s, void *userdata) {
         return 3;
 }
 
+static bool got_post = false;
+
+static int post_handler(sd_event_source *s, void *userdata) {
+        log_info("got post handler");
+
+        got_post = true;
+
+        return 2;
+}
+
 static void test_basic(void) {
         sd_event *e = NULL;
         sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
         static const char ch = 'x';
         int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
+        uint64_t event_now;
 
         assert_se(pipe(a) >= 0);
         assert_se(pipe(b) >= 0);
@@ -170,6 +179,7 @@ static void test_basic(void) {
         assert_se(pipe(k) >= 0);
 
         assert_se(sd_event_default(&e) >= 0);
+        assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
 
         assert_se(sd_event_set_watchdog(e, true) >= 0);
 
@@ -230,10 +240,14 @@ static void test_basic(void) {
         sd_event_source_unref(y);
 
         do_quit = true;
-        assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
+        assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0);
+        assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
+        assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0);
         assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
 
         assert_se(sd_event_loop(e) >= 0);
+        assert_se(got_post);
+        assert_se(got_exit);
 
         sd_event_source_unref(z);
         sd_event_source_unref(q);
@@ -248,6 +262,30 @@ static void test_basic(void) {
         safe_close_pair(k);
 }
 
+static void test_sd_event_now(void) {
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        uint64_t event_now;
+
+        assert_se(sd_event_new(&e) >= 0);
+        assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
+        assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
+        assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0);
+        assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
+        assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
+        assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
+        assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
+
+        assert_se(sd_event_run(e, 0) == 0);
+
+        assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
+        assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
+        assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
+        assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
+        assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
+        assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
+        assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
+}
+
 static int last_rtqueue_sigval = 0;
 static int n_rtqueue = 0;
 
@@ -308,7 +346,11 @@ static void test_rtqueue(void) {
 
 int main(int argc, char *argv[]) {
 
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+
         test_basic();
+        test_sd_event_now();
         test_rtqueue();
 
         return 0;
index d366c6fa417944a0228ca4a489a229d057bc84e2..5e21e5008bb3e6ea1ec51939d694b2950fda204e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,7 +23,4 @@
 
 #include "util.h"
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_hwdb*, sd_hwdb_unref);
-#define _cleanup_hwdb_unref_ _cleanup_(sd_hwdb_unrefp)
-
 bool hwdb_validate(sd_hwdb *hwdb);
index 0e034863d6c667bbf6997b5e4ae4f92df78c70db..062fa97b1773d731cd1d62d42a2748bbb9272cee 100644 (file)
@@ -279,7 +279,7 @@ static const char hwdb_bin_paths[] =
         UDEVLIBEXECDIR "/hwdb.bin\0";
 
 _public_ int sd_hwdb_new(sd_hwdb **ret) {
-        _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+        _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
         const char *hwdb_bin_path;
         const char sig[] = HWDB_SIG;
 
index c12bb1e20beb242c8206010fe46c9ceac39d6e89..d9c0116f60a53373428b6534113f3fc3693df6fe 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3f2e459825797b4f2f124e924de63a69b265119e..9d4f187502bda59c009be25927118eaddd55e2e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -810,7 +808,7 @@ _public_ int sd_get_uids(uid_t **users) {
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return -errno;
 
                 if (!de)
@@ -1017,7 +1015,8 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
         int fd;
 
-        assert_return(m, NULL);
+        if (!m)
+                return NULL;
 
         fd = MONITOR_TO_FD(m);
         close_nointr(fd);
index b0f94c9522ec379de9fdc287fae6d520683f12dd..c1fd7dd33e4abe544691cb8917d89dba5dac048d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d431ba4be4d1d664ccc2e9004f29a39e6d3d7a37..6abd8fd0cc0fd70b904d582e763e5f0240b4febc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -56,8 +54,8 @@ static int address_compare(const void *_a, const void *_b) {
 }
 
 int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ struct local_address *list = NULL;
         size_t n_list = 0, n_allocated = 0;
         sd_netlink_message *m;
@@ -167,8 +165,8 @@ int local_addresses(sd_netlink *context, int ifindex, int af, struct local_addre
 }
 
 int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ struct local_address *list = NULL;
         sd_netlink_message *m = NULL;
         size_t n_list = 0, n_allocated = 0;
index 5d0f11a2c1807e2ac3a5f4a1ebfac79f168349e8..18d71e797efab820a4be9544025c9d9fd28666f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 
 
 #include "sd-netlink.h"
+
 #include "in-addr-util.h"
 
 struct local_address {
index 8519a4d523a848932c728439b4f67b479df6a260..dcfb080ad38058d2afbe66713e90751e07d43205 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -135,5 +133,5 @@ int rtnl_rqueue_make_room(sd_netlink *rtnl);
 int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
 
 /* Make sure callbacks don't destroy the rtnl connection */
-#define RTNL_DONT_DESTROY(rtnl) \
-        _cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
+#define NETLINK_DONT_DESTROY(rtnl) \
+        _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
index 03971b35963cfe04ae667c4b2aeac33fda7709ec..3a866fdafe0104469c72801bf0b9f0f227302e73 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -65,7 +63,7 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
 }
 
 int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         const NLType *nl_type;
         size_t size;
         int r;
@@ -342,6 +340,19 @@ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, ui
         return 0;
 }
 
+int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) {
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(!m->sealed, -EPERM);
+
+        r = add_rtattr(m, type, &data, len);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) {
         int r;
 
index 13945202e40a93565209405e68341d7b1a5b04d1..590fc53fc78cf02c0bc5ce4598518e550de6da3e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -52,7 +50,7 @@ static int broadcast_groups_get(sd_netlink *nl) {
         int r;
 
         assert(nl);
-        assert(nl->fd > 0);
+        assert(nl->fd >= 0);
 
         r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
         if (r < 0) {
@@ -323,7 +321,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
  * On failure, a negative error code is returned.
  */
 int socket_read_message(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *first = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
         struct iovec iov = {};
         uint32_t group = 0;
         bool multi_part = false, done = false;
@@ -376,7 +374,7 @@ int socket_read_message(sd_netlink *rtnl) {
         }
 
         for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
                 const NLType *nl_type;
 
                 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
index 135354e5f3478ecac03469fbcd44cab2572be9da..a5758bb516842c00f1d69ea4c59031c6ea0cfe16 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -96,15 +94,6 @@ static const NLType rtnl_link_info_data_macvlan_types[] = {
         [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
 };
 
-static const NLType rtnl_link_bridge_management_types[] = {
-        [IFLA_BRIDGE_FLAGS]     = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_MODE]      = { .type = NETLINK_TYPE_U16 },
-/*
-        [IFLA_BRIDGE_VLAN_INFO] = { .type = NETLINK_TYPE_BINARY,
-                                    .len = sizeof(struct bridge_vlan_info), },
-*/
-};
-
 static const NLType rtnl_link_info_data_bridge_types[] = {
         [IFLA_BR_FORWARD_DELAY]  = { .type = NETLINK_TYPE_U32 },
         [IFLA_BR_HELLO_TIME]     = { .type = NETLINK_TYPE_U32 },
index 9e636a0b53865c929ab86a65066c7df4858828a5..ecb20bfcdc0a2b9bdc3de23810ee0a424ca214a7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 95690b7ff1244f77cc20c8ec5d13cbe23133b2d8..73b9ac0258cacd955045b7743223dbb8681ab256 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
@@ -25,7 +23,7 @@
 #include "netlink-util.h"
 
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
         int r;
 
         assert(rtnl);
@@ -55,7 +53,7 @@ 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) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
         int r;
 
         assert(rtnl);
index acc6c15ff312e41a679fc6f264ae99de60259e42..f49bf4eaa6567f38359bee23743092c0c3061645 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -39,9 +37,3 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
 
 int rtnl_log_parse_error(int r);
 int rtnl_log_create_error(int r);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_netlink*, sd_netlink_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_netlink_message*, sd_netlink_message_unref);
-
-#define _cleanup_netlink_unref_ _cleanup_(sd_netlink_unrefp)
-#define _cleanup_netlink_message_unref_ _cleanup_(sd_netlink_message_unrefp)
index 3e605db6618dd0a9db57b87c67b475a1683c3f41..090552f5765abe5c6e1e61f43d14bb4ab40d0b4e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7c24e053cfb5bf1a6718f0d0b9f6cc8ad7f1830a..4833815b43f5c1251847a98f60eafbbbd1e742f8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -35,7 +33,7 @@
 #include "util.h"
 
 static int sd_netlink_new(sd_netlink **ret) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
 
         assert_return(ret, -EINVAL);
 
@@ -44,11 +42,8 @@ static int sd_netlink_new(sd_netlink **ret) {
                 return -ENOMEM;
 
         rtnl->n_ref = REFCNT_INIT;
-
         rtnl->fd = -1;
-
         rtnl->sockaddr.nl.nl_family = AF_NETLINK;
-
         rtnl->original_pid = getpid();
 
         LIST_HEAD_INIT(rtnl->match_callbacks);
@@ -71,7 +66,7 @@ static int sd_netlink_new(sd_netlink **ret) {
 }
 
 int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         socklen_t addrlen;
         int r;
 
@@ -87,6 +82,9 @@ int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
         if (r < 0)
                 return -errno;
 
+        if (rtnl->sockaddr.nl.nl_family != AF_NETLINK)
+                return -EINVAL;
+
         rtnl->fd = fd;
 
         *ret = rtnl;
@@ -105,7 +103,7 @@ static bool rtnl_pid_changed(sd_netlink *rtnl) {
 }
 
 int sd_netlink_open_fd(sd_netlink **ret, int fd) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
@@ -118,8 +116,10 @@ int sd_netlink_open_fd(sd_netlink **ret, int fd) {
         rtnl->fd = fd;
 
         r = socket_bind(rtnl);
-        if (r < 0)
+        if (r < 0) {
+                rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
                 return r;
+        }
 
         *ret = rtnl;
         rtnl = NULL;
@@ -286,7 +286,7 @@ static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
 }
 
 static int process_timeout(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         struct reply_callback *c;
         usec_t n;
         int r;
@@ -376,7 +376,7 @@ static int process_match(sd_netlink *rtnl, sd_netlink_message *m) {
 }
 
 static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         int r;
 
         assert(rtnl);
@@ -418,7 +418,7 @@ null_message:
 }
 
 int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) {
-        RTNL_DONT_DESTROY(rtnl);
+        NETLINK_DONT_DESTROY(rtnl);
         int r;
 
         assert_return(rtnl, -EINVAL);
@@ -623,7 +623,7 @@ int sd_netlink_call(sd_netlink *rtnl,
                         received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
 
                         if (received_serial == serial) {
-                                _cleanup_netlink_message_unref_ sd_netlink_message *incoming = NULL;
+                                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
                                 uint16_t type;
 
                                 incoming = rtnl->rqueue[i];
index 0b53297ab80db5675f1f0fb121e5629b28025642..e0e28cc0cccb6b764b3eae3cefd02b62957dce8e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 58b774e0e1acf6431d1fd2f535066a5d4cbc7b3d..de5e0ffc8fc89fca3ba55fc3872929eb901de5dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -25,7 +23,6 @@
 #include "sd-netlink.h"
 
 #include "ether-addr-util.h"
-#include "event-util.h"
 #include "macro.h"
 #include "missing.h"
 #include "netlink-util.h"
@@ -34,7 +31,7 @@
 #include "util.h"
 
 static void test_message_link_bridge(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
         uint32_t cost;
 
         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
@@ -52,7 +49,7 @@ static void test_message_link_bridge(sd_netlink *rtnl) {
 }
 
 static void test_link_configure(sd_netlink *rtnl, int ifindex) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
         const char *mac = "98:fe:94:3f:c6:18", *name = "test";
         char buffer[ETHER_ADDR_TO_STRING_MAX];
         unsigned int mtu = 1450, mtu_out;
@@ -146,7 +143,7 @@ static void test_address_get(sd_netlink *rtnl, int ifindex) {
 }
 
 static void test_route(void) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req;
         struct in_addr addr, addr_data;
         uint32_t index = 2, u32_data;
         int r;
@@ -209,9 +206,9 @@ static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
 }
 
 static void test_event_loop(int ifindex) {
-        _cleanup_event_unref_ sd_event *event = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         char *ifname;
 
         ifname = strdup("lo2");
@@ -249,8 +246,8 @@ static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
 }
 
 static void test_async(int ifindex) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *r = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
         uint32_t serial;
         char *ifname;
 
@@ -270,8 +267,8 @@ static void test_async(int ifindex) {
 }
 
 static void test_pipe(int ifindex) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *m1 = NULL, *m2 = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
         int counter = 0;
 
         assert_se(sd_netlink_open(&rtnl) >= 0);
@@ -294,7 +291,7 @@ static void test_pipe(int ifindex) {
 }
 
 static void test_container(void) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         uint16_t u16_data;
         uint32_t u32_data;
         const char *string_data;
@@ -329,7 +326,7 @@ static void test_container(void) {
 }
 
 static void test_match(void) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
 
         assert_se(sd_netlink_open(&rtnl) >= 0);
 
@@ -344,7 +341,7 @@ static void test_match(void) {
 }
 
 static void test_get_addresses(sd_netlink *rtnl) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *m;
 
         assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
@@ -372,7 +369,7 @@ static void test_get_addresses(sd_netlink *rtnl) {
 }
 
 static void test_message(void) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
 
         assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT, 1, &m) >= 0);
         assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
index a2d6c5931470d0446108bfb1fbb9239be2e69a1a..a0d9b5f1a48dfaf3fc417515fbf9379f86c451d0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 11a0012348bf55b96014528d0c345242f290943a..26780dce2887abd5bc711df4e55ed18ec1095327 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,7 +21,4 @@
 
 #include "sd-network.h"
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_network_monitor*, sd_network_monitor_unref);
-#define _cleanup_network_monitor_unref_ _cleanup_(sd_network_monitor_unrefp)
-
 bool network_is_online(void);
index efbceba83d114c18aa3ba7dae0d7f2b988858576..62051992ef6ffe85ac83e51c15c5a232deb8ab45 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -95,21 +93,25 @@ _public_ int sd_network_get_ntp(char ***ret) {
         return network_get_strv("NTP", ret);
 }
 
-_public_ int sd_network_get_domains(char ***ret) {
+_public_ int sd_network_get_search_domains(char ***ret) {
         return network_get_strv("DOMAINS", ret);
 }
 
-_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
+_public_ int sd_network_get_route_domains(char ***ret) {
+        return network_get_strv("ROUTE_DOMAINS", ret);
+}
+
+static int network_link_get_string(int ifindex, const char *field, char **ret) {
         _cleanup_free_ char *s = NULL, *p = NULL;
         int r;
 
         assert_return(ifindex > 0, -EINVAL);
-        assert_return(state, -EINVAL);
+        assert_return(ret, -EINVAL);
 
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
+        if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0)
                 return -ENOMEM;
 
-        r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
+        r = parse_env_file(p, NEWLINE, field, &s, NULL);
         if (r == -ENOENT)
                 return -ENODATA;
         if (r < 0)
@@ -117,82 +119,72 @@ _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
         if (isempty(s))
                 return -ENODATA;
 
-        *state = s;
+        *ret = s;
         s = NULL;
 
         return 0;
 }
 
-_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
-        _cleanup_free_ char *s = NULL, *p = NULL;
+static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
+        _cleanup_free_ char *p = NULL, *s = NULL;
+        _cleanup_strv_free_ char **a = NULL;
         int r;
 
         assert_return(ifindex > 0, -EINVAL);
-        assert_return(filename, -EINVAL);
+        assert_return(ret, -EINVAL);
 
         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
                 return -ENOMEM;
 
-        r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL);
+        r = parse_env_file(p, NEWLINE, key, &s, NULL);
         if (r == -ENOENT)
                 return -ENODATA;
         if (r < 0)
                 return r;
-        if (isempty(s))
-                return -ENODATA;
-
-        *filename = s;
-        s = NULL;
+        if (isempty(s)) {
+                *ret = NULL;
+                return 0;
+        }
 
-        return 0;
-}
+        a = strv_split(s, " ");
+        if (!a)
+                return -ENOMEM;
 
-_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
-        _cleanup_free_ char *s = NULL, *p = NULL;
-        int r;
+        strv_uniq(a);
+        r = strv_length(a);
 
-        assert_return(ifindex > 0, -EINVAL);
-        assert_return(state, -EINVAL);
+        *ret = a;
+        a = NULL;
 
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
-                return -ENOMEM;
+        return r;
+}
 
-        r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
-        if (r == -ENOENT)
-                return -ENODATA;
-        if (r < 0)
-                return r;
-        if (isempty(s))
-                return -ENODATA;
+_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
+        return network_link_get_string(ifindex, "ADMIN_STATE", state);
+}
 
-        *state = s;
-        s = NULL;
+_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
+        return network_link_get_string(ifindex, "NETWORK_FILE", filename);
+}
 
-        return 0;
+_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
+        return network_link_get_string(ifindex, "OPER_STATE", state);
 }
 
 _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
-        _cleanup_free_ char *s = NULL, *p = NULL;
-        int r;
-
-        assert_return(ifindex > 0, -EINVAL);
-        assert_return(llmnr, -EINVAL);
-
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
-                return -ENOMEM;
+        return network_link_get_string(ifindex, "LLMNR", llmnr);
+}
 
-        r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
-        if (r == -ENOENT)
-                return -ENODATA;
-        if (r < 0)
-                return r;
-        if (isempty(s))
-                return -ENODATA;
+_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
+        return network_link_get_string(ifindex, "MDNS", mdns);
+}
 
-        *llmnr = s;
-        s = NULL;
+_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
+        return network_link_get_string(ifindex, "DNSSEC", dnssec);
+}
 
-        return 0;
+_public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) {
+        return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
 }
 
 _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
@@ -221,100 +213,31 @@ _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
 }
 
 int sd_network_link_get_timezone(int ifindex, char **ret) {
-        _cleanup_free_ char *s = NULL, *p = NULL;
-        int r;
-
-        assert_return(ifindex > 0, -EINVAL);
-        assert_return(ret, -EINVAL);
-
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
-                return -ENOMEM;
-
-        r = parse_env_file(p, NEWLINE, "TIMEZONE", &s, NULL);
-        if (r == -ENOENT)
-                return -ENODATA;
-        if (r < 0)
-                return r;
-        if (isempty(s))
-                return -ENODATA;
-
-        *ret = s;
-        s = NULL;
-        return 0;
-}
-
-static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
-        _cleanup_free_ char *p = NULL, *s = NULL;
-        _cleanup_strv_free_ char **a = NULL;
-        int r;
-
-        assert_return(ifindex > 0, -EINVAL);
-        assert_return(ret, -EINVAL);
-
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
-                return -ENOMEM;
-
-        r = parse_env_file(p, NEWLINE, key, &s, NULL);
-        if (r == -ENOENT)
-                return -ENODATA;
-        if (r < 0)
-                return r;
-        if (isempty(s)) {
-                *ret = NULL;
-                return 0;
-        }
-
-        a = strv_split(s, " ");
-        if (!a)
-                return -ENOMEM;
-
-        strv_uniq(a);
-        r = strv_length(a);
-
-        *ret = a;
-        a = NULL;
-
-        return r;
+        return network_link_get_string(ifindex, "TIMEZONE", ret);
 }
 
 _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
-        return network_get_link_strv("DNS", ifindex, ret);
+        return network_link_get_strv(ifindex, "DNS", ret);
 }
 
 _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
-        return network_get_link_strv("NTP", ifindex, ret);
+        return network_link_get_strv(ifindex, "NTP", ret);
 }
 
-_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
-        return network_get_link_strv("DOMAINS", ifindex, ret);
+_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) {
+        return network_link_get_strv(ifindex, "DOMAINS", ret);
 }
 
-_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
-        return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret);
+_public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
+        return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
 }
 
-_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
-        return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret);
+_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
+        return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
 }
 
-_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
-        int r;
-        _cleanup_free_ char *p = NULL, *s = NULL;
-
-        assert_return(ifindex > 0, -EINVAL);
-
-        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
-                return -ENOMEM;
-
-        r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
-        if (r == -ENOENT)
-                return -ENODATA;
-        if (r < 0)
-                return r;
-        if (isempty(s))
-                return -ENODATA;
-
-        return parse_boolean(s);
+_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
+        return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
 }
 
 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
diff --git a/src/libsystemd/sd-resolve/resolve-util.h b/src/libsystemd/sd-resolve/resolve-util.h
deleted file mode 100644 (file)
index 51a8a8a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 Daniel Buch
-
-  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-resolve.h"
-
-#include "util.h"
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve*, sd_resolve_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve_query*, sd_resolve_query_unref);
-
-#define _cleanup_resolve_unref_ _cleanup_(sd_resolve_unrefp)
-#define _cleanup_resolve_query_unref_ _cleanup_(sd_resolve_query_unrefp)
index 34a0b03f92ff0b00b94ed38a14ca33547f164edc..653dbfbe57e19c4a943d09d3343b1f58b41ce54f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -38,7 +36,6 @@
 #include "io-util.h"
 #include "list.h"
 #include "missing.h"
-#include "resolve-util.h"
 #include "socket-util.h"
 #include "util.h"
 
@@ -179,7 +176,7 @@ static int getnameinfo_done(sd_resolve_query *q);
 static void resolve_query_disconnect(sd_resolve_query *q);
 
 #define RESOLVE_DONT_DESTROY(resolve) \
-        _cleanup_resolve_unref_ _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
+        _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
 
 static int send_died(int out_fd) {
 
index 05544a584c75d22d0d4f5a22fb68569b711e8d17..33ef6fc0f7469c34863f964bdcf7ac042b240744 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -32,7 +30,6 @@
 
 #include "alloc-util.h"
 #include "macro.h"
-#include "resolve-util.h"
 #include "socket-util.h"
 #include "string-util.h"
 
@@ -71,8 +68,8 @@ static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, c
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_resolve_query_unref_ sd_resolve_query *q1 = NULL, *q2 = NULL;
-        _cleanup_resolve_unref_ sd_resolve *resolve = NULL;
+        _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q1 = NULL, *q2 = NULL;
+        _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL;
         int r = 0;
 
         struct addrinfo hints = {
@@ -102,11 +99,11 @@ int main(int argc, char *argv[]) {
         if (r < 0)
                 log_error_errno(r, "sd_resolve_getnameinfo(): %m");
 
-        /* Wait until the two queries are completed */
-        while (sd_resolve_query_is_done(q1) == 0 ||
-               sd_resolve_query_is_done(q2) == 0) {
-
+        /* Wait until all queries are completed */
+        for (;;) {
                 r = sd_resolve_wait(resolve, (uint64_t) -1);
+                if (r == 0)
+                        break;
                 if (r < 0) {
                         log_error_errno(r, "sd_resolve_wait(): %m");
                         assert_not_reached("sd_resolve_wait() failed");
index 9e52db3b3dd6b2fa1d10bae933e642b7f1d61ef2..33a5a04ea1caeb19b05aef78d3b8911567d8b4cb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 2d3e62410c5724a3e2684bf890912c577dbfcbf7..2aae0726c1ee955ca1591c37907493c5ebfcc6bd 100644 (file)
@@ -137,14 +137,10 @@ gid_t udev_device_get_devnode_gid(struct udev_device *udev_device) {
 }
 
 void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *udev_device_old) {
-        sd_device *device_old = NULL;
-
         assert(udev_device);
 
-        if (udev_device_old)
-                device_old = udev_device_old->device;
-
-        device_ensure_usec_initialized(udev_device->device, device_old);
+        device_ensure_usec_initialized(udev_device->device,
+                                       udev_device_old ? udev_device_old->device : NULL);
 }
 
 char **udev_device_get_properties_envp(struct udev_device *udev_device) {
index 442f9615f2d4310a4eabc5b612d9926e256ebad3..e416e178b4fa057c5d78374a644ef1367cf8701f 100644 (file)
@@ -370,7 +370,7 @@ _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumer
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) {
-        _cleanup_device_unref_ sd_device *device = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         int r;
 
         assert_return(udev_enumerate, -EINVAL);
index eba698d163e57689f956f5526e0d62de97dab7fb..a53f000015468046157d84dd6f7f5ab72424b18a 100644 (file)
@@ -53,7 +53,7 @@ struct udev_hwdb {
  * Returns: a hwdb context.
  **/
 _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
-        _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL;
+        _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb_internal = NULL;
         struct udev_hwdb *hwdb;
         int r;
 
index 5f504962919582cf926fbb2c6a1c8af899a11314..52c50751107f32f17969e94f4eb485fd5637ed2d 100644 (file)
@@ -21,8 +21,8 @@
 #define _LIBUDEV_PRIVATE_H_
 
 #include <signal.h>
-#include <stdint.h>
 #include <stdbool.h>
+#include <stdint.h>
 
 #include "libudev.h"
 
index 4a339dcfd44bd95088f714fef8f4452a54431421..365c79aa5119b14f3483c04184a7623ebe6e3b9d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -195,8 +193,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_locale(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -248,7 +246,7 @@ static int list_locales(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *map, *toggle_map;
         int r;
 
@@ -351,7 +349,7 @@ static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *layout, *model, *variant, *options;
         int r;
 
@@ -666,7 +664,7 @@ static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
 }
 
 int main(int argc, char*argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
index 720cbbaaba0121b6be453cdf8edd644bad6e4baf..f0fe59cc675ba461b5ae5cc378be1a670a05ff07 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -36,7 +34,6 @@
 #include "bus-util.h"
 #include "def.h"
 #include "env-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "fileio-label.h"
 #include "fileio.h"
@@ -327,7 +324,7 @@ static int locale_write_data(Context *c, char ***settings) {
 static int locale_update_system_manager(Context *c, sd_bus *bus) {
         _cleanup_free_ char **l_unset = NULL;
         _cleanup_strv_free_ char **l_set = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         sd_bus_error error = SD_BUS_ERROR_NULL;
         unsigned c_set, c_unset, p;
         int r;
@@ -500,7 +497,7 @@ fail:
 }
 
 static int vconsole_reload(sd_bus *bus) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -540,7 +537,7 @@ static int read_next_mapping(const char* filename,
                 if (!fgets(line, sizeof(line), f)) {
 
                         if (ferror(f))
-                                return errno ? -errno : -EIO;
+                                return errno > 0 ? -errno : -EIO;
 
                         return 0;
                 }
@@ -1259,7 +1256,7 @@ static const sd_bus_vtable locale_vtable[] = {
 };
 
 static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         assert(c);
@@ -1290,8 +1287,8 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
 
 int main(int argc, char *argv[]) {
         _cleanup_(context_free) Context context = {};
-        _cleanup_event_unref_ sd_event *event = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         log_set_target(LOG_TARGET_AUTO);
index 70fef332f7e4de99ab0d355b652661037b55a592..f2c37a8623ae84f29945fc8bd0424b50773880f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -49,7 +47,7 @@ static enum {
 } arg_action = ACTION_INHIBIT;
 
 static int inhibit(sd_bus *bus, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
         int fd;
 
@@ -77,7 +75,7 @@ static int inhibit(sd_bus *bus, sd_bus_error *error) {
 }
 
 static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *what, *who, *why, *mode;
         unsigned int uid, pid;
         unsigned n = 0;
@@ -223,8 +221,8 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         log_parse_environment();
index aff68a49fe976655a84344b47b61ac365f0fa3e0..6ad3d089bdfe5c41a96dc04d005aee54d2f69503 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -88,12 +86,12 @@ static OutputFlags get_output_flags(void) {
                 arg_all * OUTPUT_SHOW_ALL |
                 arg_full * OUTPUT_FULL_WIDTH |
                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
-                on_tty() * OUTPUT_COLOR;
+                colors_enabled() * OUTPUT_COLOR;
 }
 
 static int list_sessions(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *id, *user, *seat, *object;
         sd_bus *bus = userdata;
         unsigned k = 0;
@@ -139,8 +137,8 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
 }
 
 static int list_users(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *user, *object;
         sd_bus *bus = userdata;
         unsigned k = 0;
@@ -186,8 +184,8 @@ static int list_users(int argc, char *argv[], void *userdata) {
 }
 
 static int list_seats(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *seat, *object;
         sd_bus *bus = userdata;
         unsigned k = 0;
@@ -232,8 +230,8 @@ static int list_seats(int argc, char *argv[], void *userdata) {
 }
 
 static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *cgroup;
         int r;
@@ -784,8 +782,8 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
 }
 
 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -873,8 +871,8 @@ static int show_session(int argc, char *argv[], void *userdata) {
         }
 
         for (i = 1; i < argc; i++) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
                 const char *path = NULL;
 
                 r = sd_bus_call_method(
@@ -928,8 +926,8 @@ static int show_user(int argc, char *argv[], void *userdata) {
         }
 
         for (i = 1; i < argc; i++) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
                 const char *path = NULL;
                 uid_t uid;
 
@@ -988,8 +986,8 @@ static int show_seat(int argc, char *argv[], void *userdata) {
         }
 
         for (i = 1; i < argc; i++) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
                 const char *path = NULL;
 
                 r = sd_bus_call_method(
@@ -1022,7 +1020,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
 }
 
 static int activate(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         char *short_argv[3];
         int r, i;
@@ -1068,7 +1066,7 @@ static int activate(int argc, char *argv[], void *userdata) {
 }
 
 static int kill_session(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1100,7 +1098,7 @@ static int kill_session(int argc, char *argv[], void *userdata) {
 }
 
 static int enable_linger(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         char* short_argv[3];
         bool b;
@@ -1150,7 +1148,7 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
 }
 
 static int terminate_user(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1184,7 +1182,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) {
 }
 
 static int kill_user(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1221,7 +1219,7 @@ static int kill_user(int argc, char *argv[], void *userdata) {
 }
 
 static int attach(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1251,7 +1249,7 @@ static int attach(int argc, char *argv[], void *userdata) {
 }
 
 static int flush_devices(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r;
 
@@ -1275,7 +1273,7 @@ static int flush_devices(int argc, char *argv[], void *userdata) {
 }
 
 static int lock_sessions(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r;
 
@@ -1299,7 +1297,7 @@ static int lock_sessions(int argc, char *argv[], void *userdata) {
 }
 
 static int terminate_seat(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1534,7 +1532,7 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
index d0dd569a03cf96490a8639f968b983d2cb923f65..0cef88a82de98501aff137592a9690c3b0d0f6ce 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 93e9ed02eb6db461c5168059bbe3af6eab39482c..1286c6a3cd7b84990cf46ab045a2e058548b8c21 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 #include "libudev.h"
 
index 185108f8f1d34972cf3d6da0f5cf87f96d3e2b64..9a8089f97c43ce567b86db812fa21c2d72bfde2f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -61,7 +59,7 @@ int manager_handle_action(
                 [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
         };
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         InhibitWhat inhibit_operation;
         Inhibitor *offending = NULL;
         bool supported;
index e9b424b5f64b949bb93bea032af863b8c76e02c7..fb40ae48d2cf660a35b103fb1ba7ada15160efa7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -35,8 +33,8 @@ typedef enum HandleAction {
         _HANDLE_ACTION_INVALID = -1
 } HandleAction;
 
-#include "logind.h"
 #include "logind-inhibit.h"
+#include "logind.h"
 
 int manager_handle_action(
                 Manager *m,
index b08b69dbfc39c0350b4db9e3a94eb0c05ed18ded..baa6b7113c1038ff4f706589273ad3d421f29d10 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 80d93c7e6bdf691d4ffafbe803524ee7cd9d6479..f30cba29594d712e59de1c5ba1d70b2a743d73b4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 36cdbbe0f9296b89f40720b4c64c3a83f4fd44f8..8bdb3a9a38322f3aa33a5db87126a79478d45b12 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -139,7 +137,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
         errno = 0;
         p = getpwuid(uid);
         if (!p)
-                return errno ? -errno : -ENOENT;
+                return errno > 0 ? -errno : -ENOENT;
 
         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
 }
@@ -404,7 +402,7 @@ static int vt_is_busy(unsigned int vtnr) {
 }
 
 int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
         int r;
 
index e507a19aef66fd0faf1f08c24cdc9754aa63a6d0..1d3133ee252338ca913ec711f1c04e9e87061b08 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -53,7 +51,7 @@
 #include "utmp-wtmp.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         Session *session;
         int r;
 
@@ -88,7 +86,7 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid,
         assert(ret);
 
         if (uid == UID_INVALID) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 /* Note that we get the owner UID of the session, not the actual client UID here! */
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
@@ -124,7 +122,6 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char
                         return r;
 
                 seat = session->seat;
-
                 if (!seat)
                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
         } else {
@@ -419,7 +416,7 @@ static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error
 }
 
 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Session *session;
         Iterator i;
@@ -461,7 +458,7 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_
 }
 
 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         User *user;
         Iterator i;
@@ -501,7 +498,7 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err
 }
 
 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Seat *seat;
         Iterator i;
@@ -538,7 +535,7 @@ static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_err
 }
 
 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Inhibitor *inhibitor;
         Iterator i;
@@ -696,7 +693,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
         }
 
         if (leader == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -1094,7 +1091,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
                 return r;
 
         if (uid == UID_INVALID) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 /* Note that we get the owner UID of the session, not the actual client UID here! */
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
@@ -1111,7 +1108,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
         errno = 0;
         pw = getpwuid(uid);
         if (!pw)
-                return errno ? -errno : -ENOENT;
+                return errno > 0 ? -errno : -ENOENT;
 
         r = bus_verify_polkit_async(
                         message,
@@ -1229,7 +1226,6 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
                 return -ENOMEM;
 
         mkdir_p_label("/etc/udev/rules.d", 0755);
-        mac_selinux_init("/etc");
         r = write_string_file_atomic_label(file, rule);
         if (r < 0)
                 return r;
@@ -1465,7 +1461,7 @@ static int execute_shutdown_or_sleep(
                 const char *unit_name,
                 sd_bus_error *error) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         char *c = NULL;
         const char *p;
         int r;
@@ -1515,7 +1511,7 @@ static int execute_shutdown_or_sleep(
 
 int manager_dispatch_delayed(Manager *manager, bool timeout) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         Inhibitor *offending = NULL;
         int r;
 
@@ -1668,7 +1664,7 @@ static int verify_shutdown_creds(
                 const char *action_ignore_inhibit,
                 sd_bus_error *error) {
 
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         bool multiple_sessions, blocked;
         uid_t uid;
         int r;
@@ -1820,7 +1816,7 @@ static int nologin_timeout_handler(
 
         log_info("Creating /run/nologin, blocking further logins...");
 
-        r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+        r = write_string_file_atomic_label("/run/nologin", "System is going down.");
         if (r < 0)
                 log_error_errno(r, "Failed to create /run/nologin: %m");
         else
@@ -1889,7 +1885,7 @@ static int manager_scheduled_shutdown_handler(
                         uint64_t usec,
                         void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         Manager *m = userdata;
         const char *target;
         int r;
@@ -1915,7 +1911,7 @@ static int manager_scheduled_shutdown_handler(
 
 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         const char *action_multiple_sessions = NULL;
         const char *action_ignore_inhibit = NULL;
         const char *action = NULL;
@@ -1944,9 +1940,9 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
         } else if (streq(type, "poweroff")) {
-                action = "org.freedesktop.login1.poweroff";
-                action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
-                action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
+                action = "org.freedesktop.login1.power-off";
+                action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
+                action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
         } else
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
 
@@ -1995,7 +1991,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
 
         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
         if (r >= 0) {
-                const char *tty;
+                const char *tty = NULL;
 
                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
                 (void) sd_bus_creds_get_tty(creds, &tty);
@@ -2032,7 +2028,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
         reset_scheduled_shutdown(m);
 
         if (cancelled) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 const char *tty = NULL;
                 uid_t uid = 0;
                 int r;
@@ -2088,7 +2084,7 @@ static int method_can_shutdown_or_sleep(
                 const char *sleep_verb,
                 sd_bus_error *error) {
 
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         bool multiple_sessions, challenge, blocked;
         const char *result = NULL;
         uid_t uid;
@@ -2374,7 +2370,7 @@ static int method_set_wall_message(
 }
 
 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         const char *who, *why, *what, *mode;
         _cleanup_free_ char *id = NULL;
         _cleanup_close_ int fifo_fd = -1;
@@ -2581,7 +2577,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result)
         if (streq(result, "done"))
                 r = session_send_create_reply(s, NULL);
         else {
-                _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
 
                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
                 r = session_send_create_reply(s, &e);
@@ -2752,6 +2748,23 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
                         l);
 }
 
+static int strdup_job(sd_bus_message *reply, char **job) {
+        const char *j;
+        char *copy;
+        int r;
+
+        r = sd_bus_message_read(reply, "o", &j);
+        if (r < 0)
+                return r;
+
+        copy = strdup(j);
+        if (!copy)
+                return -ENOMEM;
+
+        *job = copy;
+        return 1;
+}
+
 int manager_start_slice(
                 Manager *manager,
                 const char *slice,
@@ -2762,11 +2775,12 @@ int manager_start_slice(
                 sd_bus_error *error,
                 char **job) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         int r;
 
         assert(manager);
         assert(slice);
+        assert(job);
 
         r = sd_bus_message_new_method_call(
                         manager->bus,
@@ -2820,22 +2834,7 @@ int manager_start_slice(
         if (r < 0)
                 return r;
 
-        if (job) {
-                const char *j;
-                char *copy;
-
-                r = sd_bus_message_read(reply, "o", &j);
-                if (r < 0)
-                        return r;
-
-                copy = strdup(j);
-                if (!copy)
-                        return -ENOMEM;
-
-                *job = copy;
-        }
-
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_start_scope(
@@ -2850,12 +2849,13 @@ int manager_start_scope(
                 sd_bus_error *error,
                 char **job) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         int r;
 
         assert(manager);
         assert(scope);
         assert(pid > 1);
+        assert(job);
 
         r = sd_bus_message_new_method_call(
                         manager->bus,
@@ -2930,30 +2930,16 @@ int manager_start_scope(
         if (r < 0)
                 return r;
 
-        if (job) {
-                const char *j;
-                char *copy;
-
-                r = sd_bus_message_read(reply, "o", &j);
-                if (r < 0)
-                        return r;
-
-                copy = strdup(j);
-                if (!copy)
-                        return -ENOMEM;
-
-                *job = copy;
-        }
-
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
         assert(unit);
+        assert(job);
 
         r = sd_bus_call_method(
                         manager->bus,
@@ -2967,30 +2953,16 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error,
         if (r < 0)
                 return r;
 
-        if (job) {
-                const char *j;
-                char *copy;
-
-                r = sd_bus_message_read(reply, "o", &j);
-                if (r < 0)
-                        return r;
-
-                copy = strdup(j);
-                if (!copy)
-                        return -ENOMEM;
-
-                *job = copy;
-        }
-
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
         assert(unit);
+        assert(job);
 
         r = sd_bus_call_method(
                         manager->bus,
@@ -3005,9 +2977,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
 
-                        if (job)
-                                *job = NULL;
-
+                        *job = NULL;
                         sd_bus_error_free(error);
                         return 0;
                 }
@@ -3015,22 +2985,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
                 return r;
         }
 
-        if (job) {
-                const char *j;
-                char *copy;
-
-                r = sd_bus_message_read(reply, "o", &j);
-                if (r < 0)
-                        return r;
-
-                copy = strdup(j);
-                if (!copy)
-                        return -ENOMEM;
-
-                *job = copy;
-        }
-
-        return 1;
+        return strdup_job(reply, job);
 }
 
 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
@@ -3083,8 +3038,8 @@ int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo
 }
 
 int manager_unit_is_active(Manager *manager, const char *unit) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *state;
         int r;
@@ -3129,8 +3084,8 @@ int manager_unit_is_active(Manager *manager, const char *unit) {
 }
 
 int manager_job_is_active(Manager *manager, const char *path) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
index ffb9162e56c435f7a7add489d410b9e96c94a555..eb5edd1cd5e11d2ce8ef2731668a1e65701497ad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6b2728586cf4d48d9cedf9d096cc581b0976d9a3..927068e00abe9edd81b157f2f63a64996a57bea1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 33fbdde557c92ae5d4f6a10b0eae0846c7454c3b..a0e3ba2b7cd20e3df8547ae3d11381244335377f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1b77fc1e9ef9f8d02756d43643199ba8c240b1be..70de199c602a7495205f3d69eed61e56b2154a83 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 43b578f364d447b11ecf0a445fa9ac3bb7091e12..3cee10d009a155c6a8d5f161dc8d2035a82dc01b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -334,7 +332,7 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/seat/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 Session *session;
                 const char *name;
@@ -416,7 +414,7 @@ int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
 
         message = sd_bus_get_current_message(bus);
         if (message) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 const char *name;
                 Session *session;
 
index 1f4936cebe4f8a77bf11aa53c4c41e83e5905338..b5192320e4827373794806c87b1f1e99e48559a3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -34,6 +32,7 @@
 #include "logind-seat.h"
 #include "mkdir.h"
 #include "parse-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
 #include "util.h"
@@ -181,7 +180,7 @@ static int vt_allocate(unsigned int vtnr) {
 
         assert(vtnr >= 1);
 
-        snprintf(p, sizeof(p), "/dev/tty%u", vtnr);
+        xsprintf(p, "/dev/tty%u", vtnr);
         fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 return -errno;
index 248dbeb9d7d94957b4e32907bf8a13ded68d71cc..9a4fbc5bc540e98f68e700bcff38143fcc26f014 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7810199a542e566b12dcd63339953e1ea23c1019..ff9170683bafd49b3dbbe0a49e3c15ebfe32e778 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -252,7 +250,7 @@ int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_erro
 }
 
 static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         Session *s = userdata;
         uid_t uid;
         int r, b;
@@ -327,7 +325,7 @@ int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
 }
 
 static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         Session *s = userdata;
         int r, force;
         uid_t uid;
@@ -521,7 +519,7 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/session/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 const char *name;
 
@@ -598,7 +596,7 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
 
         message = sd_bus_get_current_message(bus);
         if (message) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 const char *name;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
@@ -692,7 +690,7 @@ int session_send_lock_all(Manager *m, bool lock) {
 }
 
 int session_send_create_reply(Session *s, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
         _cleanup_close_ int fifo_fd = -1;
         _cleanup_free_ char *p = NULL;
 
index 9bf3ca0995530eca91c25aedcf911416f31fe8a1..4055a23277391abaee3588fae11b08aa91b5ec42 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -42,7 +40,7 @@ enum SessionDeviceNotifications {
 };
 
 static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *path = NULL;
         const char *t = NULL;
         uint32_t major, minor;
index 1c9f998371589ad0f53d7a187a67c00861d73f82..7c8503583fe19660ff70476b2f23f23dcf101a4f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9f03a7b31e348c33d935b1caff5046a0eee1efee..417b7f5d98a2e977a4dbd2e715e285e697fb27e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -514,7 +512,7 @@ static int session_start_scope(Session *s) {
         assert(s->user);
 
         if (!s->scope) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 char *scope, *job = NULL;
                 const char *description;
 
@@ -611,7 +609,7 @@ int session_start(Session *s) {
 }
 
 static int session_stop_scope(Session *s, bool force) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job = NULL;
         int r;
 
index d054c33ceca6b5a671b4352943914d99056ca04a..e24b80847489a9b7a8ccb34d9b3deb36631a1059 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,8 +23,8 @@ typedef struct Session Session;
 typedef enum KillWho KillWho;
 
 #include "list.h"
-#include "logind-user.h"
 #include "login-util.h"
+#include "logind-user.h"
 
 typedef enum SessionState {
         SESSION_OPENING,  /* Session scope is being created */
index df901f6558101111fb8ed65c02cee4242160f5a1..fd98c7becafb800daeb3f7ada0f8d8e06484a8ea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -271,7 +269,7 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/user/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
 
                 message = sd_bus_get_current_message(bus);
@@ -340,7 +338,7 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
 
         message = sd_bus_get_current_message(bus);
         if (message) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 uid_t uid;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
index 778f19b50dc1edfd87423f44a754b7b5fbd807c5..6b9c69cc45d356fff928546c62abc5450ac69aee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -393,7 +391,7 @@ fail:
 }
 
 static int user_start_slice(User *u) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *description;
         char *job;
         int r;
@@ -412,19 +410,18 @@ static int user_start_slice(User *u) {
                         u->manager->user_tasks_max,
                         &error,
                         &job);
-        if (r < 0) {
-                /* we don't fail due to this, let's try to continue */
-                if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
-                        log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", u->slice, bus_error_message(&error, r), error.name);
-        } else {
+        if (r >= 0)
                 u->slice_job = job;
-        }
+        else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
+                /* we don't fail due to this, let's try to continue */
+                log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)",
+                                u->slice, bus_error_message(&error, r), error.name);
 
         return 0;
 }
 
 static int user_start_service(User *u) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job;
         int r;
 
@@ -509,7 +506,7 @@ int user_start(User *u) {
 }
 
 static int user_stop_slice(User *u) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job;
         int r;
 
@@ -528,7 +525,7 @@ static int user_stop_slice(User *u) {
 }
 
 static int user_stop_service(User *u) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job;
         int r;
 
@@ -868,7 +865,7 @@ int config_parse_tmpfs_size(
 
                 errno = 0;
                 ul = strtoul(rvalue, &f, 10);
-                if (errno != 0 || f != e) {
+                if (errno > 0 || f != e) {
                         log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
                         return 0;
                 }
index de99cf47b4538908fd26c7f2fefbc747208619e8..4f0966dc7716783751f114c53279837bd62dea7a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 3bd61a81fd5379a24c06565589f2118bac3316fb..11a91c3947c667c177852bdf02f4bda53d6782eb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7b41174c64b2f84b723bfae6312b4f3a4314028c..933602eb087154415a31bc4e7076259fbd2fcb13 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -36,6 +34,7 @@
 #include "fd-util.h"
 #include "formats-util.h"
 #include "logind.h"
+#include "selinux-util.h"
 #include "signal-util.h"
 #include "strv.h"
 #include "udev-util.h"
@@ -70,7 +69,7 @@ static Manager *manager_new(void) {
         m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
 
         m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
-        m->user_tasks_max = UINT64_C(4096);
+        m->user_tasks_max = UINT64_C(12288);
 
         m->devices = hashmap_new(&string_hash_ops);
         m->seats = hashmap_new(&string_hash_ops);
@@ -579,7 +578,7 @@ static int manager_reserve_vt(Manager *m) {
 }
 
 static int manager_connect_bus(Manager *m) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(m);
@@ -1127,6 +1126,12 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        r = mac_selinux_init("/run");
+        if (r < 0) {
+                log_error_errno(r, "Could not initialize labelling: %m");
+                goto finish;
+        }
+
         /* Always create the directories people can create inotify
          * watches in. Note that some applications might check for the
          * existence of /run/systemd/seats/ to determine whether
index 81f6695434ad14540aa6c72840c9c49827e5a2c7..6095e482ace398488947deef2295ae518813b2f0 100644 (file)
@@ -32,4 +32,4 @@
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
 #RemoveIPC=yes
-#UserTasksMax=4096
+#UserTasksMax=12288
index f34544e64ceacea9dcea687521e92225733881c6..6748af3c07eecbe6d1cba038b75e046c51925bd4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index ed4f7c726f3c056e2cc6cac4999906b8c770eb03..40e246bb06cd6d07f23ece54816931df0f870e94 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -220,8 +218,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 int flags,
                 int argc, const char **argv) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char
                 *username, *id, *object_path, *runtime_path,
                 *service = NULL,
@@ -230,7 +228,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 *seat = NULL,
                 *type = NULL, *class = NULL,
                 *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int session_fd = -1, existing, r;
         bool debug = false, remote;
         struct passwd *pw;
@@ -509,8 +507,8 @@ _public_ PAM_EXTERN int pam_sm_close_session(
                 int flags,
                 int argc, const char **argv) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const void *existing = NULL;
         const char *id;
         int r;
index e9ca4bb03d0d15cdb0c02a14eeeffedd6d1087af..bd603e297d29c147250f0f271c0f1be69e645325 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 9ffd129c483b0d6d408cdd3d2699e4bb3fa3a178..3e94bc3ed55a78a0245a925b7e381f3f99671117 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d0727ff7c7e760b98eb381b947f30989c203f34f..a3cf9d293b4d5c1b39040d5f50a7da6e66a1b6a6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -29,8 +27,8 @@
 #include "util.h"
 
 static int inhibit(sd_bus *bus, const char *what) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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 *who = "Test Tool", *reason = "Just because!", *mode = "block";
         int fd;
         int r;
@@ -53,8 +51,8 @@ static int inhibit(sd_bus *bus, const char *what) {
 }
 
 static void print_inhibitors(sd_bus *bus) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _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 *what, *who, *why, *mode;
         uint32_t uid, pid;
         unsigned n = 0;
@@ -85,7 +83,7 @@ static void print_inhibitors(sd_bus *bus) {
 }
 
 int main(int argc, char*argv[]) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         int fd1, fd2;
         int r;
 
index ac327f71fb2b0992b3cc78ffd29cce3029c5dbd1..3d233f017c09b4fce9d13ed9e542217c5ba862b5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d805bcfdca7d837d9515d5b400400377da5f4be6..1d55fa04af5687038592eb63d14f354c37e3b814 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -112,7 +110,7 @@ int main(int argc, char *argv[]) {
         if (arg_commit)
                 r = machine_id_commit(arg_root);
         else
-                r = machine_id_setup(arg_root);
+                r = machine_id_setup(arg_root, SD_ID128_NULL);
 
 finish:
         free(arg_root);
index 4ec1766033906ba4b6be102ad1bd5cdc7c5ac88c..73f5112c4da9080c732131509eaf2b7f9e91bdde 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,6 +21,7 @@
 #include "bus-label.h"
 #include "bus-util.h"
 #include "image-dbus.h"
+#include "io-util.h"
 #include "machine-image.h"
 #include "strv.h"
 #include "user-util.h"
@@ -195,6 +194,8 @@ int bus_image_method_set_limit(
         r = sd_bus_message_read(message, "t", &limit);
         if (r < 0)
                 return r;
+        if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_verify_polkit_async(
                         message,
index d56d905c8e3095c1b084551e194c6db8d1231549..b62da996c68e183f08cf28385112238e587f4f38 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 452130a29cf362015874d241ccbf4d7ee81d02cf..71f20b3f07c8ca197e6b10ff928c0057abf2ce88 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -192,7 +190,7 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
 }
 
 int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Machine *m = userdata;
         int r;
 
@@ -375,7 +373,7 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
 }
 
 int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **l = NULL;
         Machine *m = userdata;
         char **k, **v;
@@ -481,7 +479,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
 }
 
 int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *pty_name = NULL;
         _cleanup_close_ int master = -1;
         Machine *m = userdata;
@@ -536,7 +534,7 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
                 break;
 
         case MACHINE_CONTAINER: {
-                _cleanup_bus_unref_ sd_bus *bus = NULL;
+                _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
                 char *address;
 
                 r = sd_bus_new(&bus);
@@ -570,9 +568,9 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
 }
 
 int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *pty_name = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
         _cleanup_close_ int master = -1;
         sd_bus *container_bus = NULL;
         Machine *m = userdata;
@@ -639,9 +637,9 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
 }
 
 int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *tm = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *tm = NULL;
         _cleanup_free_ char *pty_name = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
         sd_bus *container_bus = NULL;
         _cleanup_close_ int master = -1, slave = -1;
         _cleanup_strv_free_ char **env = NULL, **args = NULL;
@@ -922,7 +920,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
 
            First, we start by creating a private playground in /tmp,
            that we can mount MS_SLAVE. (Which is necessary, since
-           MS_MOUNT cannot be applied to mounts with MS_SHARED parent
+           MS_MOVE cannot be applied to mounts with MS_SHARED parent
            mounts.) */
 
         if (!mkdtemp(mount_slave))
@@ -1086,7 +1084,7 @@ finish:
 }
 
 static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         MachineOperation *o = userdata;
         int r;
 
@@ -1312,7 +1310,7 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo
         assert(m);
 
         if (streq(path, "/org/freedesktop/machine1/machine/self")) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -1411,7 +1409,7 @@ int machine_send_signal(Machine *m, bool new_machine) {
 }
 
 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
         _cleanup_free_ char *p = NULL;
 
         assert(m);
index 194e680e05b67c970510268ff96a544db8b3448a..3a8162b1712d53b647819947ab9538efb0a47323 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 6b1fae27698352db4c0bdca77fbb5ece3fcfdb9a..406d5a4b854dc6273b8904db16fb5d4b3298e45c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -432,7 +430,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
 }
 
 static int machine_stop_scope(Machine *m) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job = NULL;
         int r;
 
index ad7f2a162f594e258152afd5cc992b8eca270bcd..1d8cc5911a707da20f3ee2ab02c8ac7effdcae0d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7e17c7a41c15a7d6fcb6373486784d7e91e4376a..48531393211d03ff46fa2ed2cfb2c6016e02fba8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,7 +38,6 @@
 #include "cgroup-util.h"
 #include "copy.h"
 #include "env-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "hostname-util.h"
 #include "import-util.h"
@@ -79,7 +76,6 @@ static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 static bool arg_force = false;
 static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static const char* arg_dkr_index_url = NULL;
 static const char* arg_format = NULL;
 static const char *arg_uid = NULL;
 static char **arg_setenv = NULL;
@@ -110,7 +106,7 @@ static OutputFlags get_output_flags(void) {
                 arg_all * OUTPUT_SHOW_ALL |
                 arg_full * OUTPUT_FULL_WIDTH |
                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
-                on_tty() * OUTPUT_COLOR |
+                colors_enabled() * OUTPUT_COLOR |
                 !arg_quiet * OUTPUT_WARN_CUTOFF;
 }
 
@@ -129,8 +125,8 @@ static int compare_machine_info(const void *a, const void *b) {
 static int list_machines(int argc, char *argv[], void *userdata) {
 
         size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ MachineInfo *machines = NULL;
         const char *name, *class, *service, *object;
         size_t n_machines = 0, n_allocated = 0, j;
@@ -230,9 +226,9 @@ static int compare_image_info(const void *a, const void *b) {
 
 static int list_images(int argc, char *argv[], void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ ImageInfo *images = NULL;
         size_t n_images = 0, n_allocated = 0, j;
         const char *name, *type, *object;
@@ -344,8 +340,8 @@ static int list_images(int argc, char *argv[], void *userdata) {
 }
 
 static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL;
         const char *cgroup;
         int r;
@@ -393,7 +389,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
 }
 
 static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(bus);
@@ -454,7 +450,7 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p
 }
 
 static int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *k, *v, *pretty = NULL;
         int r;
 
@@ -701,8 +697,8 @@ static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line
 
 static int show_machine(int argc, char *argv[], void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         bool properties, new_line = false;
         sd_bus *bus = userdata;
         int r = 0, i;
@@ -950,8 +946,8 @@ static int show_image_properties(sd_bus *bus, const char *path, bool *new_line)
 
 static int show_image(int argc, char *argv[], void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         bool properties, new_line = false;
         sd_bus *bus = userdata;
         int r = 0, i;
@@ -1006,7 +1002,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
 }
 
 static int kill_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1051,7 +1047,7 @@ static int poweroff_machine(int argc, char *argv[], void *userdata) {
 }
 
 static int terminate_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1079,7 +1075,7 @@ static int terminate_machine(int argc, char *argv[], void *userdata) {
 }
 
 static int copy_files(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *abs_host_path = NULL;
         char *dest, *host_path, *container_path;
         sd_bus *bus = userdata;
@@ -1122,7 +1118,7 @@ static int copy_files(int argc, char *argv[], void *userdata) {
 }
 
 static int bind_mount(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r;
 
@@ -1226,11 +1222,11 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
 }
 
 static int login_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
-        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         int master = -1, r;
         sd_bus *bus = userdata;
         const char *pty, *match, *machine;
@@ -1293,11 +1289,11 @@ static int login_machine(int argc, char *argv[], void *userdata) {
 }
 
 static int shell_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
-        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
-        _cleanup_event_unref_ sd_event *event = NULL;
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         int master = -1, r;
         sd_bus *bus = userdata;
         const char *pty, *match, *machine, *path, *uid = NULL;
@@ -1397,7 +1393,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
 }
 
 static int remove_image(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -1425,7 +1421,7 @@ static int remove_image(int argc, char *argv[], void *userdata) {
 }
 
 static int rename_image(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r;
 
@@ -1449,7 +1445,7 @@ static int rename_image(int argc, char *argv[], void *userdata) {
 }
 
 static int clone_image(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r;
 
@@ -1473,7 +1469,7 @@ static int clone_image(int argc, char *argv[], void *userdata) {
 }
 
 static int read_only_image(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int b = true, r;
 
@@ -1528,7 +1524,7 @@ static int make_service_name(const char *name, char **ret) {
 }
 
 static int start_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         sd_bus *bus = userdata;
         int r, i;
@@ -1542,7 +1538,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
                 return log_oom();
 
         for (i = 1; i < argc; i++) {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 _cleanup_free_ char *unit = NULL;
                 const char *object;
 
@@ -1573,7 +1569,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
                         return log_oom();
         }
 
-        r = bus_wait_for_jobs(w, arg_quiet);
+        r = bus_wait_for_jobs(w, arg_quiet, NULL);
         if (r < 0)
                 return r;
 
@@ -1581,8 +1577,8 @@ static int start_machine(int argc, char *argv[], void *userdata) {
 }
 
 static int enable_machine(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int carries_install_info = 0;
         const char *method = NULL;
         sd_bus *bus = userdata;
@@ -1721,10 +1717,10 @@ static int transfer_signal_handler(sd_event_source *s, const struct signalfd_sig
 }
 
 static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
-        _cleanup_bus_slot_unref_ sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_event_unref_ sd_event* event = NULL;
+        _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_event_unrefp) sd_event* event = NULL;
         const char *path = NULL;
         uint32_t id;
         int r;
@@ -1791,7 +1787,7 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int import_tar(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *ll = NULL;
         _cleanup_close_ int fd = -1;
         const char *local = NULL, *path = NULL;
@@ -1858,7 +1854,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
 }
 
 static int import_raw(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *ll = NULL;
         _cleanup_close_ int fd = -1;
         const char *local = NULL, *path = NULL;
@@ -1940,7 +1936,7 @@ static void determine_compression_from_filename(const char *p) {
 }
 
 static int export_tar(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_close_ int fd = -1;
         const char *local = NULL, *path = NULL;
         sd_bus *bus = userdata;
@@ -1990,7 +1986,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
 }
 
 static int export_raw(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_close_ int fd = -1;
         const char *local = NULL, *path = NULL;
         sd_bus *bus = userdata;
@@ -2040,7 +2036,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
 }
 
 static int pull_tar(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *l = NULL, *ll = NULL;
         const char *local, *remote;
         sd_bus *bus = userdata;
@@ -2104,7 +2100,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
 }
 
 static int pull_raw(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *l = NULL, *ll = NULL;
         const char *local, *remote;
         sd_bus *bus = userdata;
@@ -2167,78 +2163,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
         return transfer_image_common(bus, m);
 }
 
-static int pull_dkr(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        const char *local, *remote, *tag;
-        sd_bus *bus = userdata;
-        int r;
-
-        if (arg_verify != IMPORT_VERIFY_NO) {
-                log_error("Imports from DKR do not support image verification, please pass --verify=no.");
-                return -EINVAL;
-        }
-
-        remote = argv[1];
-        tag = strchr(remote, ':');
-        if (tag) {
-                remote = strndupa(remote, tag - remote);
-                tag++;
-        }
-
-        if (!dkr_name_is_valid(remote)) {
-                log_error("DKR name '%s' is invalid.", remote);
-                return -EINVAL;
-        }
-        if (tag && !dkr_tag_is_valid(tag)) {
-                log_error("DKR tag '%s' is invalid.", remote);
-                return -EINVAL;
-        }
-
-        if (argc >= 3)
-                local = argv[2];
-        else {
-                local = strchr(remote, '/');
-                if (local)
-                        local++;
-                else
-                        local = remote;
-        }
-
-        if (isempty(local) || streq(local, "-"))
-                local = NULL;
-
-        if (local) {
-                if (!machine_name_is_valid(local)) {
-                        log_error("Local name %s is not a suitable machine name.", local);
-                        return -EINVAL;
-                }
-        }
-
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &m,
-                        "org.freedesktop.import1",
-                        "/org/freedesktop/import1",
-                        "org.freedesktop.import1.Manager",
-                        "PullDkr");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append(
-                        m,
-                        "sssssb",
-                        arg_dkr_index_url,
-                        remote,
-                        tag,
-                        local,
-                        import_verify_to_string(arg_verify),
-                        arg_force);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        return transfer_image_common(bus, m);
-}
-
 typedef struct TransferInfo {
         uint32_t id;
         const char *type;
@@ -2255,8 +2179,8 @@ static int compare_transfer_info(const void *a, const void *b) {
 
 static int list_transfers(int argc, char *argv[], void *userdata) {
         size_t max_type = strlen("TYPE"), max_local = strlen("LOCAL"), max_remote = strlen("REMOTE");
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ TransferInfo *transfers = NULL;
         size_t n_transfers = 0, n_allocated = 0, j;
         const char *type, *remote, *local, *object;
@@ -2346,7 +2270,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
 }
 
 static int cancel_transfer(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         int r, i;
 
@@ -2380,7 +2304,7 @@ static int cancel_transfer(int argc, char *argv[], void *userdata) {
 }
 
 static int set_limit(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus = userdata;
         uint64_t limit;
         int r;
@@ -2453,9 +2377,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "                              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"
-               "      --dkr-index-url=URL     Specify the index URL to use for DKR image\n"
-               "                              downloads\n\n"
+               "      --force                 Download image even if already exists\n\n"
                "Machine Commands:\n"
                "  list                        List running VMs and containers\n"
                "  status NAME...              Show VM/container details\n"
@@ -2487,7 +2409,6 @@ static int help(int argc, char *argv[], void *userdata) {
                "Image Transfer Commands:\n"
                "  pull-tar URL [NAME]         Download a TAR container image\n"
                "  pull-raw URL [NAME]         Download a RAW container or VM image\n"
-               "  pull-dkr REMOTE [NAME]      Download a DKR container image\n"
                "  import-tar FILE [NAME]      Import a local TAR container image\n"
                "  import-raw FILE [NAME]      Import a local RAW container or VM image\n"
                "  export-tar NAME [FILE]      Export a TAR container image locally\n"
@@ -2511,7 +2432,6 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_ASK_PASSWORD,
                 ARG_VERIFY,
                 ARG_FORCE,
-                ARG_DKR_INDEX_URL,
                 ARG_FORMAT,
                 ARG_UID,
                 ARG_SETENV,
@@ -2537,7 +2457,6 @@ static int parse_argv(int argc, char *argv[]) {
                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
                 { "verify",          required_argument, NULL, ARG_VERIFY          },
                 { "force",           no_argument,       NULL, ARG_FORCE           },
-                { "dkr-index-url",   required_argument, NULL, ARG_DKR_INDEX_URL   },
                 { "format",          required_argument, NULL, ARG_FORMAT          },
                 { "uid",             required_argument, NULL, ARG_UID             },
                 { "setenv",          required_argument, NULL, ARG_SETENV          },
@@ -2651,15 +2570,6 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_force = true;
                         break;
 
-                case ARG_DKR_INDEX_URL:
-                        if (!http_url_is_valid(optarg)) {
-                                log_error("Index URL is invalid: %s", optarg);
-                                return -EINVAL;
-                        }
-
-                        arg_dkr_index_url = optarg;
-                        break;
-
                 case ARG_FORMAT:
                         if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
                                 log_error("Unknown format: %s", optarg);
@@ -2726,7 +2636,6 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
                 { "export-raw",      2,        3,        0,            export_raw        },
                 { "pull-tar",        2,        3,        0,            pull_tar          },
                 { "pull-raw",        2,        3,        0,            pull_raw          },
-                { "pull-dkr",        2,        3,        0,            pull_dkr          },
                 { "list-transfers",  VERB_ANY, 1,        0,            list_transfers    },
                 { "cancel-transfer", 2,        VERB_ANY, 0,            cancel_transfer   },
                 { "set-limit",       2,        3,        0,            set_limit         },
@@ -2737,7 +2646,7 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
 }
 
 int main(int argc, char*argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
index 961767c4a958188a4e1c836db7762eb744baf3e1..b9330993304b78ec012740ddda3c73c9b241ddff 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -34,6 +32,7 @@
 #include "formats-util.h"
 #include "hostname-util.h"
 #include "image-dbus.h"
+#include "io-util.h"
 #include "machine-dbus.h"
 #include "machine-image.h"
 #include "machine-pool.h"
@@ -203,7 +202,7 @@ static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd
                 return -EINVAL;
 
         if (pid == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -228,7 +227,7 @@ static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd
 }
 
 static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Machine *machine;
         Iterator i;
@@ -333,7 +332,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
 
         if (leader == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -554,7 +553,7 @@ static int method_get_machine_os_release(sd_bus_message *message, void *userdata
 }
 
 static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
         Manager *m = userdata;
         Image *image;
@@ -813,6 +812,8 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
         r = sd_bus_message_read(message, "t", &limit);
         if (r < 0)
                 return r;
+        if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_verify_polkit_async(
                         message,
@@ -833,11 +834,14 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
         if (r < 0)
                 return r;
 
-        r = btrfs_resize_loopback("/var/lib/machines", limit, false);
-        if (r == -ENOTTY)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
-        if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
-                return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
+        /* Resize the backing loopback device, if there is one, except if we asked to drop any limit */
+        if (limit != (uint64_t) -1) {
+                r = btrfs_resize_loopback("/var/lib/machines", limit, false);
+                if (r == -ENOTTY)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
+                if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
+                        return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
+        }
 
         (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit);
 
@@ -910,7 +914,7 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
                 if (k < 0 && feof(f))
                         break;
                 if (k != 3) {
-                        if (ferror(f) && errno != 0)
+                        if (ferror(f) && errno > 0)
                                 return -errno;
 
                         return -EIO;
@@ -968,7 +972,7 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
                         if (k < 0 && feof(f))
                                 break;
                         if (k != 3) {
-                                if (ferror(f) && errno != 0)
+                                if (ferror(f) && errno > 0)
                                         return -errno;
 
                                 return -EIO;
@@ -1028,7 +1032,7 @@ static int method_map_from_machine_group(sd_bus_message *message, void *groupdat
                 if (k < 0 && feof(f))
                         break;
                 if (k != 3) {
-                        if (ferror(f) && errno != 0)
+                        if (ferror(f) && errno > 0)
                                 return -errno;
 
                         return -EIO;
@@ -1086,7 +1090,7 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
                         if (k < 0 && feof(f))
                                 break;
                         if (k != 3) {
-                                if (ferror(f) && errno != 0)
+                                if (ferror(f) && errno > 0)
                                         return -errno;
 
                                 return -EIO;
@@ -1176,7 +1180,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
                         if (streq(result, "done"))
                                 machine_send_create_reply(machine, NULL);
                         else {
-                                _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+                                _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
 
                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
 
@@ -1280,7 +1284,7 @@ int manager_start_scope(
                 sd_bus_error *error,
                 char **job) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         int r;
 
         assert(manager);
@@ -1325,6 +1329,10 @@ int manager_start_scope(
         if (r < 0)
                 return r;
 
+        r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", UINT64_C(16384));
+        if (r < 0)
+                return bus_log_create_error(r);
+
         if (more_properties) {
                 r = sd_bus_message_copy(m, more_properties, true);
                 if (r < 0)
@@ -1362,7 +1370,7 @@ int manager_start_scope(
 }
 
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
@@ -1425,8 +1433,8 @@ int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_erro
 }
 
 int manager_unit_is_active(Manager *manager, const char *unit) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *state;
         int r;
@@ -1467,8 +1475,8 @@ int manager_unit_is_active(Manager *manager, const char *unit) {
 }
 
 int manager_job_is_active(Manager *manager, const char *path) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
index a099de9f36fd34ea55b84abd2097c9b19e989f08..f2c1966a6b6ce143eb5791f10c006466ebd27fb7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -184,7 +182,7 @@ int manager_enumerate_machines(Manager *m) {
 }
 
 static int manager_connect_bus(Manager *m) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(m);
index dac7a29ed193da0c39d2c7c925d1247341a73339..e7d7dfdcebcbf7e41fdbb08a47f08e43c1823f9c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -31,9 +29,9 @@
 
 typedef struct Manager Manager;
 
-#include "machine.h"
-#include "machine-dbus.h"
 #include "image-dbus.h"
+#include "machine-dbus.h"
+#include "machine.h"
 
 struct Manager {
         sd_event *event;
index a7fdcb09cf4a0c2435d7d0e269f9a78575ba4e19..f75015d8c3dda65f7a7def71ef61cf59dc780a4d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6fcb3050c778309f03c48bb6584a42b06fdda390..60724fce805345c987cd691da6929872a3a3bbaa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,6 +38,7 @@
 #include "pager.h"
 #include "parse-util.h"
 #include "socket-util.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -196,8 +195,8 @@ static void setup_state_to_color(const char *state, const char **on, const char
 }
 
 static int list_links(int argc, char *argv[], void *userdata) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ LinkInfo *links = NULL;
         int r, c, i;
 
@@ -228,7 +227,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
 
         for (i = 0; i < c; i++) {
                 _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
-                _cleanup_device_unref_ sd_device *d = NULL;
+                _cleanup_(sd_device_unrefp) sd_device *d = NULL;
                 const char *on_color_operational, *off_color_operational,
                            *on_color_setup, *off_color_setup;
                 char devid[2 + DECIMAL_STR_MAX(int)];
@@ -275,7 +274,8 @@ static int ieee_oui(sd_hwdb *hwdb, struct ether_addr *mac, char **ret) {
         if (memcmp(mac, "\0\0\0", 3) == 0)
                 return -EINVAL;
 
-        snprintf(modalias, sizeof(modalias), "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac));
+        xsprintf(modalias, "OUI:" ETHER_ADDR_FORMAT_STR,
+                 ETHER_ADDR_FORMAT_VAL(*mac));
 
         r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description);
         if (r < 0)
@@ -297,7 +297,7 @@ static int get_gateway_description(
                 int family,
                 union in_addr_union *gateway,
                 char **gateway_description) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *m;
         int r;
 
@@ -488,6 +488,9 @@ static int dump_addresses(
 static void dump_list(const char *prefix, char **l) {
         char **i;
 
+        if (strv_isempty(l))
+                return;
+
         STRV_FOREACH(i, l) {
                 printf("%*s%s\n",
                        (int) strlen(prefix),
@@ -500,10 +503,10 @@ static int link_status_one(
                 sd_netlink *rtnl,
                 sd_hwdb *hwdb,
                 const char *name) {
-        _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
+        _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
         _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
-        _cleanup_device_unref_ sd_device *d = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *d = NULL;
         char devid[2 + DECIMAL_STR_MAX(int)];
         _cleanup_free_ char *t = NULL, *network = NULL;
         const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
@@ -550,7 +553,6 @@ static int link_status_one(
                 return rtnl_log_parse_error(r);
 
         have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
-
         if (have_mac) {
                 const uint8_t *p;
                 bool all_zeroes = true;
@@ -565,44 +567,35 @@ static int link_status_one(
                         have_mac = false;
         }
 
-        sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
+        (void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
 
-        sd_network_link_get_operational_state(ifindex, &operational_state);
+        (void) sd_network_link_get_operational_state(ifindex, &operational_state);
         operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
 
-        sd_network_link_get_setup_state(ifindex, &setup_state);
+        (void) sd_network_link_get_setup_state(ifindex, &setup_state);
         setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
 
-        sd_network_link_get_dns(ifindex, &dns);
-        sd_network_link_get_domains(ifindex, &domains);
-        r = sd_network_link_get_wildcard_domain(ifindex);
-        if (r > 0) {
-                char *wildcard;
-
-                wildcard = strdup("*");
-                if (!wildcard)
-                        return log_oom();
-
-                if (strv_consume(&domains, wildcard) < 0)
-                        return log_oom();
-        }
+        (void) sd_network_link_get_dns(ifindex, &dns);
+        (void) sd_network_link_get_search_domains(ifindex, &search_domains);
+        (void) sd_network_link_get_route_domains(ifindex, &route_domains);
+        (void) sd_network_link_get_ntp(ifindex, &ntp);
 
         sprintf(devid, "n%i", ifindex);
 
-        (void)sd_device_new_from_device_id(&d, devid);
+        (void) sd_device_new_from_device_id(&d, devid);
 
         if (d) {
-                (void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
-                (void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
-                (void)sd_device_get_property_value(d, "ID_PATH", &path);
+                (void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
+                (void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
+                (void) sd_device_get_property_value(d, "ID_PATH", &path);
 
                 r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor);
                 if (r < 0)
-                        (void)sd_device_get_property_value(d, "ID_VENDOR", &vendor);
+                        (void) sd_device_get_property_value(d, "ID_VENDOR", &vendor);
 
                 r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model);
                 if (r < 0)
-                        (void)sd_device_get_property_value(d, "ID_MODEL", &model);
+                        (void) sd_device_get_property_value(d, "ID_MODEL", &model);
         }
 
         link_get_type_string(iftype, d, &t);
@@ -651,20 +644,14 @@ static int link_status_one(
         dump_addresses(rtnl, "         Address: ", ifindex);
         dump_gateways(rtnl, hwdb, "         Gateway: ", ifindex);
 
-        if (!strv_isempty(dns))
-                dump_list("             DNS: ", dns);
-        if (!strv_isempty(domains))
-                dump_list("          Domain: ", domains);
+        dump_list("             DNS: ", dns);
+        dump_list("  Search Domains: ", search_domains);
+        dump_list("   Route Domains: ", route_domains);
 
-        (void) sd_network_link_get_ntp(ifindex, &ntp);
-        if (!strv_isempty(ntp))
-                dump_list("             NTP: ", ntp);
+        dump_list("             NTP: ", ntp);
 
-        if (!strv_isempty(carrier_bound_to))
-                dump_list("Carrier Bound To: ", carrier_bound_to);
-
-        if (!strv_isempty(carrier_bound_by))
-                dump_list("Carrier Bound By: ", carrier_bound_by);
+        dump_list("Carrier Bound To: ", carrier_bound_to);
+        dump_list("Carrier Bound By: ", carrier_bound_by);
 
         (void) sd_network_link_get_timezone(ifindex, &tz);
         if (tz)
@@ -674,8 +661,8 @@ static int link_status_one(
 }
 
 static int link_status(int argc, char *argv[], void *userdata) {
-        _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         char **name;
         int r;
 
@@ -689,30 +676,30 @@ static int link_status(int argc, char *argv[], void *userdata) {
 
         if (argc <= 1 && !arg_all) {
                 _cleanup_free_ char *operational_state = NULL;
-                _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
+                _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains;
                 const char *on_color_operational, *off_color_operational;
 
                 sd_network_get_operational_state(&operational_state);
                 operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
 
-                printf("%s%s%s      State: %s%s%s\n",
+                printf("%s%s%s        State: %s%s%s\n",
                        on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational,
                        on_color_operational, strna(operational_state), off_color_operational);
 
-                dump_addresses(rtnl, "     Address: ", 0);
-                dump_gateways(rtnl, hwdb, "     Gateway: ", 0);
+                dump_addresses(rtnl, "       Address: ", 0);
+                dump_gateways(rtnl, hwdb, "       Gateway: ", 0);
 
                 sd_network_get_dns(&dns);
-                if (!strv_isempty(dns))
-                        dump_list("         DNS: ", dns);
+                dump_list("           DNS: ", dns);
+
+                sd_network_get_search_domains(&search_domains);
+                dump_list("Search Domains: ", search_domains);
 
-                sd_network_get_domains(&domains);
-                if (!strv_isempty(domains))
-                        dump_list("      Domain: ", domains);
+                sd_network_get_route_domains(&route_domains);
+                dump_list(" Route Domains: ", route_domains);
 
                 sd_network_get_ntp(&ntp);
-                if (!strv_isempty(ntp))
-                        dump_list("         NTP: ", ntp);
+                dump_list("           NTP: ", ntp);
 
                 return 0;
         }
@@ -720,7 +707,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
         pager_open_if_enabled();
 
         if (arg_all) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
                 _cleanup_free_ LinkInfo *links = NULL;
                 int c, i;
 
@@ -906,8 +893,8 @@ static char *lldp_system_caps(uint16_t cap) {
 }
 
 static int link_lldp_status(int argc, char *argv[], void *userdata) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ LinkInfo *links = NULL;
         double ttl = -1;
         uint32_t capability;
index 889fe1e30d3a724c104624557758be0d4eac645b..d9d487d805d31d3988498d6307755ac478f7065b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e6207ccce638a75c08885957c87f7587bddb83f0..8e1378ff4059163733bff7ff72d717a865b77591 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 
 typedef struct AddressPool AddressPool;
 
+#include "in-addr-util.h"
 #include "networkd.h"
 
 struct AddressPool {
index 1ce1f4d8d680e36d22334df6da92e07fdb799180..7f9a7268cc1c53ceea5c0238f2d6e296bb1ae0ce 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -408,7 +406,7 @@ int address_get(Link *link, int family, const union in_addr_union *in_addr, unsi
 
 int address_remove(Address *address, Link *link,
                  sd_netlink_message_handler_t callback) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(address);
@@ -503,7 +501,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
 }
 
 int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(address);
index 4049a23bdc4a1c923b11b38583b8fc3badb5be86..338f6eb9a2d8f4c978b11cd2d0bf5e40a0da58af 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -28,9 +26,9 @@
 
 typedef struct Address Address;
 
-#include "networkd.h"
-#include "networkd-network.h"
 #include "networkd-link.h"
+#include "networkd-network.h"
+#include "networkd.h"
 
 #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
 
index b9c60a3c77871a765eb6087c83c28ec9cf9c0e79..03c28bbcb613527ef8d41ce07946ea365ca73152 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -54,7 +52,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
 
 static int link_set_dhcp_routes(Link *link) {
         struct in_addr gateway;
-        struct sd_dhcp_route *static_routes;
+        _cleanup_free_ sd_dhcp_route **static_routes = NULL;
         int r, n, i;
 
         assert(link);
@@ -130,9 +128,9 @@ static int link_set_dhcp_routes(Link *link) {
 
                 route->family = AF_INET;
                 route->protocol = RTPROT_DHCP;
-                route->gw.in = static_routes[i].gw_addr;
-                route->dst.in = static_routes[i].dst_addr;
-                route->dst_prefixlen = static_routes[i].dst_prefixlen;
+                assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
+                assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
+                assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
                 route->priority = link->network->dhcp_route_metric;
 
                 r = route_configure(route, link, &dhcp4_route_handler);
@@ -158,8 +156,8 @@ static int dhcp_lease_lost(Link *link) {
 
         log_link_warning(link, "DHCP lease lost");
 
-        if (link->network->dhcp_routes) {
-                struct sd_dhcp_route *routes;
+        if (link->network->dhcp_use_routes) {
+                _cleanup_free_ sd_dhcp_route **routes = NULL;
                 int n, i;
 
                 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
@@ -170,9 +168,9 @@ static int dhcp_lease_lost(Link *link) {
                                 r = route_new(&route);
                                 if (r >= 0) {
                                         route->family = AF_INET;
-                                        route->gw.in = routes[i].gw_addr;
-                                        route->dst.in = routes[i].dst_addr;
-                                        route->dst_prefixlen = routes[i].dst_prefixlen;
+                                        assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
+                                        assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
+                                        assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
 
                                         route_remove(route, link,
                                                    &link_route_remove_handler);
@@ -223,7 +221,7 @@ static int dhcp_lease_lost(Link *link) {
                 }
         }
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 uint16_t mtu;
 
                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
@@ -238,11 +236,11 @@ static int dhcp_lease_lost(Link *link) {
                 }
         }
 
-        if (link->network->dhcp_hostname) {
+        if (link->network->dhcp_use_hostname) {
                 const char *hostname = NULL;
 
-                if (link->network->hostname)
-                        hostname = link->network->hostname;
+                if (link->network->dhcp_hostname)
+                        hostname = link->network->dhcp_hostname;
                 else
                         (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
 
@@ -255,6 +253,7 @@ static int dhcp_lease_lost(Link *link) {
         }
 
         link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
+        link_dirty(link);
         link->dhcp4_configured = false;
 
         return 0;
@@ -331,6 +330,7 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
         sd_dhcp_lease_unref(link->dhcp_lease);
         link->dhcp4_configured = false;
         link->dhcp_lease = sd_dhcp_lease_ref(lease);
+        link_dirty(link);
 
         r = sd_dhcp_lease_get_address(lease, &address);
         if (r < 0)
@@ -408,8 +408,9 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                            NULL);
 
         link->dhcp_lease = sd_dhcp_lease_ref(lease);
+        link_dirty(link);
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 uint16_t mtu;
 
                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
@@ -420,11 +421,11 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                 }
         }
 
-        if (link->network->dhcp_hostname) {
+        if (link->network->dhcp_use_hostname) {
                 const char *hostname = NULL;
 
-                if (link->network->hostname)
-                        hostname = link->network->hostname;
+                if (link->network->dhcp_hostname)
+                        hostname = link->network->dhcp_hostname;
                 else
                         (void) sd_dhcp_lease_get_hostname(lease, &hostname);
 
@@ -435,7 +436,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                 }
         }
 
-        if (link->network->dhcp_timezone) {
+        if (link->network->dhcp_use_timezone) {
                 const char *tz = NULL;
 
                 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
@@ -568,45 +569,45 @@ int dhcp4_configure(Link *link) {
                         return r;
         }
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_INTERFACE_MTU);
+                                                      SD_DHCP_OPTION_INTERFACE_MTU);
                 if (r < 0)
                         return r;
         }
 
-        if (link->network->dhcp_routes) {
+        if (link->network->dhcp_use_routes) {
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_STATIC_ROUTE);
+                                                      SD_DHCP_OPTION_STATIC_ROUTE);
                 if (r < 0)
                         return r;
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
+                                                      SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
                 if (r < 0)
                         return r;
         }
 
-        /* Always acquire the timezone and NTP*/
-        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER);
+        /* Always acquire the timezone and NTP */
+        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
         if (r < 0)
                 return r;
 
-        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE);
+        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
         if (r < 0)
                 return r;
 
-        if (link->network->dhcp_sendhost) {
+        if (link->network->dhcp_send_hostname) {
                 _cleanup_free_ char *hostname = NULL;
                 const char *hn = NULL;
 
-                if (!link->network->hostname)  {
+                if (!link->network->dhcp_hostname) {
                         hostname = gethostname_malloc();
                         if (!hostname)
                                 return -ENOMEM;
 
                         hn = hostname;
                 } else
-                        hn = link->network->hostname;
+                        hn = link->network->dhcp_hostname;
 
                 if (!is_localhost(hn)) {
                         r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
index e67e51f7ef0c88086608295ee1bbd8350dc084e2..5f7a005c36a34b18d1b850012fb79d7c123b3211 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6e5480ee220bdc0b4f30e750c7c8af59a941b501..1538caa204ddba5b8d2b5ce2916202f2fbf824ea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -97,7 +95,7 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
 
 /* send a request to the kernel to add a FDB entry in its static MAC table. */
 int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         sd_netlink *rtnl;
         int r;
 
index f0efb902d0da5ff187dd395c1d0b1288b4f04598..89b3e2940554746c80807fde751be28b151d5ccf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 typedef struct FdbEntry FdbEntry;
 
-#include "networkd.h"
 #include "networkd-network.h"
+#include "networkd.h"
 
 struct FdbEntry {
         Network *network;
index f4aac4bb932e8afcb4fb6c83ac2b4fd86bde9fa1..949c75337cd449afcf649a74ae3fc78f5c6fe6f6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d09a3c2d07d1e38a85f6f6acde59143dfcb0ecfd..532557ed6c5e628859b4e52b3d80ff6b0ba851b8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -59,15 +57,19 @@ static char *link_bus_path(Link *link) {
 int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
         _cleanup_strv_free_ char **l = NULL;
         Manager *m = userdata;
+        unsigned c = 0;
         Link *link;
         Iterator i;
-        int r;
 
         assert(bus);
         assert(path);
         assert(m);
         assert(nodes);
 
+        l = new0(char*, hashmap_size(m->links) + 1);
+        if (!l)
+                return -ENOMEM;
+
         HASHMAP_FOREACH(link, m->links, i) {
                 char *p;
 
@@ -75,11 +77,10 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
                 if (!p)
                         return -ENOMEM;
 
-                r = strv_consume(&l, p);
-                if (r < 0)
-                        return r;
+                l[c++] = p;
         }
 
+        l[c] = NULL;
         *nodes = l;
         l = NULL;
 
@@ -99,7 +100,7 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void
         assert(found);
 
         r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
-        if (r < 0)
+        if (r <= 0)
                 return 0;
 
         r = parse_ifindex(identifier, &ifindex);
index 01d5942ce5b6b1bde69f6d353f76bbec8c336a9a..692c0bf63d13a3294a18439d44eae6ff045ca21e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -26,7 +24,6 @@
 #include "alloc-util.h"
 #include "bus-util.h"
 #include "dhcp-lease-internal.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "netlink-util.h"
@@ -404,7 +401,7 @@ static void link_free(Link *link) {
 
         free(link->lease_file);
 
-        sd_lldp_free(link->lldp);
+        sd_lldp_unref(link->lldp);
 
         free(link->lldp_file);
 
@@ -768,7 +765,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
                 addresses[n_addresses++] = ia;
         }
 
-        if (link->network->dhcp_dns &&
+        if (link->network->dhcp_use_dns &&
             link->dhcp_lease) {
                 const struct in_addr *da = NULL;
                 int n;
@@ -813,7 +810,7 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
                 addresses[n_addresses++] = ia;
         }
 
-        if (link->network->dhcp_ntp &&
+        if (link->network->dhcp_use_ntp &&
             link->dhcp_lease) {
                 const struct in_addr *da = NULL;
                 int n;
@@ -1149,7 +1146,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
 }
 
 int link_set_mtu(Link *link, uint32_t mtu) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(link);
@@ -1176,7 +1173,7 @@ int link_set_mtu(Link *link, uint32_t mtu) {
 }
 
 static int link_set_bridge(Link *link) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(link);
@@ -1360,7 +1357,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
 }
 
 static int link_up(Link *link) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         uint8_t ipv6ll_mode;
         int r;
 
@@ -1447,7 +1444,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
 }
 
 static int link_down(Link *link) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(link);
@@ -2040,9 +2037,13 @@ static int link_configure(Link *link) {
         assert(link->network);
         assert(link->state == LINK_STATE_PENDING);
 
-        r = link_drop_foreign_config(link);
-        if (r < 0)
-                return r;
+        /* Drop foreign config, but ignore loopback or critical devices.
+         * We do not want to remove loopback address or addresses used for root NFS. */
+        if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) {
+                r = link_drop_foreign_config(link);
+                if (r < 0)
+                        return r;
+        }
 
         r = link_set_bridge_fdb(link);
         if (r < 0)
@@ -2197,7 +2198,7 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
 }
 
 int link_initialized(Link *link, struct udev_device *device) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(link);
@@ -2296,7 +2297,8 @@ network_file_fail:
                         if (r < 0) {
                                 log_link_debug_errno(link, r, "Failed to extract next address string: %m");
                                 continue;
-                        } if (r == 0)
+                        }
+                        if (r == 0)
                                 break;
 
                         prefixlen_str = strchr(address_str, '/');
@@ -2326,10 +2328,12 @@ network_file_fail:
         }
 
         if (routes) {
+                p = routes;
+
                 for (;;) {
                         Route *route;
                         _cleanup_free_ char *route_str = NULL;
-                        _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+                        _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
                         usec_t lifetime;
                         char *prefixlen_str;
                         int family;
@@ -2340,7 +2344,8 @@ network_file_fail:
                         if (r < 0) {
                                 log_link_debug_errno(link, r, "Failed to extract next route string: %m");
                                 continue;
-                        } if (r == 0)
+                        }
+                        if (r == 0)
                                 break;
 
                         prefixlen_str = strchr(route_str, '/');
@@ -2488,7 +2493,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
         link->ipv6ll_address = *address;
         link_check_ready(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
                 r = link_acquire_ipv6_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -2504,7 +2509,7 @@ static int link_carrier_gained(Link *link) {
 
         assert(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
                 r = link_acquire_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -2722,9 +2727,10 @@ int link_save(Link *link) {
                 admin_state, oper_state);
 
         if (link->network) {
-                char **address, **domain;
                 bool space;
                 sd_dhcp6_lease *dhcp6_lease = NULL;
+                const char *dhcp_domainname = NULL;
+                char **dhcp6_domains = NULL;
 
                 if (link->dhcp6_client) {
                         r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
@@ -2736,14 +2742,9 @@ int link_save(Link *link) {
 
                 fputs("DNS=", f);
                 space = false;
-                STRV_FOREACH(address, link->network->dns) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(*address, f);
-                        space = true;
-                }
+                fputstrv(f, link->network->dns, NULL, &space);
 
-                if (link->network->dhcp_dns &&
+                if (link->network->dhcp_use_dns &&
                     link->dhcp_lease) {
                         const struct in_addr *addresses;
 
@@ -2756,7 +2757,7 @@ int link_save(Link *link) {
                         }
                 }
 
-                if (link->network->dhcp_dns && dhcp6_lease) {
+                if (link->network->dhcp_use_dns && dhcp6_lease) {
                         struct in6_addr *in6_addrs;
 
                         r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
@@ -2771,14 +2772,9 @@ int link_save(Link *link) {
 
                 fputs("NTP=", f);
                 space = false;
-                STRV_FOREACH(address, link->network->ntp) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(*address, f);
-                        space = true;
-                }
+                fputstrv(f, link->network->ntp, NULL, &space);
 
-                if (link->network->dhcp_ntp &&
+                if (link->network->dhcp_use_ntp &&
                     link->dhcp_lease) {
                         const struct in_addr *addresses;
 
@@ -2791,10 +2787,9 @@ int link_save(Link *link) {
                         }
                 }
 
-                if (link->network->dhcp_ntp && dhcp6_lease) {
+                if (link->network->dhcp_use_ntp && dhcp6_lease) {
                         struct in6_addr *in6_addrs;
                         char **hosts;
-                        char **hostname;
 
                         r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
                                                          &in6_addrs);
@@ -2806,61 +2801,60 @@ int link_save(Link *link) {
                         }
 
                         r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
-                        if (r > 0) {
-                                STRV_FOREACH(hostname, hosts) {
-                                        if (space)
-                                                fputc(' ', f);
-                                        fputs(*hostname, f);
-                                        space = true;
-                                }
-                        }
+                        if (r > 0)
+                                fputstrv(f, hosts, NULL, &space);
                 }
 
                 fputc('\n', f);
 
-                fputs("DOMAINS=", f);
-                space = false;
-                STRV_FOREACH(domain, link->network->domains) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(*domain, f);
-                        space = true;
+                if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
+                        if (link->dhcp_lease)
+                                (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
+
+                        if (dhcp6_lease)
+                                (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
                 }
 
-                if (link->network->dhcp_domains &&
-                    link->dhcp_lease) {
-                        const char *domainname;
+                fputs("DOMAINS=", f);
+                fputstrv(f, link->network->search_domains, NULL, &space);
 
-                        r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
-                        if (r >= 0) {
-                                if (space)
-                                        fputc(' ', f);
-                                fputs(domainname, f);
-                                space = true;
-                        }
-                }
+                if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname)
+                        fputs_with_space(f, dhcp_domainname, NULL, &space);
 
-                if (link->network->dhcp_domains && dhcp6_lease) {
-                        char **domains;
-
-                        r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
-                        if (r >= 0) {
-                                STRV_FOREACH(domain, domains) {
-                                        if (space)
-                                                fputc(' ', f);
-                                        fputs(*domain, f);
-                                        space = true;
-                                }
-                        }
-                }
+                if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains)
+                        fputstrv(f, dhcp6_domains, NULL, &space);
 
                 fputc('\n', f);
 
-                fprintf(f, "WILDCARD_DOMAIN=%s\n",
-                        yes_no(link->network->wildcard_domain));
+                fputs("ROUTE_DOMAINS=", f);
+                fputstrv(f, link->network->route_domains, NULL, NULL);
+
+                if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname)
+                        fputs_with_space(f, dhcp_domainname, NULL, &space);
+
+                if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains)
+                        fputstrv(f, dhcp6_domains, NULL, &space);
+
+                fputc('\n', f);
 
                 fprintf(f, "LLMNR=%s\n",
                         resolve_support_to_string(link->network->llmnr));
+                fprintf(f, "MDNS=%s\n",
+                        resolve_support_to_string(link->network->mdns));
+
+                if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID)
+                        fprintf(f, "DNSSEC=%s\n",
+                                dnssec_mode_to_string(link->network->dnssec_mode));
+
+                if (!set_isempty(link->network->dnssec_negative_trust_anchors)) {
+                        const char *n;
+
+                        fputs("DNSSEC_NTA=", f);
+                        space = false;
+                        SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i)
+                                fputs_with_space(f, n, NULL, &space);
+                        fputc('\n', f);
+                }
 
                 fputs("ADDRESSES=", f);
                 space = false;
@@ -2874,7 +2868,6 @@ int link_save(Link *link) {
                         fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
                         space = true;
                 }
-
                 fputc('\n', f);
 
                 fputs("ROUTES=", f);
@@ -2899,12 +2892,8 @@ int link_save(Link *link) {
                 bool space = false;
 
                 fputs("CARRIER_BOUND_TO=", f);
-                HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(carrier->ifname, f);
-                        space = true;
-                }
+                HASHMAP_FOREACH(carrier, link->bound_to_links, i)
+                        fputs_with_space(f, carrier->ifname, NULL, &space);
 
                 fputc('\n', f);
         }
@@ -2914,12 +2903,8 @@ int link_save(Link *link) {
                 bool space = false;
 
                 fputs("CARRIER_BOUND_BY=", f);
-                HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
-                        if (space)
-                                fputc(' ', f);
-                        fputs(carrier->ifname, f);
-                        space = true;
-                }
+                HASHMAP_FOREACH(carrier, link->bound_by_links, i)
+                        fputs_with_space(f, carrier->ifname, NULL, &space);
 
                 fputc('\n', f);
         }
index aa2235b11dc3f273b35a11cb9b099dd39c524927..0e6a7b6f21fa108e8a695c7a95951c7b73a873e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -56,9 +54,9 @@ typedef enum LinkOperationalState {
         _LINK_OPERSTATE_INVALID = -1
 } LinkOperationalState;
 
-#include "networkd.h"
-#include "networkd-network.h"
 #include "networkd-address.h"
+#include "networkd-network.h"
+#include "networkd.h"
 
 struct Link {
         Manager *manager;
index dafaf2daea61d062b7a2b56f124653744a1cadba..0c429b94714266aa20d1bad46e2f2e88a90e5b4f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 42f58fed197603ed032c175b9e797f49bff897ba..b527191a5a98144853a00b2e7dd0637d5fe17580 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "bus-util.h"
 #include "conf-parser.h"
 #include "def.h"
+#include "dns-domain.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "libudev-private.h"
 #include "local-addresses.h"
 #include "netlink-util.h"
 #include "networkd.h"
+#include "ordered-set.h"
 #include "path-util.h"
 #include "set.h"
 #include "udev-util.h"
@@ -659,15 +659,16 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
         } else if (ifindex <= 0) {
                 log_warning("rtnl: received link message with invalid ifindex: %d", ifindex);
                 return 0;
-        } else
-                link_get(m, ifindex, &link);
+        }
 
         r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
         if (r < 0) {
                 log_warning_errno(r, "rtnl: Received link message without ifname: %m");
                 return 0;
-        } else
-                netdev_get(m, name, &netdev);
+        }
+
+        (void) link_get(m, ifindex, &link);
+        (void) netdev_get(m, name, &netdev);
 
         switch (type) {
         case RTM_NEWLINK:
@@ -775,7 +776,7 @@ static int manager_connect_rtnl(Manager *m) {
         return 0;
 }
 
-static int set_put_in_addr(Set *s, const struct in_addr *address) {
+static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) {
         char *p;
         int r;
 
@@ -785,21 +786,21 @@ static int set_put_in_addr(Set *s, const struct in_addr *address) {
         if (r < 0)
                 return r;
 
-        r = set_consume(s, p);
+        r = ordered_set_consume(s, p);
         if (r == -EEXIST)
                 return 0;
 
         return r;
 }
 
-static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
+static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) {
         int r, i, c = 0;
 
         assert(s);
         assert(n <= 0 || addresses);
 
         for (i = 0; i < n; i++) {
-                r = set_put_in_addr(s, addresses+i);
+                r = ordered_set_put_in_addr(s, addresses+i);
                 if (r < 0)
                         return r;
 
@@ -809,27 +810,24 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
         return c;
 }
 
-static void print_string_set(FILE *f, const char *field, Set *s) {
+static void print_string_set(FILE *f, const char *field, OrderedSet *s) {
         bool space = false;
         Iterator i;
         char *p;
 
-        if (set_isempty(s))
+        if (ordered_set_isempty(s))
                 return;
 
         fputs(field, f);
 
-        SET_FOREACH(p, s, i) {
-                if (space)
-                        fputc(' ', f);
-                fputs(p, f);
-                space = true;
-        }
+        ORDERED_SET_FOREACH(p, s, i)
+                fputs_with_space(f, p, NULL, &space);
+
         fputc('\n', f);
 }
 
 static int manager_save(Manager *m) {
-        _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
+        _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL;
         Link *link;
         Iterator i;
         _cleanup_free_ char *temp_path = NULL;
@@ -842,16 +840,20 @@ static int manager_save(Manager *m) {
         assert(m->state_file);
 
         /* We add all NTP and DNS server to a set, to filter out duplicates */
-        dns = set_new(&string_hash_ops);
+        dns = ordered_set_new(&string_hash_ops);
         if (!dns)
                 return -ENOMEM;
 
-        ntp = set_new(&string_hash_ops);
+        ntp = ordered_set_new(&string_hash_ops);
         if (!ntp)
                 return -ENOMEM;
 
-        domains = set_new(&string_hash_ops);
-        if (!domains)
+        search_domains = ordered_set_new(&dns_name_hash_ops);
+        if (!search_domains)
+                return -ENOMEM;
+
+        route_domains = ordered_set_new(&dns_name_hash_ops);
+        if (!route_domains)
                 return -ENOMEM;
 
         HASHMAP_FOREACH(link, m->links, i) {
@@ -865,15 +867,19 @@ static int manager_save(Manager *m) {
                         continue;
 
                 /* First add the static configured entries */
-                r = set_put_strdupv(dns, link->network->dns);
+                r = ordered_set_put_strdupv(dns, link->network->dns);
+                if (r < 0)
+                        return r;
+
+                r = ordered_set_put_strdupv(ntp, link->network->ntp);
                 if (r < 0)
                         return r;
 
-                r = set_put_strdupv(ntp, link->network->ntp);
+                r = ordered_set_put_strdupv(search_domains, link->network->search_domains);
                 if (r < 0)
                         return r;
 
-                r = set_put_strdupv(domains, link->network->domains);
+                r = ordered_set_put_strdupv(route_domains, link->network->route_domains);
                 if (r < 0)
                         return r;
 
@@ -881,36 +887,41 @@ static int manager_save(Manager *m) {
                         continue;
 
                 /* Secondly, add the entries acquired via DHCP */
-                if (link->network->dhcp_dns) {
+                if (link->network->dhcp_use_dns) {
                         const struct in_addr *addresses;
 
                         r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
                         if (r > 0) {
-                                r = set_put_in_addrv(dns, addresses, r);
+                                r = ordered_set_put_in_addrv(dns, addresses, r);
                                 if (r < 0)
                                         return r;
                         } else if (r < 0 && r != -ENODATA)
                                 return r;
                 }
 
-                if (link->network->dhcp_ntp) {
+                if (link->network->dhcp_use_ntp) {
                         const struct in_addr *addresses;
 
                         r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
                         if (r > 0) {
-                                r = set_put_in_addrv(ntp, addresses, r);
+                                r = ordered_set_put_in_addrv(ntp, addresses, r);
                                 if (r < 0)
                                         return r;
                         } else if (r < 0 && r != -ENODATA)
                                 return r;
                 }
 
-                if (link->network->dhcp_domains) {
+                if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
                         const char *domainname;
 
                         r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
                         if (r >= 0) {
-                                r = set_put_strdup(domains, domainname);
+
+                                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);
+
                                 if (r < 0)
                                         return r;
                         } else if (r != -ENODATA)
@@ -933,7 +944,8 @@ static int manager_save(Manager *m) {
 
         print_string_set(f, "DNS=", dns);
         print_string_set(f, "NTP=", ntp);
-        print_string_set(f, "DOMAINS=", domains);
+        print_string_set(f, "DOMAINS=", search_domains);
+        print_string_set(f, "ROUTE_DOMAINS=", route_domains);
 
         r = fflush_and_check(f);
         if (r < 0)
@@ -1151,7 +1163,7 @@ bool manager_should_reload(Manager *m) {
 }
 
 int manager_rtnl_enumerate_links(Manager *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *link;
         int r;
 
@@ -1186,7 +1198,7 @@ int manager_rtnl_enumerate_links(Manager *m) {
 }
 
 int manager_rtnl_enumerate_addresses(Manager *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *addr;
         int r;
 
@@ -1221,7 +1233,7 @@ int manager_rtnl_enumerate_addresses(Manager *m) {
 }
 
 int manager_rtnl_enumerate_routes(Manager *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *route;
         int r;
 
index ce9e513ceb23b418eabe4be79bf0976d86b27b13..f2287be20adceba863733a27a5c4d729e2b905a2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -89,7 +87,7 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
                 address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
         }
         address->prefixlen = prefixlen;
-        address->flags = IFA_F_NOPREFIXROUTE;
+        address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
         address->cinfo.ifa_prefered = lifetime_preferred;
         address->cinfo.ifa_valid = lifetime_valid;
 
index 50b9021d0952bf043db06f85dc8b689b51d4a248..106f15fabc420ec55a0f60a6d35372d34b07b072 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
index 0cdce1605ed552b0dbde5bd37c96256ae4bd1c2b..cb6baea24f034685be5a47a06d62ea75b08c1976 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a991bdb5fbac19fbc15d0973c81ffdd0fcb8005c..cdcd08f057e151d075aeb97ae9ec968b298159a8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
@@ -46,7 +44,7 @@ static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, vo
 }
 
 static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         Bridge *b;
         int r;
 
index d3bd15e0d6d128db13b1198dd69ac39c02239902..b2bf7e15f1c4eb2118ca08d995c41cbe3d5349a6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bb246a2be07bc5499cfbcb9118004d5f8bd55c92..6617a86c201ec917df68a0364fb40a849614fa9f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
index 0d321e5ae6bc4eed5d03154e426a56fba98a48c2..29f75a149b7bbc69c652ad02ca83201254006a86 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 4a4b400e416793c8782151090564efd2a18e974e..8f506af0922b695094ec3f1eb46ecc0e729418db 100644 (file)
@@ -57,6 +57,8 @@ VXLAN.UDP6ZeroCheckSumTx,    config_parse_bool,                  0,
 VXLAN.FDBAgeingSec,          config_parse_sec,                   0,                             offsetof(VxLan, fdb_ageing)
 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)
 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)
index 27cb7d1bf012da15f4921793329436f80ea04ff8..af4177e43a96ab3817299d2b3257d9257770ba3b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 408386f3787785c0962feed6bfdde0aa3fadc43a..5b85ef2150d0f7ec66a47b6e1b3d47fc1c87039a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7144823b2da17d47ea344a42d5a7de56ff2c3792..48e98aa51bb051e0ce4ab4b391cca3616940ae8e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c491bfa3129aca5e42056c29ee6ed77486dfbe7b..8b42684de6e30ed19395967d720c9443b4f7c5f5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 385338849f40a317495c760a994c5a2b4d7e9474..46ff2974f40040991203695245f52126b6bf9b4c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
@@ -56,7 +54,7 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlin
         assert(link);
         assert(m);
         assert(t);
-        assert(t->family == AF_INET);
+        assert(t->family == AF_INET || t->family != -1);
 
         r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
         if (r < 0)
@@ -89,7 +87,7 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink
         assert(link);
         assert(m);
         assert(t);
-        assert(t->family == AF_INET);
+        assert(t->family == AF_INET || t->family != -1);
 
         r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
         if (r < 0)
@@ -126,7 +124,7 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink
                 t = GRETAP(netdev);
 
         assert(t);
-        assert(t->family == AF_INET);
+        assert(t->family == AF_INET || t->family != -1);
         assert(link);
         assert(m);
 
@@ -358,12 +356,7 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
 
         assert(t);
 
-        if (t->remote.in.s_addr == INADDR_ANY) {
-                log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
-                return -EINVAL;
-        }
-
-        if (t->family != AF_INET && t->family != AF_INET6) {
+        if (t->family != AF_INET && t->family != AF_INET6 && t->family != 0) {
                 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
                 return -EINVAL;
         }
@@ -397,15 +390,21 @@ int config_parse_tunnel_address(const char *unit,
         assert(rvalue);
         assert(data);
 
-        r = in_addr_from_string_auto(rvalue, &f, &buffer);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
+        if (streq(rvalue, "any")) {
+                t->family = 0;
                 return 0;
-        }
+        } else {
 
-        if (t->family != AF_UNSPEC && t->family != f) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
-                return 0;
+                r = in_addr_from_string_auto(rvalue, &f, &buffer);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
+                        return 0;
+                }
+
+                if (t->family != AF_UNSPEC && t->family != f) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
+                        return 0;
+                }
         }
 
         t->family = f;
@@ -498,6 +497,7 @@ static void ipip_init(NetDev *n) {
         assert(t);
 
         t->pmtudisc = true;
+        t->family = -1;
 }
 
 static void sit_init(NetDev *n) {
@@ -507,6 +507,7 @@ static void sit_init(NetDev *n) {
         assert(t);
 
         t->pmtudisc = true;
+        t->family = -1;
 }
 
 static void vti_init(NetDev *n) {
@@ -537,6 +538,7 @@ static void gre_init(NetDev *n) {
         assert(t);
 
         t->pmtudisc = true;
+        t->family = -1;
 }
 
 static void ip6gre_init(NetDev *n) {
index fa7decce18372e23b29b74a8426198d772077371..ea1d9a79e702f3437e2cc4ecff7a9004bdbcffa2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3d504a85644570df00b69036080c07dcf7027ca7..ab9a1b0426e85a6b829950b67ae26eea3e8b77e3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
index 29f8bb0ea5013a4de549c3861ae6ac9c43c033dc..b970b0ce3b80b668e5b359ecee4959309009d394 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 773a1ee6d186855838b309a465a3ccedcf5b8339..b122a06c2562bfb40a48a8fff1afc71ceed078b9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
index 85d8b49a7577ffd777703296f6b005ee82f6f2fe..f7fdf906abbfcf7fa46131f0c7a216902bc40995 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 75fbdd355ed42bf57f52091db61db9daae4ca056..b1f4714afab4b62255586e46f29592793c2852bf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 0c0fbbe093b089ab8d3f7710a1bfd59adddc8034..8701c4b7859f8a8e6130b1f9a9681c2592a38bd7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 7932b93335f259711f2167155b3d807051255106..eb9a2c06b338eff165812aeff1c7c3a72da69f2a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
     This file is part of systemd.
 
@@ -24,6 +22,8 @@
 #include "sd-netlink.h"
 
 #include "conf-parser.h"
+#include "alloc-util.h"
+#include "parse-util.h"
 #include "missing.h"
 #include "networkd-link.h"
 #include "networkd-netdev-vxlan.h"
@@ -110,6 +110,21 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m");
 
+        r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port));
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m");
+
+        if (v->port_range.low || v->port_range.high) {
+                struct ifla_vxlan_port_range port_range;
+
+                port_range.low = htobe16(v->port_range.low);
+                port_range.high = htobe16(v->port_range.high);
+
+                r = sd_netlink_message_append_data(m, IFLA_VXLAN_PORT_RANGE, &port_range, sizeof(port_range));
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m");
+        }
+
         if (v->group_policy) {
                 r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP);
                 if (r < 0)
@@ -155,6 +170,89 @@ int config_parse_vxlan_group_address(const char *unit,
         return 0;
 }
 
+int config_parse_port_range(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_free_ char *word = NULL;
+        VxLan *v = userdata;
+        unsigned low, high;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = extract_first_word(&rvalue, &word, NULL, 0);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract VXLAN port range, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (r == 0)
+                return 0;
+
+        r = parse_range(word, &low, &high);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'", word);
+                return 0;
+        }
+
+        if (low <= 0 || low > 65535 || high <= 0 || high > 65535) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word);
+                return 0;
+        }
+
+        if (high < low) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word, low, high);
+                return 0;
+        }
+
+        v->port_range.low = low;
+        v->port_range.high = high;
+
+        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) {
+        VxLan *v = userdata;
+        uint16_t port;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou16(rvalue, &port);
+        if (r < 0 || port <= 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue);
+                return 0;
+        }
+
+        v->dest_port = port;
+
+        return 0;
+}
+
 static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
         VxLan *v = VXLAN(netdev);
 
index d21f355f5dce4a82618e424507185ad8bc588dcd..459ce53f5e8bf8d030adcd931fec86834d89aaad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,9 +21,8 @@
 
 typedef struct VxLan VxLan;
 
-#include "networkd-netdev.h"
-
 #include "in-addr-util.h"
+#include "networkd-netdev.h"
 
 #define VXLAN_VID_MAX (1u << 24) - 1
 
@@ -41,6 +38,8 @@ struct VxLan {
         unsigned ttl;
         unsigned max_fdb;
 
+        uint16_t dest_port;
+
         usec_t fdb_ageing;
 
         bool learning;
@@ -52,6 +51,8 @@ struct VxLan {
         bool udp6zerocsumtx;
         bool udp6zerocsumrx;
         bool group_policy;
+
+        struct ifla_vxlan_port_range port_range;
 };
 
 extern const NetDevVTable vxlan_vtable;
@@ -66,3 +67,24 @@ int config_parse_vxlan_group_address(const char *unit,
                                      const char *rvalue,
                                      void *data,
                                      void *userdata);
+int config_parse_port_range(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_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);
index a86a6383dad37d81a475540cd0728fa28904931e..d7d014f05da7ec2a9da6ff21cfad928bb4fe9347 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -86,7 +84,7 @@ DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
 
 static void netdev_cancel_callbacks(NetDev *netdev) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         netdev_join_callback *callback;
 
         if (!netdev)
@@ -193,7 +191,7 @@ static int netdev_enter_failed(NetDev *netdev) {
 }
 
 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_handler_t callback) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(netdev);
@@ -290,7 +288,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
                 if (r < 0)
                         return r;
         } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
 
                 r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
                 if (r >= 0)
@@ -470,7 +468,7 @@ static int netdev_create(NetDev *netdev, Link *link,
 
                 log_netdev_debug(netdev, "Created");
         } else {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
 
                 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
                 if (r < 0)
index 3b9ab27b675186ef759aa7551cac78ff70249643..3eacee824b56ae01bb4e27c757217c163b347a20 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -26,8 +24,8 @@
 typedef struct NetDev NetDev;
 typedef struct NetDevVTable NetDevVTable;
 
-#include "networkd.h"
 #include "networkd-link.h"
+#include "networkd.h"
 
 typedef struct netdev_join_callback netdev_join_callback;
 
@@ -103,16 +101,16 @@ struct NetDev {
         LIST_HEAD(netdev_join_callback, callbacks);
 };
 
-#include "networkd-netdev-bridge.h"
 #include "networkd-netdev-bond.h"
-#include "networkd-netdev-vlan.h"
-#include "networkd-netdev-macvlan.h"
+#include "networkd-netdev-bridge.h"
+#include "networkd-netdev-dummy.h"
 #include "networkd-netdev-ipvlan.h"
-#include "networkd-netdev-vxlan.h"
-#include "networkd-netdev-veth.h"
+#include "networkd-netdev-macvlan.h"
 #include "networkd-netdev-tunnel.h"
-#include "networkd-netdev-dummy.h"
 #include "networkd-netdev-tuntap.h"
+#include "networkd-netdev-veth.h"
+#include "networkd-netdev-vlan.h"
+#include "networkd-netdev-vxlan.h"
 
 struct NetDevVTable {
         /* How much memory does an object of this unit type need */
index 120760a986d3ef696be1f0494a3e07cea1fae484..d6b7448a43c98c1ad06dd21f2590d66c2e438f75 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index de2c66d15372493d8a8f215844ef09b4618adb26..409df1709f76643eb507af81359b7177f7c8fd58 100644 (file)
@@ -43,9 +43,12 @@ Network.IPv6Token,                      config_parse_ipv6token,
 Network.LLDP,                           config_parse_bool,                              0,                             offsetof(Network, lldp)
 Network.Address,                        config_parse_address,                           0,                             0
 Network.Gateway,                        config_parse_gateway,                           0,                             0
-Network.Domains,                        config_parse_domains,                           0,                             offsetof(Network, domains)
+Network.Domains,                        config_parse_domains,                           0,                             0
 Network.DNS,                            config_parse_strv,                              0,                             offsetof(Network, dns)
-Network.LLMNR,                          config_parse_resolve,                           0,                             offsetof(Network, llmnr)
+Network.LLMNR,                          config_parse_resolve_support,                   0,                             offsetof(Network, llmnr)
+Network.MulticastDNS,                   config_parse_resolve_support,                   0,                             offsetof(Network, mdns)
+Network.DNSSEC,                         config_parse_dnssec_mode,                       0,                             offsetof(Network, dnssec_mode)
+Network.DNSSECNegativeTrustAnchors,     config_parse_dnssec_negative_trust_anchors,     0,                             offsetof(Network, dnssec_negative_trust_anchors)
 Network.NTP,                            config_parse_strv,                              0,                             offsetof(Network, ntp)
 Network.IPForward,                      config_parse_address_family_boolean_with_kernel,0,                             offsetof(Network, ip_forward)
 Network.IPMasquerade,                   config_parse_bool,                              0,                             offsetof(Network, ip_masquerade)
@@ -65,19 +68,19 @@ Route.Metric,                           config_parse_route_priority,
 Route.Scope,                            config_parse_route_scope,                       0,                             0
 Route.PreferredSource,                  config_parse_preferred_src,                     0,                             0
 DHCP.ClientIdentifier,                  config_parse_dhcp_client_identifier,            0,                             offsetof(Network, dhcp_client_identifier)
-DHCP.UseDNS,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_dns)
-DHCP.UseNTP,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_ntp)
-DHCP.UseMTU,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_mtu)
-DHCP.UseHostname,                       config_parse_bool,                              0,                             offsetof(Network, dhcp_hostname)
-DHCP.UseDomains,                        config_parse_bool,                              0,                             offsetof(Network, dhcp_domains)
-DHCP.UseRoutes,                         config_parse_bool,                              0,                             offsetof(Network, dhcp_routes)
-DHCP.SendHostname,                      config_parse_bool,                              0,                             offsetof(Network, dhcp_sendhost)
-DHCP.Hostname,                          config_parse_hostname,                          0,                             offsetof(Network, hostname)
+DHCP.UseDNS,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
+DHCP.UseNTP,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_ntp)
+DHCP.UseMTU,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_mtu)
+DHCP.UseHostname,                       config_parse_bool,                              0,                             offsetof(Network, dhcp_use_hostname)
+DHCP.UseDomains,                        config_parse_dhcp_use_domains,                  0,                             offsetof(Network, dhcp_use_domains)
+DHCP.UseRoutes,                         config_parse_bool,                              0,                             offsetof(Network, dhcp_use_routes)
+DHCP.SendHostname,                      config_parse_bool,                              0,                             offsetof(Network, dhcp_send_hostname)
+DHCP.Hostname,                          config_parse_hostname,                          0,                             offsetof(Network, dhcp_hostname)
 DHCP.RequestBroadcast,                  config_parse_bool,                              0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                config_parse_bool,                              0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,             config_parse_string,                            0,                             offsetof(Network, dhcp_vendor_class_identifier)
 DHCP.RouteMetric,                       config_parse_unsigned,                          0,                             offsetof(Network, dhcp_route_metric)
-DHCP.UseTimezone,                       config_parse_bool,                              0,                             offsetof(Network, dhcp_timezone)
+DHCP.UseTimezone,                       config_parse_bool,                              0,                             offsetof(Network, dhcp_use_timezone)
 DHCPServer.MaxLeaseTimeSec,             config_parse_sec,                               0,                             offsetof(Network, dhcp_server_max_lease_time_usec)
 DHCPServer.DefaultLeaseTimeSec,         config_parse_sec,                               0,                             offsetof(Network, dhcp_server_default_lease_time_usec)
 DHCPServer.EmitDNS,                     config_parse_bool,                              0,                             offsetof(Network, dhcp_server_emit_dns)
@@ -98,9 +101,9 @@ BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                       0,                             0
 /* backwards compatibility: do not add new entries to this section */
 Network.IPv4LL,                         config_parse_ipv4ll,                            0,                             offsetof(Network, link_local)
-DHCPv4.UseDNS,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_dns)
-DHCPv4.UseMTU,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname,                     config_parse_bool,                              0,                             offsetof(Network, dhcp_hostname)
-DHCP.UseDomainName,                     config_parse_bool,                              0,                             offsetof(Network, dhcp_domains)
-DHCPv4.UseDomainName,                   config_parse_bool,                              0,                             offsetof(Network, dhcp_domains)
+DHCPv4.UseDNS,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
+DHCPv4.UseMTU,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_use_mtu)
+DHCPv4.UseHostname,                     config_parse_bool,                              0,                             offsetof(Network, dhcp_use_hostname)
+DHCP.UseDomainName,                     config_parse_dhcp_use_domains,                  0,                             offsetof(Network, dhcp_use_domains)
+DHCPv4.UseDomainName,                   config_parse_dhcp_use_domains,                  0,                             offsetof(Network, dhcp_use_domains)
 DHCPv4.CriticalConnection,              config_parse_bool,                              0,                             offsetof(Network, dhcp_critical)
index 29723a852fb6d32a951a14803518f81a2cf29a16..431579009336bf3b97951ca4607461c4e1b746f4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -32,6 +30,7 @@
 #include "networkd-network.h"
 #include "networkd.h"
 #include "parse-util.h"
+#include "set.h"
 #include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -104,11 +103,11 @@ static int network_load_one(Manager *manager, const char *filename) {
         *d = '\0';
 
         network->dhcp = ADDRESS_FAMILY_NO;
-        network->dhcp_ntp = true;
-        network->dhcp_dns = true;
-        network->dhcp_hostname = true;
-        network->dhcp_routes = true;
-        network->dhcp_sendhost = true;
+        network->dhcp_use_ntp = true;
+        network->dhcp_use_dns = true;
+        network->dhcp_use_hostname = true;
+        network->dhcp_use_routes = true;
+        network->dhcp_send_hostname = true;
         network->dhcp_route_metric = DHCP_ROUTE_METRIC;
         network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
 
@@ -121,6 +120,8 @@ static int network_load_one(Manager *manager, const char *filename) {
         network->unicast_flood = true;
 
         network->llmnr = RESOLVE_SUPPORT_YES;
+        network->mdns = RESOLVE_SUPPORT_NO;
+        network->dnssec_mode = _DNSSEC_MODE_INVALID;
 
         network->link_local = ADDRESS_FAMILY_IPV6;
 
@@ -224,13 +225,14 @@ void network_free(Network *network) {
 
         free(network->description);
         free(network->dhcp_vendor_class_identifier);
-        free(network->hostname);
+        free(network->dhcp_hostname);
 
         free(network->mac);
 
         strv_free(network->ntp);
         strv_free(network->dns);
-        strv_free(network->domains);
+        strv_free(network->search_domains);
+        strv_free(network->route_domains);
         strv_free(network->bind_carrier);
 
         netdev_unref(network->bridge);
@@ -275,6 +277,8 @@ void network_free(Network *network) {
         free(network->dhcp_server_dns);
         free(network->dhcp_server_ntp);
 
+        set_free_free(network->dnssec_negative_trust_anchors);
+
         free(network);
 }
 
@@ -379,7 +383,10 @@ int network_apply(Manager *manager, Network *network, Link *link) {
                 route->protocol = RTPROT_STATIC;
         }
 
-        if (network->dns || network->ntp || network->domains) {
+        if (!strv_isempty(network->dns) ||
+            !strv_isempty(network->ntp) ||
+            !strv_isempty(network->search_domains) ||
+            !strv_isempty(network->route_domains)) {
                 manager_dirty(manager);
                 link_dirty(link);
         }
@@ -464,49 +471,85 @@ int config_parse_netdev(const char *unit,
         return 0;
 }
 
-int config_parse_domains(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;
-        char ***domains = data;
-        char **domain;
+int config_parse_domains(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        const char *p;
+        Network *n = data;
         int r;
 
-        r = config_parse_strv(unit, filename, line, section, section_line,
-                              lvalue, ltype, rvalue, domains, userdata);
-        if (r < 0)
-                return r;
+        assert(n);
+        assert(lvalue);
+        assert(rvalue);
 
-        strv_uniq(*domains);
-        network->wildcard_domain = !!strv_find(*domains, "*");
+        if (isempty(rvalue)) {
+                n->search_domains = strv_free(n->search_domains);
+                n->route_domains = strv_free(n->route_domains);
+                return 0;
+        }
 
-        STRV_FOREACH(domain, *domains) {
-                if (is_localhost(*domain))
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
-                else {
-                        r = dns_name_is_valid(*domain);
-                        if (r <= 0 && !streq(*domain, "*")) {
-                                if (r < 0)
-                                        log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
-                                if (r == 0)
-                                        log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
-                        } else
+        p = rvalue;
+        for (;;) {
+                _cleanup_free_ char *w = NULL, *normalized = NULL;
+                const char *domain;
+                bool is_route;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
+                        break;
+                }
+                if (r == 0)
+                        break;
+
+                is_route = w[0] == '~';
+                domain = is_route ? w + 1 : w;
+
+                if (dns_name_is_root(domain) || streq(domain, "*")) {
+                        /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
+                         * routing domain, unconditionally. */
+                        is_route = true;
+                        domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
+
+                } else {
+                        r = dns_name_normalize(domain, &normalized);
+                        if (r < 0) {
+                                log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
+                                continue;
+                        }
+
+                        domain = normalized;
+
+                        if (is_localhost(domain)) {
+                                log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
                                 continue;
+                        }
                 }
 
-                strv_remove(*domains, *domain);
+                if (is_route) {
+                        r = strv_extend(&n->route_domains, domain);
+                        if (r < 0)
+                                return log_oom();
 
-                /* We removed one entry, make sure we don't skip the next one */
-                domain--;
+                } else {
+                        r = strv_extend(&n->search_domains, domain);
+                        if (r < 0)
+                                return log_oom();
+                }
         }
 
+        strv_uniq(n->route_domains);
+        strv_uniq(n->search_domains);
+
         return 0;
 }
 
@@ -908,3 +951,65 @@ int config_parse_dhcp_server_ntp(
                 n->dhcp_server_ntp = m;
         }
 }
+
+int config_parse_dnssec_negative_trust_anchors(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        const char *p = rvalue;
+        Network *n = data;
+        int r;
+
+        assert(n);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
+                return 0;
+        }
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
+                        break;
+                }
+                if (r == 0)
+                        break;
+
+                r = dns_name_is_valid(w);
+                if (r <= 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w);
+                        continue;
+                }
+
+                r = set_put(n->dnssec_negative_trust_anchors, w);
+                if (r < 0)
+                        return log_oom();
+                if (r > 0)
+                        w = NULL;
+        }
+
+        return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
+
+static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
+        [DHCP_USE_DOMAINS_NO] = "no",
+        [DHCP_USE_DOMAINS_ROUTE] = "route",
+        [DHCP_USE_DOMAINS_YES] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
index a27c67eea58e7f3bf998af8daf9c163385d3a5dc..03c3f206c3de3eff4774147c1e48d75078891262 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include "condition.h"
+#include "resolve-util.h"
 
 typedef struct Network Network;
 
-#include "networkd.h"
-#include "networkd-netdev.h"
 #include "networkd-address.h"
-#include "networkd-route.h"
 #include "networkd-fdb.h"
+#include "networkd-netdev.h"
+#include "networkd-route.h"
 #include "networkd-util.h"
+#include "networkd.h"
 
 #define DHCP_ROUTE_METRIC 1024
 #define IPV4LL_ROUTE_METRIC 2048
@@ -51,6 +50,14 @@ typedef enum IPv6PrivacyExtensions {
         _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
 } IPv6PrivacyExtensions;
 
+typedef enum DHCPUseDomains {
+        DHCP_USE_DOMAINS_NO,
+        DHCP_USE_DOMAINS_YES,
+        DHCP_USE_DOMAINS_ROUTE,
+        _DHCP_USE_DOMAINS_MAX,
+        _DHCP_USE_DOMAINS_INVALID = -1,
+} DHCPUseDomains;
+
 struct Network {
         Manager *manager;
 
@@ -78,17 +85,17 @@ struct Network {
         AddressFamilyBoolean dhcp;
         DCHPClientIdentifier dhcp_client_identifier;
         char *dhcp_vendor_class_identifier;
-        char *hostname;
-        bool dhcp_dns;
-        bool dhcp_ntp;
-        bool dhcp_mtu;
-        bool dhcp_hostname;
-        bool dhcp_domains;
-        bool dhcp_sendhost;
+        char *dhcp_hostname;
+        bool dhcp_use_dns;
+        bool dhcp_use_ntp;
+        bool dhcp_use_mtu;
+        bool dhcp_use_hostname;
+        DHCPUseDomains dhcp_use_domains;
+        bool dhcp_send_hostname;
         bool dhcp_broadcast;
         bool dhcp_critical;
-        bool dhcp_routes;
-        bool dhcp_timezone;
+        bool dhcp_use_routes;
+        bool dhcp_use_timezone;
         unsigned dhcp_route_metric;
 
         /* DHCP Server Support */
@@ -140,10 +147,12 @@ struct Network {
         Hashmap *routes_by_section;
         Hashmap *fdb_entries_by_section;
 
-        bool wildcard_domain;
-        char **domains, **dns, **ntp, **bind_carrier;
+        char **search_domains, **route_domains, **dns, **ntp, **bind_carrier;
 
         ResolveSupport llmnr;
+        ResolveSupport mdns;
+        DnssecMode dnssec_mode;
+        Set *dnssec_negative_trust_anchors;
 
         LIST_FIELDS(Network, networks);
 };
@@ -170,6 +179,8 @@ int config_parse_hostname(const char *unit, const char *filename, unsigned line,
 int config_parse_timezone(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_dhcp_server_dns(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_dhcp_server_ntp(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_dnssec_negative_trust_anchors(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_dhcp_use_domains(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);
 
 /* Legacy IPv4LL support */
 int config_parse_ipv4ll(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);
@@ -183,3 +194,6 @@ int network_object_find(sd_bus *bus, const char *path, const char *interface, vo
 
 const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
 IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
+
+const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
+DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
index ed06c21160b5ea89e19094b0043994883fb9793b..e065a5a5a9ef94c28b352f7479faafe6f5822508 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,7 +19,6 @@
 
 #include "alloc-util.h"
 #include "conf-parser.h"
-#include "event-util.h"
 #include "in-addr-util.h"
 #include "netlink-util.h"
 #include "networkd-route.h"
@@ -334,7 +331,7 @@ void route_drop(Route *route) {
 
 int route_remove(Route *route, Link *link,
                sd_netlink_message_handler_t callback) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
         assert(link);
@@ -429,8 +426,8 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
 
 int route_configure(Route *route, Link *link,
                     sd_netlink_message_handler_t callback) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
-        _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
         usec_t lifetime;
         int r;
 
index b2767566745c47dc226abe0d67bfb57c03e898b8..a4a4bf265377b9c822c986dcd4f6becb04a2fc0a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,8 +21,8 @@
 
 typedef struct Route Route;
 
-#include "networkd.h"
 #include "networkd-network.h"
+#include "networkd.h"
 
 struct Route {
         Network *network;
index 2545621a93d448c17a955eb2d24e8fe107c6b039..555a7c68a19f4acd60b4ba6fd27912f743afb7e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -101,54 +99,3 @@ int config_parse_address_family_boolean_with_kernel(
 
         return 0;
 }
-
-static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
-        [RESOLVE_SUPPORT_NO] = "no",
-        [RESOLVE_SUPPORT_YES] = "yes",
-        [RESOLVE_SUPPORT_RESOLVE] = "resolve",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
-
-int config_parse_resolve(
-                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) {
-
-        ResolveSupport *resolve = data;
-        int k;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(resolve);
-
-        /* Our enum shall be a superset of booleans, hence first try
-         * to parse as boolean, and then as enum */
-
-        k = parse_boolean(rvalue);
-        if (k > 0)
-                *resolve = RESOLVE_SUPPORT_YES;
-        else if (k == 0)
-                *resolve = RESOLVE_SUPPORT_NO;
-        else {
-                ResolveSupport s;
-
-                s = resolve_support_from_string(rvalue);
-                if (s < 0){
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue);
-                        return 0;
-                }
-
-                *resolve = s;
-        }
-
-        return 0;
-}
index cc41aae85ae038006b3df12a4c1dfcb5f7a16b62..d5c385bea4a8dd47d70ba15229e8997216df3d6a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -33,20 +31,8 @@ typedef enum AddressFamilyBoolean {
         _ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
 } AddressFamilyBoolean;
 
-typedef enum ResolveSupport {
-        RESOLVE_SUPPORT_NO,
-        RESOLVE_SUPPORT_YES,
-        RESOLVE_SUPPORT_RESOLVE,
-        _RESOLVE_SUPPORT_MAX,
-        _RESOLVE_SUPPORT_INVALID = -1,
-} ResolveSupport;
-
-int config_parse_resolve(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_family_boolean(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_family_boolean_with_kernel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 
-const char* resolve_support_to_string(ResolveSupport i) _const_;
-ResolveSupport resolve_support_from_string(const char *s) _pure_;
-
 const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
 AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
index c2779ff773e42c5757b3a6cc374647ca572685fe..5727422e3d26ed819a6ed2d471d86efe9d11a93a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 068196622e925deec48e6e14ba3ec1b73ae9b783..dc35085c55d99bf11a2f9ccff962cae57edcf60b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 0c40ab2bb8ae3fda778da480fd45a293e29b0141..2ff7ddb04420f33307bde943b4f0d3cb26108dd6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -175,7 +173,7 @@ static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdat
 }
 
 static int manager_rtnl_listen(Manager *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *i;
         int r;
 
index 627c46be13b7d3895263afc044e3800d915c5df5..421c2bdf447b3b5f266dff9f3499334793c3b3ce 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ef394e0c04570c7518b51aaa884e67e9ec3fdf05..3a2615e6fde7370329bff05047480ab0933947ec 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 97665fac7aa4e2fc4e108268fef09e44d5d6e85c..7ee922621a6d9e879c5a1b76767da0a2e384c87e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <arpa/inet.h>
 
+#include "sd-bus.h"
 #include "sd-event.h"
 #include "sd-netlink.h"
-#include "sd-bus.h"
-#include "udev.h"
 
 #include "hashmap.h"
 #include "list.h"
+#include "udev.h"
 
 typedef struct Manager Manager;
 
-#include "networkd-network.h"
 #include "networkd-address-pool.h"
 #include "networkd-link.h"
+#include "networkd-network.h"
 #include "networkd-util.h"
 
 struct Manager {
index a1a77b68677dbdaea46de7c2779d218727a033ac..855646173f61554a1402bb19f926add3e30c29f4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index b1445547023a027b811162d9e0c3922ef4b836e0..49f97c61d983d65e044eaef7f3c7a5d2c9687a63 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 270bcf010fcfa46be24af468a1791818188b3af8..1db5ba71163350c6263542398ce81ccd0fb8e944 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -54,6 +52,7 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) {
                        "tasks",
                        "notify_on_release",
                        "cgroup.procs",
+                       "cgroup.events",
                        "cgroup.clone_children",
                        "cgroup.controllers",
                        "cgroup.subtree_control",
index 985fdfaad53425e99f6bceffbd36c1eb6514fe95..1ff35a299a4ac8481f1ce6c0efb6cba2cf79d863 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 int chown_cgroup(pid_t pid, uid_t uid_shift);
 int sync_cgroup(pid_t pid, bool unified_requested);
index 38245434da8bd202451cae65573a691d119596d6..86124b8779948c784a24125de3786f93831102f9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -211,7 +209,7 @@ int expose_port_watch_rtnl(
                 sd_netlink_message_handler_t handler,
                 union in_addr_union *exposed,
                 sd_netlink **ret) {
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         int fd, r;
 
         assert(event);
index 39cec286955e0e219ef7c9a24b356f1919735320..741ad9765c284cf189f03554ab9aa607b747a75d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,8 +23,9 @@
 
 #include "sd-event.h"
 #include "sd-netlink.h"
-#include "list.h"
+
 #include "in-addr-util.h"
+#include "list.h"
 
 typedef struct ExposePort {
         int protocol;
index 58f9f4c63544a2c9dcbc6570683507b325037cc4..116655cdd25377ed3577be4c2edf7c8b5a630f93 100644 (file)
@@ -15,7 +15,8 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Exec.Boot,                    config_parse_tristate,      0, offsetof(Settings, boot)
+Exec.Boot,                    config_parse_boot,          0, 0
+Exec.ProcessTwo,              config_parse_pid2,          0, 0,
 Exec.Parameters,              config_parse_strv,          0, offsetof(Settings, parameters)
 Exec.Environment,             config_parse_strv,          0, offsetof(Settings, environment)
 Exec.User,                    config_parse_string,        0, offsetof(Settings, user)
@@ -24,6 +25,7 @@ Exec.DropCapability,          config_parse_capability,    0, offsetof(Settings,
 Exec.KillSignal,              config_parse_signal,        0, offsetof(Settings, kill_signal)
 Exec.Personality,             config_parse_personality,   0, offsetof(Settings, personality)
 Exec.MachineID,               config_parse_id128,         0, offsetof(Settings, machine_id)
+Exec.WorkingDirectory,        config_parse_path,          0, offsetof(Settings, working_directory)
 Files.ReadOnly,               config_parse_tristate,      0, offsetof(Settings, read_only)
 Files.Volatile,               config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
 Files.Bind,                   config_parse_bind,          0, 0
index c8e627ac78b41fba114f43ce53c969503cdf903d..70cca1527876850731528adc74b6a85e8a45ffca 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index bdab23bcca2476ffeeeb3d18692df6046a178bb5..0daf145412bf0fceb4f04e0fe5d32f3929203206 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8f74c41c71a4fd8c93fbe0b8dc7942d233b8d662..fcb1efaa740e7a267a384f1bb3007f3c1028932f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -94,7 +92,7 @@ static int add_veth(
                 const char *ifname_container,
                 const struct ether_addr *mac_container) {
 
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
         int r;
 
         assert(rtnl);
@@ -163,7 +161,7 @@ int setup_veth(const char *machine_name,
                char iface_name[IFNAMSIZ],
                bool bridge) {
 
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         struct ether_addr mac_host, mac_container;
         int r, i;
 
@@ -204,7 +202,7 @@ int setup_veth_extra(
                 pid_t pid,
                 char **pairs) {
 
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         uint64_t idx = 0;
         char **a, **b;
         int r;
@@ -241,8 +239,8 @@ int setup_veth_extra(
 }
 
 int setup_bridge(const char *veth_name, const char *bridge_name) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         int r, bridge_ifi;
 
         assert(veth_name);
@@ -303,7 +301,7 @@ static int parse_interface(struct udev *udev, const char *name) {
 
 int move_network_interfaces(pid_t pid, char **ifaces) {
         _cleanup_udev_unref_ struct udev *udev = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         char **i;
         int r;
 
@@ -321,7 +319,7 @@ int move_network_interfaces(pid_t pid, char **ifaces) {
         }
 
         STRV_FOREACH(i, ifaces) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
                 int ifi;
 
                 ifi = parse_interface(udev, *i);
@@ -346,7 +344,7 @@ int move_network_interfaces(pid_t pid, char **ifaces) {
 
 int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
         _cleanup_udev_unref_ struct udev *udev = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         unsigned idx = 0;
         char **i;
         int r;
@@ -365,7 +363,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
         }
 
         STRV_FOREACH(i, ifaces) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
                 _cleanup_free_ char *n = NULL;
                 struct ether_addr mac;
                 int ifi;
@@ -434,7 +432,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
 
 int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
         _cleanup_udev_unref_ struct udev *udev = NULL;
-        _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         char **i;
         int r;
 
@@ -452,7 +450,7 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
         }
 
         STRV_FOREACH(i, ifaces) {
-                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+                _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
                 _cleanup_free_ char *n = NULL;
                 int ifi;
 
index b86effef47cb14e9b076ae47946227572100da2a..9ab1606d1c5a8ae67c54eb4ffd24b4a400eb5522 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,9 +20,8 @@
 ***/
 
 #include <net/if.h>
-
-#include <sys/types.h>
 #include <stdbool.h>
+#include <sys/types.h>
 
 int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
 int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
index 50871464c52ccca5e3b9061ccaf87ff5d4fdf4c6..760861089d2dcc3fffdd8c6ea7afd4d880788044 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -42,8 +40,8 @@ int register_machine(
                 bool keep_unit,
                 const char *service) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         r = sd_bus_default_system(&bus);
@@ -68,7 +66,7 @@ int register_machine(
                                 strempty(directory),
                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
         } else {
-                _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
                 char **i;
                 unsigned j;
 
@@ -105,10 +103,6 @@ int register_machine(
                                 return bus_log_create_error(r);
                 }
 
-                r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
                 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
                 if (r < 0)
                         return bus_log_create_error(r);
@@ -170,17 +164,9 @@ int register_machine(
                 }
 
                 STRV_FOREACH(i, properties) {
-                        r = sd_bus_message_open_container(m, 'r', "sv");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
                         r = bus_append_unit_property_assignment(m, *i);
                         if (r < 0)
                                 return r;
-
-                        r = sd_bus_message_close_container(m);
-                        if (r < 0)
-                                return bus_log_create_error(r);
                 }
 
                 r = sd_bus_message_close_container(m);
@@ -199,9 +185,9 @@ int register_machine(
 }
 
 int terminate_machine(pid_t pid) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *path;
         int r;
 
index d3bfd84e5e98986e7e4e810b5fce30e3b8e40b3d..304c5a485b2fbfb1fa8960691d82bb10b470e6d6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d6b64d8d5a05c4edf2c471dccb5a7204654c5959..4fb005469813e4ca956265a0c81709be6950e7a9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -24,6 +22,7 @@
 #include "conf-parser.h"
 #include "nspawn-network.h"
 #include "nspawn-settings.h"
+#include "parse-util.h"
 #include "process-util.h"
 #include "strv.h"
 #include "util.h"
@@ -39,7 +38,7 @@ int settings_load(FILE *f, const char *path, Settings **ret) {
         if (!s)
                 return -ENOMEM;
 
-        s->boot = -1;
+        s->start_mode = _START_MODE_INVALID;
         s->personality = PERSONALITY_INVALID;
 
         s->read_only = -1;
@@ -74,6 +73,7 @@ Settings* settings_free(Settings *s) {
         strv_free(s->parameters);
         strv_free(s->environment);
         free(s->user);
+        free(s->working_directory);
 
         strv_free(s->network_interfaces);
         strv_free(s->network_macvlan);
@@ -302,3 +302,93 @@ int config_parse_veth_extra(
 
         return 0;
 }
+
+int config_parse_boot(
+                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) {
+
+        Settings *settings = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue);
+                return 0;
+        }
+
+        if (r > 0) {
+                if (settings->start_mode == START_PID2)
+                        goto conflict;
+
+                settings->start_mode = START_BOOT;
+        } else {
+                if (settings->start_mode == START_BOOT)
+                        goto conflict;
+
+                if (settings->start_mode < 0)
+                        settings->start_mode = START_PID1;
+        }
+
+        return 0;
+
+conflict:
+        log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
+        return 0;
+}
+
+int config_parse_pid2(
+                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) {
+
+        Settings *settings = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue);
+                return 0;
+        }
+
+        if (r > 0) {
+                if (settings->start_mode == START_BOOT)
+                        goto conflict;
+
+                settings->start_mode = START_PID2;
+        } else {
+                if (settings->start_mode == START_PID2)
+                        goto conflict;
+
+                if (settings->start_mode < 0)
+                        settings->start_mode = START_PID1;
+        }
+
+        return 0;
+
+conflict:
+        log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring.");
+        return 0;
+}
index dde0d8bd450fa1a1630bd0b612654a7b359e4cd4..a017405cd9816a678e4f6838319257c8b6a1c4d8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <stdio.h>
 
 #include "macro.h"
-
-#include "nspawn-mount.h"
 #include "nspawn-expose-ports.h"
+#include "nspawn-mount.h"
+
+typedef enum StartMode {
+        START_PID1, /* Run parameters as command line as process 1 */
+        START_PID2, /* Use stub init process as PID 1, run parameters as command line as process 2 */
+        START_BOOT, /* Search for init system, pass arguments as parameters */
+        _START_MODE_MAX,
+        _START_MODE_INVALID = -1
+} StartMode;
 
 typedef enum SettingsMask {
-        SETTING_BOOT          = 1 << 0,
-        SETTING_ENVIRONMENT   = 1 << 1,
-        SETTING_USER          = 1 << 2,
-        SETTING_CAPABILITY    = 1 << 3,
-        SETTING_KILL_SIGNAL   = 1 << 4,
-        SETTING_PERSONALITY   = 1 << 5,
-        SETTING_MACHINE_ID    = 1 << 6,
-        SETTING_NETWORK       = 1 << 7,
-        SETTING_EXPOSE_PORTS  = 1 << 8,
-        SETTING_READ_ONLY     = 1 << 9,
-        SETTING_VOLATILE_MODE = 1 << 10,
-        SETTING_CUSTOM_MOUNTS = 1 << 11,
-        _SETTINGS_MASK_ALL    = (1 << 12) -1
+        SETTING_START_MODE        = 1 << 0,
+        SETTING_ENVIRONMENT       = 1 << 1,
+        SETTING_USER              = 1 << 2,
+        SETTING_CAPABILITY        = 1 << 3,
+        SETTING_KILL_SIGNAL       = 1 << 4,
+        SETTING_PERSONALITY       = 1 << 5,
+        SETTING_MACHINE_ID        = 1 << 6,
+        SETTING_NETWORK           = 1 << 7,
+        SETTING_EXPOSE_PORTS      = 1 << 8,
+        SETTING_READ_ONLY         = 1 << 9,
+        SETTING_VOLATILE_MODE     = 1 << 10,
+        SETTING_CUSTOM_MOUNTS     = 1 << 11,
+        SETTING_WORKING_DIRECTORY = 1 << 12,
+        _SETTINGS_MASK_ALL        = (1 << 13) -1
 } SettingsMask;
 
 typedef struct Settings {
         /* [Run] */
-        int boot;
+        StartMode start_mode;
         char **parameters;
         char **environment;
         char *user;
@@ -55,6 +61,7 @@ typedef struct Settings {
         int kill_signal;
         unsigned long personality;
         sd_id128_t machine_id;
+        char *working_directory;
 
         /* [Image] */
         int read_only;
@@ -90,3 +97,5 @@ int config_parse_volatile_mode(const char *unit, const char *filename, unsigned
 int config_parse_bind(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_tmpfs(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_veth_extra(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_boot(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_pid2(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 aa6a16309c988d416c7610c9678dc09a114ac7af..ee15a47e93e6afb24992d4f026691919f5388a6e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -261,10 +259,10 @@ int change_uid_gid(const char *user, char **_home) {
                 return log_error_errno(errno, "Failed to set auxiliary groups: %m");
 
         if (setresgid(gid, gid, gid) < 0)
-                return log_error_errno(errno, "setregid() failed: %m");
+                return log_error_errno(errno, "setresgid() failed: %m");
 
         if (setresuid(uid, uid, uid) < 0)
-                return log_error_errno(errno, "setreuid() failed: %m");
+                return log_error_errno(errno, "setresuid() failed: %m");
 
         if (_home) {
                 *_home = home;
index 33be44a946bfb694475bc79517f74a8af35900a1..b4968ba1fcbad51b9747a4436d71d5ae7da6e658 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c
new file mode 100644 (file)
index 0000000..2de87e3
--- /dev/null
@@ -0,0 +1,170 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 <sys/reboot.h>
+#include <sys/unistd.h>
+#include <sys/wait.h>
+
+#include "fd-util.h"
+#include "log.h"
+#include "nspawn-stub-pid1.h"
+#include "process-util.h"
+#include "signal-util.h"
+#include "time-util.h"
+#include "def.h"
+
+int stub_pid1(void) {
+        enum {
+                STATE_RUNNING,
+                STATE_REBOOT,
+                STATE_POWEROFF,
+        } state = STATE_RUNNING;
+
+        sigset_t fullmask, oldmask, waitmask;
+        usec_t quit_usec = USEC_INFINITY;
+        pid_t pid;
+        int r;
+
+        /* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
+         * for allowing arbitrary processes run in a container, and still have all zombies reaped. */
+
+        assert_se(sigfillset(&fullmask) >= 0);
+        assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);
+
+        pid = fork();
+        if (pid < 0)
+                return log_error_errno(errno, "Failed to fork child pid: %m");
+
+        if (pid == 0) {
+                /* Return in the child */
+                assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
+                setsid();
+                return 0;
+        }
+
+        reset_all_signal_handlers();
+
+        log_close();
+        close_all_fds(NULL, 0);
+        log_open();
+
+        rename_process("STUBINIT");
+
+        assert_se(sigemptyset(&waitmask) >= 0);
+        assert_se(sigset_add_many(&waitmask,
+                                  SIGCHLD,          /* posix: process died */
+                                  SIGINT,           /* sysv: ctrl-alt-del */
+                                  SIGRTMIN+3,       /* systemd: halt */
+                                  SIGRTMIN+4,       /* systemd: poweroff */
+                                  SIGRTMIN+5,       /* systemd: reboot */
+                                  SIGRTMIN+6,       /* systemd: kexec */
+                                  SIGRTMIN+13,      /* systemd: halt */
+                                  SIGRTMIN+14,      /* systemd: poweroff */
+                                  SIGRTMIN+15,      /* systemd: reboot */
+                                  SIGRTMIN+16,      /* systemd: kexec */
+                                  -1) >= 0);
+
+        /* Note that we ignore SIGTERM (sysv's reexec), SIGHUP (reload), and all other signals here, since we don't
+         * support reexec/reloading in this stub process. */
+
+        for (;;) {
+                siginfo_t si;
+                usec_t current_usec;
+
+                si.si_pid = 0;
+                r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG);
+                if (r < 0) {
+                        r = log_error_errno(errno, "Failed to reap children: %m");
+                        goto finish;
+                }
+
+                current_usec = now(CLOCK_MONOTONIC);
+
+                if (si.si_pid == pid || current_usec >= quit_usec) {
+
+                        /* The child we started ourselves died or we reached a timeout. */
+
+                        if (state == STATE_REBOOT) { /* dispatch a queued reboot */
+                                (void) reboot(RB_AUTOBOOT);
+                                r = log_error_errno(errno, "Failed to reboot: %m");
+                                goto finish;
+
+                        } else if (state == STATE_POWEROFF)
+                                (void) reboot(RB_POWER_OFF); /* if this fails, fall back to normal exit. */
+
+                        if (si.si_pid == pid && si.si_code == CLD_EXITED)
+                                r = si.si_status; /* pass on exit code */
+                        else
+                                r = 255; /* signal, coredump, timeout, … */
+
+                        goto finish;
+                }
+                if (si.si_pid != 0)
+                        /* We reaped something. Retry until there's nothing more to reap. */
+                        continue;
+
+                if (quit_usec == USEC_INFINITY)
+                        r = sigwaitinfo(&waitmask, &si);
+                else {
+                        struct timespec ts;
+                        r = sigtimedwait(&waitmask, &si, timespec_store(&ts, quit_usec - current_usec));
+                }
+                if (r < 0) {
+                        if (errno == EINTR) /* strace -p attach can result in EINTR, let's handle this nicely. */
+                                continue;
+                        if (errno == EAGAIN) /* timeout reached */
+                                continue;
+
+                        r = log_error_errno(errno, "Failed to wait for signal: %m");
+                        goto finish;
+                }
+
+                if (si.si_signo == SIGCHLD)
+                        continue; /* Let's reap this */
+
+                if (state != STATE_RUNNING)
+                        continue;
+
+                /* Would love to use a switch() statement here, but SIGRTMIN is actually a function call, not a
+                 * constant… */
+
+                if (si.si_signo == SIGRTMIN+3 ||
+                    si.si_signo == SIGRTMIN+4 ||
+                    si.si_signo == SIGRTMIN+13 ||
+                    si.si_signo == SIGRTMIN+14)
+
+                        state = STATE_POWEROFF;
+
+                else if (si.si_signo == SIGINT ||
+                         si.si_signo == SIGRTMIN+5 ||
+                         si.si_signo == SIGRTMIN+6 ||
+                         si.si_signo == SIGRTMIN+15 ||
+                         si.si_signo == SIGRTMIN+16)
+
+                        state = STATE_REBOOT;
+                else
+                        assert_not_reached("Got unexpected signal");
+
+                /* (void) kill_and_sigcont(pid, SIGTERM); */
+                quit_usec = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
+        }
+
+finish:
+        _exit(r < 0 ? EXIT_FAILURE : r);
+}
diff --git a/src/nspawn/nspawn-stub-pid1.h b/src/nspawn/nspawn-stub-pid1.h
new file mode 100644 (file)
index 0000000..36c1aaf
--- /dev/null
@@ -0,0 +1,22 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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/>.
+***/
+
+int stub_pid1(void);
index f6a2c0386e645a65ebbb3fcf5184ad0cc4347cdb..ef348c335b71c4991a27d1c0ea5c843c216ccc9b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -57,7 +55,6 @@
 #include "copy.h"
 #include "dev-setup.h"
 #include "env-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "fdset.h"
 #include "fileio.h"
@@ -80,6 +77,7 @@
 #include "nspawn-register.h"
 #include "nspawn-settings.h"
 #include "nspawn-setuid.h"
+#include "nspawn-stub-pid1.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
@@ -115,6 +113,7 @@ typedef enum LinkJournal {
 
 static char *arg_directory = NULL;
 static char *arg_template = NULL;
+static char *arg_chdir = NULL;
 static char *arg_user = NULL;
 static sd_id128_t arg_uuid = {};
 static char *arg_machine = NULL;
@@ -123,7 +122,7 @@ static const char *arg_selinux_apifs_context = NULL;
 static const char *arg_slice = NULL;
 static bool arg_private_network = false;
 static bool arg_read_only = false;
-static bool arg_boot = false;
+static StartMode arg_start_mode = START_PID1;
 static bool arg_ephemeral = false;
 static LinkJournal arg_link_journal = LINK_AUTO;
 static bool arg_link_journal_try = false;
@@ -193,7 +192,9 @@ static void help(void) {
                "  -x --ephemeral            Run container with snapshot of root directory, and\n"
                "                            remove it after exit\n"
                "  -i --image=PATH           File system device or disk image for the container\n"
+               "  -a --as-pid2              Maintain a stub init as PID1, invoke binary as PID2\n"
                "  -b --boot                 Boot up full system (i.e. invoke init)\n"
+               "     --chdir=PATH           Set working directory in the container\n"
                "  -u --user=USER            Run the command under specified user or uid\n"
                "  -M --machine=NAME         Set the machine name for the container\n"
                "     --uuid=UUID            Set a specific machine UUID for the container\n"
@@ -232,8 +233,8 @@ static void help(void) {
                "                            capability\n"
                "     --drop-capability=CAP  Drop the specified capability from the default set\n"
                "     --kill-signal=SIGNAL   Select signal to use for shutting down PID 1\n"
-               "     --link-journal=MODE    Link up guest journal, one of no, auto, guest, host,\n"
-               "                            try-guest, try-host\n"
+               "     --link-journal=MODE    Link up guest journal, one of no, auto, guest, \n"
+               "                            host, try-guest, try-host\n"
                "  -j                        Equivalent to --link-journal=try-guest\n"
                "     --read-only            Mount the root directory read-only\n"
                "     --bind=PATH[:PATH[:OPTIONS]]\n"
@@ -346,6 +347,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_PRIVATE_USERS,
                 ARG_KILL_SIGNAL,
                 ARG_SETTINGS,
+                ARG_CHDIR,
         };
 
         static const struct option options[] = {
@@ -356,6 +358,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "ephemeral",             no_argument,       NULL, 'x'                   },
                 { "user",                  required_argument, NULL, 'u'                   },
                 { "private-network",       no_argument,       NULL, ARG_PRIVATE_NETWORK   },
+                { "as-pid2",               no_argument,       NULL, 'a'                   },
                 { "boot",                  no_argument,       NULL, 'b'                   },
                 { "uuid",                  required_argument, NULL, ARG_UUID              },
                 { "read-only",             no_argument,       NULL, ARG_READ_ONLY         },
@@ -390,6 +393,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "private-users",         optional_argument, NULL, ARG_PRIVATE_USERS     },
                 { "kill-signal",           required_argument, NULL, ARG_KILL_SIGNAL       },
                 { "settings",              required_argument, NULL, ARG_SETTINGS          },
+                { "chdir",                 required_argument, NULL, ARG_CHDIR             },
                 {}
         };
 
@@ -401,7 +405,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "+hD:u:bL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:n", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -492,8 +496,23 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'b':
-                        arg_boot = true;
-                        arg_settings_mask |= SETTING_BOOT;
+                        if (arg_start_mode == START_PID2) {
+                                log_error("--boot and --as-pid2 may not be combined.");
+                                return -EINVAL;
+                        }
+
+                        arg_start_mode = START_BOOT;
+                        arg_settings_mask |= SETTING_START_MODE;
+                        break;
+
+                case 'a':
+                        if (arg_start_mode == START_BOOT) {
+                                log_error("--boot and --as-pid2 may not be combined.");
+                                return -EINVAL;
+                        }
+
+                        arg_start_mode = START_PID2;
+                        arg_settings_mask |= SETTING_START_MODE;
                         break;
 
                 case ARG_UUID:
@@ -850,6 +869,19 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_CHDIR:
+                        if (!path_is_absolute(optarg)) {
+                                log_error("Working directory %s is not an absolute path.", optarg);
+                                return -EINVAL;
+                        }
+
+                        r = free_and_strdup(&arg_chdir, optarg);
+                        if (r < 0)
+                                return log_oom();
+
+                        arg_settings_mask |= SETTING_WORKING_DIRECTORY;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -860,7 +892,7 @@ static int parse_argv(int argc, char *argv[]) {
         if (arg_share_system)
                 arg_register = false;
 
-        if (arg_boot && arg_share_system) {
+        if (arg_start_mode != START_PID1 && arg_share_system) {
                 log_error("--boot and --share-system may not be combined.");
                 return -EINVAL;
         }
@@ -908,7 +940,7 @@ static int parse_argv(int argc, char *argv[]) {
                 if (!arg_parameters)
                         return log_oom();
 
-                arg_settings_mask |= SETTING_BOOT;
+                arg_settings_mask |= SETTING_START_MODE;
         }
 
         /* Load all settings from .nspawn files */
@@ -944,7 +976,7 @@ static int verify_arguments(void) {
                 return -EINVAL;
         }
 
-        if (arg_boot && arg_kill_signal <= 0)
+        if (arg_start_mode == START_BOOT && arg_kill_signal <= 0)
                 arg_kill_signal = SIGRTMIN+3;
 
         return 0;
@@ -1028,7 +1060,7 @@ static int setup_timezone(const char *dest) {
         }
 
         check = strjoina("/usr/share/zoneinfo/", z);
-        check = prefix_root(dest, check);
+        check = prefix_roota(dest, check);
         if (laccess(check, F_OK) < 0) {
                 log_warning("Timezone %s does not exist in container, not updating container timezone.", z);
                 return 0;
@@ -1338,6 +1370,7 @@ static int setup_journal(const char *directory) {
         sd_id128_t machine_id, this_id;
         _cleanup_free_ char *b = NULL, *d = NULL;
         const char *etc_machine_id, *p, *q;
+        bool try;
         char *id;
         int r;
 
@@ -1345,16 +1378,21 @@ static int setup_journal(const char *directory) {
         if (arg_ephemeral)
                 return 0;
 
+        if (arg_link_journal == LINK_NO)
+                return 0;
+
+        try = arg_link_journal_try || arg_link_journal == LINK_AUTO;
+
         etc_machine_id = prefix_roota(directory, "/etc/machine-id");
 
         r = read_one_line_file(etc_machine_id, &b);
-        if (r == -ENOENT && arg_link_journal == LINK_AUTO)
+        if (r == -ENOENT && try)
                 return 0;
         else if (r < 0)
                 return log_error_errno(r, "Failed to read machine ID from %s: %m", etc_machine_id);
 
         id = strstrip(b);
-        if (isempty(id) && arg_link_journal == LINK_AUTO)
+        if (isempty(id) && try)
                 return 0;
 
         /* Verify validity */
@@ -1367,16 +1405,13 @@ static int setup_journal(const char *directory) {
                 return log_error_errno(r, "Failed to retrieve machine ID: %m");
 
         if (sd_id128_equal(machine_id, this_id)) {
-                log_full(arg_link_journal == LINK_AUTO ? LOG_WARNING : LOG_ERR,
+                log_full(try ? LOG_WARNING : LOG_ERR,
                          "Host and machine ids are equal (%s): refusing to link journals", id);
-                if (arg_link_journal == LINK_AUTO)
+                if (try)
                         return 0;
                 return -EEXIST;
         }
 
-        if (arg_link_journal == LINK_NO)
-                return 0;
-
         r = userns_mkdir(directory, "/var", 0755, 0, 0);
         if (r < 0)
                 return log_error_errno(r, "Failed to create /var: %m");
@@ -1393,21 +1428,19 @@ static int setup_journal(const char *directory) {
         q = prefix_roota(directory, p);
 
         if (path_is_mount_point(p, 0) > 0) {
-                if (arg_link_journal != LINK_AUTO) {
-                        log_error("%s: already a mount point, refusing to use for journal", p);
-                        return -EEXIST;
-                }
+                if (try)
+                        return 0;
 
-                return 0;
+                log_error("%s: already a mount point, refusing to use for journal", p);
+                return -EEXIST;
         }
 
         if (path_is_mount_point(q, 0) > 0) {
-                if (arg_link_journal != LINK_AUTO) {
-                        log_error("%s: already a mount point, refusing to use for journal", q);
-                        return -EEXIST;
-                }
+                if (try)
+                        return 0;
 
-                return 0;
+                log_error("%s: already a mount point, refusing to use for journal", q);
+                return -EEXIST;
         }
 
         r = readlink_and_make_absolute(p, &d);
@@ -1441,7 +1474,7 @@ static int setup_journal(const char *directory) {
         if (arg_link_journal == LINK_GUEST) {
 
                 if (symlink(q, p) < 0) {
-                        if (arg_link_journal_try) {
+                        if (try) {
                                 log_debug_errno(errno, "Failed to symlink %s to %s, skipping journal setup: %m", q, p);
                                 return 0;
                         } else
@@ -1457,9 +1490,9 @@ static int setup_journal(const char *directory) {
         if (arg_link_journal == LINK_HOST) {
                 /* don't create parents here -- if the host doesn't have
                  * permanent journal set up, don't force it here */
-                r = mkdir(p, 0755);
-                if (r < 0) {
-                        if (arg_link_journal_try) {
+
+                if (mkdir(p, 0755) < 0 && errno != EEXIST) {
+                        if (try) {
                                 log_debug_errno(errno, "Failed to create %s, skipping journal setup: %m", p);
                                 return 0;
                         } else
@@ -1483,7 +1516,7 @@ static int setup_journal(const char *directory) {
 }
 
 static int drop_capabilities(void) {
-        return capability_bounding_set_drop(~arg_retain, false);
+        return capability_bounding_set_drop(arg_retain, false);
 }
 
 static int reset_audit_loginuid(void) {
@@ -2563,6 +2596,16 @@ static int inner_child(
                 return -ESRCH;
         }
 
+        if (arg_chdir)
+                if (chdir(arg_chdir) < 0)
+                        return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir);
+
+        if (arg_start_mode == START_PID2) {
+                r = stub_pid1();
+                if (r < 0)
+                        return r;
+        }
+
         /* Now, explicitly close the log, so that we
          * then can close all remaining fds. Closing
          * the log explicitly first has the benefit
@@ -2574,7 +2617,7 @@ static int inner_child(
         log_close();
         (void) fdset_close_others(fds);
 
-        if (arg_boot) {
+        if (arg_start_mode == START_BOOT) {
                 char **a;
                 size_t m;
 
@@ -2598,7 +2641,9 @@ static int inner_child(
         } else if (!strv_isempty(arg_parameters))
                 execvpe(arg_parameters[0], arg_parameters, env_use);
         else {
-                chdir(home ?: "/root");
+                if (!arg_chdir)
+                        chdir(home ?: "/root");
+
                 execle("/bin/bash", "-bash", NULL, env_use);
                 execle("/bin/sh", "-sh", NULL, env_use);
         }
@@ -2894,15 +2939,22 @@ static int load_settings(void) {
         /* Copy over bits from the settings, unless they have been
          * explicitly masked by command line switches. */
 
-        if ((arg_settings_mask & SETTING_BOOT) == 0 &&
-            settings->boot >= 0) {
-                arg_boot = settings->boot;
+        if ((arg_settings_mask & SETTING_START_MODE) == 0 &&
+            settings->start_mode >= 0) {
+                arg_start_mode = settings->start_mode;
 
                 strv_free(arg_parameters);
                 arg_parameters = settings->parameters;
                 settings->parameters = NULL;
         }
 
+        if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 &&
+            settings->working_directory) {
+                free(arg_chdir);
+                arg_chdir = settings->working_directory;
+                settings->working_directory = NULL;
+        }
+
         if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 &&
             settings->environment) {
                 strv_free(arg_setenv);
@@ -3044,6 +3096,10 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
+        /* Make sure rename_process() in the stub init process can work */
+        saved_argv = argv;
+        saved_argc = argc;
+
         r = parse_argv(argc, argv);
         if (r <= 0)
                 goto finish;
@@ -3150,7 +3206,7 @@ int main(int argc, char *argv[]) {
                         }
                 }
 
-                if (arg_boot) {
+                if (arg_start_mode == START_BOOT) {
                         if (path_is_os_tree(arg_directory) <= 0) {
                                 log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory);
                                 r = -EINVAL;
@@ -3259,9 +3315,9 @@ int main(int argc, char *argv[]) {
                 };
                 int ifi = 0;
                 ssize_t l;
-                _cleanup_event_unref_ sd_event *event = NULL;
+                _cleanup_(sd_event_unrefp) sd_event *event = NULL;
                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
-                _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+                _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
                 char last_char = 0;
 
                 r = barrier_create(&barrier);
@@ -3629,6 +3685,7 @@ finish:
         free(arg_image);
         free(arg_machine);
         free(arg_user);
+        free(arg_chdir);
         strv_free(arg_setenv);
         free(arg_network_bridge);
         strv_free(arg_network_interfaces);
index ee10b105eab86f364d61e5020fab788232b9e660..2536ad2898c440f5b696278816fdfa39be8e37bb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -31,6 +29,7 @@
 #include "local-addresses.h"
 #include "macro.h"
 #include "nss-util.h"
+#include "signal-util.h"
 #include "string-util.h"
 #include "util.h"
 
@@ -63,6 +62,8 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
         char *r_name;
         unsigned n;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(pat);
         assert(buffer);
@@ -327,6 +328,8 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
         uint32_t local_address_ipv4 = 0;
         int n_addresses = 0;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(host);
         assert(buffer);
@@ -409,6 +412,8 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
         bool additional_from_hostname = false;
         unsigned n;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(addr);
         assert(host);
         assert(buffer);
index 969fa9619e17454070a4ed6335eeef38f8dc85ac..1582d702f8ccad43cf4aad3ca8f3f143203b425c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include "alloc-util.h"
 #include "bus-common-errors.h"
-#include "bus-util.h"
 #include "hostname-util.h"
 #include "in-addr-util.h"
 #include "macro.h"
 #include "nss-util.h"
+#include "signal-util.h"
 #include "string-util.h"
 #include "user-util.h"
 #include "util.h"
@@ -40,6 +38,9 @@ NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
 NSS_GETPW_PROTOTYPES(mymachines);
 NSS_GETGR_PROTOTYPES(mymachines);
 
+#define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000))
+#define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000))
+
 static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
         unsigned c = 0;
         int r;
@@ -86,8 +87,8 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
                 int32_t *ttlp) {
 
         struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ int *ifindices = NULL;
         _cleanup_free_ char *class = NULL;
         size_t l, ms, idx;
@@ -95,6 +96,8 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
         char *r_name;
         int n_ifindices, r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(pat);
         assert(buffer);
@@ -235,14 +238,16 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
                 int32_t *ttlp,
                 char **canonp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *class = NULL;
         unsigned c = 0, i = 0;
         char *r_name, *r_aliases, *r_addr, *r_addr_list;
         size_t l, idx, ms, alen;
         int r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(result);
         assert(buffer);
@@ -396,15 +401,17 @@ enum nss_status _nss_mymachines_getpwnam_r(
                 char *buffer, size_t buflen,
                 int *errnop) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *p, *e, *machine;
         uint32_t mapped;
         uid_t uid;
         size_t l;
         int r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(pwd);
 
@@ -416,6 +423,9 @@ enum nss_status _nss_mymachines_getpwnam_r(
         if (!e || e == p)
                 goto not_found;
 
+        if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
+                goto not_found;
+
         r = parse_uid(e + 1, &uid);
         if (r < 0)
                 goto not_found;
@@ -448,6 +458,10 @@ enum nss_status _nss_mymachines_getpwnam_r(
         if (r < 0)
                 goto fail;
 
+        /* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */
+        if (mapped < HOST_UID_LIMIT || mapped == uid)
+                goto not_found;
+
         l = strlen(name);
         if (buflen < l+1) {
                 *errnop = ENOMEM;
@@ -482,20 +496,22 @@ enum nss_status _nss_mymachines_getpwuid_r(
                 char *buffer, size_t buflen,
                 int *errnop) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *machine, *object;
         uint32_t mapped;
         int r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         if (!uid_is_valid(uid)) {
                 r = -EINVAL;
                 goto fail;
         }
 
         /* We consider all uids < 65536 host uids */
-        if (uid < 0x10000)
+        if (uid < HOST_UID_LIMIT)
                 goto not_found;
 
         r = sd_bus_open_system(&bus);
@@ -522,6 +538,9 @@ enum nss_status _nss_mymachines_getpwuid_r(
         if (r < 0)
                 goto fail;
 
+        if (mapped == uid)
+                goto not_found;
+
         if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
                 *errnop = ENOMEM;
                 return NSS_STATUS_TRYAGAIN;
@@ -553,15 +572,17 @@ enum nss_status _nss_mymachines_getgrnam_r(
                 char *buffer, size_t buflen,
                 int *errnop) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *p, *e, *machine;
         uint32_t mapped;
         uid_t gid;
         size_t l;
         int r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(gr);
 
@@ -573,6 +594,9 @@ enum nss_status _nss_mymachines_getgrnam_r(
         if (!e || e == p)
                 goto not_found;
 
+        if (e - p > HOST_NAME_MAX - 1)  /* -1 for the last dash */
+                goto not_found;
+
         r = parse_gid(e + 1, &gid);
         if (r < 0)
                 goto not_found;
@@ -605,6 +629,9 @@ enum nss_status _nss_mymachines_getgrnam_r(
         if (r < 0)
                 goto fail;
 
+        if (mapped < HOST_GID_LIMIT || mapped == gid)
+                goto not_found;
+
         l = sizeof(char*) + strlen(name) + 1;
         if (buflen < l) {
                 *errnop = ENOMEM;
@@ -637,20 +664,22 @@ enum nss_status _nss_mymachines_getgrgid_r(
                 char *buffer, size_t buflen,
                 int *errnop) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *machine, *object;
         uint32_t mapped;
         int r;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         if (!gid_is_valid(gid)) {
                 r = -EINVAL;
                 goto fail;
         }
 
         /* We consider all gids < 65536 host gids */
-        if (gid < 0x10000)
+        if (gid < HOST_GID_LIMIT)
                 goto not_found;
 
         r = sd_bus_open_system(&bus);
@@ -677,6 +706,9 @@ enum nss_status _nss_mymachines_getgrgid_r(
         if (r < 0)
                 goto fail;
 
+        if (mapped == gid)
+                goto not_found;
+
         if (buflen < sizeof(char*) + 1) {
                 *errnop = ENOMEM;
                 return NSS_STATUS_TRYAGAIN;
index ed59a71e3d3acd810d8288c9179b81f5fbd5fa99..69c0d9bdc13169aa9af1de41725b40d780bc31a2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "sd-bus.h"
 
 #include "bus-common-errors.h"
-#include "bus-util.h"
 #include "in-addr-util.h"
 #include "macro.h"
 #include "nss-util.h"
 #include "string-util.h"
 #include "util.h"
+#include "signal-util.h"
 
 NSS_GETHOSTBYNAME_PROTOTYPES(resolve);
 NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
@@ -119,15 +117,24 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const char *name,
+                        struct gaih_addrtuple **pat,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp);
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *canonical = NULL;
         size_t l, ms, idx;
         char *r_name;
         int c, r, i = 0;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(pat);
         assert(buffer);
@@ -136,7 +143,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -164,28 +171,10 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
-
-                        enum nss_status (*fallback)(
-                                        const char *name,
-                                        struct gaih_addrtuple **pat,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp);
-
-                        fallback = (enum nss_status (*)(const char *name,
-                                                        struct gaih_addrtuple **pat,
-                                                        char *buffer, size_t buflen,
-                                                        int *errnop, int *h_errnop,
-                                                        int32_t *ttlp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
-                        if (fallback)
-                                return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
-                }
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                *errnop = -r;
-                *h_errnop = NO_RECOVERY;
-                return NSS_STATUS_UNAVAIL;
+                goto fail;
         }
 
         c = count_addresses(reply, AF_UNSPEC, &canonical);
@@ -285,9 +274,20 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(const char *name,
+                                        struct gaih_addrtuple **pat,
+                                        char *buffer, size_t buflen,
+                                        int *errnop, int *h_errnop,
+                                        int32_t *ttlp))
+                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_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }
 
@@ -300,14 +300,25 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                 int32_t *ttlp,
                 char **canonp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const char *name,
+                        int af,
+                        struct hostent *result,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp,
+                        char **canonp);
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *r_name, *r_aliases, *r_addr, *r_addr_list;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         size_t l, idx, ms, alen;
         const char *canonical;
         int c, r, i = 0;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(name);
         assert(result);
         assert(buffer);
@@ -324,7 +335,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -352,32 +363,10 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
-
-                        enum nss_status (*fallback)(
-                                        const char *name,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp,
-                                        char **canonp);
-
-                        fallback = (enum nss_status (*)(const char *name,
-                                                        int af,
-                                                        struct hostent *result,
-                                                        char *buffer, size_t buflen,
-                                                        int *errnop, int *h_errnop,
-                                                        int32_t *ttlp,
-                                                        char **canonp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
-                        if (fallback)
-                                return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
-                }
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                *errnop = -r;
-                *h_errnop = NO_RECOVERY;
-                return NSS_STATUS_UNAVAIL;
+                goto fail;
         }
 
         c = count_addresses(reply, af, &canonical);
@@ -490,9 +479,21 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(const char *name,
+                                        int af,
+                                        struct hostent *result,
+                                        char *buffer, size_t buflen,
+                                        int *errnop, int *h_errnop,
+                                        int32_t *ttlp,
+                                        char **canonp))
+                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_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }
 
@@ -504,15 +505,26 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const void* addr, socklen_t len,
+                        int af,
+                        struct hostent *result,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp);
+
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *r_name, *r_aliases, *r_addr, *r_addr_list;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         unsigned c = 0, i = 0;
         size_t ms = 0, idx;
         const char *n;
         int r, ifindex;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(addr);
         assert(result);
         assert(buffer);
@@ -533,7 +545,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -569,28 +581,9 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                        enum nss_status (*fallback)(
-                                        const void* addr, socklen_t len,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp);
-
-                        fallback = (enum nss_status (*)(
-                                        const void* addr, socklen_t len,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
-
-                        if (fallback)
-                                return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
-                }
 
                 *errnop = -r;
                 *h_errnop = NO_RECOVERY;
@@ -660,7 +653,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 p = buffer + idx;
                 memcpy(p, n, l+1);
 
-                if (i > 1)
+                if (i > 0)
                         ((char**) r_aliases)[i-1] = p;
                 i++;
 
@@ -688,9 +681,22 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(
+                                    const void* addr, socklen_t len,
+                                    int af,
+                                    struct hostent *result,
+                                    char *buffer, size_t buflen,
+                                    int *errnop, int *h_errnop,
+                                    int32_t *ttlp))
+                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_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }
 
index 0ece72f6fe23b3ea9097397446addbe53b0cf84e..61d877fcf86df476a5f270581d3b174f2bfe45fa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 883d96608d4bba84ba5f815ad2095ccc5203cb06..6d8c05f046e7954bc7ed54972e558c4b5ab88ccb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d857ade36a0a4cdf579ac09bd544f20fb6a11810..6748bb9dd33cd70255b370dbcae6f865f879082c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,7 +38,7 @@ int main(int argc, char *argv[]) {
         _cleanup_free_ void* buf = NULL;
         size_t buf_size = 0;
         ssize_t k;
-        int r;
+        int r, open_rw_error;
         FILE *f;
         bool refresh_seed_file = true;
 
@@ -87,14 +85,23 @@ int main(int argc, char *argv[]) {
         if (streq(argv[1], "load")) {
 
                 seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
+                open_rw_error = -errno;
                 if (seed_fd < 0) {
+                        refresh_seed_file = false;
+
                         seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
                         if (seed_fd < 0) {
-                                r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
+                                bool missing = errno == ENOENT;
+
+                                log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
+                                               open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
+                                r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
+                                                   errno, "Failed to open " RANDOM_SEED " for reading: %m");
+                                if (missing)
+                                        r = 0;
+
                                 goto finish;
                         }
-
-                        refresh_seed_file = false;
                 }
 
                 random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
@@ -109,9 +116,10 @@ int main(int argc, char *argv[]) {
                 k = loop_read(seed_fd, buf, buf_size, false);
                 if (k < 0)
                         r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
-                else if (k == 0)
+                else if (k == 0) {
+                        r = 0;
                         log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
-                else {
+                else {
                         (void) lseek(seed_fd, 0, SEEK_SET);
 
                         r = loop_write(random_fd, buf, (size_t) k, false);
index 6ecadbf3e5eef9aef238eb86abf006257dde5dce..9e9c1619936b79f8dd22a973bf7b0cd5bdfeba9f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 9fc56284d245a12028808a1f11d1a17384234533..6468d1eecdb187799e74df00509871538e9fef48 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 166ab470edc51620afdb33e9fee10f17db37040b..e29175896942a5f55343d1311c94053009ec5995 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/resolve-host/Makefile b/src/resolve-host/Makefile
deleted file mode 120000 (symlink)
index d0b0e8e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile
\ No newline at end of file
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
deleted file mode 100644 (file)
index eb4e646..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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 <getopt.h>
-#include <net/if.h>
-
-#include "sd-bus.h"
-
-#include "af-list.h"
-#include "alloc-util.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "in-addr-util.h"
-#include "parse-util.h"
-#include "resolved-def.h"
-#include "resolved-dns-packet.h"
-
-#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
-
-static int arg_family = AF_UNSPEC;
-static int arg_ifindex = 0;
-static int arg_type = 0;
-static uint16_t arg_class = 0;
-static bool arg_legend = true;
-static uint64_t arg_flags = 0;
-
-static void print_source(uint64_t flags, usec_t rtt) {
-        char rtt_str[FORMAT_TIMESTAMP_MAX];
-
-        if (!arg_legend)
-                return;
-
-        if (flags == 0)
-                return;
-
-        fputs("\n-- Information acquired via", stdout);
-
-        if (flags != 0)
-                printf(" protocol%s%s%s",
-                       flags & SD_RESOLVED_DNS ? " DNS" :"",
-                       flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
-                       flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "");
-
-        assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
-
-        printf(" in %s", rtt_str);
-
-        fputc('.', stdout);
-        fputc('\n', stdout);
-}
-
-static int resolve_host(sd_bus *bus, const char *name) {
-
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        const char *canonical = NULL;
-        char ifname[IF_NAMESIZE] = "";
-        unsigned c = 0;
-        int r;
-        uint64_t flags;
-        usec_t ts;
-
-        assert(name);
-
-        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
-                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
-
-        log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
-
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &req,
-                        "org.freedesktop.resolve1",
-                        "/org/freedesktop/resolve1",
-                        "org.freedesktop.resolve1.Manager",
-                        "ResolveHostname");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        ts = now(CLOCK_MONOTONIC);
-
-        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
-        if (r < 0) {
-                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
-                return r;
-        }
-
-        ts = now(CLOCK_MONOTONIC) - ts;
-
-        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
-                const void *a;
-                size_t sz;
-                _cleanup_free_ char *pretty = NULL;
-                int ifindex, family;
-
-                assert_cc(sizeof(int) == sizeof(int32_t));
-
-                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
-                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);
-
-                if (!IN_SET(family, AF_INET, AF_INET6)) {
-                        log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
-                        continue;
-                }
-
-                if (sz != FAMILY_ADDRESS_SIZE(family)) {
-                        log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
-                        continue;
-                }
-
-                ifname[0] = 0;
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-                r = in_addr_to_string(family, a, &pretty);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to print address for %s: %m", name);
-
-                printf("%*s%s %s%s%s\n",
-                       (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
-                       pretty,
-                       isempty(ifname) ? "" : "%", ifname);
-
-                c++;
-        }
-        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_read(reply, "st", &canonical, &flags);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        if (!streq(name, canonical))
-                printf("%*s%s (%s)\n",
-                       (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
-                       canonical);
-
-        if (c == 0) {
-                log_error("%s: no addresses found", name);
-                return -ESRCH;
-        }
-
-        print_source(flags, ts);
-
-        return 0;
-}
-
-static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_free_ char *pretty = NULL;
-        char ifname[IF_NAMESIZE] = "";
-        uint64_t flags;
-        unsigned c = 0;
-        usec_t ts;
-        int r;
-
-        assert(bus);
-        assert(IN_SET(family, AF_INET, AF_INET6));
-        assert(address);
-
-        if (ifindex <= 0)
-                ifindex = arg_ifindex;
-
-        r = in_addr_to_string(family, address, &pretty);
-        if (r < 0)
-                return log_oom();
-
-        if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-        log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
-
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &req,
-                        "org.freedesktop.resolve1",
-                        "/org/freedesktop/resolve1",
-                        "org.freedesktop.resolve1.Manager",
-                        "ResolveAddress");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append(req, "ii", ifindex, family);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append(req, "t", arg_flags);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        ts = now(CLOCK_MONOTONIC);
-
-        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
-        if (r < 0) {
-                log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
-                return r;
-        }
-
-        ts = now(CLOCK_MONOTONIC) - ts;
-
-        r = sd_bus_message_enter_container(reply, 'a', "(is)");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
-                const char *n;
-
-                assert_cc(sizeof(int) == sizeof(int32_t));
-
-                r = sd_bus_message_read(reply, "is", &ifindex, &n);
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_message_exit_container(reply);
-                if (r < 0)
-                        return r;
-
-                ifname[0] = 0;
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-                printf("%*s%*s%*s%s %s\n",
-                       (int) strlen(pretty), c == 0 ? pretty : "",
-                       isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
-                       (int) strlen(ifname), c == 0 ? ifname : "",
-                       c == 0 ? ":" : " ",
-                       n);
-
-                c++;
-        }
-        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_read(reply, "t", &flags);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        if (c == 0) {
-                log_error("%s: no names found", pretty);
-                return -ESRCH;
-        }
-
-        print_source(flags, ts);
-
-        return 0;
-}
-
-static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
-        const char *percent, *a;
-        int ifi = 0;
-        int r;
-
-        percent = strchr(s, '%');
-        if (percent) {
-                if (parse_ifindex(percent+1, &ifi) < 0) {
-                        ifi = if_nametoindex(percent+1);
-                        if (ifi <= 0)
-                                return -EINVAL;
-                }
-
-                a = strndupa(s, percent - s);
-        } else
-                a = s;
-
-        r = in_addr_from_string_auto(a, family, address);
-        if (r < 0)
-                return r;
-
-        *ifindex = ifi;
-        return 0;
-}
-
-static int resolve_record(sd_bus *bus, const char *name) {
-
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        char ifname[IF_NAMESIZE] = "";
-        unsigned n = 0;
-        uint64_t flags;
-        int r;
-        usec_t ts;
-
-        assert(name);
-
-        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
-                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
-
-        log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(arg_class), dns_type_to_string(arg_type), isempty(ifname) ? "*" : ifname);
-
-        r = sd_bus_message_new_method_call(
-                        bus,
-                        &req,
-                        "org.freedesktop.resolve1",
-                        "/org/freedesktop/resolve1",
-                        "org.freedesktop.resolve1.Manager",
-                        "ResolveRecord");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        assert((uint16_t) arg_type == arg_type);
-        r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, arg_class, arg_type, arg_flags);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        ts = now(CLOCK_MONOTONIC);
-
-        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
-        if (r < 0) {
-                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
-                return r;
-        }
-
-        ts = now(CLOCK_MONOTONIC) - ts;
-
-        r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-                _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
-                _cleanup_free_ char *s = NULL;
-                uint16_t c, t;
-                int ifindex;
-                const void *d;
-                size_t l;
-
-                assert_cc(sizeof(int) == sizeof(int32_t));
-
-                r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                r = sd_bus_message_read_array(reply, 'y', &d, &l);
-                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 = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
-                if (r < 0)
-                        return log_oom();
-
-                p->refuse_compression = true;
-
-                r = dns_packet_append_blob(p, d, l, NULL);
-                if (r < 0)
-                        return log_oom();
-
-                r = dns_packet_read_rr(p, &rr, NULL);
-                if (r < 0) {
-                        log_error("Failed to parse RR.");
-                        return r;
-                }
-
-                r = dns_resource_record_to_string(rr, &s);
-                if (r < 0) {
-                        log_error("Failed to format RR.");
-                        return r;
-                }
-
-                ifname[0] = 0;
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-                printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
-                n++;
-        }
-        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_read(reply, "t", &flags);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        if (n == 0) {
-                log_error("%s: no records found", name);
-                return -ESRCH;
-        }
-
-        print_source(flags, ts);
-
-        return 0;
-}
-
-static void help_dns_types(void) {
-        int i;
-        const char *t;
-
-        if (arg_legend)
-                puts("Known DNS RR types:");
-        for (i = 0; i < _DNS_TYPE_MAX; i++) {
-                t = dns_type_to_string(i);
-                if (t)
-                        puts(t);
-        }
-}
-
-static void help_dns_classes(void) {
-        int i;
-        const char *t;
-
-        if (arg_legend)
-                puts("Known DNS RR classes:");
-        for (i = 0; i < _DNS_CLASS_MAX; i++) {
-                t = dns_class_to_string(i);
-                if (t)
-                        puts(t);
-        }
-}
-
-static void help(void) {
-        printf("%s [OPTIONS...]\n\n"
-               "Resolve IPv4 or IPv6 addresses.\n\n"
-               "  -h --help               Show this help\n"
-               "     --version            Show package version\n"
-               "  -4                      Resolve IPv4 addresses\n"
-               "  -6                      Resolve IPv6 addresses\n"
-               "  -i INTERFACE            Look on interface\n"
-               "  -p --protocol=PROTOCOL  Look via protocol\n"
-               "  -t --type=TYPE          Query RR with DNS type\n"
-               "  -c --class=CLASS        Query RR with DNS class\n"
-               "     --legend[=BOOL]      Do [not] print column headers\n"
-               , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_LEGEND,
-        };
-
-        static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'           },
-                { "version",   no_argument,       NULL, ARG_VERSION   },
-                { "type",      required_argument, NULL, 't'           },
-                { "class",     required_argument, NULL, 'c'           },
-                { "legend",    optional_argument, NULL, ARG_LEGEND    },
-                { "protocol",  required_argument, NULL, 'p'           },
-                {}
-        };
-
-        int c, r;
-
-        assert(argc >= 0);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
-                switch(c) {
-
-                case 'h':
-                        help();
-                        return 0; /* done */;
-
-                case ARG_VERSION:
-                        return version();
-
-                case '4':
-                        arg_family = AF_INET;
-                        break;
-
-                case '6':
-                        arg_family = AF_INET6;
-                        break;
-
-                case 'i': {
-                        int ifi;
-
-                        if (parse_ifindex(optarg, &ifi) >= 0)
-                                arg_ifindex = ifi;
-                        else {
-                                ifi = if_nametoindex(optarg);
-                                if (ifi <= 0)
-                                        return log_error_errno(errno, "Unknown interface %s: %m", optarg);
-
-                                arg_ifindex = ifi;
-                        }
-
-                        break;
-                }
-
-                case 't':
-                        if (streq(optarg, "help")) {
-                                help_dns_types();
-                                return 0;
-                        }
-
-                        arg_type = dns_type_from_string(optarg);
-                        if (arg_type < 0) {
-                                log_error("Failed to parse RR record type %s", optarg);
-                                return arg_type;
-                        }
-                        assert(arg_type > 0 && (uint16_t) arg_type == arg_type);
-
-                        break;
-
-                case 'c':
-                        if (streq(optarg, "help")) {
-                                help_dns_classes();
-                                return 0;
-                        }
-
-                        r = dns_class_from_string(optarg, &arg_class);
-                        if (r < 0) {
-                                log_error("Failed to parse RR record class %s", optarg);
-                                return r;
-                        }
-
-                        break;
-
-                case ARG_LEGEND:
-                        if (optarg) {
-                                r = parse_boolean(optarg);
-                                if (r < 0) {
-                                        log_error("Failed to parse --legend= argument");
-                                        return r;
-                                }
-
-                                arg_legend = !!r;
-                        } else
-                                arg_legend = false;
-                        break;
-
-                case 'p':
-                        if (streq(optarg, "dns"))
-                                arg_flags |= SD_RESOLVED_DNS;
-                        else if (streq(optarg, "llmnr"))
-                                arg_flags |= SD_RESOLVED_LLMNR;
-                        else if (streq(optarg, "llmnr-ipv4"))
-                                arg_flags |= SD_RESOLVED_LLMNR_IPV4;
-                        else if (streq(optarg, "llmnr-ipv6"))
-                                arg_flags |= SD_RESOLVED_LLMNR_IPV6;
-                        else {
-                                log_error("Unknown protocol specifier: %s", optarg);
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option");
-                }
-
-        if (arg_type == 0 && arg_class != 0) {
-                log_error("--class= may only be used in conjunction with --type=");
-                return -EINVAL;
-        }
-
-        if (arg_type != 0 && arg_class == 0)
-                arg_class = DNS_CLASS_IN;
-
-        return 1 /* work to do */;
-}
-
-int main(int argc, char **argv) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
-        int r;
-
-        log_parse_environment();
-        log_open();
-
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                goto finish;
-
-        if (optind >= argc) {
-                log_error("No arguments passed");
-                r = -EINVAL;
-                goto finish;
-        }
-
-        r = sd_bus_open_system(&bus);
-        if (r < 0) {
-                log_error_errno(r, "sd_bus_open_system: %m");
-                goto finish;
-        }
-
-        while (argv[optind]) {
-                int family, ifindex, k;
-                union in_addr_union a;
-
-                if (arg_type != 0)
-                        k = resolve_record(bus, argv[optind]);
-                else {
-                        k = parse_address(argv[optind], &family, &a, &ifindex);
-                        if (k >= 0)
-                                k = resolve_address(bus, family, &a, ifindex);
-                        else
-                                k = resolve_host(bus, argv[optind]);
-                }
-
-                if (r == 0)
-                        r = k;
-
-                optind++;
-        }
-
-finish:
-        return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/src/resolve/RFCs b/src/resolve/RFCs
new file mode 100644 (file)
index 0000000..22004a0
--- /dev/null
@@ -0,0 +1,59 @@
+Y = Comprehensively Implemented, to the point appropriate for resolved
+D = Comprehensively Implemented, by a dependency of resolved
+! = Missing and something we might want to implement
+~ = Needs no explicit support or doesn't apply
+? = Is this relevant today?
+  = We are working on this
+
+Y https://tools.ietf.org/html/rfc1034 → DOMAIN NAMES - CONCEPTS AND FACILITIES
+Y https://tools.ietf.org/html/rfc1035 → DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+? https://tools.ietf.org/html/rfc1101 → DNS Encoding of Network Names and Other Types
+Y https://tools.ietf.org/html/rfc1123 → Requirements for Internet Hosts -- Application and Support
+~ https://tools.ietf.org/html/rfc1464 → Using the Domain Name System To Store Arbitrary String Attributes
+Y https://tools.ietf.org/html/rfc1536 → Common DNS Implementation Errors and Suggested Fixes
+Y https://tools.ietf.org/html/rfc1876 → A Means for Expressing Location Information in the Domain Name System
+Y https://tools.ietf.org/html/rfc2181 → Clarifications to the DNS Specification
+Y https://tools.ietf.org/html/rfc2308 → Negative Caching of DNS Queries (DNS NCACHE)
+Y https://tools.ietf.org/html/rfc2782 → A DNS RR for specifying the location of services (DNS SRV)
+D https://tools.ietf.org/html/rfc3492 → Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
+Y https://tools.ietf.org/html/rfc3596 → DNS Extensions to Support IP Version 6
+Y https://tools.ietf.org/html/rfc3597 → Handling of Unknown DNS Resource Record (RR) Types
+Y https://tools.ietf.org/html/rfc4033 → DNS Security Introduction and Requirements
+Y https://tools.ietf.org/html/rfc4034 → Resource Records for the DNS Security Extensions
+Y https://tools.ietf.org/html/rfc4035 → Protocol Modifications for the DNS Security Extensions
+! https://tools.ietf.org/html/rfc4183 → A Suggested Scheme for DNS Resolution of Networks and Gateways
+Y https://tools.ietf.org/html/rfc4255 → Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
+Y https://tools.ietf.org/html/rfc4343 → Domain Name System (DNS) Case Insensitivity Clarification
+~ https://tools.ietf.org/html/rfc4470 → Minimally Covering NSEC Records and DNSSEC On-line Signing
+Y https://tools.ietf.org/html/rfc4501 → Domain Name System Uniform Resource Identifiers
+Y https://tools.ietf.org/html/rfc4509 → Use of SHA-256 in DNSSEC Delegation Signer (DS) Resource Records (RRs)
+~ https://tools.ietf.org/html/rfc4592 → The Role of Wildcards in the Domain Name System
+~ https://tools.ietf.org/html/rfc4697 → Observed DNS Resolution Misbehavior
+Y https://tools.ietf.org/html/rfc4795 → Link-Local Multicast Name Resolution (LLMNR)
+Y https://tools.ietf.org/html/rfc5011 → Automated Updates of DNS Security (DNSSEC) Trust Anchors
+Y https://tools.ietf.org/html/rfc5155 → DNS Security (DNSSEC) Hashed Authenticated Denial of Existence
+Y https://tools.ietf.org/html/rfc5452 → Measures for Making DNS More Resilient against Forged Answers
+Y https://tools.ietf.org/html/rfc5702 → Use of SHA-2 Algorithms with RSA in DNSKEY and RRSIG Resource Records for DNSSEC
+Y https://tools.ietf.org/html/rfc5890 → Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework
+Y https://tools.ietf.org/html/rfc5891 → Internationalized Domain Names in Applications (IDNA): Protocol
+Y https://tools.ietf.org/html/rfc5966 → DNS Transport over TCP - Implementation Requirements
+Y https://tools.ietf.org/html/rfc6303 → Locally Served DNS Zones
+Y https://tools.ietf.org/html/rfc6604 → xNAME RCODE and Status Bits Clarification
+Y https://tools.ietf.org/html/rfc6605 → Elliptic Curve Digital Signature Algorithm (DSA) for DNSSEC
+  https://tools.ietf.org/html/rfc6672 → DNAME Redirection in the DNS
+! https://tools.ietf.org/html/rfc6731 → Improved Recursive DNS Server Selection for Multi-Interfaced Nodes
+Y https://tools.ietf.org/html/rfc6761 → Special-Use Domain Names
+  https://tools.ietf.org/html/rfc6762 → Multicast DNS
+  https://tools.ietf.org/html/rfc6763 → DNS-Based Service Discovery
+~ https://tools.ietf.org/html/rfc6781 → DNSSEC Operational Practices, Version 2
+Y https://tools.ietf.org/html/rfc6840 → Clarifications and Implementation Notes for DNS Security (DNSSEC)
+Y https://tools.ietf.org/html/rfc6891 → Extension Mechanisms for DNS (EDNS(0))
+Y https://tools.ietf.org/html/rfc6944 → Applicability Statement: DNS Security (DNSSEC) DNSKEY Algorithm Implementation Status
+Y https://tools.ietf.org/html/rfc6975 → Signaling Cryptographic Algorithm Understanding in DNS Security Extensions (DNSSEC)
+Y https://tools.ietf.org/html/rfc7129 → Authenticated Denial of Existence in the DNS
+Y https://tools.ietf.org/html/rfc7646 → Definition and Use of DNSSEC Negative Trust Anchors
+~ https://tools.ietf.org/html/rfc7719 → DNS Terminology
+
+Also relevant:
+
+  https://www.iab.org/documents/correspondence-reports-documents/2013-2/iab-statement-dotless-domains-considered-harmful/
index 63b4b36e88d0b0fae45ef94c41e2ae4f77429d8f..b2f479cae5568d22cc251da15d2fcda8e57b04b5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/socket.h>
+
 #include "dns-type.h"
+#include "parse-util.h"
+#include "string-util.h"
 
 typedef const struct {
         uint16_t type;
@@ -38,13 +40,267 @@ int dns_type_from_string(const char *s) {
         assert(s);
 
         sc = lookup_dns_type(s, strlen(s));
-        if (!sc)
-                return _DNS_TYPE_INVALID;
+        if (sc)
+                return sc->id;
+
+        s = startswith_no_case(s, "TYPE");
+        if (s) {
+                unsigned x;
+
+                if (safe_atou(s, &x) >= 0 &&
+                    x <= UINT16_MAX)
+                        return (int) x;
+        }
+
+        return _DNS_TYPE_INVALID;
+}
+
+bool dns_type_is_pseudo(uint16_t type) {
+
+        /* Checks whether the specified type is a "pseudo-type". What
+         * a "pseudo-type" precisely is, is defined only very weakly,
+         * but apparently entails all RR types that are not actually
+         * stored as RRs on the server and should hence also not be
+         * cached. We use this list primarily to validate NSEC type
+         * bitfields, and to verify what to cache. */
+
+        return IN_SET(type,
+                      0, /* A Pseudo RR type, according to RFC 2931 */
+                      DNS_TYPE_ANY,
+                      DNS_TYPE_AXFR,
+                      DNS_TYPE_IXFR,
+                      DNS_TYPE_OPT,
+                      DNS_TYPE_TSIG,
+                      DNS_TYPE_TKEY
+        );
+}
+
+bool dns_class_is_pseudo(uint16_t class) {
+        return class == DNS_TYPE_ANY;
+}
+
+bool dns_type_is_valid_query(uint16_t type) {
+
+        /* The types valid as questions in packets */
 
-        return sc->id;
+        return !IN_SET(type,
+                       0,
+                       DNS_TYPE_OPT,
+                       DNS_TYPE_TSIG,
+                       DNS_TYPE_TKEY,
+
+                       /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as
+                        * they aren't really payload, but signatures for payload, and cannot be validated on their
+                        * own. After all they are the signatures, and have no signatures of their own validating
+                        * them. */
+                       DNS_TYPE_RRSIG);
 }
 
-/* XXX: find an authoritative list of all pseudo types? */
-bool dns_type_is_pseudo(int n) {
-        return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT);
+bool dns_type_is_valid_rr(uint16_t type) {
+
+        /* The types valid as RR in packets (but not necessarily
+         * stored on servers). */
+
+        return !IN_SET(type,
+                       DNS_TYPE_ANY,
+                       DNS_TYPE_AXFR,
+                       DNS_TYPE_IXFR);
+}
+
+bool dns_class_is_valid_rr(uint16_t class) {
+        return class != DNS_CLASS_ANY;
+}
+
+bool dns_type_may_redirect(uint16_t type) {
+        /* The following record types should never be redirected using
+         * CNAME/DNAME RRs. See
+         * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
+
+        if (dns_type_is_pseudo(type))
+                return false;
+
+        return !IN_SET(type,
+                       DNS_TYPE_CNAME,
+                       DNS_TYPE_DNAME,
+                       DNS_TYPE_NSEC3,
+                       DNS_TYPE_NSEC,
+                       DNS_TYPE_RRSIG,
+                       DNS_TYPE_NXT,
+                       DNS_TYPE_SIG,
+                       DNS_TYPE_KEY);
+}
+
+bool dns_type_may_wildcard(uint16_t type) {
+
+        /* The following records may not be expanded from wildcard RRsets */
+
+        if (dns_type_is_pseudo(type))
+                return false;
+
+        return !IN_SET(type,
+                       DNS_TYPE_NSEC3,
+                       DNS_TYPE_SOA,
+
+                       /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */
+                       DNS_TYPE_DNAME);
+}
+
+bool dns_type_apex_only(uint16_t type) {
+
+        /* Returns true for all RR types that may only appear signed in a zone apex */
+
+        return IN_SET(type,
+                      DNS_TYPE_SOA,
+                      DNS_TYPE_NS,            /* this one can appear elsewhere, too, but not signed */
+                      DNS_TYPE_DNSKEY,
+                      DNS_TYPE_NSEC3PARAM);
+}
+
+bool dns_type_is_dnssec(uint16_t type) {
+        return IN_SET(type,
+                      DNS_TYPE_DS,
+                      DNS_TYPE_DNSKEY,
+                      DNS_TYPE_RRSIG,
+                      DNS_TYPE_NSEC,
+                      DNS_TYPE_NSEC3,
+                      DNS_TYPE_NSEC3PARAM);
+}
+
+bool dns_type_is_obsolete(uint16_t type) {
+        return IN_SET(type,
+                      /* Obsoleted by RFC 973 */
+                      DNS_TYPE_MD,
+                      DNS_TYPE_MF,
+                      DNS_TYPE_MAILA,
+
+                      /* Kinda obsoleted by RFC 2505 */
+                      DNS_TYPE_MB,
+                      DNS_TYPE_MG,
+                      DNS_TYPE_MR,
+                      DNS_TYPE_MINFO,
+                      DNS_TYPE_MAILB,
+
+                      /* RFC1127 kinda obsoleted this by recommending against its use */
+                      DNS_TYPE_WKS,
+
+                      /* Declared historical by RFC 6563 */
+                      DNS_TYPE_A6,
+
+                      /* Obsoleted by DNSSEC-bis */
+                      DNS_TYPE_NXT,
+
+                      /* RFC 1035 removed support for concepts that needed this from RFC 883 */
+                      DNS_TYPE_NULL);
+}
+
+int dns_type_to_af(uint16_t t) {
+        switch (t) {
+
+        case DNS_TYPE_A:
+                return AF_INET;
+
+        case DNS_TYPE_AAAA:
+                return AF_INET6;
+
+        case DNS_TYPE_ANY:
+                return AF_UNSPEC;
+
+        default:
+                return -EINVAL;
+        }
+}
+
+const char *dns_class_to_string(uint16_t class) {
+
+        switch (class) {
+
+        case DNS_CLASS_IN:
+                return "IN";
+
+        case DNS_CLASS_ANY:
+                return "ANY";
+        }
+
+        return NULL;
+}
+
+int dns_class_from_string(const char *s) {
+
+        if (!s)
+                return _DNS_CLASS_INVALID;
+
+        if (strcaseeq(s, "IN"))
+                return DNS_CLASS_IN;
+        else if (strcaseeq(s, "ANY"))
+                return DNS_CLASS_ANY;
+
+        return _DNS_CLASS_INVALID;
+}
+
+const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
+
+        switch (cert_usage) {
+
+        case 0:
+                return "CA constraint";
+
+        case 1:
+                return "Service certificate constraint";
+
+        case 2:
+                return "Trust anchor assertion";
+
+        case 3:
+                return "Domain-issued certificate";
+
+        case 4 ... 254:
+                return "Unassigned";
+
+        case 255:
+                return "Private use";
+        }
+
+        return NULL;  /* clang cannot count that we covered everything */
+}
+
+const char* tlsa_selector_to_string(uint8_t selector) {
+        switch (selector) {
+
+        case 0:
+                return "Full Certificate";
+
+        case 1:
+                return "SubjectPublicKeyInfo";
+
+        case 2 ... 254:
+                return "Unassigned";
+
+        case 255:
+                return "Private use";
+        }
+
+        return NULL;
+}
+
+const char* tlsa_matching_type_to_string(uint8_t selector) {
+
+        switch (selector) {
+
+        case 0:
+                return "No hash used";
+
+        case 1:
+                return "SHA-256";
+
+        case 2:
+                return "SHA-512";
+
+        case 3 ... 254:
+                return "Unassigned";
+
+        case 255:
+                return "Private use";
+        }
+
+        return NULL;
 }
index 950af36ee30027b91df4d7b61012950d3c83dece..a6c16300213099f93b9bba42a5290c5012f24117 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include "macro.h"
 
-const char *dns_type_to_string(int type);
-int dns_type_from_string(const char *s);
-bool dns_type_is_pseudo(int n);
-
 /* DNS record types, taken from
  * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
  */
@@ -91,6 +85,7 @@ enum {
         DNS_TYPE_TALINK,
         DNS_TYPE_CDS,
         DNS_TYPE_CDNSKEY,
+        DNS_TYPE_OPENPGPKEY,
 
         DNS_TYPE_SPF        = 0x63,
         DNS_TYPE_NID,
@@ -119,3 +114,41 @@ enum {
 assert_cc(DNS_TYPE_SSHFP == 44);
 assert_cc(DNS_TYPE_TLSA == 52);
 assert_cc(DNS_TYPE_ANY == 255);
+
+/* DNS record classes, see RFC 1035 */
+enum {
+        DNS_CLASS_IN   = 0x01,
+        DNS_CLASS_ANY  = 0xFF,
+
+        _DNS_CLASS_MAX,
+        _DNS_CLASS_INVALID = -1
+};
+
+bool dns_type_is_pseudo(uint16_t type);
+bool dns_type_is_valid_query(uint16_t type);
+bool dns_type_is_valid_rr(uint16_t type);
+bool dns_type_may_redirect(uint16_t type);
+bool dns_type_is_dnssec(uint16_t type);
+bool dns_type_is_obsolete(uint16_t type);
+bool dns_type_may_wildcard(uint16_t type);
+bool dns_type_apex_only(uint16_t type);
+int dns_type_to_af(uint16_t t);
+
+bool dns_class_is_pseudo(uint16_t class);
+bool dns_class_is_valid_rr(uint16_t class);
+
+/* TYPE?? follows http://tools.ietf.org/html/rfc3597#section-5 */
+const char *dns_type_to_string(int type);
+int dns_type_from_string(const char *s);
+
+const char *dns_class_to_string(uint16_t type);
+int dns_class_from_string(const char *name);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */
+const char *tlsa_cert_usage_to_string(uint8_t cert_usage);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.3 */
+const char *tlsa_selector_to_string(uint8_t selector);
+
+/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.4 */
+const char *tlsa_matching_type_to_string(uint8_t selector);
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
new file mode 100644 (file)
index 0000000..824cb26
--- /dev/null
@@ -0,0 +1,1272 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2014 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 <getopt.h>
+#include <net/if.h>
+
+#include "sd-bus.h"
+
+#include "af-list.h"
+#include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "escape.h"
+#include "in-addr-util.h"
+#include "parse-util.h"
+#include "resolved-def.h"
+#include "resolved-dns-packet.h"
+#include "terminal-util.h"
+
+#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
+
+static int arg_family = AF_UNSPEC;
+static int arg_ifindex = 0;
+static uint16_t arg_type = 0;
+static uint16_t arg_class = 0;
+static bool arg_legend = true;
+static uint64_t arg_flags = 0;
+
+static enum {
+        MODE_RESOLVE_HOST,
+        MODE_RESOLVE_RECORD,
+        MODE_RESOLVE_SERVICE,
+        MODE_STATISTICS,
+        MODE_RESET_STATISTICS,
+} arg_mode = MODE_RESOLVE_HOST;
+
+static void print_source(uint64_t flags, usec_t rtt) {
+        char rtt_str[FORMAT_TIMESTAMP_MAX];
+
+        if (!arg_legend)
+                return;
+
+        if (flags == 0)
+                return;
+
+        fputs("\n-- Information acquired via", stdout);
+
+        if (flags != 0)
+                printf(" protocol%s%s%s%s%s",
+                       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" : "");
+
+        assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
+
+        printf(" in %s", rtt_str);
+
+        fputc('.', stdout);
+        fputc('\n', stdout);
+
+        printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
+}
+
+static int resolve_host(sd_bus *bus, const char *name) {
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *canonical = NULL;
+        char ifname[IF_NAMESIZE] = "";
+        unsigned c = 0;
+        int r;
+        uint64_t flags;
+        usec_t ts;
+
+        assert(name);
+
+        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
+                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
+
+        log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &req,
+                        "org.freedesktop.resolve1",
+                        "/org/freedesktop/resolve1",
+                        "org.freedesktop.resolve1.Manager",
+                        "ResolveHostname");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        ts = now(CLOCK_MONOTONIC);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+        if (r < 0)
+                return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r));
+
+        ts = now(CLOCK_MONOTONIC) - ts;
+
+        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
+                _cleanup_free_ char *pretty = NULL;
+                int ifindex, family;
+                const void *a;
+                size_t sz;
+
+                assert_cc(sizeof(int) == sizeof(int32_t));
+
+                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
+                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);
+
+                if (!IN_SET(family, AF_INET, AF_INET6)) {
+                        log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
+                        continue;
+                }
+
+                if (sz != FAMILY_ADDRESS_SIZE(family)) {
+                        log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
+                        return -EINVAL;
+                }
+
+                ifname[0] = 0;
+                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+
+                r = in_addr_to_string(family, a, &pretty);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to print address for %s: %m", name);
+
+                printf("%*s%s %s%s%s\n",
+                       (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
+                       pretty,
+                       isempty(ifname) ? "" : "%", ifname);
+
+                c++;
+        }
+        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_read(reply, "st", &canonical, &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (!streq(name, canonical))
+                printf("%*s%s (%s)\n",
+                       (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
+                       canonical);
+
+        if (c == 0) {
+                log_error("%s: no addresses found", name);
+                return -ESRCH;
+        }
+
+        print_source(flags, ts);
+
+        return 0;
+}
+
+static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *pretty = NULL;
+        char ifname[IF_NAMESIZE] = "";
+        uint64_t flags;
+        unsigned c = 0;
+        usec_t ts;
+        int r;
+
+        assert(bus);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+        assert(address);
+
+        if (ifindex <= 0)
+                ifindex = arg_ifindex;
+
+        r = in_addr_to_string(family, address, &pretty);
+        if (r < 0)
+                return log_oom();
+
+        if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+
+        log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &req,
+                        "org.freedesktop.resolve1",
+                        "/org/freedesktop/resolve1",
+                        "org.freedesktop.resolve1.Manager",
+                        "ResolveAddress");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(req, "ii", ifindex, family);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(req, "t", arg_flags);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        ts = now(CLOCK_MONOTONIC);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+        if (r < 0) {
+                log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
+                return r;
+        }
+
+        ts = now(CLOCK_MONOTONIC) - ts;
+
+        r = sd_bus_message_enter_container(reply, 'a', "(is)");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
+                const char *n;
+
+                assert_cc(sizeof(int) == sizeof(int32_t));
+
+                r = sd_bus_message_read(reply, "is", &ifindex, &n);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(reply);
+                if (r < 0)
+                        return r;
+
+                ifname[0] = 0;
+                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+
+                printf("%*s%*s%*s%s %s\n",
+                       (int) strlen(pretty), c == 0 ? pretty : "",
+                       isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
+                       (int) strlen(ifname), c == 0 ? ifname : "",
+                       c == 0 ? ":" : " ",
+                       n);
+
+                c++;
+        }
+        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_read(reply, "t", &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (c == 0) {
+                log_error("%s: no names found", pretty);
+                return -ESRCH;
+        }
+
+        print_source(flags, ts);
+
+        return 0;
+}
+
+static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
+        const char *percent, *a;
+        int ifi = 0;
+        int r;
+
+        percent = strchr(s, '%');
+        if (percent) {
+                if (parse_ifindex(percent+1, &ifi) < 0) {
+                        ifi = if_nametoindex(percent+1);
+                        if (ifi <= 0)
+                                return -EINVAL;
+                }
+
+                a = strndupa(s, percent - s);
+        } else
+                a = s;
+
+        r = in_addr_from_string_auto(a, family, address);
+        if (r < 0)
+                return r;
+
+        *ifindex = ifi;
+        return 0;
+}
+
+static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        char ifname[IF_NAMESIZE] = "";
+        unsigned n = 0;
+        uint64_t flags;
+        int r;
+        usec_t ts;
+
+        assert(name);
+
+        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
+                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
+
+        log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname);
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &req,
+                        "org.freedesktop.resolve1",
+                        "/org/freedesktop/resolve1",
+                        "org.freedesktop.resolve1.Manager",
+                        "ResolveRecord");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        ts = now(CLOCK_MONOTONIC);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+        if (r < 0) {
+                log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
+                return r;
+        }
+
+        ts = now(CLOCK_MONOTONIC) - ts;
+
+        r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+                _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+                const char *s;
+                uint16_t c, t;
+                int ifindex;
+                const void *d;
+                size_t l;
+
+                assert_cc(sizeof(int) == sizeof(int32_t));
+
+                r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = sd_bus_message_read_array(reply, 'y', &d, &l);
+                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 = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
+                if (r < 0)
+                        return log_oom();
+
+                p->refuse_compression = true;
+
+                r = dns_packet_append_blob(p, d, l, NULL);
+                if (r < 0)
+                        return log_oom();
+
+                r = dns_packet_read_rr(p, &rr, NULL, NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse RR: %m");
+
+                s = dns_resource_record_to_string(rr);
+                if (!s)
+                        return log_oom();
+
+                ifname[0] = 0;
+                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+
+                printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
+                n++;
+        }
+        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_read(reply, "t", &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (n == 0) {
+                log_error("%s: no records found", name);
+                return -ESRCH;
+        }
+
+        print_source(flags, ts);
+
+        return 0;
+}
+
+static int resolve_rfc4501(sd_bus *bus, const char *name) {
+        uint16_t type = 0, class = 0;
+        const char *p, *q, *n;
+        int r;
+
+        assert(bus);
+        assert(name);
+        assert(startswith(name, "dns:"));
+
+        /* Parse RFC 4501 dns: URIs */
+
+        p = name + 4;
+
+        if (p[0] == '/') {
+                const char *e;
+
+                if (p[1] != '/')
+                        goto invalid;
+
+                e = strchr(p + 2, '/');
+                if (!e)
+                        goto invalid;
+
+                if (e != p + 2)
+                        log_warning("DNS authority specification not supported; ignoring specified authority.");
+
+                p = e + 1;
+        }
+
+        q = strchr(p, '?');
+        if (q) {
+                n = strndupa(p, q - p);
+                q++;
+
+                for (;;) {
+                        const char *f;
+
+                        f = startswith_no_case(q, "class=");
+                        if (f) {
+                                _cleanup_free_ char *t = NULL;
+                                const char *e;
+
+                                if (class != 0) {
+                                        log_error("DNS class specified twice.");
+                                        return -EINVAL;
+                                }
+
+                                e = strchrnul(f, ';');
+                                t = strndup(f, e - f);
+                                if (!t)
+                                        return log_oom();
+
+                                r = dns_class_from_string(t);
+                                if (r < 0) {
+                                        log_error("Unknown DNS class %s.", t);
+                                        return -EINVAL;
+                                }
+
+                                class = r;
+
+                                if (*e == ';') {
+                                        q = e + 1;
+                                        continue;
+                                }
+
+                                break;
+                        }
+
+                        f = startswith_no_case(q, "type=");
+                        if (f) {
+                                _cleanup_free_ char *t = NULL;
+                                const char *e;
+
+                                if (type != 0) {
+                                        log_error("DNS type specified twice.");
+                                        return -EINVAL;
+                                }
+
+                                e = strchrnul(f, ';');
+                                t = strndup(f, e - f);
+                                if (!t)
+                                        return log_oom();
+
+                                r = dns_type_from_string(t);
+                                if (r < 0) {
+                                        log_error("Unknown DNS type %s.", t);
+                                        return -EINVAL;
+                                }
+
+                                type = r;
+
+                                if (*e == ';') {
+                                        q = e + 1;
+                                        continue;
+                                }
+
+                                break;
+                        }
+
+                        goto invalid;
+                }
+        } else
+                n = p;
+
+        if (type == 0)
+                type = arg_type;
+        if (type == 0)
+                type = DNS_TYPE_A;
+
+        if (class == 0)
+                class = arg_class;
+        if (class == 0)
+                class = DNS_CLASS_IN;
+
+        return resolve_record(bus, n, class, type);
+
+invalid:
+        log_error("Invalid DNS URI: %s", name);
+        return -EINVAL;
+}
+
+static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) {
+        const char *canonical_name, *canonical_type, *canonical_domain;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        char ifname[IF_NAMESIZE] = "";
+        size_t indent, sz;
+        uint64_t flags;
+        const char *p;
+        unsigned c;
+        usec_t ts;
+        int r;
+
+        assert(bus);
+        assert(domain);
+
+        if (isempty(name))
+                name = NULL;
+        if (isempty(type))
+                type = NULL;
+
+        if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
+                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
+
+        if (name)
+                log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
+        else if (type)
+                log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
+        else
+                log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &req,
+                        "org.freedesktop.resolve1",
+                        "/org/freedesktop/resolve1",
+                        "org.freedesktop.resolve1.Manager",
+                        "ResolveService");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        ts = now(CLOCK_MONOTONIC);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+        if (r < 0)
+                return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r));
+
+        ts = now(CLOCK_MONOTONIC) - ts;
+
+        r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        indent =
+                (name ? strlen(name) + 1 : 0) +
+                (type ? strlen(type) + 1 : 0) +
+                strlen(domain) + 2;
+
+        c = 0;
+        while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) {
+                uint16_t priority, weight, port;
+                const char *hostname, *canonical;
+
+                r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                if (name)
+                        printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " ");
+                if (type)
+                        printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " ");
+
+                printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
+                       (int) strlen(domain), c == 0 ? domain : "",
+                       c == 0 ? ":" : " ",
+                       hostname, port,
+                       priority, weight);
+
+                r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
+                        _cleanup_free_ char *pretty = NULL;
+                        int ifindex, family;
+                        const void *a;
+
+                        assert_cc(sizeof(int) == sizeof(int32_t));
+
+                        r = sd_bus_message_read(reply, "ii", &ifindex, &family);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_read_array(reply, 'y', &a, &sz);
+                        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);
+
+                        if (!IN_SET(family, AF_INET, AF_INET6)) {
+                                log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
+                                continue;
+                        }
+
+                        if (sz != FAMILY_ADDRESS_SIZE(family)) {
+                                log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
+                                return -EINVAL;
+                        }
+
+                        ifname[0] = 0;
+                        if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+                                log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+
+                        r = in_addr_to_string(family, a, &pretty);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to print address for %s: %m", name);
+
+                        printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
+                }
+                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_read(reply, "s", &canonical);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                if (!streq(hostname, canonical))
+                        printf("%*s(%s)\n", (int) indent, "", canonical);
+
+                r = sd_bus_message_exit_container(reply);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                c++;
+        }
+        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_enter_container(reply, 'a', "ay");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        c = 0;
+        while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) {
+                _cleanup_free_ char *escaped = NULL;
+
+                escaped = cescape_length(p, sz);
+                if (!escaped)
+                        return log_oom();
+
+                printf("%*s%s\n", (int) indent, "", escaped);
+                c++;
+        }
+        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_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (isempty(canonical_name))
+                canonical_name = NULL;
+        if (isempty(canonical_type))
+                canonical_type = NULL;
+
+        if (!streq_ptr(name, canonical_name) ||
+            !streq_ptr(type, canonical_type) ||
+            !streq_ptr(domain, canonical_domain)) {
+
+                printf("%*s(", (int) indent, "");
+
+                if (canonical_name)
+                        printf("%s/", canonical_name);
+                if (canonical_type)
+                        printf("%s/", canonical_type);
+
+                printf("%s)\n", canonical_domain);
+        }
+
+        print_source(flags, ts);
+
+        return 0;
+}
+
+static int show_statistics(sd_bus *bus) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        uint64_t n_current_transactions, n_total_transactions,
+                cache_size, n_cache_hit, n_cache_miss,
+                n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
+        int r, dnssec_supported;
+
+        assert(bus);
+
+        r = sd_bus_get_property_trivial(bus,
+                                        "org.freedesktop.resolve1",
+                                        "/org/freedesktop/resolve1",
+                                        "org.freedesktop.resolve1.Manager",
+                                        "DNSSECSupported",
+                                        &error,
+                                        'b',
+                                        &dnssec_supported);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
+
+        printf("DNSSEC supported by current servers: %s%s%s\n\n",
+               ansi_highlight(),
+               yes_no(dnssec_supported),
+               ansi_normal());
+
+        r = sd_bus_get_property(bus,
+                                "org.freedesktop.resolve1",
+                                "/org/freedesktop/resolve1",
+                                "org.freedesktop.resolve1.Manager",
+                                "TransactionStatistics",
+                                &error,
+                                &reply,
+                                "(tt)");
+        if (r < 0)
+                return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
+
+        r = sd_bus_message_read(reply, "(tt)",
+                                &n_current_transactions,
+                                &n_total_transactions);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        printf("%sTransactions%s\n"
+               "Current Transactions: %" PRIu64 "\n"
+               "  Total Transactions: %" PRIu64 "\n",
+               ansi_highlight(),
+               ansi_normal(),
+               n_current_transactions,
+               n_total_transactions);
+
+        reply = sd_bus_message_unref(reply);
+
+        r = sd_bus_get_property(bus,
+                                "org.freedesktop.resolve1",
+                                "/org/freedesktop/resolve1",
+                                "org.freedesktop.resolve1.Manager",
+                                "CacheStatistics",
+                                &error,
+                                &reply,
+                                "(ttt)");
+        if (r < 0)
+                return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r));
+
+        r = sd_bus_message_read(reply, "(ttt)",
+                                &cache_size,
+                                &n_cache_hit,
+                                &n_cache_miss);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        printf("\n%sCache%s\n"
+               "  Current Cache Size: %" PRIu64 "\n"
+               "          Cache Hits: %" PRIu64 "\n"
+               "        Cache Misses: %" PRIu64 "\n",
+               ansi_highlight(),
+               ansi_normal(),
+               cache_size,
+               n_cache_hit,
+               n_cache_miss);
+
+        reply = sd_bus_message_unref(reply);
+
+        r = sd_bus_get_property(bus,
+                                "org.freedesktop.resolve1",
+                                "/org/freedesktop/resolve1",
+                                "org.freedesktop.resolve1.Manager",
+                                "DNSSECStatistics",
+                                &error,
+                                &reply,
+                                "(tttt)");
+        if (r < 0)
+                return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r));
+
+        r = sd_bus_message_read(reply, "(tttt)",
+                                &n_dnssec_secure,
+                                &n_dnssec_insecure,
+                                &n_dnssec_bogus,
+                                &n_dnssec_indeterminate);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        printf("\n%sDNSSEC Verdicts%s\n"
+               "              Secure: %" PRIu64 "\n"
+               "            Insecure: %" PRIu64 "\n"
+               "               Bogus: %" PRIu64 "\n"
+               "       Indeterminate: %" PRIu64 "\n",
+               ansi_highlight(),
+               ansi_normal(),
+               n_dnssec_secure,
+               n_dnssec_insecure,
+               n_dnssec_bogus,
+               n_dnssec_indeterminate);
+
+        return 0;
+}
+
+static int reset_statistics(sd_bus *bus) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
+
+        r = sd_bus_call_method(bus,
+                               "org.freedesktop.resolve1",
+                               "/org/freedesktop/resolve1",
+                               "org.freedesktop.resolve1.Manager",
+                               "ResetStatistics",
+                               &error,
+                               NULL,
+                               NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r));
+
+        return 0;
+}
+
+static void help_protocol_types(void) {
+        if (arg_legend)
+                puts("Known protocol types:");
+        puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6");
+}
+
+static void help_dns_types(void) {
+        int i;
+        const char *t;
+
+        if (arg_legend)
+                puts("Known DNS RR types:");
+        for (i = 0; i < _DNS_TYPE_MAX; i++) {
+                t = dns_type_to_string(i);
+                if (t)
+                        puts(t);
+        }
+}
+
+static void help_dns_classes(void) {
+        int i;
+        const char *t;
+
+        if (arg_legend)
+                puts("Known DNS RR classes:");
+        for (i = 0; i < _DNS_CLASS_MAX; i++) {
+                t = dns_class_to_string(i);
+                if (t)
+                        puts(t);
+        }
+}
+
+static void help(void) {
+        printf("%s [OPTIONS...] NAME...\n"
+               "%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n"
+               "Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
+               "  -h --help                   Show this help\n"
+               "     --version                Show package version\n"
+               "  -4                          Resolve IPv4 addresses\n"
+               "  -6                          Resolve IPv6 addresses\n"
+               "  -i --interface=INTERFACE    Look on interface\n"
+               "  -p --protocol=PROTOCOL|help Look via protocol\n"
+               "  -t --type=TYPE|help         Query RR with DNS type\n"
+               "  -c --class=CLASS|help       Query RR with DNS class\n"
+               "     --service                Resolve service (SRV)\n"
+               "     --service-address=BOOL   Do [not] resolve address for services\n"
+               "     --service-txt=BOOL       Do [not] resolve TXT records for services\n"
+               "     --cname=BOOL             Do [not] follow CNAME redirects\n"
+               "     --search=BOOL            Do [not] use search domains\n"
+               "     --legend=BOOL            Do [not] print column headers and meta information\n"
+               "     --statistics             Show resolver statistics\n"
+               "     --reset-statistics       Reset resolver statistics\n"
+               , program_invocation_short_name, program_invocation_short_name);
+}
+
+static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_LEGEND,
+                ARG_SERVICE,
+                ARG_CNAME,
+                ARG_SERVICE_ADDRESS,
+                ARG_SERVICE_TXT,
+                ARG_SEARCH,
+                ARG_STATISTICS,
+                ARG_RESET_STATISTICS,
+        };
+
+        static const struct option options[] = {
+                { "help",             no_argument,       NULL, 'h'                  },
+                { "version",          no_argument,       NULL, ARG_VERSION          },
+                { "type",             required_argument, NULL, 't'                  },
+                { "class",            required_argument, NULL, 'c'                  },
+                { "legend",           required_argument, NULL, ARG_LEGEND           },
+                { "interface",        required_argument, NULL, 'i'                  },
+                { "protocol",         required_argument, NULL, 'p'                  },
+                { "cname",            required_argument, NULL, ARG_CNAME            },
+                { "service",          no_argument,       NULL, ARG_SERVICE          },
+                { "service-address",  required_argument, NULL, ARG_SERVICE_ADDRESS  },
+                { "service-txt",      required_argument, NULL, ARG_SERVICE_TXT      },
+                { "search",           required_argument, NULL, ARG_SEARCH           },
+                { "statistics",       no_argument,       NULL, ARG_STATISTICS,      },
+                { "reset-statistics", no_argument,       NULL, ARG_RESET_STATISTICS },
+                {}
+        };
+
+        int c, r;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
+                switch(c) {
+
+                case 'h':
+                        help();
+                        return 0; /* done */;
+
+                case ARG_VERSION:
+                        return version();
+
+                case '4':
+                        arg_family = AF_INET;
+                        break;
+
+                case '6':
+                        arg_family = AF_INET6;
+                        break;
+
+                case 'i': {
+                        int ifi;
+
+                        if (parse_ifindex(optarg, &ifi) >= 0)
+                                arg_ifindex = ifi;
+                        else {
+                                ifi = if_nametoindex(optarg);
+                                if (ifi <= 0)
+                                        return log_error_errno(errno, "Unknown interface %s: %m", optarg);
+
+                                arg_ifindex = ifi;
+                        }
+
+                        break;
+                }
+
+                case 't':
+                        if (streq(optarg, "help")) {
+                                help_dns_types();
+                                return 0;
+                        }
+
+                        r = dns_type_from_string(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse RR record type %s", optarg);
+                                return r;
+                        }
+                        arg_type = (uint16_t) r;
+                        assert((int) arg_type == r);
+
+                        arg_mode = MODE_RESOLVE_RECORD;
+                        break;
+
+                case 'c':
+                        if (streq(optarg, "help")) {
+                                help_dns_classes();
+                                return 0;
+                        }
+
+                        r = dns_class_from_string(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse RR record class %s", optarg);
+                                return r;
+                        }
+                        arg_class = (uint16_t) r;
+                        assert((int) arg_class == r);
+
+                        break;
+
+                case ARG_LEGEND:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --legend= argument");
+
+                        arg_legend = r;
+                        break;
+
+                case 'p':
+                        if (streq(optarg, "help")) {
+                                help_protocol_types();
+                                return 0;
+                        } else if (streq(optarg, "dns"))
+                                arg_flags |= SD_RESOLVED_DNS;
+                        else if (streq(optarg, "llmnr"))
+                                arg_flags |= SD_RESOLVED_LLMNR;
+                        else if (streq(optarg, "llmnr-ipv4"))
+                                arg_flags |= SD_RESOLVED_LLMNR_IPV4;
+                        else if (streq(optarg, "llmnr-ipv6"))
+                                arg_flags |= SD_RESOLVED_LLMNR_IPV6;
+                        else {
+                                log_error("Unknown protocol specifier: %s", optarg);
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case ARG_SERVICE:
+                        arg_mode = MODE_RESOLVE_SERVICE;
+                        break;
+
+                case ARG_CNAME:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --cname= argument.");
+                        if (r == 0)
+                                arg_flags |= SD_RESOLVED_NO_CNAME;
+                        else
+                                arg_flags &= ~SD_RESOLVED_NO_CNAME;
+                        break;
+
+                case ARG_SERVICE_ADDRESS:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --service-address= argument.");
+                        if (r == 0)
+                                arg_flags |= SD_RESOLVED_NO_ADDRESS;
+                        else
+                                arg_flags &= ~SD_RESOLVED_NO_ADDRESS;
+                        break;
+
+                case ARG_SERVICE_TXT:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --service-txt= argument.");
+                        if (r == 0)
+                                arg_flags |= SD_RESOLVED_NO_TXT;
+                        else
+                                arg_flags &= ~SD_RESOLVED_NO_TXT;
+                        break;
+
+                case ARG_SEARCH:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --search argument.");
+                        if (r == 0)
+                                arg_flags |= SD_RESOLVED_NO_SEARCH;
+                        else
+                                arg_flags &= ~SD_RESOLVED_NO_SEARCH;
+                        break;
+
+                case ARG_STATISTICS:
+                        arg_mode = MODE_STATISTICS;
+                        break;
+
+                case ARG_RESET_STATISTICS:
+                        arg_mode = MODE_RESET_STATISTICS;
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unhandled option");
+                }
+
+        if (arg_type == 0 && arg_class != 0) {
+                log_error("--class= may only be used in conjunction with --type=.");
+                return -EINVAL;
+        }
+
+        if (arg_type != 0 && arg_mode != MODE_RESOLVE_RECORD) {
+                log_error("--service and --type= may not be combined.");
+                return -EINVAL;
+        }
+
+        if (arg_type != 0 && arg_class == 0)
+                arg_class = DNS_CLASS_IN;
+
+        if (arg_class != 0 && arg_type == 0)
+                arg_type = DNS_TYPE_A;
+
+        return 1 /* work to do */;
+}
+
+int main(int argc, char **argv) {
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        int r;
+
+        log_parse_environment();
+        log_open();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0) {
+                log_error_errno(r, "sd_bus_open_system: %m");
+                goto finish;
+        }
+
+        switch (arg_mode) {
+
+        case MODE_RESOLVE_HOST:
+                if (optind >= argc) {
+                        log_error("No arguments passed.");
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                while (argv[optind]) {
+                        int family, ifindex, k;
+                        union in_addr_union a;
+
+                        if (startswith(argv[optind], "dns:"))
+                                k = resolve_rfc4501(bus, argv[optind]);
+                        else {
+                                k = parse_address(argv[optind], &family, &a, &ifindex);
+                                if (k >= 0)
+                                        k = resolve_address(bus, family, &a, ifindex);
+                                else
+                                        k = resolve_host(bus, argv[optind]);
+                        }
+
+                        if (r == 0)
+                                r = k;
+
+                        optind++;
+                }
+                break;
+
+        case MODE_RESOLVE_RECORD:
+                if (optind >= argc) {
+                        log_error("No arguments passed.");
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                while (argv[optind]) {
+                        int k;
+
+                        k = resolve_record(bus, argv[optind], arg_class, arg_type);
+                        if (r == 0)
+                                r = k;
+
+                        optind++;
+                }
+                break;
+
+        case MODE_RESOLVE_SERVICE:
+                if (argc < optind + 1) {
+                        log_error("Domain specification required.");
+                        r = -EINVAL;
+                        goto finish;
+
+                } else if (argc == optind + 1)
+                        r = resolve_service(bus, NULL, NULL, argv[optind]);
+                else if (argc == optind + 2)
+                        r = resolve_service(bus, NULL, argv[optind], argv[optind+1]);
+                else if (argc == optind + 3)
+                        r = resolve_service(bus, argv[optind], argv[optind+1], argv[optind+2]);
+                else {
+                        log_error("Too many arguments.");
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                break;
+
+        case MODE_STATISTICS:
+                if (argc > optind) {
+                        log_error("Too many arguments.");
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                r = show_statistics(bus);
+                break;
+
+        case MODE_RESET_STATISTICS:
+                if (argc > optind) {
+                        log_error("Too many arguments.");
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                r = reset_statistics(bus);
+                break;
+        }
+
+finish:
+        return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
index f0a3b607d4a85d7716e7a088b4f31bcde7098059..fc5e6beca04431f26d03d7ab66361c77c485b333 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "dns-domain.h"
 #include "resolved-bus.h"
 #include "resolved-def.h"
+#include "resolved-link-bus.h"
 
 static int reply_query_state(DnsQuery *q) {
-        _cleanup_free_ char *ip = NULL;
-        const char *name;
-        int r;
-
-        if (q->request_hostname)
-                name = q->request_hostname;
-        else {
-                r = in_addr_to_string(q->request_family, &q->request_address, &ip);
-                if (r < 0)
-                        return r;
-
-                name = ip;
-        }
 
         switch (q->state) {
 
@@ -55,20 +41,38 @@ static int reply_query_state(DnsQuery *q) {
         case DNS_TRANSACTION_INVALID_REPLY:
                 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
 
-        case DNS_TRANSACTION_RESOURCES:
-                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
+        case DNS_TRANSACTION_ERRNO:
+                return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m");
 
         case DNS_TRANSACTION_ABORTED:
                 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
 
-        case DNS_TRANSACTION_FAILURE: {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        case DNS_TRANSACTION_DNSSEC_FAILED:
+                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
+                                                  dnssec_result_to_string(q->answer_dnssec_result));
+
+        case DNS_TRANSACTION_NO_TRUST_ANCHOR:
+                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
+
+        case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
+                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
+
+        case DNS_TRANSACTION_NETWORK_DOWN:
+                return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down");
+
+        case DNS_TRANSACTION_NOT_FOUND:
+                /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
+                 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
+                return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
+
+        case DNS_TRANSACTION_RCODE_FAILURE: {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
-                        sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
+                        sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
                 else {
                         const char *rc, *n;
-                        char p[3]; /* the rcode is 4 bits long */
+                        char p[DECIMAL_STR_MAX(q->answer_rcode)];
 
                         rc = dns_rcode_to_string(q->answer_rcode);
                         if (!rc) {
@@ -77,7 +81,7 @@ static int reply_query_state(DnsQuery *q) {
                         }
 
                         n = strjoina(_BUS_ERROR_DNS, rc);
-                        sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
+                        sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc);
                 }
 
                 return sd_bus_reply_method_error(q->request, &error);
@@ -85,6 +89,7 @@ static int reply_query_state(DnsQuery *q) {
 
         case DNS_TRANSACTION_NULL:
         case DNS_TRANSACTION_PENDING:
+        case DNS_TRANSACTION_VALIDATING:
         case DNS_TRANSACTION_SUCCESS:
         default:
                 assert_not_reached("Impossible state");
@@ -132,11 +137,11 @@ static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifin
 }
 
 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
-        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
-        unsigned added = 0, i;
-        int r;
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        DnsResourceRecord *rr;
+        unsigned added = 0;
+        int ifindex, r;
 
         assert(q);
 
@@ -145,6 +150,16 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
                 goto finish;
         }
 
+        r = dns_query_process_cname(q);
+        if (r == -ELOOP) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
+                goto finish;
+        }
+        if (r < 0)
+                goto finish;
+        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+                return;
+
         r = sd_bus_message_new_method_return(q->request, &reply);
         if (r < 0)
                 goto finish;
@@ -153,93 +168,42 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        if (q->answer) {
-                answer = dns_answer_ref(q->answer);
-
-                for (i = 0; i < answer->n_rrs; i++) {
-                        r = dns_question_matches_rr(q->question, answer->items[i].rr);
-                        if (r < 0)
-                                goto finish;
-                        if (r == 0) {
-                                /* Hmm, if this is not an address record,
-                                   maybe it's a cname? If so, remember this */
-                                r = dns_question_matches_cname(q->question, answer->items[i].rr);
-                                if (r < 0)
-                                        goto finish;
-                                if (r > 0)
-                                        cname = dns_resource_record_ref(answer->items[i].rr);
-
-                                continue;
-                        }
-
-                        r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
-                        if (r < 0)
-                                goto finish;
+        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
+                DnsQuestion *question;
 
-                        if (!canonical)
-                                canonical = dns_resource_record_ref(answer->items[i].rr);
-
-                        added ++;
-                }
-        }
+                question = dns_query_question_for_protocol(q, q->answer_protocol);
 
-        if (added == 0) {
-                if (!cname) {
-                        r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of requested type", q->request_hostname);
+                r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
+                if (r < 0)
                         goto finish;
-                }
-
-                /* This has a cname? Then update the query with the
-                 * new cname. */
-                r = dns_query_cname_redirect(q, cname);
-                if (r < 0) {
-                        if (r == -ELOOP)
-                                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
-                        else
-                                r = sd_bus_reply_method_errno(q->request, -r, NULL);
+                if (r == 0)
+                        continue;
 
+                r = append_address(reply, rr, ifindex);
+                if (r < 0)
                         goto finish;
-                }
-
-                /* Before we restart the query, let's see if any of
-                 * the RRs we already got already answers our query */
-                for (i = 0; i < answer->n_rrs; i++) {
-                        r = dns_question_matches_rr(q->question, answer->items[i].rr);
-                        if (r < 0)
-                                goto finish;
-                        if (r == 0)
-                                continue;
-
-                        r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
-                        if (r < 0)
-                                goto finish;
 
-                        if (!canonical)
-                                canonical = dns_resource_record_ref(answer->items[i].rr);
-
-                        added++;
-                }
+                if (!canonical)
+                        canonical = dns_resource_record_ref(rr);
 
-                /* If we didn't find anything, then let's restart the
-                 * query, this time with the cname */
-                if (added <= 0) {
-                        r = dns_query_go(q);
-                        if (r < 0) {
-                                r = sd_bus_reply_method_errno(q->request, -r, NULL);
-                                goto finish;
-                        }
+                added ++;
+        }
 
-                        return;
-                }
+        if (added <= 0) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
+                goto finish;
         }
 
         r = sd_bus_message_close_container(reply);
         if (r < 0)
                 goto finish;
 
-        /* Return the precise spelling and uppercasing reported by the server */
+        /* Return the precise spelling and uppercasing and CNAME target reported by the server */
         assert(canonical);
-        r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+        r = sd_bus_message_append(
+                        reply, "st",
+                        DNS_RESOURCE_KEY_NAME(canonical->key),
+                        SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
         if (r < 0)
                 goto finish;
 
@@ -248,29 +212,29 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
 finish:
         if (r < 0) {
                 log_error_errno(r, "Failed to send hostname reply: %m");
-                sd_bus_reply_method_errno(q->request, -r, NULL);
+                sd_bus_reply_method_errno(q->request, r, NULL);
         }
 
         dns_query_free(q);
 }
 
-static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
+static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
         assert(flags);
 
         if (ifindex < 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
-        if (*flags & ~SD_RESOLVED_FLAGS_ALL)
+        if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
 
-        if (*flags == 0)
-                *flags = SD_RESOLVED_FLAGS_DEFAULT;
+        if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
+                *flags |= SD_RESOLVED_PROTOCOLS_ALL;
 
         return 0;
 }
 
 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
+        _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
         Manager *m = userdata;
         const char *hostname;
         int family, ifindex;
@@ -281,6 +245,8 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
         assert(message);
         assert(m);
 
+        assert_cc(sizeof(int) == sizeof(int32_t));
+
         r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
         if (r < 0)
                 return r;
@@ -288,69 +254,54 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
         if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
 
-        r = dns_name_normalize(hostname, NULL);
+        r = dns_name_is_valid(hostname);
         if (r < 0)
+                return r;
+        if (r == 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
 
-        r = check_ifindex_flags(ifindex, &flags, error);
+        r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
         if (r < 0)
                 return r;
 
-        question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
-        if (!question)
-                return -ENOMEM;
-
-        if (family != AF_INET6) {
-                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
-                key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
-                if (!key)
-                        return -ENOMEM;
-
-                r = dns_question_add(question, key);
-                if (r < 0)
-                        return r;
-        }
-
-        if (family != AF_INET) {
-                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
-                key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
-                if (!key)
-                        return -ENOMEM;
+        r = dns_question_new_address(&question_utf8, family, hostname, false);
+        if (r < 0)
+                return r;
 
-                r = dns_question_add(question, key);
-                if (r < 0)
-                        return r;
-        }
+        r = dns_question_new_address(&question_idna, family, hostname, true);
+        if (r < 0)
+                return r;
 
-        r = dns_query_new(m, &q, question, ifindex, flags);
+        r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags);
         if (r < 0)
                 return r;
 
         q->request = sd_bus_message_ref(message);
         q->request_family = family;
-        q->request_hostname = hostname;
         q->complete = bus_method_resolve_hostname_complete;
+        q->suppress_unroutable_family = family == AF_UNSPEC;
 
         r = dns_query_bus_track(q, message);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = dns_query_go(q);
-        if (r < 0) {
-                dns_query_free(q);
-                return r;
-        }
+        if (r < 0)
+                goto fail;
 
         return 1;
+
+fail:
+        dns_query_free(q);
+        return r;
 }
 
 static void bus_method_resolve_address_complete(DnsQuery *q) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
-        unsigned added = 0, i;
-        int r;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        DnsQuestion *question;
+        DnsResourceRecord *rr;
+        unsigned added = 0;
+        int ifindex, r;
 
         assert(q);
 
@@ -359,6 +310,16 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
                 goto finish;
         }
 
+        r = dns_query_process_cname(q);
+        if (r == -ELOOP) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
+                goto finish;
+        }
+        if (r < 0)
+                goto finish;
+        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+                return;
+
         r = sd_bus_message_new_method_return(q->request, &reply);
         if (r < 0)
                 goto finish;
@@ -367,30 +328,27 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        if (q->answer) {
-                answer = dns_answer_ref(q->answer);
+        question = dns_query_question_for_protocol(q, q->answer_protocol);
 
-                for (i = 0; i < answer->n_rrs; i++) {
-                        r = dns_question_matches_rr(q->question, answer->items[i].rr);
-                        if (r < 0)
-                                goto finish;
-                        if (r == 0)
-                                continue;
+        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
+                r = dns_question_matches_rr(question, rr, NULL);
+                if (r < 0)
+                        goto finish;
+                if (r == 0)
+                        continue;
 
-                        r = sd_bus_message_append(reply, "(is)", answer->items[i].ifindex, answer->items[i].rr->ptr.name);
-                        if (r < 0)
-                                goto finish;
+                r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
+                if (r < 0)
+                        goto finish;
 
-                        added ++;
-                }
+                added ++;
         }
 
-        if (added == 0) {
+        if (added <= 0) {
                 _cleanup_free_ char *ip = NULL;
 
                 in_addr_to_string(q->request_family, &q->request_address, &ip);
-
-                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip));
                 goto finish;
         }
 
@@ -398,7 +356,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
         if (r < 0)
                 goto finish;
 
@@ -407,16 +365,14 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
 finish:
         if (r < 0) {
                 log_error_errno(r, "Failed to send address reply: %m");
-                sd_bus_reply_method_errno(q->request, -r, NULL);
+                sd_bus_reply_method_errno(q->request, r, NULL);
         }
 
         dns_query_free(q);
 }
 
 static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
-        _cleanup_free_ char *reverse = NULL;
         Manager *m = userdata;
         int family, ifindex;
         uint64_t flags;
@@ -428,6 +384,8 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
         assert(message);
         assert(m);
 
+        assert_cc(sizeof(int) == sizeof(int32_t));
+
         r = sd_bus_message_read(message, "ii", &ifindex, &family);
         if (r < 0)
                 return r;
@@ -446,29 +404,15 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
         if (r < 0)
                 return r;
 
-        r = check_ifindex_flags(ifindex, &flags, error);
-        if (r < 0)
-                return r;
-
-        r = dns_name_reverse(family, d, &reverse);
+        r = check_ifindex_flags(ifindex, &flags, 0, error);
         if (r < 0)
                 return r;
 
-        question = dns_question_new(1);
-        if (!question)
-                return -ENOMEM;
-
-        key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
-        if (!key)
-                return -ENOMEM;
-
-        reverse = NULL;
-
-        r = dns_question_add(question, key);
+        r = dns_question_new_reverse(&question, family, d);
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question, ifindex, flags);
+        r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
         if (r < 0)
                 return r;
 
@@ -479,21 +423,53 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
 
         r = dns_query_bus_track(q, message);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = dns_query_go(q);
-        if (r < 0) {
-                dns_query_free(q);
-                return r;
-        }
+        if (r < 0)
+                goto fail;
 
         return 1;
+
+fail:
+        dns_query_free(q);
+        return r;
+}
+
+static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
+        int r;
+
+        assert(m);
+        assert(rr);
+
+        r = sd_bus_message_open_container(m, 'r', "iqqay");
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "iqq",
+                                  ifindex,
+                                  rr->key->class,
+                                  rr->key->type);
+        if (r < 0)
+                return r;
+
+        r = dns_resource_record_to_wire_format(rr, false);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
+        if (r < 0)
+                return r;
+
+        return sd_bus_message_close_container(m);
 }
 
 static void bus_method_resolve_record_complete(DnsQuery *q) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
-        unsigned added = 0, i;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        DnsResourceRecord *rr;
+        DnsQuestion *question;
+        unsigned added = 0;
+        int ifindex;
         int r;
 
         assert(q);
@@ -503,6 +479,16 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
                 goto finish;
         }
 
+        r = dns_query_process_cname(q);
+        if (r == -ELOOP) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
+                goto finish;
+        }
+        if (r < 0)
+                goto finish;
+        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+                return;
+
         r = sd_bus_message_new_method_return(q->request, &reply);
         if (r < 0)
                 goto finish;
@@ -511,54 +497,24 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        if (q->answer) {
-                answer = dns_answer_ref(q->answer);
-
-                for (i = 0; i < answer->n_rrs; i++) {
-                        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
-                        size_t start;
-
-                        r = dns_question_matches_rr(q->question, answer->items[i].rr);
-                        if (r < 0)
-                                goto finish;
-                        if (r == 0)
-                                continue;
-
-                        r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
-                        if (r < 0)
-                                goto finish;
-
-                        p->refuse_compression = true;
-
-                        r = dns_packet_append_rr(p, answer->items[i].rr, &start);
-                        if (r < 0)
-                                goto finish;
-
-                        r = sd_bus_message_open_container(reply, 'r', "iqqay");
-                        if (r < 0)
-                                goto finish;
-
-                        r = sd_bus_message_append(reply, "iqq",
-                                                  answer->items[i].ifindex,
-                                                  answer->items[i].rr->key->class,
-                                                  answer->items[i].rr->key->type);
-                        if (r < 0)
-                                goto finish;
+        question = dns_query_question_for_protocol(q, q->answer_protocol);
 
-                        r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
-                        if (r < 0)
-                                goto finish;
+        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
+                r = dns_question_matches_rr(question, rr, NULL);
+                if (r < 0)
+                        goto finish;
+                if (r == 0)
+                        continue;
 
-                        r = sd_bus_message_close_container(reply);
-                        if (r < 0)
-                                goto finish;
+                r = bus_message_append_rr(reply, rr, ifindex);
+                if (r < 0)
+                        goto finish;
 
-                        added ++;
-                }
+                added ++;
         }
 
         if (added <= 0) {
-                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", q->request_hostname);
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q));
                 goto finish;
         }
 
@@ -566,7 +522,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
         if (r < 0)
                 goto finish;
 
@@ -575,7 +531,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
 finish:
         if (r < 0) {
                 log_error_errno(r, "Failed to send record reply: %m");
-                sd_bus_reply_method_errno(q->request, -r, NULL);
+                sd_bus_reply_method_errno(q->request, r, NULL);
         }
 
         dns_query_free(q);
@@ -594,15 +550,24 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
         assert(message);
         assert(m);
 
+        assert_cc(sizeof(int) == sizeof(int32_t));
+
         r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
         if (r < 0)
                 return r;
 
-        r = dns_name_normalize(name, NULL);
+        r = dns_name_is_valid(name);
         if (r < 0)
+                return r;
+        if (r == 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
 
-        r = check_ifindex_flags(ifindex, &flags, error);
+        if (!dns_type_is_valid_query(type))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
+        if (dns_type_is_obsolete(type))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
+
+        r = check_ifindex_flags(ifindex, &flags, 0, error);
         if (r < 0)
                 return r;
 
@@ -618,95 +583,964 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question, ifindex, flags);
+        r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
         if (r < 0)
                 return r;
 
         q->request = sd_bus_message_ref(message);
-        q->request_hostname = name;
         q->complete = bus_method_resolve_record_complete;
 
         r = dns_query_bus_track(q, message);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = dns_query_go(q);
-        if (r < 0) {
-                dns_query_free(q);
-                return r;
-        }
+        if (r < 0)
+                goto fail;
 
         return 1;
+
+fail:
+        dns_query_free(q);
+        return r;
 }
 
-static const sd_bus_vtable resolve_vtable[] = {
-        SD_BUS_VTABLE_START(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),
-        SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_VTABLE_END,
-};
+static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
+        DnsQuery *aux;
+        int r;
 
-static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
-        Manager *m = userdata;
+        assert(q);
+        assert(reply);
+        assert(rr);
+        assert(rr->key);
 
-        assert(s);
-        assert(m);
+        if (rr->key->type != DNS_TYPE_SRV)
+                return 0;
 
-        m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
+        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
+                /* First, let's see if we could find an appropriate A or AAAA
+                 * record for the SRV record */
+                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
+                        DnsResourceRecord *zz;
+                        DnsQuestion *question;
 
-        manager_connect_bus(m);
-        return 0;
-}
+                        if (aux->state != DNS_TRANSACTION_SUCCESS)
+                                continue;
+                        if (aux->auxiliary_result != 0)
+                                continue;
 
-static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
-        Manager *m = userdata;
-        int b, r;
+                        question = dns_query_question_for_protocol(aux, aux->answer_protocol);
 
-        assert(message);
-        assert(m);
+                        r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
 
-        r = sd_bus_message_read(message, "b", &b);
-        if (r < 0) {
-                log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
-                return 0;
-        }
+                        DNS_ANSWER_FOREACH(zz, aux->answer) {
 
-        if (b)
-                return 0;
+                                r = dns_question_matches_rr(question, zz, NULL);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        continue;
 
-        log_debug("Coming back from suspend, verifying all RRs...");
+                                canonical = dns_resource_record_ref(zz);
+                                break;
+                        }
 
-        manager_verify_all(m);
-        return 0;
-}
+                        if (canonical)
+                                break;
+                }
 
-int manager_connect_bus(Manager *m) {
-        int r;
+                /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
+                if (!canonical)
+                        return 0;
+        }
 
-        assert(m);
+        r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
+        if (r < 0)
+                return r;
 
-        if (m->bus)
-                return 0;
+        r = sd_bus_message_append(
+                        reply,
+                        "qqqs",
+                        rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
+        if (r < 0)
+                return r;
 
-        r = sd_bus_default_system(&m->bus);
-        if (r < 0) {
-                /* We failed to connect? Yuck, we must be in early
-                 * boot. Let's try in 5s again. As soon as we have
-                 * kdbus we can stop doing this... */
+        r = sd_bus_message_open_container(reply, 'a', "(iiay)");
+        if (r < 0)
+                return r;
 
-                log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
+        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
+                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
+                        DnsResourceRecord *zz;
+                        DnsQuestion *question;
+                        int ifindex;
 
-                r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to install bus reconnect time event: %m");
+                        if (aux->state != DNS_TRANSACTION_SUCCESS)
+                                continue;
+                        if (aux->auxiliary_result != 0)
+                                continue;
 
-                return 0;
-        }
+                        question = dns_query_question_for_protocol(aux, aux->answer_protocol);
 
-        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
-        if (r < 0)
-                return log_error_errno(r, "Failed to register object: %m");
+                        r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
+
+                                r = dns_question_matches_rr(question, zz, NULL);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        continue;
+
+                                r = append_address(reply, zz, ifindex);
+                                if (r < 0)
+                                        return r;
+                        }
+                }
+        }
+
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return r;
+
+        /* Note that above we appended the hostname as encoded in the
+         * SRV, and here the canonical hostname this maps to. */
+        r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
+        DnsTxtItem *i;
+        int r;
+
+        assert(reply);
+        assert(rr);
+        assert(rr->key);
+
+        if (rr->key->type != DNS_TYPE_TXT)
+                return 0;
+
+        LIST_FOREACH(items, i, rr->txt.items) {
+
+                if (i->length <= 0)
+                        continue;
+
+                r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
+                if (r < 0)
+                        return r;
+        }
+
+        return 1;
+}
+
+static void resolve_service_all_complete(DnsQuery *q) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
+        DnsQuestion *question;
+        DnsResourceRecord *rr;
+        unsigned added = 0;
+        DnsQuery *aux;
+        int r;
+
+        assert(q);
+
+        if (q->block_all_complete > 0)
+                return;
+
+        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
+                DnsQuery *bad = NULL;
+                bool have_success = false;
+
+                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
+
+                        switch (aux->state) {
+
+                        case DNS_TRANSACTION_PENDING:
+                                /* If an auxiliary query is still pending, let's wait */
+                                return;
+
+                        case DNS_TRANSACTION_SUCCESS:
+                                if (aux->auxiliary_result == 0)
+                                        have_success = true;
+                                else
+                                        bad = aux;
+                                break;
+
+                        default:
+                                bad = aux;
+                                break;
+                        }
+                }
+
+                if (!have_success) {
+                        /* We can only return one error, hence pick the last error we encountered */
+
+                        assert(bad);
+
+                        if (bad->state == DNS_TRANSACTION_SUCCESS) {
+                                assert(bad->auxiliary_result != 0);
+
+                                if (bad->auxiliary_result == -ELOOP) {
+                                        r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad));
+                                        goto finish;
+                                }
+
+                                r = bad->auxiliary_result;
+                                goto finish;
+                        }
+
+                        r = reply_query_state(bad);
+                        goto finish;
+                }
+        }
+
+        r = sd_bus_message_new_method_return(q->request, &reply);
+        if (r < 0)
+                goto finish;
+
+        r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
+        if (r < 0)
+                goto finish;
+
+        question = dns_query_question_for_protocol(q, q->answer_protocol);
+        DNS_ANSWER_FOREACH(rr, q->answer) {
+                r = dns_question_matches_rr(question, rr, NULL);
+                if (r < 0)
+                        goto finish;
+                if (r == 0)
+                        continue;
+
+                r = append_srv(q, reply, rr);
+                if (r < 0)
+                        goto finish;
+                if (r == 0) /* not an SRV record */
+                        continue;
+
+                if (!canonical)
+                        canonical = dns_resource_record_ref(rr);
+
+                added++;
+        }
+
+        if (added <= 0) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
+                goto finish;
+        }
+
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                goto finish;
+
+        r = sd_bus_message_open_container(reply, 'a', "ay");
+        if (r < 0)
+                goto finish;
+
+        DNS_ANSWER_FOREACH(rr, q->answer) {
+                r = dns_question_matches_rr(question, rr, NULL);
+                if (r < 0)
+                        goto finish;
+                if (r == 0)
+                        continue;
+
+                r = append_txt(reply, rr);
+                if (r < 0)
+                        goto finish;
+        }
+
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                goto finish;
+
+        assert(canonical);
+        r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
+        if (r < 0)
+                goto finish;
+
+        r = sd_bus_message_append(
+                        reply,
+                        "ssst",
+                        name, type, domain,
+                        SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
+        if (r < 0)
+                goto finish;
+
+        r = sd_bus_send(q->manager->bus, reply, NULL);
+
+finish:
+        if (r < 0) {
+                log_error_errno(r, "Failed to send service reply: %m");
+                sd_bus_reply_method_errno(q->request, r, NULL);
+        }
+
+        dns_query_free(q);
+}
+
+static void resolve_service_hostname_complete(DnsQuery *q) {
+        int r;
+
+        assert(q);
+        assert(q->auxiliary_for);
+
+        if (q->state != DNS_TRANSACTION_SUCCESS) {
+                resolve_service_all_complete(q->auxiliary_for);
+                return;
+        }
+
+        r = dns_query_process_cname(q);
+        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+                return;
+
+        /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
+        q->auxiliary_result = r;
+        resolve_service_all_complete(q->auxiliary_for);
+}
+
+static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
+        _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
+        DnsQuery *aux;
+        int r;
+
+        assert(q);
+        assert(rr);
+        assert(rr->key);
+        assert(rr->key->type == DNS_TYPE_SRV);
+
+        /* OK, we found an SRV record for the service. Let's resolve
+         * the hostname included in it */
+
+        r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
+        if (r < 0)
+                return r;
+
+        r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
+        if (r < 0)
+                return r;
+
+        aux->request_family = q->request_family;
+        aux->complete = resolve_service_hostname_complete;
+
+        r = dns_query_make_auxiliary(aux, q);
+        if (r == -EAGAIN) {
+                /* Too many auxiliary lookups? If so, don't complain,
+                 * let's just not add this one, we already have more
+                 * than enough */
+
+                dns_query_free(aux);
+                return 0;
+        }
+        if (r < 0)
+                goto fail;
+
+        /* Note that auxiliary queries do not track the original bus
+         * client, only the primary request does that. */
+
+        r = dns_query_go(aux);
+        if (r < 0)
+                goto fail;
+
+        return 1;
+
+fail:
+        dns_query_free(aux);
+        return r;
+}
+
+static void bus_method_resolve_service_complete(DnsQuery *q) {
+        bool has_root_domain = false;
+        DnsResourceRecord *rr;
+        DnsQuestion *question;
+        unsigned found = 0;
+        int ifindex, r;
+
+        assert(q);
+
+        if (q->state != DNS_TRANSACTION_SUCCESS) {
+                r = reply_query_state(q);
+                goto finish;
+        }
+
+        r = dns_query_process_cname(q);
+        if (r == -ELOOP) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
+                goto finish;
+        }
+        if (r < 0)
+                goto finish;
+        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+                return;
+
+        question = dns_query_question_for_protocol(q, q->answer_protocol);
+
+        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
+                r = dns_question_matches_rr(question, rr, NULL);
+                if (r < 0)
+                        goto finish;
+                if (r == 0)
+                        continue;
+
+                if (rr->key->type != DNS_TYPE_SRV)
+                        continue;
+
+                if (dns_name_is_root(rr->srv.name)) {
+                        has_root_domain = true;
+                        continue;
+                }
+
+                if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
+                        q->block_all_complete ++;
+                        r = resolve_service_hostname(q, rr, ifindex);
+                        q->block_all_complete --;
+
+                        if (r < 0)
+                                goto finish;
+                }
+
+                found++;
+        }
+
+        if (has_root_domain && found <= 0) {
+                /* If there's exactly one SRV RR and it uses
+                 * the root domain as host name, then the
+                 * service is explicitly not offered on the
+                 * domain. Report this as a recognizable
+                 * error. See RFC 2782, Section "Usage
+                 * Rules". */
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q));
+                goto finish;
+        }
+
+        if (found <= 0) {
+                r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
+                goto finish;
+        }
+
+        /* Maybe we are already finished? check now... */
+        resolve_service_all_complete(q);
+        return;
+
+finish:
+        if (r < 0) {
+                log_error_errno(r, "Failed to send service reply: %m");
+                sd_bus_reply_method_errno(q->request, r, NULL);
+        }
+
+        dns_query_free(q);
+}
+
+static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
+        const char *name, *type, *domain;
+        _cleanup_free_ char *n = NULL;
+        Manager *m = userdata;
+        int family, ifindex;
+        uint64_t flags;
+        DnsQuery *q;
+        int r;
+
+        assert(message);
+        assert(m);
+
+        assert_cc(sizeof(int) == sizeof(int32_t));
+
+        r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
+        if (r < 0)
+                return r;
+
+        if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
+
+        if (isempty(name))
+                name = NULL;
+        else if (!dns_service_name_is_valid(name))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
+
+        if (isempty(type))
+                type = NULL;
+        else if (!dns_srv_type_is_valid(type))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
+
+        r = dns_name_is_valid(domain);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
+
+        if (name && !type)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
+
+        r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
+        if (r < 0)
+                return r;
+
+        r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
+        if (r < 0)
+                return r;
+
+        r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
+        if (r < 0)
+                return r;
+
+        r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+        if (r < 0)
+                return r;
+
+        q->request = sd_bus_message_ref(message);
+        q->request_family = family;
+        q->complete = bus_method_resolve_service_complete;
+
+        r = dns_query_bus_track(q, message);
+        if (r < 0)
+                goto fail;
+
+        r = dns_query_go(q);
+        if (r < 0)
+                goto fail;
+
+        return 1;
+
+fail:
+        dns_query_free(q);
+        return r;
+}
+
+int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) {
+        int r;
+
+        assert(reply);
+        assert(s);
+
+        r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
+        if (r < 0)
+                return r;
+
+        if (with_ifindex) {
+                r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_bus_message_append(reply, "i", s->family);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
+        if (r < 0)
+                return r;
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int bus_property_get_dns_servers(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        unsigned c = 0;
+        DnsServer *s;
+        Iterator i;
+        Link *l;
+        int r;
+
+        assert(reply);
+        assert(m);
+
+        r = sd_bus_message_open_container(reply, 'a', "(iiay)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(servers, s, m->dns_servers) {
+                r = bus_dns_server_append(reply, s, true);
+                if (r < 0)
+                        return r;
+
+                c++;
+        }
+
+        HASHMAP_FOREACH(l, m->links, i) {
+                LIST_FOREACH(servers, s, l->dns_servers) {
+                        r = bus_dns_server_append(reply, s, true);
+                        if (r < 0)
+                                return r;
+                        c++;
+                }
+        }
+
+        if (c == 0) {
+                LIST_FOREACH(servers, s, m->fallback_dns_servers) {
+                        r = bus_dns_server_append(reply, s, true);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int bus_property_get_search_domains(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        DnsSearchDomain *d;
+        Iterator i;
+        Link *l;
+        int r;
+
+        assert(reply);
+        assert(m);
+
+        r = sd_bus_message_open_container(reply, 'a', "(isb)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(domains, d, m->search_domains) {
+                r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
+                if (r < 0)
+                        return r;
+        }
+
+        HASHMAP_FOREACH(l, m->links, i) {
+                LIST_FOREACH(domains, d, l->search_domains) {
+                        r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int bus_property_get_transaction_statistics(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "(tt)",
+                                     (uint64_t) hashmap_size(m->dns_transactions),
+                                     (uint64_t) m->n_transactions_total);
+}
+
+static int bus_property_get_cache_statistics(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        uint64_t size = 0, hit = 0, miss = 0;
+        Manager *m = userdata;
+        DnsScope *s;
+
+        assert(reply);
+        assert(m);
+
+        LIST_FOREACH(scopes, s, m->dns_scopes) {
+                size += dns_cache_size(&s->cache);
+                hit += s->cache.n_hit;
+                miss += s->cache.n_miss;
+        }
+
+        return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
+}
+
+static int bus_property_get_dnssec_statistics(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "(tttt)",
+                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE],
+                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE],
+                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS],
+                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
+}
+
+static int bus_property_get_dnssec_supported(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
+}
+
+static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+        DnsScope *s;
+
+        assert(message);
+        assert(m);
+
+        LIST_FOREACH(scopes, s, m->dns_scopes)
+                s->cache.n_hit = s->cache.n_miss = 0;
+
+        m->n_transactions_total = 0;
+        zero(m->n_dnssec_verdict);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
+        Link *l;
+
+        assert(m);
+        assert(ret);
+
+        if (ifindex <= 0)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
+        l = hashmap_get(m->links, INT_TO_PTR(ifindex));
+        if (!l)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
+
+        *ret = l;
+        return 0;
+}
+
+static int get_unmanaged_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
+        Link *l;
+        int r;
+
+        assert(m);
+        assert(ret);
+
+        r = get_any_link(m, ifindex, &l, error);
+        if (r < 0)
+                return r;
+
+        if (l->flags & IFF_LOOPBACK)
+                return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name);
+        if (l->is_managed)
+                return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name);
+
+        *ret = l;
+        return 0;
+}
+
+static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
+        int ifindex, r;
+        Link *l;
+
+        assert(m);
+        assert(message);
+        assert(handler);
+
+        assert_cc(sizeof(int) == sizeof(int32_t));
+        r = sd_bus_message_read(message, "i", &ifindex);
+        if (r < 0)
+                return r;
+
+        r = get_unmanaged_link(m, ifindex, &l, error);
+        if (r < 0)
+                return r;
+
+        return handler(message, l, error);
+}
+
+static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
+}
+
+static int bus_method_set_link_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_search_domains, error);
+}
+
+static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
+}
+
+static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_mdns, error);
+}
+
+static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
+}
+
+static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
+}
+
+static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_revert, error);
+}
+
+static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_free_ char *p = NULL;
+        Manager *m = userdata;
+        int r, ifindex;
+        Link *l;
+
+        assert(message);
+        assert(m);
+
+        assert_cc(sizeof(int) == sizeof(int32_t));
+        r = sd_bus_message_read(message, "i", &ifindex);
+        if (r < 0)
+                return r;
+
+        r = get_any_link(m, ifindex, &l, error);
+        if (r < 0)
+                return r;
+
+        p = link_bus_path(l);
+        if (!p)
+                return -ENOMEM;
+
+        return sd_bus_reply_method_return(message, "o", p);
+}
+
+static const sd_bus_vtable resolve_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
+        SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
+        SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0),
+        SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
+        SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
+        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_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),
+        SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
+        SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0),
+        SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0),
+        SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
+        SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
+        SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
+        SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0),
+        SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0),
+
+        SD_BUS_VTABLE_END,
+};
+
+static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
+        Manager *m = userdata;
+
+        assert(s);
+        assert(m);
+
+        m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
+
+        manager_connect_bus(m);
+        return 0;
+}
+
+static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
+        Manager *m = userdata;
+        int b, r;
+
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "b", &b);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
+                return 0;
+        }
+
+        if (b)
+                return 0;
+
+        log_debug("Coming back from suspend, verifying all RRs...");
+
+        manager_verify_all(m);
+        return 0;
+}
+
+int manager_connect_bus(Manager *m) {
+        int r;
+
+        assert(m);
+
+        if (m->bus)
+                return 0;
+
+        r = sd_bus_default_system(&m->bus);
+        if (r < 0) {
+                /* We failed to connect? Yuck, we must be in early
+                 * boot. Let's try in 5s again. As soon as we have
+                 * kdbus we can stop doing this... */
+
+                log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
+
+                r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to install bus reconnect time event: %m");
+
+                (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
+                return 0;
+        }
+
+        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register object: %m");
+
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register link objects: %m");
+
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register link enumerator: %m");
 
         r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
         if (r < 0)
index 1e728911789f0d1bef04f358402c3fb2c7ae37bd..f49e1337d2c31cd211622497b9e57bc834be3fea 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -24,3 +22,4 @@
 #include "resolved-manager.h"
 
 int manager_connect_bus(Manager *m);
+int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex);
index 920771955136d3ab56658578271b158520003b4c..bb93fbfda2d49e2ef382b320fc8c53f6bddd91f3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "resolved-conf.h"
 #include "string-util.h"
 
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) {
-        DnsServer *first;
+int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
+        union in_addr_union address;
+        int family, r;
+        DnsServer *s;
+
+        assert(m);
+        assert(word);
+
+        r = in_addr_from_string_auto(word, &family, &address);
+        if (r < 0)
+                return r;
+
+        /* Filter out duplicates */
+        s = dns_server_find(manager_get_first_dns_server(m, type), family, &address);
+        if (s) {
+                /*
+                 * Drop the marker. This is used to find the servers
+                 * that ceased to exist, see
+                 * manager_mark_dns_servers() and
+                 * manager_flush_marked_dns_servers().
+                 */
+                dns_server_move_back_and_unmark(s);
+                return 0;
+        }
+
+        return dns_server_new(m, NULL, type, NULL, family, &address);
+}
+
+int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
         int r;
 
         assert(m);
         assert(string);
 
-        first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
-
         for(;;) {
                 _cleanup_free_ char *word = NULL;
-                union in_addr_union addr;
-                bool found = false;
-                DnsServer *s;
-                int family;
 
                 r = extract_first_word(&string, &word, NULL, 0);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to parse resolved dns server syntax \"%s\": %m", string);
+                        return r;
                 if (r == 0)
                         break;
 
-                r = in_addr_from_string_auto(word, &family, &addr);
-                if (r < 0) {
-                        log_warning("Ignoring invalid DNS address '%s'", word);
-                        continue;
-                }
+                r = manager_add_dns_server_by_string(m, type, word);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word);
+        }
+
+        return 0;
+}
+
+int manager_add_search_domain_by_string(Manager *m, const char *domain) {
+        DnsSearchDomain *d;
+        bool route_only;
+        int r;
+
+        assert(m);
+        assert(domain);
+
+        route_only = *domain == '~';
+        if (route_only)
+                domain++;
+
+        if (dns_name_is_root(domain) || streq(domain, "*")) {
+                route_only = true;
+                domain = ".";
+        }
+
+        r = dns_search_domain_find(m->search_domains, domain, &d);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                dns_search_domain_move_back_and_unmark(d);
+        else {
+                r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
+                if (r < 0)
+                        return r;
+        }
+
+        d->route_only = route_only;
+        return 0;
+}
+
+int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
+        int r;
 
-                /* Filter out duplicates */
-                LIST_FOREACH(servers, s, first)
-                        if (s->family == family && in_addr_equal(family, &s->address, &addr)) {
-                                found = true;
-                                break;
-                        }
+        assert(m);
+        assert(string);
 
-                if (found)
-                        continue;
+        for(;;) {
+                _cleanup_free_ char *word = NULL;
 
-                r = dns_server_new(m, NULL, type, NULL, family, &addr);
+                r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES);
                 if (r < 0)
                         return r;
+                if (r == 0)
+                        break;
+
+                r = manager_add_search_domain_by_string(m, word);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to add search domain '%s', ignoring.", word);
         }
 
         return 0;
 }
 
-int config_parse_dnsv(
+int config_parse_dns_servers(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -95,10 +153,10 @@ int config_parse_dnsv(
 
         if (isempty(rvalue))
                 /* Empty assignment means clear the list */
-                manager_flush_dns_servers(m, ltype);
+                dns_server_unlink_all(manager_get_first_dns_server(m, ltype));
         else {
                 /* Otherwise, add to the list */
-                r = manager_parse_dns_server(m, ltype, rvalue);
+                r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue);
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue);
                         return 0;
@@ -109,11 +167,13 @@ int config_parse_dnsv(
          * /etc/resolv.conf */
         if (ltype == DNS_SERVER_SYSTEM)
                 m->read_resolv_conf = false;
+        if (ltype == DNS_SERVER_FALLBACK)
+                m->need_builtin_fallbacks = false;
 
         return 0;
 }
 
-int config_parse_support(
+int config_parse_search_domains(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -125,34 +185,52 @@ int config_parse_support(
                 void *data,
                 void *userdata) {
 
-        Support support, *v = data;
+        Manager *m = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
+        assert(m);
 
-        support = support_from_string(rvalue);
-        if (support < 0) {
-                r = parse_boolean(rvalue);
+        if (isempty(rvalue))
+                /* Empty assignment means clear the list */
+                dns_search_domain_unlink_all(m->search_domains);
+        else {
+                /* Otherwise, add to the list */
+                r = manager_parse_search_domains_and_warn(m, rvalue);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse support level '%s'. Ignoring.", rvalue);
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue);
                         return 0;
                 }
-
-                support = r ? SUPPORT_YES : SUPPORT_NO;
         }
 
-        *v = support;
+        /* If we have a manual setting, then we stop reading
+         * /etc/resolv.conf */
+        m->read_resolv_conf = false;
+
         return 0;
 }
 
 int manager_parse_config_file(Manager *m) {
+        int r;
+
         assert(m);
 
-        return config_parse_many(PKGSYSCONFDIR "/resolved.conf",
-                                 CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
-                                 "Resolve\0",
-                                 config_item_perf_lookup, resolved_gperf_lookup,
-                                 false, m);
+        r = config_parse_many(PKGSYSCONFDIR "/resolved.conf",
+                              CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
+                              "Resolve\0",
+                              config_item_perf_lookup, resolved_gperf_lookup,
+                              false, m);
+        if (r < 0)
+                return r;
+
+        if (m->need_builtin_fallbacks) {
+                r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+
 }
index b3dbea7b6b3c7aefea90283b6e33156ce4883ecf..e1fd2cceecb84f4fca91d4231c9c5be172ab4960 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include "resolved-manager.h"
 
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string);
 int manager_parse_config_file(Manager *m);
 
+int manager_add_search_domain_by_string(Manager *m, const char *domain);
+int manager_parse_search_domains_and_warn(Manager *m, const char *string);
+
+int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word);
+int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
+
 const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned length);
 
-int config_parse_dnsv(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_support(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_dns_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 config_parse_search_domains(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_dnssec(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 086d111205b3f47a44bf978ea1d57bf19a918acd..c4c1915b18beea0bcced83b967380ca15c4296aa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#define SD_RESOLVED_DNS           ((uint64_t) 1)
-#define SD_RESOLVED_LLMNR_IPV4    ((uint64_t) 2)
-#define SD_RESOLVED_LLMNR_IPV6    ((uint64_t) 4)
+#include <inttypes.h>
+
+#define SD_RESOLVED_DNS           (UINT64_C(1) << 0)
+#define SD_RESOLVED_LLMNR_IPV4    (UINT64_C(1) << 1)
+#define SD_RESOLVED_LLMNR_IPV6    (UINT64_C(1) << 2)
+#define SD_RESOLVED_MDNS_IPV4     (UINT64_C(1) << 3)
+#define SD_RESOLVED_MDNS_IPV6     (UINT64_C(1) << 4)
+#define SD_RESOLVED_NO_CNAME      (UINT64_C(1) << 5)
+#define SD_RESOLVED_NO_TXT        (UINT64_C(1) << 6)
+#define SD_RESOLVED_NO_ADDRESS    (UINT64_C(1) << 7)
+#define SD_RESOLVED_NO_SEARCH     (UINT64_C(1) << 8)
+#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
+
 #define SD_RESOLVED_LLMNR         (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
+#define SD_RESOLVED_MDNS          (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
 
-#define SD_RESOLVED_FLAGS_ALL     (SD_RESOLVED_DNS|SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
-#define SD_RESOLVED_FLAGS_DEFAULT SD_RESOLVED_FLAGS_ALL
+#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
index 3cf9c6807477f815e6929ef6854d4291bee51413..7eb303ab951455fc59e1a1afee3a6f9eb02e1fa4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,6 +20,7 @@
 #include "alloc-util.h"
 #include "dns-domain.h"
 #include "resolved-dns-answer.h"
+#include "resolved-dns-dnssec.h"
 #include "string-util.h"
 
 DnsAnswer *dns_answer_new(unsigned n) {
@@ -46,6 +45,18 @@ DnsAnswer *dns_answer_ref(DnsAnswer *a) {
         return a;
 }
 
+static void dns_answer_flush(DnsAnswer *a) {
+        DnsResourceRecord *rr;
+
+        if (!a)
+                return;
+
+        DNS_ANSWER_FOREACH(rr, a)
+                dns_resource_record_unref(rr);
+
+        a->n_rrs = 0;
+}
+
 DnsAnswer *dns_answer_unref(DnsAnswer *a) {
         if (!a)
                 return NULL;
@@ -53,11 +64,7 @@ DnsAnswer *dns_answer_unref(DnsAnswer *a) {
         assert(a->n_ref > 0);
 
         if (a->n_ref == 1) {
-                unsigned i;
-
-                for (i = 0; i < a->n_rrs; i++)
-                        dns_resource_record_unref(a->items[i].rr);
-
+                dns_answer_flush(a);
                 free(a);
         } else
                 a->n_ref--;
@@ -65,7 +72,39 @@ DnsAnswer *dns_answer_unref(DnsAnswer *a) {
         return NULL;
 }
 
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
+static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
+        assert(rr);
+
+        if (!a)
+                return -ENOSPC;
+
+        if (a->n_rrs >= a->n_allocated)
+                return -ENOSPC;
+
+        a->items[a->n_rrs++] = (DnsAnswerItem) {
+                .rr = dns_resource_record_ref(rr),
+                .ifindex = ifindex,
+                .flags = flags,
+        };
+
+        return 1;
+}
+
+static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+        int ifindex, r;
+
+        DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) {
+                r = dns_answer_add_raw(a, rr, ifindex, flags);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
         unsigned i;
         int r;
 
@@ -73,6 +112,8 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
 
         if (!a)
                 return -ENOSPC;
+        if (a->n_ref > 1)
+                return -EBUSY;
 
         for (i = 0; i < a->n_rrs; i++) {
                 if (a->items[i].ifindex != ifindex)
@@ -82,27 +123,66 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
                 if (r < 0)
                         return r;
                 if (r > 0) {
-                        /* Entry already exists, keep the entry with
-                         * the higher RR, or the one with TTL 0 */
+                        /* Don't mix contradicting TTLs (see below) */
+                        if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+                                return -EINVAL;
 
-                        if (rr->ttl == 0 || (rr->ttl > a->items[i].rr->ttl && a->items[i].rr->ttl != 0)) {
+                        /* Entry already exists, keep the entry with
+                         * the higher RR. */
+                        if (rr->ttl > a->items[i].rr->ttl) {
                                 dns_resource_record_ref(rr);
                                 dns_resource_record_unref(a->items[i].rr);
                                 a->items[i].rr = rr;
                         }
 
+                        a->items[i].flags |= flags;
                         return 0;
                 }
+
+                r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        /* There's already an RR of the same RRset in
+                         * place! Let's see if the TTLs more or less
+                         * match. We don't really care if they match
+                         * precisely, but we do care whether one is 0
+                         * and the other is not. See RFC 2181, Section
+                         * 5.2.*/
+
+                        if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+                                return -EINVAL;
+                }
         }
 
-        if (a->n_rrs >= a->n_allocated)
-                return -ENOSPC;
+        return dns_answer_add_raw(a, rr, ifindex, flags);
+}
 
-        a->items[a->n_rrs].rr = dns_resource_record_ref(rr);
-        a->items[a->n_rrs].ifindex = ifindex;
-        a->n_rrs++;
+static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+        int ifindex, r;
 
-        return 1;
+        DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) {
+                r = dns_answer_add(a, rr, ifindex, flags);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
+        int r;
+
+        assert(a);
+        assert(rr);
+
+        r = dns_answer_reserve_or_clone(a, 1);
+        if (r < 0)
+                return r;
+
+        return dns_answer_add(*a, rr, ifindex, flags);
 }
 
 int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
@@ -128,101 +208,476 @@ int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
         soa->soa.expire = 1;
         soa->soa.minimum = ttl;
 
-        return dns_answer_add(a, soa, 0);
+        return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
 }
 
-int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key) {
-        unsigned i;
+int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
+        DnsAnswerFlags flags = 0, i_flags;
+        DnsResourceRecord *i;
+        bool found = false;
         int r;
 
         assert(key);
 
-        if (!a)
-                return 0;
+        DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
+                r = dns_resource_key_match_rr(key, i, NULL);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
 
-        for (i = 0; i < a->n_rrs; i++) {
-                r = dns_resource_key_match_rr(key, a->items[i].rr);
+                if (!ret_flags)
+                        return 1;
+
+                if (found)
+                        flags &= i_flags;
+                else {
+                        flags = i_flags;
+                        found = true;
+                }
+        }
+
+        if (ret_flags)
+                *ret_flags = flags;
+
+        return found;
+}
+
+int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) {
+        DnsAnswerFlags flags = 0, i_flags;
+        DnsResourceRecord *i;
+        bool found = false;
+        int r;
+
+        assert(rr);
+
+        DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
+                r = dns_resource_record_equal(i, rr);
                 if (r < 0)
                         return r;
-                if (r > 0)
+                if (r == 0)
+                        continue;
+
+                if (!ret_flags)
                         return 1;
+
+                if (found)
+                        flags &= i_flags;
+                else {
+                        flags = i_flags;
+                        found = true;
+                }
         }
 
-        return 0;
+        if (ret_flags)
+                *ret_flags = flags;
+
+        return found;
 }
 
-int dns_answer_match_soa(DnsResourceKey *key, DnsResourceKey *soa) {
-        if (soa->class != DNS_CLASS_IN)
-                return 0;
+int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
+        DnsAnswerFlags flags = 0, i_flags;
+        DnsResourceRecord *i;
+        bool found = false;
+        int r;
+
+        assert(key);
+
+        DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
+                r = dns_resource_key_equal(i->key, key);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                if (!ret_flags)
+                        return true;
+
+                if (found)
+                        flags &= i_flags;
+                else {
+                        flags = i_flags;
+                        found = true;
+                }
+        }
+
+        if (ret_flags)
+                *ret_flags = flags;
+
+        return found;
+}
+
+int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
+        DnsResourceRecord *i;
+
+        DNS_ANSWER_FOREACH(i, a) {
+                if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3))
+                        return true;
+        }
+
+        return false;
+}
+
+int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) {
+        DnsResourceRecord *rr;
+        int r;
+
+        /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */
+
+        DNS_ANSWER_FOREACH(rr, answer) {
+                const char *p;
+
+                if (rr->key->type != DNS_TYPE_NSEC3)
+                        continue;
+
+                p = DNS_RESOURCE_KEY_NAME(rr->key);
+                r = dns_name_parent(&p);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = dns_name_equal(p, zone);
+                if (r != 0)
+                        return r;
+        }
+
+        return false;
+}
+
+int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
+        DnsResourceRecord *rr, *soa = NULL;
+        DnsAnswerFlags rr_flags, soa_flags = 0;
+        int r;
+
+        assert(key);
 
-        if (soa->type != DNS_TYPE_SOA)
+        /* For a SOA record we can never find a matching SOA record */
+        if (key->type == DNS_TYPE_SOA)
                 return 0;
 
-        if (!dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa)))
+        DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
+                r = dns_resource_key_match_soa(key, rr->key);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+
+                        if (soa) {
+                                r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(soa->key));
+                                if (r < 0)
+                                        return r;
+                                if (r > 0)
+                                        continue;
+                        }
+
+                        soa = rr;
+                        soa_flags = rr_flags;
+                }
+        }
+
+        if (!soa)
                 return 0;
 
+        if (ret)
+                *ret = soa;
+        if (flags)
+                *flags = soa_flags;
+
         return 1;
 }
 
-int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret) {
-        unsigned i;
+int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
+        DnsResourceRecord *rr;
+        DnsAnswerFlags rr_flags;
+        int r;
 
         assert(key);
+
+        /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
+        if (!dns_type_may_redirect(key->type))
+                return 0;
+
+        DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
+                r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        if (ret)
+                                *ret = rr;
+                        if (flags)
+                                *flags = rr_flags;
+                        return 1;
+                }
+        }
+
+        return 0;
+}
+
+int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL;
+        int r;
+
         assert(ret);
 
-        if (!a)
+        if (dns_answer_size(a) <= 0) {
+                *ret = dns_answer_ref(b);
                 return 0;
+        }
 
-        /* For a SOA record we can never find a matching SOA record */
-        if (key->type == DNS_TYPE_SOA)
+        if (dns_answer_size(b) <= 0) {
+                *ret = dns_answer_ref(a);
                 return 0;
+        }
 
-        for (i = 0; i < a->n_rrs; i++) {
+        k = dns_answer_new(a->n_rrs + b->n_rrs);
+        if (!k)
+                return -ENOMEM;
 
-                if (dns_answer_match_soa(key, a->items[i].rr->key)) {
-                        *ret = a->items[i].rr;
-                        return 1;
-                }
-        }
+        r = dns_answer_add_raw_all(k, a);
+        if (r < 0)
+                return r;
+
+        r = dns_answer_add_all(k, b);
+        if (r < 0)
+                return r;
+
+        *ret = k;
+        k = NULL;
+
+        return 0;
+}
+
+int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) {
+        DnsAnswer *merged;
+        int r;
+
+        assert(a);
+
+        r = dns_answer_merge(*a, b, &merged);
+        if (r < 0)
+                return r;
+
+        dns_answer_unref(*a);
+        *a = merged;
 
         return 0;
 }
 
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b) {
-        _cleanup_(dns_answer_unrefp) DnsAnswer *ret = NULL;
-        DnsAnswer *k;
+int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
+        bool found = false, other = false;
+        DnsResourceRecord *rr;
         unsigned i;
         int r;
 
-        if (a && (!b || b->n_rrs <= 0))
-                return dns_answer_ref(a);
-        if ((!a || a->n_rrs <= 0) && b)
-                return dns_answer_ref(b);
+        assert(a);
+        assert(key);
 
-        ret = dns_answer_new((a ? a->n_rrs : 0) + (b ? b->n_rrs : 0));
-        if (!ret)
-                return NULL;
+        /* Remove all entries matching the specified key from *a */
+
+        DNS_ANSWER_FOREACH(rr, *a) {
+                r = dns_resource_key_equal(rr->key, key);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        found = true;
+                else
+                        other = true;
+
+                if (found && other)
+                        break;
+        }
 
-        if (a) {
-                for (i = 0; i < a->n_rrs; i++) {
-                        r = dns_answer_add(ret, a->items[i].rr, a->items[i].ifindex);
+        if (!found)
+                return 0;
+
+        if (!other) {
+                *a = dns_answer_unref(*a); /* Return NULL for the empty answer */
+                return 1;
+        }
+
+        if ((*a)->n_ref > 1) {
+                _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
+                DnsAnswerFlags flags;
+                int ifindex;
+
+                copy = dns_answer_new((*a)->n_rrs);
+                if (!copy)
+                        return -ENOMEM;
+
+                DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
+                        r = dns_resource_key_equal(rr->key, key);
                         if (r < 0)
-                                return NULL;
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        r = dns_answer_add_raw(copy, rr, ifindex, flags);
+                        if (r < 0)
+                                return r;
                 }
+
+                dns_answer_unref(*a);
+                *a = copy;
+                copy = NULL;
+
+                return 1;
+        }
+
+        /* Only a single reference, edit in-place */
+
+        i = 0;
+        for (;;) {
+                if (i >= (*a)->n_rrs)
+                        break;
+
+                r = dns_resource_key_equal((*a)->items[i].rr->key, key);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        /* Kill this entry */
+
+                        dns_resource_record_unref((*a)->items[i].rr);
+                        memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
+                        (*a)->n_rrs --;
+                        continue;
+
+                } else
+                        /* Keep this entry */
+                        i++;
+        }
+
+        return 1;
+}
+
+int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
+        bool found = false, other = false;
+        DnsResourceRecord *rr;
+        unsigned i;
+        int r;
+
+        assert(a);
+        assert(rm);
+
+        /* Remove all entries matching the specified RR from *a */
+
+        DNS_ANSWER_FOREACH(rr, *a) {
+                r = dns_resource_record_equal(rr, rm);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        found = true;
+                else
+                        other = true;
+
+                if (found && other)
+                        break;
         }
 
-        if (b) {
-                for (i = 0; i < b->n_rrs; i++) {
-                        r = dns_answer_add(ret, b->items[i].rr, b->items[i].ifindex);
+        if (!found)
+                return 0;
+
+        if (!other) {
+                *a = dns_answer_unref(*a); /* Return NULL for the empty answer */
+                return 1;
+        }
+
+        if ((*a)->n_ref > 1) {
+                _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
+                DnsAnswerFlags flags;
+                int ifindex;
+
+                copy = dns_answer_new((*a)->n_rrs);
+                if (!copy)
+                        return -ENOMEM;
+
+                DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
+                        r = dns_resource_record_equal(rr, rm);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        r = dns_answer_add_raw(copy, rr, ifindex, flags);
                         if (r < 0)
-                                return NULL;
+                                return r;
                 }
+
+                dns_answer_unref(*a);
+                *a = copy;
+                copy = NULL;
+
+                return 1;
+        }
+
+        /* Only a single reference, edit in-place */
+
+        i = 0;
+        for (;;) {
+                if (i >= (*a)->n_rrs)
+                        break;
+
+                r = dns_resource_record_equal((*a)->items[i].rr, rm);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        /* Kill this entry */
+
+                        dns_resource_record_unref((*a)->items[i].rr);
+                        memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
+                        (*a)->n_rrs --;
+                        continue;
+
+                } else
+                        /* Keep this entry */
+                        i++;
+        }
+
+        return 1;
+}
+
+int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
+        DnsResourceRecord *rr_source;
+        int ifindex_source, r;
+        DnsAnswerFlags flags_source;
+
+        assert(a);
+        assert(key);
+
+        /* Copy all RRs matching the specified key from source into *a */
+
+        DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) {
+
+                r = dns_resource_key_equal(rr_source->key, key);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                /* Make space for at least one entry */
+                r = dns_answer_reserve_or_clone(a, 1);
+                if (r < 0)
+                        return r;
+
+                r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags);
+                if (r < 0)
+                        return r;
         }
 
-        k = ret;
-        ret = NULL;
+        return 0;
+}
 
-        return k;
+int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
+        int r;
+
+        assert(to);
+        assert(from);
+        assert(key);
+
+        r = dns_answer_copy_by_key(to, *from, key, or_flags);
+        if (r < 0)
+                return r;
+
+        return dns_answer_remove_by_key(from, key);
 }
 
 void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
@@ -261,6 +716,8 @@ void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
 int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
         DnsAnswer *n;
 
+        assert(a);
+
         if (n_free <= 0)
                 return 0;
 
@@ -275,6 +732,9 @@ int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
                 if ((*a)->n_allocated >= ns)
                         return 0;
 
+                /* Allocate more than we need */
+                ns *= 2;
+
                 n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns);
                 if (!n)
                         return -ENOMEM;
@@ -289,3 +749,110 @@ int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
         *a = n;
         return 0;
 }
+
+int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
+        int r;
+
+        assert(a);
+
+        /* Tries to extend the DnsAnswer object. And if that's not
+         * possibly, since we are not the sole owner, then allocate a
+         * new, appropriately sized one. Either way, after this call
+         * the object will only have a single reference, and has room
+         * for at least the specified number of RRs. */
+
+        r = dns_answer_reserve(a, n_free);
+        if (r != -EBUSY)
+                return r;
+
+        assert(*a);
+
+        n = dns_answer_new(((*a)->n_rrs + n_free) * 2);
+        if (!n)
+                return -ENOMEM;
+
+        r = dns_answer_add_raw_all(n, *a);
+        if (r < 0)
+                return r;
+
+        dns_answer_unref(*a);
+        *a = n;
+        n = NULL;
+
+        return 0;
+}
+
+void dns_answer_dump(DnsAnswer *answer, FILE *f) {
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+        int ifindex;
+
+        if (!f)
+                f = stdout;
+
+        DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
+                const char *t;
+
+                fputc('\t', f);
+
+                t = dns_resource_record_to_string(rr);
+                if (!t) {
+                        log_oom();
+                        continue;
+                }
+
+                fputs(t, f);
+
+                if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER))
+                        fputs("\t;", f);
+
+                if (ifindex != 0)
+                        printf(" ifindex=%i", ifindex);
+                if (flags & DNS_ANSWER_AUTHENTICATED)
+                        fputs(" authenticated", f);
+                if (flags & DNS_ANSWER_CACHEABLE)
+                        fputs(" cachable", f);
+                if (flags & DNS_ANSWER_SHARED_OWNER)
+                        fputs(" shared-owner", f);
+
+                fputc('\n', f);
+        }
+}
+
+bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) {
+        DnsResourceRecord *rr;
+        int r;
+
+        assert(cname);
+
+        /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is
+         * synthesized from it */
+
+        if (cname->key->type != DNS_TYPE_CNAME)
+                return 0;
+
+        DNS_ANSWER_FOREACH(rr, a) {
+                _cleanup_free_ char *n = NULL;
+
+                if (rr->key->type != DNS_TYPE_DNAME)
+                        continue;
+                if (rr->key->class != cname->key->class)
+                        continue;
+
+                r = dns_name_change_suffix(cname->cname.name, rr->dname.name, DNS_RESOURCE_KEY_NAME(rr->key), &n);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = dns_name_equal(n, DNS_RESOURCE_KEY_NAME(cname->key));
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        return 1;
+
+        }
+
+        return 0;
+}
index 044d73b19c3173fc9e718f712fe7a714f796d651..8f9c15eab4f67282125b9402f8b82db82419ded9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 typedef struct DnsAnswer DnsAnswer;
 typedef struct DnsAnswerItem DnsAnswerItem;
 
+#include "macro.h"
 #include "resolved-dns-rr.h"
 
 /* A simple array of resource records. We keep track of the
  * originating ifindex for each RR where that makes sense, so that we
  * can qualify A and AAAA RRs referring to a local link with the
- * right ifindex. */
+ * right ifindex.
+ *
+ * Note that we usually encode the the empty DnsAnswer object as a simple NULL. */
+
+typedef enum DnsAnswerFlags {
+        DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */
+        DNS_ANSWER_CACHEABLE     = 2, /* Item is subject to caching */
+        DNS_ANSWER_SHARED_OWNER  = 4, /* For mDNS: RRset may be owner by multiple peers */
+} DnsAnswerFlags;
 
 struct DnsAnswerItem {
         DnsResourceRecord *rr;
         int ifindex;
+        DnsAnswerFlags flags;
 };
 
 struct DnsAnswer {
@@ -46,15 +54,90 @@ DnsAnswer *dns_answer_new(unsigned n);
 DnsAnswer *dns_answer_ref(DnsAnswer *a);
 DnsAnswer *dns_answer_unref(DnsAnswer *a);
 
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex);
+int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
+int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
 int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl);
-int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key);
-int dns_answer_match_soa(DnsResourceKey *key, DnsResourceKey *soa);
-int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret);
 
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b);
+int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
+int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *combined_flags);
+int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
+int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
+int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
+
+int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
+int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
+
+int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret);
+int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
+
 void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local);
 
 int dns_answer_reserve(DnsAnswer **a, unsigned n_free);
+int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free);
+
+int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key);
+int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr);
+
+int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags);
+int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags);
+
+bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
+
+static inline unsigned dns_answer_size(DnsAnswer *a) {
+        return a ? a->n_rrs : 0;
+}
+
+void dns_answer_dump(DnsAnswer *answer, FILE *f);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
+
+#define _DNS_ANSWER_FOREACH(q, kk, a)                                   \
+        for (unsigned UNIQ_T(i, q) = ({                                 \
+                                (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
+                                0;                                      \
+                        });                                             \
+             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL))
+
+#define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a)
+
+#define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a)                      \
+        for (unsigned UNIQ_T(i, q) = ({                                 \
+                                (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
+                                (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
+                                0;                                      \
+                        });                                             \
+             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q)++,                                            \
+                     (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
+                     (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0))
+
+#define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a)
+
+#define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a)                         \
+        for (unsigned UNIQ_T(i, q) = ({                                 \
+                                (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
+                                (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
+                                0;                                      \
+                        });                                             \
+             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q)++,                                            \
+                     (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
+                     (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
+
+#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
+
+#define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a)                     \
+        for (unsigned UNIQ_T(i, q) = ({                                 \
+                                (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
+                                (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
+                                (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
+                                0;                                      \
+                        });                                             \
+             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q)++,                                            \
+                     (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
+                     (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \
+                     (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
+
+#define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a)
index 04f64022e01c4444e404e8f6e6f9c598afff04a5..9bcc71724e2a12dd62cb760abb143c06b67e4fdb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include "alloc-util.h"
+#include "dns-domain.h"
+#include "resolved-dns-answer.h"
 #include "resolved-dns-cache.h"
 #include "resolved-dns-packet.h"
+#include "string-util.h"
 
-/* Never cache more than 1K entries */
-#define CACHE_MAX 1024
+/* Never cache more than 4K entries. RFC 1536, Section 5 suggests to
+ * leave DNS caches unbounded, but that's crazy. */
+#define CACHE_MAX 4096
 
-/* We never keep any item longer than 10min in our cache */
-#define CACHE_TTL_MAX_USEC (10 * USEC_PER_MINUTE)
+/* We never keep any item longer than 2h in our cache */
+#define CACHE_TTL_MAX_USEC (2 * USEC_PER_HOUR)
 
 typedef enum DnsCacheItemType DnsCacheItemType;
 typedef struct DnsCacheItem DnsCacheItem;
@@ -39,13 +41,19 @@ enum DnsCacheItemType {
 };
 
 struct DnsCacheItem {
+        DnsCacheItemType type;
         DnsResourceKey *key;
         DnsResourceRecord *rr;
+
         usec_t until;
-        DnsCacheItemType type;
-        unsigned prioq_idx;
+        bool authenticated:1;
+        bool shared_owner:1;
+
+        int ifindex;
         int owner_family;
         union in_addr_union owner_address;
+
+        unsigned prioq_idx;
         LIST_FIELDS(DnsCacheItem, by_key);
 };
 
@@ -60,7 +68,7 @@ static void dns_cache_item_free(DnsCacheItem *i) {
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
 
-static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) {
+static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) {
         DnsCacheItem *first;
 
         assert(c);
@@ -81,34 +89,55 @@ static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) {
         dns_cache_item_free(i);
 }
 
-void dns_cache_flush(DnsCache *c) {
-        DnsCacheItem *i;
+static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) {
+        DnsCacheItem *first, *i;
+        int r;
+
+        first = hashmap_get(c->by_key, rr->key);
+        LIST_FOREACH(by_key, i, first) {
+                r = dns_resource_record_equal(i->rr, rr);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        dns_cache_item_unlink_and_free(c, i);
+                        return true;
+                }
+        }
+
+        return false;
+}
+
+static bool dns_cache_remove_by_key(DnsCache *c, DnsResourceKey *key) {
+        DnsCacheItem *first, *i, *n;
 
         assert(c);
+        assert(key);
 
-        while ((i = hashmap_first(c->by_key)))
-                dns_cache_item_remove_and_free(c, i);
+        first = hashmap_remove(c->by_key, key);
+        if (!first)
+                return false;
 
-        assert(hashmap_size(c->by_key) == 0);
-        assert(prioq_size(c->by_expiry) == 0);
+        LIST_FOREACH_SAFE(by_key, i, n, first) {
+                prioq_remove(c->by_expiry, i, &i->prioq_idx);
+                dns_cache_item_free(i);
+        }
 
-        c->by_key = hashmap_free(c->by_key);
-        c->by_expiry = prioq_free(c->by_expiry);
+        return true;
 }
 
-static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) {
-        DnsCacheItem *i;
-        bool exist = false;
+void dns_cache_flush(DnsCache *c) {
+        DnsResourceKey *key;
 
         assert(c);
-        assert(key);
 
-        while ((i = hashmap_get(c->by_key, key))) {
-                dns_cache_item_remove_and_free(c, i);
-                exist = true;
-        }
+        while ((key = hashmap_first_key(c->by_key)))
+                dns_cache_remove_by_key(c, key);
 
-        return exist;
+        assert(hashmap_size(c->by_key) == 0);
+        assert(prioq_size(c->by_expiry) == 0);
+
+        c->by_key = hashmap_free(c->by_key);
+        c->by_expiry = prioq_free(c->by_expiry);
 }
 
 static void dns_cache_make_space(DnsCache *c, unsigned add) {
@@ -138,7 +167,7 @@ static void dns_cache_make_space(DnsCache *c, unsigned add) {
                 /* Take an extra reference to the key so that it
                  * doesn't go away in the middle of the remove call */
                 key = dns_resource_key_ref(i->key);
-                dns_cache_remove(c, key);
+                dns_cache_remove_by_key(c, key);
         }
 }
 
@@ -150,7 +179,6 @@ void dns_cache_prune(DnsCache *c) {
         /* Remove all entries that are past their TTL */
 
         for (;;) {
-                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
                 DnsCacheItem *i;
 
                 i = prioq_peek(c->by_expiry);
@@ -163,10 +191,19 @@ void dns_cache_prune(DnsCache *c) {
                 if (i->until > t)
                         break;
 
-                /* Take an extra reference to the key so that it
-                 * doesn't go away in the middle of the remove call */
-                key = dns_resource_key_ref(i->key);
-                dns_cache_remove(c, key);
+                /* Depending whether this is an mDNS shared entry
+                 * either remove only this one RR or the whole
+                 * RRset */
+                if (i->shared_owner)
+                        dns_cache_item_unlink_and_free(c, i);
+                else {
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+
+                        /* Take an extra reference to the key so that it
+                         * doesn't go away in the middle of the remove call */
+                        key = dns_resource_key_ref(i->key);
+                        dns_cache_remove_by_key(c, key);
+                }
         }
 }
 
@@ -209,6 +246,19 @@ static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) {
 
         first = hashmap_get(c->by_key, i->key);
         if (first) {
+                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
+
+                /* Keep a reference to the original key, while we manipulate the list. */
+                k = dns_resource_key_ref(first->key);
+
+                /* Now, try to reduce the number of keys we keep */
+                dns_resource_key_reduce(&first->key, &i->key);
+
+                if (first->rr)
+                        dns_resource_key_reduce(&first->rr->key, &i->key);
+                if (i->rr)
+                        dns_resource_key_reduce(&i->rr->key, &i->key);
+
                 LIST_PREPEND(by_key, first, i);
                 assert_se(hashmap_replace(c->by_key, first->key, first) >= 0);
         } else {
@@ -235,10 +285,57 @@ static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) {
         return NULL;
 }
 
-static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, usec_t timestamp) {
+static usec_t calculate_until(DnsResourceRecord *rr, uint32_t nsec_ttl, usec_t timestamp, bool use_soa_minimum) {
+        uint32_t ttl;
+        usec_t u;
+
+        assert(rr);
+
+        ttl = MIN(rr->ttl, nsec_ttl);
+        if (rr->key->type == DNS_TYPE_SOA && use_soa_minimum) {
+                /* If this is a SOA RR, and it is requested, clamp to
+                 * the SOA's minimum field. This is used when we do
+                 * negative caching, to determine the TTL for the
+                 * negative caching entry.  See RFC 2308, Section
+                 * 5. */
+
+                if (ttl > rr->soa.minimum)
+                        ttl = rr->soa.minimum;
+        }
+
+        u = ttl * USEC_PER_SEC;
+        if (u > CACHE_TTL_MAX_USEC)
+                u = CACHE_TTL_MAX_USEC;
+
+        if (rr->expiry != USEC_INFINITY) {
+                usec_t left;
+
+                /* Make use of the DNSSEC RRSIG expiry info, if we
+                 * have it */
+
+                left = LESS_BY(rr->expiry, now(CLOCK_REALTIME));
+                if (u > left)
+                        u = left;
+        }
+
+        return timestamp + u;
+}
+
+static void dns_cache_item_update_positive(
+                DnsCache *c,
+                DnsCacheItem *i,
+                DnsResourceRecord *rr,
+                bool authenticated,
+                bool shared_owner,
+                usec_t timestamp,
+                int ifindex,
+                int owner_family,
+                const union in_addr_union *owner_address) {
+
         assert(c);
         assert(i);
         assert(rr);
+        assert(owner_address);
 
         i->type = DNS_CACHE_POSITIVE;
 
@@ -255,7 +352,14 @@ static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsReso
         dns_resource_key_unref(i->key);
         i->key = dns_resource_key_ref(rr->key);
 
-        i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
+        i->until = calculate_until(rr, (uint32_t) -1, timestamp, false);
+        i->authenticated = authenticated;
+        i->shared_owner = shared_owner;
+
+        i->ifindex = ifindex;
+
+        i->owner_family = owner_family;
+        i->owner_address = *owner_address;
 
         prioq_reshuffle(c->by_expiry, i, &i->prioq_idx);
 }
@@ -263,42 +367,59 @@ static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsReso
 static int dns_cache_put_positive(
                 DnsCache *c,
                 DnsResourceRecord *rr,
+                bool authenticated,
+                bool shared_owner,
                 usec_t timestamp,
+                int ifindex,
                 int owner_family,
                 const union in_addr_union *owner_address) {
 
         _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
         _cleanup_free_ char *key_str = NULL;
         DnsCacheItem *existing;
-        int r;
+        int r, k;
 
         assert(c);
         assert(rr);
         assert(owner_address);
 
-        /* New TTL is 0? Delete the entry... */
+        /* Never cache pseudo RRs */
+        if (dns_class_is_pseudo(rr->key->class))
+                return 0;
+        if (dns_type_is_pseudo(rr->key->type))
+                return 0;
+
+        /* New TTL is 0? Delete this specific entry... */
         if (rr->ttl <= 0) {
-                r = dns_resource_key_to_string(rr->key, &key_str);
-                if (r < 0)
-                        return r;
+                k = dns_cache_remove_by_rr(c, rr);
 
-                if (dns_cache_remove(c, rr->key))
-                        log_debug("Removed zero TTL entry from cache: %s", key_str);
-                else
-                        log_debug("Not caching zero TTL cache entry: %s", key_str);
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        r = dns_resource_key_to_string(rr->key, &key_str);
+                        if (r < 0)
+                                return r;
 
-                return 0;
-        }
+                        if (k > 0)
+                                log_debug("Removed zero TTL entry from cache: %s", key_str);
+                        else
+                                log_debug("Not caching zero TTL cache entry: %s", key_str);
+                }
 
-        if (rr->key->class == DNS_CLASS_ANY)
-                return 0;
-        if (rr->key->type == DNS_TYPE_ANY)
                 return 0;
+        }
 
-        /* Entry exists already? Update TTL and timestamp */
+        /* Entry exists already? Update TTL, timestamp and owner*/
         existing = dns_cache_get(c, rr);
         if (existing) {
-                dns_cache_item_update_positive(c, existing, rr, timestamp);
+                dns_cache_item_update_positive(
+                                c,
+                                existing,
+                                rr,
+                                authenticated,
+                                shared_owner,
+                                timestamp,
+                                ifindex,
+                                owner_family,
+                                owner_address);
                 return 0;
         }
 
@@ -316,20 +437,25 @@ static int dns_cache_put_positive(
         i->type = DNS_CACHE_POSITIVE;
         i->key = dns_resource_key_ref(rr->key);
         i->rr = dns_resource_record_ref(rr);
-        i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
-        i->prioq_idx = PRIOQ_IDX_NULL;
+        i->until = calculate_until(rr, (uint32_t) -1, timestamp, false);
+        i->authenticated = authenticated;
+        i->shared_owner = shared_owner;
+        i->ifindex = ifindex;
         i->owner_family = owner_family;
         i->owner_address = *owner_address;
+        i->prioq_idx = PRIOQ_IDX_NULL;
 
         r = dns_cache_link_item(c, i);
         if (r < 0)
                 return r;
 
-        r = dns_resource_key_to_string(i->key, &key_str);
-        if (r < 0)
-                return r;
+        if (log_get_max_level() >= LOG_DEBUG) {
+                r = dns_resource_key_to_string(i->key, &key_str);
+                if (r < 0)
+                        return r;
 
-        log_debug("Added cache entry for %s", key_str);
+                log_debug("Added positive cache entry for %s", key_str);
+        }
 
         i = NULL;
         return 0;
@@ -339,8 +465,10 @@ static int dns_cache_put_negative(
                 DnsCache *c,
                 DnsResourceKey *key,
                 int rcode,
+                bool authenticated,
+                uint32_t nsec_ttl,
                 usec_t timestamp,
-                uint32_t soa_ttl,
+                DnsResourceRecord *soa,
                 int owner_family,
                 const union in_addr_union *owner_address) {
 
@@ -350,20 +478,25 @@ static int dns_cache_put_negative(
 
         assert(c);
         assert(key);
+        assert(soa);
         assert(owner_address);
 
-        dns_cache_remove(c, key);
-
-        if (key->class == DNS_CLASS_ANY)
+        /* Never cache pseudo RR keys. DNS_TYPE_ANY is particularly
+         * important to filter out as we use this as a pseudo-type for
+         * NXDOMAIN entries */
+        if (dns_class_is_pseudo(key->class))
                 return 0;
-        if (key->type == DNS_TYPE_ANY)
+        if (dns_type_is_pseudo(key->type))
                 return 0;
-        if (soa_ttl <= 0) {
-                r = dns_resource_key_to_string(key, &key_str);
-                if (r < 0)
-                        return r;
 
-                log_debug("Not caching negative entry with zero SOA TTL: %s", key_str);
+        if (nsec_ttl <= 0 || soa->soa.minimum <= 0 || soa->ttl <= 0) {
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        r = dns_resource_key_to_string(key, &key_str);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s", key_str);
+                }
 
                 return 0;
         }
@@ -382,63 +515,139 @@ static int dns_cache_put_negative(
                 return -ENOMEM;
 
         i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN;
-        i->key = dns_resource_key_ref(key);
-        i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
-        i->prioq_idx = PRIOQ_IDX_NULL;
+        i->until = calculate_until(soa, nsec_ttl, timestamp, true);
+        i->authenticated = authenticated;
         i->owner_family = owner_family;
         i->owner_address = *owner_address;
+        i->prioq_idx = PRIOQ_IDX_NULL;
+
+        if (i->type == DNS_CACHE_NXDOMAIN) {
+                /* NXDOMAIN entries should apply equally to all types, so we use ANY as
+                 * a pseudo type for this purpose here. */
+                i->key = dns_resource_key_new(key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(key));
+                if (!i->key)
+                        return -ENOMEM;
+
+                /* Make sure to remove any previous entry for this
+                 * specific ANY key. (For non-ANY keys the cache data
+                 * is already cleared by the caller.) Note that we
+                 * don't bother removing positive or NODATA cache
+                 * items in this case, because it would either be slow
+                 * or require explicit indexing by name */
+                dns_cache_remove_by_key(c, key);
+        } else
+                i->key = dns_resource_key_ref(key);
 
         r = dns_cache_link_item(c, i);
         if (r < 0)
                 return r;
 
-        r = dns_resource_key_to_string(i->key, &key_str);
-        if (r < 0)
-                return r;
+        if (log_get_max_level() >= LOG_DEBUG) {
+                r = dns_resource_key_to_string(i->key, &key_str);
+                if (r < 0)
+                        return r;
 
-        log_debug("Added %s cache entry for %s", i->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", key_str);
+                log_debug("Added %s cache entry for %s", i->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", key_str);
+        }
 
         i = NULL;
         return 0;
 }
 
+static void dns_cache_remove_previous(
+                DnsCache *c,
+                DnsResourceKey *key,
+                DnsAnswer *answer) {
+
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+
+        assert(c);
+
+        /* First, if we were passed a key (i.e. on LLMNR/DNS, but
+         * not on mDNS), delete all matching old RRs, so that we only
+         * keep complete by_key in place. */
+        if (key)
+                dns_cache_remove_by_key(c, key);
+
+        /* Second, flush all entries matching the answer, unless this
+         * is an RR that is explicitly marked to be "shared" between
+         * peers (i.e. mDNS RRs without the flush-cache bit set). */
+        DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
+                if ((flags & DNS_ANSWER_CACHEABLE) == 0)
+                        continue;
+
+                if (flags & DNS_ANSWER_SHARED_OWNER)
+                        continue;
+
+                dns_cache_remove_by_key(c, rr->key);
+        }
+}
+
+static bool rr_eligible(DnsResourceRecord *rr) {
+        assert(rr);
+
+        /* When we see an NSEC/NSEC3 RR, we'll only cache it if it is from the lower zone, not the upper zone, since
+         * that's where the interesting bits are (with exception of DS RRs). Of course, this way we cannot derive DS
+         * existence from any cached NSEC/NSEC3, but that should be fine. */
+
+        switch (rr->key->type) {
+
+        case DNS_TYPE_NSEC:
+                return !bitmap_isset(rr->nsec.types, DNS_TYPE_NS) ||
+                        bitmap_isset(rr->nsec.types, DNS_TYPE_SOA);
+
+        case DNS_TYPE_NSEC3:
+                return !bitmap_isset(rr->nsec3.types, DNS_TYPE_NS) ||
+                        bitmap_isset(rr->nsec3.types, DNS_TYPE_SOA);
+
+        default:
+                return true;
+        }
+}
+
 int dns_cache_put(
                 DnsCache *c,
                 DnsResourceKey *key,
                 int rcode,
                 DnsAnswer *answer,
-                unsigned max_rrs,
+                bool authenticated,
+                uint32_t nsec_ttl,
                 usec_t timestamp,
                 int owner_family,
                 const union in_addr_union *owner_address) {
 
-        DnsResourceRecord *soa = NULL;
-        unsigned cache_keys, i;
-        int r;
+        DnsResourceRecord *soa = NULL, *rr;
+        DnsAnswerFlags flags;
+        unsigned cache_keys;
+        int r, ifindex;
 
         assert(c);
+        assert(owner_address);
 
-        if (key) {
-                /* First, if we were passed a key, delete all matching old RRs,
-                 * so that we only keep complete by_key in place. */
-                dns_cache_remove(c, key);
-        }
+        dns_cache_remove_previous(c, key, answer);
 
-        if (!answer)
-                return 0;
+        if (dns_answer_size(answer) <= 0) {
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        _cleanup_free_ char *key_str = NULL;
+
+                        r = dns_resource_key_to_string(key, &key_str);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Not caching negative entry without a SOA record: %s", key_str);
+                }
 
-        for (i = 0; i < answer->n_rrs; i++)
-                dns_cache_remove(c, answer->items[i].rr->key);
+                return 0;
+        }
 
         /* We only care for positive replies and NXDOMAINs, on all
          * other replies we will simply flush the respective entries,
          * and that's it */
-
         if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
                 return 0;
 
-        cache_keys = answer->n_rrs;
-
+        cache_keys = dns_answer_size(answer);
         if (key)
                 cache_keys ++;
 
@@ -449,58 +658,70 @@ int dns_cache_put(
                 timestamp = now(clock_boottime_or_monotonic());
 
         /* Second, add in positive entries for all contained RRs */
-        for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) {
-                r = dns_cache_put_positive(c, answer->items[i].rr, timestamp, owner_family, owner_address);
+        DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
+                if ((flags & DNS_ANSWER_CACHEABLE) == 0)
+                        continue;
+
+                r = rr_eligible(rr);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = dns_cache_put_positive(
+                                c,
+                                rr,
+                                flags & DNS_ANSWER_AUTHENTICATED,
+                                flags & DNS_ANSWER_SHARED_OWNER,
+                                timestamp,
+                                ifindex,
+                                owner_family, owner_address);
                 if (r < 0)
                         goto fail;
         }
 
-        if (!key)
+        if (!key) /* mDNS doesn't know negative caching, really */
                 return 0;
 
         /* Third, add in negative entries if the key has no RR */
-        r = dns_answer_contains(answer, key);
+        r = dns_answer_match_key(answer, key, NULL);
         if (r < 0)
                 goto fail;
         if (r > 0)
                 return 0;
 
-        /* See https://tools.ietf.org/html/rfc2308, which
-         * say that a matching SOA record in the packet
-         * is used to to enable negative caching. */
+        /* But not if it has a matching CNAME/DNAME (the negative
+         * caching will be done on the canonical name, not on the
+         * alias) */
+        r = dns_answer_find_cname_or_dname(answer, key, NULL, NULL);
+        if (r < 0)
+                goto fail;
+        if (r > 0)
+                return 0;
 
-        r = dns_answer_find_soa(answer, key, &soa);
+        /* See https://tools.ietf.org/html/rfc2308, which say that a
+         * matching SOA record in the packet is used to to enable
+         * negative caching. */
+        r = dns_answer_find_soa(answer, key, &soa, &flags);
         if (r < 0)
                 goto fail;
         if (r == 0)
                 return 0;
 
-        /* Also, if the requested key is an alias, the negative response should
-           be cached for each name in the redirect chain. Any CNAME record in
-           the response is from the redirection chain, though only the final one
-           is guaranteed to be included. This means that we cannot verify the
-           chain and that we need to cache them all as it may be incomplete. */
-        for (i = 0; i < answer->n_rrs; i++) {
-                DnsResourceRecord *answer_rr = answer->items[i].rr;
-
-                if (answer_rr->key->type == DNS_TYPE_CNAME) {
-                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *canonical_key = NULL;
-
-                        canonical_key = dns_resource_key_new_redirect(key, answer_rr);
-                        if (!canonical_key)
-                                goto fail;
-
-                        /* Let's not add negative cache entries for records outside the current zone. */
-                        if (!dns_answer_match_soa(canonical_key, soa->key))
-                                continue;
-
-                        r = dns_cache_put_negative(c, canonical_key, rcode, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
-                        if (r < 0)
-                                goto fail;
-                }
-        }
+        /* Refuse using the SOA data if it is unsigned, but the key is
+         * signed */
+        if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0)
+                return 0;
 
-        r = dns_cache_put_negative(c, key, rcode, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
+        r = dns_cache_put_negative(
+                        c,
+                        key,
+                        rcode,
+                        authenticated,
+                        nsec_ttl,
+                        timestamp,
+                        soa,
+                        owner_family, owner_address);
         if (r < 0)
                 goto fail;
 
@@ -511,75 +732,122 @@ fail:
          * added, just in case */
 
         if (key)
-                dns_cache_remove(c, key);
+                dns_cache_remove_by_key(c, key);
 
-        for (i = 0; i < answer->n_rrs; i++)
-                dns_cache_remove(c, answer->items[i].rr->key);
+        DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
+                if ((flags & DNS_ANSWER_CACHEABLE) == 0)
+                        continue;
+
+                dns_cache_remove_by_key(c, rr->key);
+        }
 
         return r;
 }
 
-static DnsCacheItem *dns_cache_get_by_key_follow_cname(DnsCache *c, DnsResourceKey *k) {
-        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *cname_key = NULL;
-        DnsCacheItem *i, *j;
+static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, DnsResourceKey *k) {
+        DnsCacheItem *i;
+        const char *n;
+        int r;
 
         assert(c);
         assert(k);
 
+        /* If we hit some OOM error, or suchlike, we don't care too
+         * much, after all this is just a cache */
+
         i = hashmap_get(c->by_key, k);
-        if (i || k->type == DNS_TYPE_CNAME)
+        if (i)
+                return i;
+
+        n = DNS_RESOURCE_KEY_NAME(k);
+
+        /* Check if we have an NXDOMAIN cache item for the name, notice that we use
+         * the pseudo-type ANY for NXDOMAIN cache items. */
+        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_ANY, n));
+        if (i && i->type == DNS_CACHE_NXDOMAIN)
                 return i;
 
-        /* check if we have a CNAME record instead */
-        cname_key = dns_resource_key_new_cname(k);
-        if (!cname_key)
-                return NULL;
+        if (dns_type_may_redirect(k->type)) {
+                /* Check if we have a CNAME record instead */
+                i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n));
+                if (i)
+                        return i;
+
+                /* OK, let's look for cached DNAME records. */
+                for (;;) {
+                        if (isempty(n))
+                                return NULL;
 
-        j = hashmap_get(c->by_key, cname_key);
-        if (j)
-                return j;
+                        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n));
+                        if (i)
+                                return i;
 
-        return i;
+                        /* Jump one label ahead */
+                        r = dns_name_parent(&n);
+                        if (r <= 0)
+                                return NULL;
+                }
+        }
+
+        if (k->type != DNS_TYPE_NSEC) {
+                /* Check if we have an NSEC record instead for the name. */
+                i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n));
+                if (i)
+                        return i;
+        }
+
+        return NULL;
 }
 
-int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **ret) {
+int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **ret, bool *authenticated) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
         unsigned n = 0;
         int r;
         bool nxdomain = false;
         _cleanup_free_ char *key_str = NULL;
-        DnsCacheItem *j, *first;
+        DnsCacheItem *j, *first, *nsec = NULL;
+        bool have_authenticated = false, have_non_authenticated = false;
 
         assert(c);
         assert(key);
         assert(rcode);
         assert(ret);
+        assert(authenticated);
 
         if (key->type == DNS_TYPE_ANY ||
             key->class == DNS_CLASS_ANY) {
 
-                /* If we have ANY lookups we simply refresh */
+                /* If we have ANY lookups we don't use the cache, so
+                 * that the caller refreshes via the network. */
 
-                r = dns_resource_key_to_string(key, &key_str);
-                if (r < 0)
-                        return r;
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        r = dns_resource_key_to_string(key, &key_str);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Ignoring cache for ANY lookup: %s", key_str);
+                }
 
-                log_debug("Ignoring cache for ANY lookup: %s", key_str);
+                c->n_miss++;
 
                 *ret = NULL;
                 *rcode = DNS_RCODE_SUCCESS;
                 return 0;
         }
 
-        first = dns_cache_get_by_key_follow_cname(c, key);
+        first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key);
         if (!first) {
                 /* If one question cannot be answered we need to refresh */
 
-                r = dns_resource_key_to_string(key, &key_str);
-                if (r < 0)
-                        return r;
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        r = dns_resource_key_to_string(key, &key_str);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Cache miss for %s", key_str);
+                }
 
-                log_debug("Cache miss for %s", key_str);
+                c->n_miss++;
 
                 *ret = NULL;
                 *rcode = DNS_RCODE_SUCCESS;
@@ -587,24 +855,68 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
         }
 
         LIST_FOREACH(by_key, j, first) {
-                if (j->rr)
+                if (j->rr) {
+                        if (j->rr->key->type == DNS_TYPE_NSEC)
+                                nsec = j;
+
                         n++;
-                else if (j->type == DNS_CACHE_NXDOMAIN)
+                else if (j->type == DNS_CACHE_NXDOMAIN)
                         nxdomain = true;
+
+                if (j->authenticated)
+                        have_authenticated = true;
+                else
+                        have_non_authenticated = true;
         }
 
-        r = dns_resource_key_to_string(key, &key_str);
-        if (r < 0)
-                return r;
+        if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) {
+                /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from
+                 * the lower-zone of a zone cut, but the DS RRs are on the upper zone. */
+
+                if (log_get_max_level() >= LOG_DEBUG) {
+                        r = dns_resource_key_to_string(key, &key_str);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("NSEC NODATA cache hit for %s", key_str);
+                }
+
+                /* We only found an NSEC record that matches our name.
+                 * If it says the type doesn't exist report
+                 * NODATA. Otherwise report a cache miss. */
+
+                *ret = NULL;
+                *rcode = DNS_RCODE_SUCCESS;
+                *authenticated = nsec->authenticated;
 
-        log_debug("%s cache hit for %s",
-                  nxdomain ? "NXDOMAIN" :
-                     n > 0 ? "Positive" : "NODATA",
-                  key_str);
+                if (!bitmap_isset(nsec->rr->nsec.types, key->type) &&
+                    !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) &&
+                    !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_DNAME)) {
+                        c->n_hit++;
+                        return 1;
+                }
+
+                c->n_miss++;
+                return 0;
+        }
+
+        if (log_get_max_level() >= LOG_DEBUG) {
+                r = dns_resource_key_to_string(key, &key_str);
+                if (r < 0)
+                        return r;
+
+                log_debug("%s cache hit for %s",
+                          n > 0    ? "Positive" :
+                          nxdomain ? "NXDOMAIN" : "NODATA",
+                          key_str);
+        }
 
         if (n <= 0) {
+                c->n_hit++;
+
                 *ret = NULL;
                 *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS;
+                *authenticated = have_authenticated && !have_non_authenticated;
                 return 1;
         }
 
@@ -616,13 +928,16 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
                 if (!j->rr)
                         continue;
 
-                r = dns_answer_add(answer, j->rr, 0);
+                r = dns_answer_add(answer, j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0);
                 if (r < 0)
                         return r;
         }
 
+        c->n_hit++;
+
         *ret = answer;
         *rcode = DNS_RCODE_SUCCESS;
+        *authenticated = have_authenticated && !have_non_authenticated;
         answer = NULL;
 
         return n;
@@ -664,6 +979,55 @@ int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_
         return 1;
 }
 
+int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
+        unsigned ancount = 0;
+        Iterator iterator;
+        DnsCacheItem *i;
+        int r;
+
+        assert(cache);
+        assert(p);
+
+        HASHMAP_FOREACH(i, cache->by_key, iterator) {
+                DnsCacheItem *j;
+
+                LIST_FOREACH(by_key, j, i) {
+                        if (!j->rr)
+                                continue;
+
+                        if (!j->shared_owner)
+                                continue;
+
+                        r = dns_packet_append_rr(p, j->rr, NULL, NULL);
+                        if (r == -EMSGSIZE && p->protocol == DNS_PROTOCOL_MDNS) {
+                                /* For mDNS, if we're unable to stuff all known answers into the given packet,
+                                 * allocate a new one, push the RR into that one and link it to the current one.
+                                 */
+
+                                DNS_PACKET_HEADER(p)->ancount = htobe16(ancount);
+                                ancount = 0;
+
+                                r = dns_packet_new_query(&p->more, p->protocol, 0, true);
+                                if (r < 0)
+                                        return r;
+
+                                /* continue with new packet */
+                                p = p->more;
+                                r = dns_packet_append_rr(p, j->rr, NULL, NULL);
+                        }
+
+                        if (r < 0)
+                                return r;
+
+                        ancount ++;
+                }
+        }
+
+        DNS_PACKET_HEADER(p)->ancount = htobe16(ancount);
+
+        return 0;
+}
+
 void dns_cache_dump(DnsCache *cache, FILE *f) {
         Iterator iterator;
         DnsCacheItem *i;
@@ -679,13 +1043,13 @@ void dns_cache_dump(DnsCache *cache, FILE *f) {
                 DnsCacheItem *j;
 
                 LIST_FOREACH(by_key, j, i) {
-                        _cleanup_free_ char *t = NULL;
 
                         fputc('\t', f);
 
                         if (j->rr) {
-                                r = dns_resource_record_to_string(j->rr, &t);
-                                if (r < 0) {
+                                const char *t;
+                                t = dns_resource_record_to_string(j->rr);
+                                if (!t) {
                                         log_oom();
                                         continue;
                                 }
@@ -693,13 +1057,14 @@ void dns_cache_dump(DnsCache *cache, FILE *f) {
                                 fputs(t, f);
                                 fputc('\n', f);
                         } else {
-                                r = dns_resource_key_to_string(j->key, &t);
+                                _cleanup_free_ char *z = NULL;
+                                r = dns_resource_key_to_string(j->key, &z);
                                 if (r < 0) {
                                         log_oom();
                                         continue;
                                 }
 
-                                fputs(t, f);
+                                fputs(z, f);
                                 fputs(" -- ", f);
                                 fputs(j->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", f);
                                 fputc('\n', f);
@@ -714,3 +1079,10 @@ bool dns_cache_is_empty(DnsCache *cache) {
 
         return hashmap_isempty(cache->by_key);
 }
+
+unsigned dns_cache_size(DnsCache *cache) {
+        if (!cache)
+                return 0;
+
+        return hashmap_size(cache->by_key);
+}
index 60cf6a47848d22986c54a2599332a0bc780174b4..2293718e869caaa1f835b68c6c2d624bb9ff6e81 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-
 #include "hashmap.h"
+#include "list.h"
 #include "prioq.h"
 #include "time-util.h"
-#include "list.h"
 
 typedef struct DnsCache {
         Hashmap *by_key;
         Prioq *by_expiry;
+        unsigned n_hit;
+        unsigned n_miss;
 } DnsCache;
 
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
 #include "resolved-dns-answer.h"
+#include "resolved-dns-packet.h"
+#include "resolved-dns-question.h"
+#include "resolved-dns-rr.h"
 
 void dns_cache_flush(DnsCache *c);
 void dns_cache_prune(DnsCache *c);
 
-int dns_cache_put(DnsCache *c, DnsResourceKey *key, int rcode, DnsAnswer *answer, unsigned max_rrs, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
-int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **answer);
+int dns_cache_put(DnsCache *c, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
+int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **answer, bool *authenticated);
 
 int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);
 
 void dns_cache_dump(DnsCache *cache, FILE *f);
 bool dns_cache_is_empty(DnsCache *cache);
+
+unsigned dns_cache_size(DnsCache *cache);
+
+int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p);
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
new file mode 100644 (file)
index 0000000..7123d2d
--- /dev/null
@@ -0,0 +1,2211 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
+#endif
+
+#include "alloc-util.h"
+#include "dns-domain.h"
+#include "hexdecoct.h"
+#include "resolved-dns-dnssec.h"
+#include "resolved-dns-packet.h"
+#include "string-table.h"
+
+#define VERIFY_RRS_MAX 256
+#define MAX_KEY_SIZE (32*1024)
+
+/* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
+#define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
+
+/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */
+#define NSEC3_ITERATIONS_MAX 2500
+
+/*
+ * The DNSSEC Chain of trust:
+ *
+ *            Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
+ *            DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
+ *            DS RRs are protected like normal RRs
+ *
+ * Example chain:
+ *            Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
+ */
+
+uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
+        const uint8_t *p;
+        uint32_t sum, f;
+        size_t i;
+
+        /* The algorithm from RFC 4034, Appendix B. */
+
+        assert(dnskey);
+        assert(dnskey->key->type == DNS_TYPE_DNSKEY);
+
+        f = (uint32_t) dnskey->dnskey.flags;
+
+        if (mask_revoke)
+                f &= ~DNSKEY_FLAG_REVOKE;
+
+        sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
+
+        p = dnskey->dnskey.key;
+
+        for (i = 0; i < dnskey->dnskey.key_size; i++)
+                sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
+
+        sum += (sum >> 16) & UINT32_C(0xFFFF);
+
+        return sum & UINT32_C(0xFFFF);
+}
+
+int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
+        size_t c = 0;
+        int r;
+
+        /* Converts the specified hostname into DNSSEC canonicalized
+         * form. */
+
+        if (buffer_max < 2)
+                return -ENOBUFS;
+
+        for (;;) {
+                r = dns_label_unescape(&n, buffer, buffer_max);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                if (buffer_max < (size_t) r + 2)
+                        return -ENOBUFS;
+
+                /* The DNSSEC canonical form is not clear on what to
+                 * do with dots appearing in labels, the way DNS-SD
+                 * does it. Refuse it for now. */
+
+                if (memchr(buffer, '.', r))
+                        return -EINVAL;
+
+                ascii_strlower_n(buffer, (size_t) r);
+                buffer[r] = '.';
+
+                buffer += r + 1;
+                c += r + 1;
+
+                buffer_max -= r + 1;
+        }
+
+        if (c <= 0) {
+                /* Not even a single label: this is the root domain name */
+
+                assert(buffer_max > 2);
+                buffer[0] = '.';
+                buffer[1] = 0;
+
+                return 1;
+        }
+
+        return (int) c;
+}
+
+#ifdef HAVE_GCRYPT
+
+static void initialize_libgcrypt(void) {
+        const char *p;
+
+        if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
+                return;
+
+        p = gcry_check_version("1.4.5");
+        assert(p);
+
+        gcry_control(GCRYCTL_DISABLE_SECMEM);
+        gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+}
+
+static int rr_compare(const void *a, const void *b) {
+        DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
+        size_t m;
+        int r;
+
+        /* Let's order the RRs according to RFC 4034, Section 6.3 */
+
+        assert(x);
+        assert(*x);
+        assert((*x)->wire_format);
+        assert(y);
+        assert(*y);
+        assert((*y)->wire_format);
+
+        m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(*x), DNS_RESOURCE_RECORD_RDATA_SIZE(*y));
+
+        r = memcmp(DNS_RESOURCE_RECORD_RDATA(*x), DNS_RESOURCE_RECORD_RDATA(*y), m);
+        if (r != 0)
+                return r;
+
+        if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) < DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
+                return -1;
+        else if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) > DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
+                return 1;
+
+        return 0;
+}
+
+static int dnssec_rsa_verify_raw(
+                const char *hash_algorithm,
+                const void *signature, size_t signature_size,
+                const void *data, size_t data_size,
+                const void *exponent, size_t exponent_size,
+                const void *modulus, size_t modulus_size) {
+
+        gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
+        gcry_mpi_t n = NULL, e = NULL, s = NULL;
+        gcry_error_t ge;
+        int r;
+
+        assert(hash_algorithm);
+
+        ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&signature_sexp,
+                             NULL,
+                             "(sig-val (rsa (s %m)))",
+                             s);
+
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&data_sexp,
+                             NULL,
+                             "(data (flags pkcs1) (hash %s %b))",
+                             hash_algorithm,
+                             (int) data_size,
+                             data);
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&public_key_sexp,
+                             NULL,
+                             "(public-key (rsa (n %m) (e %m)))",
+                             n,
+                             e);
+        if (ge != 0) {
+                r = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
+        if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
+                r = 0;
+        else if (ge != 0) {
+                log_debug("RSA signature check failed: %s", gpg_strerror(ge));
+                r = -EIO;
+        } else
+                r = 1;
+
+finish:
+        if (e)
+                gcry_mpi_release(e);
+        if (n)
+                gcry_mpi_release(n);
+        if (s)
+                gcry_mpi_release(s);
+
+        if (public_key_sexp)
+                gcry_sexp_release(public_key_sexp);
+        if (signature_sexp)
+                gcry_sexp_release(signature_sexp);
+        if (data_sexp)
+                gcry_sexp_release(data_sexp);
+
+        return r;
+}
+
+static int dnssec_rsa_verify(
+                const char *hash_algorithm,
+                const void *hash, size_t hash_size,
+                DnsResourceRecord *rrsig,
+                DnsResourceRecord *dnskey) {
+
+        size_t exponent_size, modulus_size;
+        void *exponent, *modulus;
+
+        assert(hash_algorithm);
+        assert(hash);
+        assert(hash_size > 0);
+        assert(rrsig);
+        assert(dnskey);
+
+        if (*(uint8_t*) dnskey->dnskey.key == 0) {
+                /* exponent is > 255 bytes long */
+
+                exponent = (uint8_t*) dnskey->dnskey.key + 3;
+                exponent_size =
+                        ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) |
+                        ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]);
+
+                if (exponent_size < 256)
+                        return -EINVAL;
+
+                if (3 + exponent_size >= dnskey->dnskey.key_size)
+                        return -EINVAL;
+
+                modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
+                modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
+
+        } else {
+                /* exponent is <= 255 bytes long */
+
+                exponent = (uint8_t*) dnskey->dnskey.key + 1;
+                exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
+
+                if (exponent_size <= 0)
+                        return -EINVAL;
+
+                if (1 + exponent_size >= dnskey->dnskey.key_size)
+                        return -EINVAL;
+
+                modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
+                modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
+        }
+
+        return dnssec_rsa_verify_raw(
+                        hash_algorithm,
+                        rrsig->rrsig.signature, rrsig->rrsig.signature_size,
+                        hash, hash_size,
+                        exponent, exponent_size,
+                        modulus, modulus_size);
+}
+
+static int dnssec_ecdsa_verify_raw(
+                const char *hash_algorithm,
+                const char *curve,
+                const void *signature_r, size_t signature_r_size,
+                const void *signature_s, size_t signature_s_size,
+                const void *data, size_t data_size,
+                const void *key, size_t key_size) {
+
+        gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
+        gcry_mpi_t q = NULL, r = NULL, s = NULL;
+        gcry_error_t ge;
+        int k;
+
+        assert(hash_algorithm);
+
+        ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&signature_sexp,
+                             NULL,
+                             "(sig-val (ecdsa (r %m) (s %m)))",
+                             r,
+                             s);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&data_sexp,
+                             NULL,
+                             "(data (flags rfc6979) (hash %s %b))",
+                             hash_algorithm,
+                             (int) data_size,
+                             data);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_sexp_build(&public_key_sexp,
+                             NULL,
+                             "(public-key (ecc (curve %s) (q %m)))",
+                             curve,
+                             q);
+        if (ge != 0) {
+                k = -EIO;
+                goto finish;
+        }
+
+        ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
+        if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
+                k = 0;
+        else if (ge != 0) {
+                log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
+                k = -EIO;
+        } else
+                k = 1;
+finish:
+        if (r)
+                gcry_mpi_release(r);
+        if (s)
+                gcry_mpi_release(s);
+        if (q)
+                gcry_mpi_release(q);
+
+        if (public_key_sexp)
+                gcry_sexp_release(public_key_sexp);
+        if (signature_sexp)
+                gcry_sexp_release(signature_sexp);
+        if (data_sexp)
+                gcry_sexp_release(data_sexp);
+
+        return k;
+}
+
+static int dnssec_ecdsa_verify(
+                const char *hash_algorithm,
+                int algorithm,
+                const void *hash, size_t hash_size,
+                DnsResourceRecord *rrsig,
+                DnsResourceRecord *dnskey) {
+
+        const char *curve;
+        size_t key_size;
+        uint8_t *q;
+
+        assert(hash);
+        assert(hash_size);
+        assert(rrsig);
+        assert(dnskey);
+
+        if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
+                key_size = 32;
+                curve = "NIST P-256";
+        } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
+                key_size = 48;
+                curve = "NIST P-384";
+        } else
+                return -EOPNOTSUPP;
+
+        if (dnskey->dnskey.key_size != key_size * 2)
+                return -EINVAL;
+
+        if (rrsig->rrsig.signature_size != key_size * 2)
+                return -EINVAL;
+
+        q = alloca(key_size*2 + 1);
+        q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
+        memcpy(q+1, dnskey->dnskey.key, key_size*2);
+
+        return dnssec_ecdsa_verify_raw(
+                        hash_algorithm,
+                        curve,
+                        rrsig->rrsig.signature, key_size,
+                        (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
+                        hash, hash_size,
+                        q, key_size*2+1);
+}
+
+static void md_add_uint8(gcry_md_hd_t md, uint8_t v) {
+        gcry_md_write(md, &v, sizeof(v));
+}
+
+static void md_add_uint16(gcry_md_hd_t md, uint16_t v) {
+        v = htobe16(v);
+        gcry_md_write(md, &v, sizeof(v));
+}
+
+static void md_add_uint32(gcry_md_hd_t md, uint32_t v) {
+        v = htobe32(v);
+        gcry_md_write(md, &v, sizeof(v));
+}
+
+static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
+        int n_key_labels, n_signer_labels;
+        const char *name;
+        int r;
+
+        /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and
+         * .n_skip_labels_signer fields so that we can use them later on. */
+
+        assert(rrsig);
+        assert(rrsig->key->type == DNS_TYPE_RRSIG);
+
+        /* Check if this RRSIG RR is already prepared */
+        if (rrsig->n_skip_labels_source != (unsigned) -1)
+                return 0;
+
+        if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
+                return -EINVAL;
+
+        name = DNS_RESOURCE_KEY_NAME(rrsig->key);
+
+        n_key_labels = dns_name_count_labels(name);
+        if (n_key_labels < 0)
+                return n_key_labels;
+        if (rrsig->rrsig.labels > n_key_labels)
+                return -EINVAL;
+
+        n_signer_labels = dns_name_count_labels(rrsig->rrsig.signer);
+        if (n_signer_labels < 0)
+                return n_signer_labels;
+        if (n_signer_labels > rrsig->rrsig.labels)
+                return -EINVAL;
+
+        r = dns_name_skip(name, n_key_labels - n_signer_labels, &name);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EINVAL;
+
+        /* Check if the signer is really a suffix of us */
+        r = dns_name_equal(name, rrsig->rrsig.signer);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EINVAL;
+
+        rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels;
+        rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels;
+
+        return 0;
+}
+
+static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
+        usec_t expiration, inception, skew;
+
+        assert(rrsig);
+        assert(rrsig->key->type == DNS_TYPE_RRSIG);
+
+        if (realtime == USEC_INFINITY)
+                realtime = now(CLOCK_REALTIME);
+
+        expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
+        inception = rrsig->rrsig.inception * USEC_PER_SEC;
+
+        /* Consider inverted validity intervals as expired */
+        if (inception > expiration)
+                return true;
+
+        /* Permit a certain amount of clock skew of 10% of the valid
+         * time range. This takes inspiration from unbound's
+         * resolver. */
+        skew = (expiration - inception) / 10;
+        if (skew > SKEW_MAX)
+                skew = SKEW_MAX;
+
+        if (inception < skew)
+                inception = 0;
+        else
+                inception -= skew;
+
+        if (expiration + skew < expiration)
+                expiration = USEC_INFINITY;
+        else
+                expiration += skew;
+
+        return realtime < inception || realtime > expiration;
+}
+
+static int algorithm_to_gcrypt_md(uint8_t algorithm) {
+
+        /* Translates a DNSSEC signature algorithm into a gcrypt
+         * digest identifier.
+         *
+         * Note that we implement all algorithms listed as "Must
+         * implement" and "Recommended to Implement" in RFC6944. We
+         * don't implement any algorithms that are listed as
+         * "Optional" or "Must Not Implement". Specifically, we do not
+         * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and
+         * GOST-ECC. */
+
+        switch (algorithm) {
+
+        case DNSSEC_ALGORITHM_RSASHA1:
+        case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
+                return GCRY_MD_SHA1;
+
+        case DNSSEC_ALGORITHM_RSASHA256:
+        case DNSSEC_ALGORITHM_ECDSAP256SHA256:
+                return GCRY_MD_SHA256;
+
+        case DNSSEC_ALGORITHM_ECDSAP384SHA384:
+                return GCRY_MD_SHA384;
+
+        case DNSSEC_ALGORITHM_RSASHA512:
+                return GCRY_MD_SHA512;
+
+        default:
+                return -EOPNOTSUPP;
+        }
+}
+
+static void dnssec_fix_rrset_ttl(
+                DnsResourceRecord *list[],
+                unsigned n,
+                DnsResourceRecord *rrsig,
+                usec_t realtime) {
+
+        unsigned k;
+
+        assert(list);
+        assert(n > 0);
+        assert(rrsig);
+
+        for (k = 0; k < n; k++) {
+                DnsResourceRecord *rr = list[k];
+
+                /* Pick the TTL as the minimum of the RR's TTL, the
+                 * RR's original TTL according to the RRSIG and the
+                 * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
+                rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
+                rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
+
+                /* Copy over information about the signer and wildcard source of synthesis */
+                rr->n_skip_labels_source = rrsig->n_skip_labels_source;
+                rr->n_skip_labels_signer = rrsig->n_skip_labels_signer;
+        }
+
+        rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
+}
+
+int dnssec_verify_rrset(
+                DnsAnswer *a,
+                const DnsResourceKey *key,
+                DnsResourceRecord *rrsig,
+                DnsResourceRecord *dnskey,
+                usec_t realtime,
+                DnssecResult *result) {
+
+        uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
+        DnsResourceRecord **list, *rr;
+        const char *source, *name;
+        gcry_md_hd_t md = NULL;
+        int r, md_algorithm;
+        size_t k, n = 0;
+        size_t hash_size;
+        void *hash;
+        bool wildcard;
+
+        assert(key);
+        assert(rrsig);
+        assert(dnskey);
+        assert(result);
+        assert(rrsig->key->type == DNS_TYPE_RRSIG);
+        assert(dnskey->key->type == DNS_TYPE_DNSKEY);
+
+        /* Verifies the the RRSet matching the specified "key" in "a",
+         * using the signature "rrsig" and the key "dnskey". It's
+         * assumed the RRSIG and DNSKEY match. */
+
+        md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm);
+        if (md_algorithm == -EOPNOTSUPP) {
+                *result = DNSSEC_UNSUPPORTED_ALGORITHM;
+                return 0;
+        }
+        if (md_algorithm < 0)
+                return md_algorithm;
+
+        r = dnssec_rrsig_prepare(rrsig);
+        if (r == -EINVAL) {
+                *result = DNSSEC_INVALID;
+                return r;
+        }
+        if (r < 0)
+                return r;
+
+        r = dnssec_rrsig_expired(rrsig, realtime);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                *result = DNSSEC_SIGNATURE_EXPIRED;
+                return 0;
+        }
+
+        name = DNS_RESOURCE_KEY_NAME(key);
+
+        /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
+        if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
+                r = dns_name_equal(rrsig->rrsig.signer, name);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        *result = DNSSEC_INVALID;
+                        return 0;
+                }
+        }
+
+        /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
+        if (rrsig->rrsig.type_covered == DNS_TYPE_DS) {
+                r = dns_name_equal(rrsig->rrsig.signer, name);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        *result = DNSSEC_INVALID;
+                        return 0;
+                }
+        }
+
+        /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
+        r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
+        if (r < 0)
+                return r;
+        if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) {
+                /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */
+                *result = DNSSEC_INVALID;
+                return 0;
+        }
+        if (r == 1) {
+                /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
+                 * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
+                r = dns_name_startswith(name, "*");
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        source = name;
+
+                wildcard = r == 0;
+        } else
+                wildcard = r > 0;
+
+        /* Collect all relevant RRs in a single array, so that we can look at the RRset */
+        list = newa(DnsResourceRecord *, dns_answer_size(a));
+
+        DNS_ANSWER_FOREACH(rr, a) {
+                r = dns_resource_key_equal(key, rr->key);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                /* We need the wire format for ordering, and digest calculation */
+                r = dns_resource_record_to_wire_format(rr, true);
+                if (r < 0)
+                        return r;
+
+                list[n++] = rr;
+
+                if (n > VERIFY_RRS_MAX)
+                        return -E2BIG;
+        }
+
+        if (n <= 0)
+                return -ENODATA;
+
+        /* Bring the RRs into canonical order */
+        qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare);
+
+        /* OK, the RRs are now in canonical order. Let's calculate the digest */
+        initialize_libgcrypt();
+
+        hash_size = gcry_md_get_algo_dlen(md_algorithm);
+        assert(hash_size > 0);
+
+        gcry_md_open(&md, md_algorithm, 0);
+        if (!md)
+                return -EIO;
+
+        md_add_uint16(md, rrsig->rrsig.type_covered);
+        md_add_uint8(md, rrsig->rrsig.algorithm);
+        md_add_uint8(md, rrsig->rrsig.labels);
+        md_add_uint32(md, rrsig->rrsig.original_ttl);
+        md_add_uint32(md, rrsig->rrsig.expiration);
+        md_add_uint32(md, rrsig->rrsig.inception);
+        md_add_uint16(md, rrsig->rrsig.key_tag);
+
+        r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
+        if (r < 0)
+                goto finish;
+        gcry_md_write(md, wire_format_name, r);
+
+        /* Convert the source of synthesis into wire format */
+        r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true);
+        if (r < 0)
+                goto finish;
+
+        for (k = 0; k < n; k++) {
+                size_t l;
+
+                rr = list[k];
+
+                /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */
+                if (wildcard)
+                        gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2);
+                gcry_md_write(md, wire_format_name, r);
+
+                md_add_uint16(md, rr->key->type);
+                md_add_uint16(md, rr->key->class);
+                md_add_uint32(md, rrsig->rrsig.original_ttl);
+
+                l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr);
+                assert(l <= 0xFFFF);
+
+                md_add_uint16(md, (uint16_t) l);
+                gcry_md_write(md, DNS_RESOURCE_RECORD_RDATA(rr), l);
+        }
+
+        hash = gcry_md_read(md, 0);
+        if (!hash) {
+                r = -EIO;
+                goto finish;
+        }
+
+        switch (rrsig->rrsig.algorithm) {
+
+        case DNSSEC_ALGORITHM_RSASHA1:
+        case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
+        case DNSSEC_ALGORITHM_RSASHA256:
+        case DNSSEC_ALGORITHM_RSASHA512:
+                r = dnssec_rsa_verify(
+                                gcry_md_algo_name(md_algorithm),
+                                hash, hash_size,
+                                rrsig,
+                                dnskey);
+                break;
+
+        case DNSSEC_ALGORITHM_ECDSAP256SHA256:
+        case DNSSEC_ALGORITHM_ECDSAP384SHA384:
+                r = dnssec_ecdsa_verify(
+                                gcry_md_algo_name(md_algorithm),
+                                rrsig->rrsig.algorithm,
+                                hash, hash_size,
+                                rrsig,
+                                dnskey);
+                break;
+        }
+
+        if (r < 0)
+                goto finish;
+
+        /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
+        if (r > 0)
+                dnssec_fix_rrset_ttl(list, n, rrsig, realtime);
+
+        if (r == 0)
+                *result = DNSSEC_INVALID;
+        else if (wildcard)
+                *result = DNSSEC_VALIDATED_WILDCARD;
+        else
+                *result = DNSSEC_VALIDATED;
+
+        r = 0;
+
+finish:
+        gcry_md_close(md);
+        return r;
+}
+
+int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
+
+        assert(rrsig);
+        assert(dnskey);
+
+        /* Checks if the specified DNSKEY RR matches the key used for
+         * the signature in the specified RRSIG RR */
+
+        if (rrsig->key->type != DNS_TYPE_RRSIG)
+                return -EINVAL;
+
+        if (dnskey->key->type != DNS_TYPE_DNSKEY)
+                return 0;
+        if (dnskey->key->class != rrsig->key->class)
+                return 0;
+        if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
+                return 0;
+        if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
+                return 0;
+        if (dnskey->dnskey.protocol != 3)
+                return 0;
+        if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
+                return 0;
+
+        if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
+                return 0;
+
+        return dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), rrsig->rrsig.signer);
+}
+
+int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
+        assert(key);
+        assert(rrsig);
+
+        /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
+
+        if (rrsig->key->type != DNS_TYPE_RRSIG)
+                return 0;
+        if (rrsig->key->class != key->class)
+                return 0;
+        if (rrsig->rrsig.type_covered != key->type)
+                return 0;
+
+        return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key));
+}
+
+int dnssec_verify_rrset_search(
+                DnsAnswer *a,
+                const DnsResourceKey *key,
+                DnsAnswer *validated_dnskeys,
+                usec_t realtime,
+                DnssecResult *result,
+                DnsResourceRecord **ret_rrsig) {
+
+        bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
+        DnsResourceRecord *rrsig;
+        int r;
+
+        assert(key);
+        assert(result);
+
+        /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
+
+        if (!a || a->n_rrs <= 0)
+                return -ENODATA;
+
+        /* Iterate through each RRSIG RR. */
+        DNS_ANSWER_FOREACH(rrsig, a) {
+                DnsResourceRecord *dnskey;
+                DnsAnswerFlags flags;
+
+                /* Is this an RRSIG RR that applies to RRs matching our key? */
+                r = dnssec_key_match_rrsig(key, rrsig);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                found_rrsig = true;
+
+                /* Look for a matching key */
+                DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
+                        DnssecResult one_result;
+
+                        if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
+                                continue;
+
+                        /* Is this a DNSKEY RR that matches they key of our RRSIG? */
+                        r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        /* Take the time here, if it isn't set yet, so
+                         * that we do all validations with the same
+                         * time. */
+                        if (realtime == USEC_INFINITY)
+                                realtime = now(CLOCK_REALTIME);
+
+                        /* Yay, we found a matching RRSIG with a matching
+                         * DNSKEY, awesome. Now let's verify all entries of
+                         * the RRSet against the RRSIG and DNSKEY
+                         * combination. */
+
+                        r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
+                        if (r < 0)
+                                return r;
+
+                        switch (one_result) {
+
+                        case DNSSEC_VALIDATED:
+                        case DNSSEC_VALIDATED_WILDCARD:
+                                /* Yay, the RR has been validated,
+                                 * return immediately, but fix up the expiry */
+                                if (ret_rrsig)
+                                        *ret_rrsig = rrsig;
+
+                                *result = one_result;
+                                return 0;
+
+                        case DNSSEC_INVALID:
+                                /* If the signature is invalid, let's try another
+                                   key and/or signature. After all they
+                                   key_tags and stuff are not unique, and
+                                   might be shared by multiple keys. */
+                                found_invalid = true;
+                                continue;
+
+                        case DNSSEC_UNSUPPORTED_ALGORITHM:
+                                /* If the key algorithm is
+                                   unsupported, try another
+                                   RRSIG/DNSKEY pair, but remember we
+                                   encountered this, so that we can
+                                   return a proper error when we
+                                   encounter nothing better. */
+                                found_unsupported_algorithm = true;
+                                continue;
+
+                        case DNSSEC_SIGNATURE_EXPIRED:
+                                /* If the signature is expired, try
+                                   another one, but remember it, so
+                                   that we can return this */
+                                found_expired_rrsig = true;
+                                continue;
+
+                        default:
+                                assert_not_reached("Unexpected DNSSEC validation result");
+                        }
+                }
+        }
+
+        if (found_expired_rrsig)
+                *result = DNSSEC_SIGNATURE_EXPIRED;
+        else if (found_unsupported_algorithm)
+                *result = DNSSEC_UNSUPPORTED_ALGORITHM;
+        else if (found_invalid)
+                *result = DNSSEC_INVALID;
+        else if (found_rrsig)
+                *result = DNSSEC_MISSING_KEY;
+        else
+                *result = DNSSEC_NO_SIGNATURE;
+
+        if (ret_rrsig)
+                *ret_rrsig = NULL;
+
+        return 0;
+}
+
+int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
+        DnsResourceRecord *rr;
+        int r;
+
+        /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */
+
+        DNS_ANSWER_FOREACH(rr, a) {
+                r = dnssec_key_match_rrsig(key, rr);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        return 1;
+        }
+
+        return 0;
+}
+
+static int digest_to_gcrypt_md(uint8_t algorithm) {
+
+        /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
+
+        switch (algorithm) {
+
+        case DNSSEC_DIGEST_SHA1:
+                return GCRY_MD_SHA1;
+
+        case DNSSEC_DIGEST_SHA256:
+                return GCRY_MD_SHA256;
+
+        case DNSSEC_DIGEST_SHA384:
+                return GCRY_MD_SHA384;
+
+        default:
+                return -EOPNOTSUPP;
+        }
+}
+
+int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
+        char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX];
+        gcry_md_hd_t md = NULL;
+        size_t hash_size;
+        int md_algorithm, r;
+        void *result;
+
+        assert(dnskey);
+        assert(ds);
+
+        /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
+
+        if (dnskey->key->type != DNS_TYPE_DNSKEY)
+                return -EINVAL;
+        if (ds->key->type != DNS_TYPE_DS)
+                return -EINVAL;
+        if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
+                return -EKEYREJECTED;
+        if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
+                return -EKEYREJECTED;
+        if (dnskey->dnskey.protocol != 3)
+                return -EKEYREJECTED;
+
+        if (dnskey->dnskey.algorithm != ds->ds.algorithm)
+                return 0;
+        if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag)
+                return 0;
+
+        initialize_libgcrypt();
+
+        md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type);
+        if (md_algorithm < 0)
+                return md_algorithm;
+
+        hash_size = gcry_md_get_algo_dlen(md_algorithm);
+        assert(hash_size > 0);
+
+        if (ds->ds.digest_size != hash_size)
+                return 0;
+
+        r = dnssec_canonicalize(DNS_RESOURCE_KEY_NAME(dnskey->key), owner_name, sizeof(owner_name));
+        if (r < 0)
+                return r;
+
+        gcry_md_open(&md, md_algorithm, 0);
+        if (!md)
+                return -EIO;
+
+        gcry_md_write(md, owner_name, r);
+        if (mask_revoke)
+                md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
+        else
+                md_add_uint16(md, dnskey->dnskey.flags);
+        md_add_uint8(md, dnskey->dnskey.protocol);
+        md_add_uint8(md, dnskey->dnskey.algorithm);
+        gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
+
+        result = gcry_md_read(md, 0);
+        if (!result) {
+                r = -EIO;
+                goto finish;
+        }
+
+        r = memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0;
+
+finish:
+        gcry_md_close(md);
+        return r;
+}
+
+int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
+        DnsResourceRecord *ds;
+        DnsAnswerFlags flags;
+        int r;
+
+        assert(dnskey);
+
+        if (dnskey->key->type != DNS_TYPE_DNSKEY)
+                return 0;
+
+        DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
+
+                if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
+                        continue;
+
+                if (ds->key->type != DNS_TYPE_DS)
+                        continue;
+                if (ds->key->class != dnskey->key->class)
+                        continue;
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), DNS_RESOURCE_KEY_NAME(ds->key));
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = dnssec_verify_dnskey_by_ds(dnskey, ds, false);
+                if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP))
+                        return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        return 1;
+        }
+
+        return 0;
+}
+
+static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
+
+        /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */
+
+        switch (algorithm) {
+
+        case NSEC3_ALGORITHM_SHA1:
+                return GCRY_MD_SHA1;
+
+        default:
+                return -EOPNOTSUPP;
+        }
+}
+
+int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
+        uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX];
+        gcry_md_hd_t md = NULL;
+        size_t hash_size;
+        int algorithm;
+        void *result;
+        unsigned k;
+        int r;
+
+        assert(nsec3);
+        assert(name);
+        assert(ret);
+
+        if (nsec3->key->type != DNS_TYPE_NSEC3)
+                return -EINVAL;
+
+        if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX) {
+                log_debug("Ignoring NSEC3 RR %s with excessive number of iterations.", dns_resource_record_to_string(nsec3));
+                return -EOPNOTSUPP;
+        }
+
+        algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm);
+        if (algorithm < 0)
+                return algorithm;
+
+        initialize_libgcrypt();
+
+        hash_size = gcry_md_get_algo_dlen(algorithm);
+        assert(hash_size > 0);
+
+        if (nsec3->nsec3.next_hashed_name_size != hash_size)
+                return -EINVAL;
+
+        r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
+        if (r < 0)
+                return r;
+
+        gcry_md_open(&md, algorithm, 0);
+        if (!md)
+                return -EIO;
+
+        gcry_md_write(md, wire_format, r);
+        gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
+
+        result = gcry_md_read(md, 0);
+        if (!result) {
+                r = -EIO;
+                goto finish;
+        }
+
+        for (k = 0; k < nsec3->nsec3.iterations; k++) {
+                uint8_t tmp[hash_size];
+                memcpy(tmp, result, hash_size);
+
+                gcry_md_reset(md);
+                gcry_md_write(md, tmp, hash_size);
+                gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
+
+                result = gcry_md_read(md, 0);
+                if (!result) {
+                        r = -EIO;
+                        goto finish;
+                }
+        }
+
+        memcpy(ret, result, hash_size);
+        r = (int) hash_size;
+
+finish:
+        gcry_md_close(md);
+        return r;
+}
+
+static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
+        const char *a, *b;
+        int r;
+
+        assert(rr);
+
+        if (rr->key->type != DNS_TYPE_NSEC3)
+                return 0;
+
+        /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
+        if (!IN_SET(rr->nsec3.flags, 0, 1))
+                return 0;
+
+        /* Ignore NSEC3 RRs whose algorithm we don't know */
+        if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0)
+                return 0;
+        /* Ignore NSEC3 RRs with an excessive number of required iterations */
+        if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
+                return 0;
+
+        /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
+         * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
+        if (rr->n_skip_labels_source != 0 && rr->n_skip_labels_source != (unsigned) -1)
+                return 0;
+        /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
+        if (rr->n_skip_labels_signer != 1 && rr->n_skip_labels_signer != (unsigned) -1)
+                return 0;
+
+        if (!nsec3)
+                return 1;
+
+        /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
+
+        if (nsec3 == rr) /* Shortcut */
+                return 1;
+
+        if (rr->key->class != nsec3->key->class)
+                return 0;
+        if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
+                return 0;
+        if (rr->nsec3.iterations != nsec3->nsec3.iterations)
+                return 0;
+        if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
+                return 0;
+        if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
+                return 0;
+
+        a = DNS_RESOURCE_KEY_NAME(rr->key);
+        r = dns_name_parent(&a); /* strip off hash */
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 0;
+
+        b = DNS_RESOURCE_KEY_NAME(nsec3->key);
+        r = dns_name_parent(&b); /* strip off hash */
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 0;
+
+        /* Make sure both have the same parent */
+        return dns_name_equal(a, b);
+}
+
+static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) {
+        _cleanup_free_ char *l = NULL;
+        char *j;
+
+        assert(hashed);
+        assert(hashed_size > 0);
+        assert(zone);
+        assert(ret);
+
+        l = base32hexmem(hashed, hashed_size, false);
+        if (!l)
+                return -ENOMEM;
+
+        j = strjoin(l, ".", zone, NULL);
+        if (!j)
+                return -ENOMEM;
+
+        *ret = j;
+        return (int) hashed_size;
+}
+
+static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) {
+        uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
+        int hashed_size;
+
+        assert(nsec3);
+        assert(domain);
+        assert(zone);
+        assert(ret);
+
+        hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
+        if (hashed_size < 0)
+                return hashed_size;
+
+        return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret);
+}
+
+/* See RFC 5155, Section 8
+ * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
+ * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
+ * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
+ * matches the wildcard domain.
+ *
+ * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
+ * that there is no proof either way. The latter is the case if a the proof of non-existence of a given
+ * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
+ * to conclude anything we indicate this by returning NO_RR. */
+static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
+        _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL;
+        const char *zone, *p, *pp = NULL, *wildcard;
+        DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL;
+        DnsAnswerFlags flags;
+        int hashed_size, r;
+        bool a, no_closer = false, no_wildcard = false, optout = false;
+
+        assert(key);
+        assert(result);
+
+        /* First step, find the zone name and the NSEC3 parameters of the zone.
+         * it is sufficient to look for the longest common suffix we find with
+         * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
+         * records from a given zone in a response must use the same
+         * parameters. */
+        zone = DNS_RESOURCE_KEY_NAME(key);
+        for (;;) {
+                DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
+                        r = nsec3_is_good(zone_rr, NULL);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = dns_name_equal_skip(DNS_RESOURCE_KEY_NAME(zone_rr->key), 1, zone);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                goto found_zone;
+                }
+
+                /* Strip one label from the front */
+                r = dns_name_parent(&zone);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+        }
+
+        *result = DNSSEC_NSEC_NO_RR;
+        return 0;
+
+found_zone:
+        /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
+        p = DNS_RESOURCE_KEY_NAME(key);
+        for (;;) {
+                _cleanup_free_ char *hashed_domain = NULL;
+
+                hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain);
+                if (hashed_size == -EOPNOTSUPP) {
+                        *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
+                        return 0;
+                }
+                if (hashed_size < 0)
+                        return hashed_size;
+
+                DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
+
+                        r = nsec3_is_good(enclosure_rr, zone_rr);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
+                                continue;
+
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(enclosure_rr->key), hashed_domain);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                a = flags & DNS_ANSWER_AUTHENTICATED;
+                                goto found_closest_encloser;
+                        }
+                }
+
+                /* We didn't find the closest encloser with this name,
+                 * but let's remember this domain name, it might be
+                 * the next closer name */
+
+                pp = p;
+
+                /* Strip one label from the front */
+                r = dns_name_parent(&p);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+        }
+
+        *result = DNSSEC_NSEC_NO_RR;
+        return 0;
+
+found_closest_encloser:
+        /* We found a closest encloser in 'p'; next closer is 'pp' */
+
+        if (!pp) {
+                /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR
+                 * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are
+                 * appropriately set. */
+
+                if (key->type == DNS_TYPE_DS) {
+                        if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
+                                return -EBADMSG;
+                } else {
+                        if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
+                            !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
+                                return -EBADMSG;
+                }
+
+                /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
+                if (bitmap_isset(enclosure_rr->nsec3.types, key->type))
+                        *result = DNSSEC_NSEC_FOUND;
+                else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME))
+                        *result = DNSSEC_NSEC_CNAME;
+                else
+                        *result = DNSSEC_NSEC_NODATA;
+
+                if (authenticated)
+                        *authenticated = a;
+                if (ttl)
+                        *ttl = enclosure_rr->ttl;
+
+                return 0;
+        }
+
+        /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
+        if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
+                return -EBADMSG;
+
+        /* Ensure that this data is from the delegated domain
+         * (i.e. originates from the "lower" DNS server), and isn't
+         * just glue records (i.e. doesn't originate from the "upper"
+         * DNS server). */
+        if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
+            !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
+                return -EBADMSG;
+
+        /* Prove that there is no next closer and whether or not there is a wildcard domain. */
+
+        wildcard = strjoina("*.", p);
+        r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain);
+        if (r < 0)
+                return r;
+        if (r != hashed_size)
+                return -EBADMSG;
+
+        r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain);
+        if (r < 0)
+                return r;
+        if (r != hashed_size)
+                return -EBADMSG;
+
+        DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
+                _cleanup_free_ char *next_hashed_domain = NULL;
+
+                r = nsec3_is_good(rr, zone_rr);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain);
+                if (r < 0)
+                        return r;
+
+                r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), next_closer_domain, next_hashed_domain);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        if (rr->nsec3.flags & 1)
+                                optout = true;
+
+                        a = a && (flags & DNS_ANSWER_AUTHENTICATED);
+
+                        no_closer = true;
+                }
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        a = a && (flags & DNS_ANSWER_AUTHENTICATED);
+
+                        wildcard_rr = rr;
+                }
+
+                r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain, next_hashed_domain);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        if (rr->nsec3.flags & 1)
+                                /* This only makes sense if we have a wildcard delegation, which is
+                                 * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
+                                 * this not happening, so hence cannot simply conclude NXDOMAIN as
+                                 * we would wish */
+                                optout = true;
+
+                        a = a && (flags & DNS_ANSWER_AUTHENTICATED);
+
+                        no_wildcard = true;
+                }
+        }
+
+        if (wildcard_rr && no_wildcard)
+                return -EBADMSG;
+
+        if (!no_closer) {
+                *result = DNSSEC_NSEC_NO_RR;
+                return 0;
+        }
+
+        if (wildcard_rr) {
+                /* A wildcard exists that matches our query. */
+                if (optout)
+                        /* This is not specified in any RFC to the best of my knowledge, but
+                         * if the next closer enclosure is covered by an opt-out NSEC3 RR
+                         * it means that we cannot prove that the source of synthesis is
+                         * correct, as there may be a closer match. */
+                        *result = DNSSEC_NSEC_OPTOUT;
+                else if (bitmap_isset(wildcard_rr->nsec3.types, key->type))
+                        *result = DNSSEC_NSEC_FOUND;
+                else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME))
+                        *result = DNSSEC_NSEC_CNAME;
+                else
+                        *result = DNSSEC_NSEC_NODATA;
+        } else {
+                if (optout)
+                        /* The RFC only specifies that we have to care for optout for NODATA for
+                         * DS records. However, children of an insecure opt-out delegation should
+                         * also be considered opt-out, rather than verified NXDOMAIN.
+                         * Note that we do not require a proof of wildcard non-existence if the
+                         * next closer domain is covered by an opt-out, as that would not provide
+                         * any additional information. */
+                        *result = DNSSEC_NSEC_OPTOUT;
+                else if (no_wildcard)
+                        *result = DNSSEC_NSEC_NXDOMAIN;
+                else {
+                        *result = DNSSEC_NSEC_NO_RR;
+
+                        return 0;
+                }
+        }
+
+        if (authenticated)
+                *authenticated = a;
+
+        if (ttl)
+                *ttl = enclosure_rr->ttl;
+
+        return 0;
+}
+
+static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
+        char label[DNS_LABEL_MAX];
+        const char *n;
+        int r;
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_NSEC);
+
+        /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
+
+        if (rr->n_skip_labels_source != 1)
+                return 0;
+
+        n = DNS_RESOURCE_KEY_NAME(rr->key);
+        r = dns_label_unescape(&n, label, sizeof(label));
+        if (r <= 0)
+                return r;
+        if (r != 1 || label[0] != '*')
+                return 0;
+
+        return dns_name_endswith(name, n);
+}
+
+static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
+        const char *nn, *common_suffix;
+        int r;
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_NSEC);
+
+        /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
+         *
+         * A couple of examples:
+         *
+         *      NSEC             bar →   waldo.foo.bar: indicates that foo.bar exists and is an ENT
+         *      NSEC   waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs
+         *      NSEC yyy.zzz.xoo.bar →             bar: indicates pretty much nothing about ENTs
+         */
+
+        /* First, determine parent of next domain. */
+        nn = rr->nsec.next_domain_name;
+        r = dns_name_parent(&nn);
+        if (r <= 0)
+                return r;
+
+        /* If the name we just determined is not equal or child of the name we are interested in, then we can't say
+         * anything at all. */
+        r = dns_name_endswith(nn, name);
+        if (r <= 0)
+                return r;
+
+        /* If the name we we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */
+        r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
+        if (r < 0)
+                return r;
+
+        return dns_name_endswith(name, common_suffix);
+}
+
+static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) {
+        int r;
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_NSEC);
+
+        /* Checks whether this NSEC originates to the parent zone or the child zone. */
+
+        r = dns_name_parent(&name);
+        if (r <= 0)
+                return r;
+
+        r = dns_name_equal(name, DNS_RESOURCE_KEY_NAME(rr->key));
+        if (r <= 0)
+                return r;
+
+        /* DNAME, and NS without SOA is an indication for a delegation. */
+        if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME))
+                return 1;
+
+        if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
+                return 1;
+
+        return 0;
+}
+
+static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
+        const char *common_suffix, *p;
+        int r;
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_NSEC);
+
+        /* Checks whether the "Next Closer" is witin the space covered by the specified RR. */
+
+        r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
+        if (r < 0)
+                return r;
+
+        for (;;) {
+                p = name;
+                r = dns_name_parent(&name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 0;
+
+                r = dns_name_equal(name, common_suffix);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        break;
+        }
+
+        /* p is now the "Next Closer". */
+
+        return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), p, rr->nsec.next_domain_name);
+}
+
+static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) {
+        const char *common_suffix, *wc;
+        int r;
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_NSEC);
+
+        /* Checks whether the "Wildcard at the Closest Encloser" is within the space covered by the specified
+         * RR. Specifically, checks whether 'name' has the common suffix of the NSEC RR's owner and next names as
+         * suffix, and whether the NSEC covers the name generated by that suffix prepended with an asterisk label.
+         *
+         *     NSEC             bar →   waldo.foo.bar: indicates that *.bar and *.foo.bar do not exist
+         *     NSEC   waldo.foo.bar → yyy.zzz.xoo.bar: indicates that *.xoo.bar and *.zzz.xoo.bar do not exist (and more ...)
+         *     NSEC yyy.zzz.xoo.bar →             bar: indicates that a number of wildcards don#t exist either...
+         */
+
+        r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
+        if (r < 0)
+                return r;
+
+        /* If the common suffix is not shared by the name we are interested in, it has nothing to say for us. */
+        r = dns_name_endswith(name, common_suffix);
+        if (r <= 0)
+                return r;
+
+        wc = strjoina("*.", common_suffix, NULL);
+        return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wc, rr->nsec.next_domain_name);
+}
+
+int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
+        bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false;
+        DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL;
+        DnsAnswerFlags flags;
+        const char *name;
+        int r;
+
+        assert(key);
+        assert(result);
+
+        /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
+
+        name = DNS_RESOURCE_KEY_NAME(key);
+
+        DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
+
+                if (rr->key->class != key->class)
+                        continue;
+
+                have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3);
+
+                if (rr->key->type != DNS_TYPE_NSEC)
+                        continue;
+
+                /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */
+                r = dns_resource_record_is_synthetic(rr);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                /* Check if this is a direct match. If so, we have encountered a NODATA case */
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), name);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        /* If it's not a direct match, maybe it's a wild card match? */
+                        r = dnssec_nsec_wildcard_equal(rr, name);
+                        if (r < 0)
+                                return r;
+                }
+                if (r > 0) {
+                        if (key->type == DNS_TYPE_DS) {
+                                /* If we look for a DS RR and the server sent us the NSEC RR of the child zone
+                                 * we have a problem. For DS RRs we want the NSEC RR from the parent */
+                                if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
+                                        continue;
+                        } else {
+                                /* For all RR types, ensure that if NS is set SOA is set too, so that we know
+                                 * we got the child's NSEC. */
+                                if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) &&
+                                    !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
+                                        continue;
+                        }
+
+                        if (bitmap_isset(rr->nsec.types, key->type))
+                                *result = DNSSEC_NSEC_FOUND;
+                        else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME))
+                                *result = DNSSEC_NSEC_CNAME;
+                        else
+                                *result = DNSSEC_NSEC_NODATA;
+
+                        if (authenticated)
+                                *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
+                        if (ttl)
+                                *ttl = rr->ttl;
+
+                        return 0;
+                }
+
+                /* Check if the name we are looking for is an empty non-terminal within the owner or next name
+                 * of the NSEC RR. */
+                r = dnssec_nsec_in_path(rr, name);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        *result = DNSSEC_NSEC_NODATA;
+
+                        if (authenticated)
+                                *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
+                        if (ttl)
+                                *ttl = rr->ttl;
+
+                        return 0;
+                }
+
+                /* The following two "covering" checks, are not useful if the NSEC is from the parent */
+                r = dnssec_nsec_from_parent_zone(rr, name);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                /* Check if this NSEC RR proves the absence of an explicit RR under this name */
+                r = dnssec_nsec_covers(rr, name);
+                if (r < 0)
+                        return r;
+                if (r > 0 && (!covering_rr || !covering_rr_authenticated)) {
+                        covering_rr = rr;
+                        covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
+                }
+
+                /* Check if this NSEC RR proves the absence of a wildcard RR under this name */
+                r = dnssec_nsec_covers_wildcard(rr, name);
+                if (r < 0)
+                        return r;
+                if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) {
+                        wildcard_rr = rr;
+                        wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
+                }
+        }
+
+        if (covering_rr && wildcard_rr) {
+                /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we
+                 * proved the NXDOMAIN case. */
+                *result = DNSSEC_NSEC_NXDOMAIN;
+
+                if (authenticated)
+                        *authenticated = covering_rr_authenticated && wildcard_rr_authenticated;
+                if (ttl)
+                        *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl);
+
+                return 0;
+        }
+
+        /* OK, this was not sufficient. Let's see if NSEC3 can help. */
+        if (have_nsec3)
+                return dnssec_test_nsec3(answer, key, result, authenticated, ttl);
+
+        /* No approproate NSEC RR found, report this. */
+        *result = DNSSEC_NSEC_NO_RR;
+        return 0;
+}
+
+static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+        int r;
+
+        assert(name);
+        assert(zone);
+
+        /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified
+         * 'zone'. The 'zone' must be a suffix of the 'name'. */
+
+        DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
+                bool found = false;
+
+                if (rr->key->type != type && type != DNS_TYPE_ANY)
+                        continue;
+
+                switch (rr->key->type) {
+
+                case DNS_TYPE_NSEC:
+
+                        /* We only care for NSEC RRs from the indicated zone */
+                        r = dns_resource_record_is_signer(rr, zone);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), name, rr->nsec.next_domain_name);
+                        if (r < 0)
+                                return r;
+
+                        found = r > 0;
+                        break;
+
+                case DNS_TYPE_NSEC3: {
+                        _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL;
+
+                        /* We only care for NSEC3 RRs from the indicated zone */
+                        r = dns_resource_record_is_signer(rr, zone);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = nsec3_is_good(rr, NULL);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                break;
+
+                        /* Format the domain we are testing with the NSEC3 RR's hash function */
+                        r = nsec3_hashed_domain_make(
+                                        rr,
+                                        name,
+                                        zone,
+                                        &hashed_domain);
+                        if (r < 0)
+                                return r;
+                        if ((size_t) r != rr->nsec3.next_hashed_name_size)
+                                break;
+
+                        /* Format the NSEC3's next hashed name as proper domain name */
+                        r = nsec3_hashed_domain_format(
+                                        rr->nsec3.next_hashed_name,
+                                        rr->nsec3.next_hashed_name_size,
+                                        zone,
+                                        &next_hashed_domain);
+                        if (r < 0)
+                                return r;
+
+                        r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain, next_hashed_domain);
+                        if (r < 0)
+                                return r;
+
+                        found = r > 0;
+                        break;
+                }
+
+                default:
+                        continue;
+                }
+
+                if (found) {
+                        if (authenticated)
+                                *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
+                        return 1;
+                }
+        }
+
+        return 0;
+}
+
+static int dnssec_test_positive_wildcard_nsec3(
+                DnsAnswer *answer,
+                const char *name,
+                const char *source,
+                const char *zone,
+                bool *authenticated) {
+
+        const char *next_closer = NULL;
+        int r;
+
+        /* Run a positive NSEC3 wildcard proof. Specifically:
+         *
+         * A proof that the the "next closer" of the generating wildcard does not exist.
+         *
+         * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for
+         * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name
+         * exists for the NSEC3 RR and we are done.
+         *
+         * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that
+         * c.d.e.f does not exist. */
+
+        for (;;) {
+                next_closer = name;
+                r = dns_name_parent(&name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 0;
+
+                r = dns_name_equal(name, source);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        break;
+        }
+
+        return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated);
+}
+
+static int dnssec_test_positive_wildcard_nsec(
+                DnsAnswer *answer,
+                const char *name,
+                const char *source,
+                const char *zone,
+                bool *_authenticated) {
+
+        bool authenticated = true;
+        int r;
+
+        /* Run a positive NSEC wildcard proof. Specifically:
+         *
+         * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and
+         * a prefix of the synthesizing source "source" in the zone "zone".
+         *
+         * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
+         *
+         * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we
+         * have to prove that none of the following exist:
+         *
+         *      1) a.b.c.d.e.f
+         *      2) *.b.c.d.e.f
+         *      3)   b.c.d.e.f
+         *      4)   *.c.d.e.f
+         *      5)     c.d.e.f
+         *
+         */
+
+        for (;;) {
+                _cleanup_free_ char *wc = NULL;
+                bool a = false;
+
+                /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing,
+                 * i.e between the owner name and the next name of an NSEC RR. */
+                r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a);
+                if (r <= 0)
+                        return r;
+
+                authenticated = authenticated && a;
+
+                /* Strip one label off */
+                r = dns_name_parent(&name);
+                if (r <= 0)
+                        return r;
+
+                /* Did we reach the source of synthesis? */
+                r = dns_name_equal(name, source);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        /* Successful exit */
+                        *_authenticated = authenticated;
+                        return 1;
+                }
+
+                /* Safety check, that the source of synthesis is still our suffix */
+                r = dns_name_endswith(name, source);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -EBADMSG;
+
+                /* Replace the label we stripped off with an asterisk */
+                wc = strappend("*.", name);
+                if (!wc)
+                        return -ENOMEM;
+
+                /* And check if the proof holds for the asterisk name, too */
+                r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a);
+                if (r <= 0)
+                        return r;
+
+                authenticated = authenticated && a;
+                /* In the next iteration we'll check the non-asterisk-prefixed version */
+        }
+}
+
+int dnssec_test_positive_wildcard(
+                DnsAnswer *answer,
+                const char *name,
+                const char *source,
+                const char *zone,
+                bool *authenticated) {
+
+        int r;
+
+        assert(name);
+        assert(source);
+        assert(zone);
+        assert(authenticated);
+
+        r = dns_answer_contains_zone_nsec3(answer, zone);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated);
+        else
+                return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
+}
+
+#else
+
+int dnssec_verify_rrset(
+                DnsAnswer *a,
+                const DnsResourceKey *key,
+                DnsResourceRecord *rrsig,
+                DnsResourceRecord *dnskey,
+                usec_t realtime,
+                DnssecResult *result) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_verify_rrset_search(
+                DnsAnswer *a,
+                const DnsResourceKey *key,
+                DnsAnswer *validated_dnskeys,
+                usec_t realtime,
+                DnssecResult *result,
+                DnsResourceRecord **ret_rrsig) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
+
+        return -EOPNOTSUPP;
+}
+
+int dnssec_test_positive_wildcard(
+                DnsAnswer *answer,
+                const char *name,
+                const char *source,
+                const char *zone,
+                bool *authenticated) {
+
+        return -EOPNOTSUPP;
+}
+
+#endif
+
+static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
+        [DNSSEC_VALIDATED] = "validated",
+        [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard",
+        [DNSSEC_INVALID] = "invalid",
+        [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
+        [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
+        [DNSSEC_NO_SIGNATURE] = "no-signature",
+        [DNSSEC_MISSING_KEY] = "missing-key",
+        [DNSSEC_UNSIGNED] = "unsigned",
+        [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
+        [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
+        [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
+};
+DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
+
+static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = {
+        [DNSSEC_SECURE] = "secure",
+        [DNSSEC_INSECURE] = "insecure",
+        [DNSSEC_BOGUS] = "bogus",
+        [DNSSEC_INDETERMINATE] = "indeterminate",
+};
+DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict);
diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h
new file mode 100644 (file)
index 0000000..77bd4d7
--- /dev/null
@@ -0,0 +1,102 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef enum DnssecResult DnssecResult;
+typedef enum DnssecVerdict DnssecVerdict;
+
+#include "dns-domain.h"
+#include "resolved-dns-answer.h"
+#include "resolved-dns-rr.h"
+
+enum DnssecResult {
+        /* These five are returned by dnssec_verify_rrset() */
+        DNSSEC_VALIDATED,
+        DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */
+        DNSSEC_INVALID,
+        DNSSEC_SIGNATURE_EXPIRED,
+        DNSSEC_UNSUPPORTED_ALGORITHM,
+
+        /* These two are added by dnssec_verify_rrset_search() */
+        DNSSEC_NO_SIGNATURE,
+        DNSSEC_MISSING_KEY,
+
+        /* These two are added by the DnsTransaction logic */
+        DNSSEC_UNSIGNED,
+        DNSSEC_FAILED_AUXILIARY,
+        DNSSEC_NSEC_MISMATCH,
+        DNSSEC_INCOMPATIBLE_SERVER,
+
+        _DNSSEC_RESULT_MAX,
+        _DNSSEC_RESULT_INVALID = -1
+};
+
+enum DnssecVerdict {
+        DNSSEC_SECURE,
+        DNSSEC_INSECURE,
+        DNSSEC_BOGUS,
+        DNSSEC_INDETERMINATE,
+
+        _DNSSEC_VERDICT_MAX,
+        _DNSSEC_VERDICT_INVALID = -1
+};
+
+#define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2)
+
+/* The longest digest we'll ever generate, of all digest algorithms we support */
+#define DNSSEC_HASH_SIZE_MAX (MAX(20, 32))
+
+int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok);
+int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig);
+
+int dnssec_verify_rrset(DnsAnswer *answer, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result);
+int dnssec_verify_rrset_search(DnsAnswer *answer, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **rrsig);
+
+int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke);
+int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds);
+
+int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key);
+
+uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke);
+
+int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max);
+
+int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret);
+
+typedef enum DnssecNsecResult {
+        DNSSEC_NSEC_NO_RR,     /* No suitable NSEC/NSEC3 RR found */
+        DNSSEC_NSEC_CNAME,     /* Didn't find what was asked for, but did find CNAME */
+        DNSSEC_NSEC_UNSUPPORTED_ALGORITHM,
+        DNSSEC_NSEC_NXDOMAIN,
+        DNSSEC_NSEC_NODATA,
+        DNSSEC_NSEC_FOUND,
+        DNSSEC_NSEC_OPTOUT,
+} DnssecNsecResult;
+
+int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
+
+
+int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated);
+
+const char* dnssec_result_to_string(DnssecResult m) _const_;
+DnssecResult dnssec_result_from_string(const char *s) _pure_;
+
+const char* dnssec_verdict_to_string(DnssecVerdict m) _const_;
+DnssecVerdict dnssec_verdict_from_string(const char *s) _pure_;
index f23b3cf89340d120119ed20c53900250611e66e6..c940dd892988fd72347da5fb293d5cca70a834d0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -28,6 +26,8 @@
 #include "utf8.h"
 #include "util.h"
 
+#define EDNS0_OPT_DO (1<<15)
+
 int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
         DnsPacket *p;
         size_t a;
@@ -56,6 +56,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
         p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
         p->allocated = a;
         p->protocol = protocol;
+        p->opt_start = p->opt_size = (size_t) -1;
         p->n_ref = 1;
 
         *ret = p;
@@ -63,20 +64,18 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
         return 0;
 }
 
-int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
-        DnsPacket *p;
-        DnsPacketHeader *h;
-        int r;
+void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
 
-        assert(ret);
+        DnsPacketHeader *h;
 
-        r = dns_packet_new(&p, protocol, mtu);
-        if (r < 0)
-                return r;
+        assert(p);
 
         h = DNS_PACKET_HEADER(p);
 
-        if (protocol == DNS_PROTOCOL_LLMNR)
+        switch(p->protocol) {
+        case DNS_PROTOCOL_LLMNR:
+                assert(!truncated);
+
                 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
                                                          0 /* opcode */,
                                                          0 /* c */,
@@ -86,7 +85,23 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
                                                          0 /* ad */,
                                                          0 /* cd */,
                                                          0 /* rcode */));
-        else
+                break;
+
+        case DNS_PROTOCOL_MDNS:
+                h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0         /* qr */,
+                                                         0         /* opcode */,
+                                                         0         /* aa */,
+                                                         truncated /* tc */,
+                                                         0         /* rd (ask for recursion) */,
+                                                         0         /* ra */,
+                                                         0         /* ad */,
+                                                         0         /* cd */,
+                                                         0         /* rcode */));
+                break;
+
+        default:
+                assert(!truncated);
+
                 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
                                                          0 /* opcode */,
                                                          0 /* aa */,
@@ -94,8 +109,25 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
                                                          1 /* rd (ask for recursion) */,
                                                          0 /* ra */,
                                                          0 /* ad */,
-                                                         0 /* cd */,
+                                                         dnssec_checking_disabled /* cd */,
                                                          0 /* rcode */));
+        }
+}
+
+int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
+        DnsPacket *p;
+        int r;
+
+        assert(ret);
+
+        r = dns_packet_new(&p, protocol, mtu);
+        if (r < 0)
+                return r;
+
+        /* Always set the TC bit to 0 initially.
+         * If there are multiple packets later, we'll update the bit shortly before sending.
+         */
+        dns_packet_set_flags(p, dnssec_checking_disabled, false);
 
         *ret = p;
         return 0;
@@ -106,6 +138,8 @@ DnsPacket *dns_packet_ref(DnsPacket *p) {
         if (!p)
                 return NULL;
 
+        assert(!p->on_stack);
+
         assert(p->n_ref > 0);
         p->n_ref++;
         return p;
@@ -118,13 +152,16 @@ static void dns_packet_free(DnsPacket *p) {
 
         dns_question_unref(p->question);
         dns_answer_unref(p->answer);
+        dns_resource_record_unref(p->opt);
 
         while ((s = hashmap_steal_first_key(p->names)))
                 free(s);
         hashmap_free(p->names);
 
         free(p->_data);
-        free(p);
+
+        if (!p->on_stack)
+                free(p);
 }
 
 DnsPacket *dns_packet_unref(DnsPacket *p) {
@@ -133,6 +170,8 @@ DnsPacket *dns_packet_unref(DnsPacket *p) {
 
         assert(p->n_ref > 0);
 
+        dns_packet_unref(p->more);
+
         if (p->n_ref == 1)
                 dns_packet_free(p);
         else
@@ -169,6 +208,7 @@ int dns_packet_validate_reply(DnsPacket *p) {
                 return -EBADMSG;
 
         switch (p->protocol) {
+
         case DNS_PROTOCOL_LLMNR:
                 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
                 if (DNS_PACKET_QDCOUNT(p) != 1)
@@ -176,6 +216,13 @@ int dns_packet_validate_reply(DnsPacket *p) {
 
                 break;
 
+        case DNS_PROTOCOL_MDNS:
+                /* RFC 6762, Section 18 */
+                if (DNS_PACKET_RCODE(p) != 0)
+                        return -EBADMSG;
+
+                break;
+
         default:
                 break;
         }
@@ -202,6 +249,7 @@ int dns_packet_validate_query(DnsPacket *p) {
                 return -EBADMSG;
 
         switch (p->protocol) {
+
         case DNS_PROTOCOL_LLMNR:
                 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
                 if (DNS_PACKET_QDCOUNT(p) != 1)
@@ -217,6 +265,18 @@ int dns_packet_validate_query(DnsPacket *p) {
 
                 break;
 
+        case DNS_PROTOCOL_MDNS:
+                /* RFC 6762, Section 18 */
+                if (DNS_PACKET_AA(p)    != 0 ||
+                    DNS_PACKET_RD(p)    != 0 ||
+                    DNS_PACKET_RA(p)    != 0 ||
+                    DNS_PACKET_AD(p)    != 0 ||
+                    DNS_PACKET_CD(p)    != 0 ||
+                    DNS_PACKET_RCODE(p) != 0)
+                        return -EBADMSG;
+
+                break;
+
         default:
                 break;
         }
@@ -267,7 +327,7 @@ static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start
         return 0;
 }
 
-static void dns_packet_truncate(DnsPacket *p, size_t sz) {
+void dns_packet_truncate(DnsPacket *p, size_t sz) {
         Iterator i;
         char *s;
         void *n;
@@ -349,43 +409,68 @@ int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
 }
 
 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
+        assert(p);
+        assert(s);
+
+        return dns_packet_append_raw_string(p, s, strlen(s), start);
+}
+
+int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
         void *d;
-        size_t l;
         int r;
 
         assert(p);
-        assert(s);
+        assert(s || size == 0);
 
-        l = strlen(s);
-        if (l > 255)
+        if (size > 255)
                 return -E2BIG;
 
-        r = dns_packet_extend(p, 1 + l, &d, start);
+        r = dns_packet_extend(p, 1 + size, &d, start);
         if (r < 0)
                 return r;
 
-        ((uint8_t*) d)[0] = (uint8_t) l;
-        memcpy(((uint8_t*) d) + 1, s, l);
+        ((uint8_t*) d)[0] = (uint8_t) size;
+
+        if (size > 0)
+                memcpy(((uint8_t*) d) + 1, s, size);
 
         return 0;
 }
 
-int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
-        void *w;
+int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
+        uint8_t *w;
         int r;
 
+        /* Append a label to a packet. Optionally, does this in DNSSEC
+         * canonical form, if this label is marked as a candidate for
+         * it, and the canonical form logic is enabled for the
+         * packet */
+
         assert(p);
         assert(d);
 
         if (l > DNS_LABEL_MAX)
                 return -E2BIG;
 
-        r = dns_packet_extend(p, 1 + l, &w, start);
+        r = dns_packet_extend(p, 1 + l, (void**) &w, start);
         if (r < 0)
                 return r;
 
-        ((uint8_t*) w)[0] = (uint8_t) l;
-        memcpy(((uint8_t*) w) + 1, d, l);
+        *(w++) = (uint8_t) l;
+
+        if (p->canonical_form && canonical_candidate) {
+                size_t i;
+
+                /* Generate in canonical form, as defined by DNSSEC
+                 * RFC 4034, Section 6.2, i.e. all lower-case. */
+
+                for (i = 0; i < l; i++)
+                        w[i] = (uint8_t) ascii_tolower(d[i]);
+        } else
+                /* Otherwise, just copy the string unaltered. This is
+                 * essential for DNS-SD, where the casing of labels
+                 * matters and needs to be retained. */
+                memcpy(w, d, l);
 
         return 0;
 }
@@ -394,6 +479,7 @@ int dns_packet_append_name(
                 DnsPacket *p,
                 const char *name,
                 bool allow_compression,
+                bool canonical_candidate,
                 size_t *start) {
 
         size_t saved_size;
@@ -407,11 +493,10 @@ int dns_packet_append_name(
 
         saved_size = p->size;
 
-        while (*name) {
-                _cleanup_free_ char *s = NULL;
+        while (!dns_name_is_root(name)) {
+                const char *z = name;
                 char label[DNS_LABEL_MAX];
                 size_t n = 0;
-                int k;
 
                 if (allow_compression)
                         n = PTR_TO_SIZE(hashmap_get(p->names, name));
@@ -427,32 +512,23 @@ int dns_packet_append_name(
                         }
                 }
 
-                s = strdup(name);
-                if (!s) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
                 r = dns_label_unescape(&name, label, sizeof(label));
                 if (r < 0)
                         goto fail;
 
-                if (p->protocol == DNS_PROTOCOL_DNS)
-                        k = dns_label_apply_idna(label, r, label, sizeof(label));
-                else
-                        k = dns_label_undo_idna(label, r, label, sizeof(label));
-                if (k < 0) {
-                        r = k;
-                        goto fail;
-                }
-                if (k > 0)
-                        r = k;
-
-                r = dns_packet_append_label(p, label, r, &n);
+                r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
                 if (r < 0)
                         goto fail;
 
                 if (allow_compression) {
+                        _cleanup_free_ char *s = NULL;
+
+                        s = strdup(z);
+                        if (!s) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
                         r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
                         if (r < 0)
                                 goto fail;
@@ -489,7 +565,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start)
 
         saved_size = p->size;
 
-        r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
+        r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL);
         if (r < 0)
                 goto fail;
 
@@ -511,7 +587,7 @@ fail:
         return r;
 }
 
-static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
+static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
         size_t saved_size;
         int r;
 
@@ -552,7 +628,6 @@ static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
         int r;
 
         assert(p);
-        assert(types);
 
         saved_size = p->size;
 
@@ -568,27 +643,143 @@ static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
                 }
 
                 window = n >> 8;
-
                 entry = n & 255;
 
                 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
         }
 
-        r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
+        if (bitmaps[entry / 8] != 0) {
+                r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
+                if (r < 0)
+                        goto fail;
+        }
+
+        if (start)
+                *start = saved_size;
+
+        return 0;
+fail:
+        dns_packet_truncate(p, saved_size);
+        return r;
+}
+
+/* Append the OPT pseudo-RR described in RFC6891 */
+int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
+        size_t saved_size;
+        int r;
+
+        assert(p);
+        /* we must never advertise supported packet size smaller than the legacy max */
+        assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
+
+        if (p->opt_start != (size_t) -1)
+                return -EBUSY;
+
+        assert(p->opt_size == (size_t) -1);
+
+        saved_size = p->size;
+
+        /* empty name */
+        r = dns_packet_append_uint8(p, 0, NULL);
+        if (r < 0)
+                return r;
+
+        /* type */
+        r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
+        if (r < 0)
+                goto fail;
+
+        /* maximum udp packet that can be received */
+        r = dns_packet_append_uint16(p, max_udp_size, NULL);
+        if (r < 0)
+                goto fail;
+
+        /* extended RCODE and VERSION */
+        r = dns_packet_append_uint16(p, 0, NULL);
+        if (r < 0)
+                goto fail;
+
+        /* flags: DNSSEC OK (DO), see RFC3225 */
+        r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
         if (r < 0)
                 goto fail;
 
+        /* RDLENGTH */
+
+        if (edns0_do) {
+                /* If DO is on, also append RFC6975 Algorithm data */
+
+                static const uint8_t rfc6975[] = {
+
+                        0, 5, /* OPTION_CODE: DAU */
+                        0, 6, /* LIST_LENGTH */
+                        DNSSEC_ALGORITHM_RSASHA1,
+                        DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
+                        DNSSEC_ALGORITHM_RSASHA256,
+                        DNSSEC_ALGORITHM_RSASHA512,
+                        DNSSEC_ALGORITHM_ECDSAP256SHA256,
+                        DNSSEC_ALGORITHM_ECDSAP384SHA384,
+
+                        0, 6, /* OPTION_CODE: DHU */
+                        0, 3, /* LIST_LENGTH */
+                        DNSSEC_DIGEST_SHA1,
+                        DNSSEC_DIGEST_SHA256,
+                        DNSSEC_DIGEST_SHA384,
+
+                        0, 7, /* OPTION_CODE: N3U */
+                        0, 1, /* LIST_LENGTH */
+                        NSEC3_ALGORITHM_SHA1,
+                };
+
+                r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL);
+        } else
+                r = dns_packet_append_uint16(p, 0, NULL);
+
+        if (r < 0)
+                goto fail;
+
+        DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
+
+        p->opt_start = saved_size;
+        p->opt_size = p->size - saved_size;
+
         if (start)
                 *start = saved_size;
 
         return 0;
+
 fail:
         dns_packet_truncate(p, saved_size);
         return r;
 }
 
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
-        size_t saved_size, rdlength_offset, end, rdlength;
+int dns_packet_truncate_opt(DnsPacket *p) {
+        assert(p);
+
+        if (p->opt_start == (size_t) -1) {
+                assert(p->opt_size == (size_t) -1);
+                return 0;
+        }
+
+        assert(p->opt_size != (size_t) -1);
+        assert(DNS_PACKET_ARCOUNT(p) > 0);
+
+        if (p->opt_start + p->opt_size != p->size)
+                return -EBUSY;
+
+        dns_packet_truncate(p, p->opt_start);
+        DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
+        p->opt_start = p->opt_size = (size_t) -1;
+
+        return 1;
+}
+
+int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
+        size_t saved_size, rdlength_offset, end, rdlength, rds;
         int r;
 
         assert(p);
@@ -609,6 +800,8 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
         if (r < 0)
                 goto fail;
 
+        rds = p->size - saved_size;
+
         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
 
         case DNS_TYPE_SRV:
@@ -624,14 +817,14 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_append_name(p, rr->srv.name, true, NULL);
+                r = dns_packet_append_name(p, rr->srv.name, true, false, NULL);
                 break;
 
         case DNS_TYPE_PTR:
         case DNS_TYPE_NS:
         case DNS_TYPE_CNAME:
         case DNS_TYPE_DNAME:
-                r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
+                r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
                 break;
 
         case DNS_TYPE_HINFO:
@@ -643,19 +836,20 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 break;
 
         case DNS_TYPE_SPF: /* exactly the same as TXT */
-        case DNS_TYPE_TXT: {
-                char **s;
+        case DNS_TYPE_TXT:
 
-                if (strv_isempty(rr->txt.strings)) {
+                if (!rr->txt.items) {
                         /* RFC 6763, section 6.1 suggests to generate
                          * single empty string for an empty array. */
 
-                        r = dns_packet_append_string(p, "", NULL);
+                        r = dns_packet_append_raw_string(p, NULL, 0, NULL);
                         if (r < 0)
                                 goto fail;
                 } else {
-                        STRV_FOREACH(s, rr->txt.strings) {
-                                r = dns_packet_append_string(p, *s, NULL);
+                        DnsTxtItem *i;
+
+                        LIST_FOREACH(items, i, rr->txt.items) {
+                                r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
                                 if (r < 0)
                                         goto fail;
                         }
@@ -663,7 +857,6 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
 
                 r = 0;
                 break;
-        }
 
         case DNS_TYPE_A:
                 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
@@ -674,11 +867,11 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 break;
 
         case DNS_TYPE_SOA:
-                r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
+                r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
+                r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
                 if (r < 0)
                         goto fail;
 
@@ -706,7 +899,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
+                r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
                 break;
 
         case DNS_TYPE_LOC:
@@ -766,11 +959,11 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 break;
 
         case DNS_TYPE_DNSKEY:
-                r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
+                r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_append_uint8(p, 3u, NULL);
+                r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
                 if (r < 0)
                         goto fail;
 
@@ -810,7 +1003,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
+                r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
                 if (r < 0)
                         goto fail;
 
@@ -818,7 +1011,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 break;
 
         case DNS_TYPE_NSEC:
-                r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
+                r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
                 if (r < 0)
                         goto fail;
 
@@ -827,6 +1020,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                         goto fail;
 
                 break;
+
         case DNS_TYPE_NSEC3:
                 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
                 if (r < 0)
@@ -861,10 +1055,29 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                         goto fail;
 
                 break;
+
+        case DNS_TYPE_TLSA:
+                r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
+                break;
+
+        case DNS_TYPE_OPT:
+        case DNS_TYPE_OPENPGPKEY:
         case _DNS_TYPE_INVALID: /* unparseable */
         default:
 
-                r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
+                r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
                 break;
         }
         if (r < 0)
@@ -873,7 +1086,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
         /* Let's calculate the actual data size and update the field */
         rdlength = p->size - rdlength_offset - sizeof(uint16_t);
         if (rdlength > 0xFFFF) {
-                r = ENOSPC;
+                r = -ENOSPC;
                 goto fail;
         }
 
@@ -887,6 +1100,9 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
         if (start)
                 *start = saved_size;
 
+        if (rdata_start)
+                *rdata_start = rds;
+
         return 0;
 
 fail:
@@ -894,7 +1110,6 @@ fail:
         return r;
 }
 
-
 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
         assert(p);
 
@@ -1062,6 +1277,35 @@ fail:
         return r;
 }
 
+int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
+        size_t saved_rindex;
+        uint8_t c;
+        int r;
+
+        assert(p);
+
+        saved_rindex = p->rindex;
+
+        r = dns_packet_read_uint8(p, &c, NULL);
+        if (r < 0)
+                goto fail;
+
+        r = dns_packet_read(p, c, ret, NULL);
+        if (r < 0)
+                goto fail;
+
+        if (size)
+                *size = c;
+        if (start)
+                *start = saved_rindex;
+
+        return 0;
+
+fail:
+        dns_packet_rewind(p, saved_rindex);
+        return r;
+}
+
 int dns_packet_read_name(
                 DnsPacket *p,
                 char **_ret,
@@ -1094,7 +1338,6 @@ int dns_packet_read_name(
                         /* End of name */
                         break;
                 else if (c <= 63) {
-                        _cleanup_free_ char *t = NULL;
                         const char *label;
 
                         /* Literal label */
@@ -1102,21 +1345,20 @@ int dns_packet_read_name(
                         if (r < 0)
                                 goto fail;
 
-                        r = dns_label_escape(label, c, &t);
-                        if (r < 0)
-                                goto fail;
-
-                        if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
+                        if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
                                 r = -ENOMEM;
                                 goto fail;
                         }
 
-                        if (!first)
-                                ret[n++] = '.';
-                        else
+                        if (first)
                                 first = false;
+                        else
+                                ret[n++] = '.';
+
+                        r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+                        if (r < 0)
+                                goto fail;
 
-                        memcpy(ret + n, t, r);
                         n += r;
                         continue;
                 } else if (allow_compression && (c & 0xc0) == 0xc0) {
@@ -1277,8 +1519,9 @@ fail:
         return r;
 }
 
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
+int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
         _cleanup_free_ char *name = NULL;
+        bool cache_flush = false;
         uint16_t class, type;
         DnsResourceKey *key;
         size_t saved_rindex;
@@ -1301,6 +1544,15 @@ int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
         if (r < 0)
                 goto fail;
 
+        if (p->protocol == DNS_PROTOCOL_MDNS) {
+                /* See RFC6762, Section 10.2 */
+
+                if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
+                        class &= ~MDNS_RR_CACHE_FLUSH;
+                        cache_flush = true;
+                }
+        }
+
         key = dns_resource_key_new_consume(class, type, name);
         if (!key) {
                 r = -ENOMEM;
@@ -1310,6 +1562,8 @@ int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
         name = NULL;
         *ret = key;
 
+        if (ret_cache_flush)
+                *ret_cache_flush = cache_flush;
         if (start)
                 *start = saved_rindex;
 
@@ -1325,22 +1579,12 @@ static bool loc_size_ok(uint8_t size) {
         return m <= 9 && e <= 9 && (m > 0 || e == 0);
 }
 
-static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
-        assert(rr);
-
-        if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
-                return -EBADMSG;
-
-        rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
-        rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
-        return 0;
-}
-
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
+int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
         size_t saved_rindex, offset;
         uint16_t rdlength;
+        bool cache_flush;
         int r;
 
         assert(p);
@@ -1348,12 +1592,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
 
         saved_rindex = p->rindex;
 
-        r = dns_packet_read_key(p, &key, NULL);
+        r = dns_packet_read_key(p, &key, &cache_flush, NULL);
         if (r < 0)
                 goto fail;
 
-        if (key->class == DNS_CLASS_ANY ||
-            key->type == DNS_TYPE_ANY) {
+        if (!dns_class_is_valid_rr(key->class)||
+            !dns_type_is_valid_rr(key->type)) {
                 r = -EBADMSG;
                 goto fail;
         }
@@ -1368,6 +1612,11 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
         if (r < 0)
                 goto fail;
 
+        /* RFC 2181, Section 8, suggests to
+         * treat a TTL with the MSB set as a zero TTL. */
+        if (rr->ttl & UINT32_C(0x80000000))
+                rr->ttl = 0;
+
         r = dns_packet_read_uint16(p, &rdlength, NULL);
         if (r < 0)
                 goto fail;
@@ -1412,24 +1661,37 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
         case DNS_TYPE_SPF: /* exactly the same as TXT */
         case DNS_TYPE_TXT:
                 if (rdlength <= 0) {
+                        DnsTxtItem *i;
                         /* RFC 6763, section 6.1 suggests to treat
                          * empty TXT RRs as equivalent to a TXT record
                          * with a single empty string. */
 
-                        r = strv_extend(&rr->txt.strings, "");
-                        if (r < 0)
-                                goto fail;
+                        i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
+                        if (!i)
+                                return -ENOMEM;
+
+                        rr->txt.items = i;
                 } else {
+                        DnsTxtItem *last = NULL;
+
                         while (p->rindex < offset + rdlength) {
-                                char *s;
+                                DnsTxtItem *i;
+                                const void *data;
+                                size_t sz;
 
-                                r = dns_packet_read_string(p, &s, NULL);
+                                r = dns_packet_read_raw_string(p, &data, &sz, NULL);
                                 if (r < 0)
-                                        goto fail;
+                                        return r;
 
-                                r = strv_consume(&rr->txt.strings, s);
-                                if (r < 0)
-                                        goto fail;
+                                i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
+                                if (!i)
+                                        return -ENOMEM;
+
+                                memcpy(i->data, data, sz);
+                                i->length = sz;
+
+                                LIST_INSERT_AFTER(items, rr->txt.items, last, i);
+                                last = i;
                         }
                 }
 
@@ -1565,6 +1827,7 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 }
 
                 break;
+
         case DNS_TYPE_SSHFP:
                 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
                 if (r < 0)
@@ -1587,28 +1850,15 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
 
                 break;
 
-        case DNS_TYPE_DNSKEY: {
-                uint16_t flags;
-                uint8_t proto;
-
-                r = dns_packet_read_uint16(p, &flags, NULL);
-                if (r < 0)
-                        goto fail;
-
-                r = dnskey_parse_flags(rr, flags);
+        case DNS_TYPE_DNSKEY:
+                r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
                 if (r < 0)
                         goto fail;
 
-                r = dns_packet_read_uint8(p, &proto, NULL);
+                r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
                 if (r < 0)
                         goto fail;
 
-                /* protocol is required to be always 3 */
-                if (proto != 3) {
-                        r = -EBADMSG;
-                        goto fail;
-                }
-
                 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
                 if (r < 0)
                         goto fail;
@@ -1625,7 +1875,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 }
 
                 break;
-        }
 
         case DNS_TYPE_RRSIG:
                 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
@@ -1673,8 +1922,16 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
 
                 break;
 
-        case DNS_TYPE_NSEC:
-                r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
+        case DNS_TYPE_NSEC: {
+
+                /*
+                 * RFC6762, section 18.14 explictly states mDNS should use name compression.
+                 * This contradicts RFC3845, section 2.1.1
+                 */
+
+                bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
+
+                r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
                 if (r < 0)
                         goto fail;
 
@@ -1682,15 +1939,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means
-                   something went wrong */
-                if (bitmap_isclear(rr->nsec.types)) {
-                        r = -EBADMSG;
-                        goto fail;
-                }
+                /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
+                 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
+                 * without the NSEC bit set. */
 
                 break;
-
+        }
         case DNS_TYPE_NSEC3: {
                 uint8_t size;
 
@@ -1736,9 +1990,37 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
 
                 break;
         }
+
+        case DNS_TYPE_TLSA:
+                r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_read_memdup(p, rdlength - 3,
+                                           &rr->tlsa.data, &rr->tlsa.data_size,
+                                           NULL);
+                if (rr->tlsa.data_size <= 0) {
+                        /* the accepted size depends on the algorithm, but for now
+                           just ensure that the value is greater than zero */
+                        r = -EBADMSG;
+                        goto fail;
+                }
+
+                break;
+
+        case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
+        case DNS_TYPE_OPENPGPKEY:
         default:
         unparseable:
-                r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
+                r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
                 if (r < 0)
                         goto fail;
                 break;
@@ -1753,6 +2035,8 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
         *ret = rr;
         rr = NULL;
 
+        if (ret_cache_flush)
+                *ret_cache_flush = cache_flush;
         if (start)
                 *start = saved_rindex;
 
@@ -1762,6 +2046,48 @@ fail:
         return r;
 }
 
+static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
+        const uint8_t* p;
+        bool found_dau_dhu_n3u = false;
+        size_t l;
+
+        /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
+         * a reply). */
+
+        assert(rr);
+        assert(rr->key->type == DNS_TYPE_OPT);
+
+        /* Check that the version is 0 */
+        if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0)
+                return false;
+
+        p = rr->opt.data;
+        l = rr->opt.data_size;
+        while (l > 0) {
+                uint16_t option_code, option_length;
+
+                /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */
+                if (l < 4U)
+                        return false;
+
+                option_code = unaligned_read_be16(p);
+                option_length = unaligned_read_be16(p + 2);
+
+                if (l < option_length + 4U)
+                        return false;
+
+                /* RFC 6975 DAU, DHU or N3U fields found. */
+                if (IN_SET(option_code, 5, 6, 7))
+                        found_dau_dhu_n3u = true;
+
+                p += option_length + 4U;
+                l -= option_length + 4U;
+        }
+
+        *rfc6975 = found_dau_dhu_n3u;
+        return true;
+}
+
 int dns_packet_extract(DnsPacket *p) {
         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
@@ -1785,11 +2111,22 @@ int dns_packet_extract(DnsPacket *p) {
 
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+                        bool cache_flush;
 
-                        r = dns_packet_read_key(p, &key, NULL);
+                        r = dns_packet_read_key(p, &key, &cache_flush, NULL);
                         if (r < 0)
                                 goto finish;
 
+                        if (cache_flush) {
+                                r = -EBADMSG;
+                                goto finish;
+                        }
+
+                        if (!dns_type_is_valid_query(key->type)) {
+                                r = -EBADMSG;
+                                goto finish;
+                        }
+
                         r = dns_question_add(question, key);
                         if (r < 0)
                                 goto finish;
@@ -1798,6 +2135,9 @@ int dns_packet_extract(DnsPacket *p) {
 
         n = DNS_PACKET_RRCOUNT(p);
         if (n > 0) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL;
+                bool bad_opt = false;
+
                 answer = dns_answer_new(n);
                 if (!answer) {
                         r = -ENOMEM;
@@ -1806,15 +2146,84 @@ int dns_packet_extract(DnsPacket *p) {
 
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+                        bool cache_flush;
 
-                        r = dns_packet_read_rr(p, &rr, NULL);
+                        r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
                         if (r < 0)
                                 goto finish;
 
-                        r = dns_answer_add(answer, rr, p->ifindex);
-                        if (r < 0)
-                                goto finish;
+                        /* Try to reduce memory usage a bit */
+                        if (previous)
+                                dns_resource_key_reduce(&rr->key, &previous->key);
+
+                        if (rr->key->type == DNS_TYPE_OPT) {
+                                bool has_rfc6975;
+
+                                if (p->opt || bad_opt) {
+                                        /* Multiple OPT RRs? if so, let's ignore all, because there's something wrong
+                                         * with the server, and if one is valid we wouldn't know which one. */
+                                        log_debug("Multiple OPT RRs detected, ignoring all.");
+                                        bad_opt = true;
+                                        continue;
+                                }
+
+                                if (!dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key))) {
+                                        /* If the OPT RR is not owned by the root domain, then it is bad, let's ignore
+                                         * it. */
+                                        log_debug("OPT RR is not owned by root domain, ignoring.");
+                                        bad_opt = true;
+                                        continue;
+                                }
+
+                                if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
+                                        /* OPT RR is in the wrong section? Some Belkin routers do this. This is a hint
+                                         * the EDNS implementation is borked, like the Belkin one is, hence ignore
+                                         * it. */
+                                        log_debug("OPT RR in wrong section, ignoring.");
+                                        bad_opt = true;
+                                        continue;
+                                }
+
+                                if (!opt_is_good(rr, &has_rfc6975)) {
+                                        log_debug("Malformed OPT RR, ignoring.");
+                                        bad_opt = true;
+                                        continue;
+                                }
+
+                                if (has_rfc6975) {
+                                        /* If the OPT RR contains RFC6975 algorithm data, then this is indication that
+                                         * the server just copied the OPT it got from us (which contained that data)
+                                         * back into the reply. If so, then it doesn't properly support EDNS, as
+                                         * RFC6975 makes it very clear that the algorithm data should only be contained
+                                         * in questions, never in replies. Crappy Belkin routers copy the OPT data for
+                                         * example, hence let's detect this so that we downgrade early. */
+                                        log_debug("OPT RR contained RFC6975 data, ignoring.");
+                                        bad_opt = true;
+                                        continue;
+                                }
+
+                                p->opt = dns_resource_record_ref(rr);
+                        } else {
+
+                                /* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be
+                                 * cached. Hence mark only those RRs as cacheable by default, but not the ones from the
+                                 * Additional or Authority sections. */
+
+                                r = dns_answer_add(answer, rr, p->ifindex,
+                                                   (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
+                                                   (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0));
+                                if (r < 0)
+                                        goto finish;
+                        }
+
+                        /* Remember this RR, so that we potentically can merge it's ->key object with the next RR. Note
+                         * that we only do this if we actually decided to keep the RR around. */
+                        dns_resource_record_unref(previous);
+                        previous = dns_resource_record_ref(rr);
                 }
+
+                if (bad_opt)
+                        p->opt = dns_resource_record_unref(p->opt);
         }
 
         p->question = question;
@@ -1832,6 +2241,30 @@ finish:
         return r;
 }
 
+int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
+        int r;
+
+        assert(p);
+        assert(key);
+
+        /* Checks if the specified packet is a reply for the specified
+         * key and the specified key is the only one in the question
+         * section. */
+
+        if (DNS_PACKET_QR(p) != 1)
+                return 0;
+
+        /* Let's unpack the packet, if that hasn't happened yet. */
+        r = dns_packet_extract(p);
+        if (r < 0)
+                return r;
+
+        if (p->question->n_keys != 1)
+                return 0;
+
+        return dns_resource_key_equal(p->question->keys[0], key);
+}
+
 static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
         [DNS_RCODE_SUCCESS] = "SUCCESS",
         [DNS_RCODE_FORMERR] = "FORMERR",
@@ -1860,17 +2293,3 @@ static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
         [DNS_PROTOCOL_LLMNR] = "llmnr",
 };
 DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
-
-static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
-        [DNSSEC_ALGORITHM_RSAMD5]             = "RSAMD5",
-        [DNSSEC_ALGORITHM_DH]                 = "DH",
-        [DNSSEC_ALGORITHM_DSA]                = "DSA",
-        [DNSSEC_ALGORITHM_ECC]                = "ECC",
-        [DNSSEC_ALGORITHM_RSASHA1]            = "RSASHA1",
-        [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1]     = "DSA-NSEC3-SHA1",
-        [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
-        [DNSSEC_ALGORITHM_INDIRECT]           = "INDIRECT",
-        [DNSSEC_ALGORITHM_PRIVATEDNS]         = "PRIVATEDNS",
-        [DNSSEC_ALGORITHM_PRIVATEOID]         = "PRIVATEOID",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
index fbbabaf232d7d47e767866bbf9b35317c8c8ebaf..0bf34d270ce909798a9e1f1ed064a9173d636f73 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
 
-#include <netinet/udp.h>
 #include <netinet/ip.h>
+#include <netinet/udp.h>
 
-#include "macro.h"
-#include "sparse-endian.h"
 #include "hashmap.h"
 #include "in-addr-util.h"
+#include "macro.h"
+#include "sparse-endian.h"
 
 typedef struct DnsPacketHeader DnsPacketHeader;
 typedef struct DnsPacket DnsPacket;
 
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
 #include "resolved-def.h"
+#include "resolved-dns-answer.h"
+#include "resolved-dns-question.h"
+#include "resolved-dns-rr.h"
 
 typedef enum DnsProtocol {
         DNS_PROTOCOL_DNS,
@@ -65,6 +63,9 @@ struct DnsPacketHeader {
 /* RFC 1035 say 512 is the maximum, for classic unicast DNS */
 #define DNS_PACKET_UNICAST_SIZE_MAX 512
 
+/* 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
 
 struct DnsPacket {
@@ -73,10 +74,12 @@ struct DnsPacket {
         size_t size, allocated, rindex;
         void *_data; /* don't access directly, use DNS_PACKET_DATA()! */
         Hashmap *names; /* For name compression */
+        size_t opt_start, opt_size;
 
         /* Parsed data */
         DnsQuestion *question;
         DnsAnswer *answer;
+        DnsResourceRecord *opt;
 
         /* Packet reception metadata */
         int ifindex;
@@ -85,8 +88,13 @@ struct DnsPacket {
         uint16_t sender_port, destination_port;
         uint32_t ttl;
 
-        bool extracted;
-        bool refuse_compression;
+        /* For support of truncated packets */
+        DnsPacket *more;
+
+        bool on_stack:1;
+        bool extracted:1;
+        bool refuse_compression:1;
+        bool canonical_form:1;
 };
 
 static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
@@ -109,7 +117,17 @@ static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
 #define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1)
 #define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1)
 #define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1)
-#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
+
+static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) {
+        uint16_t rcode;
+
+        if (p->opt)
+                rcode = (uint16_t) (p->opt->ttl >> 24);
+        else
+                rcode = 0;
+
+        return rcode | (be16toh(DNS_PACKET_HEADER(p)->flags) & 15);
+}
 
 /* LLMNR defines some bits differently */
 #define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p)
@@ -139,7 +157,9 @@ static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
 }
 
 int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu);
+int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled);
+
+void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
 
 DnsPacket *dns_packet_ref(DnsPacket *p);
 DnsPacket *dns_packet_unref(DnsPacket *p);
@@ -150,16 +170,22 @@ int dns_packet_validate(DnsPacket *p);
 int dns_packet_validate_reply(DnsPacket *p);
 int dns_packet_validate_query(DnsPacket *p);
 
+int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key);
+
 int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start);
 int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start);
 int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start);
 int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start);
 int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start);
-int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, size_t *start);
-int dns_packet_append_name(DnsPacket *p, const char *name,
-                           bool allow_compression, size_t *start);
+int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start);
+int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, bool canonical_candidate, size_t *start);
+int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start);
 int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start);
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start);
+int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start);
+int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start);
+
+void dns_packet_truncate(DnsPacket *p, size_t sz);
+int dns_packet_truncate_opt(DnsPacket *p);
 
 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start);
 int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start);
@@ -167,16 +193,25 @@ int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start);
 int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start);
 int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start);
 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start);
-int dns_packet_read_name(DnsPacket *p, char **ret,
-                         bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start);
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start);
+int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start);
+int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start);
+int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start);
+int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start);
 
 void dns_packet_rewind(DnsPacket *p, size_t idx);
 
 int dns_packet_skip_question(DnsPacket *p);
 int dns_packet_extract(DnsPacket *p);
 
+static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket *p) {
+        /* Never cache data originating from localhost, under the
+         * assumption, that it's coming from a locally DNS forwarder
+         * or server, that is caching on its own. */
+
+        return in_addr_is_localhost(p->family, &p->sender) == 0;
+}
+
+/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
 enum {
         DNS_RCODE_SUCCESS = 0,
         DNS_RCODE_FORMERR = 1,
@@ -209,42 +244,25 @@ DnsProtocol dns_protocol_from_string(const char *s) _pure_;
 #define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) })
 #define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } })
 
-#define DNSKEY_FLAG_ZONE_KEY (1u << 8)
-#define DNSKEY_FLAG_SEP      (1u << 0)
+#define MDNS_MULTICAST_IPV4_ADDRESS  ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) })
+#define MDNS_MULTICAST_IPV6_ADDRESS  ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } })
 
-static inline uint16_t dnskey_to_flags(const DnsResourceRecord *rr) {
-        return (rr->dnskey.zone_key_flag * DNSKEY_FLAG_ZONE_KEY |
-                rr->dnskey.sep_flag * DNSKEY_FLAG_SEP);
-}
+static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
+        uint64_t f;
 
-/* http://tools.ietf.org/html/rfc4034#appendix-A.1 */
-enum {
-        DNSSEC_ALGORITHM_RSAMD5 = 1,
-        DNSSEC_ALGORITHM_DH,
-        DNSSEC_ALGORITHM_DSA,
-        DNSSEC_ALGORITHM_ECC,
-        DNSSEC_ALGORITHM_RSASHA1,
-        DNSSEC_ALGORITHM_DSA_NSEC3_SHA1,
-        DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
-        DNSSEC_ALGORITHM_INDIRECT = 252,
-        DNSSEC_ALGORITHM_PRIVATEDNS,
-        DNSSEC_ALGORITHM_PRIVATEOID,
-        _DNSSEC_ALGORITHM_MAX_DEFINED
-};
+        /* Converts a protocol + family into a flags field as used in queries and responses */
 
-const char* dnssec_algorithm_to_string(int i) _const_;
-int dnssec_algorithm_from_string(const char *s) _pure_;
-
-static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family) {
-
-        /* Converts a protocol + family into a flags field as used in queries */
+        f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
 
         switch (protocol) {
         case DNS_PROTOCOL_DNS:
-                return SD_RESOLVED_DNS;
+                return f|SD_RESOLVED_DNS;
 
         case DNS_PROTOCOL_LLMNR:
-                return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4;
+                return f|(family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4);
+
+        case DNS_PROTOCOL_MDNS:
+                return family == AF_INET6 ? SD_RESOLVED_MDNS_IPV6 : SD_RESOLVED_MDNS_IPV4;
 
         default:
                 break;
index f7cb84e2a62fed26af548d5b06f2d41ad7405c32..a378b2b7f76ba26689ada494f9168bc269e5144e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include "alloc-util.h"
 #include "dns-domain.h"
+#include "dns-type.h"
 #include "hostname-util.h"
 #include "local-addresses.h"
 #include "resolved-dns-query.h"
+#include "resolved-dns-synthesize.h"
+#include "resolved-etc-hosts.h"
+#include "string-util.h"
 
 /* How long to wait for the query in total */
 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
 
 #define CNAME_MAX 8
 #define QUERIES_MAX 2048
+#define AUXILIARY_QUERIES_MAX 64
 
-static void dns_query_stop(DnsQuery *q) {
-        DnsTransaction *t;
+static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
+        DnsQueryCandidate *c;
 
+        assert(ret);
         assert(q);
+        assert(s);
 
-        q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
+        c = new0(DnsQueryCandidate, 1);
+        if (!c)
+                return -ENOMEM;
 
-        while ((t = set_steal_first(q->transactions))) {
-                set_remove(t->queries, q);
-                dns_transaction_gc(t);
-        }
-}
+        c->query = q;
+        c->scope = s;
 
-DnsQuery *dns_query_free(DnsQuery *q) {
-        if (!q)
-                return NULL;
+        LIST_PREPEND(candidates_by_query, q->candidates, c);
+        LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
 
-        dns_query_stop(q);
-        set_free(q->transactions);
+        *ret = c;
+        return 0;
+}
 
-        dns_question_unref(q->question);
-        dns_answer_unref(q->answer);
+static void dns_query_candidate_stop(DnsQueryCandidate *c) {
+        DnsTransaction *t;
 
-        sd_bus_message_unref(q->request);
-        sd_bus_track_unref(q->bus_track);
+        assert(c);
 
-        if (q->manager) {
-                LIST_REMOVE(queries, q->manager->dns_queries, q);
-                q->manager->n_dns_queries--;
+        while ((t = set_steal_first(c->transactions))) {
+                set_remove(t->notify_query_candidates, c);
+                dns_transaction_gc(t);
         }
-
-        free(q);
-
-        return NULL;
 }
 
-int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
-        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
-        unsigned i;
-        int r;
-
-        assert(m);
-        assert(question);
+DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
 
-        r = dns_question_is_valid(question);
-        if (r < 0)
-                return r;
+        if (!c)
+                return NULL;
 
-        if (m->n_dns_queries >= QUERIES_MAX)
-                return -EBUSY;
+        dns_query_candidate_stop(c);
 
-        q = new0(DnsQuery, 1);
-        if (!q)
-                return -ENOMEM;
+        set_free(c->transactions);
+        dns_search_domain_unref(c->search_domain);
 
-        q->question = dns_question_ref(question);
-        q->ifindex = ifindex;
-        q->flags = flags;
+        if (c->query)
+                LIST_REMOVE(candidates_by_query, c->query->candidates, c);
 
-        for (i = 0; i < question->n_keys; i++) {
-                _cleanup_free_ char *p;
+        if (c->scope)
+                LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
 
-                r = dns_resource_key_to_string(question->keys[i], &p);
-                if (r < 0)
-                        return r;
+        free(c);
 
-                log_debug("Looking up RR for %s", p);
-        }
-
-        LIST_PREPEND(queries, m->dns_queries, q);
-        m->n_dns_queries++;
-        q->manager = m;
-
-        if (ret)
-                *ret = q;
-        q = NULL;
-
-        return 0;
+        return NULL;
 }
 
-static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
-        assert(q);
-        assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
-        assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
+static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
+        DnsSearchDomain *next = NULL;
 
-        /* Note that this call might invalidate the query. Callers
-         * should hence not attempt to access the query or transaction
-         * after calling this function. */
+        assert(c);
 
-        q->state = state;
+        if (c->search_domain && c->search_domain->linked)
+                next = c->search_domain->domains_next;
+        else
+                next = dns_scope_get_search_domains(c->scope);
 
-        dns_query_stop(q);
-        if (q->complete)
-                q->complete(q);
-}
+        for (;;) {
+                if (!next) /* We hit the end of the list */
+                        return 0;
 
-static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
-        DnsQuery *q = userdata;
+                if (!next->route_only)
+                        break;
 
-        assert(s);
-        assert(q);
+                /* Skip over route-only domains */
+                next = next->domains_next;
+        }
 
-        dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
-        return 0;
+        dns_search_domain_unref(c->search_domain);
+        c->search_domain = dns_search_domain_ref(next);
+
+        return 1;
 }
 
-static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
+static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
         DnsTransaction *t;
         int r;
 
-        assert(q);
-        assert(s);
+        assert(c);
         assert(key);
 
-        r = set_ensure_allocated(&q->transactions, NULL);
-        if (r < 0)
-                return r;
-
-        t = dns_scope_find_transaction(s, key, true);
+        t = dns_scope_find_transaction(c->scope, key, true);
         if (!t) {
-                r = dns_transaction_new(&t, s, key);
+                r = dns_transaction_new(&t, c->scope, key);
                 if (r < 0)
                         return r;
+        } else {
+                if (set_contains(c->transactions, t))
+                        return 0;
         }
 
-        r = set_ensure_allocated(&t->queries, NULL);
+        r = set_ensure_allocated(&c->transactions, NULL);
+        if (r < 0)
+                goto gc;
+
+        r = set_ensure_allocated(&t->notify_query_candidates, NULL);
         if (r < 0)
                 goto gc;
 
-        r = set_put(t->queries, q);
+        r = set_put(t->notify_query_candidates, c);
         if (r < 0)
                 goto gc;
 
-        r = set_put(q->transactions, t);
+        r = set_put(c->transactions, t);
         if (r < 0) {
-                set_remove(t->queries, q);
+                (void) set_remove(t->notify_query_candidates, c);
                 goto gc;
         }
 
-        return 0;
+        return 1;
 
 gc:
         dns_transaction_gc(t);
         return r;
 }
 
-static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
-        unsigned i;
+static int dns_query_candidate_go(DnsQueryCandidate *c) {
+        DnsTransaction *t;
+        Iterator i;
         int r;
+        unsigned n = 0;
 
-        assert(q);
-        assert(s);
+        assert(c);
 
-        /* Create one transaction per question key */
+        /* Start the transactions that are not started yet */
+        SET_FOREACH(t, c->transactions, i) {
+                if (t->state != DNS_TRANSACTION_NULL)
+                        continue;
 
-        for (i = 0; i < q->question->n_keys; i++) {
-                r = dns_query_add_transaction(q, s, q->question->keys[i]);
+                r = dns_transaction_go(t);
                 if (r < 0)
                         return r;
+
+                n++;
         }
 
+        /* If there was nothing to start, then let's proceed immediately */
+        if (n == 0)
+                dns_query_candidate_notify(c);
+
         return 0;
 }
 
-static int SYNTHESIZE_IFINDEX(int ifindex) {
+static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
+        DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
+        DnsTransaction *t;
+        Iterator i;
 
-        /* When the caller asked for resolving on a specific
-         * interface, we synthesize the answer for that
-         * interface. However, if nothing specific was claimed and we
-         * only return localhost RRs, we synthesize the answer for
-         * localhost. */
+        assert(c);
 
-        if (ifindex > 0)
-                return ifindex;
+        if (c->error_code != 0)
+                return DNS_TRANSACTION_ERRNO;
 
-        return LOOPBACK_IFINDEX;
-}
+        SET_FOREACH(t, c->transactions, i) {
+
+                switch (t->state) {
+
+                case DNS_TRANSACTION_NULL:
+                        /* If there's a NULL transaction pending, then
+                         * this means not all transactions where
+                         * started yet, and we were called from within
+                         * the stackframe that is supposed to start
+                         * remaining transactions. In this case,
+                         * simply claim the candidate is pending. */
 
-static int SYNTHESIZE_FAMILY(uint64_t flags) {
+                case DNS_TRANSACTION_PENDING:
+                case DNS_TRANSACTION_VALIDATING:
+                        /* If there's one transaction currently in
+                         * VALIDATING state, then this means there's
+                         * also one in PENDING state, hence we can
+                         * return PENDING immediately. */
+                        return DNS_TRANSACTION_PENDING;
+
+                case DNS_TRANSACTION_SUCCESS:
+                        state = t->state;
+                        break;
 
-        /* Picks an address family depending on set flags. This is
-         * purely for synthesized answers, where the family we return
-         * for the reply should match what was requested in the
-         * question, even though we are synthesizing the answer
-         * here. */
+                default:
+                        if (state != DNS_TRANSACTION_SUCCESS)
+                                state = t->state;
 
-        if (!(flags & SD_RESOLVED_DNS)) {
-                if (flags & SD_RESOLVED_LLMNR_IPV4)
-                        return AF_INET;
-                if (flags & SD_RESOLVED_LLMNR_IPV6)
-                        return AF_INET6;
+                        break;
+                }
         }
 
-        return AF_UNSPEC;
+        return state;
 }
 
-static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
+static bool dns_query_candidate_is_routable(DnsQueryCandidate *c, uint16_t type) {
+        int family;
+
+        assert(c);
+
+        /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of
+         * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR,
+         * or a routable IPv6 address if we query an AAAA RR. */
 
-        /* Similar as SYNTHESIZE_FAMILY() but does this for the
-         * protocol. If resolving via DNS was requested, we claim it
-         * was DNS. Similar, if nothing specific was
-         * requested. However, if only resolving via LLMNR was
-         * requested we return that. */
+        if (!c->query->suppress_unroutable_family)
+                return true;
 
-        if (flags & SD_RESOLVED_DNS)
-                return DNS_PROTOCOL_DNS;
-        if (flags & SD_RESOLVED_LLMNR)
-                return DNS_PROTOCOL_LLMNR;
+        if (c->scope->protocol != DNS_PROTOCOL_DNS)
+                return true;
 
-        return DNS_PROTOCOL_DNS;
+        family = dns_type_to_af(type);
+        if (family < 0)
+                return true;
+
+        if (c->scope->link)
+                return link_relevant(c->scope->link, family, false);
+        else
+                return manager_routable(c->scope->manager, family);
 }
 
-static int dns_type_to_af(uint16_t t) {
-        switch (t) {
+static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
+        DnsQuestion *question;
+        DnsResourceKey *key;
+        int n = 0, r;
 
-        case DNS_TYPE_A:
-                return AF_INET;
+        assert(c);
 
-        case DNS_TYPE_AAAA:
-                return AF_INET6;
+        dns_query_candidate_stop(c);
 
-        case DNS_TYPE_ANY:
-                return AF_UNSPEC;
+        question = dns_query_question_for_protocol(c->query, c->scope->protocol);
 
-        default:
-                return -EINVAL;
+        /* Create one transaction per question key */
+        DNS_QUESTION_FOREACH(key, question) {
+                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL;
+                DnsResourceKey *qkey;
+
+                if (!dns_query_candidate_is_routable(c, key->type))
+                        continue;
+
+                if (c->search_domain) {
+                        r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name);
+                        if (r < 0)
+                                goto fail;
+
+                        qkey = new_key;
+                } else
+                        qkey = key;
+
+                if (!dns_scope_good_key(c->scope, qkey))
+                        continue;
+
+                r = dns_query_candidate_add_transaction(c, qkey);
+                if (r < 0)
+                        goto fail;
+
+                n++;
         }
+
+        return n;
+
+fail:
+        dns_query_candidate_stop(c);
+        return r;
 }
 
-static int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
+void dns_query_candidate_notify(DnsQueryCandidate *c) {
+        DnsTransactionState state;
         int r;
 
-        assert(q);
-        assert(key);
-        assert(answer);
+        assert(c);
 
-        r = dns_answer_reserve(answer, 2);
-        if (r < 0)
-                return r;
-
-        if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        state = dns_query_candidate_state(c);
 
-                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
-                if (!rr)
-                        return -ENOMEM;
+        if (DNS_TRANSACTION_IS_LIVE(state))
+                return;
 
-                rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
+        if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
 
-                r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
+                r = dns_query_candidate_next_search_domain(c);
                 if (r < 0)
-                        return r;
-        }
+                        goto fail;
+
+                if (r > 0) {
+                        /* OK, there's another search domain to try, let's do so. */
 
-        if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+                        r = dns_query_candidate_setup_transactions(c);
+                        if (r < 0)
+                                goto fail;
 
-                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
-                if (!rr)
-                        return -ENOMEM;
+                        if (r > 0) {
+                                /* New transactions where queued. Start them and wait */
 
-                rr->aaaa.in6_addr = in6addr_loopback;
+                                r = dns_query_candidate_go(c);
+                                if (r < 0)
+                                        goto fail;
+
+                                return;
+                        }
+                }
 
-                r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
-                if (r < 0)
-                        return r;
         }
 
-        return 0;
+        dns_query_ready(c->query);
+        return;
+
+fail:
+        log_warning_errno(r, "Failed to follow search domains: %m");
+        c->error_code = r;
+        dns_query_ready(c->query);
 }
 
-static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
-        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+static void dns_query_stop(DnsQuery *q) {
+        DnsQueryCandidate *c;
 
-        rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
-        if (!rr)
-                return -ENOMEM;
+        assert(q);
 
-        rr->ptr.name = strdup(to);
-        if (!rr->ptr.name)
-                return -ENOMEM;
+        q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
 
-        return dns_answer_add(*answer, rr, ifindex);
+        LIST_FOREACH(candidates_by_query, c, q->candidates)
+                dns_query_candidate_stop(c);
 }
 
-static int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
-        int r;
-
+static void dns_query_free_candidates(DnsQuery *q) {
         assert(q);
-        assert(key);
-        assert(answer);
 
-        r = dns_answer_reserve(answer, 1);
-        if (r < 0)
-                return r;
+        while (q->candidates)
+                dns_query_candidate_free(q->candidates);
+}
 
-        if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
-                r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
-                if (r < 0)
-                        return r;
-        }
+static void dns_query_reset_answer(DnsQuery *q) {
+        assert(q);
 
-        return 0;
+        q->answer = dns_answer_unref(q->answer);
+        q->answer_rcode = 0;
+        q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+        q->answer_errno = 0;
+        q->answer_authenticated = false;
+        q->answer_protocol = _DNS_PROTOCOL_INVALID;
+        q->answer_family = AF_UNSPEC;
+        q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain);
 }
 
-static int answer_add_addresses_rr(
-                DnsAnswer **answer,
-                const char *name,
-                struct local_address *addresses,
-                unsigned n_addresses) {
+DnsQuery *dns_query_free(DnsQuery *q) {
+        if (!q)
+                return NULL;
 
-        unsigned j;
-        int r;
+        while (q->auxiliary_queries)
+                dns_query_free(q->auxiliary_queries);
 
-        assert(answer);
-        assert(name);
+        if (q->auxiliary_for) {
+                assert(q->auxiliary_for->n_auxiliary_queries > 0);
+                q->auxiliary_for->n_auxiliary_queries--;
+                LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
+        }
 
-        r = dns_answer_reserve(answer, n_addresses);
-        if (r < 0)
-                return r;
+        dns_query_free_candidates(q);
 
-        for (j = 0; j < n_addresses; j++) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        dns_question_unref(q->question_idna);
+        dns_question_unref(q->question_utf8);
 
-                r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
-                if (r < 0)
-                        return r;
+        dns_query_reset_answer(q);
 
-                r = dns_answer_add(*answer, rr, addresses[j].ifindex);
-                if (r < 0)
-                        return r;
+        sd_bus_message_unref(q->request);
+        sd_bus_track_unref(q->bus_track);
+
+        free(q->request_address_string);
+
+        if (q->manager) {
+                LIST_REMOVE(queries, q->manager->dns_queries, q);
+                q->manager->n_dns_queries--;
         }
 
-        return 0;
+        free(q);
+
+        return NULL;
 }
 
-static int answer_add_addresses_ptr(
-                DnsAnswer **answer,
-                const char *name,
-                struct local_address *addresses,
-                unsigned n_addresses,
-                int af, const union in_addr_union *match) {
+int dns_query_new(
+                Manager *m,
+                DnsQuery **ret,
+                DnsQuestion *question_utf8,
+                DnsQuestion *question_idna,
+                int ifindex, uint64_t flags) {
 
-        unsigned j;
+        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
+        DnsResourceKey *key;
+        bool good = false;
         int r;
 
-        assert(answer);
-        assert(name);
+        assert(m);
 
-        for (j = 0; j < n_addresses; j++) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        if (dns_question_size(question_utf8) > 0) {
+                r = dns_question_is_valid_for_query(question_utf8);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -EINVAL;
 
-                if (af != AF_UNSPEC) {
+                good = true;
+        }
 
-                        if (addresses[j].family != af)
-                                continue;
+        /* If the IDNA and UTF8 questions are the same, merge their references */
+        r = dns_question_is_equal(question_idna, question_utf8);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                question_idna = question_utf8;
+        else {
+                if (dns_question_size(question_idna) > 0) {
+                        r = dns_question_is_valid_for_query(question_idna);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                return -EINVAL;
 
-                        if (match && !in_addr_equal(af, match, &addresses[j].address))
-                                continue;
+                        good = true;
                 }
+        }
+
+        if (!good) /* don't allow empty queries */
+                return -EINVAL;
+
+        if (m->n_dns_queries >= QUERIES_MAX)
+                return -EBUSY;
+
+        q = new0(DnsQuery, 1);
+        if (!q)
+                return -ENOMEM;
+
+        q->question_utf8 = dns_question_ref(question_utf8);
+        q->question_idna = dns_question_ref(question_idna);
+        q->ifindex = ifindex;
+        q->flags = flags;
+        q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+        q->answer_protocol = _DNS_PROTOCOL_INVALID;
+        q->answer_family = AF_UNSPEC;
 
-                r = dns_answer_reserve(answer, 1);
+        /* First dump UTF8  question */
+        DNS_QUESTION_FOREACH(key, question_utf8) {
+                _cleanup_free_ char *p = NULL;
+
+                r = dns_resource_key_to_string(key, &p);
                 if (r < 0)
                         return r;
 
-                r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
+                log_debug("Looking up RR for %s.", strstrip(p));
+        }
+
+        /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
+        DNS_QUESTION_FOREACH(key, question_idna) {
+                _cleanup_free_ char *p = NULL;
+
+                r = dns_question_contains(question_utf8, key);
                 if (r < 0)
                         return r;
+                if (r > 0)
+                        continue;
 
-                r = dns_answer_add(*answer, rr, addresses[j].ifindex);
+                r = dns_resource_key_to_string(key, &p);
                 if (r < 0)
                         return r;
+
+                log_debug("Looking up IDNA RR for %s.", strstrip(p));
         }
 
+        LIST_PREPEND(queries, m->dns_queries, q);
+        m->n_dns_queries++;
+        q->manager = m;
+
+        if (ret)
+                *ret = q;
+        q = NULL;
+
         return 0;
 }
 
-static int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
-        _cleanup_free_ struct local_address *addresses = NULL;
-        int n = 0, af;
-
+int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
         assert(q);
-        assert(key);
-        assert(answer);
-
-        af = dns_type_to_af(key->type);
-        if (af >= 0) {
-                n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
-                if (n < 0)
-                        return n;
-
-                if (n == 0) {
-                        struct local_address buffer[2];
-
-                        /* If we have no local addresses then use ::1
-                         * and 127.0.0.2 as local ones. */
-
-                        if (af == AF_INET || af == AF_UNSPEC)
-                                buffer[n++] = (struct local_address) {
-                                        .family = AF_INET,
-                                        .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
-                                        .address.in.s_addr = htobe32(0x7F000002),
-                                };
-
-                        if (af == AF_INET6 || af == AF_UNSPEC)
-                                buffer[n++] = (struct local_address) {
-                                        .family = AF_INET6,
-                                        .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
-                                        .address.in6 = in6addr_loopback,
-                                };
-
-                        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
-                }
-        }
+        assert(auxiliary_for);
 
-        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
-
-static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
-        _cleanup_free_ struct local_address *addresses = NULL;
-        int n, r;
+        /* Ensure that that the query is not auxiliary yet, and
+         * nothing else is auxiliary to it either */
+        assert(!q->auxiliary_for);
+        assert(!q->auxiliary_queries);
 
-        assert(q);
-        assert(address);
-        assert(answer);
+        /* Ensure that the unit we shall be made auxiliary for isn't
+         * auxiliary itself */
+        assert(!auxiliary_for->auxiliary_for);
 
-        if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
+        if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
+                return -EAGAIN;
 
-                /* Always map the IPv4 address 127.0.0.2 to the local
-                 * hostname, in addition to "localhost": */
+        LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
+        q->auxiliary_for = auxiliary_for;
 
-                r = dns_answer_reserve(answer, 3);
-                if (r < 0)
-                        return r;
+        auxiliary_for->n_auxiliary_queries++;
+        return 0;
+}
 
-                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
-                if (r < 0)
-                        return r;
+static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
+        assert(q);
+        assert(!DNS_TRANSACTION_IS_LIVE(state));
+        assert(DNS_TRANSACTION_IS_LIVE(q->state));
 
-                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
-                if (r < 0)
-                        return r;
+        /* Note that this call might invalidate the query. Callers
+         * should hence not attempt to access the query or transaction
+         * after calling this function. */
 
-                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
-                if (r < 0)
-                        return r;
+        q->state = state;
 
-                return 0;
-        }
+        dns_query_stop(q);
+        if (q->complete)
+                q->complete(q);
+}
 
-        n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
-        if (n < 0)
-                return n;
+static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
+        DnsQuery *q = userdata;
 
-        r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
-        if (r < 0)
-                return r;
+        assert(s);
+        assert(q);
 
-        return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
+        dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
+        return 0;
 }
 
-static int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
-        _cleanup_free_ struct local_address *addresses = NULL;
-        int n = 0, af;
+static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
+        DnsQueryCandidate *c;
+        int r;
 
         assert(q);
-        assert(key);
-        assert(answer);
+        assert(s);
 
-        af = dns_type_to_af(key->type);
-        if (af >= 0) {
-                n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
-                if (n < 0)
-                        return n;
-        }
+        r = dns_query_candidate_new(&c, q, s);
+        if (r < 0)
+                return r;
 
-        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
+        /* If this a single-label domain on DNS, we might append a suitable search domain first. */
+        if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0)  {
+                r = dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question_idna));
+                if (r < 0)
+                        goto fail;
+                if (r > 0) {
+                        /* OK, we need a search domain now. Let's find one for this scope */
 
-static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
-        _cleanup_free_ struct local_address *addresses = NULL;
-        int n;
+                        r = dns_query_candidate_next_search_domain(c);
+                        if (r <= 0) /* if there's no search domain, then we won't add any transaction. */
+                                goto fail;
+                }
+        }
 
-        assert(q);
-        assert(address);
-        assert(answer);
+        r = dns_query_candidate_setup_transactions(c);
+        if (r < 0)
+                goto fail;
 
-        n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
-        if (n < 0)
-                return n;
+        return 0;
 
-        return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
+fail:
+        dns_query_candidate_free(c);
+        return r;
 }
 
 static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
-        unsigned i;
         int r;
 
         assert(q);
         assert(state);
 
-        /* Tries to synthesize localhost RR replies where appropriate */
+        /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
+         * the normal lookup finished. The data from the network hence takes precedence over the data we
+         * synthesize. (But note that many scopes refuse to resolve certain domain names) */
 
         if (!IN_SET(*state,
-                    DNS_TRANSACTION_FAILURE,
+                    DNS_TRANSACTION_RCODE_FAILURE,
                     DNS_TRANSACTION_NO_SERVERS,
                     DNS_TRANSACTION_TIMEOUT,
-                    DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
+                    DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
+                    DNS_TRANSACTION_NETWORK_DOWN,
+                    DNS_TRANSACTION_NOT_FOUND))
                 return 0;
 
-        for (i = 0; i < q->question->n_keys; i++) {
-                union in_addr_union address;
-                const char *name;
-                int af;
-
-                if (q->question->keys[i]->class != DNS_CLASS_IN &&
-                    q->question->keys[i]->class != DNS_CLASS_ANY)
-                        continue;
-
-                name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
-
-                if (is_localhost(name)) {
+        r = dns_synthesize_answer(
+                        q->manager,
+                        q->question_utf8,
+                        q->ifindex,
+                        &answer);
 
-                        r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
-
-                } else if (manager_is_own_hostname(q->manager, name)) {
+        if (r <= 0)
+                return r;
 
-                        r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
+        dns_query_reset_answer(q);
 
-                } else if (is_gateway_hostname(name)) {
+        q->answer = answer;
+        answer = NULL;
+        q->answer_rcode = DNS_RCODE_SUCCESS;
+        q->answer_protocol = dns_synthesize_protocol(q->flags);
+        q->answer_family = dns_synthesize_family(q->flags);
+        q->answer_authenticated = true;
 
-                        r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
+        *state = DNS_TRANSACTION_SUCCESS;
 
-                } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
-                           dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
+        return 1;
+}
 
-                        r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
+static int dns_query_try_etc_hosts(DnsQuery *q) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        int r;
 
-                } else if (dns_name_address(name, &af, &address) > 0) {
+        assert(q);
 
-                        r = synthesize_system_hostname_ptr(q, af, &address, &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
+        /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
+         * data from /etc/hosts hence takes precedence over the network. */
 
-                        r = synthesize_gateway_ptr(q, af, &address, &answer);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
-                }
-        }
+        r = manager_etc_hosts_lookup(
+                        q->manager,
+                        q->question_utf8,
+                        &answer);
+        if (r <= 0)
+                return r;
 
-        if (!answer)
-                return 0;
+        dns_query_reset_answer(q);
 
-        dns_answer_unref(q->answer);
         q->answer = answer;
         answer = NULL;
-
-        q->answer_family = SYNTHESIZE_FAMILY(q->flags);
-        q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
         q->answer_rcode = DNS_RCODE_SUCCESS;
-
-        *state = DNS_TRANSACTION_SUCCESS;
+        q->answer_protocol = dns_synthesize_protocol(q->flags);
+        q->answer_family = dns_synthesize_family(q->flags);
+        q->answer_authenticated = true;
 
         return 1;
 }
@@ -609,9 +668,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
 int dns_query_go(DnsQuery *q) {
         DnsScopeMatch found = DNS_SCOPE_NO;
         DnsScope *s, *first = NULL;
-        DnsTransaction *t;
-        const char *name;
-        Iterator i;
+        DnsQueryCandidate *c;
         int r;
 
         assert(q);
@@ -619,13 +676,21 @@ int dns_query_go(DnsQuery *q) {
         if (q->state != DNS_TRANSACTION_NULL)
                 return 0;
 
-        assert(q->question);
-        assert(q->question->n_keys > 0);
-
-        name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
+        r = dns_query_try_etc_hosts(q);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                dns_query_complete(q, DNS_TRANSACTION_SUCCESS);
+                return 1;
+        }
 
         LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
                 DnsScopeMatch match;
+                const char *name;
+
+                name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol));
+                if (!name)
+                        continue;
 
                 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
                 if (match < 0)
@@ -650,17 +715,25 @@ int dns_query_go(DnsQuery *q) {
         if (found == DNS_SCOPE_NO) {
                 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
 
-                dns_query_synthesize_reply(q, &state);
+                r = dns_query_synthesize_reply(q, &state);
+                if (r < 0)
+                        return r;
+
                 dns_query_complete(q, state);
                 return 1;
         }
 
-        r = dns_query_add_transaction_split(q, first);
+        r = dns_query_add_candidate(q, first);
         if (r < 0)
                 goto fail;
 
         LIST_FOREACH(scopes, s, first->scopes_next) {
                 DnsScopeMatch match;
+                const char *name;
+
+                name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol));
+                if (!name)
+                        continue;
 
                 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
                 if (match < 0)
@@ -669,15 +742,12 @@ int dns_query_go(DnsQuery *q) {
                 if (match != found)
                         continue;
 
-                r = dns_query_add_transaction_split(q, s);
+                r = dns_query_add_candidate(q, s);
                 if (r < 0)
                         goto fail;
         }
 
-        q->answer = dns_answer_unref(q->answer);
-        q->answer_rcode = 0;
-        q->answer_family = AF_UNSPEC;
-        q->answer_protocol = _DNS_PROTOCOL_INVALID;
+        dns_query_reset_answer(q);
 
         r = sd_event_add_time(
                         q->manager->event,
@@ -688,17 +758,18 @@ int dns_query_go(DnsQuery *q) {
         if (r < 0)
                 goto fail;
 
+        (void) sd_event_source_set_description(q->timeout_event_source, "query-timeout");
+
         q->state = DNS_TRANSACTION_PENDING;
         q->block_ready++;
 
-        /* Start the transactions that are not started yet */
-        SET_FOREACH(t, q->transactions, i) {
-                if (t->state != DNS_TRANSACTION_NULL)
-                        continue;
-
-                r = dns_transaction_go(t);
-                if (r < 0)
+        /* Start the transactions */
+        LIST_FOREACH(candidates_by_query, c, q->candidates) {
+                r = dns_query_candidate_go(c);
+                if (r < 0) {
+                        q->block_ready--;
                         goto fail;
+                }
         }
 
         q->block_ready--;
@@ -711,151 +782,268 @@ fail:
         return r;
 }
 
-void dns_query_ready(DnsQuery *q) {
-        DnsTransaction *t;
+static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
         DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
-        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
-        int rcode = 0;
-        DnsScope *scope = NULL;
-        bool pending = false;
+        bool has_authenticated = false, has_non_authenticated = false;
+        DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
+        DnsTransaction *t;
         Iterator i;
+        int r;
 
         assert(q);
-        assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
 
-        /* Note that this call might invalidate the query. Callers
-         * should hence not attempt to access the query or transaction
-         * after calling this function, unless the block_ready
-         * counter was explicitly bumped before doing so. */
+        if (!c) {
+                r = dns_query_synthesize_reply(q, &state);
+                if (r < 0)
+                        goto fail;
 
-        if (q->block_ready > 0)
+                dns_query_complete(q, state);
                 return;
+        }
 
-        SET_FOREACH(t, q->transactions, i) {
-
-                /* If we found a successful answer, ignore all answers from other scopes */
-                if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
-                        continue;
-
-                /* One of the transactions is still going on, let's maybe wait for it */
-                if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
-                        pending = true;
-                        continue;
-                }
+        if (c->error_code != 0) {
+                /* If the candidate had an error condition of its own, start with that. */
+                state = DNS_TRANSACTION_ERRNO;
+                q->answer = dns_answer_unref(q->answer);
+                q->answer_rcode = 0;
+                q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+                q->answer_errno = c->error_code;
+        }
 
-                /* One of the transactions is successful, let's use
-                 * it, and copy its data out */
-                if (t->state == DNS_TRANSACTION_SUCCESS) {
-                        DnsAnswer *a;
+        SET_FOREACH(t, c->transactions, i) {
 
-                        if (t->received) {
-                                rcode = DNS_PACKET_RCODE(t->received);
-                                a = t->received->answer;
-                        } else {
-                                rcode = t->cached_rcode;
-                                a = t->cached;
-                        }
+                switch (t->state) {
 
-                        if (state == DNS_TRANSACTION_SUCCESS) {
-                                DnsAnswer *merged;
+                case DNS_TRANSACTION_SUCCESS: {
+                        /* We found a successfuly reply, merge it into the answer */
+                        r = dns_answer_extend(&q->answer, t->answer);
+                        if (r < 0)
+                                goto fail;
 
-                                merged = dns_answer_merge(answer, a);
-                                if (!merged) {
-                                        dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
-                                        return;
-                                }
+                        q->answer_rcode = t->answer_rcode;
+                        q->answer_errno = 0;
 
-                                dns_answer_unref(answer);
-                                answer = merged;
+                        if (t->answer_authenticated) {
+                                has_authenticated = true;
+                                dnssec_result_authenticated = t->answer_dnssec_result;
                         } else {
-                                dns_answer_unref(answer);
-                                answer = dns_answer_ref(a);
+                                has_non_authenticated = true;
+                                dnssec_result_non_authenticated = t->answer_dnssec_result;
                         }
 
-                        scope = t->scope;
                         state = DNS_TRANSACTION_SUCCESS;
-                        continue;
+                        break;
                 }
 
-                /* One of the transactions has failed, let's see
-                 * whether we find anything better, but if not, return
-                 * its response data */
-                if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
-                        DnsAnswer *a;
+                case DNS_TRANSACTION_NULL:
+                case DNS_TRANSACTION_PENDING:
+                case DNS_TRANSACTION_VALIDATING:
+                case DNS_TRANSACTION_ABORTED:
+                        /* Ignore transactions that didn't complete */
+                        continue;
 
-                        if (t->received) {
-                                rcode = DNS_PACKET_RCODE(t->received);
-                                a = t->received->answer;
-                        } else {
-                                rcode = t->cached_rcode;
-                                a = t->cached;
-                        }
+                default:
+                        /* Any kind of failure? Store the data away,
+                         * if there's nothing stored yet. */
 
-                        dns_answer_unref(answer);
-                        answer = dns_answer_ref(a);
+                        if (state == DNS_TRANSACTION_SUCCESS)
+                                continue;
 
-                        scope = t->scope;
-                        state = DNS_TRANSACTION_FAILURE;
-                        continue;
-                }
+                        q->answer = dns_answer_unref(q->answer);
+                        q->answer_rcode = t->answer_rcode;
+                        q->answer_dnssec_result = t->answer_dnssec_result;
+                        q->answer_errno = t->answer_errno;
 
-                if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
                         state = t->state;
+                        break;
+                }
         }
 
-        if (pending) {
+        if (state == DNS_TRANSACTION_SUCCESS) {
+                q->answer_authenticated = has_authenticated && !has_non_authenticated;
+                q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated;
+        }
+
+        q->answer_protocol = c->scope->protocol;
+        q->answer_family = c->scope->family;
 
-                /* If so far we weren't successful, and there's
-                 * something still pending, then wait for it */
-                if (state != DNS_TRANSACTION_SUCCESS)
+        dns_search_domain_unref(q->answer_search_domain);
+        q->answer_search_domain = dns_search_domain_ref(c->search_domain);
+
+        r = dns_query_synthesize_reply(q, &state);
+        if (r < 0)
+                goto fail;
+
+        dns_query_complete(q, state);
+        return;
+
+fail:
+        q->answer_errno = -r;
+        dns_query_complete(q, DNS_TRANSACTION_ERRNO);
+}
+
+void dns_query_ready(DnsQuery *q) {
+
+        DnsQueryCandidate *bad = NULL, *c;
+        bool pending = false;
+
+        assert(q);
+        assert(DNS_TRANSACTION_IS_LIVE(q->state));
+
+        /* Note that this call might invalidate the query. Callers
+         * should hence not attempt to access the query or transaction
+         * after calling this function, unless the block_ready
+         * counter was explicitly bumped before doing so. */
+
+        if (q->block_ready > 0)
+                return;
+
+        LIST_FOREACH(candidates_by_query, c, q->candidates) {
+                DnsTransactionState state;
+
+                state = dns_query_candidate_state(c);
+                switch (state) {
+
+                case DNS_TRANSACTION_SUCCESS:
+                        /* One of the candidates is successful,
+                         * let's use it, and copy its data out */
+                        dns_query_accept(q, c);
                         return;
 
-                /* If we already were successful, then only wait for
-                 * other transactions on the same scope to finish. */
-                SET_FOREACH(t, q->transactions, i) {
-                        if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
-                                return;
-                }
-        }
+                case DNS_TRANSACTION_NULL:
+                case DNS_TRANSACTION_PENDING:
+                case DNS_TRANSACTION_VALIDATING:
+                        /* One of the candidates is still going on,
+                         * let's maybe wait for it */
+                        pending = true;
+                        break;
 
-        if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
-                q->answer = dns_answer_ref(answer);
-                q->answer_rcode = rcode;
-                q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
-                q->answer_family = scope ? scope->family : AF_UNSPEC;
+                default:
+                        /* Any kind of failure */
+                        bad = c;
+                        break;
+                }
         }
 
-        /* Try to synthesize a reply if we couldn't resolve something. */
-        dns_query_synthesize_reply(q, &state);
+        if (pending)
+                return;
 
-        dns_query_complete(q, state);
+        dns_query_accept(q, bad);
 }
 
-int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
-        _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
-        int r;
+static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
+        _cleanup_(dns_question_unrefp) DnsQuestion *nq_idna = NULL, *nq_utf8 = NULL;
+        int r, k;
 
         assert(q);
 
+        q->n_cname_redirects ++;
         if (q->n_cname_redirects > CNAME_MAX)
                 return -ELOOP;
 
-        r = dns_question_cname_redirect(q->question, cname, &nq);
+        r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna);
         if (r < 0)
                 return r;
+        else if (r > 0)
+                log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna));
+
+        k = dns_question_is_equal(q->question_idna, q->question_utf8);
+        if (k < 0)
+                return r;
+        if (k > 0) {
+                /* Same question? Shortcut new question generation */
+                nq_utf8 = dns_question_ref(nq_idna);
+                k = r;
+        } else {
+                k = dns_question_cname_redirect(q->question_utf8, cname, &nq_utf8);
+                if (k < 0)
+                        return k;
+                else if (k > 0)
+                        log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8));
+        }
 
-        dns_question_unref(q->question);
-        q->question = nq;
-        nq = NULL;
+        if (r == 0 && k == 0) /* No actual cname happened? */
+                return -ELOOP;
 
-        q->n_cname_redirects++;
+        if (q->answer_protocol == DNS_PROTOCOL_DNS) {
+                /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
+                 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
+                 * ones. */
+
+                q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */
+        }
+
+        /* Turn off searching for the new name */
+        q->flags |= SD_RESOLVED_NO_SEARCH;
+
+        dns_question_unref(q->question_idna);
+        q->question_idna = nq_idna;
+        nq_idna = NULL;
+
+        dns_question_unref(q->question_utf8);
+        q->question_utf8 = nq_utf8;
+        nq_utf8 = NULL;
+
+        dns_query_free_candidates(q);
+        dns_query_reset_answer(q);
 
-        dns_query_stop(q);
         q->state = DNS_TRANSACTION_NULL;
 
         return 0;
 }
 
+int dns_query_process_cname(DnsQuery *q) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
+        DnsQuestion *question;
+        DnsResourceRecord *rr;
+        int r;
+
+        assert(q);
+
+        if (!IN_SET(q->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NULL))
+                return DNS_QUERY_NOMATCH;
+
+        question = dns_query_question_for_protocol(q, q->answer_protocol);
+
+        DNS_ANSWER_FOREACH(rr, q->answer) {
+                r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */
+
+                r = dns_question_matches_cname_or_dname(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
+                if (r < 0)
+                        return r;
+                if (r > 0 && !cname)
+                        cname = dns_resource_record_ref(rr);
+        }
+
+        if (!cname)
+                return DNS_QUERY_NOMATCH; /* No match and no cname to follow */
+
+        if (q->flags & SD_RESOLVED_NO_CNAME)
+                return -ELOOP;
+
+        /* OK, let's actually follow the CNAME */
+        r = dns_query_cname_redirect(q, cname);
+        if (r < 0)
+                return r;
+
+        /* Let's see if the answer can already answer the new
+         * redirected question */
+        r = dns_query_process_cname(q);
+        if (r != DNS_QUERY_NOMATCH)
+                return r;
+
+        /* OK, it cannot, let's begin with the new query */
+        r = dns_query_go(q);
+        if (r < 0)
+                return r;
+
+        return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */
+}
+
 static int on_bus_track(sd_bus_track *t, void *userdata) {
         DnsQuery *q = userdata;
 
@@ -885,3 +1073,42 @@ int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
 
         return 0;
 }
+
+DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) {
+        assert(q);
+
+        switch (protocol) {
+
+        case DNS_PROTOCOL_DNS:
+                return q->question_idna;
+
+        case DNS_PROTOCOL_MDNS:
+        case DNS_PROTOCOL_LLMNR:
+                return q->question_utf8;
+
+        default:
+                return NULL;
+        }
+}
+
+const char *dns_query_string(DnsQuery *q) {
+        const char *name;
+        int r;
+
+        /* Returns a somewhat useful human-readable lookup key string for this query */
+
+        if (q->request_address_string)
+                return q->request_address_string;
+
+        if (q->request_address_valid) {
+                r = in_addr_to_string(q->request_family, &q->request_address, &q->request_address_string);
+                if (r >= 0)
+                        return q->request_address_string;
+        }
+
+        name = dns_question_first_name(q->question_utf8);
+        if (name)
+                return name;
+
+        return dns_question_first_name(q->question_idna);
+}
index e7063d967885f0478d536bbd09aeb0ca2a49777a..c2ac02f68b7719cfcfe85a3126a39b2c8b7f48ac 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 
 #include "sd-bus.h"
+
 #include "set.h"
 
+typedef struct DnsQueryCandidate DnsQueryCandidate;
 typedef struct DnsQuery DnsQuery;
 
-#include "resolved-dns-question.h"
 #include "resolved-dns-answer.h"
+#include "resolved-dns-question.h"
 #include "resolved-dns-stream.h"
+#include "resolved-dns-search-domain.h"
+
+struct DnsQueryCandidate {
+        DnsQuery *query;
+        DnsScope *scope;
+
+        DnsSearchDomain *search_domain;
+
+        int error_code;
+        Set *transactions;
+
+        LIST_FIELDS(DnsQueryCandidate, candidates_by_query);
+        LIST_FIELDS(DnsQueryCandidate, candidates_by_scope);
+};
 
 struct DnsQuery {
         Manager *manager;
-        DnsQuestion *question;
+
+        /* When resolving a service, we first create a TXT+SRV query,
+         * and then for the hostnames we discover auxiliary A+AAAA
+         * queries. This pointer always points from the auxiliary
+         * queries back to the TXT+SRV query. */
+        DnsQuery *auxiliary_for;
+        LIST_HEAD(DnsQuery, auxiliary_queries);
+        unsigned n_auxiliary_queries;
+        int auxiliary_result;
+
+        /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note that even
+         * on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names (in contrast to their
+         * domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference between these two fields is mostly
+         * relevant only for explicit *hostname* lookups as well as the domain suffixes of service lookups. */
+        DnsQuestion *question_idna;
+        DnsQuestion *question_utf8;
 
         uint64_t flags;
         int ifindex;
 
+        /* If true, A or AAAA RR lookups will be suppressed on links with no routable address of the matching address
+         * family */
+        bool suppress_unroutable_family;
+
         DnsTransactionState state;
         unsigned n_cname_redirects;
 
+        LIST_HEAD(DnsQueryCandidate, candidates);
         sd_event_source *timeout_event_source;
 
         /* Discovered data */
         DnsAnswer *answer;
-        int answer_family;
-        DnsProtocol answer_protocol;
         int answer_rcode;
+        DnssecResult answer_dnssec_result;
+        bool answer_authenticated;
+        DnsProtocol answer_protocol;
+        int answer_family;
+        DnsSearchDomain *answer_search_domain;
+        int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
 
         /* Bus client information */
         sd_bus_message *request;
         int request_family;
-        const char *request_hostname;
+        bool request_address_valid;
         union in_addr_union request_address;
+        unsigned block_all_complete;
+        char *request_address_string;
 
         /* Completion callback */
         void (*complete)(DnsQuery* q);
         unsigned block_ready;
 
-        Set *transactions;
-
         sd_bus_track *bus_track;
 
         LIST_FIELDS(DnsQuery, queries);
+        LIST_FIELDS(DnsQuery, auxiliary_queries);
 };
 
-int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question, int family, uint64_t flags);
+enum {
+        DNS_QUERY_MATCH,
+        DNS_QUERY_NOMATCH,
+        DNS_QUERY_RESTARTED,
+};
+
+DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c);
+void dns_query_candidate_notify(DnsQueryCandidate *c);
+
+int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags);
 DnsQuery *dns_query_free(DnsQuery *q);
 
+int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for);
+
 int dns_query_go(DnsQuery *q);
 void dns_query_ready(DnsQuery *q);
 
-int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname);
+int dns_query_process_cname(DnsQuery *q);
 
 int dns_query_bus_track(DnsQuery *q, sd_bus_message *m);
 
+DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol);
+
+const char *dns_query_string(DnsQuery *q);
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
index 48951221dc9ccbd090c3573d469aa40e9888968a..8e452e79a4dc4e84bd42ca68731e9288df20a742 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,6 +19,7 @@
 
 #include "alloc-util.h"
 #include "dns-domain.h"
+#include "dns-type.h"
 #include "resolved-dns-question.h"
 
 DnsQuestion *dns_question_new(unsigned n) {
@@ -89,7 +88,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
         return 0;
 }
 
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
+int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
         unsigned i;
         int r;
 
@@ -99,7 +98,7 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
                 return 0;
 
         for (i = 0; i < q->n_keys; i++) {
-                r = dns_resource_key_match_rr(q->keys[i], rr);
+                r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
                 if (r != 0)
                         return r;
         }
@@ -107,7 +106,7 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
         return 0;
 }
 
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
+int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
         unsigned i;
         int r;
 
@@ -116,8 +115,15 @@ int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
         if (!q)
                 return 0;
 
+        if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))
+                return 0;
+
         for (i = 0; i < q->n_keys; i++) {
-                r = dns_resource_key_match_cname(q->keys[i], rr);
+                /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
+                if (!dns_type_may_redirect(q->keys[i]->type))
+                        return 0;
+
+                r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
                 if (r != 0)
                         return r;
         }
@@ -125,7 +131,7 @@ int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
         return 0;
 }
 
-int dns_question_is_valid(DnsQuestion *q) {
+int dns_question_is_valid_for_query(DnsQuestion *q) {
         const char *name;
         unsigned i;
         int r;
@@ -144,62 +150,23 @@ int dns_question_is_valid(DnsQuestion *q) {
                 return 0;
 
         /* Check that all keys in this question bear the same name */
-        for (i = 1; i < q->n_keys; i++) {
+        for (i = 0; i < q->n_keys; i++) {
                 assert(q->keys[i]);
 
-                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
-                if (r <= 0)
-                        return r;
-        }
-
-        return 1;
-}
-
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) {
-        unsigned j;
-        int r;
-
-        /* Checks if all keys in "other" are also contained in "q" */
-
-        if (!other)
-                return 1;
-
-        for (j = 0; j < other->n_keys; j++) {
-                DnsResourceKey *b = other->keys[j];
-                bool found = false;
-                unsigned i;
-
-                if (!q)
-                        return 0;
-
-                for (i = 0; i < q->n_keys; i++) {
-                        DnsResourceKey *a = q->keys[i];
-
-                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
-                        if (r < 0)
+                if (i > 0) {
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
+                        if (r <= 0)
                                 return r;
-
-                        if (r == 0)
-                                continue;
-
-                        if (a->class != b->class && a->class != DNS_CLASS_ANY)
-                                continue;
-
-                        if (a->type != b->type && a->type != DNS_TYPE_ANY)
-                                continue;
-
-                        found = true;
-                        break;
                 }
 
-                if (!found)
+                if (!dns_type_is_valid_query(q->keys[i]->type))
                         return 0;
         }
 
         return 1;
 }
 
-int dns_question_contains(DnsQuestion *a, DnsResourceKey *k) {
+int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
         unsigned j;
         int r;
 
@@ -221,6 +188,9 @@ int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
         unsigned j;
         int r;
 
+        if (a == b)
+                return 1;
+
         if (!a)
                 return !b || b->n_keys == 0;
         if (!b)
@@ -245,25 +215,36 @@ int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
 
 int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
         _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
+        DnsResourceKey *key;
         bool same = true;
-        unsigned i;
         int r;
 
         assert(cname);
         assert(ret);
+        assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
 
-        if (!q) {
-                n = dns_question_new(0);
-                if (!n)
-                        return -ENOMEM;
-
-                *ret = n;
-                n = 0;
+        if (dns_question_size(q) <= 0) {
+                *ret = NULL;
                 return 0;
         }
 
-        for (i = 0; i < q->n_keys; i++) {
-                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), cname->cname.name);
+        DNS_QUESTION_FOREACH(key, q) {
+                _cleanup_free_ char *destination = NULL;
+                const char *d;
+
+                if (cname->key->type == DNS_TYPE_CNAME)
+                        d = cname->cname.name;
+                else {
+                        r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        d = destination;
+                }
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), d);
                 if (r < 0)
                         return r;
 
@@ -273,9 +254,9 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
                 }
         }
 
+        /* Fully the same, indicate we didn't do a thing */
         if (same) {
-                /* Shortcut, the names are already right */
-                *ret = dns_question_ref(q);
+                *ret = NULL;
                 return 0;
         }
 
@@ -284,10 +265,10 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
                 return -ENOMEM;
 
         /* Create a new question, and patch in the new name */
-        for (i = 0; i < q->n_keys; i++) {
+        DNS_QUESTION_FOREACH(key, q) {
                 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
 
-                k = dns_resource_key_new_redirect(q->keys[i], cname);
+                k = dns_resource_key_new_redirect(key, cname);
                 if (!k)
                         return -ENOMEM;
 
@@ -301,3 +282,187 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
 
         return 1;
 }
+
+const char *dns_question_first_name(DnsQuestion *q) {
+
+        if (!q)
+                return NULL;
+
+        if (q->n_keys < 1)
+                return NULL;
+
+        return DNS_RESOURCE_KEY_NAME(q->keys[0]);
+}
+
+int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) {
+        _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
+        _cleanup_free_ char *buf = NULL;
+        int r;
+
+        assert(ret);
+        assert(name);
+
+        if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
+                return -EAFNOSUPPORT;
+
+        if (convert_idna) {
+                r = dns_name_apply_idna(name, &buf);
+                if (r < 0)
+                        return r;
+
+                name = buf;
+        }
+
+        q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
+        if (!q)
+                return -ENOMEM;
+
+        if (family != AF_INET6) {
+                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+
+                key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name);
+                if (!key)
+                        return -ENOMEM;
+
+                r = dns_question_add(q, key);
+                if (r < 0)
+                        return r;
+        }
+
+        if (family != AF_INET) {
+                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+
+                key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
+                if (!key)
+                        return -ENOMEM;
+
+                r = dns_question_add(q, key);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = q;
+        q = NULL;
+
+        return 0;
+}
+
+int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) {
+        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+        _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
+        _cleanup_free_ char *reverse = NULL;
+        int r;
+
+        assert(ret);
+        assert(a);
+
+        if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
+                return -EAFNOSUPPORT;
+
+        r = dns_name_reverse(family, a, &reverse);
+        if (r < 0)
+                return r;
+
+        q = dns_question_new(1);
+        if (!q)
+                return -ENOMEM;
+
+        key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
+        if (!key)
+                return -ENOMEM;
+
+        reverse = NULL;
+
+        r = dns_question_add(q, key);
+        if (r < 0)
+                return r;
+
+        *ret = q;
+        q = NULL;
+
+        return 0;
+}
+
+int dns_question_new_service(
+                DnsQuestion **ret,
+                const char *service,
+                const char *type,
+                const char *domain,
+                bool with_txt,
+                bool convert_idna) {
+
+        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+        _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
+        _cleanup_free_ char *buf = NULL, *joined = NULL;
+        const char *name;
+        int r;
+
+        assert(ret);
+
+        /* We support three modes of invocation:
+         *
+         * 1. Only a domain is specified, in which case we assume a properly encoded SRV RR name, including service
+         *    type and possibly a service name. If specified in this way we assume it's already IDNA converted if
+         *    that's necessary.
+         *
+         * 2. Both service type and a domain specified, in which case a normal SRV RR is assumed, without a DNS-SD
+         *    style prefix. In this case we'll IDNA convert the domain, if that's requested.
+         *
+         * 3. All three of service name, type and domain are specified, in which case a DNS-SD service is put
+         *    together. The service name is never IDNA converted, and the domain is if requested.
+         *
+         * It's not supported to specify a service name without a type, or no domain name.
+         */
+
+        if (!domain)
+                return -EINVAL;
+
+        if (type) {
+                if (convert_idna) {
+                        r = dns_name_apply_idna(domain, &buf);
+                        if (r < 0)
+                                return r;
+
+                        domain = buf;
+                }
+
+                r = dns_service_join(service, type, domain, &joined);
+                if (r < 0)
+                        return r;
+
+                name = joined;
+        } else {
+                if (service)
+                        return -EINVAL;
+
+                name = domain;
+        }
+
+        q = dns_question_new(1 + with_txt);
+        if (!q)
+                return -ENOMEM;
+
+        key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name);
+        if (!key)
+                return -ENOMEM;
+
+        r = dns_question_add(q, key);
+        if (r < 0)
+                return r;
+
+        if (with_txt) {
+                dns_resource_key_unref(key);
+                key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name);
+                if (!key)
+                        return -ENOMEM;
+
+                r = dns_question_add(q, key);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = q;
+        q = NULL;
+
+        return 0;
+}
index 13cd1f20f31ea893afbd6ede50e62008deec1094..ea41478975d6ea347ce0acc3df52f10e76333681 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 typedef struct DnsQuestion DnsQuestion;
 
+#include "macro.h"
 #include "resolved-dns-rr.h"
 
-/* A simple array of resources keys */
+/* A simple array of resource keys */
 
 struct DnsQuestion {
         unsigned n_ref;
@@ -37,15 +36,34 @@ DnsQuestion *dns_question_new(unsigned n);
 DnsQuestion *dns_question_ref(DnsQuestion *q);
 DnsQuestion *dns_question_unref(DnsQuestion *q);
 
+int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna);
+int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
+int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
+
 int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
 
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr);
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr);
-int dns_question_is_valid(DnsQuestion *q);
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other);
-int dns_question_contains(DnsQuestion *a, DnsResourceKey *k);
+int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);
+int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char* search_domain);
+int dns_question_is_valid_for_query(DnsQuestion *q);
+int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k);
 int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b);
 
 int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret);
 
+const char *dns_question_first_name(DnsQuestion *q);
+
+static inline unsigned dns_question_size(DnsQuestion *q) {
+        return q ? q->n_keys : 0;
+}
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
+
+#define _DNS_QUESTION_FOREACH(u, key, q)                                \
+        for (unsigned UNIQ_T(i, u) = ({                                 \
+                                (key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \
+                                0;                                      \
+                        });                                             \
+             (q) && (UNIQ_T(i, u) < (q)->n_keys);                       \
+             UNIQ_T(i, u)++, (key) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->keys[UNIQ_T(i, u)] : NULL))
+
+#define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q)
index ba2ea686f33ec13d75841f624590fbde71d1ca7e..40f8e28dfd2ec982f96691580e047c6789f8fe33 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "dns-domain.h"
 #include "dns-type.h"
 #include "hexdecoct.h"
+#include "resolved-dns-dnssec.h"
 #include "resolved-dns-packet.h"
 #include "resolved-dns-rr.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
+#include "terminal-util.h"
 
 DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
         DnsResourceKey *k;
@@ -50,17 +51,62 @@ DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *
         return k;
 }
 
-DnsResourceKey* dns_resource_key_new_cname(const DnsResourceKey *key) {
+DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
+        int r;
+
         assert(key);
+        assert(cname);
+
+        assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
 
-        return dns_resource_key_new(key->class, DNS_TYPE_CNAME, DNS_RESOURCE_KEY_NAME(key));
+        if (cname->key->type == DNS_TYPE_CNAME)
+                return dns_resource_key_new(key->class, key->type, cname->cname.name);
+        else {
+                DnsResourceKey *k;
+                char *destination = NULL;
+
+                r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
+                if (r < 0)
+                        return NULL;
+                if (r == 0)
+                        return dns_resource_key_ref((DnsResourceKey*) key);
+
+                k = dns_resource_key_new_consume(key->class, key->type, destination);
+                if (!k) {
+                        free(destination);
+                        return NULL;
+                }
+
+                return k;
+        }
 }
 
-DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
+int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) {
+        DnsResourceKey *new_key;
+        char *joined;
+        int r;
+
+        assert(ret);
         assert(key);
-        assert(cname);
+        assert(name);
 
-        return dns_resource_key_new(key->class, key->type, cname->cname.name);
+        if (dns_name_is_root(name)) {
+                *ret = dns_resource_key_ref(key);
+                return 0;
+        }
+
+        r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), name, &joined);
+        if (r < 0)
+                return r;
+
+        new_key = dns_resource_key_new_consume(key->class, key->type, joined);
+        if (!new_key) {
+                free(joined);
+                return -ENOMEM;
+        }
+
+        *ret = new_key;
+        return 0;
 }
 
 DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
@@ -85,6 +131,10 @@ DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
         if (!k)
                 return NULL;
 
+        /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
+         * set this to -1, they should not be reffed/unreffed */
+        assert(k->n_ref != (unsigned) -1);
+
         assert(k->n_ref > 0);
         k->n_ref++;
 
@@ -95,6 +145,7 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
         if (!k)
                 return NULL;
 
+        assert(k->n_ref != (unsigned) -1);
         assert(k->n_ref > 0);
 
         if (k->n_ref == 1) {
@@ -106,9 +157,20 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
         return NULL;
 }
 
+bool dns_resource_key_is_address(const DnsResourceKey *key) {
+        assert(key);
+
+        /* Check if this is an A or AAAA resource key */
+
+        return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
+}
+
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
         int r;
 
+        if (a == b)
+                return 1;
+
         r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
         if (r <= 0)
                 return r;
@@ -122,30 +184,90 @@ int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
         return 1;
 }
 
-int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
+int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) {
+        int r;
+
         assert(key);
         assert(rr);
 
+        if (key == rr->key)
+                return 1;
+
+        /* Checks if an rr matches the specified key. If a search
+         * domain is specified, it will also be checked if the key
+         * with the search domain suffixed might match the RR. */
+
         if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
                 return 0;
 
         if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
                 return 0;
 
-        return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
+        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
+        if (r != 0)
+                return r;
+
+        if (search_domain) {
+                _cleanup_free_ char *joined = NULL;
+
+                r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
+                if (r < 0)
+                        return r;
+
+                return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), joined);
+        }
+
+        return 0;
 }
 
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
+int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
+        int r;
+
         assert(key);
-        assert(rr);
+        assert(cname);
 
-        if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
+        if (cname->class != key->class && key->class != DNS_CLASS_ANY)
+                return 0;
+
+        if (cname->type == DNS_TYPE_CNAME)
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
+        else if (cname->type == DNS_TYPE_DNAME)
+                r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
+        else
+                return 0;
+
+        if (r != 0)
+                return r;
+
+        if (search_domain) {
+                _cleanup_free_ char *joined = NULL;
+
+                r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
+                if (r < 0)
+                        return r;
+
+                if (cname->type == DNS_TYPE_CNAME)
+                        return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(cname));
+                else if (cname->type == DNS_TYPE_DNAME)
+                        return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(cname));
+        }
+
+        return 0;
+}
+
+int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) {
+        assert(soa);
+        assert(key);
+
+        /* Checks whether 'soa' is a SOA record for the specified key. */
+
+        if (soa->class != key->class)
                 return 0;
 
-        if (rr->key->type != DNS_TYPE_CNAME)
+        if (soa->type != DNS_TYPE_SOA)
                 return 0;
 
-        return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
+        return dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa));
 }
 
 static void dns_resource_key_hash_func(const void *i, struct siphash *state) {
@@ -186,9 +308,12 @@ const struct hash_ops dns_resource_key_hash_ops = {
 
 int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
         char cbuf[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)];
-        const char *c, *t;
+        const char *c, *t, *n;
         char *s;
 
+        /* If we cannot convert the CLASS/TYPE into a known string,
+           use the format recommended by RFC 3597, Section 5. */
+
         c = dns_class_to_string(key->class);
         if (!c) {
                 sprintf(cbuf, "CLASS%u", key->class);
@@ -201,13 +326,54 @@ int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
                 t = tbuf;
         }
 
-        if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
+        n = DNS_RESOURCE_KEY_NAME(key);
+        if (asprintf(&s, "%s%s %s %-5s", n, endswith(n, ".") ? "" : ".", c, t) < 0)
                 return -ENOMEM;
 
         *ret = s;
         return 0;
 }
 
+bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
+        assert(a);
+        assert(b);
+
+        /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
+         * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
+         * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
+         * superficial data. */
+
+        if (!*a)
+                return false;
+        if (!*b)
+                return false;
+
+        /* We refuse merging const keys */
+        if ((*a)->n_ref == (unsigned) -1)
+                return false;
+        if ((*b)->n_ref == (unsigned) -1)
+                return false;
+
+        /* Already the same? */
+        if (*a == *b)
+                return true;
+
+        /* Are they really identical? */
+        if (dns_resource_key_equal(*a, *b) <= 0)
+                return false;
+
+        /* Keep the one which already has more references. */
+        if ((*a)->n_ref > (*b)->n_ref) {
+                dns_resource_key_unref(*b);
+                *b = dns_resource_key_ref(*a);
+        } else {
+                dns_resource_key_unref(*a);
+                *a = dns_resource_key_ref(*b);
+        }
+
+        return true;
+}
+
 DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
         DnsResourceRecord *rr;
 
@@ -217,6 +383,8 @@ DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
 
         rr->n_ref = 1;
         rr->key = dns_resource_key_ref(key);
+        rr->expiry = USEC_INFINITY;
+        rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1;
 
         return rr;
 }
@@ -273,7 +441,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
 
                 case DNS_TYPE_TXT:
                 case DNS_TYPE_SPF:
-                        strv_free(rr->txt.strings);
+                        dns_txt_item_free_all(rr->txt.items);
                         break;
 
                 case DNS_TYPE_SOA:
@@ -318,13 +486,20 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
                 case DNS_TYPE_AAAA:
                         break;
 
+                case DNS_TYPE_TLSA:
+                        free(rr->tlsa.data);
+                        break;
+
+                case DNS_TYPE_OPENPGPKEY:
                 default:
                         free(rr->generic.data);
                 }
 
+                free(rr->wire_format);
                 dns_resource_key_unref(rr->key);
         }
 
+        free(rr->to_string);
         free(rr);
 
         return NULL;
@@ -394,12 +569,19 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
         return 0;
 }
 
+#define FIELD_EQUAL(a, b, field) \
+        ((a).field ## _size == (b).field ## _size &&  \
+         memcmp((a).field, (b).field, (a).field ## _size) == 0)
+
 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
         int r;
 
         assert(a);
         assert(b);
 
+        if (a == b)
+                return 1;
+
         r = dns_resource_key_equal(a->key, b->key);
         if (r <= 0)
                 return r;
@@ -430,7 +612,7 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
 
         case DNS_TYPE_SPF: /* exactly the same as TXT */
         case DNS_TYPE_TXT:
-                return strv_equal(a->txt.strings, b->txt.strings);
+                return dns_txt_item_equal(a->txt.items, b->txt.items);
 
         case DNS_TYPE_A:
                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
@@ -472,36 +654,30 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
                 return a->ds.key_tag == b->ds.key_tag &&
                        a->ds.algorithm == b->ds.algorithm &&
                        a->ds.digest_type == b->ds.digest_type &&
-                       a->ds.digest_size == b->ds.digest_size &&
-                       memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
+                       FIELD_EQUAL(a->ds, b->ds, digest);
 
         case DNS_TYPE_SSHFP:
                 return a->sshfp.algorithm == b->sshfp.algorithm &&
                        a->sshfp.fptype == b->sshfp.fptype &&
-                       a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
-                       memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
+                       FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
 
         case DNS_TYPE_DNSKEY:
-                return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
-                       a->dnskey.sep_flag == b->dnskey.sep_flag &&
+                return a->dnskey.flags == b->dnskey.flags &&
+                       a->dnskey.protocol == b->dnskey.protocol &&
                        a->dnskey.algorithm == b->dnskey.algorithm &&
-                       a->dnskey.key_size == b->dnskey.key_size &&
-                       memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
+                       FIELD_EQUAL(a->dnskey, b->dnskey, key);
 
         case DNS_TYPE_RRSIG:
                 /* do the fast comparisons first */
-                if (a->rrsig.type_covered != b->rrsig.type_covered ||
-                    a->rrsig.algorithm != b->rrsig.algorithm ||
-                    a->rrsig.labels != b->rrsig.labels ||
-                    a->rrsig.original_ttl != b->rrsig.original_ttl ||
-                    a->rrsig.expiration != b->rrsig.expiration ||
-                    a->rrsig.inception != b->rrsig.inception ||
-                    a->rrsig.key_tag != b->rrsig.key_tag ||
-                    a->rrsig.signature_size != b->rrsig.signature_size ||
-                    memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
-                        return false;
-
-                return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
+                return a->rrsig.type_covered == b->rrsig.type_covered &&
+                       a->rrsig.algorithm == b->rrsig.algorithm &&
+                       a->rrsig.labels == b->rrsig.labels &&
+                       a->rrsig.original_ttl == b->rrsig.original_ttl &&
+                       a->rrsig.expiration == b->rrsig.expiration &&
+                       a->rrsig.inception == b->rrsig.inception &&
+                       a->rrsig.key_tag == b->rrsig.key_tag &&
+                       FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
+                       dns_name_equal(a->rrsig.signer, b->rrsig.signer);
 
         case DNS_TYPE_NSEC:
                 return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
@@ -509,16 +685,20 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
 
         case DNS_TYPE_NSEC3:
                 return a->nsec3.algorithm == b->nsec3.algorithm &&
-                    a->nsec3.flags == b->nsec3.flags &&
-                    a->nsec3.iterations == b->nsec3.iterations &&
-                    a->nsec3.salt_size == b->nsec3.salt_size &&
-                    memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
-                    memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
-                    bitmap_equal(a->nsec3.types, b->nsec3.types);
+                       a->nsec3.flags == b->nsec3.flags &&
+                       a->nsec3.iterations == b->nsec3.iterations &&
+                       FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
+                       FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
+                       bitmap_equal(a->nsec3.types, b->nsec3.types);
+
+        case DNS_TYPE_TLSA:
+                return a->tlsa.cert_usage == b->tlsa.cert_usage &&
+                       a->tlsa.selector == b->tlsa.selector &&
+                       a->tlsa.matching_type == b->tlsa.matching_type &&
+                       FIELD_EQUAL(a->tlsa, b->tlsa, data);
 
         default:
-                return a->generic.size == b->generic.size &&
-                        memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
+                return FIELD_EQUAL(a->generic, b->generic, data);
         }
 }
 
@@ -600,16 +780,56 @@ static char *format_types(Bitmap *types) {
         return strjoin("( ", str, " )", NULL);
 }
 
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
+static char *format_txt(DnsTxtItem *first) {
+        DnsTxtItem *i;
+        size_t c = 1;
+        char *p, *s;
+
+        LIST_FOREACH(items, i, first)
+                c += i->length * 4 + 3;
+
+        p = s = new(char, c);
+        if (!s)
+                return NULL;
+
+        LIST_FOREACH(items, i, first) {
+                size_t j;
+
+                if (i != first)
+                        *(p++) = ' ';
+
+                *(p++) = '"';
+
+                for (j = 0; j < i->length; j++) {
+                        if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
+                                *(p++) = '\\';
+                                *(p++) = '0' + (i->data[j] / 100);
+                                *(p++) = '0' + ((i->data[j] / 10) % 10);
+                                *(p++) = '0' + (i->data[j] % 10);
+                        } else
+                                *(p++) = i->data[j];
+                }
+
+                *(p++) = '"';
+        }
+
+        *p = 0;
+        return s;
+}
+
+const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
         _cleanup_free_ char *k = NULL, *t = NULL;
         char *s;
         int r;
 
         assert(rr);
 
+        if (rr->to_string)
+                return rr->to_string;
+
         r = dns_resource_key_to_string(rr->key, &k);
         if (r < 0)
-                return r;
+                return NULL;
 
         switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
 
@@ -621,7 +841,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->srv.port,
                              strna(rr->srv.name));
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_PTR:
@@ -630,26 +850,25 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
         case DNS_TYPE_DNAME:
                 s = strjoin(k, " ", rr->ptr.name, NULL);
                 if (!s)
-                        return -ENOMEM;
+                        return NULL;
 
                 break;
 
         case DNS_TYPE_HINFO:
                 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
                 if (!s)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_SPF: /* exactly the same as TXT */
         case DNS_TYPE_TXT:
-                t = strv_join_quoted(rr->txt.strings);
+                t = format_txt(rr->txt.items);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 s = strjoin(k, " ", t, NULL);
                 if (!s)
-                        return -ENOMEM;
-
+                        return NULL;
                 break;
 
         case DNS_TYPE_A: {
@@ -657,22 +876,22 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
 
                 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
                 if (r < 0)
-                        return r;
+                        return NULL;
 
                 s = strjoin(k, " ", x, NULL);
                 if (!s)
-                        return -ENOMEM;
+                        return NULL;
                 break;
         }
 
         case DNS_TYPE_AAAA:
                 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
                 if (r < 0)
-                        return r;
+                        return NULL;
 
                 s = strjoin(k, " ", t, NULL);
                 if (!s)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_SOA:
@@ -686,7 +905,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->soa.expire,
                              rr->soa.minimum);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_MX:
@@ -695,7 +914,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->mx.priority,
                              rr->mx.exchange);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_LOC:
@@ -708,17 +927,17 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                                     rr->loc.horiz_pre,
                                     rr->loc.vert_pre);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 s = strjoin(k, " ", t, NULL);
                 if (!s)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_DS:
                 t = hexmem(rr->ds.digest, rr->ds.digest_size);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 r = asprintf(&s, "%s %u %u %u %s",
                              k,
@@ -727,13 +946,13 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->ds.digest_type,
                              t);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_SSHFP:
                 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 r = asprintf(&s, "%s %u %u %s",
                              k,
@@ -741,80 +960,113 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              rr->sshfp.fptype,
                              t);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_DNSKEY: {
-                const char *alg;
+                _cleanup_free_ char *alg = NULL;
+                char *ss;
+                int n, n1;
+                uint16_t key_tag;
 
-                alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
+                key_tag = dnssec_keytag(rr, true);
 
-                t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
-                if (!t)
-                        return -ENOMEM;
+                r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
+                if (r < 0)
+                        return NULL;
 
-                r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
+                r = asprintf(&s, "%s %n%u %u %s %n",
                              k,
-                             dnskey_to_flags(rr),
-                             alg ? -1 : 0, alg,
-                             alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
-                             t);
+                             &n1,
+                             rr->dnskey.flags,
+                             rr->dnskey.protocol,
+                             alg,
+                             &n);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
+
+                r = base64_append(&s, n,
+                                  rr->dnskey.key, rr->dnskey.key_size,
+                                  8, columns());
+                if (r < 0)
+                        return NULL;
+
+                r = asprintf(&ss, "%s\n"
+                             "%*s-- Flags:%s%s%s\n"
+                             "%*s-- Key tag: %u",
+                             s,
+                             n1, "",
+                             rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
+                             rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
+                             rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
+                             n1, "",
+                             key_tag);
+                if (r < 0)
+                        return NULL;
+                free(s);
+                s = ss;
+
                 break;
         }
 
         case DNS_TYPE_RRSIG: {
-                const char *type, *alg;
+                _cleanup_free_ char *alg = NULL;
                 char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
+                const char *type;
+                int n;
 
                 type = dns_type_to_string(rr->rrsig.type_covered);
-                alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
 
-                t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
-                if (!t)
-                        return -ENOMEM;
+                r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
+                if (r < 0)
+                        return NULL;
 
                 r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
                 if (r < 0)
-                        return r;
+                        return NULL;
 
                 r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
                 if (r < 0)
-                        return r;
+                        return NULL;
 
                 /* TYPE?? follows
                  * http://tools.ietf.org/html/rfc3597#section-5 */
 
-                r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
+                r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
                              k,
                              type ?: "TYPE",
                              type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
-                             alg ? -1 : 0, alg,
-                             alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
+                             alg,
                              rr->rrsig.labels,
                              rr->rrsig.original_ttl,
                              expiration,
                              inception,
                              rr->rrsig.key_tag,
                              rr->rrsig.signer,
-                             t);
+                             &n);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
+
+                r = base64_append(&s, n,
+                                  rr->rrsig.signature, rr->rrsig.signature_size,
+                                  8, columns());
+                if (r < 0)
+                        return NULL;
+
                 break;
         }
 
         case DNS_TYPE_NSEC:
                 t = format_types(rr->nsec.types);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 r = asprintf(&s, "%s %s %s",
                              k,
                              rr->nsec.next_domain_name,
                              t);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
 
         case DNS_TYPE_NSEC3: {
@@ -823,16 +1075,16 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                 if (rr->nsec3.salt_size > 0) {
                         salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
                         if (!salt)
-                                return -ENOMEM;
+                                return NULL;
                 }
 
                 hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
                 if (!hash)
-                        return -ENOMEM;
+                        return NULL;
 
                 t = format_types(rr->nsec3.types);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
                 r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
                              k,
@@ -843,50 +1095,427 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
                              hash,
                              t);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
+
+                break;
+        }
+
+        case DNS_TYPE_TLSA: {
+                const char *cert_usage, *selector, *matching_type;
+                char *ss;
+                int n;
+
+                cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
+                selector = tlsa_selector_to_string(rr->tlsa.selector);
+                matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
+
+                r = asprintf(&s, "%s %u %u %u %n",
+                             k,
+                             rr->tlsa.cert_usage,
+                             rr->tlsa.selector,
+                             rr->tlsa.matching_type,
+                             &n);
+                if (r < 0)
+                        return NULL;
+
+                r = base64_append(&s, n,
+                                  rr->tlsa.data, rr->tlsa.data_size,
+                                  8, columns());
+                if (r < 0)
+                        return NULL;
+
+                r = asprintf(&ss, "%s\n"
+                             "%*s-- Cert. usage: %s\n"
+                             "%*s-- Selector: %s\n"
+                             "%*s-- Matching type: %s",
+                             s,
+                             n - 6, "", cert_usage,
+                             n - 6, "", selector,
+                             n - 6, "", matching_type);
+                if (r < 0)
+                        return NULL;
+                free(s);
+                s = ss;
+
+                break;
+        }
+
+        case DNS_TYPE_OPENPGPKEY: {
+                int n;
 
+                r = asprintf(&s, "%s %n",
+                             k,
+                             &n);
+                if (r < 0)
+                        return NULL;
+
+                r = base64_append(&s, n,
+                                  rr->generic.data, rr->generic.data_size,
+                                  8, columns());
+                if (r < 0)
+                        return NULL;
                 break;
         }
 
         default:
-                t = hexmem(rr->generic.data, rr->generic.size);
+                t = hexmem(rr->generic.data, rr->generic.data_size);
                 if (!t)
-                        return -ENOMEM;
+                        return NULL;
 
-                r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
+                /* Format as documented in RFC 3597, Section 5 */
+                r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
                 if (r < 0)
-                        return -ENOMEM;
+                        return NULL;
                 break;
         }
 
-        *ret = s;
+        rr->to_string = s;
+        return s;
+}
+
+int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
+
+        DnsPacket packet = {
+                .n_ref = 1,
+                .protocol = DNS_PROTOCOL_DNS,
+                .on_stack = true,
+                .refuse_compression = true,
+                .canonical_form = canonical,
+        };
+
+        size_t start, rds;
+        int r;
+
+        assert(rr);
+
+        /* Generates the RR in wire-format, optionally in the
+         * canonical form as discussed in the DNSSEC RFC 4034, Section
+         * 6.2. We allocate a throw-away DnsPacket object on the stack
+         * here, because we need some book-keeping for memory
+         * management, and can reuse the DnsPacket serializer, that
+         * can generate the canonical form, too, but also knows label
+         * compression and suchlike. */
+
+        if (rr->wire_format && rr->wire_format_canonical == canonical)
+                return 0;
+
+        r = dns_packet_append_rr(&packet, rr, &start, &rds);
+        if (r < 0)
+                return r;
+
+        assert(start == 0);
+        assert(packet._data);
+
+        free(rr->wire_format);
+        rr->wire_format = packet._data;
+        rr->wire_format_size = packet.size;
+        rr->wire_format_rdata_offset = rds;
+        rr->wire_format_canonical = canonical;
+
+        packet._data = NULL;
+        dns_packet_unref(&packet);
+
         return 0;
 }
 
-const char *dns_class_to_string(uint16_t class) {
+int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
+        const char *n;
+        int r;
 
-        switch (class) {
+        assert(rr);
+        assert(ret);
 
-        case DNS_CLASS_IN:
-                return "IN";
+        /* Returns the RRset's signer, if it is known. */
 
-        case DNS_CLASS_ANY:
-                return "ANY";
-        }
+        if (rr->n_skip_labels_signer == (unsigned) -1)
+                return -ENODATA;
 
-        return NULL;
+        n = DNS_RESOURCE_KEY_NAME(rr->key);
+        r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EINVAL;
+
+        *ret = n;
+        return 0;
 }
 
-int dns_class_from_string(const char *s, uint16_t *class) {
-        assert(s);
-        assert(class);
+int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
+        const char *n;
+        int r;
+
+        assert(rr);
+        assert(ret);
 
-        if (strcaseeq(s, "IN"))
-                *class = DNS_CLASS_IN;
-        else if (strcaseeq(s, "ANY"))
-                *class = DNS_CLASS_ANY;
-        else
+        /* Returns the RRset's synthesizing source, if it is known. */
+
+        if (rr->n_skip_labels_source == (unsigned) -1)
+                return -ENODATA;
+
+        n = DNS_RESOURCE_KEY_NAME(rr->key);
+        r = dns_name_skip(n, rr->n_skip_labels_source, &n);
+        if (r < 0)
+                return r;
+        if (r == 0)
                 return -EINVAL;
 
+        *ret = n;
         return 0;
 }
+
+int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) {
+        const char *signer;
+        int r;
+
+        assert(rr);
+
+        r = dns_resource_record_signer(rr, &signer);
+        if (r < 0)
+                return r;
+
+        return dns_name_equal(zone, signer);
+}
+
+int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
+        int r;
+
+        assert(rr);
+
+        /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
+
+        if (rr->n_skip_labels_source == (unsigned) -1)
+                return -ENODATA;
+
+        if (rr->n_skip_labels_source == 0)
+                return 0;
+
+        if (rr->n_skip_labels_source > 1)
+                return 1;
+
+        r = dns_name_startswith(DNS_RESOURCE_KEY_NAME(rr->key), "*");
+        if (r < 0)
+                return r;
+
+        return !r;
+}
+
+static void dns_resource_record_hash_func(const void *i, struct siphash *state) {
+        const DnsResourceRecord *rr = i;
+
+        assert(rr);
+
+        dns_resource_key_hash_func(rr->key, state);
+
+        switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
+
+        case DNS_TYPE_SRV:
+                siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
+                siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state);
+                siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state);
+                dns_name_hash_func(rr->srv.name, state);
+                break;
+
+        case DNS_TYPE_PTR:
+        case DNS_TYPE_NS:
+        case DNS_TYPE_CNAME:
+        case DNS_TYPE_DNAME:
+                dns_name_hash_func(rr->ptr.name, state);
+                break;
+
+        case DNS_TYPE_HINFO:
+                string_hash_func(rr->hinfo.cpu, state);
+                string_hash_func(rr->hinfo.os, state);
+                break;
+
+        case DNS_TYPE_TXT:
+        case DNS_TYPE_SPF: {
+                DnsTxtItem *j;
+
+                LIST_FOREACH(items, j, rr->txt.items) {
+                        siphash24_compress(j->data, j->length, state);
+
+                        /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
+                         * followed by "". */
+                        siphash24_compress_byte(0, state);
+                }
+                break;
+        }
+
+        case DNS_TYPE_A:
+                siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state);
+                break;
+
+        case DNS_TYPE_AAAA:
+                siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state);
+                break;
+
+        case DNS_TYPE_SOA:
+                dns_name_hash_func(rr->soa.mname, state);
+                dns_name_hash_func(rr->soa.rname, state);
+                siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state);
+                siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state);
+                siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state);
+                siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state);
+                siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state);
+                break;
+
+        case DNS_TYPE_MX:
+                siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state);
+                dns_name_hash_func(rr->mx.exchange, state);
+                break;
+
+        case DNS_TYPE_LOC:
+                siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state);
+                siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state);
+                siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state);
+                siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state);
+                siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state);
+                siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state);
+                siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state);
+                break;
+
+        case DNS_TYPE_SSHFP:
+                siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
+                siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
+                siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
+                break;
+
+        case DNS_TYPE_DNSKEY:
+                siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
+                siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
+                siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
+                siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
+                break;
+
+        case DNS_TYPE_RRSIG:
+                siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state);
+                siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state);
+                siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state);
+                siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state);
+                siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state);
+                siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
+                siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
+                dns_name_hash_func(rr->rrsig.signer, state);
+                siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
+                break;
+
+        case DNS_TYPE_NSEC:
+                dns_name_hash_func(rr->nsec.next_domain_name, state);
+                /* FIXME: we leave out the type bitmap here. Hash
+                 * would be better if we'd take it into account
+                 * too. */
+                break;
+
+        case DNS_TYPE_DS:
+                siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
+                siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
+                siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
+                siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
+                break;
+
+        case DNS_TYPE_NSEC3:
+                siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
+                siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
+                siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
+                siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
+                siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
+                /* FIXME: We leave the bitmaps out */
+                break;
+
+        case DNS_TYPE_TLSA:
+                siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
+                siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
+                siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
+                siphash24_compress(&rr->tlsa.data, rr->tlsa.data_size, state);
+                break;
+
+        case DNS_TYPE_OPENPGPKEY:
+        default:
+                siphash24_compress(rr->generic.data, rr->generic.data_size, state);
+                break;
+        }
+}
+
+static int dns_resource_record_compare_func(const void *a, const void *b) {
+        const DnsResourceRecord *x = a, *y = b;
+        int ret;
+
+        ret = dns_resource_key_compare_func(x->key, y->key);
+        if (ret != 0)
+                return ret;
+
+        if (dns_resource_record_equal(x, y))
+                return 0;
+
+        /* This is a bit dirty, we don't implement proper ordering, but
+         * the hashtable doesn't need ordering anyway, hence we don't
+         * care. */
+        return x < y ? -1 : 1;
+}
+
+const struct hash_ops dns_resource_record_hash_ops = {
+        .hash = dns_resource_record_hash_func,
+        .compare = dns_resource_record_compare_func,
+};
+
+DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
+        DnsTxtItem *n;
+
+        if (!i)
+                return NULL;
+
+        n = i->items_next;
+
+        free(i);
+        return dns_txt_item_free_all(n);
+}
+
+bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
+
+        if (a == b)
+                return true;
+
+        if (!a != !b)
+                return false;
+
+        if (!a)
+                return true;
+
+        if (a->length != b->length)
+                return false;
+
+        if (memcmp(a->data, b->data, a->length) != 0)
+                return false;
+
+        return dns_txt_item_equal(a->items_next, b->items_next);
+}
+
+static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
+        /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
+        [DNSSEC_ALGORITHM_RSAMD5]             = "RSAMD5",
+        [DNSSEC_ALGORITHM_DH]                 = "DH",
+        [DNSSEC_ALGORITHM_DSA]                = "DSA",
+        [DNSSEC_ALGORITHM_ECC]                = "ECC",
+        [DNSSEC_ALGORITHM_RSASHA1]            = "RSASHA1",
+        [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1]     = "DSA-NSEC3-SHA1",
+        [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
+        [DNSSEC_ALGORITHM_RSASHA256]          = "RSASHA256",
+        [DNSSEC_ALGORITHM_RSASHA512]          = "RSASHA512",
+        [DNSSEC_ALGORITHM_ECC_GOST]           = "ECC-GOST",
+        [DNSSEC_ALGORITHM_ECDSAP256SHA256]    = "ECDSAP256SHA256",
+        [DNSSEC_ALGORITHM_ECDSAP384SHA384]    = "ECDSAP384SHA384",
+        [DNSSEC_ALGORITHM_INDIRECT]           = "INDIRECT",
+        [DNSSEC_ALGORITHM_PRIVATEDNS]         = "PRIVATEDNS",
+        [DNSSEC_ALGORITHM_PRIVATEOID]         = "PRIVATEOID",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
+
+static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
+        /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
+        [DNSSEC_DIGEST_SHA1] = "SHA-1",
+        [DNSSEC_DIGEST_SHA256] = "SHA-256",
+        [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
+        [DNSSEC_DIGEST_SHA384] = "SHA-384",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);
index 9e2207c0aac128992cd6ec00664563f81fd5f21c..2e0dfbaba3d4b6cfd5709c6a07cb4c46ae18a67b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include <netinet/in.h>
 
 #include "bitmap.h"
+#include "dns-type.h"
 #include "hashmap.h"
 #include "in-addr-util.h"
-#include "dns-type.h"
+#include "list.h"
 
 typedef struct DnsResourceKey DnsResourceKey;
 typedef struct DnsResourceRecord DnsResourceRecord;
+typedef struct DnsTxtItem DnsTxtItem;
+
+/* DNSKEY RR flags */
+#define DNSKEY_FLAG_SEP      (UINT16_C(1) << 0)
+#define DNSKEY_FLAG_REVOKE   (UINT16_C(1) << 7)
+#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8)
+
+/* mDNS RR flags */
+#define MDNS_RR_CACHE_FLUSH  (UINT16_C(1) << 15)
+
+/* DNSSEC algorithm identifiers, see
+ * http://tools.ietf.org/html/rfc4034#appendix-A.1 and
+ * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
+enum {
+        DNSSEC_ALGORITHM_RSAMD5 = 1,
+        DNSSEC_ALGORITHM_DH,
+        DNSSEC_ALGORITHM_DSA,
+        DNSSEC_ALGORITHM_ECC,
+        DNSSEC_ALGORITHM_RSASHA1,
+        DNSSEC_ALGORITHM_DSA_NSEC3_SHA1,
+        DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
+        DNSSEC_ALGORITHM_RSASHA256 = 8,        /* RFC 5702 */
+        DNSSEC_ALGORITHM_RSASHA512 = 10,       /* RFC 5702 */
+        DNSSEC_ALGORITHM_ECC_GOST = 12,        /* RFC 5933 */
+        DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */
+        DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */
+        DNSSEC_ALGORITHM_INDIRECT = 252,
+        DNSSEC_ALGORITHM_PRIVATEDNS,
+        DNSSEC_ALGORITHM_PRIVATEOID,
+        _DNSSEC_ALGORITHM_MAX_DEFINED
+};
+
+/* DNSSEC digest identifiers, see
+ * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
+enum {
+        DNSSEC_DIGEST_SHA1 = 1,
+        DNSSEC_DIGEST_SHA256 = 2,              /* RFC 4509 */
+        DNSSEC_DIGEST_GOST_R_34_11_94 = 3,     /* RFC 5933 */
+        DNSSEC_DIGEST_SHA384 = 4,              /* RFC 6605 */
+        _DNSSEC_DIGEST_MAX_DEFINED
+};
 
-/* DNS record classes, see RFC 1035 */
+/* DNSSEC NSEC3 hash algorithms, see
+ * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
 enum {
-        DNS_CLASS_IN   = 0x01,
-        DNS_CLASS_ANY  = 0xFF,
-        _DNS_CLASS_MAX,
-        _DNS_CLASS_INVALID = -1
+        NSEC3_ALGORITHM_SHA1 = 1,
+        _NSEC3_ALGORITHM_MAX_DEFINED
 };
 
 struct DnsResourceKey {
-        unsigned n_ref;
+        unsigned n_ref; /* (unsigned -1) for const keys, see below */
         uint16_t class, type;
         char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */
 };
 
+/* Creates a temporary resource key. This is only useful to quickly
+ * look up something, without allocating a full DnsResourceKey object
+ * for it. Note that it is not OK to take references to this kind of
+ * resource key object. */
+#define DNS_RESOURCE_KEY_CONST(c, t, n)                 \
+        ((DnsResourceKey) {                             \
+                .n_ref = (unsigned) -1,                 \
+                .class = c,                             \
+                .type = t,                              \
+                ._name = (char*) n,                     \
+        })
+
+
+struct DnsTxtItem {
+        size_t length;
+        LIST_FIELDS(DnsTxtItem, items);
+        uint8_t data[];
+};
+
 struct DnsResourceRecord {
         unsigned n_ref;
         DnsResourceKey *key;
+
+        char *to_string;
+
         uint32_t ttl;
-        bool unparseable;
+        usec_t expiry; /* RRSIG signature expiry */
+
+        /* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */
+        unsigned n_skip_labels_signer;
+        /* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */
+        unsigned n_skip_labels_source;
+
+        bool unparseable:1;
+
+        bool wire_format_canonical:1;
+        void *wire_format;
+        size_t wire_format_size;
+        size_t wire_format_rdata_offset;
+
         union {
                 struct {
                         void *data;
-                        size_t size;
-                } generic;
+                        size_t data_size;
+                } generic, opt;
 
                 struct {
                         uint16_t priority;
@@ -73,7 +147,7 @@ struct DnsResourceRecord {
                 } hinfo;
 
                 struct {
-                        char **strings;
+                        DnsTxtItem *items;
                 } txt, spf;
 
                 struct {
@@ -99,6 +173,7 @@ struct DnsResourceRecord {
                         char *exchange;
                 } mx;
 
+                /* https://tools.ietf.org/html/rfc1876 */
                 struct {
                         uint8_t version;
                         uint8_t size;
@@ -109,14 +184,6 @@ struct DnsResourceRecord {
                         uint32_t altitude;
                 } loc;
 
-                struct {
-                        uint16_t key_tag;
-                        uint8_t algorithm;
-                        uint8_t digest_type;
-                        void *digest;
-                        size_t digest_size;
-                } ds;
-
                 /* https://tools.ietf.org/html/rfc4255#section-3.1 */
                 struct {
                         uint8_t algorithm;
@@ -127,8 +194,8 @@ struct DnsResourceRecord {
 
                 /* http://tools.ietf.org/html/rfc4034#section-2.1 */
                 struct {
-                        bool zone_key_flag:1;
-                        bool sep_flag:1;
+                        uint16_t flags;
+                        uint8_t protocol;
                         uint8_t algorithm;
                         void* key;
                         size_t key_size;
@@ -148,11 +215,21 @@ struct DnsResourceRecord {
                         size_t signature_size;
                 } rrsig;
 
+                /* https://tools.ietf.org/html/rfc4034#section-4.1 */
                 struct {
                         char *next_domain_name;
                         Bitmap *types;
                 } nsec;
 
+                /* https://tools.ietf.org/html/rfc4034#section-5.1 */
+                struct {
+                        uint16_t key_tag;
+                        uint8_t algorithm;
+                        uint8_t digest_type;
+                        void *digest;
+                        size_t digest_size;
+                } ds;
+
                 struct {
                         uint8_t algorithm;
                         uint8_t flags;
@@ -163,11 +240,20 @@ struct DnsResourceRecord {
                         size_t next_hashed_name_size;
                         Bitmap *types;
                 } nsec3;
+
+                /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
+                struct {
+                        uint8_t cert_usage;
+                        uint8_t selector;
+                        uint8_t matching_type;
+                        void *data;
+                        size_t data_size;
+                } tlsa;
         };
 };
 
 static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) {
-        if (_unlikely_(!key))
+        if (!key)
                 return NULL;
 
         if (key->_name)
@@ -176,18 +262,47 @@ static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) {
         return (char*) key + sizeof(DnsResourceKey);
 }
 
+static inline const void* DNS_RESOURCE_RECORD_RDATA(DnsResourceRecord *rr) {
+        if (!rr)
+                return NULL;
+
+        if (!rr->wire_format)
+                return NULL;
+
+        assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
+        return (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset;
+}
+
+static inline size_t DNS_RESOURCE_RECORD_RDATA_SIZE(DnsResourceRecord *rr) {
+        if (!rr)
+                return 0;
+        if (!rr->wire_format)
+                return 0;
+
+        assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
+        return rr->wire_format_size - rr->wire_format_rdata_offset;
+}
+
 DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name);
-DnsResourceKey* dns_resource_key_new_cname(const DnsResourceKey *key);
 DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname);
+int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name);
 DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
 DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
 DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
+bool dns_resource_key_is_address(const DnsResourceKey *key);
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
-int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr);
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr);
+int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain);
+int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain);
+int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa);
 int dns_resource_key_to_string(const DnsResourceKey *key, char **ret);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
 
+static inline bool dns_key_is_shared(const DnsResourceKey *key) {
+        return IN_SET(key->type, DNS_TYPE_PTR);
+}
+
+bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b);
+
 DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key);
 DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name);
 DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr);
@@ -195,10 +310,24 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
 int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
 int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret);
+const char* dns_resource_record_to_string(DnsResourceRecord *rr);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
 
-const char *dns_class_to_string(uint16_t type);
-int dns_class_from_string(const char *name, uint16_t *class);
+int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical);
+
+int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret);
+int dns_resource_record_source(DnsResourceRecord *rr, const char **ret);
+int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone);
+int dns_resource_record_is_synthetic(DnsResourceRecord *rr);
+
+DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
+bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
 
 extern const struct hash_ops dns_resource_key_hash_ops;
+extern const struct hash_ops dns_resource_record_hash_ops;
+
+int dnssec_algorithm_to_string_alloc(int i, char **ret);
+int dnssec_algorithm_from_string(const char *s) _pure_;
+
+int dnssec_digest_to_string_alloc(int i, char **ret);
+int dnssec_digest_from_string(const char *s) _pure_;
index b15370b017b8e9d5c06c74ddbf369608364c7233..a406872a38d4182deaae1ad972e4e9ca99d4386e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,6 +28,7 @@
 #include "random-util.h"
 #include "resolved-dns-scope.h"
 #include "resolved-llmnr.h"
+#include "resolved-mdns.h"
 #include "socket-util.h"
 #include "strv.h"
 
@@ -56,9 +55,24 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
         s->family = family;
         s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
 
+        if (protocol == DNS_PROTOCOL_DNS) {
+                /* Copy DNSSEC mode from the link if it is set there,
+                 * otherwise take the manager's DNSSEC mode. Note that
+                 * we copy this only at scope creation time, and do
+                 * not update it from the on, even if the setting
+                 * changes. */
+
+                if (l)
+                        s->dnssec_mode = link_get_dnssec_mode(l);
+                else
+                        s->dnssec_mode = manager_get_dnssec_mode(m);
+        } else
+                s->dnssec_mode = DNSSEC_NO;
+
         LIST_PREPEND(scopes, m->dns_scopes, s);
 
         dns_scope_llmnr_membership(s, true);
+        dns_scope_mdns_membership(s, true);
 
         log_debug("New scope on link %s, protocol %s, family %s", l ? l->name : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family));
 
@@ -69,29 +83,40 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
         return 0;
 }
 
-DnsScope* dns_scope_free(DnsScope *s) {
-        DnsTransaction *t;
-        DnsResourceRecord *rr;
-
-        if (!s)
-                return NULL;
-
-        log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
+static void dns_scope_abort_transactions(DnsScope *s) {
+        assert(s);
 
-        dns_scope_llmnr_membership(s, false);
+        while (s->transactions) {
+                DnsTransaction *t = s->transactions;
 
-        while ((t = hashmap_steal_first(s->transactions))) {
                 /* Abort the transaction, but make sure it is not
                  * freed while we still look at it */
 
                 t->block_gc++;
-                dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
+                if (DNS_TRANSACTION_IS_LIVE(t->state))
+                        dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
                 t->block_gc--;
 
                 dns_transaction_free(t);
         }
+}
 
-        hashmap_free(s->transactions);
+DnsScope* dns_scope_free(DnsScope *s) {
+        DnsResourceRecord *rr;
+
+        if (!s)
+                return NULL;
+
+        log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
+
+        dns_scope_llmnr_membership(s, false);
+        dns_scope_mdns_membership(s, false);
+        dns_scope_abort_transactions(s);
+
+        while (s->query_candidates)
+                dns_query_candidate_free(s->query_candidates);
+
+        hashmap_free(s->transactions_by_key);
 
         while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
                 dns_resource_record_unref(rr);
@@ -103,7 +128,6 @@ DnsScope* dns_scope_free(DnsScope *s) {
         dns_zone_flush(&s->zone);
 
         LIST_REMOVE(scopes, s->manager->dns_scopes, s);
-        strv_free(s->domains);
         free(s);
 
         return NULL;
@@ -136,11 +160,11 @@ void dns_scope_next_dns_server(DnsScope *s) {
 void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
         assert(s);
 
-        if (rtt > s->max_rtt) {
-                s->max_rtt = rtt;
-                s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2),
-                                        MULTICAST_RESEND_TIMEOUT_MAX_USEC);
-        }
+        if (rtt <= s->max_rtt)
+                return;
+
+        s->max_rtt = rtt;
+        s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
 }
 
 void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
@@ -150,17 +174,15 @@ void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
                 s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
 }
 
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
+static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
         union in_addr_union addr;
         int ifindex = 0, r;
         int family;
-        uint16_t port;
         uint32_t mtu;
 
         assert(s);
         assert(p);
         assert(p->protocol == s->protocol);
-        assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
 
         if (s->link) {
                 mtu = s->link->mtu;
@@ -169,7 +191,10 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
                 mtu = manager_find_mtu(s->manager);
 
         switch (s->protocol) {
+
         case DNS_PROTOCOL_DNS:
+                assert(fd >= 0);
+
                 if (DNS_PACKET_QDCOUNT(p) > 1)
                         return -EOPNOTSUPP;
 
@@ -186,6 +211,8 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
                 break;
 
         case DNS_PROTOCOL_LLMNR:
+                assert(fd < 0);
+
                 if (DNS_PACKET_QDCOUNT(p) > 1)
                         return -EOPNOTSUPP;
 
@@ -193,7 +220,6 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
                         return -EBUSY;
 
                 family = s->family;
-                port = LLMNR_PORT;
 
                 if (family == AF_INET) {
                         addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
@@ -206,7 +232,32 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
                 if (fd < 0)
                         return fd;
 
-                r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
+                r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p);
+                if (r < 0)
+                        return r;
+
+                break;
+
+        case DNS_PROTOCOL_MDNS:
+                assert(fd < 0);
+
+                if (!ratelimit_test(&s->ratelimit))
+                        return -EBUSY;
+
+                family = s->family;
+
+                if (family == AF_INET) {
+                        addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
+                        fd = manager_mdns_ipv4_fd(s->manager);
+                } else if (family == AF_INET6) {
+                        addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
+                        fd = manager_mdns_ipv6_fd(s->manager);
+                } else
+                        return -EAFNOSUPPORT;
+                if (fd < 0)
+                        return fd;
+
+                r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p);
                 if (r < 0)
                         return r;
 
@@ -219,8 +270,39 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
         return 1;
 }
 
-static int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
-        DnsServer *srv = NULL;
+int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) {
+        int r;
+
+        assert(s);
+        assert(p);
+        assert(p->protocol == s->protocol);
+        assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0));
+
+        do {
+                /* If there are multiple linked packets, set the TC bit in all but the last of them */
+                if (p->more) {
+                        assert(p->protocol == DNS_PROTOCOL_MDNS);
+                        dns_packet_set_flags(p, true, true);
+                }
+
+                r = dns_scope_emit_one(s, fd, p);
+                if (r < 0)
+                        return r;
+
+                p = p->more;
+        } while (p);
+
+        return 0;
+}
+
+static int dns_scope_socket(
+                DnsScope *s,
+                int type,
+                int family,
+                const union in_addr_union *address,
+                DnsServer *server,
+                uint16_t port) {
+
         _cleanup_close_ int fd = -1;
         union sockaddr_union sa = {};
         socklen_t salen;
@@ -228,26 +310,27 @@ static int dns_scope_socket(DnsScope *s, int type, int family, const union in_ad
         int ret, r;
 
         assert(s);
-        assert((family == AF_UNSPEC) == !address);
 
-        if (family == AF_UNSPEC) {
-                srv = dns_scope_get_dns_server(s);
-                if (!srv)
-                        return -ESRCH;
+        if (server) {
+                assert(family == AF_UNSPEC);
+                assert(!address);
 
-                sa.sa.sa_family = srv->family;
-                if (srv->family == AF_INET) {
+                sa.sa.sa_family = server->family;
+                if (server->family == AF_INET) {
                         sa.in.sin_port = htobe16(port);
-                        sa.in.sin_addr = srv->address.in;
+                        sa.in.sin_addr = server->address.in;
                         salen = sizeof(sa.in);
-                } else if (srv->family == AF_INET6) {
+                } else if (server->family == AF_INET6) {
                         sa.in6.sin6_port = htobe16(port);
-                        sa.in6.sin6_addr = srv->address.in6;
+                        sa.in6.sin6_addr = server->address.in6;
                         sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
                         salen = sizeof(sa.in6);
                 } else
                         return -EAFNOSUPPORT;
         } else {
+                assert(family != AF_UNSPEC);
+                assert(address);
+
                 sa.sa.sa_family = family;
 
                 if (family == AF_INET) {
@@ -305,36 +388,34 @@ static int dns_scope_socket(DnsScope *s, int type, int family, const union in_ad
         if (r < 0 && errno != EINPROGRESS)
                 return -errno;
 
-        if (server)
-                *server = srv;
-
         ret = fd;
         fd = -1;
 
         return ret;
 }
 
-int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server) {
-        return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, 53, server);
+int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) {
+        return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port);
 }
 
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
-        return dns_scope_socket(s, SOCK_STREAM, family, address, port, server);
+int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port) {
+        return dns_scope_socket(s, SOCK_STREAM, family, address, server, port);
 }
 
 DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
-        char **i;
+        DnsSearchDomain *d;
 
         assert(s);
         assert(domain);
 
-        if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
-                return DNS_SCOPE_NO;
+        /* Checks if the specified domain is something to look up on
+         * this scope. Note that this accepts non-qualified hostnames,
+         * i.e. those without any search path prefixed yet. */
 
-        if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
+        if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
                 return DNS_SCOPE_NO;
 
-        if (dns_name_root(domain) != 0)
+        if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
                 return DNS_SCOPE_NO;
 
         /* Never resolve any loopback hostname or IP address via DNS,
@@ -345,15 +426,38 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
             dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
                 return DNS_SCOPE_NO;
 
-        STRV_FOREACH(i, s->domains)
-                if (dns_name_endswith(domain, *i) > 0)
+        /* Never respond to some of the domains listed in RFC6303 */
+        if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 ||
+            dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 ||
+            dns_name_equal(domain, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
+                return DNS_SCOPE_NO;
+
+        /* Never respond to some of the domains listed in RFC6761 */
+        if (dns_name_endswith(domain, "invalid") > 0)
+                return DNS_SCOPE_NO;
+
+        /* Always honour search domains for routing queries. Note that
+         * we return DNS_SCOPE_YES here, rather than just
+         * DNS_SCOPE_MAYBE, which means wildcard scopes won't be
+         * considered anymore. */
+        LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
+                if (dns_name_endswith(domain, d->name) > 0)
                         return DNS_SCOPE_YES;
 
         switch (s->protocol) {
+
         case DNS_PROTOCOL_DNS:
+
+                /* Exclude link-local IP ranges */
                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
-                    dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
-                    dns_name_single_label(domain) == 0)
+                    dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
+                    dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
+                    dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
+                    dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
+                    /* If networks use .local in their private setups, they are supposed to also add .local to their search
+                     * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
+                     * send such queries ordinary DNS servers. */
+                    dns_name_endswith(domain, "local") == 0)
                         return DNS_SCOPE_MAYBE;
 
                 return DNS_SCOPE_NO;
@@ -371,7 +475,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
         case DNS_PROTOCOL_LLMNR:
                 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
                     (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
-                    (dns_name_single_label(domain) > 0 && /* only resolve single label names via LLMNR */
+                    (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
                      !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
                      manager_is_own_hostname(s->manager, domain) <= 0))  /* never resolve the local hostname via LLMNR */
                         return DNS_SCOPE_MAYBE;
@@ -383,38 +487,56 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
         }
 }
 
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
+bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
+        int key_family;
+
         assert(s);
         assert(key);
 
-        if (s->protocol == DNS_PROTOCOL_DNS)
-                return true;
+        /* Check if it makes sense to resolve the specified key on
+         * this scope. Note that this call assumes as fully qualified
+         * name, i.e. the search suffixes already appended. */
+
+        if (key->class != DNS_CLASS_IN)
+                return false;
+
+        if (s->protocol == DNS_PROTOCOL_DNS) {
+
+                /* On classic DNS, looking up non-address RRs is always
+                 * fine. (Specifically, we want to permit looking up
+                 * DNSKEY and DS records on the root and top-level
+                 * domains.) */
+                if (!dns_resource_key_is_address(key))
+                        return true;
+
+                /* However, we refuse to look up A and AAAA RRs on the
+                 * root and single-label domains, under the assumption
+                 * that those should be resolved via LLMNR or search
+                 * path only, and should not be leaked onto the
+                 * internet. */
+                return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) ||
+                         dns_name_is_root(DNS_RESOURCE_KEY_NAME(key)));
+        }
 
         /* On mDNS and LLMNR, send A and AAAA queries only on the
          * respective scopes */
 
-        if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
-                return false;
-
-        if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
-                return false;
+        key_family = dns_type_to_af(key->type);
+        if (key_family < 0)
+                return true;
 
-        return true;
+        return key_family == s->family;
 }
 
-int dns_scope_llmnr_membership(DnsScope *s, bool b) {
+static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
         int fd;
 
         assert(s);
-
-        if (s->protocol != DNS_PROTOCOL_LLMNR)
-                return 0;
-
         assert(s->link);
 
         if (s->family == AF_INET) {
                 struct ip_mreqn mreqn = {
-                        .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
+                        .imr_multiaddr = in,
                         .imr_ifindex = s->link->ifindex,
                 };
 
@@ -433,7 +555,7 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
 
         } else if (s->family == AF_INET6) {
                 struct ipv6_mreq mreq = {
-                        .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
+                        .ipv6mr_multiaddr = in6,
                         .ipv6mr_interface = s->link->ifindex,
                 };
 
@@ -452,6 +574,22 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
         return 0;
 }
 
+int dns_scope_llmnr_membership(DnsScope *s, bool b) {
+
+        if (s->protocol != DNS_PROTOCOL_LLMNR)
+                return 0;
+
+        return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
+}
+
+int dns_scope_mdns_membership(DnsScope *s, bool b) {
+
+        if (s->protocol != DNS_PROTOCOL_MDNS)
+                return 0;
+
+        return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
+}
+
 static int dns_scope_make_reply_packet(
                 DnsScope *s,
                 uint16_t id,
@@ -502,7 +640,7 @@ static int dns_scope_make_reply_packet(
 
         if (answer) {
                 for (i = 0; i < answer->n_rrs; i++) {
-                        r = dns_packet_append_rr(p, answer->items[i].rr, NULL);
+                        r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
                         if (r < 0)
                                 return r;
                 }
@@ -512,7 +650,7 @@ static int dns_scope_make_reply_packet(
 
         if (soa) {
                 for (i = 0; i < soa->n_rrs; i++) {
-                        r = dns_packet_append_rr(p, soa->items[i].rr, NULL);
+                        r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
                         if (r < 0)
                                 return r;
                 }
@@ -543,6 +681,7 @@ static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+        DnsResourceKey *key = NULL;
         bool tentative = false;
         int r, fd;
 
@@ -576,7 +715,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
                 return;
         }
 
-        r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
+        assert(p->question->n_keys == 1);
+        key = p->question->keys[0];
+
+        r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
         if (r < 0) {
                 log_debug_errno(r, "Failed to lookup key: %m");
                 return;
@@ -634,15 +776,15 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key,
 
         /* Try to find an ongoing transaction that is a equal to the
          * specified question */
-        t = hashmap_get(scope->transactions, key);
+        t = hashmap_get(scope->transactions_by_key, key);
         if (!t)
                 return NULL;
 
         /* Refuse reusing transactions that completed based on cached
          * data instead of a real packet, if that's requested. */
         if (!cache_ok &&
-            IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
-            !t->received)
+            IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
+            t->answer_source != DNS_TRANSACTION_NETWORK)
                 return NULL;
 
         return t;
@@ -674,7 +816,11 @@ static int dns_scope_make_conflict_packet(
                                                               0 /* (ad) */,
                                                               0 /* (cd) */,
                                                               0));
-        random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
+
+        /* For mDNS, the transaction ID should always be 0 */
+        if (s->protocol != DNS_PROTOCOL_MDNS)
+                random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
+
         DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
         DNS_PACKET_HEADER(p)->arcount = htobe16(1);
 
@@ -682,7 +828,7 @@ static int dns_scope_make_conflict_packet(
         if (r < 0)
                 return r;
 
-        r = dns_packet_append_rr(p, rr, NULL);
+        r = dns_packet_append_rr(p, rr, NULL, NULL);
         if (r < 0)
                 return r;
 
@@ -715,7 +861,7 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata
                         return 0;
                 }
 
-                r = dns_scope_emit(scope, -1, p);
+                r = dns_scope_emit_udp(scope, -1, p);
                 if (r < 0)
                         log_debug_errno(r, "Failed to send conflict packet: %m");
         }
@@ -764,6 +910,8 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
         if (r < 0)
                 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
 
+        (void) sd_event_source_set_description(scope->conflict_event_source, "scope-conflict");
+
         return 0;
 }
 
@@ -846,3 +994,35 @@ void dns_scope_dump(DnsScope *s, FILE *f) {
                 dns_cache_dump(&s->cache, f);
         }
 }
+
+DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
+        assert(s);
+
+        if (s->protocol != DNS_PROTOCOL_DNS)
+                return NULL;
+
+        if (s->link)
+                return s->link->search_domains;
+
+        return s->manager->search_domains;
+}
+
+bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
+        assert(s);
+
+        if (s->protocol != DNS_PROTOCOL_DNS)
+                return false;
+
+        return dns_name_is_single_label(name);
+}
+
+bool dns_scope_network_good(DnsScope *s) {
+        /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes
+         * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global
+         * DNS scope we check whether there are any links that are up and have an address. */
+
+        if (s->link)
+                return true;
+
+        return manager_routable(s->manager, AF_UNSPEC);
+}
index b75f212897cdaf913e2db617a32750c81807168f..291e5817d081ce7df53c023f7376ac0ec1c09327 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 typedef struct DnsScope DnsScope;
 
-#include "resolved-dns-server.h"
-#include "resolved-dns-packet.h"
 #include "resolved-dns-cache.h"
+#include "resolved-dns-dnssec.h"
+#include "resolved-dns-packet.h"
+#include "resolved-dns-server.h"
 #include "resolved-dns-zone.h"
 #include "resolved-link.h"
 
@@ -44,11 +43,10 @@ struct DnsScope {
 
         DnsProtocol protocol;
         int family;
+        DnssecMode dnssec_mode;
 
         Link *link;
 
-        char **domains;
-
         DnsCache cache;
         DnsZone zone;
 
@@ -60,7 +58,18 @@ struct DnsScope {
         usec_t resend_timeout;
         usec_t max_rtt;
 
-        Hashmap *transactions;
+        LIST_HEAD(DnsQueryCandidate, query_candidates);
+
+        /* Note that we keep track of ongoing transactions in two
+         * ways: once in a hashmap, indexed by the rr key, and once in
+         * a linked list. We use the hashmap to quickly find
+         * transactions we can reuse for a key. But note that there
+         * might be multiple transactions for the same key (because
+         * the zone probing can't reuse a transaction answered from
+         * the zone or the cache), and the hashmap only tracks the
+         * most recent entry. */
+        Hashmap *transactions_by_key;
+        LIST_HEAD(DnsTransaction, transactions);
 
         LIST_FIELDS(DnsScope, scopes);
 };
@@ -71,17 +80,18 @@ DnsScope* dns_scope_free(DnsScope *s);
 void dns_scope_packet_received(DnsScope *s, usec_t rtt);
 void dns_scope_packet_lost(DnsScope *s, usec_t usec);
 
-int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p);
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);
-int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server);
+int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p);
+int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port);
+int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port);
 
 DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
+bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key);
 
 DnsServer *dns_scope_get_dns_server(DnsScope *s);
 void dns_scope_next_dns_server(DnsScope *s);
 
 int dns_scope_llmnr_membership(DnsScope *s, bool b);
+int dns_scope_mdns_membership(DnsScope *s, bool b);
 
 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p);
 
@@ -91,3 +101,9 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr);
 void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);
 
 void dns_scope_dump(DnsScope *s, FILE *f);
+
+DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
+
+bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name);
+
+bool dns_scope_network_good(DnsScope *s);
diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c
new file mode 100644 (file)
index 0000000..7324710
--- /dev/null
@@ -0,0 +1,227 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "dns-domain.h"
+#include "resolved-dns-search-domain.h"
+
+int dns_search_domain_new(
+                Manager *m,
+                DnsSearchDomain **ret,
+                DnsSearchDomainType type,
+                Link *l,
+                const char *name) {
+
+        _cleanup_free_ char *normalized = NULL;
+        DnsSearchDomain *d;
+        int r;
+
+        assert(m);
+        assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
+        assert(name);
+
+        r = dns_name_normalize(name, &normalized);
+        if (r < 0)
+                return r;
+
+        if (l) {
+                if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
+                        return -E2BIG;
+        } else {
+                if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX)
+                        return -E2BIG;
+        }
+
+        d = new0(DnsSearchDomain, 1);
+        if (!d)
+                return -ENOMEM;
+
+        d->n_ref = 1;
+        d->manager = m;
+        d->type = type;
+        d->name = normalized;
+        normalized = NULL;
+
+        switch (type) {
+
+        case DNS_SEARCH_DOMAIN_LINK:
+                d->link = l;
+                LIST_APPEND(domains, l->search_domains, d);
+                l->n_search_domains++;
+                break;
+
+        case DNS_SERVER_SYSTEM:
+                LIST_APPEND(domains, m->search_domains, d);
+                m->n_search_domains++;
+                break;
+
+        default:
+                assert_not_reached("Unknown search domain type");
+        }
+
+        d->linked = true;
+
+        if (ret)
+                *ret = d;
+
+        return 0;
+}
+
+DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d) {
+        if (!d)
+                return NULL;
+
+        assert(d->n_ref > 0);
+        d->n_ref++;
+
+        return d;
+}
+
+DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) {
+        if (!d)
+                return NULL;
+
+        assert(d->n_ref > 0);
+        d->n_ref--;
+
+        if (d->n_ref > 0)
+                return NULL;
+
+        free(d->name);
+        free(d);
+
+        return NULL;
+}
+
+void dns_search_domain_unlink(DnsSearchDomain *d) {
+        assert(d);
+        assert(d->manager);
+
+        if (!d->linked)
+                return;
+
+        switch (d->type) {
+
+        case DNS_SEARCH_DOMAIN_LINK:
+                assert(d->link);
+                assert(d->link->n_search_domains > 0);
+                LIST_REMOVE(domains, d->link->search_domains, d);
+                d->link->n_search_domains--;
+                break;
+
+        case DNS_SEARCH_DOMAIN_SYSTEM:
+                assert(d->manager->n_search_domains > 0);
+                LIST_REMOVE(domains, d->manager->search_domains, d);
+                d->manager->n_search_domains--;
+                break;
+        }
+
+        d->linked = false;
+
+        dns_search_domain_unref(d);
+}
+
+void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) {
+        DnsSearchDomain *tail;
+
+        assert(d);
+
+        if (!d->marked)
+                return;
+
+        d->marked = false;
+
+        if (!d->linked || !d->domains_next)
+                return;
+
+        switch (d->type) {
+
+        case DNS_SEARCH_DOMAIN_LINK:
+                assert(d->link);
+                LIST_FIND_TAIL(domains, d, tail);
+                LIST_REMOVE(domains, d->link->search_domains, d);
+                LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d);
+                break;
+
+        case DNS_SEARCH_DOMAIN_SYSTEM:
+                LIST_FIND_TAIL(domains, d, tail);
+                LIST_REMOVE(domains, d->manager->search_domains, d);
+                LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
+                break;
+
+        default:
+                assert_not_reached("Unknown search domain type");
+        }
+}
+
+void dns_search_domain_unlink_all(DnsSearchDomain *first) {
+        DnsSearchDomain *next;
+
+        if (!first)
+                return;
+
+        next = first->domains_next;
+        dns_search_domain_unlink(first);
+
+        dns_search_domain_unlink_all(next);
+}
+
+void dns_search_domain_unlink_marked(DnsSearchDomain *first) {
+        DnsSearchDomain *next;
+
+        if (!first)
+                return;
+
+        next = first->domains_next;
+
+        if (first->marked)
+                dns_search_domain_unlink(first);
+
+        dns_search_domain_unlink_marked(next);
+}
+
+void dns_search_domain_mark_all(DnsSearchDomain *first) {
+        if (!first)
+                return;
+
+        first->marked = true;
+        dns_search_domain_mark_all(first->domains_next);
+}
+
+int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
+        DnsSearchDomain *d;
+        int r;
+
+        assert(name);
+        assert(ret);
+
+        LIST_FOREACH(domains, d, first) {
+
+                r = dns_name_equal(name, d->name);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        *ret = d;
+                        return 1;
+                }
+        }
+
+        *ret = NULL;
+        return 0;
+}
diff --git a/src/resolve/resolved-dns-search-domain.h b/src/resolve/resolved-dns-search-domain.h
new file mode 100644 (file)
index 0000000..eaacef4
--- /dev/null
@@ -0,0 +1,74 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+
+typedef struct DnsSearchDomain DnsSearchDomain;
+
+typedef enum DnsSearchDomainType {
+        DNS_SEARCH_DOMAIN_SYSTEM,
+        DNS_SEARCH_DOMAIN_LINK,
+} DnsSearchDomainType;
+
+#include "resolved-link.h"
+#include "resolved-manager.h"
+
+struct DnsSearchDomain {
+        Manager *manager;
+
+        unsigned n_ref;
+
+        DnsSearchDomainType type;
+        Link *link;
+
+        char *name;
+
+        bool marked:1;
+        bool route_only:1;
+
+        bool linked:1;
+        LIST_FIELDS(DnsSearchDomain, domains);
+};
+
+int dns_search_domain_new(
+                Manager *m,
+                DnsSearchDomain **ret,
+                DnsSearchDomainType type,
+                Link *link,
+                const char *name);
+
+DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d);
+DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d);
+
+void dns_search_domain_unlink(DnsSearchDomain *d);
+void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d);
+
+void dns_search_domain_unlink_all(DnsSearchDomain *first);
+void dns_search_domain_unlink_marked(DnsSearchDomain *first);
+void dns_search_domain_mark_all(DnsSearchDomain *first);
+
+int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret);
+
+static inline const char* DNS_SEARCH_DOMAIN_NAME(DnsSearchDomain *d) {
+        return d ? d->name : NULL;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsSearchDomain*, dns_search_domain_unref);
index e803f635abda8835e93e0eba1638ac4383fc9756..27342a0e04ce5ad1a42763303368d6cccdb0a911 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sd-messages.h>
+
 #include "alloc-util.h"
 #include "resolved-dns-server.h"
+#include "resolved-resolv-conf.h"
 #include "siphash24.h"
+#include "string-table.h"
+#include "string-util.h"
 
 /* After how much time to repeat classic DNS requests */
 #define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
 #define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC)
 
+/* The amount of time to wait before retrying with a full feature set */
+#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
+#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
+
+/* The number of times we will attempt a certain feature set before degrading */
+#define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3
+
 int dns_server_new(
                 Manager *m,
                 DnsServer **ret,
@@ -35,36 +45,61 @@ int dns_server_new(
                 int family,
                 const union in_addr_union *in_addr) {
 
-        DnsServer *s, *tail;
+        DnsServer *s;
 
         assert(m);
         assert((type == DNS_SERVER_LINK) == !!l);
         assert(in_addr);
 
+        if (!IN_SET(family, AF_INET, AF_INET6))
+                return -EAFNOSUPPORT;
+
+        if (l) {
+                if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
+                        return -E2BIG;
+        } else {
+                if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
+                        return -E2BIG;
+        }
+
         s = new0(DnsServer, 1);
         if (!s)
                 return -ENOMEM;
 
         s->n_ref = 1;
+        s->manager = m;
+        s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
+        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
+        s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
+        s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
         s->type = type;
         s->family = family;
         s->address = *in_addr;
         s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
 
-        if (type == DNS_SERVER_LINK) {
-                LIST_FIND_TAIL(servers, l->dns_servers, tail);
-                LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
+        switch (type) {
+
+        case DNS_SERVER_LINK:
                 s->link = l;
-        } else if (type == DNS_SERVER_SYSTEM) {
-                LIST_FIND_TAIL(servers, m->dns_servers, tail);
-                LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
-        } else if (type == DNS_SERVER_FALLBACK) {
-                LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
-                LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
-        } else
+                LIST_APPEND(servers, l->dns_servers, s);
+                l->n_dns_servers++;
+                break;
+
+        case DNS_SERVER_SYSTEM:
+                LIST_APPEND(servers, m->dns_servers, s);
+                m->n_dns_servers++;
+                break;
+
+        case DNS_SERVER_FALLBACK:
+                LIST_APPEND(servers, m->fallback_dns_servers, s);
+                m->n_dns_servers++;
+                break;
+
+        default:
                 assert_not_reached("Unknown server type");
+        }
 
-        s->manager = m;
+        s->linked = true;
 
         /* A new DNS server that isn't fallback is added and the one
          * we used so far was a fallback one? Then let's try to pick
@@ -85,56 +120,447 @@ DnsServer* dns_server_ref(DnsServer *s)  {
                 return NULL;
 
         assert(s->n_ref > 0);
-
         s->n_ref ++;
 
         return s;
 }
 
-static DnsServer* dns_server_free(DnsServer *s)  {
+DnsServer* dns_server_unref(DnsServer *s)  {
         if (!s)
                 return NULL;
 
+        assert(s->n_ref > 0);
+        s->n_ref --;
+
+        if (s->n_ref > 0)
+                return NULL;
+
+        free(s->server_string);
+        free(s);
+        return NULL;
+}
+
+void dns_server_unlink(DnsServer *s) {
+        assert(s);
+        assert(s->manager);
+
+        /* This removes the specified server from the linked list of
+         * servers, but any server might still stay around if it has
+         * refs, for example from an ongoing transaction. */
+
+        if (!s->linked)
+                return;
+
+        switch (s->type) {
+
+        case DNS_SERVER_LINK:
+                assert(s->link);
+                assert(s->link->n_dns_servers > 0);
+                LIST_REMOVE(servers, s->link->dns_servers, s);
+                break;
+
+        case DNS_SERVER_SYSTEM:
+                assert(s->manager->n_dns_servers > 0);
+                LIST_REMOVE(servers, s->manager->dns_servers, s);
+                s->manager->n_dns_servers--;
+                break;
+
+        case DNS_SERVER_FALLBACK:
+                assert(s->manager->n_dns_servers > 0);
+                LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
+                s->manager->n_dns_servers--;
+                break;
+        }
+
+        s->linked = false;
+
         if (s->link && s->link->current_dns_server == s)
                 link_set_dns_server(s->link, NULL);
 
-        if (s->manager && s->manager->current_dns_server == s)
+        if (s->manager->current_dns_server == s)
                 manager_set_dns_server(s->manager, NULL);
 
-        free(s);
+        dns_server_unref(s);
+}
 
-        return NULL;
+void dns_server_move_back_and_unmark(DnsServer *s) {
+        DnsServer *tail;
+
+        assert(s);
+
+        if (!s->marked)
+                return;
+
+        s->marked = false;
+
+        if (!s->linked || !s->servers_next)
+                return;
+
+        /* Move us to the end of the list, so that the order is
+         * strictly kept, if we are not at the end anyway. */
+
+        switch (s->type) {
+
+        case DNS_SERVER_LINK:
+                assert(s->link);
+                LIST_FIND_TAIL(servers, s, tail);
+                LIST_REMOVE(servers, s->link->dns_servers, s);
+                LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s);
+                break;
+
+        case DNS_SERVER_SYSTEM:
+                LIST_FIND_TAIL(servers, s, tail);
+                LIST_REMOVE(servers, s->manager->dns_servers, s);
+                LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s);
+                break;
+
+        case DNS_SERVER_FALLBACK:
+                LIST_FIND_TAIL(servers, s, tail);
+                LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
+                LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s);
+                break;
+
+        default:
+                assert_not_reached("Unknown server type");
+        }
 }
 
-DnsServer* dns_server_unref(DnsServer *s)  {
-        if (!s)
-                return NULL;
+static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) {
+        assert(s);
 
-        assert(s->n_ref > 0);
+        if (s->verified_feature_level > level)
+                return;
 
-        if (s->n_ref == 1)
-                dns_server_free(s);
-        else
-                s->n_ref --;
+        if (s->verified_feature_level != level) {
+                log_debug("Verified we get a response at feature level %s from DNS server %s.",
+                          dns_server_feature_level_to_string(level),
+                          dns_server_string(s));
+                s->verified_feature_level = level;
+        }
 
-        return NULL;
+        assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0);
 }
 
-void dns_server_packet_received(DnsServer *s, usec_t rtt) {
+void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) {
         assert(s);
 
-        if (rtt > s->max_rtt) {
+        if (protocol == IPPROTO_UDP) {
+                if (s->possible_feature_level == level)
+                        s->n_failed_udp = 0;
+
+                /* If the RRSIG data is missing, then we can only validate EDNS0 at max */
+                if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO)
+                        level = DNS_SERVER_FEATURE_LEVEL_DO - 1;
+
+                /* If the OPT RR got lost, then we can only validate UDP at max */
+                if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
+                        level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
+
+                /* Even if we successfully receive a reply to a request announcing support for large packets,
+                   that does not mean we can necessarily receive large packets. */
+                if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
+                        level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
+
+        } else if (protocol == IPPROTO_TCP) {
+
+                if (s->possible_feature_level == level)
+                        s->n_failed_tcp = 0;
+
+                /* Successful TCP connections are only useful to verify the TCP feature level. */
+                level = DNS_SERVER_FEATURE_LEVEL_TCP;
+        }
+
+        dns_server_verified(s, level);
+
+        /* Remember the size of the largest UDP packet we received from a server,
+           we know that we can always announce support for packets with at least
+           this size. */
+        if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size)
+                s->received_udp_packet_max = size;
+
+        if (s->max_rtt < rtt) {
                 s->max_rtt = rtt;
-                s->resend_timeout = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2),
-                                        DNS_TIMEOUT_MAX_USEC);
+                s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
         }
 }
 
-void dns_server_packet_lost(DnsServer *s, usec_t usec) {
+void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec) {
+        assert(s);
+        assert(s->manager);
+
+        if (s->possible_feature_level == level) {
+                if (protocol == IPPROTO_UDP)
+                        s->n_failed_udp ++;
+                else if (protocol == IPPROTO_TCP)
+                        s->n_failed_tcp ++;
+        }
+
+        if (s->resend_timeout > usec)
+                return;
+
+        s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
+}
+
+void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel level) {
         assert(s);
 
-        if (s->resend_timeout <= usec)
-                s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
+        /* Invoked whenever we get a FORMERR, SERVFAIL or NOTIMP rcode from a server. */
+
+        if (s->possible_feature_level != level)
+                return;
+
+        s->packet_failed = true;
+}
+
+void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) {
+        assert(s);
+
+        /* Invoked whenever we get a packet with TC bit set. */
+
+        if (s->possible_feature_level != level)
+                return;
+
+        s->packet_truncated = true;
+}
+
+void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level) {
+        assert(s);
+
+        if (level < DNS_SERVER_FEATURE_LEVEL_DO)
+                return;
+
+        /* If the RRSIG RRs are missing, we have to downgrade what we previously verified */
+        if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO)
+                s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_DO-1;
+
+        s->packet_rrsig_missing = true;
+}
+
+void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level) {
+        assert(s);
+
+        if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
+                return;
+
+        /* If the OPT RR got lost, we have to downgrade what we previously verified */
+        if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
+                s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0-1;
+
+        s->packet_bad_opt = true;
+}
+
+static bool dns_server_grace_period_expired(DnsServer *s) {
+        usec_t ts;
+
+        assert(s);
+        assert(s->manager);
+
+        if (s->verified_usec == 0)
+                return false;
+
+        assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
+
+        if (s->verified_usec + s->features_grace_period_usec > ts)
+                return false;
+
+        s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC);
+
+        return true;
+}
+
+static void dns_server_reset_counters(DnsServer *s) {
+        assert(s);
+
+        s->n_failed_udp = 0;
+        s->n_failed_tcp = 0;
+        s->packet_failed = false;
+        s->packet_truncated = false;
+        s->verified_usec = 0;
+
+        /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
+         * grace period ends, but not when lowering the possible feature level, as a lower level feature level should
+         * not make RRSIGs appear or OPT appear, but rather make them disappear. If the reappear anyway, then that's
+         * indication for a differently broken OPT/RRSIG implementation, and we really don't want to support that
+         * either.
+         *
+         * This is particularly important to deal with certain Belkin routers which break OPT for certain lookups (A),
+         * but pass traffic through for others (AAAA). If we detect the broken behaviour on one lookup we should not
+         * reenable it for another, because we cannot validate things anyway, given that the RRSIG/OPT data will be
+         * incomplete. */
+}
+
+DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
+        assert(s);
+
+        if (s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_BEST &&
+            dns_server_grace_period_expired(s)) {
+
+                s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
+
+                dns_server_reset_counters(s);
+
+                s->packet_bad_opt = false;
+                s->packet_rrsig_missing = false;
+
+                log_info("Grace period over, resuming full feature set (%s) for DNS server %s.",
+                         dns_server_feature_level_to_string(s->possible_feature_level),
+                         dns_server_string(s));
+
+        } else if (s->possible_feature_level <= s->verified_feature_level)
+                s->possible_feature_level = s->verified_feature_level;
+        else {
+                DnsServerFeatureLevel p = s->possible_feature_level;
+
+                if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
+                    s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TCP) {
+
+                        /* We are at the TCP (lowest) level, and we tried a couple of TCP connections, and it didn't
+                         * work. Upgrade back to UDP again. */
+                        log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
+                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
+
+                } else if (s->packet_bad_opt &&
+                           s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
+
+                        /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below
+                         * EDNS0 levels. After all, some records generate different responses with and without OPT RR
+                         * in the request. Example:
+                         * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
+
+                        log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
+                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
+
+                } else if (s->packet_rrsig_missing &&
+                           s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) {
+
+                        /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't
+                         * augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore,
+                         * after all some servers generate different replies depending if an OPT RR is in the query or
+                         * not. */
+
+                        log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
+                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
+
+                } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
+                            s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_UDP) {
+
+                        /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
+                         * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
+                         * idea. We might downgrade all the way down to TCP this way. */
+
+                        log_debug("Lost too many UDP packets, downgrading feature level...");
+                        s->possible_feature_level--;
+
+                } else if (s->packet_failed &&
+                           s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
+
+                        /* We got a failure packet, and are at a feature level above UDP. Note that in this case we
+                         * downgrade no further than UDP, under the assumption that a failure packet indicates an
+                         * incompatible packet contents, but not a problem with the transport. */
+
+                        log_debug("Got server failure, downgrading feature level...");
+                        s->possible_feature_level--;
+
+                } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
+                           s->packet_truncated &&
+                           s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
+
+                         /* We got too many TCP connection failures in a row, we had at least one truncated packet, and
+                          * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
+                          * data we hope to make the packet smaller, so that it still works via UDP given that TCP
+                          * appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't
+                          * go further down, since that's TCP, and TCP failed too often after all. */
+
+                        log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
+                        s->possible_feature_level--;
+                }
+
+                if (p != s->possible_feature_level) {
+
+                        /* We changed the feature level, reset the counting */
+                        dns_server_reset_counters(s);
+
+                        log_warning("Using degraded feature set (%s) for DNS server %s.",
+                                    dns_server_feature_level_to_string(s->possible_feature_level),
+                                    dns_server_string(s));
+                }
+        }
+
+        return s->possible_feature_level;
+}
+
+int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) {
+        size_t packet_size;
+        bool edns_do;
+        int r;
+
+        assert(server);
+        assert(packet);
+        assert(packet->protocol == DNS_PROTOCOL_DNS);
+
+        /* Fix the OPT field in the packet to match our current feature level. */
+
+        r = dns_packet_truncate_opt(packet);
+        if (r < 0)
+                return r;
+
+        if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
+                return 0;
+
+        edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
+
+        if (level >= DNS_SERVER_FEATURE_LEVEL_LARGE)
+                packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
+        else
+                packet_size = server->received_udp_packet_max;
+
+        return dns_packet_append_opt(packet, packet_size, edns_do, NULL);
+}
+
+const char *dns_server_string(DnsServer *server) {
+        assert(server);
+
+        if (!server->server_string)
+                (void) in_addr_to_string(server->family, &server->address, &server->server_string);
+
+        return strna(server->server_string);
+}
+
+bool dns_server_dnssec_supported(DnsServer *server) {
+        assert(server);
+
+        /* Returns whether the server supports DNSSEC according to what we know about it */
+
+        if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
+                return false;
+
+        if (server->packet_bad_opt)
+                return false;
+
+        if (server->packet_rrsig_missing)
+                return false;
+
+        /* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */
+        if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS)
+                return false;
+
+        return true;
+}
+
+void dns_server_warn_downgrade(DnsServer *server) {
+        assert(server);
+
+        if (server->warned_downgrade)
+                return;
+
+        log_struct(LOG_NOTICE,
+                   LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_DOWNGRADE),
+                   LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)),
+                   "DNS_SERVER=%s", dns_server_string(server),
+                   "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level),
+                   NULL);
+
+        server->warned_downgrade = true;
 }
 
 static void dns_server_hash_func(const void *p, struct siphash *state) {
@@ -161,3 +587,154 @@ const struct hash_ops dns_server_hash_ops = {
         .hash = dns_server_hash_func,
         .compare = dns_server_compare_func
 };
+
+void dns_server_unlink_all(DnsServer *first) {
+        DnsServer *next;
+
+        if (!first)
+                return;
+
+        next = first->servers_next;
+        dns_server_unlink(first);
+
+        dns_server_unlink_all(next);
+}
+
+void dns_server_unlink_marked(DnsServer *first) {
+        DnsServer *next;
+
+        if (!first)
+                return;
+
+        next = first->servers_next;
+
+        if (first->marked)
+                dns_server_unlink(first);
+
+        dns_server_unlink_marked(next);
+}
+
+void dns_server_mark_all(DnsServer *first) {
+        if (!first)
+                return;
+
+        first->marked = true;
+        dns_server_mark_all(first->servers_next);
+}
+
+DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) {
+        DnsServer *s;
+
+        LIST_FOREACH(servers, s, first)
+                if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
+                        return s;
+
+        return NULL;
+}
+
+DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) {
+        assert(m);
+
+        switch (t) {
+
+        case DNS_SERVER_SYSTEM:
+                return m->dns_servers;
+
+        case DNS_SERVER_FALLBACK:
+                return m->fallback_dns_servers;
+
+        default:
+                return NULL;
+        }
+}
+
+DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
+        assert(m);
+
+        if (m->current_dns_server == s)
+                return s;
+
+        if (s)
+                log_info("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);
+
+        if (m->unicast_scope)
+                dns_cache_flush(&m->unicast_scope->cache);
+
+        return s;
+}
+
+DnsServer *manager_get_dns_server(Manager *m) {
+        Link *l;
+        assert(m);
+
+        /* Try to read updates resolv.conf */
+        manager_read_resolv_conf(m);
+
+        /* If no DNS server was chosen so far, pick the first one */
+        if (!m->current_dns_server)
+                manager_set_dns_server(m, m->dns_servers);
+
+        if (!m->current_dns_server) {
+                bool found = false;
+                Iterator i;
+
+                /* No DNS servers configured, let's see if there are
+                 * any on any links. If not, we use the fallback
+                 * servers */
+
+                HASHMAP_FOREACH(l, m->links, i)
+                        if (l->dns_servers) {
+                                found = true;
+                                break;
+                        }
+
+                if (!found)
+                        manager_set_dns_server(m, m->fallback_dns_servers);
+        }
+
+        return m->current_dns_server;
+}
+
+void manager_next_dns_server(Manager *m) {
+        assert(m);
+
+        /* If there's currently no DNS server set, then the next
+         * manager_get_dns_server() will find one */
+        if (!m->current_dns_server)
+                return;
+
+        /* Change to the next one, but make sure to follow the linked
+         * list only if the server is still linked. */
+        if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
+                manager_set_dns_server(m, m->current_dns_server->servers_next);
+                return;
+        }
+
+        /* If there was no next one, then start from the beginning of
+         * the list */
+        if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
+                manager_set_dns_server(m, m->fallback_dns_servers);
+        else
+                manager_set_dns_server(m, m->dns_servers);
+}
+
+static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
+        [DNS_SERVER_SYSTEM] = "system",
+        [DNS_SERVER_FALLBACK] = "fallback",
+        [DNS_SERVER_LINK] = "link",
+};
+DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType);
+
+static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
+        [DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
+        [DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
+        [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
+        [DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO",
+        [DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE",
+};
+DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);
index 10111fd6bde39f5ed5974c4548fcc5827ac1d151..9f4a69c37abcbd0b9ba259e9d0122e62da13c932 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 #include "in-addr-util.h"
 
 typedef struct DnsServer DnsServer;
-typedef enum DnsServerSource DnsServerSource;
 
 typedef enum DnsServerType {
         DNS_SERVER_SYSTEM,
         DNS_SERVER_FALLBACK,
         DNS_SERVER_LINK,
 } DnsServerType;
+#define _DNS_SERVER_TYPE_MAX (DNS_SERVER_LINK + 1)
+
+const char* dns_server_type_to_string(DnsServerType i) _const_;
+DnsServerType dns_server_type_from_string(const char *s) _pure_;
+
+typedef enum DnsServerFeatureLevel {
+        DNS_SERVER_FEATURE_LEVEL_TCP,
+        DNS_SERVER_FEATURE_LEVEL_UDP,
+        DNS_SERVER_FEATURE_LEVEL_EDNS0,
+        DNS_SERVER_FEATURE_LEVEL_DO,
+        DNS_SERVER_FEATURE_LEVEL_LARGE,
+        _DNS_SERVER_FEATURE_LEVEL_MAX,
+        _DNS_SERVER_FEATURE_LEVEL_INVALID = -1
+} DnsServerFeatureLevel;
+
+#define DNS_SERVER_FEATURE_LEVEL_WORST 0
+#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1)
+
+const char* dns_server_feature_level_to_string(int i) _const_;
+int dns_server_feature_level_from_string(const char *s) _pure_;
 
 #include "resolved-link.h"
+#include "resolved-manager.h"
 
 struct DnsServer {
         Manager *manager;
@@ -40,33 +58,85 @@ struct DnsServer {
         unsigned n_ref;
 
         DnsServerType type;
-
         Link *link;
 
         int family;
         union in_addr_union address;
 
+        char *server_string;
+
         usec_t resend_timeout;
         usec_t max_rtt;
 
+        DnsServerFeatureLevel verified_feature_level;
+        DnsServerFeatureLevel possible_feature_level;
+
+        size_t received_udp_packet_max;
+
+        unsigned n_failed_udp;
+        unsigned n_failed_tcp;
+
+        bool packet_failed:1;
+        bool packet_truncated:1;
+        bool packet_bad_opt:1;
+        bool packet_rrsig_missing:1;
+
+        usec_t verified_usec;
+        usec_t features_grace_period_usec;
+
+        /* Whether we already warned about downgrading to non-DNSSEC mode for this server */
+        bool warned_downgrade:1;
+
+        /* Used when GC'ing old DNS servers when configuration changes. */
         bool marked:1;
 
+        /* If linked is set, then this server appears in the servers linked list */
+        bool linked:1;
         LIST_FIELDS(DnsServer, servers);
 };
 
 int dns_server_new(
                 Manager *m,
-                DnsServer **s,
+                DnsServer **ret,
                 DnsServerType type,
-                Link *l,
+                Link *link,
                 int family,
                 const union in_addr_union *address);
 
 DnsServer* dns_server_ref(DnsServer *s);
 DnsServer* dns_server_unref(DnsServer *s);
 
-void dns_server_packet_received(DnsServer *s, usec_t rtt);
-void dns_server_packet_lost(DnsServer *s, usec_t usec);
+void dns_server_unlink(DnsServer *s);
+void dns_server_move_back_and_unmark(DnsServer *s);
+
+void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size);
+void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec);
+void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel level);
+void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level);
+void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
+void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
+
+DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
+
+int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level);
+
+const char *dns_server_string(DnsServer *server);
+
+bool dns_server_dnssec_supported(DnsServer *server);
+
+void dns_server_warn_downgrade(DnsServer *server);
+
+DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr);
+
+void dns_server_unlink_all(DnsServer *first);
+void dns_server_unlink_marked(DnsServer *first);
+void dns_server_mark_all(DnsServer *first);
+
+DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t);
+
+DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
+DnsServer *manager_get_dns_server(Manager *m);
+void manager_next_dns_server(Manager *m);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
 
index 1c501182fb77e5bba2321d23295e12a5093d6afb..a1040aeff4594f2465c4c152b51d13d210c80883 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -347,7 +345,6 @@ DnsStream *dns_stream_free(DnsStream *s) {
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_free);
 
 int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
-        static const int one = 1;
         _cleanup_(dns_stream_freep) DnsStream *s = NULL;
         int r;
 
@@ -364,14 +361,12 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
         s->fd = -1;
         s->protocol = protocol;
 
-        r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
-        if (r < 0)
-                return -errno;
-
         r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s);
         if (r < 0)
                 return r;
 
+        (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io");
+
         r = sd_event_add_time(
                         m->event,
                         &s->timeout_event_source,
@@ -381,6 +376,8 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
         if (r < 0)
                 return r;
 
+        (void) sd_event_source_set_description(s->timeout_event_source, "dns-stream-timeout");
+
         LIST_PREPEND(streams, m->dns_streams, s);
         s->manager = m;
         s->fd = fd;
index fb81e9f1ac5919b5d17daf5acacb104e489f9a61..5ccc842249564ed9860824256324bbc3b80d68d1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
diff --git a/src/resolve/resolved-dns-synthesize.c b/src/resolve/resolved-dns-synthesize.c
new file mode 100644 (file)
index 0000000..f4a43de
--- /dev/null
@@ -0,0 +1,413 @@
+/***
+  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 "alloc-util.h"
+#include "hostname-util.h"
+#include "local-addresses.h"
+#include "resolved-dns-synthesize.h"
+
+int dns_synthesize_ifindex(int ifindex) {
+
+        /* When the caller asked for resolving on a specific
+         * interface, we synthesize the answer for that
+         * interface. However, if nothing specific was claimed and we
+         * only return localhost RRs, we synthesize the answer for
+         * localhost. */
+
+        if (ifindex > 0)
+                return ifindex;
+
+        return LOOPBACK_IFINDEX;
+}
+
+int dns_synthesize_family(uint64_t flags) {
+
+        /* Picks an address family depending on set flags. This is
+         * purely for synthesized answers, where the family we return
+         * for the reply should match what was requested in the
+         * question, even though we are synthesizing the answer
+         * here. */
+
+        if (!(flags & SD_RESOLVED_DNS)) {
+                if (flags & (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_MDNS_IPV4))
+                        return AF_INET;
+                if (flags & (SD_RESOLVED_LLMNR_IPV6|SD_RESOLVED_MDNS_IPV6))
+                        return AF_INET6;
+        }
+
+        return AF_UNSPEC;
+}
+
+DnsProtocol dns_synthesize_protocol(uint64_t flags) {
+
+        /* Similar as dns_synthesize_family() but does this for the
+         * protocol. If resolving via DNS was requested, we claim it
+         * was DNS. Similar, if nothing specific was
+         * requested. However, if only resolving via LLMNR was
+         * requested we return that. */
+
+        if (flags & SD_RESOLVED_DNS)
+                return DNS_PROTOCOL_DNS;
+        if (flags & SD_RESOLVED_LLMNR)
+                return DNS_PROTOCOL_LLMNR;
+        if (flags & SD_RESOLVED_MDNS)
+                return DNS_PROTOCOL_MDNS;
+
+        return DNS_PROTOCOL_DNS;
+}
+
+static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
+        int r;
+
+        assert(m);
+        assert(key);
+        assert(answer);
+
+        r = dns_answer_reserve(answer, 2);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
+                if (!rr)
+                        return -ENOMEM;
+
+                rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
+
+                r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
+                if (!rr)
+                        return -ENOMEM;
+
+                rr->aaaa.in6_addr = in6addr_loopback;
+
+                r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+        rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
+        if (!rr)
+                return -ENOMEM;
+
+        rr->ptr.name = strdup(to);
+        if (!rr->ptr.name)
+                return -ENOMEM;
+
+        return dns_answer_add(*answer, rr, ifindex, flags);
+}
+
+static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
+        int r;
+
+        assert(m);
+        assert(key);
+        assert(answer);
+
+        if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
+                r = dns_answer_reserve(answer, 1);
+                if (r < 0)
+                        return r;
+
+                r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int answer_add_addresses_rr(
+                DnsAnswer **answer,
+                const char *name,
+                struct local_address *addresses,
+                unsigned n_addresses) {
+
+        unsigned j;
+        int r;
+
+        assert(answer);
+        assert(name);
+
+        r = dns_answer_reserve(answer, n_addresses);
+        if (r < 0)
+                return r;
+
+        for (j = 0; j < n_addresses; j++) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
+                if (r < 0)
+                        return r;
+
+                r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int answer_add_addresses_ptr(
+                DnsAnswer **answer,
+                const char *name,
+                struct local_address *addresses,
+                unsigned n_addresses,
+                int af, const union in_addr_union *match) {
+
+        unsigned j;
+        int r;
+
+        assert(answer);
+        assert(name);
+
+        for (j = 0; j < n_addresses; j++) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                if (af != AF_UNSPEC) {
+
+                        if (addresses[j].family != af)
+                                continue;
+
+                        if (match && !in_addr_equal(af, match, &addresses[j].address))
+                                continue;
+                }
+
+                r = dns_answer_reserve(answer, 1);
+                if (r < 0)
+                        return r;
+
+                r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
+                if (r < 0)
+                        return r;
+
+                r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
+        _cleanup_free_ struct local_address *addresses = NULL;
+        int n = 0, af;
+
+        assert(m);
+        assert(key);
+        assert(answer);
+
+        af = dns_type_to_af(key->type);
+        if (af >= 0) {
+                n = local_addresses(m->rtnl, ifindex, af, &addresses);
+                if (n < 0)
+                        return n;
+
+                if (n == 0) {
+                        struct local_address buffer[2];
+
+                        /* If we have no local addresses then use ::1
+                         * and 127.0.0.2 as local ones. */
+
+                        if (af == AF_INET || af == AF_UNSPEC)
+                                buffer[n++] = (struct local_address) {
+                                        .family = AF_INET,
+                                        .ifindex = dns_synthesize_ifindex(ifindex),
+                                        .address.in.s_addr = htobe32(0x7F000002),
+                                };
+
+                        if (af == AF_INET6 || af == AF_UNSPEC)
+                                buffer[n++] = (struct local_address) {
+                                        .family = AF_INET6,
+                                        .ifindex = dns_synthesize_ifindex(ifindex),
+                                        .address.in6 = in6addr_loopback,
+                                };
+
+                        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
+                }
+        }
+
+        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
+}
+
+static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
+        _cleanup_free_ struct local_address *addresses = NULL;
+        int n, r;
+
+        assert(m);
+        assert(address);
+        assert(answer);
+
+        if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
+
+                /* Always map the IPv4 address 127.0.0.2 to the local
+                 * hostname, in addition to "localhost": */
+
+                r = dns_answer_reserve(answer, 3);
+                if (r < 0)
+                        return r;
+
+                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+
+                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+
+                r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+
+                return 0;
+        }
+
+        n = local_addresses(m->rtnl, ifindex, af, &addresses);
+        if (n < 0)
+                return n;
+
+        r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address);
+        if (r < 0)
+                return r;
+
+        return answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address);
+}
+
+static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
+        _cleanup_free_ struct local_address *addresses = NULL;
+        int n = 0, af;
+
+        assert(m);
+        assert(key);
+        assert(answer);
+
+        af = dns_type_to_af(key->type);
+        if (af >= 0) {
+                n = local_gateways(m->rtnl, ifindex, af, &addresses);
+                if (n < 0)
+                        return n;
+        }
+
+        return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
+}
+
+static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
+        _cleanup_free_ struct local_address *addresses = NULL;
+        int n;
+
+        assert(m);
+        assert(address);
+        assert(answer);
+
+        n = local_gateways(m->rtnl, ifindex, af, &addresses);
+        if (n < 0)
+                return n;
+
+        return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
+}
+
+int dns_synthesize_answer(
+                Manager *m,
+                DnsQuestion *q,
+                int ifindex,
+                DnsAnswer **ret) {
+
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        DnsResourceKey *key;
+        bool found = false;
+        int r;
+
+        assert(m);
+        assert(q);
+
+        DNS_QUESTION_FOREACH(key, q) {
+                union in_addr_union address;
+                const char *name;
+                int af;
+
+                if (key->class != DNS_CLASS_IN &&
+                    key->class != DNS_CLASS_ANY)
+                        continue;
+
+                name = DNS_RESOURCE_KEY_NAME(key);
+
+                if (is_localhost(name)) {
+
+                        r = synthesize_localhost_rr(m, key, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
+
+                } else if (manager_is_own_hostname(m, name)) {
+
+                        r = synthesize_system_hostname_rr(m, key, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
+
+                } else if (is_gateway_hostname(name)) {
+
+                        r = synthesize_gateway_rr(m, key, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
+
+                } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
+                           dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
+
+                        r = synthesize_localhost_ptr(m, key, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
+
+                } else if (dns_name_address(name, &af, &address) > 0) {
+
+                        r = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
+
+                        r = synthesize_gateway_ptr(m, af, &address, ifindex, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
+                } else
+                        continue;
+
+                found = true;
+        }
+
+        r = found;
+
+        if (ret) {
+                *ret = answer;
+                answer = NULL;
+        }
+
+        return r;
+}
diff --git a/src/resolve/resolved-dns-synthesize.h b/src/resolve/resolved-dns-synthesize.h
new file mode 100644 (file)
index 0000000..5d829bb
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "resolved-dns-answer.h"
+#include "resolved-dns-question.h"
+#include "resolved-manager.h"
+
+int dns_synthesize_ifindex(int ifindex);
+int dns_synthesize_family(uint64_t flags);
+DnsProtocol dns_synthesize_protocol(uint64_t flags);
+
+int dns_synthesize_answer(Manager *m, DnsQuestion *q, int ifindex, DnsAnswer **ret);
index 6545f6cd8a7ed39a37b9fd4d945e2257f1b608c9..d48fdd1281abd2021ceebf1fc4bfbc3283974005 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sd-messages.h>
+
 #include "af-list.h"
 #include "alloc-util.h"
 #include "dns-domain.h"
+#include "errno-list.h"
 #include "fd-util.h"
 #include "random-util.h"
+#include "resolved-dns-cache.h"
 #include "resolved-dns-transaction.h"
 #include "resolved-llmnr.h"
 #include "string-table.h"
 
+#define TRANSACTIONS_MAX 4096
+
+static void dns_transaction_reset_answer(DnsTransaction *t) {
+        assert(t);
+
+        t->received = dns_packet_unref(t->received);
+        t->answer = dns_answer_unref(t->answer);
+        t->answer_rcode = 0;
+        t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+        t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
+        t->answer_authenticated = false;
+        t->answer_nsec_ttl = (uint32_t) -1;
+        t->answer_errno = 0;
+}
+
+static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) {
+        DnsTransaction *z;
+
+        assert(t);
+
+        while ((z = set_steal_first(t->dnssec_transactions))) {
+                set_remove(z->notify_transactions, t);
+                dns_transaction_gc(z);
+        }
+}
+
+static void dns_transaction_close_connection(DnsTransaction *t) {
+        assert(t);
+
+        t->stream = dns_stream_free(t->stream);
+        t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
+        t->dns_udp_fd = safe_close(t->dns_udp_fd);
+}
+
+static void dns_transaction_stop_timeout(DnsTransaction *t) {
+        assert(t);
+
+        t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
+}
+
 DnsTransaction* dns_transaction_free(DnsTransaction *t) {
-        DnsQuery *q;
+        DnsQueryCandidate *c;
         DnsZoneItem *i;
+        DnsTransaction *z;
 
         if (!t)
                 return NULL;
 
-        sd_event_source_unref(t->timeout_event_source);
+        log_debug("Freeing transaction %" PRIu16 ".", t->id);
 
-        dns_packet_unref(t->sent);
-        dns_packet_unref(t->received);
-        dns_answer_unref(t->cached);
+        dns_transaction_close_connection(t);
+        dns_transaction_stop_timeout(t);
 
-        sd_event_source_unref(t->dns_udp_event_source);
-        safe_close(t->dns_udp_fd);
+        dns_packet_unref(t->sent);
+        dns_transaction_reset_answer(t);
 
         dns_server_unref(t->server);
-        dns_stream_free(t->stream);
 
         if (t->scope) {
-                hashmap_remove(t->scope->transactions, t->key);
+                hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
+                LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
 
                 if (t->id != 0)
                         hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
         }
 
-        dns_resource_key_unref(t->key);
-
-        while ((q = set_steal_first(t->queries)))
-                set_remove(q->transactions, t);
-        set_free(t->queries);
+        while ((c = set_steal_first(t->notify_query_candidates)))
+                set_remove(c->transactions, t);
+        set_free(t->notify_query_candidates);
 
-        while ((i = set_steal_first(t->zone_items)))
+        while ((i = set_steal_first(t->notify_zone_items)))
                 i->probe_transaction = NULL;
-        set_free(t->zone_items);
+        set_free(t->notify_zone_items);
+
+        while ((z = set_steal_first(t->notify_transactions)))
+                set_remove(z->dnssec_transactions, t);
+        set_free(t->notify_transactions);
+
+        dns_transaction_flush_dnssec_transactions(t);
+        set_free(t->dnssec_transactions);
+
+        dns_answer_unref(t->validated_keys);
+        dns_resource_key_unref(t->key);
+        free(t->key_string);
 
         free(t);
         return NULL;
@@ -70,14 +121,36 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
 
-void dns_transaction_gc(DnsTransaction *t) {
+bool dns_transaction_gc(DnsTransaction *t) {
         assert(t);
 
         if (t->block_gc > 0)
-                return;
+                return true;
 
-        if (set_isempty(t->queries) && set_isempty(t->zone_items))
+        if (set_isempty(t->notify_query_candidates) &&
+            set_isempty(t->notify_zone_items) &&
+            set_isempty(t->notify_transactions)) {
                 dns_transaction_free(t);
+                return false;
+        }
+
+        return true;
+}
+
+static uint16_t pick_new_id(Manager *m) {
+        uint16_t new_id;
+
+        /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of
+         * transactions, and it's much lower than the space of IDs. */
+
+        assert_cc(TRANSACTIONS_MAX < 0xFFFF);
+
+        do
+                random_bytes(&new_id, sizeof(new_id));
+        while (new_id == 0 ||
+               hashmap_get(m->dns_transactions, UINT_TO_PTR(new_id)));
+
+        return new_id;
 }
 
 int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
@@ -88,11 +161,24 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
         assert(s);
         assert(key);
 
+        /* Don't allow looking up invalid or pseudo RRs */
+        if (!dns_type_is_valid_query(key->type))
+                return -EINVAL;
+        if (dns_type_is_obsolete(key->type))
+                return -EOPNOTSUPP;
+
+        /* We only support the IN class */
+        if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY)
+                return -EOPNOTSUPP;
+
+        if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX)
+                return -EBUSY;
+
         r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
         if (r < 0)
                 return r;
 
-        r = hashmap_ensure_allocated(&s->transactions, &dns_resource_key_hash_ops);
+        r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
         if (r < 0)
                 return r;
 
@@ -101,13 +187,13 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
                 return -ENOMEM;
 
         t->dns_udp_fd = -1;
+        t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
+        t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+        t->answer_nsec_ttl = (uint32_t) -1;
         t->key = dns_resource_key_ref(key);
+        t->current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
 
-        /* Find a fresh, unused transaction id */
-        do
-                random_bytes(&t->id, sizeof(t->id));
-        while (t->id == 0 ||
-               hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
+        t->id = pick_new_id(s->manager);
 
         r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
         if (r < 0) {
@@ -115,14 +201,17 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
                 return r;
         }
 
-        r = hashmap_put(s->transactions, t->key, t);
+        r = hashmap_replace(s->transactions_by_key, t->key, t);
         if (r < 0) {
                 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
                 return r;
         }
 
+        LIST_PREPEND(transactions_by_scope, s->transactions, t);
         t->scope = s;
 
+        s->manager->n_transactions_total ++;
+
         if (ret)
                 *ret = t;
 
@@ -131,11 +220,20 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
         return 0;
 }
 
-static void dns_transaction_stop(DnsTransaction *t) {
+static void dns_transaction_shuffle_id(DnsTransaction *t) {
+        uint16_t new_id;
         assert(t);
 
-        t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
-        t->stream = dns_stream_free(t->stream);
+        /* Pick a new ID for this transaction. */
+
+        new_id = pick_new_id(t->scope->manager);
+        assert_se(hashmap_remove_and_put(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id), UINT_TO_PTR(new_id), t) >= 0);
+
+        log_debug("Transaction %" PRIu16 " is now %" PRIu16 ".", t->id, new_id);
+        t->id = new_id;
+
+        /* Make sure we generate a new packet with the new ID */
+        t->sent = dns_packet_unref(t->sent);
 }
 
 static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
@@ -150,7 +248,9 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
 
         in_addr_to_string(p->family, &p->sender, &pretty);
 
-        log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
+        log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
+                  t->id,
+                  dns_transaction_key_string(t),
                   dns_protocol_to_string(t->scope->protocol),
                   t->scope->link ? t->scope->link->name : "*",
                   t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
@@ -166,7 +266,7 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
         log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
 
         t->block_gc++;
-        while ((z = set_first(t->zone_items))) {
+        while ((z = set_first(t->notify_zone_items))) {
                 /* First, make sure the zone item drops the reference
                  * to us */
                 dns_zone_item_probe_stop(z);
@@ -181,39 +281,150 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
 }
 
 void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
-        DnsQuery *q;
+        DnsQueryCandidate *c;
         DnsZoneItem *z;
+        DnsTransaction *d;
         Iterator i;
+        const char *st;
 
         assert(t);
-        assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
+        assert(!DNS_TRANSACTION_IS_LIVE(state));
+
+        if (state == DNS_TRANSACTION_DNSSEC_FAILED)
+                log_struct(LOG_NOTICE,
+                           LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_FAILURE),
+                           LOG_MESSAGE("DNSSEC validation failed for question %s: %s", dns_transaction_key_string(t), dnssec_result_to_string(t->answer_dnssec_result)),
+                           "DNS_TRANSACTION=%" PRIu16, t->id,
+                           "DNS_QUESTION=%s", dns_transaction_key_string(t),
+                           "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
+                           "DNS_SERVER=%s", dns_server_string(t->server),
+                           "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level),
+                           NULL);
 
         /* Note that this call might invalidate the query. Callers
          * should hence not attempt to access the query or transaction
          * after calling this function. */
 
-        log_debug("Transaction on scope %s on %s/%s now complete with <%s>",
+        if (state == DNS_TRANSACTION_ERRNO)
+                st = errno_to_name(t->answer_errno);
+        else
+                st = dns_transaction_state_to_string(state);
+
+        log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
+                  t->id,
+                  dns_transaction_key_string(t),
                   dns_protocol_to_string(t->scope->protocol),
                   t->scope->link ? t->scope->link->name : "*",
                   t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
-                  dns_transaction_state_to_string(state));
+                  st,
+                  t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
+                  t->answer_authenticated ? "authenticated" : "unsigned");
 
         t->state = state;
 
-        dns_transaction_stop(t);
+        dns_transaction_close_connection(t);
+        dns_transaction_stop_timeout(t);
 
         /* Notify all queries that are interested, but make sure the
          * transaction isn't freed while we are still looking at it */
         t->block_gc++;
-        SET_FOREACH(q, t->queries, i)
-                dns_query_ready(q);
-        SET_FOREACH(z, t->zone_items, i)
-                dns_zone_item_ready(z);
-        t->block_gc--;
 
+        SET_FOREACH(c, t->notify_query_candidates, i)
+                dns_query_candidate_notify(c);
+        SET_FOREACH(z, t->notify_zone_items, i)
+                dns_zone_item_notify(z);
+
+        if (!set_isempty(t->notify_transactions)) {
+                DnsTransaction **nt;
+                unsigned j, n = 0;
+
+                /* We need to be careful when notifying other
+                 * transactions, as that might destroy other
+                 * transactions in our list. Hence, in order to be
+                 * able to safely iterate through the list of
+                 * transactions, take a GC lock on all of them
+                 * first. Then, in a second loop, notify them, but
+                 * first unlock that specific transaction. */
+
+                nt = newa(DnsTransaction*, set_size(t->notify_transactions));
+                SET_FOREACH(d, t->notify_transactions, i) {
+                        nt[n++] = d;
+                        d->block_gc++;
+                }
+
+                assert(n == set_size(t->notify_transactions));
+
+                for (j = 0; j < n; j++) {
+                        if (set_contains(t->notify_transactions, nt[j]))
+                                dns_transaction_notify(nt[j], t);
+
+                        nt[j]->block_gc--;
+                        dns_transaction_gc(nt[j]);
+                }
+        }
+
+        t->block_gc--;
         dns_transaction_gc(t);
 }
 
+static int dns_transaction_pick_server(DnsTransaction *t) {
+        DnsServer *server;
+
+        assert(t);
+        assert(t->scope->protocol == DNS_PROTOCOL_DNS);
+
+        server = dns_scope_get_dns_server(t->scope);
+        if (!server)
+                return -ESRCH;
+
+        t->current_feature_level = dns_server_possible_feature_level(server);
+
+        if (server == t->server)
+                return 0;
+
+        dns_server_unref(t->server);
+        t->server = dns_server_ref(server);
+
+        return 1;
+}
+
+static void dns_transaction_retry(DnsTransaction *t) {
+        int r;
+
+        assert(t);
+
+        log_debug("Retrying transaction %" PRIu16 ".", t->id);
+
+        /* Before we try again, switch to a new server. */
+        dns_scope_next_dns_server(t->scope);
+
+        r = dns_transaction_go(t);
+        if (r < 0) {
+                t->answer_errno = -r;
+                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+        }
+}
+
+static int dns_transaction_maybe_restart(DnsTransaction *t) {
+        assert(t);
+
+        if (!t->server)
+                return 0;
+
+        if (t->current_feature_level <= dns_server_possible_feature_level(t->server))
+                return 0;
+
+        /* The server's current feature level is lower than when we sent the original query. We learnt something from
+           the response or possibly an auxiliary DNSSEC response that we didn't know before.  We take that as reason to
+           restart the whole transaction. This is a good idea to deal with servers that respond rubbish if we include
+           OPT RR or DO bit. One of these cases is documented here, for example:
+           https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
+
+        log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID.");
+        dns_transaction_shuffle_id(t);
+        return dns_transaction_go(t);
+}
+
 static int on_stream_complete(DnsStream *s, int error) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
         DnsTransaction *t;
@@ -228,13 +439,31 @@ static int on_stream_complete(DnsStream *s, int error) {
 
         t->stream = dns_stream_free(t->stream);
 
+        if (ERRNO_IS_DISCONNECT(error)) {
+                usec_t usec;
+
+                if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
+                        /* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the
+                         * question on this scope. */
+                        dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
+                        return 0;
+                }
+
+                log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
+                assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+                dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level, usec - t->start_usec);
+
+                dns_transaction_retry(t);
+                return 0;
+        }
         if (error != 0) {
-                dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+                t->answer_errno = error;
+                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
                 return 0;
         }
 
         if (dns_packet_validate_reply(p) <= 0) {
-                log_debug("Invalid LLMNR TCP packet.");
+                log_debug("Invalid TCP reply packet.");
                 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
                 return 0;
         }
@@ -245,32 +474,46 @@ static int on_stream_complete(DnsStream *s, int error) {
         dns_transaction_process_reply(t, p);
         t->block_gc--;
 
-        /* If the response wasn't useful, then complete the transition now */
+        /* If the response wasn't useful, then complete the transition
+         * now. After all, we are the worst feature set now with TCP
+         * sockets, and there's really no point in retrying. */
         if (t->state == DNS_TRANSACTION_PENDING)
                 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+        else
+                dns_transaction_gc(t);
 
         return 0;
 }
 
 static int dns_transaction_open_tcp(DnsTransaction *t) {
-        DnsServer *server = NULL;
         _cleanup_close_ int fd = -1;
         int r;
 
         assert(t);
 
-        if (t->stream)
-                return 0;
+        dns_transaction_close_connection(t);
 
         switch (t->scope->protocol) {
+
         case DNS_PROTOCOL_DNS:
-                fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
+                r = dns_transaction_pick_server(t);
+                if (r < 0)
+                        return r;
+
+                if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
+                        return -EOPNOTSUPP;
+
+                r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
+                if (r < 0)
+                        return r;
+
+                fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, 53);
                 break;
 
         case DNS_PROTOCOL_LLMNR:
                 /* When we already received a reply to this (but it was truncated), send to its sender address */
                 if (t->received)
-                        fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
+                        fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port);
                 else {
                         union in_addr_union address;
                         int family = AF_UNSPEC;
@@ -287,7 +530,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
                         if (family != t->scope->family)
                                 return -ESRCH;
 
-                        fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
+                        fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT);
                 }
 
                 break;
@@ -302,7 +545,6 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
         r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
         if (r < 0)
                 return r;
-
         fd = -1;
 
         r = dns_stream_write_packet(t->stream, t->sent);
@@ -311,9 +553,6 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
                 return r;
         }
 
-        dns_server_unref(t->server);
-        t->server = dns_server_ref(server);
-        t->received = dns_packet_unref(t->received);
         t->stream->complete = on_stream_complete;
         t->stream->transaction = t;
 
@@ -323,17 +562,221 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
         if (t->scope->link)
                 t->stream->ifindex = t->scope->link->ifindex;
 
+        dns_transaction_reset_answer(t);
+
+        t->tried_stream = true;
+
         return 0;
 }
 
-static void dns_transaction_next_dns_server(DnsTransaction *t) {
+static void dns_transaction_cache_answer(DnsTransaction *t) {
         assert(t);
 
-        t->server = dns_server_unref(t->server);
-        t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
-        t->dns_udp_fd = safe_close(t->dns_udp_fd);
+        /* For mDNS we cache whenever we get the packet, rather than
+         * in each transaction. */
+        if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
+                return;
 
-        dns_scope_next_dns_server(t->scope);
+        /* We never cache if this packet is from the local host, under
+         * the assumption that a locally running DNS server would
+         * cache this anyway, and probably knows better when to flush
+         * the cache then we could. */
+        if (!DNS_PACKET_SHALL_CACHE(t->received))
+                return;
+
+        dns_cache_put(&t->scope->cache,
+                      t->key,
+                      t->answer_rcode,
+                      t->answer,
+                      t->answer_authenticated,
+                      t->answer_nsec_ttl,
+                      0,
+                      t->received->family,
+                      &t->received->sender);
+}
+
+static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
+        DnsTransaction *dt;
+        Iterator i;
+
+        assert(t);
+
+        SET_FOREACH(dt, t->dnssec_transactions, i)
+                if (DNS_TRANSACTION_IS_LIVE(dt->state))
+                        return true;
+
+        return false;
+}
+
+static int dns_transaction_dnssec_ready(DnsTransaction *t) {
+        DnsTransaction *dt;
+        Iterator i;
+
+        assert(t);
+
+        /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still
+         * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */
+
+        SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                switch (dt->state) {
+
+                case DNS_TRANSACTION_NULL:
+                case DNS_TRANSACTION_PENDING:
+                case DNS_TRANSACTION_VALIDATING:
+                        /* Still ongoing */
+                        return 0;
+
+                case DNS_TRANSACTION_RCODE_FAILURE:
+                        if (dt->answer_rcode != DNS_RCODE_NXDOMAIN) {
+                                log_debug("Auxiliary DNSSEC RR query failed with rcode=%s.", dns_rcode_to_string(dt->answer_rcode));
+                                goto fail;
+                        }
+
+                        /* Fall-through: NXDOMAIN is good enough for us. This is because some DNS servers erronously
+                         * return NXDOMAIN for empty non-terminals (Akamai...), and we need to handle that nicely, when
+                         * asking for parent SOA or similar RRs to make unsigned proofs. */
+
+                case DNS_TRANSACTION_SUCCESS:
+                        /* All good. */
+                        break;
+
+                case DNS_TRANSACTION_DNSSEC_FAILED:
+                        /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC
+                         * validationr result */
+
+                        log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(dt->answer_dnssec_result));
+                        t->answer_dnssec_result = dt->answer_dnssec_result; /* Copy error code over */
+                        dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
+                        return 0;
+
+
+                default:
+                        log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state));
+                        goto fail;
+                }
+        }
+
+        /* All is ready, we can go and validate */
+        return 1;
+
+fail:
+        t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY;
+        dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
+        return 0;
+}
+
+static void dns_transaction_process_dnssec(DnsTransaction *t) {
+        int r;
+
+        assert(t);
+
+        /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
+        r = dns_transaction_dnssec_ready(t);
+        if (r < 0)
+                goto fail;
+        if (r == 0) /* We aren't ready yet (or one of our auxiliary transactions failed, and we shouldn't validate now */
+                return;
+
+        /* See if we learnt things from the additional DNSSEC transactions, that we didn't know before, and better
+         * restart the lookup immediately. */
+        r = dns_transaction_maybe_restart(t);
+        if (r < 0)
+                goto fail;
+        if (r > 0) /* Transaction got restarted... */
+                return;
+
+        /* All our auxiliary DNSSEC transactions are complete now. Try
+         * to validate our RRset now. */
+        r = dns_transaction_validate_dnssec(t);
+        if (r == -EBADMSG) {
+                dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+                return;
+        }
+        if (r < 0)
+                goto fail;
+
+        if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
+            t->scope->dnssec_mode == DNSSEC_YES) {
+                /*  We are not in automatic downgrade mode, and the
+                 *  server is bad, refuse operation. */
+                dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
+                return;
+        }
+
+        if (!IN_SET(t->answer_dnssec_result,
+                    _DNSSEC_RESULT_INVALID,        /* No DNSSEC validation enabled */
+                    DNSSEC_VALIDATED,              /* Answer is signed and validated successfully */
+                    DNSSEC_UNSIGNED,               /* Answer is right-fully unsigned */
+                    DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */
+                dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
+                return;
+        }
+
+        if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER)
+                dns_server_warn_downgrade(t->server);
+
+        dns_transaction_cache_answer(t);
+
+        if (t->answer_rcode == DNS_RCODE_SUCCESS)
+                dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+        else
+                dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
+
+        return;
+
+fail:
+        t->answer_errno = -r;
+        dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+}
+
+static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
+        int r;
+
+        assert(t);
+
+        /* Checks whether the answer is positive, i.e. either a direct
+         * answer to the question, or a CNAME/DNAME for it */
+
+        r = dns_answer_match_key(t->answer, t->key, flags);
+        if (r != 0)
+                return r;
+
+        r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
+        if (r != 0)
+                return r;
+
+        return false;
+}
+
+static int dns_transaction_fix_rcode(DnsTransaction *t) {
+        int r;
+
+        assert(t);
+
+        /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the
+         * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a
+         * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first
+         * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when
+         * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle
+         * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a
+         * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server
+         * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an
+         * incomplete CNAME/DNAME chain.
+         *
+         * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS,
+         * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new
+         * lookup. */
+
+        if (t->answer_rcode != DNS_RCODE_NXDOMAIN)
+                return 0;
+
+        r = dns_transaction_has_positive_answer(t, NULL);
+        if (r <= 0)
+                return r;
+
+        t->answer_rcode = DNS_RCODE_SUCCESS;
+        return 0;
 }
 
 void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
@@ -342,15 +785,20 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
 
         assert(t);
         assert(p);
-        assert(t->state == DNS_TRANSACTION_PENDING);
         assert(t->scope);
         assert(t->scope->manager);
 
+        if (t->state != DNS_TRANSACTION_PENDING)
+                return;
+
         /* Note that this call might invalidate the query. Callers
          * should hence not attempt to access the query or transaction
          * after calling this function. */
 
+        log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
+
         switch (t->scope->protocol) {
+
         case DNS_PROTOCOL_LLMNR:
                 assert(t->scope->link);
 
@@ -373,7 +821,24 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
 
                 break;
 
+        case DNS_PROTOCOL_MDNS:
+                assert(t->scope->link);
+
+                /* For mDNS we will not accept any packets from other interfaces */
+                if (p->ifindex != t->scope->link->ifindex)
+                        return;
+
+                if (p->family != t->scope->family)
+                        return;
+
+                break;
+
         case DNS_PROTOCOL_DNS:
+                /* Note that we do not need to verify the
+                 * addresses/port numbers of incoming traffic, as we
+                 * invoked connect() on our UDP socket in which case
+                 * the kernel already does the needed verification for
+                 * us. */
                 break;
 
         default:
@@ -385,6 +850,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
                 t->received = dns_packet_ref(p);
         }
 
+        t->answer_source = DNS_TRANSACTION_NETWORK;
+
         if (p->ipproto == IPPROTO_TCP) {
                 if (DNS_PACKET_TC(p)) {
                         /* Truncated via TCP? Somebody must be fucking with us */
@@ -402,22 +869,42 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
         assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
 
         switch (t->scope->protocol) {
+
         case DNS_PROTOCOL_DNS:
                 assert(t->server);
 
-                dns_server_packet_received(t->server, ts - t->start_usec);
+                if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
+
+                        /* Request failed, immediately try again with reduced features */
+                        log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
+
+                        dns_server_packet_failed(t->server, t->current_feature_level);
+                        dns_transaction_retry(t);
+                        return;
+                } else if (DNS_PACKET_TC(p))
+                        dns_server_packet_truncated(t->server, t->current_feature_level);
 
                 break;
+
         case DNS_PROTOCOL_LLMNR:
         case DNS_PROTOCOL_MDNS:
                 dns_scope_packet_received(t->scope, ts - t->start_usec);
-
                 break;
+
         default:
-                break;
+                assert_not_reached("Invalid DNS protocol.");
         }
 
         if (DNS_PACKET_TC(p)) {
+
+                /* Truncated packets for mDNS are not allowed. Give up immediately. */
+                if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
+                        dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+                        return;
+                }
+
+                log_debug("Reply truncated, retrying via TCP.");
+
                 /* Response was truncated, let's try again with good old TCP */
                 r = dns_transaction_open_tcp(t);
                 if (r == -ESRCH) {
@@ -425,47 +912,101 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
                         dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
                         return;
                 }
+                if (r == -EOPNOTSUPP) {
+                        /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC  */
+                        dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
+                        return;
+                }
                 if (r < 0) {
                         /* On LLMNR, if we cannot connect to the host,
                          * we immediately give up */
-                        if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
-                                dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
-                                return;
-                        }
+                        if (t->scope->protocol != DNS_PROTOCOL_DNS)
+                                goto fail;
 
                         /* On DNS, couldn't send? Try immediately again, with a new server */
-                        dns_transaction_next_dns_server(t);
-
-                        r = dns_transaction_go(t);
-                        if (r < 0) {
-                                dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
-                                return;
-                        }
-
-                        return;
+                        dns_transaction_retry(t);
                 }
+
+                return;
         }
 
-        /* Parse and update the cache */
+        /* After the superficial checks, actually parse the message. */
         r = dns_packet_extract(p);
         if (r < 0) {
                 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
                 return;
         }
 
-        /* Only consider responses with equivalent query section to the request */
-        if (p->question->n_keys != 1 || dns_resource_key_equal(p->question->keys[0], t->key) <= 0) {
-                dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
-                return;
+        /* Report that the OPT RR was missing */
+        if (t->server) {
+                if (!p->opt)
+                        dns_server_packet_bad_opt(t->server, t->current_feature_level);
+
+                dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, ts - t->start_usec, p->size);
         }
 
-        /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
-        dns_cache_put(&t->scope->cache, t->key, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
+        /* See if we know things we didn't know before that indicate we better restart the lookup immediately. */
+        r = dns_transaction_maybe_restart(t);
+        if (r < 0)
+                goto fail;
+        if (r > 0) /* Transaction got restarted... */
+                return;
 
-        if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
-                dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
-        else
-                dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
+        if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
+
+                /* Only consider responses with equivalent query section to the request */
+                r = dns_packet_is_reply_for(p, t->key);
+                if (r < 0)
+                        goto fail;
+                if (r == 0) {
+                        dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+                        return;
+                }
+
+                /* Install the answer as answer to the transaction */
+                dns_answer_unref(t->answer);
+                t->answer = dns_answer_ref(p->answer);
+                t->answer_rcode = DNS_PACKET_RCODE(p);
+                t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+                t->answer_authenticated = false;
+
+                r = dns_transaction_fix_rcode(t);
+                if (r < 0)
+                        goto fail;
+
+                /* Block GC while starting requests for additional DNSSEC RRs */
+                t->block_gc++;
+                r = dns_transaction_request_dnssec_keys(t);
+                t->block_gc--;
+
+                /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */
+                if (!dns_transaction_gc(t))
+                        return;
+
+                /* Requesting additional keys might have resulted in
+                 * this transaction to fail, since the auxiliary
+                 * request failed for some reason. If so, we are not
+                 * in pending state anymore, and we should exit
+                 * quickly. */
+                if (t->state != DNS_TRANSACTION_PENDING)
+                        return;
+                if (r < 0)
+                        goto fail;
+                if (r > 0) {
+                        /* There are DNSSEC transactions pending now. Update the state accordingly. */
+                        t->state = DNS_TRANSACTION_VALIDATING;
+                        dns_transaction_close_connection(t);
+                        dns_transaction_stop_timeout(t);
+                        return;
+                }
+        }
+
+        dns_transaction_process_dnssec(t);
+        return;
+
+fail:
+        t->answer_errno = -r;
+        dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
 }
 
 static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@@ -477,99 +1018,126 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
         assert(t->scope);
 
         r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
-        if (r <= 0)
-                return r;
+        if (ERRNO_IS_DISCONNECT(-r)) {
+                usec_t usec;
 
-        if (dns_packet_validate_reply(p) > 0 &&
-            DNS_PACKET_ID(p) == t->id)
-                dns_transaction_process_reply(t, p);
-        else
-                log_debug("Invalid DNS packet.");
+                /* UDP connection failure get reported via ICMP and then are possible delivered to us on the next
+                 * recvmsg(). Treat this like a lost packet. */
+
+                log_debug_errno(r, "Connection failure for DNS UDP packet: %m");
+                assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+                dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level, usec - t->start_usec);
+
+                dns_transaction_retry(t);
+                return 0;
+        }
+        if (r < 0) {
+                dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+                t->answer_errno = -r;
+                return 0;
+        }
+
+        r = dns_packet_validate_reply(p);
+        if (r < 0) {
+                log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m");
+                return 0;
+        }
+        if (r == 0) {
+                log_debug("Received inappropriate DNS packet as response, ignoring.");
+                return 0;
+        }
 
+        if (DNS_PACKET_ID(p) != t->id) {
+                log_debug("Received packet with incorrect transaction ID, ignoring.");
+                return 0;
+        }
+
+        dns_transaction_process_reply(t, p);
         return 0;
 }
 
-static int dns_transaction_emit(DnsTransaction *t) {
+static int dns_transaction_emit_udp(DnsTransaction *t) {
         int r;
 
         assert(t);
 
-        if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
-                DnsServer *server = NULL;
-                _cleanup_close_ int fd = -1;
+        if (t->scope->protocol == DNS_PROTOCOL_DNS) {
 
-                fd = dns_scope_udp_dns_socket(t->scope, &server);
-                if (fd < 0)
-                        return fd;
-
-                r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
+                r = dns_transaction_pick_server(t);
                 if (r < 0)
                         return r;
 
-                t->dns_udp_fd = fd;
-                fd = -1;
-                t->server = dns_server_ref(server);
-        }
+                if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP)
+                        return -EAGAIN;
 
-        r = dns_scope_emit(t->scope, t->dns_udp_fd, t->sent);
-        if (r < 0)
-                return r;
+                if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
+                        return -EOPNOTSUPP;
 
-        return 0;
-}
+                if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
+                        int fd;
 
-static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
-        DnsTransaction *t = userdata;
-        int r;
+                        dns_transaction_close_connection(t);
 
-        assert(s);
-        assert(t);
+                        fd = dns_scope_socket_udp(t->scope, t->server, 53);
+                        if (fd < 0)
+                                return fd;
+
+                        r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
+                        if (r < 0) {
+                                safe_close(fd);
+                                return r;
+                        }
 
-        /* Timeout reached? Try again, with a new server */
-        dns_transaction_next_dns_server(t);
+                        (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp");
+                        t->dns_udp_fd = fd;
+                }
 
-        /* ... and possibly increased timeout */
-        if (t->server)
-                dns_server_packet_lost(t->server, usec - t->start_usec);
-        else
-                dns_scope_packet_lost(t->scope, usec - t->start_usec);
+                r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
+                if (r < 0)
+                        return r;
+        else
+                dns_transaction_close_connection(t);
 
-        r = dns_transaction_go(t);
+        r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent);
         if (r < 0)
-                dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+                return r;
+
+        dns_transaction_reset_answer(t);
 
         return 0;
 }
 
-static int dns_transaction_make_packet(DnsTransaction *t) {
-        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
-        int r;
+static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
+        DnsTransaction *t = userdata;
 
+        assert(s);
         assert(t);
 
-        if (t->sent)
-                return 0;
+        if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
+                /* Timeout reached? Increase the timeout for the server used */
+                switch (t->scope->protocol) {
 
-        r = dns_packet_new_query(&p, t->scope->protocol, 0);
-        if (r < 0)
-                return r;
+                case DNS_PROTOCOL_DNS:
+                        assert(t->server);
+                        dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level, usec - t->start_usec);
+                        break;
 
-        r = dns_scope_good_key(t->scope, t->key);
-        if (r < 0)
-                return r;
-        if (r == 0)
-                return -EDOM;
+                case DNS_PROTOCOL_LLMNR:
+                case DNS_PROTOCOL_MDNS:
+                        dns_scope_packet_lost(t->scope, usec - t->start_usec);
+                        break;
 
-        r = dns_packet_append_key(p, t->key, NULL);
-        if (r < 0)
-                return r;
+                default:
+                        assert_not_reached("Invalid DNS protocol.");
+                }
 
-        DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
-        DNS_PACKET_HEADER(p)->id = t->id;
+                if (t->initial_jitter_scheduled)
+                        t->initial_jitter_elapsed = true;
+        }
 
-        t->sent = p;
-        p = NULL;
+        log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
 
+        dns_transaction_retry(t);
         return 0;
 }
 
@@ -578,57 +1146,124 @@ static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
         assert(t->scope);
 
         switch (t->scope->protocol) {
+
         case DNS_PROTOCOL_DNS:
                 assert(t->server);
-
                 return t->server->resend_timeout;
-        case DNS_PROTOCOL_LLMNR:
+
         case DNS_PROTOCOL_MDNS:
+                assert(t->n_attempts > 0);
+                return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
+
+        case DNS_PROTOCOL_LLMNR:
                 return t->scope->resend_timeout;
+
         default:
                 assert_not_reached("Invalid DNS protocol.");
         }
 }
 
-int dns_transaction_go(DnsTransaction *t) {
-        bool had_stream;
-        usec_t ts;
+static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
         int r;
 
         assert(t);
 
-        had_stream = !!t->stream;
-
-        dns_transaction_stop(t);
+        dns_transaction_stop_timeout(t);
 
-        log_debug("Excercising transaction on scope %s on %s/%s",
-                  dns_protocol_to_string(t->scope->protocol),
-                  t->scope->link ? t->scope->link->name : "*",
-                  t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
+        r = dns_scope_network_good(t->scope);
+        if (r < 0)
+                return r;
+        if (r == 0) {
+                dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN);
+                return 0;
+        }
 
         if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
                 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
                 return 0;
         }
 
-        if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
+        if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) {
                 /* If we already tried via a stream, then we don't
                  * retry on LLMNR. See RFC 4795, Section 2.7. */
                 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
                 return 0;
         }
 
-        assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
-
         t->n_attempts++;
         t->start_usec = ts;
-        t->received = dns_packet_unref(t->received);
-        t->cached = dns_answer_unref(t->cached);
-        t->cached_rcode = 0;
+
+        dns_transaction_reset_answer(t);
+        dns_transaction_flush_dnssec_transactions(t);
+
+        /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
+        if (t->scope->protocol == DNS_PROTOCOL_DNS) {
+                r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        t->answer_rcode = DNS_RCODE_SUCCESS;
+                        t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
+                        t->answer_authenticated = true;
+                        dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+                        return 0;
+                }
+
+                if (dns_name_is_root(DNS_RESOURCE_KEY_NAME(t->key)) &&
+                    t->key->type == DNS_TYPE_DS) {
+
+                        /* Hmm, this is a request for the root DS? A
+                         * DS RR doesn't exist in the root zone, and
+                         * if our trust anchor didn't know it either,
+                         * this means we cannot do any DNSSEC logic
+                         * anymore. */
+
+                        if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
+                                /* We are in downgrade mode. In this
+                                 * case, synthesize an unsigned empty
+                                 * response, so that the any lookup
+                                 * depending on this one can continue
+                                 * assuming there was no DS, and hence
+                                 * the root zone was unsigned. */
+
+                                t->answer_rcode = DNS_RCODE_SUCCESS;
+                                t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
+                                t->answer_authenticated = false;
+                                dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+                        } else
+                                /* If we are not in downgrade mode,
+                                 * then fail the lookup, because we
+                                 * cannot reasonably answer it. There
+                                 * might be DS RRs, but we don't know
+                                 * them, and the DNS server won't tell
+                                 * them to us (and even if it would,
+                                 * we couldn't validate it and trust
+                                 * it). */
+                                dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR);
+
+                        return 0;
+                }
+        }
+
+        /* Check the zone, but only if this transaction is not used
+         * for probing or verifying a zone item. */
+        if (set_isempty(t->notify_zone_items)) {
+
+                r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        t->answer_rcode = DNS_RCODE_SUCCESS;
+                        t->answer_source = DNS_TRANSACTION_ZONE;
+                        t->answer_authenticated = true;
+                        dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+                        return 0;
+                }
+        }
 
         /* Check the cache, but only if this transaction is not used
          * for probing or verifying a zone item. */
-        if (set_isempty(t->zone_items)) {
+        if (set_isempty(t->notify_zone_items)) {
 
                 /* Before trying the cache, let's make sure we figured out a
                  * server to use. Should this cause a change of server this
@@ -638,55 +1273,223 @@ int dns_transaction_go(DnsTransaction *t) {
                 /* Let's then prune all outdated entries */
                 dns_cache_prune(&t->scope->cache);
 
-                r = dns_cache_lookup(&t->scope->cache, t->key, &t->cached_rcode, &t->cached);
+                r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
                 if (r < 0)
                         return r;
                 if (r > 0) {
-                        if (t->cached_rcode == DNS_RCODE_SUCCESS)
+                        t->answer_source = DNS_TRANSACTION_CACHE;
+                        if (t->answer_rcode == DNS_RCODE_SUCCESS)
                                 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
                         else
-                                dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
+                                dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
                         return 0;
                 }
         }
 
-        if (t->scope->protocol == DNS_PROTOCOL_LLMNR && !t->initial_jitter) {
-                usec_t jitter;
+        return 1;
+}
+
+static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
+
+        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+        bool add_known_answers = false;
+        DnsTransaction *other;
+        unsigned qdcount;
+        usec_t ts;
+        int r;
+
+        assert(t);
+        assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
+
+        /* Discard any previously prepared packet, so we can start over and coalesce again */
+        t->sent = dns_packet_unref(t->sent);
+
+        r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
+        if (r < 0)
+                return r;
+
+        r = dns_packet_append_key(p, t->key, NULL);
+        if (r < 0)
+                return r;
+
+        qdcount = 1;
+
+        if (dns_key_is_shared(t->key))
+                add_known_answers = true;
+
+        /*
+         * For mDNS, we want to coalesce as many open queries in pending transactions into one single
+         * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
+         * in our current scope, and see whether their timing contraints allow them to be sent.
+         */
+
+        assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
+
+        LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
+
+                /* Skip ourselves */
+                if (other == t)
+                        continue;
+
+                if (other->state != DNS_TRANSACTION_PENDING)
+                        continue;
+
+                if (other->next_attempt_after > ts)
+                        continue;
+
+                if (qdcount >= UINT16_MAX)
+                        break;
+
+                r = dns_packet_append_key(p, other->key, NULL);
+
+                /*
+                 * If we can't stuff more questions into the packet, just give up.
+                 * One of the 'other' transactions will fire later and take care of the rest.
+                 */
+                if (r == -EMSGSIZE)
+                        break;
+
+                if (r < 0)
+                        return r;
+
+                r = dns_transaction_prepare(other, ts);
+                if (r <= 0)
+                        continue;
+
+                ts += transaction_get_resend_timeout(other);
+
+                r = sd_event_add_time(
+                                other->scope->manager->event,
+                                &other->timeout_event_source,
+                                clock_boottime_or_monotonic(),
+                                ts, 0,
+                                on_transaction_timeout, other);
+                if (r < 0)
+                        return r;
+
+                (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
+
+                other->state = DNS_TRANSACTION_PENDING;
+                other->next_attempt_after = ts;
+
+                qdcount ++;
+
+                if (dns_key_is_shared(other->key))
+                        add_known_answers = true;
+        }
+
+        DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
+
+        /* Append known answer section if we're asking for any shared record */
+        if (add_known_answers) {
+                r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
+                if (r < 0)
+                        return r;
+        }
+
+        t->sent = p;
+        p = NULL;
+
+        return 0;
+}
+
+static int dns_transaction_make_packet(DnsTransaction *t) {
+        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+        int r;
+
+        assert(t);
+
+        if (t->scope->protocol == DNS_PROTOCOL_MDNS)
+                return dns_transaction_make_packet_mdns(t);
+
+        if (t->sent)
+                return 0;
+
+        r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO);
+        if (r < 0)
+                return r;
+
+        r = dns_packet_append_key(p, t->key, NULL);
+        if (r < 0)
+                return r;
+
+        DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
+        DNS_PACKET_HEADER(p)->id = t->id;
+
+        t->sent = p;
+        p = NULL;
+
+        return 0;
+}
+
+int dns_transaction_go(DnsTransaction *t) {
+        usec_t ts;
+        int r;
+
+        assert(t);
+
+        assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
+
+        r = dns_transaction_prepare(t, ts);
+        if (r <= 0)
+                return r;
+
+        log_debug("Excercising transaction %" PRIu16 " for <%s> on scope %s on %s/%s.",
+                  t->id,
+                  dns_transaction_key_string(t),
+                  dns_protocol_to_string(t->scope->protocol),
+                  t->scope->link ? t->scope->link->name : "*",
+                  t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
+
+        if (!t->initial_jitter_scheduled &&
+            (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
+             t->scope->protocol == DNS_PROTOCOL_MDNS)) {
+                usec_t jitter, accuracy;
 
                 /* RFC 4795 Section 2.7 suggests all queries should be
                  * delayed by a random time from 0 to JITTER_INTERVAL. */
 
-                t->initial_jitter = true;
+                t->initial_jitter_scheduled = true;
 
                 random_bytes(&jitter, sizeof(jitter));
-                jitter %= LLMNR_JITTER_INTERVAL_USEC;
+
+                switch (t->scope->protocol) {
+
+                case DNS_PROTOCOL_LLMNR:
+                        jitter %= LLMNR_JITTER_INTERVAL_USEC;
+                        accuracy = LLMNR_JITTER_INTERVAL_USEC;
+                        break;
+
+                case DNS_PROTOCOL_MDNS:
+                        jitter %= MDNS_JITTER_RANGE_USEC;
+                        jitter += MDNS_JITTER_MIN_USEC;
+                        accuracy = MDNS_JITTER_RANGE_USEC;
+                        break;
+                default:
+                        assert_not_reached("bad protocol");
+                }
 
                 r = sd_event_add_time(
                                 t->scope->manager->event,
                                 &t->timeout_event_source,
                                 clock_boottime_or_monotonic(),
-                                ts + jitter,
-                                LLMNR_JITTER_INTERVAL_USEC,
+                                ts + jitter, accuracy,
                                 on_transaction_timeout, t);
                 if (r < 0)
                         return r;
 
+                (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
+
                 t->n_attempts = 0;
+                t->next_attempt_after = ts;
                 t->state = DNS_TRANSACTION_PENDING;
 
-                log_debug("Delaying LLMNR transaction for " USEC_FMT "us.", jitter);
+                log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
                 return 0;
         }
 
         /* Otherwise, we need to ask the network */
         r = dns_transaction_make_packet(t);
-        if (r == -EDOM) {
-                /* Not the right request to make on this network?
-                 * (i.e. an A request made on IPv6 or an AAAA request
-                 * made on IPv4, on LLMNR or mDNS.) */
-                dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
-                return 0;
-        }
         if (r < 0)
                 return r;
 
@@ -698,50 +1501,1526 @@ int dns_transaction_go(DnsTransaction *t) {
                  * always be made via TCP on LLMNR */
                 r = dns_transaction_open_tcp(t);
         } else {
-                /* Try via UDP, and if that fails due to large size try via TCP */
-                r = dns_transaction_emit(t);
+                /* Try via UDP, and if that fails due to large size or lack of
+                 * support try via TCP */
+                r = dns_transaction_emit_udp(t);
                 if (r == -EMSGSIZE)
+                        log_debug("Sending query via TCP since it is too large.");
+                if (r == -EAGAIN)
+                        log_debug("Sending query via TCP since server doesn't support UDP.");
+                if (r == -EMSGSIZE || r == -EAGAIN)
                         r = dns_transaction_open_tcp(t);
         }
+
         if (r == -ESRCH) {
                 /* No servers to send this to? */
                 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
                 return 0;
-        } else if (r < 0) {
-                if (t->scope->protocol != DNS_PROTOCOL_DNS) {
-                        dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
-                        return 0;
-                }
+        }
+        if (r == -EOPNOTSUPP) {
+                /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC  */
+                dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
+                return 0;
+        }
+        if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(-r)) {
+                /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot
+                 * answer this request with this protocol. */
+                dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
+                return 0;
+        }
+        if (r < 0) {
+                if (t->scope->protocol != DNS_PROTOCOL_DNS)
+                        return r;
 
                 /* Couldn't send? Try immediately again, with a new server */
-                dns_transaction_next_dns_server(t);
+                dns_scope_next_dns_server(t->scope);
 
                 return dns_transaction_go(t);
         }
 
+        ts += transaction_get_resend_timeout(t);
+
         r = sd_event_add_time(
                         t->scope->manager->event,
                         &t->timeout_event_source,
                         clock_boottime_or_monotonic(),
-                        ts + transaction_get_resend_timeout(t), 0,
+                        ts, 0,
                         on_transaction_timeout, t);
         if (r < 0)
                 return r;
 
+        (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
+
         t->state = DNS_TRANSACTION_PENDING;
+        t->next_attempt_after = ts;
+
         return 1;
 }
 
-static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
-        [DNS_TRANSACTION_NULL] = "null",
-        [DNS_TRANSACTION_PENDING] = "pending",
-        [DNS_TRANSACTION_FAILURE] = "failure",
-        [DNS_TRANSACTION_SUCCESS] = "success",
-        [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
-        [DNS_TRANSACTION_TIMEOUT] = "timeout",
-        [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
+static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
+        DnsTransaction *n;
+        Iterator i;
+        int r;
+
+        assert(t);
+        assert(aux);
+
+        /* Try to find cyclic dependencies between transaction objects */
+
+        if (t == aux)
+                return 1;
+
+        SET_FOREACH(n, aux->dnssec_transactions, i) {
+                r = dns_transaction_find_cyclic(t, n);
+                if (r != 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
+        DnsTransaction *aux;
+        int r;
+
+        assert(t);
+        assert(ret);
+        assert(key);
+
+        aux = dns_scope_find_transaction(t->scope, key, true);
+        if (!aux) {
+                r = dns_transaction_new(&aux, t->scope, key);
+                if (r < 0)
+                        return r;
+        } else {
+                if (set_contains(t->dnssec_transactions, aux)) {
+                        *ret = aux;
+                        return 0;
+                }
+
+                r = dns_transaction_find_cyclic(t, aux);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        log_debug("Detected potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).",
+                                  aux->id,
+                                  strna(dns_transaction_key_string(aux)),
+                                  t->id,
+                                  strna(dns_transaction_key_string(t)));
+                        return -ELOOP;
+                }
+        }
+
+        r = set_ensure_allocated(&t->dnssec_transactions, NULL);
+        if (r < 0)
+                goto gc;
+
+        r = set_ensure_allocated(&aux->notify_transactions, NULL);
+        if (r < 0)
+                goto gc;
+
+        r = set_put(t->dnssec_transactions, aux);
+        if (r < 0)
+                goto gc;
+
+        r = set_put(aux->notify_transactions, t);
+        if (r < 0) {
+                (void) set_remove(t->dnssec_transactions, aux);
+                goto gc;
+        }
+
+        *ret = aux;
+        return 1;
+
+gc:
+        dns_transaction_gc(aux);
+        return r;
+}
+
+static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
+        DnsTransaction *aux;
+        int r;
+
+        assert(t);
+        assert(key);
+
+        /* Try to get the data from the trust anchor */
+        r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                r = dns_answer_extend(&t->validated_keys, a);
+                if (r < 0)
+                        return r;
+
+                return 0;
+        }
+
+        /* This didn't work, ask for it via the network/cache then. */
+        r = dns_transaction_add_dnssec_transaction(t, key, &aux);
+        if (r == -ELOOP) /* This would result in a cyclic dependency */
+                return 0;
+        if (r < 0)
+                return r;
+
+        if (aux->state == DNS_TRANSACTION_NULL) {
+                r = dns_transaction_go(aux);
+                if (r < 0)
+                        return r;
+        }
+
+        return 1;
+}
+
+static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
+        int r;
+
+        assert(t);
+
+        /* Check whether the specified name is in the the NTA
+         * database, either in the global one, or the link-local
+         * one. */
+
+        r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name);
+        if (r != 0)
+                return r;
+
+        if (!t->scope->link)
+                return 0;
+
+        return set_contains(t->scope->link->dnssec_negative_trust_anchors, name);
+}
+
+static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
+        int r;
+
+        assert(t);
+
+        /* Checks whether the answer is negative, and lacks NSEC/NSEC3
+         * RRs to prove it */
+
+        r = dns_transaction_has_positive_answer(t, NULL);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        /* Is this key explicitly listed as a negative trust anchor?
+         * If so, it's nothing we need to care about */
+        r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key));
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        /* The answer does not contain any RRs that match to the
+         * question. If so, let's see if there are any NSEC/NSEC3 RRs
+         * included. If not, the answer is unsigned. */
+
+        r = dns_answer_contains_nsec_or_nsec3(t->answer);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        return true;
+}
+
+static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
+        int r;
+
+        assert(t);
+        assert(rr);
+
+        /* Check if the specified RR is the "primary" response,
+         * i.e. either matches the question precisely or is a
+         * CNAME/DNAME for it. */
+
+        r = dns_resource_key_match_rr(t->key, rr, NULL);
+        if (r != 0)
+                return r;
+
+        return dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
+}
+
+static bool dns_transaction_dnssec_supported(DnsTransaction *t) {
+        assert(t);
+
+        /* Checks whether our transaction's DNS server is assumed to be compatible with DNSSEC. Returns false as soon
+         * as we changed our mind about a server, and now believe it is incompatible with DNSSEC. */
+
+        if (t->scope->protocol != DNS_PROTOCOL_DNS)
+                return false;
+
+        /* If we have picked no server, then we are working from the cache or some other source, and DNSSEC might well
+         * be supported, hence return true. */
+        if (!t->server)
+                return true;
+
+        if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
+                return false;
+
+        return dns_server_dnssec_supported(t->server);
+}
+
+static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
+        DnsTransaction *dt;
+        Iterator i;
+
+        assert(t);
+
+        /* Checks whether our transaction our any of the auxiliary transactions couldn't do DNSSEC. */
+
+        if (!dns_transaction_dnssec_supported(t))
+                return false;
+
+        SET_FOREACH(dt, t->dnssec_transactions, i)
+                if (!dns_transaction_dnssec_supported(dt))
+                        return false;
+
+        return true;
+}
+
+int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
+        DnsResourceRecord *rr;
+
+        int r;
+
+        assert(t);
+
+        /*
+         * Retrieve all auxiliary RRs for the answer we got, so that
+         * we can verify signatures or prove that RRs are rightfully
+         * unsigned. Specifically:
+         *
+         * - For RRSIG we get the matching DNSKEY
+         * - For DNSKEY we get the matching DS
+         * - For unsigned SOA/NS we get the matching DS
+         * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
+         * - For other unsigned RRs we get the matching SOA RR
+         * - For SOA/NS/DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
+         * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
+         */
+
+        if (t->scope->dnssec_mode == DNSSEC_NO)
+                return 0;
+        if (t->answer_source != DNS_TRANSACTION_NETWORK)
+                return 0; /* We only need to validate stuff from the network */
+        if (!dns_transaction_dnssec_supported(t))
+                return 0; /* If we can't do DNSSEC anyway there's no point in geting the auxiliary RRs */
+
+        DNS_ANSWER_FOREACH(rr, t->answer) {
+
+                if (dns_type_is_pseudo(rr->key->type))
+                        continue;
+
+                /* If this RR is in the negative trust anchor, we don't need to validate it. */
+                r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                switch (rr->key->type) {
+
+                case DNS_TYPE_RRSIG: {
+                        /* For each RRSIG we request the matching DNSKEY */
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
+
+                        /* If this RRSIG is about a DNSKEY RR and the
+                         * signer is the same as the owner, then we
+                         * already have the DNSKEY, and we don't have
+                         * to look for more. */
+                        if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
+                                r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key));
+                                if (r < 0)
+                                        return r;
+                                if (r > 0)
+                                        continue;
+                        }
+
+                        /* If the signer is not a parent of our
+                         * original query, then this is about an
+                         * auxiliary RRset, but not anything we asked
+                         * for. In this case we aren't interested,
+                         * because we don't want to request additional
+                         * RRs for stuff we didn't really ask for, and
+                         * also to avoid request loops, where
+                         * additional RRs from one transaction result
+                         * in another transaction whose additonal RRs
+                         * point back to the original transaction, and
+                         * we deadlock. */
+                        r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), rr->rrsig.signer);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
+                        if (!dnskey)
+                                return -ENOMEM;
+
+                        log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.key_tag);
+                        r = dns_transaction_request_dnssec_rr(t, dnskey);
+                        if (r < 0)
+                                return r;
+                        break;
+                }
+
+                case DNS_TYPE_DNSKEY: {
+                        /* For each DNSKEY we request the matching DS */
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
+
+                        /* If the DNSKEY we are looking at is not for
+                         * zone we are interested in, nor any of its
+                         * parents, we aren't interested, and don't
+                         * request it. After all, we don't want to end
+                         * up in request loops, and want to keep
+                         * additional traffic down. */
+
+                        r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (!ds)
+                                return -ENOMEM;
+
+                        log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dnssec_keytag(rr, false));
+                        r = dns_transaction_request_dnssec_rr(t, ds);
+                        if (r < 0)
+                                return r;
+
+                        break;
+                }
+
+                case DNS_TYPE_SOA:
+                case DNS_TYPE_NS: {
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
+
+                        /* For an unsigned SOA or NS, try to acquire
+                         * the matching DS RR, as we are at a zone cut
+                         * then, and whether a DS exists tells us
+                         * whether the zone is signed. Do so only if
+                         * this RR matches our original question,
+                         * however. */
+
+                        r = dns_resource_key_match_rr(t->key, rr, NULL);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = dnssec_has_rrsig(t->answer, rr->key);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (!ds)
+                                return -ENOMEM;
+
+                        log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
+                        r = dns_transaction_request_dnssec_rr(t, ds);
+                        if (r < 0)
+                                return r;
+
+                        break;
+                }
+
+                case DNS_TYPE_DS:
+                case DNS_TYPE_CNAME:
+                case DNS_TYPE_DNAME: {
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+                        const char *name;
+
+                        /* CNAMEs and DNAMEs cannot be located at a
+                         * zone apex, hence ask for the parent SOA for
+                         * unsigned CNAME/DNAME RRs, maybe that's the
+                         * apex. But do all that only if this is
+                         * actually a response to our original
+                         * question.
+                         *
+                         * Similar for DS RRs, which are signed when
+                         * the parent SOA is signed. */
+
+                        r = dns_transaction_is_primary_response(t, rr);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = dnssec_has_rrsig(t->answer, rr->key);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        r = dns_answer_has_dname_for_cname(t->answer, rr);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        name = DNS_RESOURCE_KEY_NAME(rr->key);
+                        r = dns_name_parent(&name);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
+                        if (!soa)
+                                return -ENOMEM;
+
+                        log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
+                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        if (r < 0)
+                                return r;
+
+                        break;
+                }
+
+                default: {
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+
+                        /* For other unsigned RRsets (including
+                         * NSEC/NSEC3!), look for proof the zone is
+                         * unsigned, by requesting the SOA RR of the
+                         * zone. However, do so only if they are
+                         * directly relevant to our original
+                         * question. */
+
+                        r = dns_transaction_is_primary_response(t, rr);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        r = dnssec_has_rrsig(t->answer, rr->key);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+
+                        soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (!soa)
+                                return -ENOMEM;
+
+                        log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dns_resource_record_to_string(rr));
+                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        if (r < 0)
+                                return r;
+                        break;
+                }}
+        }
+
+        /* Above, we requested everything necessary to validate what
+         * we got. Now, let's request what we need to validate what we
+         * didn't get... */
+
+        r = dns_transaction_has_unsigned_negative_answer(t);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                const char *name;
+
+                name = DNS_RESOURCE_KEY_NAME(t->key);
+
+                /* If this was a SOA or NS request, then this
+                 * indicates that we are not at a zone apex, hence ask
+                 * the parent name instead. If this was a DS request,
+                 * then it's signed when the parent zone is signed,
+                 * hence ask the parent in that case, too. */
+
+                if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
+                        r = dns_name_parent(&name);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
+                        else
+                                name = NULL;
+                } else
+                        log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
+
+                if (name) {
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+
+                        soa = dns_resource_key_new(t->key->class, DNS_TYPE_SOA, name);
+                        if (!soa)
+                                return -ENOMEM;
+
+                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return dns_transaction_dnssec_is_live(t);
+}
+
+void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
+        assert(t);
+        assert(source);
+
+        /* Invoked whenever any of our auxiliary DNSSEC transactions completed its work. If the state is still PENDING,
+           we are still in the loop that adds further DNSSEC transactions, hence don't check if we are ready yet. If
+           the state is VALIDATING however, we should check if we are complete now. */
+
+        if (t->state == DNS_TRANSACTION_VALIDATING)
+                dns_transaction_process_dnssec(t);
+}
+
+static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
+        DnsResourceRecord *rr;
+        int ifindex, r;
+
+        assert(t);
+
+        /* Add all DNSKEY RRs from the answer that are validated by DS
+         * RRs from the list of validated keys to the list of
+         * validated keys. */
+
+        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
+
+                r = dnssec_verify_dnskey_by_ds_search(rr, t->validated_keys);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                /* If so, the DNSKEY is validated too. */
+                r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) {
+        int r;
+
+        assert(t);
+        assert(rr);
+
+        /* Checks if the RR we are looking for must be signed with an
+         * RRSIG. This is used for positive responses. */
+
+        if (t->scope->dnssec_mode == DNSSEC_NO)
+                return false;
+
+        if (dns_type_is_pseudo(rr->key->type))
+                return -EINVAL;
+
+        r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        switch (rr->key->type) {
+
+        case DNS_TYPE_RRSIG:
+                /* RRSIGs are the signatures themselves, they need no signing. */
+                return false;
+
+        case DNS_TYPE_SOA:
+        case DNS_TYPE_NS: {
+                DnsTransaction *dt;
+                Iterator i;
+
+                /* For SOA or NS RRs we look for a matching DS transaction */
+
+                SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                        if (dt->key->class != rr->key->class)
+                                continue;
+                        if (dt->key->type != DNS_TYPE_DS)
+                                continue;
+
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        /* We found a DS transactions for the SOA/NS
+                         * RRs we are looking at. If it discovered signed DS
+                         * RRs, then we need to be signed, too. */
+
+                        if (!dt->answer_authenticated)
+                                return false;
+
+                        return dns_answer_match_key(dt->answer, dt->key, NULL);
+                }
+
+                /* We found nothing that proves this is safe to leave
+                 * this unauthenticated, hence ask inist on
+                 * authentication. */
+                return true;
+        }
+
+        case DNS_TYPE_DS:
+        case DNS_TYPE_CNAME:
+        case DNS_TYPE_DNAME: {
+                const char *parent = NULL;
+                DnsTransaction *dt;
+                Iterator i;
+
+                /*
+                 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
+                 *
+                 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
+                 */
+
+                SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                        if (dt->key->class != rr->key->class)
+                                continue;
+                        if (dt->key->type != DNS_TYPE_SOA)
+                                continue;
+
+                        if (!parent) {
+                                parent = DNS_RESOURCE_KEY_NAME(rr->key);
+                                r = dns_name_parent(&parent);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0) {
+                                        if (rr->key->type == DNS_TYPE_DS)
+                                                return true;
+
+                                        /* A CNAME/DNAME without a parent? That's sooo weird. */
+                                        log_debug("Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id);
+                                        return -EBADMSG;
+                                }
+                        }
+
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), parent);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        return t->answer_authenticated;
+                }
+
+                return true;
+        }
+
+        default: {
+                DnsTransaction *dt;
+                Iterator i;
+
+                /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
+
+                SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                        if (dt->key->class != rr->key->class)
+                                continue;
+                        if (dt->key->type != DNS_TYPE_SOA)
+                                continue;
+
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        /* We found the transaction that was supposed to find
+                         * the SOA RR for us. It was successful, but found no
+                         * RR for us. This means we are not at a zone cut. In
+                         * this case, we require authentication if the SOA
+                         * lookup was authenticated too. */
+                        return t->answer_authenticated;
+                }
+
+                return true;
+        }}
+}
+
+static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) {
+        DnsTransaction *dt;
+        const char *tld;
+        Iterator i;
+        int r;
+
+        /* If DNSSEC downgrade mode is on, checks whether the
+         * specified RR is one level below a TLD we have proven not to
+         * exist. In such a case we assume that this is a private
+         * domain, and permit it.
+         *
+         * This detects cases like the Fritz!Box router networks. Each
+         * Fritz!Box router serves a private "fritz.box" zone, in the
+         * non-existing TLD "box". Requests for the "fritz.box" domain
+         * are served by the router itself, while requests for the
+         * "box" domain will result in NXDOMAIN.
+         *
+         * Note that this logic is unable to detect cases where a
+         * router serves a private DNS zone directly under
+         * non-existing TLD. In such a case we cannot detect whether
+         * the TLD is supposed to exist or not, as all requests we
+         * make for it will be answered by the router's zone, and not
+         * by the root zone. */
+
+        assert(t);
+
+        if (t->scope->dnssec_mode != DNSSEC_ALLOW_DOWNGRADE)
+                return false; /* In strict DNSSEC mode what doesn't exist, doesn't exist */
+
+        tld = DNS_RESOURCE_KEY_NAME(key);
+        r = dns_name_parent(&tld);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return false; /* Already the root domain */
+
+        if (!dns_name_is_single_label(tld))
+                return false;
+
+        SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                if (dt->key->class != key->class)
+                        continue;
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), tld);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                /* We found an auxiliary lookup we did for the TLD. If
+                 * that returned with NXDOMAIN, we know the TLD didn't
+                 * exist, and hence this might be a private zone. */
+
+                return dt->answer_rcode == DNS_RCODE_NXDOMAIN;
+        }
+
+        return false;
+}
+
+static int dns_transaction_requires_nsec(DnsTransaction *t) {
+        DnsTransaction *dt;
+        const char *name;
+        Iterator i;
+        int r;
+
+        assert(t);
+
+        /* Checks if we need to insist on NSEC/NSEC3 RRs for proving
+         * this negative reply */
+
+        if (t->scope->dnssec_mode == DNSSEC_NO)
+                return false;
+
+        if (dns_type_is_pseudo(t->key->type))
+                return -EINVAL;
+
+        r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key));
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        r = dns_transaction_in_private_tld(t, t->key);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                /* The lookup is from a TLD that is proven not to
+                 * exist, and we are in downgrade mode, hence ignore
+                 * that fact that we didn't get any NSEC RRs.*/
+
+                log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.", dns_transaction_key_string(t));
+                return false;
+        }
+
+        name = DNS_RESOURCE_KEY_NAME(t->key);
+
+        if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
+
+                /* We got a negative reply for this SOA/NS lookup? If
+                 * so, then we are not at a zone apex, and thus should
+                 * look at the result of the parent SOA lookup.
+                 *
+                 * We got a negative reply for this DS lookup? DS RRs
+                 * are signed when their parent zone is signed, hence
+                 * also check the parent SOA in this case. */
+
+                r = dns_name_parent(&name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return true;
+        }
+
+        /* For all other RRs we check the SOA on the same level to see
+         * if it's signed. */
+
+        SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                if (dt->key->class != t->key->class)
+                        continue;
+                if (dt->key->type != DNS_TYPE_SOA)
+                        continue;
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                return dt->answer_authenticated;
+        }
+
+        /* If in doubt, require NSEC/NSEC3 */
+        return true;
+}
+
+static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) {
+        DnsResourceRecord *rrsig;
+        bool found = false;
+        int r;
+
+        /* Checks whether any of the DNSKEYs used for the RRSIGs for
+         * the specified RRset is authenticated (i.e. has a matching
+         * DS RR). */
+
+        r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key));
+        if (r < 0)
+                return r;
+        if (r > 0)
+                return false;
+
+        DNS_ANSWER_FOREACH(rrsig, t->answer) {
+                DnsTransaction *dt;
+                Iterator i;
+
+                r = dnssec_key_match_rrsig(rr->key, rrsig);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                        if (dt->key->class != rr->key->class)
+                                continue;
+
+                        if (dt->key->type == DNS_TYPE_DNSKEY) {
+
+                                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        continue;
+
+                                /* OK, we found an auxiliary DNSKEY
+                                 * lookup. If that lookup is
+                                 * authenticated, report this. */
+
+                                if (dt->answer_authenticated)
+                                        return true;
+
+                                found = true;
+
+                        } else if (dt->key->type == DNS_TYPE_DS) {
+
+                                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        continue;
+
+                                /* OK, we found an auxiliary DS
+                                 * lookup. If that lookup is
+                                 * authenticated and non-zero, we
+                                 * won! */
+
+                                if (!dt->answer_authenticated)
+                                        return false;
+
+                                return dns_answer_match_key(dt->answer, dt->key, NULL);
+                        }
+                }
+        }
+
+        return found ? false : -ENXIO;
+}
+
+static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) {
+        assert(t);
+        assert(rr);
+
+        /* We know that the root domain is signed, hence if it appears
+         * not to be signed, there's a problem with the DNS server */
+
+        return rr->key->class == DNS_CLASS_IN &&
+                dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key));
+}
+
+static int dns_transaction_check_revoked_trust_anchors(DnsTransaction *t) {
+        DnsResourceRecord *rr;
+        int r;
+
+        assert(t);
+
+        /* Maybe warn the user that we encountered a revoked DNSKEY
+         * for a key from our trust anchor. Note that we don't care
+         * whether the DNSKEY can be authenticated or not. It's
+         * sufficient if it is self-signed. */
+
+        DNS_ANSWER_FOREACH(rr, t->answer) {
+                r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, rr, t->answer);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) {
+        bool changed;
+        int r;
+
+        assert(t);
+
+        /* Removes all DNSKEY/DS objects from t->validated_keys that
+         * our trust anchors database considers revoked. */
+
+        do {
+                DnsResourceRecord *rr;
+
+                changed = false;
+
+                DNS_ANSWER_FOREACH(rr, t->validated_keys) {
+                        r = dns_trust_anchor_is_revoked(&t->scope->manager->trust_anchor, rr);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                r = dns_answer_remove_by_rr(&t->validated_keys, rr);
+                                if (r < 0)
+                                        return r;
+
+                                assert(r > 0);
+                                changed = true;
+                                break;
+                        }
+                }
+        } while (changed);
+
+        return 0;
+}
+
+static int dns_transaction_copy_validated(DnsTransaction *t) {
+        DnsTransaction *dt;
+        Iterator i;
+        int r;
+
+        assert(t);
+
+        /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */
+
+        SET_FOREACH(dt, t->dnssec_transactions, i) {
+
+                if (DNS_TRANSACTION_IS_LIVE(dt->state))
+                        continue;
+
+                if (!dt->answer_authenticated)
+                        continue;
+
+                r = dns_answer_extend(&t->validated_keys, dt->answer);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int dns_transaction_validate_dnssec(DnsTransaction *t) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
+        enum {
+                PHASE_DNSKEY,   /* Phase #1, only validate DNSKEYs */
+                PHASE_NSEC,     /* Phase #2, only validate NSEC+NSEC3 */
+                PHASE_ALL,      /* Phase #3, validate everything else */
+        } phase;
+        DnsResourceRecord *rr;
+        DnsAnswerFlags flags;
+        int r;
+
+        assert(t);
+
+        /* We have now collected all DS and DNSKEY RRs in
+         * t->validated_keys, let's see which RRs we can now
+         * authenticate with that. */
+
+        if (t->scope->dnssec_mode == DNSSEC_NO)
+                return 0;
+
+        /* Already validated */
+        if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID)
+                return 0;
+
+        /* Our own stuff needs no validation */
+        if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
+                t->answer_dnssec_result = DNSSEC_VALIDATED;
+                t->answer_authenticated = true;
+                return 0;
+        }
+
+        /* Cached stuff is not affected by validation. */
+        if (t->answer_source != DNS_TRANSACTION_NETWORK)
+                return 0;
+
+        if (!dns_transaction_dnssec_supported_full(t)) {
+                /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */
+                t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
+                log_debug("Not validating response for %" PRIu16 ", server lacks DNSSEC support.", t->id);
+                return 0;
+        }
+
+        log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, dns_transaction_key_string(t));
+
+        /* First, see if this response contains any revoked trust
+         * anchors we care about */
+        r = dns_transaction_check_revoked_trust_anchors(t);
+        if (r < 0)
+                return r;
+
+        /* Third, copy all RRs we acquired successfully from auxiliary RRs over. */
+        r = dns_transaction_copy_validated(t);
+        if (r < 0)
+                return r;
+
+        /* Second, see if there are DNSKEYs we already know a
+         * validated DS for. */
+        r = dns_transaction_validate_dnskey_by_ds(t);
+        if (r < 0)
+                return r;
+
+        /* Fourth, remove all DNSKEY and DS RRs again that our trust
+         * anchor says are revoked. After all we might have marked
+         * some keys revoked above, but they might still be lingering
+         * in our validated_keys list. */
+        r = dns_transaction_invalidate_revoked_keys(t);
+        if (r < 0)
+                return r;
+
+        phase = PHASE_DNSKEY;
+        for (;;) {
+                bool changed = false, have_nsec = false;
+
+                DNS_ANSWER_FOREACH(rr, t->answer) {
+                        DnsResourceRecord *rrsig = NULL;
+                        DnssecResult result;
+
+                        switch (rr->key->type) {
+
+                        case DNS_TYPE_RRSIG:
+                                continue;
+
+                        case DNS_TYPE_DNSKEY:
+                                /* We validate DNSKEYs only in the DNSKEY and ALL phases */
+                                if (phase == PHASE_NSEC)
+                                        continue;
+                                break;
+
+                        case DNS_TYPE_NSEC:
+                        case DNS_TYPE_NSEC3:
+                                have_nsec = true;
+
+                                /* We validate NSEC/NSEC3 only in the NSEC and ALL phases */
+                                if (phase == PHASE_DNSKEY)
+                                        continue;
+
+                                break;
+
+                        default:
+                                /* We validate all other RRs only in the ALL phases */
+                                if (phase != PHASE_ALL)
+                                        continue;
+
+                                break;
+                        }
+
+                        r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result, &rrsig);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
+
+                        if (result == DNSSEC_VALIDATED) {
+
+                                if (rr->key->type == DNS_TYPE_DNSKEY) {
+                                        /* If we just validated a
+                                         * DNSKEY RRset, then let's
+                                         * add these keys to the set
+                                         * of validated keys for this
+                                         * transaction. */
+
+                                        r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED);
+                                        if (r < 0)
+                                                return r;
+
+                                        /* some of the DNSKEYs we just
+                                         * added might already have
+                                         * been revoked, remove them
+                                         * again in that case. */
+                                        r = dns_transaction_invalidate_revoked_keys(t);
+                                        if (r < 0)
+                                                return r;
+                                }
+
+                                /* Add the validated RRset to the new
+                                 * list of validated RRsets, and
+                                 * remove it from the unvalidated
+                                 * RRsets. We mark the RRset as
+                                 * authenticated and cacheable. */
+                                r = dns_answer_move_by_key(&validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE);
+                                if (r < 0)
+                                        return r;
+
+                                manager_dnssec_verdict(t->scope->manager, DNSSEC_SECURE, rr->key);
+
+                                /* Exit the loop, we dropped something from the answer, start from the beginning */
+                                changed = true;
+                                break;
+                        }
+
+                        /* If we haven't read all DNSKEYs yet a negative result of the validation is irrelevant, as
+                         * there might be more DNSKEYs coming. Similar, if we haven't read all NSEC/NSEC3 RRs yet, we
+                         * cannot do positive wildcard proofs yet, as those require the NSEC/NSEC3 RRs. */
+                        if (phase != PHASE_ALL)
+                                continue;
+
+                        if (result == DNSSEC_VALIDATED_WILDCARD) {
+                                bool authenticated = false;
+                                const char *source;
+
+                                /* This RRset validated, but as a wildcard. This means we need to prove via NSEC/NSEC3
+                                 * that no matching non-wildcard RR exists.*/
+
+                                /* First step, determine the source of synthesis */
+                                r = dns_resource_record_source(rrsig, &source);
+                                if (r < 0)
+                                        return r;
+
+                                r = dnssec_test_positive_wildcard(
+                                                validated,
+                                                DNS_RESOURCE_KEY_NAME(rr->key),
+                                                source,
+                                                rrsig->rrsig.signer,
+                                                &authenticated);
+
+                                /* Unless the NSEC proof showed that the key really doesn't exist something is off. */
+                                if (r == 0)
+                                        result = DNSSEC_INVALID;
+                                else {
+                                        r = dns_answer_move_by_key(&validated, &t->answer, rr->key, authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0);
+                                        if (r < 0)
+                                                return r;
+
+                                        manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, rr->key);
+
+                                        /* Exit the loop, we dropped something from the answer, start from the beginning */
+                                        changed = true;
+                                        break;
+                                }
+                        }
+
+                        if (result == DNSSEC_NO_SIGNATURE) {
+                                r = dns_transaction_requires_rrsig(t, rr);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0) {
+                                        /* Data does not require signing. In that case, just copy it over,
+                                         * but remember that this is by no means authenticated.*/
+                                        r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
+                                        if (r < 0)
+                                                return r;
+
+                                        manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
+                                        changed = true;
+                                        break;
+                                }
+
+                                r = dns_transaction_known_signed(t, rr);
+                                if (r < 0)
+                                        return r;
+                                if (r > 0) {
+                                        /* This is an RR we know has to be signed. If it isn't this means
+                                         * the server is not attaching RRSIGs, hence complain. */
+
+                                        dns_server_packet_rrsig_missing(t->server, t->current_feature_level);
+
+                                        if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
+
+                                                /* Downgrading is OK? If so, just consider the information unsigned */
+
+                                                r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
+                                                if (r < 0)
+                                                        return r;
+
+                                                manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
+                                                changed = true;
+                                                break;
+                                        }
+
+                                        /* Otherwise, fail */
+                                        t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
+                                        return 0;
+                                }
+
+                                r = dns_transaction_in_private_tld(t, rr->key);
+                                if (r < 0)
+                                        return r;
+                                if (r > 0) {
+                                        _cleanup_free_ char *s = NULL;
+
+                                        /* The data is from a TLD that is proven not to exist, and we are in downgrade
+                                         * mode, hence ignore the fact that this was not signed. */
+
+                                        (void) dns_resource_key_to_string(rr->key, &s);
+                                        log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.", strna(s ? strstrip(s) : NULL));
+
+                                        r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
+                                        if (r < 0)
+                                                return r;
+
+                                        manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
+                                        changed = true;
+                                        break;
+                                }
+                        }
+
+                        if (IN_SET(result,
+                                   DNSSEC_MISSING_KEY,
+                                   DNSSEC_SIGNATURE_EXPIRED,
+                                   DNSSEC_UNSUPPORTED_ALGORITHM)) {
+
+                                r = dns_transaction_dnskey_authenticated(t, rr);
+                                if (r < 0 && r != -ENXIO)
+                                        return r;
+                                if (r == 0) {
+                                        /* The DNSKEY transaction was not authenticated, this means there's
+                                         * no DS for this, which means it's OK if no keys are found for this signature. */
+
+                                        r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
+                                        if (r < 0)
+                                                return r;
+
+                                        manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
+                                        changed = true;
+                                        break;
+                                }
+                        }
+
+                        r = dns_transaction_is_primary_response(t, rr);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+
+                                /* Look for a matching DNAME for this CNAME */
+                                r = dns_answer_has_dname_for_cname(t->answer, rr);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0) {
+                                        /* Also look among the stuff we already validated */
+                                        r = dns_answer_has_dname_for_cname(validated, rr);
+                                        if (r < 0)
+                                                return r;
+                                }
+
+                                if (r == 0) {
+                                        if (IN_SET(result,
+                                                   DNSSEC_INVALID,
+                                                   DNSSEC_SIGNATURE_EXPIRED,
+                                                   DNSSEC_NO_SIGNATURE))
+                                                manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key);
+                                        else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */
+                                                manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key);
+
+                                        /* This is a primary response to our question, and it failed validation. That's
+                                         * fatal. */
+                                        t->answer_dnssec_result = result;
+                                        return 0;
+                                }
+
+                                /* This is a primary response, but we do have a DNAME RR in the RR that can replay this
+                                 * CNAME, hence rely on that, and we can remove the CNAME in favour of it. */
+                        }
+
+                        /* This is just some auxiliary data. Just remove the RRset and continue. */
+                        r = dns_answer_remove_by_key(&t->answer, rr->key);
+                        if (r < 0)
+                                return r;
+
+                        /* Exit the loop, we dropped something from the answer, start from the beginning */
+                        changed = true;
+                        break;
+                }
+
+                /* Restart the inner loop as long as we managed to achieve something */
+                if (changed)
+                        continue;
+
+                if (phase == PHASE_DNSKEY && have_nsec) {
+                        /* OK, we processed all DNSKEYs, and there are NSEC/NSEC3 RRs, look at those now. */
+                        phase = PHASE_NSEC;
+                        continue;
+                }
+
+                if (phase != PHASE_ALL) {
+                        /* OK, we processed all DNSKEYs and NSEC/NSEC3 RRs, look at all the rest now. Note that in this
+                         * third phase we start to remove RRs we couldn't validate. */
+                        phase = PHASE_ALL;
+                        continue;
+                }
+
+                /* We're done */
+                break;
+        }
+
+        dns_answer_unref(t->answer);
+        t->answer = validated;
+        validated = NULL;
+
+        /* At this point the answer only contains validated
+         * RRsets. Now, let's see if it actually answers the question
+         * we asked. If so, great! If it doesn't, then see if
+         * NSEC/NSEC3 can prove this. */
+        r = dns_transaction_has_positive_answer(t, &flags);
+        if (r > 0) {
+                /* Yes, it answers the question! */
+
+                if (flags & DNS_ANSWER_AUTHENTICATED) {
+                        /* The answer is fully authenticated, yay. */
+                        t->answer_dnssec_result = DNSSEC_VALIDATED;
+                        t->answer_rcode = DNS_RCODE_SUCCESS;
+                        t->answer_authenticated = true;
+                } else {
+                        /* The answer is not fully authenticated. */
+                        t->answer_dnssec_result = DNSSEC_UNSIGNED;
+                        t->answer_authenticated = false;
+                }
+
+        } else if (r == 0) {
+                DnssecNsecResult nr;
+                bool authenticated = false;
+
+                /* Bummer! Let's check NSEC/NSEC3 */
+                r = dnssec_nsec_test(t->answer, t->key, &nr, &authenticated, &t->answer_nsec_ttl);
+                if (r < 0)
+                        return r;
+
+                switch (nr) {
+
+                case DNSSEC_NSEC_NXDOMAIN:
+                        /* NSEC proves the domain doesn't exist. Very good. */
+                        log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
+                        t->answer_dnssec_result = DNSSEC_VALIDATED;
+                        t->answer_rcode = DNS_RCODE_NXDOMAIN;
+                        t->answer_authenticated = authenticated;
+
+                        manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
+                        break;
+
+                case DNSSEC_NSEC_NODATA:
+                        /* NSEC proves that there's no data here, very good. */
+                        log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
+                        t->answer_dnssec_result = DNSSEC_VALIDATED;
+                        t->answer_rcode = DNS_RCODE_SUCCESS;
+                        t->answer_authenticated = authenticated;
+
+                        manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
+                        break;
+
+                case DNSSEC_NSEC_OPTOUT:
+                        /* NSEC3 says the data might not be signed */
+                        log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
+                        t->answer_dnssec_result = DNSSEC_UNSIGNED;
+                        t->answer_authenticated = false;
+
+                        manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
+                        break;
+
+                case DNSSEC_NSEC_NO_RR:
+                        /* No NSEC data? Bummer! */
+
+                        r = dns_transaction_requires_nsec(t);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
+                                manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
+                        } else {
+                                t->answer_dnssec_result = DNSSEC_UNSIGNED;
+                                t->answer_authenticated = false;
+                                manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
+                        }
+
+                        break;
+
+                case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
+                        /* We don't know the NSEC3 algorithm used? */
+                        t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
+                        manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, t->key);
+                        break;
+
+                case DNSSEC_NSEC_FOUND:
+                case DNSSEC_NSEC_CNAME:
+                        /* NSEC says it needs to be there, but we couldn't find it? Bummer! */
+                        t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
+                        manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
+                        break;
+
+                default:
+                        assert_not_reached("Unexpected NSEC result.");
+                }
+        }
+
+        return 1;
+}
+
+const char *dns_transaction_key_string(DnsTransaction *t) {
+        assert(t);
+
+        if (!t->key_string) {
+                if (dns_resource_key_to_string(t->key, &t->key_string) < 0)
+                        return "n/a";
+        }
+
+        return strstrip(t->key_string);
+}
+
+static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
+        [DNS_TRANSACTION_NULL] = "null",
+        [DNS_TRANSACTION_PENDING] = "pending",
+        [DNS_TRANSACTION_VALIDATING] = "validating",
+        [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure",
+        [DNS_TRANSACTION_SUCCESS] = "success",
+        [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
+        [DNS_TRANSACTION_TIMEOUT] = "timeout",
+        [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
         [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
-        [DNS_TRANSACTION_RESOURCES] = "resources",
+        [DNS_TRANSACTION_ERRNO] = "errno",
         [DNS_TRANSACTION_ABORTED] = "aborted",
+        [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
+        [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor",
+        [DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported",
+        [DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
+        [DNS_TRANSACTION_NOT_FOUND] = "not-found",
 };
 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
+
+static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
+        [DNS_TRANSACTION_NETWORK] = "network",
+        [DNS_TRANSACTION_CACHE] = "cache",
+        [DNS_TRANSACTION_ZONE] = "zone",
+        [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
+};
+DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);
index acf6a6f651a509323030bc554e02908f8dc61612..46171947112c53c4f86a148e29271bab825109de 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 typedef struct DnsTransaction DnsTransaction;
 typedef enum DnsTransactionState DnsTransactionState;
+typedef enum DnsTransactionSource DnsTransactionSource;
 
 enum DnsTransactionState {
         DNS_TRANSACTION_NULL,
         DNS_TRANSACTION_PENDING,
-        DNS_TRANSACTION_FAILURE,
+        DNS_TRANSACTION_VALIDATING,
+        DNS_TRANSACTION_RCODE_FAILURE,
         DNS_TRANSACTION_SUCCESS,
         DNS_TRANSACTION_NO_SERVERS,
         DNS_TRANSACTION_TIMEOUT,
         DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
         DNS_TRANSACTION_INVALID_REPLY,
-        DNS_TRANSACTION_RESOURCES,
+        DNS_TRANSACTION_ERRNO,
         DNS_TRANSACTION_ABORTED,
+        DNS_TRANSACTION_DNSSEC_FAILED,
+        DNS_TRANSACTION_NO_TRUST_ANCHOR,
+        DNS_TRANSACTION_RR_TYPE_UNSUPPORTED,
+        DNS_TRANSACTION_NETWORK_DOWN,
+        DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */
         _DNS_TRANSACTION_STATE_MAX,
         _DNS_TRANSACTION_STATE_INVALID = -1
 };
 
-#include "resolved-dns-scope.h"
+#define DNS_TRANSACTION_IS_LIVE(state) IN_SET((state), DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING)
+
+enum DnsTransactionSource {
+        DNS_TRANSACTION_NETWORK,
+        DNS_TRANSACTION_CACHE,
+        DNS_TRANSACTION_ZONE,
+        DNS_TRANSACTION_TRUST_ANCHOR,
+        _DNS_TRANSACTION_SOURCE_MAX,
+        _DNS_TRANSACTION_SOURCE_INVALID = -1
+};
+
+#include "resolved-dns-answer.h"
 #include "resolved-dns-packet.h"
 #include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
+#include "resolved-dns-scope.h"
 
 struct DnsTransaction {
         DnsScope *scope;
 
         DnsResourceKey *key;
+        char *key_string;
 
         DnsTransactionState state;
+
         uint16_t id;
 
-        bool initial_jitter;
+        bool tried_stream:1;
+
+        bool initial_jitter_scheduled:1;
+        bool initial_jitter_elapsed:1;
 
         DnsPacket *sent, *received;
-        DnsAnswer *cached;
-        int cached_rcode;
+
+        DnsAnswer *answer;
+        int answer_rcode;
+        DnssecResult answer_dnssec_result;
+        DnsTransactionSource answer_source;
+        uint32_t answer_nsec_ttl;
+        int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
+
+        /* Indicates whether the primary answer is authenticated,
+         * i.e. whether the RRs from answer which directly match the
+         * question are authenticated, or, if there are none, whether
+         * the NODATA or NXDOMAIN case is. It says nothing about
+         * additional RRs listed in the answer, however they have
+         * their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit
+         * is defined different than the AD bit in DNS packets, as
+         * that covers more than just the actual primary answer. */
+        bool answer_authenticated;
+
+        /* Contains DNSKEY, DS, SOA RRs we already verified and need
+         * to authenticate this reply */
+        DnsAnswer *validated_keys;
 
         usec_t start_usec;
+        usec_t next_attempt_after;
         sd_event_source *timeout_event_source;
         unsigned n_attempts;
 
+        /* UDP connection logic, if we need it */
         int dns_udp_fd;
         sd_event_source *dns_udp_event_source;
 
+        /* TCP connection logic, if we need it */
+        DnsStream *stream;
+
         /* The active server */
         DnsServer *server;
 
-        /* TCP connection logic, if we need it */
-        DnsStream *stream;
+        /* The features of the DNS server at time of transaction start */
+        DnsServerFeatureLevel current_feature_level;
 
-        /* Queries this transaction is referenced by and that shall be
-         * notified about this specific transaction completing. */
-        Set *queries;
+        /* Query candidates this transaction is referenced by and that
+         * shall be notified about this specific transaction
+         * completing. */
+        Set *notify_query_candidates;
 
         /* Zone items this transaction is referenced by and that shall
          * be notified about completion. */
-        Set *zone_items;
+        Set *notify_zone_items;
+
+        /* Other transactions that this transactions is referenced by
+         * and that shall be notified about completion. This is used
+         * when transactions want to validate their RRsets, but need
+         * another DNSKEY or DS RR to do so. */
+        Set *notify_transactions;
+
+        /* The opposite direction: the transactions this transaction
+         * created in order to request DNSKEY or DS RRs. */
+        Set *dnssec_transactions;
 
         unsigned block_gc;
 
@@ -87,22 +143,35 @@ struct DnsTransaction {
 int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
 DnsTransaction* dns_transaction_free(DnsTransaction *t);
 
-void dns_transaction_gc(DnsTransaction *t);
+bool dns_transaction_gc(DnsTransaction *t);
 int dns_transaction_go(DnsTransaction *t);
 
 void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
 void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state);
 
+void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
+int dns_transaction_validate_dnssec(DnsTransaction *t);
+int dns_transaction_request_dnssec_keys(DnsTransaction *t);
+
+const char *dns_transaction_key_string(DnsTransaction *t);
+
 const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
 DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;
 
+const char* dns_transaction_source_to_string(DnsTransactionSource p) _const_;
+DnsTransactionSource dns_transaction_source_from_string(const char *s) _pure_;
+
 /* LLMNR Jitter interval, see RFC 4795 Section 7 */
 #define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC)
 
+/* mDNS Jitter interval, see RFC 6762 Section 5.2 */
+#define MDNS_JITTER_MIN_USEC   (20 * USEC_PER_MSEC)
+#define MDNS_JITTER_RANGE_USEC (100 * USEC_PER_MSEC)
+
 /* Maximum attempts to send DNS requests, across all DNS servers */
 #define DNS_TRANSACTION_ATTEMPTS_MAX 16
 
 /* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */
 #define LLMNR_TRANSACTION_ATTEMPTS_MAX 3
 
-#define TRANSACTION_ATTEMPTS_MAX(p) (p == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX)
+#define TRANSACTION_ATTEMPTS_MAX(p) ((p) == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX)
diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c
new file mode 100644 (file)
index 0000000..a75337e
--- /dev/null
@@ -0,0 +1,743 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sd-messages.h>
+
+#include "alloc-util.h"
+#include "conf-files.h"
+#include "def.h"
+#include "dns-domain.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
+#include "resolved-dns-trust-anchor.h"
+#include "resolved-dns-dnssec.h"
+#include "set.h"
+#include "string-util.h"
+#include "strv.h"
+
+static const char trust_anchor_dirs[] = CONF_PATHS_NULSTR("dnssec-trust-anchors.d");
+
+/* The DS RR from https://data.iana.org/root-anchors/root-anchors.xml, retrieved December 2015 */
+static const uint8_t root_digest[] =
+        { 0x49, 0xAA, 0xC1, 0x1D, 0x7B, 0x6F, 0x64, 0x46, 0x70, 0x2E, 0x54, 0xA1, 0x60, 0x73, 0x71, 0x60,
+          0x7A, 0x1A, 0x41, 0x85, 0x52, 0x00, 0xFD, 0x2C, 0xE1, 0xCD, 0xDE, 0x32, 0xF2, 0x4E, 0x8F, 0xB5 };
+
+static bool dns_trust_anchor_knows_domain_positive(DnsTrustAnchor *d, const char *name) {
+        assert(d);
+
+        /* Returns true if there's an entry for the specified domain
+         * name in our trust anchor */
+
+        return
+                hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DNSKEY, name)) ||
+                hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, name));
+}
+
+static int dns_trust_anchor_add_builtin_positive(DnsTrustAnchor *d) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        int r;
+
+        assert(d);
+
+        r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
+        if (r < 0)
+                return r;
+
+        /* Only add the built-in trust anchor if there's neither a DS
+         * nor a DNSKEY defined for the root domain. That way users
+         * have an easy way to override the root domain DS/DNSKEY
+         * data. */
+        if (dns_trust_anchor_knows_domain_positive(d, "."))
+                return 0;
+
+        /* Add the RR from https://data.iana.org/root-anchors/root-anchors.xml */
+        rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "");
+        if (!rr)
+                return -ENOMEM;
+
+        rr->ds.key_tag = 19036;
+        rr->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        rr->ds.digest_type = DNSSEC_DIGEST_SHA256;
+        rr->ds.digest_size = sizeof(root_digest);
+        rr->ds.digest = memdup(root_digest, rr->ds.digest_size);
+        if (!rr->ds.digest)
+                return  -ENOMEM;
+
+        answer = dns_answer_new(1);
+        if (!answer)
+                return -ENOMEM;
+
+        r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+        if (r < 0)
+                return r;
+
+        r = hashmap_put(d->positive_by_key, rr->key, answer);
+        if (r < 0)
+                return r;
+
+        answer = NULL;
+        return 0;
+}
+
+static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) {
+
+        static const char private_domains[] =
+                /* RFC 6761 says that .test is a special domain for
+                 * testing and not to be installed in the root zone */
+                "test\0"
+
+                /* RFC 6761 says that these reverse IP lookup ranges
+                 * are for private addresses, and hence should not
+                 * show up in the root zone */
+                "10.in-addr.arpa\0"
+                "16.172.in-addr.arpa\0"
+                "17.172.in-addr.arpa\0"
+                "18.172.in-addr.arpa\0"
+                "19.172.in-addr.arpa\0"
+                "20.172.in-addr.arpa\0"
+                "21.172.in-addr.arpa\0"
+                "22.172.in-addr.arpa\0"
+                "23.172.in-addr.arpa\0"
+                "24.172.in-addr.arpa\0"
+                "25.172.in-addr.arpa\0"
+                "26.172.in-addr.arpa\0"
+                "27.172.in-addr.arpa\0"
+                "28.172.in-addr.arpa\0"
+                "29.172.in-addr.arpa\0"
+                "30.172.in-addr.arpa\0"
+                "31.172.in-addr.arpa\0"
+                "168.192.in-addr.arpa\0"
+
+                /* RFC 6762 reserves the .local domain for Multicast
+                 * DNS, it hence cannot appear in the root zone. (Note
+                 * that we by default do not route .local traffic to
+                 * DNS anyway, except when a configured search domain
+                 * suggests so.) */
+                "local\0"
+
+                /* These two are well known, popular private zone
+                 * TLDs, that are blocked from delegation, according
+                 * to:
+                 * http://icannwiki.com/Name_Collision#NGPC_Resolution
+                 *
+                 * There's also ongoing work on making this official
+                 * in an RRC:
+                 * https://www.ietf.org/archive/id/draft-chapin-additional-reserved-tlds-02.txt */
+                "home\0"
+                "corp\0"
+
+                /* The following four TLDs are suggested for private
+                 * zones in RFC 6762, Appendix G, and are hence very
+                 * unlikely to be made official TLDs any day soon */
+                "lan\0"
+                "intranet\0"
+                "internal\0"
+                "private\0";
+
+        const char *name;
+        int r;
+
+        assert(d);
+
+        /* Only add the built-in trust anchor if there's no negative
+         * trust anchor defined at all. This enables easy overriding
+         * of negative trust anchors. */
+
+        if (set_size(d->negative_by_name) > 0)
+                return 0;
+
+        r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops);
+        if (r < 0)
+                return r;
+
+        /* We add a couple of domains as default negative trust
+         * anchors, where it's very unlikely they will be installed in
+         * the root zone. If they exist they must be private, and thus
+         * unsigned. */
+
+        NULSTR_FOREACH(name, private_domains) {
+
+                if (dns_trust_anchor_knows_domain_positive(d, name))
+                        continue;
+
+                r = set_put_strdup(d->negative_by_name, name);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        _cleanup_free_ char *domain = NULL, *class = NULL, *type = NULL;
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        DnsAnswer *old_answer = NULL;
+        const char *p = s;
+        int r;
+
+        assert(d);
+        assert(line);
+
+        r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES);
+        if (r < 0)
+                return log_warning_errno(r, "Unable to parse domain in line %s:%u: %m", path, line);
+
+        if (!dns_name_is_valid(domain)) {
+                log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
+                return -EINVAL;
+        }
+
+        r = extract_many_words(&p, NULL, 0, &class, &type, NULL);
+        if (r < 0)
+                return log_warning_errno(r, "Unable to parse class and type in line %s:%u: %m", path, line);
+        if (r != 2) {
+                log_warning("Missing class or type in line %s:%u", path, line);
+                return -EINVAL;
+        }
+
+        if (!strcaseeq(class, "IN")) {
+                log_warning("RR class %s is not supported, ignoring line %s:%u.", class, path, line);
+                return -EINVAL;
+        }
+
+        if (strcaseeq(type, "DS")) {
+                _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL;
+                _cleanup_free_ void *dd = NULL;
+                uint16_t kt;
+                int a, dt;
+                size_t l;
+
+                r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL);
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line);
+                        return -EINVAL;
+                }
+                if (r != 4) {
+                        log_warning("Missing DS parameters on line %s:%u", path, line);
+                        return -EINVAL;
+                }
+
+                r = safe_atou16(key_tag, &kt);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to parse DS key tag %s on line %s:%u: %m", key_tag, path, line);
+
+                a = dnssec_algorithm_from_string(algorithm);
+                if (a < 0) {
+                        log_warning("Failed to parse DS algorithm %s on line %s:%u", algorithm, path, line);
+                        return -EINVAL;
+                }
+
+                dt = dnssec_digest_from_string(digest_type);
+                if (dt < 0) {
+                        log_warning("Failed to parse DS digest type %s on line %s:%u", digest_type, path, line);
+                        return -EINVAL;
+                }
+
+                r = unhexmem(digest, strlen(digest), &dd, &l);
+                if (r < 0) {
+                        log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line);
+                        return -EINVAL;
+                }
+
+                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, domain);
+                if (!rr)
+                        return log_oom();
+
+                rr->ds.key_tag = kt;
+                rr->ds.algorithm = a;
+                rr->ds.digest_type = dt;
+                rr->ds.digest_size = l;
+                rr->ds.digest = dd;
+                dd = NULL;
+
+        } else if (strcaseeq(type, "DNSKEY")) {
+                _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL;
+                _cleanup_free_ void *k = NULL;
+                uint16_t f;
+                size_t l;
+                int a;
+
+                r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line);
+                if (r != 4) {
+                        log_warning("Missing DNSKEY parameters on line %s:%u", path, line);
+                        return -EINVAL;
+                }
+
+                if (!streq(protocol, "3")) {
+                        log_warning("DNSKEY Protocol is not 3 on line %s:%u", path, line);
+                        return -EINVAL;
+                }
+
+                r = safe_atou16(flags, &f);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to parse DNSKEY flags field %s on line %s:%u", flags, path, line);
+                if ((f & DNSKEY_FLAG_ZONE_KEY) == 0) {
+                        log_warning("DNSKEY lacks zone key bit set on line %s:%u", path, line);
+                        return -EINVAL;
+                }
+                if ((f & DNSKEY_FLAG_REVOKE)) {
+                        log_warning("DNSKEY is already revoked on line %s:%u", path, line);
+                        return -EINVAL;
+                }
+
+                a = dnssec_algorithm_from_string(algorithm);
+                if (a < 0) {
+                        log_warning("Failed to parse DNSKEY algorithm %s on line %s:%u", algorithm, path, line);
+                        return -EINVAL;
+                }
+
+                r = unbase64mem(key, strlen(key), &k, &l);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line);
+
+                rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain);
+                if (!rr)
+                        return log_oom();
+
+                rr->dnskey.flags = f;
+                rr->dnskey.protocol = 3;
+                rr->dnskey.algorithm = a;
+                rr->dnskey.key_size = l;
+                rr->dnskey.key = k;
+                k = NULL;
+
+        } else {
+                log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line);
+                return -EINVAL;
+        }
+
+        if (!isempty(p)) {
+                log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line);
+                return -EINVAL;
+        }
+
+        r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
+        if (r < 0)
+                return log_oom();
+
+        old_answer = hashmap_get(d->positive_by_key, rr->key);
+        answer = dns_answer_ref(old_answer);
+
+        r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add trust anchor RR: %m");
+
+        r = hashmap_replace(d->positive_by_key, rr->key, answer);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add answer to trust anchor: %m");
+
+        old_answer = dns_answer_unref(old_answer);
+        answer = NULL;
+
+        return 0;
+}
+
+static int dns_trust_anchor_load_negative(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) {
+        _cleanup_free_ char *domain = NULL;
+        const char *p = s;
+        int r;
+
+        assert(d);
+        assert(line);
+
+        r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES);
+        if (r < 0)
+                return log_warning_errno(r, "Unable to parse line %s:%u: %m", path, line);
+
+        if (!dns_name_is_valid(domain)) {
+                log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
+                return -EINVAL;
+        }
+
+        if (!isempty(p)) {
+                log_warning("Trailing garbage at line %s:%u, ignoring line.", path, line);
+                return -EINVAL;
+        }
+
+        r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops);
+        if (r < 0)
+                return log_oom();
+
+        r = set_put(d->negative_by_name, domain);
+        if (r < 0)
+                return log_oom();
+        if (r > 0)
+                domain = NULL;
+
+        return 0;
+}
+
+static int dns_trust_anchor_load_files(
+                DnsTrustAnchor *d,
+                const char *suffix,
+                int (*loader)(DnsTrustAnchor *d, const char *path, unsigned n, const char *line)) {
+
+        _cleanup_strv_free_ char **files = NULL;
+        char **f;
+        int r;
+
+        assert(d);
+        assert(suffix);
+        assert(loader);
+
+        r = conf_files_list_nulstr(&files, suffix, NULL, trust_anchor_dirs);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix);
+
+        STRV_FOREACH(f, files) {
+                _cleanup_fclose_ FILE *g = NULL;
+                char line[LINE_MAX];
+                unsigned n = 0;
+
+                g = fopen(*f, "r");
+                if (!g) {
+                        if (errno == ENOENT)
+                                continue;
+
+                        log_warning_errno(errno, "Failed to open %s: %m", *f);
+                        continue;
+                }
+
+                FOREACH_LINE(line, g, log_warning_errno(errno, "Failed to read %s, ignoring: %m", *f)) {
+                        char *l;
+
+                        n++;
+
+                        l = strstrip(line);
+                        if (isempty(l))
+                                continue;
+
+                        if (*l == ';')
+                                continue;
+
+                        (void) loader(d, *f, n, l);
+                }
+        }
+
+        return 0;
+}
+
+static int domain_name_cmp(const void *a, const void *b) {
+        char **x = (char**) a, **y = (char**) b;
+
+        return dns_name_compare_func(*x, *y);
+}
+
+static int dns_trust_anchor_dump(DnsTrustAnchor *d) {
+        DnsAnswer *a;
+        Iterator i;
+
+        assert(d);
+
+        if (hashmap_isempty(d->positive_by_key))
+                log_info("No positive trust anchors defined.");
+        else {
+                log_info("Positive Trust Anchors:");
+                HASHMAP_FOREACH(a, d->positive_by_key, i) {
+                        DnsResourceRecord *rr;
+
+                        DNS_ANSWER_FOREACH(rr, a)
+                                log_info("%s", dns_resource_record_to_string(rr));
+                }
+        }
+
+        if (set_isempty(d->negative_by_name))
+                log_info("No negative trust anchors defined.");
+        else {
+                _cleanup_free_ char **l = NULL, *j = NULL;
+
+                l = set_get_strv(d->negative_by_name);
+                if (!l)
+                        return log_oom();
+
+                qsort_safe(l, set_size(d->negative_by_name), sizeof(char*), domain_name_cmp);
+
+                j = strv_join(l, " ");
+                if (!j)
+                        return log_oom();
+
+                log_info("Negative trust anchors: %s", j);
+        }
+
+        return 0;
+}
+
+int dns_trust_anchor_load(DnsTrustAnchor *d) {
+        int r;
+
+        assert(d);
+
+        /* If loading things from disk fails, we don't consider this fatal */
+        (void) dns_trust_anchor_load_files(d, ".positive", dns_trust_anchor_load_positive);
+        (void) dns_trust_anchor_load_files(d, ".negative", dns_trust_anchor_load_negative);
+
+        /* However, if the built-in DS fails, then we have a problem. */
+        r = dns_trust_anchor_add_builtin_positive(d);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add built-in positive trust anchor: %m");
+
+        r = dns_trust_anchor_add_builtin_negative(d);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add built-in negative trust anchor: %m");
+
+        dns_trust_anchor_dump(d);
+
+        return 0;
+}
+
+void dns_trust_anchor_flush(DnsTrustAnchor *d) {
+        DnsAnswer *a;
+        DnsResourceRecord *rr;
+
+        assert(d);
+
+        while ((a = hashmap_steal_first(d->positive_by_key)))
+                dns_answer_unref(a);
+        d->positive_by_key = hashmap_free(d->positive_by_key);
+
+        while ((rr = set_steal_first(d->revoked_by_rr)))
+                dns_resource_record_unref(rr);
+        d->revoked_by_rr = set_free(d->revoked_by_rr);
+
+        d->negative_by_name = set_free_free(d->negative_by_name);
+}
+
+int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey *key, DnsAnswer **ret) {
+        DnsAnswer *a;
+
+        assert(d);
+        assert(key);
+        assert(ret);
+
+        /* We only serve DS and DNSKEY RRs. */
+        if (!IN_SET(key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY))
+                return 0;
+
+        a = hashmap_get(d->positive_by_key, key);
+        if (!a)
+                return 0;
+
+        *ret = dns_answer_ref(a);
+        return 1;
+}
+
+int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name) {
+        assert(d);
+        assert(name);
+
+        return set_contains(d->negative_by_name, name);
+}
+
+static int dns_trust_anchor_revoked_put(DnsTrustAnchor *d, DnsResourceRecord *rr) {
+        int r;
+
+        assert(d);
+
+        r = set_ensure_allocated(&d->revoked_by_rr, &dns_resource_record_hash_ops);
+        if (r < 0)
+                return r;
+
+        r = set_put(d->revoked_by_rr, rr);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                dns_resource_record_ref(rr);
+
+        return r;
+}
+
+static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *new_answer = NULL;
+        DnsAnswer *old_answer;
+        int r;
+
+        /* Remember that this is a revoked trust anchor RR */
+        r = dns_trust_anchor_revoked_put(d, rr);
+        if (r < 0)
+                return r;
+
+        /* Remove this from the positive trust anchor */
+        old_answer = hashmap_get(d->positive_by_key, rr->key);
+        if (!old_answer)
+                return 0;
+
+        new_answer = dns_answer_ref(old_answer);
+
+        r = dns_answer_remove_by_rr(&new_answer, rr);
+        if (r <= 0)
+                return r;
+
+        /* We found the key! Warn the user */
+        log_struct(LOG_WARNING,
+                   LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED),
+                   LOG_MESSAGE("DNSSEC Trust anchor %s has been revoked. Please update the trust anchor, or upgrade your operating system."), strna(dns_resource_record_to_string(rr)),
+                   "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr),
+                   NULL);
+
+        if (dns_answer_size(new_answer) <= 0) {
+                assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer);
+                dns_answer_unref(old_answer);
+                return 1;
+        }
+
+        r = hashmap_replace(d->positive_by_key, new_answer->items[0].rr->key, new_answer);
+        if (r < 0)
+                return r;
+
+        new_answer = NULL;
+        dns_answer_unref(old_answer);
+        return 1;
+}
+
+static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceRecord *revoked_dnskey) {
+        DnsAnswer *a;
+        int r;
+
+        assert(d);
+        assert(revoked_dnskey);
+        assert(revoked_dnskey->key->type == DNS_TYPE_DNSKEY);
+        assert(revoked_dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE);
+
+        a = hashmap_get(d->positive_by_key, revoked_dnskey->key);
+        if (a) {
+                DnsResourceRecord *anchor;
+
+                /* First, look for the precise DNSKEY in our trust anchor database */
+
+                DNS_ANSWER_FOREACH(anchor, a) {
+
+                        if (anchor->dnskey.protocol != revoked_dnskey->dnskey.protocol)
+                                continue;
+
+                        if (anchor->dnskey.algorithm != revoked_dnskey->dnskey.algorithm)
+                                continue;
+
+                        if (anchor->dnskey.key_size != revoked_dnskey->dnskey.key_size)
+                                continue;
+
+                        /* Note that we allow the REVOKE bit to be
+                         * different! It will be set in the revoked
+                         * key, but unset in our version of it */
+                        if (((anchor->dnskey.flags ^ revoked_dnskey->dnskey.flags) | DNSKEY_FLAG_REVOKE) != DNSKEY_FLAG_REVOKE)
+                                continue;
+
+                        if (memcmp(anchor->dnskey.key, revoked_dnskey->dnskey.key, anchor->dnskey.key_size) != 0)
+                                continue;
+
+                        dns_trust_anchor_remove_revoked(d, anchor);
+                        break;
+                }
+        }
+
+        a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(revoked_dnskey->key)));
+        if (a) {
+                DnsResourceRecord *anchor;
+
+                /* Second, look for DS RRs matching this DNSKEY in our trust anchor database */
+
+                DNS_ANSWER_FOREACH(anchor, a) {
+
+                        /* We set mask_revoke to true here, since our
+                         * DS fingerprint will be the one of the
+                         * unrevoked DNSKEY, but the one we got passed
+                         * here has the bit set. */
+                        r = dnssec_verify_dnskey_by_ds(revoked_dnskey, anchor, true);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
+
+                        dns_trust_anchor_remove_revoked(d, anchor);
+                        break;
+                }
+        }
+
+        return 0;
+}
+
+int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs) {
+        DnsResourceRecord *rrsig;
+        int r;
+
+        assert(d);
+        assert(dnskey);
+
+        /* Looks if "dnskey" is a self-signed RR that has been revoked
+         * and matches one of our trust anchor entries. If so, removes
+         * it from the trust anchor and returns > 0. */
+
+        if (dnskey->key->type != DNS_TYPE_DNSKEY)
+                return 0;
+
+        /* Is this DNSKEY revoked? */
+        if ((dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE) == 0)
+                return 0;
+
+        /* Could this be interesting to us at all? If not,
+         * there's no point in looking for and verifying a
+         * self-signed RRSIG. */
+        if (!dns_trust_anchor_knows_domain_positive(d, DNS_RESOURCE_KEY_NAME(dnskey->key)))
+                return 0;
+
+        /* Look for a self-signed RRSIG in the other rrs belonging to this DNSKEY */
+        DNS_ANSWER_FOREACH(rrsig, rrs) {
+                DnssecResult result;
+
+                if (rrsig->key->type != DNS_TYPE_RRSIG)
+                        continue;
+
+                r = dnssec_rrsig_match_dnskey(rrsig, dnskey, true);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                r = dnssec_verify_rrset(rrs, dnskey->key, rrsig, dnskey, USEC_INFINITY, &result);
+                if (r < 0)
+                        return r;
+                if (result != DNSSEC_VALIDATED)
+                        continue;
+
+                /* Bingo! This is a revoked self-signed DNSKEY. Let's
+                 * see if this precise one exists in our trust anchor
+                 * database, too. */
+                r = dns_trust_anchor_check_revoked_one(d, dnskey);
+                if (r < 0)
+                        return r;
+
+                return 1;
+        }
+
+        return 0;
+}
+
+int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) {
+        assert(d);
+
+        if (!IN_SET(rr->key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY))
+                return 0;
+
+        return set_contains(d->revoked_by_rr, rr);
+}
diff --git a/src/resolve/resolved-dns-trust-anchor.h b/src/resolve/resolved-dns-trust-anchor.h
new file mode 100644 (file)
index 0000000..635c75f
--- /dev/null
@@ -0,0 +1,43 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef struct DnsTrustAnchor DnsTrustAnchor;
+
+#include "hashmap.h"
+#include "resolved-dns-answer.h"
+#include "resolved-dns-rr.h"
+
+/* This contains a fixed database mapping domain names to DS or DNSKEY records. */
+
+struct DnsTrustAnchor {
+        Hashmap *positive_by_key;
+        Set *negative_by_name;
+        Set *revoked_by_rr;
+};
+
+int dns_trust_anchor_load(DnsTrustAnchor *d);
+void dns_trust_anchor_flush(DnsTrustAnchor *d);
+
+int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey* key, DnsAnswer **answer);
+int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name);
+
+int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs);
+int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr);
index 48dcf76daac9bf40e252c2c56516467176ad3aea..f52383cfd117433f79633ff21b69e47b5f0c084b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,7 +37,7 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
         t = i->probe_transaction;
         i->probe_transaction = NULL;
 
-        set_remove(t->zone_items, i);
+        set_remove(t->notify_zone_items, i);
         dns_transaction_gc(t);
 }
 
@@ -163,7 +161,6 @@ static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) {
 }
 
 static int dns_zone_item_probe_start(DnsZoneItem *i)  {
-        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
         DnsTransaction *t;
         int r;
 
@@ -172,22 +169,24 @@ static int dns_zone_item_probe_start(DnsZoneItem *i)  {
         if (i->probe_transaction)
                 return 0;
 
-        key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key));
-        if (!key)
-                return -ENOMEM;
-
-        t = dns_scope_find_transaction(i->scope, key, false);
+        t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key)), false);
         if (!t) {
+                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
+
+                key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key));
+                if (!key)
+                        return -ENOMEM;
+
                 r = dns_transaction_new(&t, i->scope, key);
                 if (r < 0)
                         return r;
         }
 
-        r = set_ensure_allocated(&t->zone_items, NULL);
+        r = set_ensure_allocated(&t->notify_zone_items, NULL);
         if (r < 0)
                 goto gc;
 
-        r = set_put(t->zone_items, i);
+        r = set_put(t->notify_zone_items, i);
         if (r < 0)
                 goto gc;
 
@@ -205,7 +204,7 @@ static int dns_zone_item_probe_start(DnsZoneItem *i)  {
                 }
         }
 
-        dns_zone_item_ready(i);
+        dns_zone_item_notify(i);
         return 0;
 
 gc:
@@ -222,9 +221,9 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
         assert(s);
         assert(rr);
 
-        if (rr->key->class == DNS_CLASS_ANY)
+        if (dns_class_is_pseudo(rr->key->class))
                 return -EINVAL;
-        if (rr->key->type == DNS_TYPE_ANY)
+        if (dns_type_is_pseudo(rr->key->type))
                 return -EINVAL;
 
         existing = dns_zone_get(z, rr);
@@ -283,97 +282,76 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
         return 0;
 }
 
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
-        unsigned i, n_answer = 0, n_soa = 0;
-        bool tentative = true;
+        unsigned n_answer = 0;
+        DnsZoneItem *j, *first;
+        bool tentative = true, need_soa = false;
         int r;
 
         assert(z);
-        assert(q);
+        assert(key);
         assert(ret_answer);
-        assert(ret_soa);
 
-        if (q->n_keys <= 0) {
-                *ret_answer = NULL;
-                *ret_soa = NULL;
-
-                if (ret_tentative)
-                        *ret_tentative = false;
+        /* First iteration, count what we have */
 
-                return 0;
-        }
+        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+                bool found = false, added = false;
+                int k;
 
-        /* First iteration, count what we have */
-        for (i = 0; i < q->n_keys; i++) {
-                DnsZoneItem *j, *first;
+                /* If this is a generic match, then we have to
+                 * go through the list by the name and look
+                 * for everything manually */
 
-                if (q->keys[i]->type == DNS_TYPE_ANY ||
-                    q->keys[i]->class == DNS_CLASS_ANY) {
-                        bool found = false, added = false;
-                        int k;
+                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                LIST_FOREACH(by_name, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                        /* If this is a generic match, then we have to
-                         * go through the list by the name and look
-                         * for everything manually */
+                        found = true;
 
-                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                        LIST_FOREACH(by_name, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
+                        k = dns_resource_key_match_rr(key, j->rr, NULL);
+                        if (k < 0)
+                                return k;
+                        if (k > 0) {
+                                n_answer++;
+                                added = true;
+                        }
 
-                                found = true;
+                }
 
-                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
-                                if (k < 0)
-                                        return k;
-                                if (k > 0) {
-                                        n_answer++;
-                                        added = true;
-                                }
+                if (found && !added)
+                        need_soa = true;
 
-                        }
+        } else {
+                bool found = false;
 
-                        if (found && !added)
-                                n_soa++;
+                /* If this is a specific match, then look for
+                 * the right key immediately */
 
-                } else {
-                        bool found = false;
+                first = hashmap_get(z->by_key, key);
+                LIST_FOREACH(by_key, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                        /* If this is a specific match, then look for
-                         * the right key immediately */
+                        found = true;
+                        n_answer++;
+                }
 
-                        first = hashmap_get(z->by_key, q->keys[i]);
-                        LIST_FOREACH(by_key, j, first) {
+                if (!found) {
+                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                        LIST_FOREACH(by_name, j, first) {
                                 if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                         continue;
 
-                                found = true;
-                                n_answer++;
-                        }
-
-                        if (!found) {
-                                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                                LIST_FOREACH(by_name, j, first) {
-                                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                                continue;
-
-                                        n_soa++;
-                                        break;
-                                }
+                                need_soa = true;
+                                break;
                         }
                 }
         }
 
-        if (n_answer <= 0 && n_soa <= 0) {
-                *ret_answer = NULL;
-                *ret_soa = NULL;
-
-                if (ret_tentative)
-                        *ret_tentative = false;
-
-                return 0;
-        }
+        if (n_answer <= 0 && !need_soa)
+                goto return_empty;
 
         if (n_answer > 0) {
                 answer = dns_answer_new(n_answer);
@@ -381,111 +359,122 @@ int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswe
                         return -ENOMEM;
         }
 
-        if (n_soa > 0) {
-                soa = dns_answer_new(n_soa);
+        if (need_soa) {
+                soa = dns_answer_new(1);
                 if (!soa)
                         return -ENOMEM;
         }
 
         /* Second iteration, actually add the RRs to the answers */
-        for (i = 0; i < q->n_keys; i++) {
-                DnsZoneItem *j, *first;
-
-                if (q->keys[i]->type == DNS_TYPE_ANY ||
-                    q->keys[i]->class == DNS_CLASS_ANY) {
-                        bool found = false, added = false;
-                        int k;
-
-                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                        LIST_FOREACH(by_name, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
-
-                                found = true;
+        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+                bool found = false, added = false;
+                int k;
 
-                                if (j->state != DNS_ZONE_ITEM_PROBING)
-                                        tentative = false;
+                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                LIST_FOREACH(by_name, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
-                                if (k < 0)
-                                        return k;
-                                if (k > 0) {
-                                        r = dns_answer_add(answer, j->rr, 0);
-                                        if (r < 0)
-                                                return r;
+                        found = true;
 
-                                        added = true;
-                                }
-                        }
+                        if (j->state != DNS_ZONE_ITEM_PROBING)
+                                tentative = false;
 
-                        if (found && !added) {
-                                r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+                        k = dns_resource_key_match_rr(key, j->rr, NULL);
+                        if (k < 0)
+                                return k;
+                        if (k > 0) {
+                                r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED);
                                 if (r < 0)
                                         return r;
+
+                                added = true;
                         }
-                } else {
-                        bool found = false;
+                }
 
-                        first = hashmap_get(z->by_key, q->keys[i]);
-                        LIST_FOREACH(by_key, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
+                if (found && !added) {
+                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+                        if (r < 0)
+                                return r;
+                }
+        } else {
+                bool found = false;
 
-                                found = true;
+                first = hashmap_get(z->by_key, key);
+                LIST_FOREACH(by_key, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                                if (j->state != DNS_ZONE_ITEM_PROBING)
-                                        tentative = false;
+                        found = true;
 
-                                r = dns_answer_add(answer, j->rr, 0);
-                                if (r < 0)
-                                        return r;
-                        }
+                        if (j->state != DNS_ZONE_ITEM_PROBING)
+                                tentative = false;
 
-                        if (!found) {
-                                bool add_soa = false;
+                        r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED);
+                        if (r < 0)
+                                return r;
+                }
 
-                                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                                LIST_FOREACH(by_name, j, first) {
-                                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                                continue;
+                if (!found) {
+                        bool add_soa = false;
+
+                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                        LIST_FOREACH(by_name, j, first) {
+                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                        continue;
 
-                                        if (j->state != DNS_ZONE_ITEM_PROBING)
-                                                tentative = false;
+                                if (j->state != DNS_ZONE_ITEM_PROBING)
+                                        tentative = false;
 
-                                        add_soa = true;
-                                }
+                                add_soa = true;
+                        }
 
-                                if (add_soa) {
-                                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
-                                        if (r < 0)
-                                                return r;
-                                }
+                        if (add_soa) {
+                                r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+                                if (r < 0)
+                                        return r;
                         }
                 }
         }
 
+        /* If the caller sets ret_tentative to NULL, then use this as
+         * indication to not return tentative entries */
+
+        if (!ret_tentative && tentative)
+                goto return_empty;
+
         *ret_answer = answer;
         answer = NULL;
 
-        *ret_soa = soa;
-        soa = NULL;
+        if (ret_soa) {
+                *ret_soa = soa;
+                soa = NULL;
+        }
 
         if (ret_tentative)
                 *ret_tentative = tentative;
 
         return 1;
+
+return_empty:
+        *ret_answer = NULL;
+
+        if (ret_soa)
+                *ret_soa = NULL;
+
+        if (ret_tentative)
+                *ret_tentative = false;
+
+        return 0;
 }
 
 void dns_zone_item_conflict(DnsZoneItem *i) {
-        _cleanup_free_ char *pretty = NULL;
-
         assert(i);
 
         if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED))
                 return;
 
-        dns_resource_record_to_string(i->rr, &pretty);
-        log_info("Detected conflict on %s", strna(pretty));
+        log_info("Detected conflict on %s", strna(dns_resource_record_to_string(i->rr)));
 
         dns_zone_item_probe_stop(i);
 
@@ -497,16 +486,14 @@ void dns_zone_item_conflict(DnsZoneItem *i) {
                 manager_next_hostname(i->scope->manager);
 }
 
-void dns_zone_item_ready(DnsZoneItem *i) {
-        _cleanup_free_ char *pretty = NULL;
-
+void dns_zone_item_notify(DnsZoneItem *i) {
         assert(i);
         assert(i->probe_transaction);
 
         if (i->block_ready > 0)
                 return;
 
-        if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
+        if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
                 return;
 
         if (i->probe_transaction->state == DNS_TRANSACTION_SUCCESS) {
@@ -536,15 +523,13 @@ void dns_zone_item_ready(DnsZoneItem *i) {
                 log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost.");
         }
 
-        dns_resource_record_to_string(i->rr, &pretty);
-        log_debug("Record %s successfully probed.", strna(pretty));
+        log_debug("Record %s successfully probed.", strna(dns_resource_record_to_string(i->rr)));
 
         dns_zone_item_probe_stop(i);
         i->state = DNS_ZONE_ITEM_ESTABLISHED;
 }
 
 static int dns_zone_item_verify(DnsZoneItem *i) {
-        _cleanup_free_ char *pretty = NULL;
         int r;
 
         assert(i);
@@ -552,8 +537,7 @@ static int dns_zone_item_verify(DnsZoneItem *i) {
         if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
                 return 0;
 
-        dns_resource_record_to_string(i->rr, &pretty);
-        log_debug("Verifying RR %s", strna(pretty));
+        log_debug("Verifying RR %s", strna(dns_resource_record_to_string(i->rr)));
 
         i->state = DNS_ZONE_ITEM_VERIFYING;
         r = dns_zone_item_probe_start(i);
@@ -638,7 +622,6 @@ void dns_zone_verify_all(DnsZone *zone) {
 void dns_zone_dump(DnsZone *zone, FILE *f) {
         Iterator iterator;
         DnsZoneItem *i;
-        int r;
 
         if (!zone)
                 return;
@@ -650,10 +633,10 @@ void dns_zone_dump(DnsZone *zone, FILE *f) {
                 DnsZoneItem *j;
 
                 LIST_FOREACH(by_key, j, i) {
-                        _cleanup_free_ char *t = NULL;
+                        const char *t;
 
-                        r = dns_resource_record_to_string(j->rr, &t);
-                        if (r < 0) {
+                        t = dns_resource_record_to_string(j->rr);
+                        if (!t) {
                                 log_oom();
                                 continue;
                         }
index 495d17cdb1214391d691797abffadbec94edfd50..408833c359a8a16ba63f6aa999931bacf70d5481 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -31,9 +29,9 @@ typedef struct DnsZone {
 typedef struct DnsZoneItem DnsZoneItem;
 typedef enum DnsZoneItemState DnsZoneItemState;
 
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
 #include "resolved-dns-answer.h"
+#include "resolved-dns-question.h"
+#include "resolved-dns-rr.h"
 #include "resolved-dns-transaction.h"
 
 /* RFC 4795 Section 2.8. suggests a TTL of 30s by default */
@@ -67,10 +65,10 @@ void dns_zone_flush(DnsZone *z);
 int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
 void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
 
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
 
 void dns_zone_item_conflict(DnsZoneItem *i);
-void dns_zone_item_ready(DnsZoneItem *i);
+void dns_zone_item_notify(DnsZoneItem *i);
 
 int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr);
 int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key);
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
new file mode 100644 (file)
index 0000000..ee82c96
--- /dev/null
@@ -0,0 +1,448 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "fd-util.h"
+#include "fileio.h"
+#include "hostname-util.h"
+#include "resolved-etc-hosts.h"
+#include "resolved-dns-synthesize.h"
+#include "string-util.h"
+#include "strv.h"
+#include "time-util.h"
+
+/* Recheck /etc/hosts at most once every 2s */
+#define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC)
+
+typedef struct EtcHostsItem {
+        int family;
+        union in_addr_union address;
+
+        char **names;
+} EtcHostsItem;
+
+typedef struct EtcHostsItemByName {
+        char *name;
+
+        EtcHostsItem **items;
+        size_t n_items, n_allocated;
+} EtcHostsItemByName;
+
+void manager_etc_hosts_flush(Manager *m) {
+        EtcHostsItem *item;
+        EtcHostsItemByName *bn;
+
+        while ((item = set_steal_first(m->etc_hosts_by_address))) {
+                strv_free(item->names);
+                free(item);
+        }
+
+        while ((bn = hashmap_steal_first(m->etc_hosts_by_name))) {
+                free(bn->name);
+                free(bn->items);
+                free(bn);
+        }
+
+        m->etc_hosts_by_address = set_free(m->etc_hosts_by_address);
+        m->etc_hosts_by_name = hashmap_free(m->etc_hosts_by_name);
+
+        m->etc_hosts_mtime = USEC_INFINITY;
+}
+
+static void etc_hosts_item_hash_func(const void *p, struct siphash *state) {
+        const EtcHostsItem *item = p;
+
+        siphash24_compress(&item->family, sizeof(item->family), state);
+
+        if (item->family == AF_INET)
+                siphash24_compress(&item->address.in, sizeof(item->address.in), state);
+        else if (item->family == AF_INET6)
+                siphash24_compress(&item->address.in6, sizeof(item->address.in6), state);
+}
+
+static int etc_hosts_item_compare_func(const void *a, const void *b) {
+        const EtcHostsItem *x = a, *y = b;
+
+        if (x->family != y->family)
+                return x->family - y->family;
+
+        if (x->family == AF_INET)
+                return memcmp(&x->address.in.s_addr, &y->address.in.s_addr, sizeof(struct in_addr));
+
+        if (x->family == AF_INET6)
+                return memcmp(&x->address.in6.s6_addr, &y->address.in6.s6_addr, sizeof(struct in6_addr));
+
+        return trivial_compare_func(a, b);
+}
+
+static const struct hash_ops etc_hosts_item_ops = {
+        .hash = etc_hosts_item_hash_func,
+        .compare = etc_hosts_item_compare_func,
+};
+
+static int add_item(Manager *m, int family, const union in_addr_union *address, char **names) {
+
+        EtcHostsItem key = {
+                .family = family,
+                .address = *address,
+        };
+        EtcHostsItem *item;
+        char **n;
+        int r;
+
+        assert(m);
+        assert(address);
+
+        r = in_addr_is_null(family, address);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to
+                 * nothing. */
+                item = NULL;
+        else {
+                /* If this is a normal address, then, simply add entry mapping it to the specified names */
+
+                item = set_get(m->etc_hosts_by_address, &key);
+                if (item) {
+                        r = strv_extend_strv(&item->names, names, true);
+                        if (r < 0)
+                                return log_oom();
+                } else {
+
+                        r = set_ensure_allocated(&m->etc_hosts_by_address, &etc_hosts_item_ops);
+                        if (r < 0)
+                                return log_oom();
+
+                        item = new0(EtcHostsItem, 1);
+                        if (!item)
+                                return log_oom();
+
+                        item->family = family;
+                        item->address = *address;
+                        item->names = names;
+
+                        r = set_put(m->etc_hosts_by_address, item);
+                        if (r < 0) {
+                                free(item);
+                                return log_oom();
+                        }
+                }
+        }
+
+        STRV_FOREACH(n, names) {
+                EtcHostsItemByName *bn;
+
+                bn = hashmap_get(m->etc_hosts_by_name, *n);
+                if (!bn) {
+                        r = hashmap_ensure_allocated(&m->etc_hosts_by_name, &dns_name_hash_ops);
+                        if (r < 0)
+                                return log_oom();
+
+                        bn = new0(EtcHostsItemByName, 1);
+                        if (!bn)
+                                return log_oom();
+
+                        bn->name = strdup(*n);
+                        if (!bn->name) {
+                                free(bn);
+                                return log_oom();
+                        }
+
+                        r = hashmap_put(m->etc_hosts_by_name, bn->name, bn);
+                        if (r < 0) {
+                                free(bn->name);
+                                free(bn);
+                                return log_oom();
+                        }
+                }
+
+                if (item) {
+                        if (!GREEDY_REALLOC(bn->items, bn->n_allocated, bn->n_items+1))
+                                return log_oom();
+
+                        bn->items[bn->n_items++] = item;
+                }
+        }
+
+        return 0;
+}
+
+static int parse_line(Manager *m, unsigned nr, const char *line) {
+        _cleanup_free_ char *address = NULL;
+        _cleanup_strv_free_ char **names = NULL;
+        union in_addr_union in;
+        bool suppressed = false;
+        int family, r;
+
+        assert(m);
+        assert(line);
+
+        r = extract_first_word(&line, &address, NULL, EXTRACT_RELAX);
+        if (r < 0)
+                return log_error_errno(r, "Couldn't extract address, in line /etc/hosts:%u.", nr);
+        if (r == 0) {
+                log_error("Premature end of line, in line /etc/hosts:%u.", nr);
+                return -EINVAL;
+        }
+
+        r = in_addr_from_string_auto(address, &family, &in);
+        if (r < 0)
+                return log_error_errno(r, "Address '%s' is invalid, in line /etc/hosts:%u.", address, nr);
+
+        for (;;) {
+                _cleanup_free_ char *name = NULL;
+
+                r = extract_first_word(&line, &name, NULL, EXTRACT_RELAX);
+                if (r < 0)
+                        return log_error_errno(r, "Couldn't extract host name, in line /etc/hosts:%u.", nr);
+                if (r == 0)
+                        break;
+
+                r = dns_name_is_valid(name);
+                if (r <= 0)
+                        return log_error_errno(r, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u.", name, nr);
+
+                if (is_localhost(name)) {
+                        /* Suppress the "localhost" line that is often seen */
+                        suppressed = true;
+                        continue;
+                }
+
+                r = strv_push(&names, name);
+                if (r < 0)
+                        return log_oom();
+
+                name = NULL;
+        }
+
+        if (strv_isempty(names)) {
+
+                if (suppressed)
+                        return 0;
+
+                log_error("Line is missing any host names, in line /etc/hosts:%u.", nr);
+                return -EINVAL;
+        }
+
+        /* Takes possession of the names strv */
+        r = add_item(m, family, &in, names);
+        if (r < 0)
+                return r;
+
+        names = NULL;
+        return r;
+}
+
+int manager_etc_hosts_read(Manager *m) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char line[LINE_MAX];
+        struct stat st;
+        usec_t ts;
+        unsigned nr = 0;
+        int r;
+
+        assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0);
+
+        /* See if we checked /etc/hosts recently already */
+        if (m->etc_hosts_last != USEC_INFINITY && m->etc_hosts_last + ETC_HOSTS_RECHECK_USEC > ts)
+                return 0;
+
+        m->etc_hosts_last = ts;
+
+        if (m->etc_hosts_mtime != USEC_INFINITY) {
+                if (stat("/etc/hosts", &st) < 0) {
+                        if (errno == ENOENT) {
+                                r = 0;
+                                goto clear;
+                        }
+
+                        return log_error_errno(errno, "Failed to stat /etc/hosts: %m");
+                }
+
+                /* Did the mtime change? If not, there's no point in re-reading the file. */
+                if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime)
+                        return 0;
+        }
+
+        f = fopen("/etc/hosts", "re");
+        if (!f) {
+                if (errno == ENOENT) {
+                        r = 0;
+                        goto clear;
+                }
+
+                return log_error_errno(errno, "Failed to open /etc/hosts: %m");
+        }
+
+        /* Take the timestamp at the beginning of processing, so that any changes made later are read on the next
+         * invocation */
+        r = fstat(fileno(f), &st);
+        if (r < 0)
+                return log_error_errno(errno, "Failed to fstat() /etc/hosts: %m");
+
+        manager_etc_hosts_flush(m);
+
+        FOREACH_LINE(line, f, return log_error_errno(errno, "Failed to read /etc/hosts: %m")) {
+                char *l;
+
+                nr ++;
+
+                l = strstrip(line);
+                if (isempty(l))
+                        continue;
+                if (l[0] == '#')
+                        continue;
+
+                r = parse_line(m, nr, l);
+                if (r == -ENOMEM) /* On OOM we abandon the half-built-up structure. All other errors we ignore and proceed */
+                        goto clear;
+        }
+
+        m->etc_hosts_mtime = timespec_load(&st.st_mtim);
+        m->etc_hosts_last = ts;
+
+        return 1;
+
+clear:
+        manager_etc_hosts_flush(m);
+        return r;
+}
+
+int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
+        bool found_a = false, found_aaaa = false;
+        EtcHostsItemByName *bn;
+        EtcHostsItem k = {};
+        DnsResourceKey *t;
+        const char *name;
+        unsigned i;
+        int r;
+
+        assert(m);
+        assert(q);
+        assert(answer);
+
+        r = manager_etc_hosts_read(m);
+        if (r < 0)
+                return r;
+
+        name = dns_question_first_name(q);
+        if (!name)
+                return 0;
+
+        r = dns_name_address(name, &k.family, &k.address);
+        if (r > 0) {
+                EtcHostsItem *item;
+                DnsResourceKey *found_ptr = NULL;
+
+                item = set_get(m->etc_hosts_by_address, &k);
+                if (!item)
+                        return 0;
+
+                /* We have an address in /etc/hosts that matches the queried name. Let's return successful. Actual data
+                 * we'll only return if the request was for PTR. */
+
+                DNS_QUESTION_FOREACH(t, q) {
+                        if (!IN_SET(t->type, DNS_TYPE_PTR, DNS_TYPE_ANY))
+                                continue;
+                        if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
+                                continue;
+
+                        r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                found_ptr = t;
+                                break;
+                        }
+                }
+
+                if (found_ptr) {
+                        char **n;
+
+                        r = dns_answer_reserve(answer, strv_length(item->names));
+                        if (r < 0)
+                                return r;
+
+                        STRV_FOREACH(n, item->names) {
+                                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                                rr = dns_resource_record_new(found_ptr);
+                                if (!rr)
+                                        return -ENOMEM;
+
+                                rr->ptr.name = strdup(*n);
+                                if (!rr->ptr.name)
+                                        return -ENOMEM;
+
+                                r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+                                if (r < 0)
+                                        return r;
+                        }
+                }
+
+                return 1;
+        }
+
+        bn = hashmap_get(m->etc_hosts_by_name, name);
+        if (!bn)
+                return 0;
+
+        r = dns_answer_reserve(answer, bn->n_items);
+        if (r < 0)
+                return r;
+
+        DNS_QUESTION_FOREACH(t, q) {
+                if (!IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY))
+                        continue;
+                if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
+                        continue;
+
+                r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        continue;
+
+                if (IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_ANY))
+                        found_a = true;
+                if (IN_SET(t->type, DNS_TYPE_AAAA, DNS_TYPE_ANY))
+                        found_aaaa = true;
+
+                if (found_a && found_aaaa)
+                        break;
+        }
+
+        for (i = 0; i < bn->n_items; i++) {
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+
+                if ((found_a && bn->items[i]->family != AF_INET) &&
+                    (found_aaaa && bn->items[i]->family != AF_INET6))
+                        continue;
+
+                r = dns_resource_record_new_address(&rr, bn->items[i]->family, &bn->items[i]->address, bn->name);
+                if (r < 0)
+                        return r;
+
+                r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+                if (r < 0)
+                        return r;
+        }
+
+        return 1;
+}
diff --git a/src/resolve/resolved-etc-hosts.h b/src/resolve/resolved-etc-hosts.h
new file mode 100644 (file)
index 0000000..9d5a175
--- /dev/null
@@ -0,0 +1,28 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "resolved-manager.h"
+#include "resolved-dns-question.h"
+#include "resolved-dns-answer.h"
+
+void manager_etc_hosts_flush(Manager *m);
+int manager_etc_hosts_read(Manager *m);
+int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer);
index 8e78fbf06abe02e5215dad3825f83189f3db4226..82f26215df6df1ff7634ba0f6298f10154a620d1 100644 (file)
@@ -14,6 +14,8 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Resolve.DNS,          config_parse_dnsv,    DNS_SERVER_SYSTEM,   0
-Resolve.FallbackDNS,  config_parse_dnsv,    DNS_SERVER_FALLBACK, 0
-Resolve.LLMNR,        config_parse_support, 0,                   offsetof(Manager, llmnr_support)
+Resolve.DNS,          config_parse_dns_servers,     DNS_SERVER_SYSTEM,   0
+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.DNSSEC,       config_parse_dnssec_mode,     0,                   offsetof(Manager, dnssec_mode)
diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
new file mode 100644 (file)
index 0000000..df7516f
--- /dev/null
@@ -0,0 +1,550 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "alloc-util.h"
+#include "bus-util.h"
+#include "parse-util.h"
+#include "resolve-util.h"
+#include "resolved-bus.h"
+#include "resolved-link-bus.h"
+#include "strv.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_dnssec_mode, dnssec_mode, DnssecMode);
+
+static int property_get_dns(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Link *l = userdata;
+        DnsServer *s;
+        int r;
+
+        assert(reply);
+        assert(l);
+
+        r = sd_bus_message_open_container(reply, 'a', "(iay)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(servers, s, l->dns_servers) {
+                r = bus_dns_server_append(reply, s, false);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_domains(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Link *l = userdata;
+        DnsSearchDomain *d;
+        int r;
+
+        assert(reply);
+        assert(l);
+
+        r = sd_bus_message_open_container(reply, 'a', "(sb)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(domains, d, l->search_domains) {
+                r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_scopes_mask(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Link *l = userdata;
+        uint64_t mask;
+
+        assert(reply);
+        assert(l);
+
+        mask =  (l->unicast_scope ? SD_RESOLVED_DNS : 0) |
+                (l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) |
+                (l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) |
+                (l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) |
+                (l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0);
+
+        return sd_bus_message_append(reply, "t", mask);
+}
+
+static int property_get_ntas(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Link *l = userdata;
+        const char *name;
+        Iterator i;
+        int r;
+
+        assert(reply);
+        assert(l);
+
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
+
+        SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) {
+                r = sd_bus_message_append(reply, "s", name);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_dnssec_supported(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Link *l = userdata;
+
+        assert(reply);
+        assert(l);
+
+        return sd_bus_message_append(reply, "b", link_dnssec_supported(l));
+}
+
+int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_free_ struct in_addr_data *dns = NULL;
+        size_t allocated = 0, n = 0;
+        Link *l = userdata;
+        unsigned i;
+        int r;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_enter_container(message, 'a', "(iay)");
+        if (r < 0)
+                return r;
+
+        for (;;) {
+                int family;
+                size_t sz;
+                const void *d;
+
+                assert_cc(sizeof(int) == sizeof(int32_t));
+
+                r = sd_bus_message_enter_container(message, 'r', "iay");
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                r = sd_bus_message_read(message, "i", &family);
+                if (r < 0)
+                        return r;
+
+                if (!IN_SET(family, AF_INET, AF_INET6))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
+
+                r = sd_bus_message_read_array(message, 'y', &d, &sz);
+                if (r < 0)
+                        return r;
+                if (sz != FAMILY_ADDRESS_SIZE(family))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
+
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
+
+                if (!GREEDY_REALLOC(dns, allocated, n+1))
+                        return -ENOMEM;
+
+                dns[n].family = family;
+                memcpy(&dns[n].address, d, sz);
+                n++;
+        }
+
+        r = sd_bus_message_exit_container(message);
+        if (r < 0)
+                return r;
+
+        dns_server_mark_all(l->dns_servers);
+
+        for (i = 0; i < n; i++) {
+                DnsServer *s;
+
+                s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address);
+                if (s)
+                        dns_server_move_back_and_unmark(s);
+                else {
+                        r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address);
+                        if (r < 0)
+                                goto clear;
+                }
+
+        }
+
+        dns_server_unlink_marked(l->dns_servers);
+        link_allocate_scopes(l);
+
+        return sd_bus_reply_method_return(message, NULL);
+
+clear:
+        dns_server_unlink_all(l->dns_servers);
+        return r;
+}
+
+int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Link *l = userdata;
+        int r;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_enter_container(message, 'a', "(sb)");
+        if (r < 0)
+                return r;
+
+        for (;;) {
+                const char *name;
+                int route_only;
+
+                r = sd_bus_message_read(message, "(sb)", &name, &route_only);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                r = dns_name_is_valid(name);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
+                if (!route_only && dns_name_is_root(name))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
+        }
+
+        dns_search_domain_mark_all(l->search_domains);
+
+        r = sd_bus_message_rewind(message, false);
+        if (r < 0)
+                return r;
+
+        for (;;) {
+                DnsSearchDomain *d;
+                const char *name;
+                int route_only;
+
+                r = sd_bus_message_read(message, "(sb)", &name, &route_only);
+                if (r < 0)
+                        goto clear;
+                if (r == 0)
+                        break;
+
+                r = dns_search_domain_find(l->search_domains, name, &d);
+                if (r < 0)
+                        goto clear;
+
+                if (r > 0)
+                        dns_search_domain_move_back_and_unmark(d);
+                else {
+                        r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
+                        if (r < 0)
+                                goto clear;
+                }
+
+                d->route_only = route_only;
+        }
+
+        r = sd_bus_message_exit_container(message);
+        if (r < 0)
+                goto clear;
+
+        dns_search_domain_unlink_marked(l->search_domains);
+        return sd_bus_reply_method_return(message, NULL);
+
+clear:
+        dns_search_domain_unlink_all(l->search_domains);
+        return r;
+}
+
+int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Link *l = userdata;
+        ResolveSupport mode;
+        const char *llmnr;
+        int r;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_read(message, "s", &llmnr);
+        if (r < 0)
+                return r;
+
+        if (isempty(llmnr))
+                mode = RESOLVE_SUPPORT_YES;
+        else {
+                mode = resolve_support_from_string(llmnr);
+                if (mode < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
+        }
+
+        l->llmnr_support = mode;
+        link_allocate_scopes(l);
+        link_add_rrs(l, false);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Link *l = userdata;
+        ResolveSupport mode;
+        const char *mdns;
+        int r;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_read(message, "s", &mdns);
+        if (r < 0)
+                return r;
+
+        if (isempty(mdns))
+                mode = RESOLVE_SUPPORT_NO;
+        else {
+                mode = resolve_support_from_string(mdns);
+                if (mode < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
+        }
+
+        l->mdns_support = mode;
+        link_allocate_scopes(l);
+        link_add_rrs(l, false);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Link *l = userdata;
+        const char *dnssec;
+        DnssecMode mode;
+        int r;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_read(message, "s", &dnssec);
+        if (r < 0)
+                return r;
+
+        if (isempty(dnssec))
+                mode = _DNSSEC_MODE_INVALID;
+        else {
+                mode = dnssec_mode_from_string(dnssec);
+                if (mode < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
+        }
+
+        link_set_dnssec_mode(l, mode);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_set_free_free_ Set *ns = NULL;
+        _cleanup_free_ char **ntas = NULL;
+        Link *l = userdata;
+        int r;
+        char **i;
+
+        assert(message);
+        assert(l);
+
+        r = sd_bus_message_read_strv(message, &ntas);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(i, ntas) {
+                r = dns_name_is_valid(*i);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i);
+        }
+
+        ns = set_new(&dns_name_hash_ops);
+        if (!ns)
+                return -ENOMEM;
+
+        STRV_FOREACH(i, ntas) {
+                r = set_put_strdup(ns, *i);
+                if (r < 0)
+                        return r;
+        }
+
+        set_free_free(l->dnssec_negative_trust_anchors);
+        l->dnssec_negative_trust_anchors = ns;
+        ns = NULL;
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Link *l = userdata;
+
+        assert(message);
+        assert(l);
+
+        link_flush_settings(l);
+        link_allocate_scopes(l);
+        link_add_rrs(l, false);
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+const sd_bus_vtable link_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
+        SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
+        SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
+        SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
+        SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
+        SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0),
+        SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
+        SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0),
+
+        SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0),
+        SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_search_domains, 0),
+        SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0),
+        SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0),
+        SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0),
+        SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0),
+        SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0),
+
+        SD_BUS_VTABLE_END
+};
+
+int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+        _cleanup_free_ char *e = NULL;
+        Manager *m = userdata;
+        int ifindex;
+        Link *link;
+        int r;
+
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
+
+        r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e);
+        if (r <= 0)
+                return 0;
+
+        r = parse_ifindex(e, &ifindex);
+        if (r < 0)
+                return 0;
+
+        link = hashmap_get(m->links, INT_TO_PTR(ifindex));
+        if (!link)
+                return 0;
+
+        *found = link;
+        return 1;
+}
+
+char *link_bus_path(Link *link) {
+        _cleanup_free_ char *ifindex = NULL;
+        char *p;
+        int r;
+
+        assert(link);
+
+        if (asprintf(&ifindex, "%i", link->ifindex) < 0)
+                return NULL;
+
+        r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p);
+        if (r < 0)
+                return NULL;
+
+        return p;
+}
+
+int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+        _cleanup_strv_free_ char **l = NULL;
+        Manager *m = userdata;
+        Link *link;
+        Iterator i;
+        unsigned c = 0;
+
+        assert(bus);
+        assert(path);
+        assert(m);
+        assert(nodes);
+
+        l = new0(char*, hashmap_size(m->links) + 1);
+        if (!l)
+                return -ENOMEM;
+
+        HASHMAP_FOREACH(link, m->links, i) {
+                char *p;
+
+                p = link_bus_path(link);
+                if (!p)
+                        return -ENOMEM;
+
+                l[c++] = p;
+        }
+
+        l[c] = NULL;
+        *nodes = l;
+        l = NULL;
+
+        return 1;
+}
diff --git a/src/resolve/resolved-link-bus.h b/src/resolve/resolved-link-bus.h
new file mode 100644 (file)
index 0000000..31e6cd2
--- /dev/null
@@ -0,0 +1,38 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "resolved-link.h"
+
+extern const sd_bus_vtable link_vtable[];
+
+int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
+char *link_bus_path(Link *link);
+int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+
+int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error);
index 28926410753ffae5925bd94e7731808cab5ef640..c5863b3aa240f75832caff66a8e6df1d5852ff54 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -46,7 +44,10 @@ int link_new(Manager *m, Link **ret, int ifindex) {
                 return -ENOMEM;
 
         l->ifindex = ifindex;
-        l->llmnr_support = SUPPORT_YES;
+        l->llmnr_support = RESOLVE_SUPPORT_YES;
+        l->mdns_support = RESOLVE_SUPPORT_NO;
+        l->dnssec_mode = _DNSSEC_MODE_INVALID;
+        l->operstate = IF_OPER_UNKNOWN;
 
         r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
         if (r < 0)
@@ -61,37 +62,48 @@ int link_new(Manager *m, Link **ret, int ifindex) {
         return 0;
 }
 
+void link_flush_settings(Link *l) {
+        assert(l);
+
+        l->llmnr_support = RESOLVE_SUPPORT_YES;
+        l->mdns_support = RESOLVE_SUPPORT_NO;
+        l->dnssec_mode = _DNSSEC_MODE_INVALID;
+
+        dns_server_unlink_all(l->dns_servers);
+        dns_search_domain_unlink_all(l->search_domains);
+
+        l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
+}
+
 Link *link_free(Link *l) {
         if (!l)
                 return NULL;
 
+        link_flush_settings(l);
+
         while (l->addresses)
-                link_address_free(l->addresses);
+                (void) link_address_free(l->addresses);
 
         if (l->manager)
                 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
 
-        while (l->dns_servers) {
-                DnsServer *s = l->dns_servers;
-
-                LIST_REMOVE(servers, l->dns_servers, s);
-                dns_server_unref(s);
-        }
-
         dns_scope_free(l->unicast_scope);
         dns_scope_free(l->llmnr_ipv4_scope);
         dns_scope_free(l->llmnr_ipv6_scope);
+        dns_scope_free(l->mdns_ipv4_scope);
+        dns_scope_free(l->mdns_ipv6_scope);
 
         free(l);
         return NULL;
 }
 
-static void link_allocate_scopes(Link *l) {
+void link_allocate_scopes(Link *l) {
         int r;
 
         assert(l);
 
-        if (l->dns_servers) {
+        if (link_relevant(l, AF_UNSPEC, false) &&
+            l->dns_servers) {
                 if (!l->unicast_scope) {
                         r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
                         if (r < 0)
@@ -100,9 +112,9 @@ static void link_allocate_scopes(Link *l) {
         } else
                 l->unicast_scope = dns_scope_free(l->unicast_scope);
 
-        if (link_relevant(l, AF_INET) &&
-            l->llmnr_support != SUPPORT_NO &&
-            l->manager->llmnr_support != SUPPORT_NO) {
+        if (link_relevant(l, AF_INET, true) &&
+            l->llmnr_support != RESOLVE_SUPPORT_NO &&
+            l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
                 if (!l->llmnr_ipv4_scope) {
                         r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
                         if (r < 0)
@@ -111,9 +123,9 @@ static void link_allocate_scopes(Link *l) {
         } else
                 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
 
-        if (link_relevant(l, AF_INET6) &&
-            l->llmnr_support != SUPPORT_NO &&
-            l->manager->llmnr_support != SUPPORT_NO &&
+        if (link_relevant(l, AF_INET6, true) &&
+            l->llmnr_support != RESOLVE_SUPPORT_NO &&
+            l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
             socket_ipv6_is_supported()) {
                 if (!l->llmnr_ipv6_scope) {
                         r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
@@ -122,6 +134,28 @@ static void link_allocate_scopes(Link *l) {
                 }
         } else
                 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
+
+        if (link_relevant(l, AF_INET, true) &&
+            l->mdns_support != RESOLVE_SUPPORT_NO &&
+            l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
+                if (!l->mdns_ipv4_scope) {
+                        r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
+                }
+        } else
+                l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
+
+        if (link_relevant(l, AF_INET6, true) &&
+            l->mdns_support != RESOLVE_SUPPORT_NO &&
+            l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
+                if (!l->mdns_ipv6_scope) {
+                        r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
+                }
+        } else
+                l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
 }
 
 void link_add_rrs(Link *l, bool force_remove) {
@@ -142,7 +176,8 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
         if (r < 0)
                 return r;
 
-        sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
+        (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
+        (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
 
         if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
                 strncpy(l->name, n, sizeof(l->name)-1);
@@ -158,29 +193,32 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
 static int link_update_dns_servers(Link *l) {
         _cleanup_strv_free_ char **nameservers = NULL;
         char **nameserver;
-        DnsServer *s, *nx;
         int r;
 
         assert(l);
 
         r = sd_network_link_get_dns(l->ifindex, &nameservers);
+        if (r == -ENODATA) {
+                r = 0;
+                goto clear;
+        }
         if (r < 0)
                 goto clear;
 
-        LIST_FOREACH(servers, s, l->dns_servers)
-                s->marked = true;
+        dns_server_mark_all(l->dns_servers);
 
         STRV_FOREACH(nameserver, nameservers) {
                 union in_addr_union a;
+                DnsServer *s;
                 int family;
 
                 r = in_addr_from_string_auto(*nameserver, &family, &a);
                 if (r < 0)
                         goto clear;
 
-                s = link_find_dns_server(l, family, &a);
+                s = dns_server_find(l->dns_servers, family, &a);
                 if (s)
-                        s->marked = false;
+                        dns_server_move_back_and_unmark(s);
                 else {
                         r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
                         if (r < 0)
@@ -188,104 +226,330 @@ static int link_update_dns_servers(Link *l) {
                 }
         }
 
-        LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
-                if (s->marked) {
-                        LIST_REMOVE(servers, l->dns_servers, s);
-                        dns_server_unref(s);
-                }
-
+        dns_server_unlink_marked(l->dns_servers);
         return 0;
 
 clear:
-        while (l->dns_servers) {
-                s = l->dns_servers;
+        dns_server_unlink_all(l->dns_servers);
+        return r;
+}
+
+static int link_update_llmnr_support(Link *l) {
+        _cleanup_free_ char *b = NULL;
+        int r;
+
+        assert(l);
 
-                LIST_REMOVE(servers, l->dns_servers, s);
-                dns_server_unref(s);
+        r = sd_network_link_get_llmnr(l->ifindex, &b);
+        if (r == -ENODATA) {
+                r = 0;
+                goto clear;
         }
+        if (r < 0)
+                goto clear;
 
+        l->llmnr_support = resolve_support_from_string(b);
+        if (l->llmnr_support < 0) {
+                r = -EINVAL;
+                goto clear;
+        }
+
+        return 0;
+
+clear:
+        l->llmnr_support = RESOLVE_SUPPORT_YES;
         return r;
 }
 
-static int link_update_llmnr_support(Link *l) {
+static int link_update_mdns_support(Link *l) {
         _cleanup_free_ char *b = NULL;
         int r;
 
         assert(l);
 
-        r = sd_network_link_get_llmnr(l->ifindex, &b);
+        r = sd_network_link_get_mdns(l->ifindex, &b);
+        if (r == -ENODATA) {
+                r = 0;
+                goto clear;
+        }
         if (r < 0)
                 goto clear;
 
-        r = parse_boolean(b);
-        if (r < 0) {
-                if (streq(b, "resolve"))
-                        l->llmnr_support = SUPPORT_RESOLVE;
-                else
-                        goto clear;
+        l->mdns_support = resolve_support_from_string(b);
+        if (l->mdns_support < 0) {
+                r = -EINVAL;
+                goto clear;
+        }
+
+        return 0;
+
+clear:
+        l->mdns_support = RESOLVE_SUPPORT_NO;
+        return r;
+}
+
+void link_set_dnssec_mode(Link *l, DnssecMode mode) {
+
+        assert(l);
+
+        if (l->dnssec_mode == mode)
+                return;
+
+        if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
+            (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
+            (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
+
+                /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
+                 * allow-downgrade mode to full DNSSEC mode, flush it too. */
+                if (l->unicast_scope)
+                        dns_cache_flush(&l->unicast_scope->cache);
+        }
+
+        l->dnssec_mode = mode;
+}
 
-        } else if (r > 0)
-                l->llmnr_support = SUPPORT_YES;
-        else
-                l->llmnr_support = SUPPORT_NO;
+static int link_update_dnssec_mode(Link *l) {
+        _cleanup_free_ char *m = NULL;
+        DnssecMode mode;
+        int r;
+
+        assert(l);
+
+        r = sd_network_link_get_dnssec(l->ifindex, &m);
+        if (r == -ENODATA) {
+                r = 0;
+                goto clear;
+        }
+        if (r < 0)
+                goto clear;
+
+        mode = dnssec_mode_from_string(m);
+        if (mode < 0) {
+                r = -EINVAL;
+                goto clear;
+        }
+
+        link_set_dnssec_mode(l, mode);
 
         return 0;
 
 clear:
-        l->llmnr_support = SUPPORT_YES;
+        l->dnssec_mode = _DNSSEC_MODE_INVALID;
         return r;
 }
 
-static int link_update_domains(Link *l) {
+static int link_update_dnssec_negative_trust_anchors(Link *l) {
+        _cleanup_strv_free_ char **ntas = NULL;
+        _cleanup_set_free_free_ Set *ns = NULL;
+        char **i;
         int r;
 
-        if (!l->unicast_scope)
-                return 0;
+        assert(l);
+
+        r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
+        if (r == -ENODATA) {
+                r = 0;
+                goto clear;
+        }
+        if (r < 0)
+                goto clear;
+
+        ns = set_new(&dns_name_hash_ops);
+        if (!ns)
+                return -ENOMEM;
+
+        STRV_FOREACH(i, ntas) {
+                r = set_put_strdup(ns, *i);
+                if (r < 0)
+                        return r;
+        }
+
+        set_free_free(l->dnssec_negative_trust_anchors);
+        l->dnssec_negative_trust_anchors = ns;
+        ns = NULL;
+
+        return 0;
+
+clear:
+        l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
+        return r;
+}
 
-        l->unicast_scope->domains = strv_free(l->unicast_scope->domains);
+static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
+        DnsSearchDomain *d;
+        int r;
 
-        r = sd_network_link_get_domains(l->ifindex,
-                                        &l->unicast_scope->domains);
+        r = dns_search_domain_find(l->search_domains, name, &d);
         if (r < 0)
                 return r;
+        if (r > 0)
+                dns_search_domain_move_back_and_unmark(d);
+        else {
+                r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
+                if (r < 0)
+                        return r;
+        }
 
+        d->route_only = route_only;
         return 0;
 }
 
+static int link_update_search_domains(Link *l) {
+        _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
+        char **i;
+        int r, q;
+
+        assert(l);
+
+        r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
+        if (r < 0 && r != -ENODATA)
+                goto clear;
+
+        q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
+        if (q < 0 && q != -ENODATA) {
+                r = q;
+                goto clear;
+        }
+
+        if (r == -ENODATA && q == -ENODATA) {
+                /* networkd knows nothing about this interface, and that's fine. */
+                r = 0;
+                goto clear;
+        }
+
+        dns_search_domain_mark_all(l->search_domains);
+
+        STRV_FOREACH(i, sdomains) {
+                r = link_update_search_domain_one(l, *i, false);
+                if (r < 0)
+                        goto clear;
+        }
+
+        STRV_FOREACH(i, rdomains) {
+                r = link_update_search_domain_one(l, *i, true);
+                if (r < 0)
+                        goto clear;
+        }
+
+        dns_search_domain_unlink_marked(l->search_domains);
+        return 0;
+
+clear:
+        dns_search_domain_unlink_all(l->search_domains);
+        return r;
+}
+
+static int link_is_unmanaged(Link *l) {
+        _cleanup_free_ char *state = NULL;
+        int r;
+
+        assert(l);
+
+        r = sd_network_link_get_setup_state(l->ifindex, &state);
+        if (r == -ENODATA)
+                return 1;
+        if (r < 0)
+                return r;
+
+        return STR_IN_SET(state, "pending", "unmanaged");
+}
+
+static void link_read_settings(Link *l) {
+        int r;
+
+        assert(l);
+
+        /* Read settings from networkd, except when networkd is not managing this interface. */
+
+        r = link_is_unmanaged(l);
+        if (r < 0) {
+                log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
+                return;
+        }
+        if (r > 0) {
+
+                /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
+                if (l->is_managed)
+                        link_flush_settings(l);
+
+                l->is_managed = false;
+                return;
+        }
+
+        l->is_managed = true;
+
+        r = link_update_dns_servers(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
+
+        r = link_update_llmnr_support(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
+
+        r = link_update_mdns_support(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
+
+        r = link_update_dnssec_mode(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
+
+        r = link_update_dnssec_negative_trust_anchors(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
+
+        r = link_update_search_domains(l);
+        if (r < 0)
+                log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
+}
+
 int link_update_monitor(Link *l) {
         assert(l);
 
-        link_update_dns_servers(l);
-        link_update_llmnr_support(l);
+        link_read_settings(l);
         link_allocate_scopes(l);
-        link_update_domains(l);
         link_add_rrs(l, false);
 
         return 0;
 }
 
-bool link_relevant(Link *l, int family) {
+bool link_relevant(Link *l, int family, bool local_multicast) {
         _cleanup_free_ char *state = NULL;
         LinkAddress *a;
 
         assert(l);
 
-        /* A link is relevant if it isn't a loopback or pointopoint
-         * device, has a link beat, can do multicast and has at least
-         * one relevant IP address */
+        /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint 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
+         * least one routable address.*/
 
-        if (l->flags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_DORMANT))
+        if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
                 return false;
 
-        if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
+        if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
                 return false;
 
-        sd_network_link_get_operational_state(l->ifindex, &state);
+        if (local_multicast) {
+                if (l->flags & IFF_POINTOPOINT)
+                        return false;
+
+                if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
+                        return false;
+        }
+
+        /* Check kernel operstate
+         * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
+        if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
+                return false;
+
+        (void) sd_network_link_get_operational_state(l->ifindex, &state);
         if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
                 return false;
 
         LIST_FOREACH(addresses, a, l->addresses)
-                if (a->family == family && link_address_relevant(a))
+                if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
                         return true;
 
         return false;
@@ -303,31 +567,17 @@ LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *i
         return NULL;
 }
 
-DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr) {
-        DnsServer *s;
-
-        assert(l);
-
-        LIST_FOREACH(servers, s, l->dns_servers)
-                if (s->family == family && in_addr_equal(family, &s->address, in_addr))
-                        return s;
-        return NULL;
-}
-
 DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
         assert(l);
 
         if (l->current_dns_server == s)
                 return s;
 
-        if (s) {
-                _cleanup_free_ char *ip = NULL;
-
-                in_addr_to_string(s->family, &s->address, &ip);
-                log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name);
-        }
+        if (s)
+                log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
 
-        l->current_dns_server = s;
+        dns_server_unref(l->current_dns_server);
+        l->current_dns_server = dns_server_ref(s);
 
         if (l->unicast_scope)
                 dns_cache_flush(&l->unicast_scope->cache);
@@ -350,7 +600,9 @@ void link_next_dns_server(Link *l) {
         if (!l->current_dns_server)
                 return;
 
-        if (l->current_dns_server->servers_next) {
+        /* Change to the next one, but make sure to follow the linked
+         * list only if this server is actually still linked. */
+        if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
                 link_set_dns_server(l, l->current_dns_server->servers_next);
                 return;
         }
@@ -358,6 +610,30 @@ void link_next_dns_server(Link *l) {
         link_set_dns_server(l, l->dns_servers);
 }
 
+DnssecMode link_get_dnssec_mode(Link *l) {
+        assert(l);
+
+        if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
+                return l->dnssec_mode;
+
+        return manager_get_dnssec_mode(l->manager);
+}
+
+bool link_dnssec_supported(Link *l) {
+        DnsServer *server;
+
+        assert(l);
+
+        if (link_get_dnssec_mode(l) == DNSSEC_NO)
+                return false;
+
+        server = link_get_dns_server(l);
+        if (server)
+                return dns_server_dnssec_supported(server);
+
+        return true;
+}
+
 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
         LinkAddress *a;
 
@@ -417,10 +693,10 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) {
         if (a->family == AF_INET) {
 
                 if (!force_remove &&
-                    link_address_relevant(a) &&
+                    link_address_relevant(a, true) &&
                     a->link->llmnr_ipv4_scope &&
-                    a->link->llmnr_support == SUPPORT_YES &&
-                    a->link->manager->llmnr_support == SUPPORT_YES) {
+                    a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
+                    a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
 
                         if (!a->link->manager->llmnr_host_ipv4_key) {
                                 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
@@ -474,10 +750,10 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) {
         if (a->family == AF_INET6) {
 
                 if (!force_remove &&
-                    link_address_relevant(a) &&
+                    link_address_relevant(a, true) &&
                     a->link->llmnr_ipv6_scope &&
-                    a->link->llmnr_support == SUPPORT_YES &&
-                    a->link->manager->llmnr_support == SUPPORT_YES) {
+                    a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
+                    a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
 
                         if (!a->link->manager->llmnr_host_ipv6_key) {
                                 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
@@ -551,13 +827,13 @@ int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
         return 0;
 }
 
-bool link_address_relevant(LinkAddress *a) {
+bool link_address_relevant(LinkAddress *a, bool local_multicast) {
         assert(a);
 
         if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
                 return false;
 
-        if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
+        if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
                 return false;
 
         return true;
index e3ab27c2497329b3dc757c73a50b6e49bb229c37..f534c12824d53a0ae09d17f32c5ff0ec97391cb5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include "in-addr-util.h"
 #include "ratelimit.h"
+#include "resolve-util.h"
 
 typedef struct Link Link;
 typedef struct LinkAddress LinkAddress;
 
 #include "resolved-dns-rr.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
 #include "resolved-manager.h"
 
+#define LINK_SEARCH_DOMAINS_MAX 32
+#define LINK_DNS_SERVERS_MAX 32
+
 struct LinkAddress {
         Link *link;
 
@@ -56,34 +60,52 @@ struct Link {
 
         LIST_HEAD(DnsServer, dns_servers);
         DnsServer *current_dns_server;
+        unsigned n_dns_servers;
+
+        LIST_HEAD(DnsSearchDomain, search_domains);
+        unsigned n_search_domains;
 
-        Support llmnr_support;
+        ResolveSupport llmnr_support;
+        ResolveSupport mdns_support;
+        DnssecMode dnssec_mode;
+        Set *dnssec_negative_trust_anchors;
 
         DnsScope *unicast_scope;
         DnsScope *llmnr_ipv4_scope;
         DnsScope *llmnr_ipv6_scope;
+        DnsScope *mdns_ipv4_scope;
+        DnsScope *mdns_ipv6_scope;
+
+        bool is_managed;
 
         char name[IF_NAMESIZE];
         uint32_t mtu;
+        uint8_t operstate;
 };
 
 int link_new(Manager *m, Link **ret, int ifindex);
 Link *link_free(Link *l);
 int link_update_rtnl(Link *l, sd_netlink_message *m);
 int link_update_monitor(Link *l);
-bool link_relevant(Link *l, int family);
+bool link_relevant(Link *l, int family, bool local_multicast);
 LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr);
 void link_add_rrs(Link *l, bool force_remove);
 
+void link_flush_settings(Link *l);
+void link_set_dnssec_mode(Link *l, DnssecMode mode);
+void link_allocate_scopes(Link *l);
+
 DnsServer* link_set_dns_server(Link *l, DnsServer *s);
-DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr);
 DnsServer* link_get_dns_server(Link *l);
 void link_next_dns_server(Link *l);
 
+DnssecMode link_get_dnssec_mode(Link *l);
+bool link_dnssec_supported(Link *l);
+
 int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr);
 LinkAddress *link_address_free(LinkAddress *a);
 int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m);
-bool link_address_relevant(LinkAddress *l);
+bool link_address_relevant(LinkAddress *l, bool local_multicast);
 void link_address_add_rrs(LinkAddress *a, bool force_remove);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
index 6a7ff9d24589329ce5d85d811502dce74d7907fa..ef12abfbb52d33fe60fed2923f40af40d804a9dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -47,7 +45,7 @@ int manager_llmnr_start(Manager *m) {
 
         assert(m);
 
-        if (m->llmnr_support == SUPPORT_NO)
+        if (m->llmnr_support == RESOLVE_SUPPORT_NO)
                 return 0;
 
         r = manager_llmnr_ipv4_udp_fd(m);
@@ -80,7 +78,7 @@ int manager_llmnr_start(Manager *m) {
 
 eaddrinuse:
         log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
-        m->llmnr_support = SUPPORT_NO;
+        m->llmnr_support = RESOLVE_SUPPORT_NO;
         manager_llmnr_stop(m);
 
         return 0;
@@ -117,7 +115,7 @@ static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *u
 
                 dns_scope_process_query(scope, NULL, p);
         } else
-                log_debug("Invalid LLMNR UDP packet.");
+                log_debug("Invalid LLMNR UDP packet, ignoring.");
 
         return 0;
 }
@@ -193,6 +191,8 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
         if (r < 0)
                 goto fail;
 
+        (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
+
         return m->llmnr_ipv4_udp_fd;
 
 fail:
@@ -267,10 +267,10 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
         }
 
         r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
-        if (r < 0)  {
-                r = -errno;
+        if (r < 0)
                 goto fail;
-        }
+
+        (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
 
         return m->llmnr_ipv6_udp_fd;
 
@@ -393,6 +393,8 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) {
         if (r < 0)
                 goto fail;
 
+        (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
+
         return m->llmnr_ipv4_tcp_fd;
 
 fail:
@@ -461,10 +463,10 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
         }
 
         r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
-        if (r < 0)  {
-                r = -errno;
+        if (r < 0)
                 goto fail;
-        }
+
+        (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
 
         return m->llmnr_ipv6_tcp_fd;
 
index d489d481e8e4309f40cb95123bcd126abe77aab9..8133582fa70ed78709c37ac754ee7468339129ee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a588538b52afa2eb892804444ba4cbcd1b212531..bf5efe4cfa142f2827ec6d03420ef3bca1a0325d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,7 +19,6 @@
 
 #include <netinet/in.h>
 #include <poll.h>
-#include <resolv.h>
 #include <sys/ioctl.h>
 
 #include "af-list.h"
 #include "random-util.h"
 #include "resolved-bus.h"
 #include "resolved-conf.h"
+#include "resolved-etc-hosts.h"
 #include "resolved-llmnr.h"
 #include "resolved-manager.h"
+#include "resolved-mdns.h"
+#include "resolved-resolv-conf.h"
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -193,7 +193,7 @@ fail:
 }
 
 static int manager_rtnl_listen(Manager *m) {
-        _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         sd_netlink_message *i;
         int r;
 
@@ -204,7 +204,7 @@ static int manager_rtnl_listen(Manager *m) {
         if (r < 0)
                 return r;
 
-        r = sd_netlink_attach_event(m->rtnl, m->event, 0);
+        r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
         if (r < 0)
                 return r;
 
@@ -286,7 +286,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
 
         r = manager_write_resolv_conf(m);
         if (r < 0)
-                log_warning_errno(r, "Could not update resolv.conf: %m");
+                log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
 
         return 0;
 }
@@ -312,6 +312,12 @@ static int manager_network_monitor_listen(Manager *m) {
         if (r < 0)
                 return r;
 
+        r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5);
+        if (r < 0)
+                return r;
+
+        (void) sd_event_source_set_description(m->network_event_source, "network-monitor");
+
         return 0;
 }
 
@@ -351,7 +357,7 @@ static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
                 return -EINVAL;
         }
 
-        r = dns_label_escape(label, r, &n);
+        r = dns_label_escape_new(label, r, &n);
         if (r < 0)
                 return log_error_errno(r, "Failed to escape host name: %m");
 
@@ -419,6 +425,8 @@ static int manager_watch_hostname(Manager *m) {
                         return log_error_errno(r, "Failed to add hostname event source: %m");
         }
 
+        (void) sd_event_source_set_description(m->hostname_event_source, "hostname");
+
         r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
         if (r < 0) {
                 log_info("Defaulting to hostname 'linux'.");
@@ -472,12 +480,21 @@ int manager_new(Manager **ret) {
 
         m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
         m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
+        m->mdns_ipv4_fd = m->mdns_ipv6_fd = -1;
         m->hostname_fd = -1;
 
-        m->llmnr_support = SUPPORT_YES;
+        m->llmnr_support = RESOLVE_SUPPORT_YES;
+        m->mdns_support = RESOLVE_SUPPORT_NO;
+        m->dnssec_mode = DNSSEC_NO;
         m->read_resolv_conf = true;
+        m->need_builtin_fallbacks = true;
+        m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY;
 
-        r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
+        r = dns_trust_anchor_load(&m->trust_anchor);
+        if (r < 0)
+                return r;
+
+        r = manager_parse_config_file(m);
         if (r < 0)
                 return r;
 
@@ -527,6 +544,10 @@ int manager_start(Manager *m) {
         if (r < 0)
                 return r;
 
+        r = manager_mdns_start(m);
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
@@ -536,15 +557,16 @@ Manager *manager_free(Manager *m) {
         if (!m)
                 return NULL;
 
+        dns_server_unlink_all(m->dns_servers);
+        dns_server_unlink_all(m->fallback_dns_servers);
+        dns_search_domain_unlink_all(m->search_domains);
+
         while ((l = hashmap_first(m->links)))
                link_free(l);
 
         while (m->dns_queries)
                 dns_query_free(m->dns_queries);
 
-        manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
-        manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
-
         dns_scope_free(m->unicast_scope);
 
         hashmap_free(m->links);
@@ -553,7 +575,11 @@ Manager *manager_free(Manager *m) {
         sd_event_source_unref(m->network_event_source);
         sd_network_monitor_unref(m->network_monitor);
 
+        sd_netlink_unref(m->rtnl);
+        sd_event_source_unref(m->rtnl_event_source);
+
         manager_llmnr_stop(m);
+        manager_mdns_stop(m);
 
         sd_bus_slot_unref(m->prepare_for_sleep_slot);
         sd_event_source_unref(m->bus_retry_event_source);
@@ -571,299 +597,14 @@ Manager *manager_free(Manager *m) {
         free(m->llmnr_hostname);
         free(m->mdns_hostname);
 
+        dns_trust_anchor_flush(&m->trust_anchor);
+        manager_etc_hosts_flush(m);
+
         free(m);
 
         return NULL;
 }
 
-int manager_read_resolv_conf(Manager *m) {
-        _cleanup_fclose_ FILE *f = NULL;
-        struct stat st, own;
-        char line[LINE_MAX];
-        DnsServer *s, *nx;
-        usec_t t;
-        int r;
-
-        assert(m);
-
-        /* Reads the system /etc/resolv.conf, if it exists and is not
-         * symlinked to our own resolv.conf instance */
-
-        if (!m->read_resolv_conf)
-                return 0;
-
-        r = stat("/etc/resolv.conf", &st);
-        if (r < 0) {
-                if (errno != ENOENT)
-                        log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
-                r = -errno;
-                goto clear;
-        }
-
-        /* Have we already seen the file? */
-        t = timespec_load(&st.st_mtim);
-        if (t == m->resolv_conf_mtime)
-                return 0;
-
-        m->resolv_conf_mtime = t;
-
-        /* Is it symlinked to our own file? */
-        if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
-            st.st_dev == own.st_dev &&
-            st.st_ino == own.st_ino) {
-                r = 0;
-                goto clear;
-        }
-
-        f = fopen("/etc/resolv.conf", "re");
-        if (!f) {
-                if (errno != ENOENT)
-                        log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
-                r = -errno;
-                goto clear;
-        }
-
-        if (fstat(fileno(f), &st) < 0) {
-                r = log_error_errno(errno, "Failed to stat open file: %m");
-                goto clear;
-        }
-
-        LIST_FOREACH(servers, s, m->dns_servers)
-                s->marked = true;
-
-        FOREACH_LINE(line, f, r = -errno; goto clear) {
-                union in_addr_union address;
-                int family;
-                char *l;
-                const char *a;
-
-                truncate_nl(line);
-
-                l = strstrip(line);
-                if (*l == '#' || *l == ';')
-                        continue;
-
-                a = first_word(l, "nameserver");
-                if (!a)
-                        continue;
-
-                r = in_addr_from_string_auto(a, &family, &address);
-                if (r < 0) {
-                        log_warning("Failed to parse name server %s.", a);
-                        continue;
-                }
-
-                LIST_FOREACH(servers, s, m->dns_servers)
-                        if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
-                                break;
-
-                if (s)
-                        s->marked = false;
-                else {
-                        r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
-                        if (r < 0)
-                                goto clear;
-                }
-        }
-
-        LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
-                if (s->marked) {
-                        LIST_REMOVE(servers, m->dns_servers, s);
-                        dns_server_unref(s);
-                }
-
-        /* Whenever /etc/resolv.conf changes, start using the first
-         * DNS server of it. This is useful to deal with broken
-         * network managing implementations (like NetworkManager),
-         * that when connecting to a VPN place both the VPN DNS
-         * servers and the local ones in /etc/resolv.conf. Without
-         * resetting the DNS server to use back to the first entry we
-         * will continue to use the local one thus being unable to
-         * resolve VPN domains. */
-        manager_set_dns_server(m, m->dns_servers);
-
-        return 0;
-
-clear:
-        while (m->dns_servers) {
-                s = m->dns_servers;
-
-                LIST_REMOVE(servers, m->dns_servers, s);
-                dns_server_unref(s);
-        }
-
-        return r;
-}
-
-static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
-        _cleanup_free_ char *t  = NULL;
-        int r;
-
-        assert(s);
-        assert(f);
-        assert(count);
-
-        r = in_addr_to_string(s->family, &s->address, &t);
-        if (r < 0) {
-                log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
-                return;
-        }
-
-        if (*count == MAXNS)
-                fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
-
-        fprintf(f, "nameserver %s\n", t);
-        (*count) ++;
-}
-
-static void write_resolv_conf_search(
-                const char *domain, FILE *f,
-                unsigned *count,
-                unsigned *length) {
-
-        assert(domain);
-        assert(f);
-        assert(length);
-
-        if (*count >= MAXDNSRCH ||
-            *length + strlen(domain) > 256) {
-                if (*count == MAXDNSRCH)
-                        fputs(" # Too many search domains configured, remaining ones ignored.", f);
-                if (*length <= 256)
-                        fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
-
-                return;
-        }
-
-        fprintf(f, " %s", domain);
-
-        (*length) += strlen(domain);
-        (*count) ++;
-}
-
-static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
-        Iterator i;
-
-        fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
-              "# Third party programs must not access this file directly, but\n"
-              "# only through the symlink at /etc/resolv.conf. To manage\n"
-              "# resolv.conf(5) in a different way, replace the symlink by a\n"
-              "# static file or a different symlink.\n\n", f);
-
-        if (ordered_set_isempty(dns))
-                fputs("# No DNS servers known.\n", f);
-        else {
-                DnsServer *s;
-                unsigned count = 0;
-
-                ORDERED_SET_FOREACH(s, dns, i)
-                        write_resolv_conf_server(s, f, &count);
-        }
-
-        if (!ordered_set_isempty(domains)) {
-                unsigned length = 0, count = 0;
-                char *domain;
-
-                fputs("search", f);
-                ORDERED_SET_FOREACH(domain, domains, i)
-                        write_resolv_conf_search(domain, f, &count, &length);
-                fputs("\n", f);
-        }
-
-        return fflush_and_check(f);
-}
-
-int manager_write_resolv_conf(Manager *m) {
-        static const char path[] = "/run/systemd/resolve/resolv.conf";
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
-        DnsServer *s;
-        Iterator i;
-        Link *l;
-        int r;
-
-        assert(m);
-
-        /* Read the system /etc/resolv.conf first */
-        manager_read_resolv_conf(m);
-
-        /* Add the full list to a set, to filter out duplicates */
-        dns = ordered_set_new(&dns_server_hash_ops);
-        if (!dns)
-                return -ENOMEM;
-
-        domains = ordered_set_new(&dns_name_hash_ops);
-        if (!domains)
-                return -ENOMEM;
-
-        /* First add the system-wide servers */
-        LIST_FOREACH(servers, s, m->dns_servers) {
-                r = ordered_set_put(dns, s);
-                if (r == -EEXIST)
-                        continue;
-                if (r < 0)
-                        return r;
-        }
-
-        /* Then, add the per-link servers and domains */
-        HASHMAP_FOREACH(l, m->links, i) {
-                char **domain;
-
-                LIST_FOREACH(servers, s, l->dns_servers) {
-                        r = ordered_set_put(dns, s);
-                        if (r == -EEXIST)
-                                continue;
-                        if (r < 0)
-                                return r;
-                }
-
-                if (!l->unicast_scope)
-                        continue;
-
-                STRV_FOREACH(domain, l->unicast_scope->domains) {
-                        r = ordered_set_put(domains, *domain);
-                        if (r == -EEXIST)
-                                continue;
-                        if (r < 0)
-                                return r;
-                }
-        }
-
-        /* If we found nothing, add the fallback servers */
-        if (ordered_set_isempty(dns)) {
-                LIST_FOREACH(servers, s, m->fallback_dns_servers) {
-                        r = ordered_set_put(dns, s);
-                        if (r == -EEXIST)
-                                continue;
-                        if (r < 0)
-                                return r;
-                }
-        }
-
-        r = fopen_temporary_label(path, path, &f, &temp_path);
-        if (r < 0)
-                return r;
-
-        fchmod(fileno(f), 0644);
-
-        r = write_resolv_conf_contents(f, dns, domains);
-        if (r < 0)
-                goto fail;
-
-        if (rename(temp_path, path) < 0) {
-                r = -errno;
-                goto fail;
-        }
-
-        return 0;
-
-fail:
-        (void) unlink(path);
-        (void) unlink(temp_path);
-        return r;
-}
-
 int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
         union {
@@ -1046,7 +787,7 @@ static int write_loop(int fd, void *message, size_t length) {
 int manager_write(Manager *m, int fd, DnsPacket *p) {
         int r;
 
-        log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
+        log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
 
         r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
         if (r < 0)
@@ -1161,7 +902,7 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add
         assert(port > 0);
         assert(p);
 
-        log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
+        log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
 
         if (family == AF_INET)
                 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
@@ -1171,97 +912,6 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add
         return -EAFNOSUPPORT;
 }
 
-DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
-        DnsServer *s;
-
-        assert(m);
-        assert(in_addr);
-
-        LIST_FOREACH(servers, s, m->dns_servers)
-                if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
-                        return s;
-
-        LIST_FOREACH(servers, s, m->fallback_dns_servers)
-                if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
-                        return s;
-
-        return NULL;
-}
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
-        assert(m);
-
-        if (m->current_dns_server == s)
-                return s;
-
-        if (s) {
-                _cleanup_free_ char *ip = NULL;
-
-                in_addr_to_string(s->family, &s->address, &ip);
-                log_info("Switching to system DNS server %s.", strna(ip));
-        }
-
-        m->current_dns_server = s;
-
-        if (m->unicast_scope)
-                dns_cache_flush(&m->unicast_scope->cache);
-
-        return s;
-}
-
-DnsServer *manager_get_dns_server(Manager *m) {
-        Link *l;
-        assert(m);
-
-        /* Try to read updates resolv.conf */
-        manager_read_resolv_conf(m);
-
-        if (!m->current_dns_server)
-                manager_set_dns_server(m, m->dns_servers);
-
-        if (!m->current_dns_server) {
-                bool found = false;
-                Iterator i;
-
-                /* No DNS servers configured, let's see if there are
-                 * any on any links. If not, we use the fallback
-                 * servers */
-
-                HASHMAP_FOREACH(l, m->links, i)
-                        if (l->dns_servers) {
-                                found = true;
-                                break;
-                        }
-
-                if (!found)
-                        manager_set_dns_server(m, m->fallback_dns_servers);
-        }
-
-        return m->current_dns_server;
-}
-
-void manager_next_dns_server(Manager *m) {
-        assert(m);
-
-        /* If there's currently no DNS server set, then the next
-         * manager_get_dns_server() will find one */
-        if (!m->current_dns_server)
-                return;
-
-        /* Change to the next one */
-        if (m->current_dns_server->servers_next) {
-                manager_set_dns_server(m, m->current_dns_server->servers_next);
-                return;
-        }
-
-        /* If there was no next one, then start from the beginning of
-         * the list */
-        if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
-                manager_set_dns_server(m, m->fallback_dns_servers);
-        else
-                manager_set_dns_server(m, m->dns_servers);
-}
-
 uint32_t manager_find_mtu(Manager *m) {
         uint32_t mtu = 0;
         Link *l;
@@ -1396,11 +1046,25 @@ DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
         if (!l)
                 return NULL;
 
-        if (p->protocol == DNS_PROTOCOL_LLMNR) {
+        switch (p->protocol) {
+        case DNS_PROTOCOL_LLMNR:
                 if (p->family == AF_INET)
                         return l->llmnr_ipv4_scope;
                 else if (p->family == AF_INET6)
                         return l->llmnr_ipv6_scope;
+
+                break;
+
+        case DNS_PROTOCOL_MDNS:
+                if (p->family == AF_INET)
+                        return l->mdns_ipv4_scope;
+                else if (p->family == AF_INET6)
+                        return l->mdns_ipv6_scope;
+
+                break;
+
+        default:
+                break;
         }
 
         return NULL;
@@ -1415,49 +1079,163 @@ void manager_verify_all(Manager *m) {
                 dns_zone_verify_all(&s->zone);
 }
 
-void manager_flush_dns_servers(Manager *m, DnsServerType t) {
+int manager_is_own_hostname(Manager *m, const char *name) {
+        int r;
+
+        assert(m);
+        assert(name);
+
+        if (m->llmnr_hostname) {
+                r = dns_name_equal(name, m->llmnr_hostname);
+                if (r != 0)
+                        return r;
+        }
+
+        if (m->mdns_hostname)
+                return dns_name_equal(name, m->mdns_hostname);
+
+        return 0;
+}
+
+int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
         DnsServer *s;
+        Iterator i;
+        Link *l;
+        int r;
 
         assert(m);
+        assert(dns);
 
-        if (t == DNS_SERVER_SYSTEM)
-                while (m->dns_servers) {
-                        s = m->dns_servers;
+        r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
+        if (r < 0)
+                return r;
 
-                        LIST_REMOVE(servers, m->dns_servers, s);
-                        dns_server_unref(s);
-                }
+        /* First add the system-wide servers and domains */
+        LIST_FOREACH(servers, s, m->dns_servers) {
+                r = ordered_set_put(*dns, s);
+                if (r == -EEXIST)
+                        continue;
+                if (r < 0)
+                        return r;
+        }
 
-        if (t == DNS_SERVER_FALLBACK)
-                while (m->fallback_dns_servers) {
-                        s = m->fallback_dns_servers;
+        /* Then, add the per-link servers */
+        HASHMAP_FOREACH(l, m->links, i) {
+                LIST_FOREACH(servers, s, l->dns_servers) {
+                        r = ordered_set_put(*dns, s);
+                        if (r == -EEXIST)
+                                continue;
+                        if (r < 0)
+                                return r;
+                }
+        }
 
-                        LIST_REMOVE(servers, m->fallback_dns_servers, s);
-                        dns_server_unref(s);
+        /* If we found nothing, add the fallback servers */
+        if (ordered_set_isempty(*dns)) {
+                LIST_FOREACH(servers, s, m->fallback_dns_servers) {
+                        r = ordered_set_put(*dns, s);
+                        if (r == -EEXIST)
+                                continue;
+                        if (r < 0)
+                                return r;
                 }
+        }
+
+        return 0;
 }
 
-int manager_is_own_hostname(Manager *m, const char *name) {
+int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
+        DnsSearchDomain *d;
+        Iterator i;
+        Link *l;
         int r;
 
         assert(m);
-        assert(name);
+        assert(domains);
 
-        if (m->llmnr_hostname) {
-                r = dns_name_equal(name, m->llmnr_hostname);
-                if (r != 0)
+        r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(domains, d, m->search_domains) {
+                r = ordered_set_put(*domains, d->name);
+                if (r == -EEXIST)
+                        continue;
+                if (r < 0)
                         return r;
         }
 
-        if (m->mdns_hostname)
-                return dns_name_equal(name, m->mdns_hostname);
+        HASHMAP_FOREACH(l, m->links, i) {
+
+                LIST_FOREACH(domains, d, l->search_domains) {
+                        r = ordered_set_put(*domains, d->name);
+                        if (r == -EEXIST)
+                                continue;
+                        if (r < 0)
+                                return r;
+                }
+        }
 
         return 0;
 }
 
-static const char* const support_table[_SUPPORT_MAX] = {
-        [SUPPORT_NO] = "no",
-        [SUPPORT_YES] = "yes",
-        [SUPPORT_RESOLVE] = "resolve",
-};
-DEFINE_STRING_TABLE_LOOKUP(support, Support);
+DnssecMode manager_get_dnssec_mode(Manager *m) {
+        assert(m);
+
+        if (m->dnssec_mode != _DNSSEC_MODE_INVALID)
+                return m->dnssec_mode;
+
+        return DNSSEC_NO;
+}
+
+bool manager_dnssec_supported(Manager *m) {
+        DnsServer *server;
+        Iterator i;
+        Link *l;
+
+        assert(m);
+
+        if (manager_get_dnssec_mode(m) == DNSSEC_NO)
+                return false;
+
+        server = manager_get_dns_server(m);
+        if (server && !dns_server_dnssec_supported(server))
+                return false;
+
+        HASHMAP_FOREACH(l, m->links, i)
+                if (!link_dnssec_supported(l))
+                        return false;
+
+        return true;
+}
+
+void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) {
+
+        assert(verdict >= 0);
+        assert(verdict < _DNSSEC_VERDICT_MAX);
+
+        if (log_get_max_level() >= LOG_DEBUG) {
+                _cleanup_free_ char *s = NULL;
+
+                (void) dns_resource_key_to_string(key, &s);
+
+                log_debug("Found verdict for lookup %s: %s", s ? strstrip(s) : "n/a", dnssec_verdict_to_string(verdict));
+        }
+
+        m->n_dnssec_verdict[verdict]++;
+}
+
+bool manager_routable(Manager *m, int family) {
+        Iterator i;
+        Link *l;
+
+        assert(m);
+
+        /* Returns true if the host has at least one interface with a routable address of the specified type */
+
+        HASHMAP_FOREACH(l, m->links, i)
+                if (link_relevant(l, family, false))
+                        return true;
+
+        return false;
+}
index fe7fe99505817e0736c3c5085ece4fad8f65d3bf..e82a824f291140b8ec8001e391dd29ff294c4545 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include "sd-event.h"
-#include "sd-network.h"
 #include "sd-netlink.h"
-#include "list.h"
+#include "sd-network.h"
+
 #include "hashmap.h"
+#include "list.h"
+#include "ordered-set.h"
+#include "resolve-util.h"
 
 typedef struct Manager Manager;
-typedef enum Support Support;
-
-enum Support {
-        SUPPORT_NO,
-        SUPPORT_YES,
-        SUPPORT_RESOLVE,
-        _SUPPORT_MAX,
-        _SUPPORT_INVALID = -1
-};
 
 #include "resolved-dns-query.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
 #include "resolved-dns-stream.h"
+#include "resolved-dns-trust-anchor.h"
 #include "resolved-link.h"
 
+#define MANAGER_SEARCH_DOMAINS_MAX 32
+#define MANAGER_DNS_SERVERS_MAX 32
+
 struct Manager {
         sd_event *event;
 
-        Support llmnr_support;
+        ResolveSupport llmnr_support;
+        ResolveSupport mdns_support;
+        DnssecMode dnssec_mode;
 
         /* Network */
         Hashmap *links;
@@ -67,11 +67,20 @@ struct Manager {
         /* Unicast dns */
         LIST_HEAD(DnsServer, dns_servers);
         LIST_HEAD(DnsServer, fallback_dns_servers);
+        unsigned n_dns_servers; /* counts both main and fallback */
         DnsServer *current_dns_server;
 
-        bool read_resolv_conf;
+        LIST_HEAD(DnsSearchDomain, search_domains);
+        unsigned n_search_domains;
+        bool permit_domain_search;
+
+        bool need_builtin_fallbacks:1;
+
+        bool read_resolv_conf:1;
         usec_t resolv_conf_mtime;
 
+        DnsTrustAnchor trust_anchor;
+
         LIST_HEAD(DnsScope, dns_scopes);
         DnsScope *unicast_scope;
 
@@ -86,6 +95,13 @@ struct Manager {
         sd_event_source *llmnr_ipv4_tcp_event_source;
         sd_event_source *llmnr_ipv6_tcp_event_source;
 
+        /* mDNS */
+        int mdns_ipv4_fd;
+        int mdns_ipv6_fd;
+
+        sd_event_source *mdns_ipv4_event_source;
+        sd_event_source *mdns_ipv6_event_source;
+
         /* dbus */
         sd_bus *bus;
         sd_event_source *bus_retry_event_source;
@@ -104,6 +120,14 @@ struct Manager {
         sd_bus_slot *prepare_for_sleep_slot;
 
         sd_event_source *sigusr1_event_source;
+
+        unsigned n_transactions_total;
+        unsigned n_dnssec_verdict[_DNSSEC_VERDICT_MAX];
+
+        /* Data from /etc/hosts */
+        Set* etc_hosts_by_address;
+        Hashmap* etc_hosts_by_name;
+        usec_t etc_hosts_last, etc_hosts_mtime;
 };
 
 /* Manager */
@@ -112,13 +136,6 @@ int manager_new(Manager **ret);
 Manager* manager_free(Manager *m);
 
 int manager_start(Manager *m);
-int manager_read_resolv_conf(Manager *m);
-int manager_write_resolv_conf(Manager *m);
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
-DnsServer *manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr);
-DnsServer *manager_get_dns_server(Manager *m);
-void manager_next_dns_server(Manager *m);
 
 uint32_t manager_find_mtu(Manager *m);
 
@@ -137,13 +154,18 @@ DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
 
 void manager_verify_all(Manager *m);
 
-void manager_flush_dns_servers(Manager *m, DnsServerType t);
-
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 
 #define EXTRA_CMSG_SPACE 1024
 
 int manager_is_own_hostname(Manager *m, const char *name);
 
-const char* support_to_string(Support p) _const_;
-int support_from_string(const char *s) _pure_;
+int manager_compile_dns_servers(Manager *m, OrderedSet **servers);
+int manager_compile_search_domains(Manager *m, OrderedSet **domains);
+
+DnssecMode manager_get_dnssec_mode(Manager *m);
+bool manager_dnssec_supported(Manager *m);
+
+void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key);
+
+bool manager_routable(Manager *m, int family);
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
new file mode 100644 (file)
index 0000000..bc8b8b8
--- /dev/null
@@ -0,0 +1,287 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Daniel Mack
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <resolv.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "fd-util.h"
+#include "resolved-manager.h"
+#include "resolved-mdns.h"
+
+void manager_mdns_stop(Manager *m) {
+        assert(m);
+
+        m->mdns_ipv4_event_source = sd_event_source_unref(m->mdns_ipv4_event_source);
+        m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd);
+
+        m->mdns_ipv6_event_source = sd_event_source_unref(m->mdns_ipv6_event_source);
+        m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd);
+}
+
+int manager_mdns_start(Manager *m) {
+        int r;
+
+        assert(m);
+
+        if (m->mdns_support == RESOLVE_SUPPORT_NO)
+                return 0;
+
+        r = manager_mdns_ipv4_fd(m);
+        if (r == -EADDRINUSE)
+                goto eaddrinuse;
+        if (r < 0)
+                return r;
+
+        if (socket_ipv6_is_supported()) {
+                r = manager_mdns_ipv6_fd(m);
+                if (r == -EADDRINUSE)
+                        goto eaddrinuse;
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+
+eaddrinuse:
+        log_warning("There appears to be another mDNS responder running. Turning off mDNS support.");
+        m->mdns_support = RESOLVE_SUPPORT_NO;
+        manager_mdns_stop(m);
+
+        return 0;
+}
+
+static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+        Manager *m = userdata;
+        DnsScope *scope;
+        int r;
+
+        r = manager_recv(m, fd, DNS_PROTOCOL_MDNS, &p);
+        if (r <= 0)
+                return r;
+
+        scope = manager_find_scope(m, p);
+        if (!scope) {
+                log_warning("Got mDNS UDP packet on unknown scope. Ignoring.");
+                return 0;
+        }
+
+        if (dns_packet_validate_reply(p) > 0) {
+                DnsResourceRecord *rr;
+
+                log_debug("Got mDNS reply packet");
+
+                /*
+                 * mDNS is different from regular DNS and LLMNR with regard to handling responses.
+                 * While on other protocols, we can ignore every answer that doesn't match a question
+                 * we broadcast earlier, RFC6762, section 18.1 recommends looking at and caching all
+                 * incoming information, regardless of the DNS packet ID.
+                 *
+                 * Hence, extract the packet here, and try to find a transaction for answer the we got
+                 * and complete it. Also store the new information in scope's cache.
+                 */
+                r = dns_packet_extract(p);
+                if (r < 0) {
+                        log_debug("mDNS packet extraction failed.");
+                        return 0;
+                }
+
+                dns_scope_check_conflicts(scope, p);
+
+                DNS_ANSWER_FOREACH(rr, p->answer) {
+                        const char *name = DNS_RESOURCE_KEY_NAME(rr->key);
+                        DnsTransaction *t;
+
+                        /* If the received reply packet contains ANY record that is not .local or .in-addr.arpa,
+                         * we assume someone's playing tricks on us and discard the packet completely. */
+                        if (!(dns_name_endswith(name, "in-addr.arpa") > 0 ||
+                              dns_name_endswith(name, "local") > 0))
+                                return 0;
+
+                        t = dns_scope_find_transaction(scope, rr->key, false);
+                        if (t)
+                                dns_transaction_process_reply(t, p);
+                }
+
+                dns_cache_put(&scope->cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
+
+        } else if (dns_packet_validate_query(p) > 0)  {
+                log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
+
+                dns_scope_process_query(scope, NULL, p);
+        } else
+                log_debug("Invalid mDNS UDP packet.");
+
+        return 0;
+}
+
+int manager_mdns_ipv4_fd(Manager *m) {
+        union sockaddr_union sa = {
+                .in.sin_family = AF_INET,
+                .in.sin_port = htobe16(MDNS_PORT),
+        };
+        static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
+        int r;
+
+        assert(m);
+
+        if (m->mdns_ipv4_fd >= 0)
+                return m->mdns_ipv4_fd;
+
+        m->mdns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (m->mdns_ipv4_fd < 0)
+                return -errno;
+
+        r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
+        if (r < 0) {
+                r = -errno;
+                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;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        /* Disable Don't-Fragment bit in the IP header */
+        r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, m->mdns_ipv4_fd, EPOLLIN, on_mdns_packet, m);
+        if (r < 0)
+                goto fail;
+
+        return m->mdns_ipv4_fd;
+
+fail:
+        m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd);
+        return r;
+}
+
+int manager_mdns_ipv6_fd(Manager *m) {
+        union sockaddr_union sa = {
+                .in6.sin6_family = AF_INET6,
+                .in6.sin6_port = htobe16(MDNS_PORT),
+        };
+        static const int one = 1, ttl = 255;
+        int r;
+
+        assert(m);
+
+        if (m->mdns_ipv6_fd >= 0)
+                return m->mdns_ipv6_fd;
+
+        m->mdns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (m->mdns_ipv6_fd < 0)
+                return -errno;
+
+        r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
+        r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
+        if (r < 0) {
+                r = -errno;
+                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;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6));
+        if (r < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m);
+        if (r < 0)
+                goto fail;
+
+        return m->mdns_ipv6_fd;
+
+fail:
+        m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd);
+        return r;
+}
diff --git a/src/resolve/resolved-mdns.h b/src/resolve/resolved-mdns.h
new file mode 100644 (file)
index 0000000..5d27464
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Daniel Mack
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "resolved-manager.h"
+
+#define MDNS_PORT 5353
+
+int manager_mdns_ipv4_fd(Manager *m);
+int manager_mdns_ipv6_fd(Manager *m);
+
+void manager_mdns_stop(Manager *m);
+int manager_mdns_start(Manager *m);
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
new file mode 100644 (file)
index 0000000..065427b
--- /dev/null
@@ -0,0 +1,267 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <resolv.h>
+
+#include "alloc-util.h"
+#include "dns-domain.h"
+#include "fd-util.h"
+#include "fileio-label.h"
+#include "fileio.h"
+#include "ordered-set.h"
+#include "resolved-conf.h"
+#include "resolved-resolv-conf.h"
+#include "string-util.h"
+#include "strv.h"
+
+int manager_read_resolv_conf(Manager *m) {
+        _cleanup_fclose_ FILE *f = NULL;
+        struct stat st, own;
+        char line[LINE_MAX];
+        usec_t t;
+        int r;
+
+        assert(m);
+
+        /* Reads the system /etc/resolv.conf, if it exists and is not
+         * symlinked to our own resolv.conf instance */
+
+        if (!m->read_resolv_conf)
+                return 0;
+
+        r = stat("/etc/resolv.conf", &st);
+        if (r < 0) {
+                if (errno == ENOENT)
+                        return 0;
+
+                r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
+                goto clear;
+        }
+
+        /* Have we already seen the file? */
+        t = timespec_load(&st.st_mtim);
+        if (t == m->resolv_conf_mtime)
+                return 0;
+
+        /* Is it symlinked to our own file? */
+        if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
+            st.st_dev == own.st_dev &&
+            st.st_ino == own.st_ino)
+                return 0;
+
+        f = fopen("/etc/resolv.conf", "re");
+        if (!f) {
+                if (errno == ENOENT)
+                        return 0;
+
+                r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
+                goto clear;
+        }
+
+        if (fstat(fileno(f), &st) < 0) {
+                r = log_error_errno(errno, "Failed to stat open file: %m");
+                goto clear;
+        }
+
+        dns_server_mark_all(m->dns_servers);
+        dns_search_domain_mark_all(m->search_domains);
+
+        FOREACH_LINE(line, f, r = -errno; goto clear) {
+                const char *a;
+                char *l;
+
+                l = strstrip(line);
+                if (*l == '#' || *l == ';')
+                        continue;
+
+                a = first_word(l, "nameserver");
+                if (a) {
+                        r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
+
+                        continue;
+                }
+
+                a = first_word(l, "domain");
+                if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */
+                        a = first_word(l, "search");
+                if (a) {
+                        r = manager_parse_search_domains_and_warn(m, a);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a);
+                }
+        }
+
+        m->resolv_conf_mtime = t;
+
+        /* Flush out all servers and search domains that are still
+         * marked. Those are then ones that didn't appear in the new
+         * /etc/resolv.conf */
+        dns_server_unlink_marked(m->dns_servers);
+        dns_search_domain_unlink_marked(m->search_domains);
+
+        /* Whenever /etc/resolv.conf changes, start using the first
+         * DNS server of it. This is useful to deal with broken
+         * network managing implementations (like NetworkManager),
+         * that when connecting to a VPN place both the VPN DNS
+         * servers and the local ones in /etc/resolv.conf. Without
+         * resetting the DNS server to use back to the first entry we
+         * will continue to use the local one thus being unable to
+         * resolve VPN domains. */
+        manager_set_dns_server(m, m->dns_servers);
+
+        /* Unconditionally flush the cache when /etc/resolv.conf is
+         * modified, even if the data it contained was completely
+         * identical to the previous version we used. We do this
+         * because altering /etc/resolv.conf is typically done when
+         * the network configuration changes, and that should be
+         * enough to flush the global unicast DNS cache. */
+        if (m->unicast_scope)
+                dns_cache_flush(&m->unicast_scope->cache);
+
+        return 0;
+
+clear:
+        dns_server_unlink_all(m->dns_servers);
+        dns_search_domain_unlink_all(m->search_domains);
+        return r;
+}
+
+static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
+        assert(s);
+        assert(f);
+        assert(count);
+
+        (void) dns_server_string(s);
+
+        if (!s->server_string) {
+                log_warning("Our of memory, or invalid DNS address. Ignoring server.");
+                return;
+        }
+
+        if (*count == MAXNS)
+                fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
+        (*count) ++;
+
+        fprintf(f, "nameserver %s\n", s->server_string);
+}
+
+static void write_resolv_conf_search(
+                const char *domain,
+                FILE *f,
+                unsigned *count,
+                unsigned *length) {
+
+        assert(domain);
+        assert(f);
+        assert(length);
+
+        if (*count >= MAXDNSRCH ||
+            *length + strlen(domain) > 256) {
+                if (*count == MAXDNSRCH)
+                        fputs(" # Too many search domains configured, remaining ones ignored.", f);
+                if (*length <= 256)
+                        fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
+
+                return;
+        }
+
+        (*length) += strlen(domain);
+        (*count) ++;
+
+        fputc(' ', f);
+        fputs(domain, f);
+}
+
+static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
+        Iterator i;
+
+        fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
+              "# Third party programs must not access this file directly, but\n"
+              "# only through the symlink at /etc/resolv.conf. To manage\n"
+              "# resolv.conf(5) in a different way, replace the symlink by a\n"
+              "# static file or a different symlink.\n\n", f);
+
+        if (ordered_set_isempty(dns))
+                fputs("# No DNS servers known.\n", f);
+        else {
+                unsigned count = 0;
+                DnsServer *s;
+
+                ORDERED_SET_FOREACH(s, dns, i)
+                        write_resolv_conf_server(s, f, &count);
+        }
+
+        if (!ordered_set_isempty(domains)) {
+                unsigned length = 0, count = 0;
+                char *domain;
+
+                fputs("search", f);
+                ORDERED_SET_FOREACH(domain, domains, i)
+                        write_resolv_conf_search(domain, f, &count, &length);
+                fputs("\n", f);
+        }
+
+        return fflush_and_check(f);
+}
+
+int manager_write_resolv_conf(Manager *m) {
+
+        _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
+        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        int r;
+
+        assert(m);
+
+        /* Read the system /etc/resolv.conf first */
+        manager_read_resolv_conf(m);
+
+        /* Add the full list to a set, to filter out duplicates */
+        r = manager_compile_dns_servers(m, &dns);
+        if (r < 0)
+                return r;
+
+        r = manager_compile_search_domains(m, &domains);
+        if (r < 0)
+                return r;
+
+        r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path);
+        if (r < 0)
+                return r;
+
+        fchmod(fileno(f), 0644);
+
+        r = write_resolv_conf_contents(f, dns, domains);
+        if (r < 0)
+                goto fail;
+
+        if (rename(temp_path, PRIVATE_RESOLV_CONF) < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        return 0;
+
+fail:
+        (void) unlink(PRIVATE_RESOLV_CONF);
+        (void) unlink(temp_path);
+        return r;
+}
diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h
new file mode 100644 (file)
index 0000000..75fa080
--- /dev/null
@@ -0,0 +1,27 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "resolved-manager.h"
+
+#define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
+
+int manager_read_resolv_conf(Manager *m);
+int manager_write_resolv_conf(Manager *m);
index 7ba0546f4a8b698ba80d87079f32d33dd79be682..c7e2ab14d64566ade068bd129f26f6c411961e7b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -26,6 +24,7 @@
 #include "mkdir.h"
 #include "resolved-conf.h"
 #include "resolved-manager.h"
+#include "resolved-resolv-conf.h"
 #include "selinux-util.h"
 #include "signal-util.h"
 #include "user-util.h"
@@ -80,10 +79,6 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = manager_parse_config_file(m);
-        if (r < 0)
-                log_warning_errno(r, "Failed to parse configuration file: %m");
-
         r = manager_start(m);
         if (r < 0) {
                 log_error_errno(r, "Failed to start manager: %m");
@@ -94,7 +89,7 @@ int main(int argc, char *argv[]) {
          * symlink */
         r = manager_write_resolv_conf(m);
         if (r < 0)
-                log_warning_errno(r, "Could not create resolv.conf: %m");
+                log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m");
 
         sd_notify(false,
                   "READY=1\n"
index 3eb19e42b742e60cadee813a98ce3be2fbe697ce..efc9c6733a3cfb23efe4e53f71f3294ecf21979c 100644 (file)
@@ -14,4 +14,6 @@
 [Resolve]
 #DNS=
 #FallbackDNS=@DNS_SERVERS@
+#Domains=
 #LLMNR=yes
+#DNSSEC=no
diff --git a/src/resolve/test-dnssec-complex.c b/src/resolve/test-dnssec-complex.c
new file mode 100644 (file)
index 0000000..58c089e
--- /dev/null
@@ -0,0 +1,236 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 <netinet/ip.h>
+
+#include "sd-bus.h"
+
+#include "af-list.h"
+#include "alloc-util.h"
+#include "bus-common-errors.h"
+#include "dns-type.h"
+#include "random-util.h"
+#include "string-util.h"
+#include "time-util.h"
+
+#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
+
+static void prefix_random(const char *name, char **ret) {
+        uint64_t i, u;
+        char *m = NULL;
+
+        u = 1 + (random_u64() & 3);
+
+        for (i = 0; i < u; i++) {
+                _cleanup_free_ char *b = NULL;
+                char *x;
+
+                assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64()));
+                x = strjoin(b, ".", name, NULL);
+                assert_se(x);
+
+                free(m);
+                m = x;
+        }
+
+        *ret = m;
+ }
+
+static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *m = NULL;
+        int r;
+
+        /* If the name starts with a dot, we prefix one to three random labels */
+        if (startswith(name, ".")) {
+                prefix_random(name + 1, &m);
+                name = m;
+        }
+
+        assert_se(sd_bus_message_new_method_call(
+                                  bus,
+                                  &req,
+                                  "org.freedesktop.resolve1",
+                                  "/org/freedesktop/resolve1",
+                                  "org.freedesktop.resolve1.Manager",
+                                  "ResolveRecord") >= 0);
+
+        assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+
+        if (r < 0) {
+                assert_se(result);
+                assert_se(sd_bus_error_has_name(&error, result));
+                log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name);
+        } else {
+                assert_se(!result);
+                log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type));
+        }
+}
+
+static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *m = NULL;
+        const char *af;
+        int r;
+
+        af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family);
+
+        /* If the name starts with a dot, we prefix one to three random labels */
+        if (startswith(name, ".")) {
+                prefix_random(name + 1, &m);
+                name = m;
+        }
+
+        assert_se(sd_bus_message_new_method_call(
+                                  bus,
+                                  &req,
+                                  "org.freedesktop.resolve1",
+                                  "/org/freedesktop/resolve1",
+                                  "org.freedesktop.resolve1.Manager",
+                                  "ResolveHostname") >= 0);
+
+        assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0);
+
+        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
+
+        if (r < 0) {
+                assert_se(result);
+                assert_se(sd_bus_error_has_name(&error, result));
+                log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name);
+        } else {
+                assert_se(!result);
+                log_info("[OK] %s/%s succeeded.", name, af);
+        }
+
+}
+
+int main(int argc, char* argv[]) {
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+
+        /* Note that this is a manual test as it requires:
+         *
+         *    Full network access
+         *    A DNSSEC capable DNS server
+         *    That zones contacted are still set up as they were when I wrote this.
+         */
+
+        assert_se(sd_bus_open_system(&bus) >= 0);
+
+        /* Normally signed */
+        test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL);
+
+        test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL);
+
+        /* Normally signed, NODATA */
+        test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+        test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+
+        /* Invalid signature */
+        test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
+        test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED);
+
+        /* Invalid signature, RSA, wildcard */
+        test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
+        test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
+
+        /* Invalid signature, ECDSA, wildcard */
+        test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
+        test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
+
+        /* NXDOMAIN in NSEC domain */
+        test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
+
+        /* wildcard, NSEC zone */
+        test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL);
+
+        /* wildcard, NSEC zone, NODATA */
+        test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+
+        /* wildcard, NSEC3 zone */
+        test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL);
+
+        /* wildcard, NSEC3 zone, NODATA */
+        test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+
+        /* wildcard, NSEC zone, CNAME */
+        test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL);
+        test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL);
+
+        /* wildcard, NSEC zone, NODATA, CNAME */
+        test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+
+        /* wildcard, NSEC3 zone, CNAME */
+        test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL);
+        test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL);
+        test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL);
+
+        /* wildcard, NSEC3 zone, NODATA, CNAME */
+        test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
+
+        /* NODATA due to empty non-terminal in NSEC domain */
+        test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR);
+        test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR);
+        test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR);
+        test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR);
+
+        /* NXDOMAIN in NSEC root zone: */
+        test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
+
+        /* NXDOMAIN in NSEC3 .com zone: */
+        test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
+
+        /* Unsigned A */
+        test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL);
+        test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL);
+        test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL);
+        test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
+        test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
+
+#ifdef 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);
+        test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL);
+#endif
+
+        /* DNAME, pointing to NXDOMAIN */
+        test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
+        test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
+        test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
+
+        return 0;
+}
diff --git a/src/resolve/test-dnssec.c b/src/resolve/test-dnssec.c
new file mode 100644 (file)
index 0000000..a093d86
--- /dev/null
@@ -0,0 +1,336 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "alloc-util.h"
+#include "resolved-dns-dnssec.h"
+#include "resolved-dns-rr.h"
+#include "string-util.h"
+#include "hexdecoct.h"
+
+static void test_dnssec_verify_rrset2(void) {
+
+        static const uint8_t signature_blob[] = {
+                0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
+                0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
+                0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
+                0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
+                0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
+                0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
+                0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
+                0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
+        };
+
+        static const uint8_t dnskey_blob[] = {
+                0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
+                0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
+                0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
+                0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
+                0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
+                0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
+                0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
+                0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
+                0x74, 0x62, 0xfe, 0xd7,
+        };
+
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        DnssecResult result;
+
+        nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
+        assert_se(nsec);
+
+        nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
+        assert_se(nsec->nsec.next_domain_name);
+
+        nsec->nsec.types = bitmap_new();
+        assert_se(nsec->nsec.types);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_A) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NS) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_SOA) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_MX) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_TXT) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_RRSIG) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NSEC) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_DNSKEY) >= 0);
+        assert_se(bitmap_set(nsec->nsec.types, 65534) >= 0);
+
+        log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec)));
+
+        rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
+        assert_se(rrsig);
+
+        rrsig->rrsig.type_covered = DNS_TYPE_NSEC;
+        rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        rrsig->rrsig.labels = 2;
+        rrsig->rrsig.original_ttl = 300;
+        rrsig->rrsig.expiration = 0x5689002f;
+        rrsig->rrsig.inception = 0x56617230;
+        rrsig->rrsig.key_tag = 30390;
+        rrsig->rrsig.signer = strdup("Nasa.Gov.");
+        assert_se(rrsig->rrsig.signer);
+        rrsig->rrsig.signature_size = sizeof(signature_blob);
+        rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
+        assert_se(rrsig->rrsig.signature);
+
+        log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
+
+        dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
+        assert_se(dnskey);
+
+        dnskey->dnskey.flags = 256;
+        dnskey->dnskey.protocol = 3;
+        dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        dnskey->dnskey.key_size = sizeof(dnskey_blob);
+        dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
+        assert_se(dnskey->dnskey.key);
+
+        log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
+        log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
+
+        assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
+        assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
+
+        answer = dns_answer_new(1);
+        assert_se(answer);
+        assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+
+        /* Validate the RR as it if was 2015-12-11 today */
+        assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0);
+        assert_se(result == DNSSEC_VALIDATED);
+}
+
+static void test_dnssec_verify_rrset(void) {
+
+        static const uint8_t signature_blob[] = {
+                0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
+                0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
+                0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
+                0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
+                0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
+                0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
+                0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
+                0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
+        };
+
+        static const uint8_t dnskey_blob[] = {
+                0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
+                0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
+                0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
+                0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
+                0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
+                0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
+                0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
+                0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
+                0x4f, 0x00, 0x51, 0x3b,
+        };
+
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL;
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+        DnssecResult result;
+
+        a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
+        assert_se(a);
+
+        a->a.in_addr.s_addr = inet_addr("52.0.14.116");
+
+        log_info("A: %s", strna(dns_resource_record_to_string(a)));
+
+        rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
+        assert_se(rrsig);
+
+        rrsig->rrsig.type_covered = DNS_TYPE_A;
+        rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        rrsig->rrsig.labels = 2;
+        rrsig->rrsig.original_ttl = 600;
+        rrsig->rrsig.expiration = 0x5683135c;
+        rrsig->rrsig.inception = 0x565b7da8;
+        rrsig->rrsig.key_tag = 63876;
+        rrsig->rrsig.signer = strdup("Nasa.Gov.");
+        assert_se(rrsig->rrsig.signer);
+        rrsig->rrsig.signature_size = sizeof(signature_blob);
+        rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
+        assert_se(rrsig->rrsig.signature);
+
+        log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
+
+        dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
+        assert_se(dnskey);
+
+        dnskey->dnskey.flags = 256;
+        dnskey->dnskey.protocol = 3;
+        dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        dnskey->dnskey.key_size = sizeof(dnskey_blob);
+        dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
+        assert_se(dnskey->dnskey.key);
+
+        log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
+        log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
+
+        assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
+        assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
+
+        answer = dns_answer_new(1);
+        assert_se(answer);
+        assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+
+        /* Validate the RR as it if was 2015-12-2 today */
+        assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0);
+        assert_se(result == DNSSEC_VALIDATED);
+}
+
+static void test_dnssec_verify_dns_key(void) {
+
+        static const uint8_t ds1_fprint[] = {
+                0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
+                0x80, 0x67, 0x14, 0x01,
+        };
+        static const uint8_t ds2_fprint[] = {
+                0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
+                0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
+        };
+        static const uint8_t dnskey_blob[] = {
+                0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
+                0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
+                0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
+                0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
+                0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
+                0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
+                0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
+                0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
+                0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
+                0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
+                0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
+                0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
+                0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
+                0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
+                0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
+                0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
+                0xe7, 0xea, 0x77, 0x03,
+        };
+
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
+
+        /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
+        ds1 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "nasa.gov");
+        assert_se(ds1);
+
+        ds1->ds.key_tag = 47857;
+        ds1->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        ds1->ds.digest_type = DNSSEC_DIGEST_SHA1;
+        ds1->ds.digest_size = sizeof(ds1_fprint);
+        ds1->ds.digest = memdup(ds1_fprint, ds1->ds.digest_size);
+        assert_se(ds1->ds.digest);
+
+        log_info("DS1: %s", strna(dns_resource_record_to_string(ds1)));
+
+        ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
+        assert_se(ds2);
+
+        ds2->ds.key_tag = 47857;
+        ds2->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        ds2->ds.digest_type = DNSSEC_DIGEST_SHA256;
+        ds2->ds.digest_size = sizeof(ds2_fprint);
+        ds2->ds.digest = memdup(ds2_fprint, ds2->ds.digest_size);
+        assert_se(ds2->ds.digest);
+
+        log_info("DS2: %s", strna(dns_resource_record_to_string(ds2)));
+
+        dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
+        assert_se(dnskey);
+
+        dnskey->dnskey.flags = 257;
+        dnskey->dnskey.protocol = 3;
+        dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
+        dnskey->dnskey.key_size = sizeof(dnskey_blob);
+        dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
+        assert_se(dnskey->dnskey.key);
+
+        log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
+        log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
+
+        assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0);
+        assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
+}
+
+static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
+        char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
+
+        assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
+        if (r < 0)
+                return;
+
+        assert_se(streq(canonicalized, canonical));
+}
+
+static void test_dnssec_canonicalize(void) {
+        test_dnssec_canonicalize_one("", ".", 1);
+        test_dnssec_canonicalize_one(".", ".", 1);
+        test_dnssec_canonicalize_one("foo", "foo.", 4);
+        test_dnssec_canonicalize_one("foo.", "foo.", 4);
+        test_dnssec_canonicalize_one("FOO.", "foo.", 4);
+        test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
+        test_dnssec_canonicalize_one("FOO..bar.", NULL, -EINVAL);
+}
+
+static void test_dnssec_nsec3_hash(void) {
+        static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE };
+        static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 };
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+        uint8_t h[DNSSEC_HASH_SIZE_MAX];
+        _cleanup_free_ char *b = NULL;
+        int k;
+
+        /* The NSEC3 RR for eurid.eu on 2015-12-14. */
+        rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC3, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu.");
+        assert_se(rr);
+
+        rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1;
+        rr->nsec3.flags = 1;
+        rr->nsec3.iterations = 1;
+        rr->nsec3.salt = memdup(salt, sizeof(salt));
+        assert_se(rr->nsec3.salt);
+        rr->nsec3.salt_size = sizeof(salt);
+        rr->nsec3.next_hashed_name = memdup(next_hashed_name, sizeof(next_hashed_name));
+        assert_se(rr->nsec3.next_hashed_name);
+        rr->nsec3.next_hashed_name_size = sizeof(next_hashed_name);
+
+        log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr)));
+
+        k = dnssec_nsec3_hash(rr, "eurid.eu", &h);
+        assert_se(k >= 0);
+
+        b = base32hexmem(h, k, false);
+        assert_se(b);
+        assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
+}
+
+int main(int argc, char*argv[]) {
+
+        test_dnssec_canonicalize();
+        test_dnssec_verify_dns_key();
+        test_dnssec_verify_rrset();
+        test_dnssec_verify_rrset2();
+        test_dnssec_nsec3_hash();
+
+        return 0;
+}
diff --git a/src/resolve/test-resolve-tables.c b/src/resolve/test-resolve-tables.c
new file mode 100644 (file)
index 0000000..63660af
--- /dev/null
@@ -0,0 +1,27 @@
+/***
+  This file is part of systemd
+
+  Copyright 2013 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 "dns-type.h"
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+        test_table_sparse(dns_type, DNS_TYPE);
+
+        return EXIT_SUCCESS;
+}
index 5c45a3ae6c519d17f2edb290c0e2faaea6ce16c3..0acdf229ed9ac59b673b4fd1b2b93b85d2d34de0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e1accc467ba01a26ad4b1456bcdbf97673e6a160..e7f4c21f735378e65e5dfc80e8afbd20abc60808 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,7 +28,6 @@
 #include "bus-util.h"
 #include "calendarspec.h"
 #include "env-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "formats-util.h"
 #include "parse-util.h"
@@ -423,17 +420,9 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
                 return r;
 
         STRV_FOREACH(i, properties) {
-                r = sd_bus_message_open_container(m, 'r', "sv");
-                if (r < 0)
-                        return r;
-
                 r = bus_append_unit_property_assignment(m, *i);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
         }
 
         return 0;
@@ -741,8 +730,8 @@ static int start_transient_service(
                 sd_bus *bus,
                 char **argv) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_free_ char *service = NULL, *pty_path = NULL;
         _cleanup_close_ int master = -1;
@@ -766,7 +755,7 @@ static int start_transient_service(
                                 return log_error_errno(errno, "Failed to unlock tty: %m");
 
                 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
-                        _cleanup_bus_unref_ sd_bus *system_bus = NULL;
+                        _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL;
                         const char *s;
 
                         r = sd_bus_default_system(&system_bus);
@@ -876,7 +865,7 @@ static int start_transient_service(
 
         if (master >= 0) {
                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
-                _cleanup_event_unref_ sd_event *event = NULL;
+                _cleanup_(sd_event_unrefp) sd_event *event = NULL;
                 char last_char = 0;
 
                 r = sd_event_default(&event);
@@ -916,8 +905,8 @@ static int start_transient_scope(
                 sd_bus *bus,
                 char **argv) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _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;
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
         _cleanup_free_ char *scope = NULL;
@@ -1060,8 +1049,8 @@ static int start_transient_timer(
                 sd_bus *bus,
                 char **argv) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _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;
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_free_ char *timer = NULL, *service = NULL;
         const char *object = NULL;
@@ -1208,7 +1197,7 @@ static int start_transient_timer(
 }
 
 int main(int argc, char* argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *description = NULL, *command = NULL;
         int r;
 
index 35f2e1b67dd390adaea047eebae21478d64c8a6a..2aa951fce98d10c03acee49255b3b4987ba0e95c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -71,6 +69,7 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
 int calc_acl_mask_if_needed(acl_t *acl_p) {
         acl_entry_t i;
         int r;
+        bool need = false;
 
         assert(acl_p);
 
@@ -85,17 +84,16 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
                 if (tag == ACL_MASK)
                         return 0;
 
-                if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
-                        if (acl_calc_mask(acl_p) < 0)
-                                return -errno;
-
-                        return 1;
-                }
+                if (IN_SET(tag, ACL_USER, ACL_GROUP))
+                        need = true;
         }
         if (r < 0)
                 return -errno;
 
-        return 0;
+        if (need && acl_calc_mask(acl_p) < 0)
+                return -errno;
+
+        return need;
 }
 
 int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
@@ -398,3 +396,34 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
         old = NULL;
         return 0;
 }
+
+int add_acls_for_user(int fd, uid_t uid) {
+        _cleanup_(acl_freep) acl_t acl = NULL;
+        acl_entry_t entry;
+        acl_permset_t permset;
+        int r;
+
+        acl = acl_get_fd(fd);
+        if (!acl)
+                return -errno;
+
+        r = acl_find_uid(acl, uid, &entry);
+        if (r <= 0) {
+                if (acl_create_entry(&acl, &entry) < 0 ||
+                    acl_set_tag_type(entry, ACL_USER) < 0 ||
+                    acl_set_qualifier(entry, &uid) < 0)
+                        return -errno;
+        }
+
+        /* We do not recalculate the mask unconditionally here,
+         * so that the fchmod() mask above stays intact. */
+        if (acl_get_permset(entry, &permset) < 0 ||
+            acl_add_perm(permset, ACL_READ) < 0)
+                return -errno;
+
+        r = calc_acl_mask_if_needed(&acl);
+        if (r < 0)
+                return r;
+
+        return acl_set_fd(fd, acl);
+}
index cf612e87225038221021a55e260bc1e12797b8e9..396e9e067ee6c997ff1b0cb9328a8b5b0e19439a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,9 +21,9 @@
 
 #ifdef HAVE_ACL
 
+#include <acl/libacl.h>
 #include <stdbool.h>
 #include <sys/acl.h>
-#include <acl/libacl.h>
 
 #include "macro.h"
 
@@ -35,6 +33,7 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path);
 int acl_search_groups(const char* path, char ***ret_groups);
 int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask);
 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
+int add_acls_for_user(int fd, uid_t uid);
 
 /* acl_free takes multiple argument types.
  * Multiple cleanup functions are necessary. */
index 30e03c0652f4f1692ea10e283356885683e453fc..3cb9e781fd8631d61ac4e049f8614c7bc472a83d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <fcntl.h>
+#include <stddef.h>
 #include <stdint.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -30,7 +29,6 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "time-util.h"
-#include "util.h"
 
 struct acpi_table_header {
         char signature[4];
index fc4fe6f10ffef145bb26a31cf861b11f1d28fe0f..fc28175d0a67eb5bbe7aaa738307df8d098085c5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index f6ac43adfe7756536b6da19532a8b473adaaff21..edd695fd238e4750154aca6a6fe7174e06e8ab1f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stddef.h>
+
 #include "alloc-util.h"
 #include "apparmor-util.h"
 #include "fileio.h"
 #include "parse-util.h"
-#include "util.h"
 
 bool mac_apparmor_use(void) {
         static int cached_use = -1;
index a3d1b3b066f1e25662d294b5e9909c2b52bd11bc..524f7401529f0bc1b9e1720515ef8849227f5959 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 73937bd5a7f8d8e131854039e7e342f9c341be27..a9ecfc1cd632245210af1eef14d5e26898dbf5cc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -22,6 +20,7 @@
 #include <sys/utsname.h>
 
 #include "architecture.h"
+#include "macro.h"
 #include "string-table.h"
 #include "string-util.h"
 
index 61d067cad7bd6c8d1c4e86e2f8d5e7750348393b..26679e28c6bba3b146f2ab9015402ea9dda8ac3c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,6 +21,7 @@
 
 #include <endian.h>
 
+#include "macro.h"
 #include "util.h"
 
 /* A cleaned up architecture definition. We don't want to get lost in
index fbe2b6fecb95e7d6911641069b05f9d076cb0cae..6805873f9e032dc6cbfa2bbd83c42e43e3b13690 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
 #include <poll.h>
+#include <signal.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/inotify.h>
 #include <sys/signalfd.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
 #include <sys/un.h>
 #include <termios.h>
 #include <unistd.h>
@@ -38,6 +45,8 @@
 #include "fileio.h"
 #include "formats-util.h"
 #include "io-util.h"
+#include "log.h"
+#include "macro.h"
 #include "missing.h"
 #include "mkdir.h"
 #include "random-util.h"
@@ -46,7 +55,9 @@
 #include "string-util.h"
 #include "strv.h"
 #include "terminal-util.h"
+#include "time-util.h"
 #include "umask-util.h"
+#include "utf8.h"
 #include "util.h"
 
 #define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2)
@@ -59,7 +70,7 @@ static int lookup_key(const char *keyname, key_serial_t *ret) {
 
         serial = request_key("user", keyname, NULL, 0);
         if (serial == -1)
-                return -errno;
+                return negative_errno();
 
         *ret = serial;
         return 0;
@@ -201,8 +212,8 @@ int ask_password_tty(
                 char **ret) {
 
         struct termios old_termios, new_termios;
-        char passphrase[LINE_MAX], *x;
-        size_t p = 0;
+        char passphrase[LINE_MAX + 1] = {}, *x;
+        size_t p = 0, codepoint = 0;
         int r;
         _cleanup_close_ int ttyfd = -1, notify = -1;
         struct pollfd pollfd[2];
@@ -366,8 +377,13 @@ int ask_password_tty(
 
                         passphrase[p++] = c;
 
-                        if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0)
-                                loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false);
+                        if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) {
+                                n = utf8_encoded_valid_unichar(passphrase + codepoint);
+                                if (n >= 0) {
+                                        codepoint = p;
+                                        loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false);
+                                }
+                        }
 
                         dirty = true;
                 }
index 913cad9f8ae6f88b10bb381eaf337a5610a7bf2d..9d7f65130c9c54e79ed1e27f7f8d4269daf94a90 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index e605490c3211c58c8ccafab1f09aff0317d9e6c6..59a34a9d1123220e55dab65bf3205824226faa55 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <sys/stat.h>
+#include <syslog.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
index 39a496090f297341ddb02a73a503994821cd2772..49599f0a6079a23c0bdae70dc778752f6ad9521e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 879aca93744de074b709727ae3906735eba329f2..7e0152761ccb0a1b20e221ea31aa06bd7da21751 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,6 +21,8 @@
 #include "acpi-fpdt.h"
 #include "boot-timestamps.h"
 #include "efivars.h"
+#include "macro.h"
+#include "time-util.h"
 
 int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
         usec_t x = 0, y = 0, a;
index a3d2405b5630e86be4509c95d765a69c8ac0c388..6f691026beea757b79ad55ae4f6f55aa205e913e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 73ceeba18f986289698cecc7cb1f83e8183950a1..38557f0b8df0ae26e4ac04a05c4dd3e89932161c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
+#include <unistd.h>
 
+#include "sd-bus-protocol.h"
 #include "sd-bus.h"
 #include "sd-daemon.h"
 #include "sd-event.h"
+#include "sd-id128.h"
 
 #include "alloc-util.h"
-#include "bus-error.h"
 #include "bus-internal.h"
 #include "bus-label.h"
 #include "bus-message.h"
 #include "def.h"
 #include "env-util.h"
 #include "escape.h"
+#include "extract-word.h"
 #include "fd-util.h"
+#include "hashmap.h"
+#include "install.h"
+#include "kdbus.h"
+#include "log.h"
 #include "macro.h"
 #include "missing.h"
 #include "parse-util.h"
@@ -49,6 +62,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "syslog-util.h"
+#include "time-util.h"
 #include "unit-name.h"
 #include "user-util.h"
 #include "utf8.h"
@@ -181,7 +195,7 @@ int bus_event_loop_with_idle(
 }
 
 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
         int r, has_owner = 0;
 
         assert(c);
@@ -207,7 +221,7 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
 }
 
 static int check_good_user(sd_bus_message *m, uid_t good_user) {
-        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
         uid_t sender_uid;
         int r;
 
@@ -257,8 +271,8 @@ int bus_test_polkit(
                 return 1;
 #ifdef ENABLE_POLKIT
         else {
-                _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 int authorized = false, challenge = false;
                 const char *sender, **k, **v;
 
@@ -361,7 +375,7 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) {
 }
 
 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
         AsyncPolkitQuery *q = userdata;
         int r;
 
@@ -399,7 +413,7 @@ int bus_verify_polkit_async(
                 sd_bus_error *error) {
 
 #ifdef ENABLE_POLKIT
-        _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
         AsyncPolkitQuery *q;
         const char *sender, **k, **v;
         sd_bus_message_handler_t callback;
@@ -587,7 +601,7 @@ int bus_check_peercred(sd_bus *c) {
 }
 
 int bus_connect_system_systemd(sd_bus **_bus) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         int r;
 
         assert(_bus);
@@ -641,7 +655,7 @@ int bus_connect_system_systemd(sd_bus **_bus) {
 }
 
 int bus_connect_user_systemd(sd_bus **_bus) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *ee = NULL;
         const char *e;
         int r;
@@ -907,8 +921,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
 }
 
 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -1091,7 +1105,7 @@ int bus_message_map_all_properties(
                 const struct bus_properties_map *map,
                 void *userdata) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(m);
@@ -1197,8 +1211,8 @@ int bus_map_all_properties(
                 const struct bus_properties_map *map,
                 void *userdata) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -1382,7 +1396,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
 
 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
         const char *eq, *field;
-        int r;
+        int r, rl;
 
         assert(m);
         assert(assignment);
@@ -1393,20 +1407,18 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 return -EINVAL;
         }
 
+        r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
+        if (r < 0)
+                return bus_log_create_error(r);
+
         field = strndupa(assignment, eq - assignment);
         eq ++;
 
         if (streq(field, "CPUQuota")) {
 
-                if (isempty(eq)) {
-
-                        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
-                        r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
-
-                } else if (endswith(eq, "%")) {
+                if (isempty(eq))
+                        r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
+                else if (endswith(eq, "%")) {
                         double percent;
 
                         if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
@@ -1414,49 +1426,78 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                                 return -EINVAL;
                         }
 
-                        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
-                        r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
+                        r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100);
                 } else {
                         log_error("CPU quota needs to be in percent.");
                         return -EINVAL;
                 }
 
-                if (r < 0)
-                        return bus_log_create_error(r);
+                goto finish;
 
-                return 0;
         } else if (streq(field, "EnvironmentFile")) {
-                r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
-                if (r < 0)
-                        return r;
 
-                r = sd_bus_message_append(m, "v", "a(sb)", 1,
+                r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
                                           eq[0] == '-' ? eq + 1 : eq,
                                           eq[0] == '-');
+                goto finish;
+
+        } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) {
+                char *n;
+                usec_t t;
+                size_t l;
+                r = parse_sec(eq, &t);
                 if (r < 0)
-                        return r;
-                return 0;
+                        return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
+
+                l = strlen(field);
+                n = newa(char, l + 2);
+                if (!n)
+                        return log_oom();
+
+                /* Change suffix Sec → USec */
+                strcpy(mempcpy(n, field, l - 3), "USec");
+                r = sd_bus_message_append(m, "sv", n, "t", t);
+                goto finish;
         }
 
         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
         if (r < 0)
                 return bus_log_create_error(r);
 
-        if (STR_IN_SET(field,
+        rl = rlimit_from_string(field);
+        if (rl >= 0) {
+                const char *sn;
+                struct rlimit l;
+
+                r = rlimit_parse(rl, eq, &l);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse resource limit: %s", eq);
+
+                r = sd_bus_message_append(m, "v", "t", l.rlim_max);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_close_container(m);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                sn = strjoina(field, "Soft");
+                r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
+
+        } else if (STR_IN_SET(field,
                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
                        "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
                        "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
-                       "SyslogLevelPrefix", "Delegate")) {
+                       "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
 
                 r = parse_boolean(eq);
-                if (r < 0) {
-                        log_error("Failed to parse boolean assignment %s.", assignment);
-                        return -EINVAL;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
 
                 r = sd_bus_message_append(m, "v", "b", r);
 
@@ -1628,21 +1669,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
                 }
 
-        } else if (rlimit_from_string(field) >= 0) {
-                uint64_t rl;
-
-                if (streq(eq, "infinity"))
-                        rl = (uint64_t) -1;
-                else {
-                        r = safe_atou64(eq, &rl);
-                        if (r < 0) {
-                                log_error("Invalid resource limit: %s", eq);
-                                return -EINVAL;
-                        }
-                }
-
-                r = sd_bus_message_append(m, "v", "t", rl);
-
         } else if (streq(field, "Nice")) {
                 int32_t i;
 
@@ -1712,16 +1738,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 r = sd_bus_message_append(m, "v", "i", sig);
 
-        } else if (streq(field, "AccuracySec")) {
-                usec_t u;
-
-                r = parse_sec(eq, &u);
-                if (r < 0) {
-                        log_error("Failed to parse %s value %s", field, eq);
-                        return -EINVAL;
-                }
-
-                r = sd_bus_message_append(m, "v", "t", u);
         } else if (streq(field, "TimerSlackNSec")) {
                 nsec_t n;
 
@@ -1835,6 +1851,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 return -EINVAL;
         }
 
+finish:
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_close_container(m);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -2007,13 +2028,21 @@ static const struct {
         { "start-limit", "start of the service was attempted too often" }
 };
 
-static void log_job_error_with_service_result(const char* service, const char *result) {
-        _cleanup_free_ char *service_shell_quoted = NULL;
+static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) {
+        _cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL;
 
         assert(service);
 
         service_shell_quoted = shell_maybe_quote(service);
 
+        systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL);
+        if (!systemctl_extra_args) {
+                log_oom();
+                return;
+        }
+
+        systemctl_extra_args = strstrip(systemctl_extra_args);
+
         if (!isempty(result)) {
                 unsigned i;
 
@@ -2022,27 +2051,30 @@ static void log_job_error_with_service_result(const char* service, const char *r
                                 break;
 
                 if (i < ELEMENTSOF(explanations)) {
-                        log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+                        log_error("Job for %s failed because %s. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
                                   service,
                                   explanations[i].explanation,
+                                  systemctl_extra_args,
                                   strna(service_shell_quoted));
 
                         goto finish;
                 }
         }
 
-        log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+        log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
                   service,
+                  systemctl_extra_args,
                   strna(service_shell_quoted));
 
 finish:
         /* For some results maybe additional explanation is required */
         if (streq_ptr(result, "start-limit"))
-                log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
+                log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.",
+                         systemctl_extra_args,
                          strna(service_shell_quoted));
 }
 
-static int check_wait_response(BusWaitForJobs *d, bool quiet) {
+static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) {
         int r = 0;
 
         assert(d->result);
@@ -2055,7 +2087,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
                 else if (streq(d->result, "dependency"))
                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
                 else if (streq(d->result, "invalid"))
-                        log_error("Job for %s invalid.", strna(d->name));
+                        log_error("%s is not active, cannot reload.", strna(d->name));
                 else if (streq(d->result, "assert"))
                         log_error("Assertion failed on job for %s.", strna(d->name));
                 else if (streq(d->result, "unsupported"))
@@ -2069,7 +2101,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
                                 if (q < 0)
                                         log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
 
-                                log_job_error_with_service_result(d->name, result);
+                                log_job_error_with_service_result(d->name, result, extra_args);
                         } else
                                 log_error("Job failed. See \"journalctl -xe\" for details.");
                 }
@@ -2093,7 +2125,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
         return r;
 }
 
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
+int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) {
         int r = 0;
 
         assert(d);
@@ -2106,7 +2138,7 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
                         return log_error_errno(q, "Failed to wait for response: %m");
 
                 if (d->result) {
-                        q = check_wait_response(d, quiet);
+                        q = check_wait_response(d, quiet, extra_args);
                         /* Return the first error as it is most likely to be
                          * meaningful. */
                         if (q < 0 && r == 0)
@@ -2141,7 +2173,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
         if (r < 0)
                 return log_oom();
 
-        return bus_wait_for_jobs(d, quiet);
+        return bus_wait_for_jobs(d, quiet, NULL);
 }
 
 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
@@ -2347,23 +2379,28 @@ int bus_property_get_rlimit(
         struct rlimit *rl;
         uint64_t u;
         rlim_t x;
+        const char *is_soft;
 
         assert(bus);
         assert(reply);
         assert(userdata);
 
+        is_soft = endswith(property, "Soft");
         rl = *(struct rlimit**) userdata;
         if (rl)
-                x = rl->rlim_max;
+                x = is_soft ? rl->rlim_cur : rl->rlim_max;
         else {
                 struct rlimit buf = {};
                 int z;
+                const char *s;
+
+                s = is_soft ? strndupa(property, is_soft - property) : property;
 
-                z = rlimit_from_string(strstr(property, "Limit"));
+                z = rlimit_from_string(strstr(s, "Limit"));
                 assert(z >= 0);
 
                 getrlimit(z, &buf);
-                x = buf.rlim_max;
+                x = is_soft ? buf.rlim_cur : buf.rlim_max;
         }
 
         /* rlim_t might have different sizes, let's map
index 3925c10fde4d8df3a29d141d7a87553007d2ae7d..204da5568269cf1a4c1f00bce978fc8e2c8798ff 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "sd-bus-vtable.h"
 #include "sd-bus.h"
 #include "sd-event.h"
 
 #include "hashmap.h"
 #include "install.h"
+#include "macro.h"
 #include "string-util.h"
 #include "time-util.h"
 
@@ -137,21 +142,6 @@ typedef struct UnitInfo {
 
 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_flush_close_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref);
-
-#define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
-#define _cleanup_bus_flush_close_unref_ _cleanup_(sd_bus_flush_close_unrefp)
-#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp)
-#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
-#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
-#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp)
-#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
-
 #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type)              \
         int function(sd_bus *bus,                                       \
                      const char *path,                                  \
@@ -190,7 +180,7 @@ typedef struct BusWaitForJobs BusWaitForJobs;
 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret);
 void bus_wait_for_jobs_free(BusWaitForJobs *d);
 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path);
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet);
+int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args);
 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free);
index 129ffc7056bebbd62be6829d5f3f6b8294900053..f3039b23f741e4638a2ad729d34e260dd6158ccc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -21,7 +19,9 @@
 
 #include <dirent.h>
 #include <errno.h>
+#include <stddef.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "formats-util.h"
 #include "locale-util.h"
 #include "macro.h"
+#include "output-mode.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
-#include "util.h"
 
 static int compare(const void *a, const void *b) {
         const pid_t *p = a, *q = b;
index aa832454b5c4d5a6b95bf37e9e859b5056f21e84..3ab7dfb33cca226b4faec6c7d369650261a383a9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -23,7 +21,9 @@
 
 #include <stdbool.h>
 #include <sys/types.h>
+
 #include "logs-show.h"
+#include "output-mode.h"
 
 int show_cgroup_by_path(const char *path, const char *prefix, unsigned columns, bool kernel_threads, OutputFlags flags);
 int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned columns, bool kernel_threads, OutputFlags flags);
index 71cc613704cd99fbbc4a00dc73b479b5b2491ec6..a3ac7aeb822a738a50e4ef88c1d1977e98d9c1b1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <mqueue.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <sys/sem.h>
 #include <sys/shm.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include "clean-ipc.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
+#include "log.h"
+#include "macro.h"
 #include "string-util.h"
 #include "strv.h"
-#include "util.h"
 
 static int clean_sysvipc_shm(uid_t delete_uid) {
         _cleanup_fclose_ FILE *f = NULL;
index 2de57fad269713260d78bab8bc4b0baec12c1204..44a83afcf703dc1a1f960aba6dd51ef12abfa014 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index a69719116c9907e06f8fa5b3845c0a4147090bad..f93785865ef8b5c807997e04460cc1afa26d938c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <fcntl.h>
 #include <fnmatch.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "sd-id128.h"
@@ -38,6 +40,8 @@
 #include "glob-util.h"
 #include "hostname-util.h"
 #include "ima-util.h"
+#include "list.h"
+#include "macro.h"
 #include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -231,7 +235,7 @@ static int condition_test_security(Condition *c) {
         assert(c->type == CONDITION_SECURITY);
 
         if (streq(c->parameter, "selinux"))
-                return mac_selinux_use();
+                return mac_selinux_have();
         if (streq(c->parameter, "smack"))
                 return mac_smack_use();
         if (streq(c->parameter, "apparmor"))
index 0780e78123ab6d2628120482a48f6ef9c67ae9be..bdda04b7702b0a593cf606a9a401a28bd35165e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 486122b0fd68ac9bfd35c0212aa7fc87222c1945..e7fe9ac21e1c4fea93916a89deac2b691391289a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 ***/
 
 #include <errno.h>
+#include <limits.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
-#include "sd-messages.h"
+#include <sys/types.h>
 
 #include "alloc-util.h"
 #include "conf-files.h"
 #include "conf-parser.h"
+#include "extract-word.h"
 #include "fd-util.h"
 #include "fs-util.h"
 #include "log.h"
@@ -40,8 +40,8 @@
 #include "string-util.h"
 #include "strv.h"
 #include "syslog-util.h"
+#include "time-util.h"
 #include "utf8.h"
-#include "util.h"
 
 int config_item_table_lookup(
                 const void *table,
index fb0234baae1039eebf19e60145ff999ca4e8aed2..a91c94c322eb8fb5c6844ba687b8e1a92c5c08a4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdio.h>
+#include <errno.h>
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <syslog.h>
 
+#include "alloc-util.h"
+#include "log.h"
 #include "macro.h"
 
 /* An abstract parser for simple, line based, shallow configuration
index ad3c17d5bd108262fef6fad863a030086d90dc22..b2d464c1173beab7542c604432612dd2e9f09bf4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -26,6 +24,7 @@
 #include "alloc-util.h"
 #include "dev-setup.h"
 #include "label.h"
+#include "log.h"
 #include "path-util.h"
 #include "user-util.h"
 #include "util.h"
index ab2748db7f349e8fb3d6afcf73646e6c096be52b..5766a620600aa192b65c73d7ed69bef2afec66b6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 7af15e00984e077f3a27cb35912b98749f2973ea..45d24c0079ca76be22ce9c53215aaf831697baaa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <stringprep.h>
 #endif
 
+#include <endian.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+
 #include "alloc-util.h"
 #include "dns-domain.h"
+#include "hashmap.h"
 #include "hexdecoct.h"
+#include "in-addr-util.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "string-util.h"
+#include "strv.h"
+#include "utf8.h"
 
 int dns_label_unescape(const char **name, char *dest, size_t sz) {
         const char *n;
@@ -37,7 +46,6 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
 
         assert(name);
         assert(*name);
-        assert(dest);
 
         n = *name;
         d = dest;
@@ -51,12 +59,12 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
                 if (*n == 0)
                         break;
 
-                if (sz <= 0)
-                        return -ENOSPC;
-
                 if (r >= DNS_LABEL_MAX)
                         return -EINVAL;
 
+                if (sz <= 0)
+                        return -ENOBUFS;
+
                 if (*n == '\\') {
                         /* Escaped character */
 
@@ -68,9 +76,12 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
 
                         else if (*n == '\\' || *n == '.') {
                                 /* Escaped backslash or dot */
-                                *(d++) = *(n++);
+
+                                if (d)
+                                        *(d++) = *n;
                                 sz--;
                                 r++;
+                                n++;
 
                         } else if (n[0] >= '0' && n[0] <= '9') {
                                 unsigned k;
@@ -85,11 +96,17 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
                                         ((unsigned) (n[1] - '0') * 10) +
                                         ((unsigned) (n[2] - '0'));
 
-                                /* Don't allow CC characters or anything that doesn't fit in 8bit */
-                                if (k < ' ' || k > 255 || k == 127)
+                                /* Don't allow anything that doesn't
+                                 * fit in 8bit. Note that we do allow
+                                 * control characters, as some servers
+                                 * (e.g. cloudflare) are happy to
+                                 * generate labels with them
+                                 * inside. */
+                                if (k > 255)
                                         return -EINVAL;
 
-                                *(d++) = (char) k;
+                                if (d)
+                                        *(d++) = (char) k;
                                 sz--;
                                 r++;
 
@@ -100,9 +117,12 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
                 } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
 
                         /* Normal character */
-                        *(d++) = *(n++);
+
+                        if (d)
+                                *(d++) = *n;
                         sz--;
                         r++;
+                        n++;
                 } else
                         return -EINVAL;
         }
@@ -111,7 +131,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
         if (r == 0 && *n)
                 return -EINVAL;
 
-        if (sz >= 1)
+        if (sz >= 1 && d)
                 *d = 0;
 
         *name = n;
@@ -137,20 +157,24 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
                 return 0;
         }
 
-        assert(**label_terminal == '.' || **label_terminal == 0);
+        terminal = *label_terminal;
+        assert(*terminal == '.' || *terminal == 0);
 
-        /* skip current terminal character */
-        terminal = *label_terminal - 1;
+        /* Skip current terminal character (and accept domain names ending it ".") */
+        if (*terminal == 0)
+                terminal--;
+        if (terminal >= name && *terminal == '.')
+                terminal--;
 
-        /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */
+        /* Point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */
         for (;;) {
                 if (terminal < name) {
-                        /* reached the first label, so indicate that there are no more */
+                        /* Reached the first label, so indicate that there are no more */
                         terminal = NULL;
                         break;
                 }
 
-                /* find the start of the last label */
+                /* Find the start of the last label */
                 if (*terminal == '.') {
                         const char *y;
                         unsigned slashes = 0;
@@ -159,7 +183,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
                                 slashes ++;
 
                         if (slashes % 2 == 0) {
-                                /* the '.' was not escaped */
+                                /* The '.' was not escaped */
                                 name = terminal + 1;
                                 break;
                         } else {
@@ -180,30 +204,36 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
         return r;
 }
 
-int dns_label_escape(const char *p, size_t l, char **ret) {
-        _cleanup_free_ char *s = NULL;
+int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
         char *q;
-        int r;
 
-        assert(p);
-        assert(ret);
+        /* DNS labels must be between 1 and 63 characters long. A
+         * zero-length label does not exist. See RFC 2182, Section
+         * 11. */
 
-        if (l > DNS_LABEL_MAX)
+        if (l <= 0 || l > DNS_LABEL_MAX)
                 return -EINVAL;
+        if (sz < 1)
+                return -ENOBUFS;
 
-        s = malloc(l * 4 + 1);
-        if (!s)
-                return -ENOMEM;
+        assert(p);
+        assert(dest);
 
-        q = s;
+        q = dest;
         while (l > 0) {
 
                 if (*p == '.' || *p == '\\') {
 
                         /* Dot or backslash */
+
+                        if (sz < 3)
+                                return -ENOBUFS;
+
                         *(q++) = '\\';
                         *(q++) = *p;
 
+                        sz -= 2;
+
                 } else if (*p == '_' ||
                            *p == '-' ||
                            (*p >= '0' && *p <= '9') ||
@@ -211,25 +241,55 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
                            (*p >= 'A' && *p <= 'Z')) {
 
                         /* Proper character */
+
+                        if (sz < 2)
+                                return -ENOBUFS;
+
                         *(q++) = *p;
-                } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
+                        sz -= 1;
+
+                } else {
 
                         /* Everything else */
+
+                        if (sz < 5)
+                                return -ENOBUFS;
+
                         *(q++) = '\\';
                         *(q++) = '0' + (char) ((uint8_t) *p / 100);
                         *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
                         *(q++) = '0' + (char) ((uint8_t) *p % 10);
 
-                } else
-                        return -EINVAL;
+                        sz -= 4;
+                }
 
                 p++;
                 l--;
         }
 
         *q = 0;
+        return (int) (q - dest);
+}
+
+int dns_label_escape_new(const char *p, size_t l, char **ret) {
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        assert(p);
+        assert(ret);
+
+        if (l <= 0 || l > DNS_LABEL_MAX)
+                return -EINVAL;
+
+        s = new(char, DNS_LABEL_ESCAPED_MAX);
+        if (!s)
+                return -ENOMEM;
+
+        r = dns_label_escape(p, l, s, DNS_LABEL_ESCAPED_MAX);
+        if (r < 0)
+                return r;
+
         *ret = s;
-        r = q - s;
         s = NULL;
 
         return r;
@@ -238,32 +298,52 @@ int dns_label_escape(const char *p, size_t l, char **ret) {
 int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
 #ifdef HAVE_LIBIDN
         _cleanup_free_ uint32_t *input = NULL;
-        size_t input_size;
+        size_t input_size, l;
         const char *p;
         bool contains_8bit = false;
+        char buffer[DNS_LABEL_MAX+1];
 
         assert(encoded);
         assert(decoded);
-        assert(decoded_max >= DNS_LABEL_MAX);
+
+        /* Converts an U-label into an A-label */
 
         if (encoded_size <= 0)
-                return 0;
+                return -EINVAL;
 
         for (p = encoded; p < encoded + encoded_size; p++)
                 if ((uint8_t) *p > 127)
                         contains_8bit = true;
 
-        if (!contains_8bit)
+        if (!contains_8bit) {
+                if (encoded_size > DNS_LABEL_MAX)
+                        return -EINVAL;
+
                 return 0;
+        }
 
         input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
         if (!input)
                 return -ENOMEM;
 
-        if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
+        if (idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
+                return -EINVAL;
+
+        l = strlen(buffer);
+
+        /* Verify that the the result is not longer than one DNS label. */
+        if (l <= 0 || l > DNS_LABEL_MAX)
                 return -EINVAL;
+        if (l > decoded_max)
+                return -ENOBUFS;
 
-        return strlen(decoded);
+        memcpy(decoded, buffer, l);
+
+        /* If there's room, append a trailing NUL byte, but only then */
+        if (decoded_max > l)
+                decoded[l] = 0;
+
+        return (int) l;
 #else
         return 0;
 #endif
@@ -277,11 +357,14 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
         uint32_t *output = NULL;
         size_t w;
 
-        /* To be invoked after unescaping */
+        /* To be invoked after unescaping. Converts an A-label into an U-label. */
 
         assert(encoded);
         assert(decoded);
 
+        if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
+                return -EINVAL;
+
         if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
                 return 0;
 
@@ -301,11 +384,16 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
         if (!result)
                 return -ENOMEM;
         if (w <= 0)
-                return 0;
-        if (w+1 > decoded_max)
                 return -EINVAL;
+        if (w > decoded_max)
+                return -ENOBUFS;
+
+        memcpy(decoded, result, w);
+
+        /* Append trailing NUL byte if there's space, but only then. */
+        if (decoded_max > w)
+                decoded[w] = 0;
 
-        memcpy(decoded, result, w+1);
         return w;
 #else
         return 0;
@@ -315,16 +403,20 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
 int dns_name_concat(const char *a, const char *b, char **_ret) {
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
-        const char *p = a;
+        const char *p;
         bool first = true;
         int r;
 
-        assert(a);
+        if (a)
+                p = a;
+        else if (b) {
+                p = b;
+                b = NULL;
+        } else
+                goto finish;
 
         for (;;) {
-                _cleanup_free_ char *t = NULL;
                 char label[DNS_LABEL_MAX];
-                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
@@ -343,37 +435,47 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
                         break;
                 }
 
-                k = dns_label_undo_idna(label, r, label, sizeof(label));
-                if (k < 0)
-                        return k;
-                if (k > 0)
-                        r = k;
-
-                r = dns_label_escape(label, r, &t);
-                if (r < 0)
-                        return r;
-
                 if (_ret) {
-                        if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
+                        if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
                                 return -ENOMEM;
 
+                        r = dns_label_escape(label, r, ret + n + !first, DNS_LABEL_ESCAPED_MAX);
+                        if (r < 0)
+                                return r;
+
                         if (!first)
-                                ret[n++] = '.';
-                        else
-                                first = false;
+                                ret[n] = '.';
+                } else {
+                        char escaped[DNS_LABEL_ESCAPED_MAX];
 
-                        memcpy(ret + n, t, r);
+                        r = dns_label_escape(label, r, escaped, sizeof(escaped));
+                        if (r < 0)
+                                return r;
                 }
 
+                if (!first)
+                        n++;
+                else
+                        first = false;
+
                 n += r;
         }
 
-        if (n > DNS_NAME_MAX)
+finish:
+        if (n > DNS_HOSTNAME_MAX)
                 return -EINVAL;
 
         if (_ret) {
-                if (!GREEDY_REALLOC(ret, allocated, n + 1))
-                        return -ENOMEM;
+                if (n == 0) {
+                        /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
+                        if (!GREEDY_REALLOC(ret, allocated, 2))
+                                return -ENOMEM;
+
+                        ret[n++] = '.';
+                } else {
+                        if (!GREEDY_REALLOC(ret, allocated, n + 1))
+                                return -ENOMEM;
+                }
 
                 ret[n] = 0;
                 *_ret = ret;
@@ -389,27 +491,18 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
 
         assert(p);
 
-        while (*p) {
+        for (;;) {
                 char label[DNS_LABEL_MAX+1];
-                int k;
 
                 r = dns_label_unescape(&p, label, sizeof(label));
                 if (r < 0)
                         break;
-
-                k = dns_label_undo_idna(label, r, label, sizeof(label));
-                if (k < 0)
-                        break;
-                if (k > 0)
-                        r = k;
-
                 if (r == 0)
                         break;
 
-                label[r] = 0;
-                ascii_strlower(label);
-
-                string_hash_func(label, state);
+                ascii_strlower_n(label, r);
+                siphash24_compress(label, r, state);
+                siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */
         }
 
         /* enforce that all names are terminated by the empty label */
@@ -418,7 +511,7 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
 
 int dns_name_compare_func(const void *a, const void *b) {
         const char *x, *y;
-        int r, q, k, w;
+        int r, q;
 
         assert(a);
         assert(b);
@@ -427,7 +520,7 @@ int dns_name_compare_func(const void *a, const void *b) {
         y = (const char *) b + strlen(b);
 
         for (;;) {
-                char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
 
                 if (x == NULL && y == NULL)
                         return 0;
@@ -437,17 +530,7 @@ int dns_name_compare_func(const void *a, const void *b) {
                 if (r < 0 || q < 0)
                         return r - q;
 
-                k = dns_label_undo_idna(la, r, la, sizeof(la));
-                w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
-                if (k < 0 || w < 0)
-                        return k - w;
-                if (k > 0)
-                        r = k;
-                if (w > 0)
-                        r = w;
-
-                la[r] = lb[q] = 0;
-                r = strcasecmp(la, lb);
+                r = ascii_strcasecmp_nn(la, r, lb, q);
                 if (r != 0)
                         return r;
         }
@@ -459,45 +542,35 @@ const struct hash_ops dns_name_hash_ops = {
 };
 
 int dns_name_equal(const char *x, const char *y) {
-        int r, q, k, w;
+        int r, q;
 
         assert(x);
         assert(y);
 
         for (;;) {
-                char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
-
-                if (*x == 0 && *y == 0)
-                        return true;
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
 
                 r = dns_label_unescape(&x, la, sizeof(la));
                 if (r < 0)
                         return r;
 
-                k = dns_label_undo_idna(la, r, la, sizeof(la));
-                if (k < 0)
-                        return k;
-                if (k > 0)
-                        r = k;
-
                 q = dns_label_unescape(&y, lb, sizeof(lb));
                 if (q < 0)
                         return q;
-                w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
-                if (w < 0)
-                        return w;
-                if (w > 0)
-                        q = w;
-
-                la[r] = lb[q] = 0;
-                if (strcasecmp(la, lb))
+
+                if (r != q)
+                        return false;
+                if (r == 0)
+                        return true;
+
+                if (ascii_strcasecmp_n(la, lb, r) != 0)
                         return false;
         }
 }
 
 int dns_name_endswith(const char *name, const char *suffix) {
         const char *n, *s, *saved_n = NULL;
-        int r, q, k, w;
+        int r, q;
 
         assert(name);
         assert(suffix);
@@ -506,16 +579,11 @@ int dns_name_endswith(const char *name, const char *suffix) {
         s = suffix;
 
         for (;;) {
-                char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
+                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
 
                 r = dns_label_unescape(&n, ln, sizeof(ln));
                 if (r < 0)
                         return r;
-                k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
-                if (k < 0)
-                        return k;
-                if (k > 0)
-                        r = k;
 
                 if (!saved_n)
                         saved_n = n;
@@ -523,20 +591,13 @@ int dns_name_endswith(const char *name, const char *suffix) {
                 q = dns_label_unescape(&s, ls, sizeof(ls));
                 if (q < 0)
                         return q;
-                w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
-                if (w < 0)
-                        return w;
-                if (w > 0)
-                        q = w;
 
                 if (r == 0 && q == 0)
                         return true;
                 if (r == 0 && saved_n == n)
                         return false;
 
-                ln[r] = ls[q] = 0;
-
-                if (r != q || strcasecmp(ln, ls)) {
+                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
 
                         /* Not the same, let's jump back, and try with the next label again */
                         s = suffix;
@@ -546,6 +607,91 @@ int dns_name_endswith(const char *name, const char *suffix) {
         }
 }
 
+int dns_name_startswith(const char *name, const char *prefix) {
+        const char *n, *p;
+        int r, q;
+
+        assert(name);
+        assert(prefix);
+
+        n = name;
+        p = prefix;
+
+        for (;;) {
+                char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX];
+
+                r = dns_label_unescape(&p, lp, sizeof(lp));
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return true;
+
+                q = dns_label_unescape(&n, ln, sizeof(ln));
+                if (q < 0)
+                        return q;
+
+                if (r != q)
+                        return false;
+                if (ascii_strcasecmp_n(ln, lp, r) != 0)
+                        return false;
+        }
+}
+
+int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) {
+        const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix;
+        int r, q;
+
+        assert(name);
+        assert(old_suffix);
+        assert(new_suffix);
+        assert(ret);
+
+        n = name;
+        s = old_suffix;
+
+        for (;;) {
+                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
+
+                if (!saved_before)
+                        saved_before = n;
+
+                r = dns_label_unescape(&n, ln, sizeof(ln));
+                if (r < 0)
+                        return r;
+
+                if (!saved_after)
+                        saved_after = n;
+
+                q = dns_label_unescape(&s, ls, sizeof(ls));
+                if (q < 0)
+                        return q;
+
+                if (r == 0 && q == 0)
+                        break;
+                if (r == 0 && saved_after == n) {
+                        *ret = NULL; /* doesn't match */
+                        return 0;
+                }
+
+                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
+
+                        /* Not the same, let's jump back, and try with the next label again */
+                        s = old_suffix;
+                        n = saved_after;
+                        saved_after = saved_before = NULL;
+                }
+        }
+
+        /* Found it! Now generate the new name */
+        prefix = strndupa(name, saved_before - name);
+
+        r = dns_name_concat(prefix, new_suffix, ret);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
 int dns_name_between(const char *a, const char *b, const char *c) {
         int n;
 
@@ -684,34 +830,493 @@ int dns_name_address(const char *p, int *family, union in_addr_union *address) {
         return 0;
 }
 
-int dns_name_root(const char *name) {
-        char label[DNS_LABEL_MAX+1];
-        int r;
+bool dns_name_is_root(const char *name) {
 
         assert(name);
 
-        r = dns_label_unescape(&name, label, sizeof(label));
-        if (r < 0)
-                return r;
+        /* There are exactly two ways to encode the root domain name:
+         * as empty string, or with a single dot. */
 
-        return r == 0 && *name == 0;
+        return STR_IN_SET(name, "", ".");
 }
 
-int dns_name_single_label(const char *name) {
-        char label[DNS_LABEL_MAX+1];
+bool dns_name_is_single_label(const char *name) {
         int r;
 
         assert(name);
 
-        r = dns_label_unescape(&name, label, sizeof(label));
+        r = dns_name_parent(&name);
+        if (r <= 0)
+                return false;
+
+        return dns_name_is_root(name);
+}
+
+/* Encode a domain name according to RFC 1035 Section 3.1, without compression */
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical) {
+        uint8_t *label_length, *out;
+        int r;
+
+        assert(domain);
+        assert(buffer);
+
+        out = buffer;
+
+        do {
+                /* Reserve a byte for label length */
+                if (len <= 0)
+                        return -ENOBUFS;
+                len--;
+                label_length = out;
+                out++;
+
+                /* Convert and copy a single label. Note that
+                 * dns_label_unescape() returns 0 when it hits the end
+                 * of the domain name, which we rely on here to encode
+                 * the trailing NUL byte. */
+                r = dns_label_unescape(&domain, (char *) out, len);
+                if (r < 0)
+                        return r;
+
+                /* Optionally, output the name in DNSSEC canonical
+                 * format, as described in RFC 4034, section 6.2. Or
+                 * in other words: in lower-case. */
+                if (canonical)
+                        ascii_strlower_n((char*) out, (size_t) r);
+
+                /* Fill label length, move forward */
+                *label_length = r;
+                out += r;
+                len -= r;
+
+        } while (r != 0);
+
+        /* Verify the maximum size of the encoded name. The trailing
+         * dot + NUL byte account are included this time, hence
+         * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this
+         * time. */
+        if (out - buffer > DNS_HOSTNAME_MAX + 2)
+                return -EINVAL;
+
+        return out - buffer;
+}
+
+static bool srv_type_label_is_valid(const char *label, size_t n) {
+        size_t k;
+
+        assert(label);
+
+        if (n < 2) /* Label needs to be at least 2 chars long */
+                return false;
+
+        if (label[0] != '_') /* First label char needs to be underscore */
+                return false;
+
+        /* Second char must be a letter */
+        if (!(label[1] >= 'A' && label[1] <= 'Z') &&
+            !(label[1] >= 'a' && label[1] <= 'z'))
+                return false;
+
+        /* Third and further chars must be alphanumeric or a hyphen */
+        for (k = 2; k < n; k++) {
+                if (!(label[k] >= 'A' && label[k] <= 'Z') &&
+                    !(label[k] >= 'a' && label[k] <= 'z') &&
+                    !(label[k] >= '0' && label[k] <= '9') &&
+                    label[k] != '-')
+                        return false;
+        }
+
+        return true;
+}
+
+bool dns_srv_type_is_valid(const char *name) {
+        unsigned c = 0;
+        int r;
+
+        if (!name)
+                return false;
+
+        for (;;) {
+                char label[DNS_LABEL_MAX];
+
+                /* This more or less implements RFC 6335, Section 5.1 */
+
+                r = dns_label_unescape(&name, label, sizeof(label));
+                if (r < 0)
+                        return false;
+                if (r == 0)
+                        break;
+
+                if (c >= 2)
+                        return false;
+
+                if (!srv_type_label_is_valid(label, r))
+                        return false;
+
+                c++;
+        }
+
+        return c == 2; /* exactly two labels */
+}
+
+bool dns_service_name_is_valid(const char *name) {
+        size_t l;
+
+        /* This more or less implements RFC 6763, Section 4.1.1 */
+
+        if (!name)
+                return false;
+
+        if (!utf8_is_valid(name))
+                return false;
+
+        if (string_has_cc(name, NULL))
+                return false;
+
+        l = strlen(name);
+        if (l <= 0)
+                return false;
+        if (l > 63)
+                return false;
+
+        return true;
+}
+
+int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
+        char escaped[DNS_LABEL_ESCAPED_MAX];
+        _cleanup_free_ char *n = NULL;
+        int r;
+
+        assert(type);
+        assert(domain);
+        assert(ret);
+
+        if (!dns_srv_type_is_valid(type))
+                return -EINVAL;
+
+        if (!name)
+                return dns_name_concat(type, domain, ret);
+
+        if (!dns_service_name_is_valid(name))
+                return -EINVAL;
+
+        r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped));
         if (r < 0)
                 return r;
-        if (r == 0)
-                return 0;
 
-        r = dns_label_unescape(&name, label, sizeof(label));
+        r = dns_name_concat(type, domain, &n);
+        if (r < 0)
+                return r;
+
+        return dns_name_concat(escaped, n, ret);
+}
+
+static bool dns_service_name_label_is_valid(const char *label, size_t n) {
+        char *s;
+
+        assert(label);
+
+        if (memchr(label, 0, n))
+                return false;
+
+        s = strndupa(label, n);
+        return dns_service_name_is_valid(s);
+}
+
+int dns_service_split(const char *joined, char **_name, char **_type, char **_domain) {
+        _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
+        const char *p = joined, *q = NULL, *d = NULL;
+        char a[DNS_LABEL_MAX], b[DNS_LABEL_MAX], c[DNS_LABEL_MAX];
+        int an, bn, cn, r;
+        unsigned x = 0;
+
+        assert(joined);
+
+        /* Get first label from the full name */
+        an = dns_label_unescape(&p, a, sizeof(a));
+        if (an < 0)
+                return an;
+
+        if (an > 0) {
+                x++;
+
+                /* If there was a first label, try to get the second one */
+                bn = dns_label_unescape(&p, b, sizeof(b));
+                if (bn < 0)
+                        return bn;
+
+                if (bn > 0) {
+                        x++;
+
+                        /* If there was a second label, try to get the third one */
+                        q = p;
+                        cn = dns_label_unescape(&p, c, sizeof(c));
+                        if (cn < 0)
+                                return cn;
+
+                        if (cn > 0)
+                                x++;
+                } else
+                        cn = 0;
+        } else
+                an = 0;
+
+        if (x >= 2 && srv_type_label_is_valid(b, bn)) {
+
+                if (x >= 3 && srv_type_label_is_valid(c, cn)) {
+
+                        if (dns_service_name_label_is_valid(a, an)) {
+                                /* OK, got <name> . <type> . <type2> . <domain> */
+
+                                name = strndup(a, an);
+                                if (!name)
+                                        return -ENOMEM;
+
+                                type = strjoin(b, ".", c, NULL);
+                                if (!type)
+                                        return -ENOMEM;
+
+                                d = p;
+                                goto finish;
+                        }
+
+                } else if (srv_type_label_is_valid(a, an)) {
+
+                        /* OK, got <type> . <type2> . <domain> */
+
+                        name = NULL;
+
+                        type = strjoin(a, ".", b, NULL);
+                        if (!type)
+                                return -ENOMEM;
+
+                        d = q;
+                        goto finish;
+                }
+        }
+
+        name = NULL;
+        type = NULL;
+        d = joined;
+
+finish:
+        r = dns_name_normalize(d, &domain);
         if (r < 0)
                 return r;
 
-        return r == 0 && *name == 0;
+        if (_domain) {
+                *_domain = domain;
+                domain = NULL;
+        }
+
+        if (_type) {
+                *_type = type;
+                type = NULL;
+        }
+
+        if (_name) {
+                *_name = name;
+                name = NULL;
+        }
+
+        return 0;
+}
+
+static int dns_name_build_suffix_table(const char *name, const char*table[]) {
+        const char *p;
+        unsigned n = 0;
+        int r;
+
+        assert(name);
+        assert(table);
+
+        p = name;
+        for (;;) {
+                if (n > DNS_N_LABELS_MAX)
+                        return -EINVAL;
+
+                table[n] = p;
+                r = dns_name_parent(&p);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                n++;
+        }
+
+        return (int) n;
+}
+
+int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
+        const char* labels[DNS_N_LABELS_MAX+1];
+        int n;
+
+        assert(name);
+        assert(ret);
+
+        n = dns_name_build_suffix_table(name, labels);
+        if (n < 0)
+                return n;
+
+        if ((unsigned) n < n_labels)
+                return -EINVAL;
+
+        *ret = labels[n - n_labels];
+        return (int) (n - n_labels);
+}
+
+int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
+        int r;
+
+        assert(a);
+        assert(ret);
+
+        for (; n_labels > 0; n_labels --) {
+                r = dns_name_parent(&a);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        *ret = "";
+                        return 0;
+                }
+        }
+
+        *ret = a;
+        return 1;
+}
+
+int dns_name_count_labels(const char *name) {
+        unsigned n = 0;
+        const char *p;
+        int r;
+
+        assert(name);
+
+        p = name;
+        for (;;) {
+                r = dns_name_parent(&p);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                if (n >= DNS_N_LABELS_MAX)
+                        return -EINVAL;
+
+                n++;
+        }
+
+        return (int) n;
+}
+
+int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {
+        int r;
+
+        assert(a);
+        assert(b);
+
+        r = dns_name_skip(a, n_labels, &a);
+        if (r <= 0)
+                return r;
+
+        return dns_name_equal(a, b);
+}
+
+int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
+        const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1];
+        int n = 0, m = 0, k = 0, r, q;
+
+        assert(a);
+        assert(b);
+        assert(ret);
+
+        /* Determines the common suffix of domain names a and b */
+
+        n = dns_name_build_suffix_table(a, a_labels);
+        if (n < 0)
+                return n;
+
+        m = dns_name_build_suffix_table(b, b_labels);
+        if (m < 0)
+                return m;
+
+        for (;;) {
+                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
+                const char *x, *y;
+
+                if (k >= n || k >= m) {
+                        *ret = a_labels[n - k];
+                        return 0;
+                }
+
+                x = a_labels[n - 1 - k];
+                r = dns_label_unescape(&x, la, sizeof(la));
+                if (r < 0)
+                        return r;
+
+                y = b_labels[m - 1 - k];
+                q = dns_label_unescape(&y, lb, sizeof(lb));
+                if (q < 0)
+                        return q;
+
+                if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) {
+                        *ret = a_labels[n - k];
+                        return 0;
+                }
+
+                k++;
+        }
+}
+
+int dns_name_apply_idna(const char *name, char **ret) {
+        _cleanup_free_ char *buf = NULL;
+        size_t n = 0, allocated = 0;
+        bool first = true;
+        int r, q;
+
+        assert(name);
+        assert(ret);
+
+        for (;;) {
+                char label[DNS_LABEL_MAX];
+
+                r = dns_label_unescape(&name, label, sizeof(label));
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                q = dns_label_apply_idna(label, r, label, sizeof(label));
+                if (q < 0)
+                        return q;
+                if (q > 0)
+                        r = q;
+
+                if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+                        return -ENOMEM;
+
+                r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
+                if (r < 0)
+                        return r;
+
+                if (first)
+                        first = false;
+                else
+                        buf[n++] = '.';
+
+                n +=r;
+        }
+
+        if (n > DNS_HOSTNAME_MAX)
+                return -EINVAL;
+
+        if (!GREEDY_REALLOC(buf, allocated, n + 1))
+                return -ENOMEM;
+
+        buf[n] = 0;
+        *ret = buf;
+        buf = NULL;
+
+        return (int) n;
 }
index 1f0d242c18bb0e5aecde3aba12a4e2a5f571ac26..2de3642cb39317af463da6b71ec656fa4a91ba36 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #pragma once
 
 
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
 #include "hashmap.h"
 #include "in-addr-util.h"
 
+/* Length of a single label, with all escaping removed, excluding any trailing dot or NUL byte */
 #define DNS_LABEL_MAX 63
-#define DNS_NAME_MAX 255
+
+/* Worst case length of a single label, with all escaping applied and room for a trailing NUL byte. */
+#define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1)
+
+/* Maximum length of a full hostname, consisting of a series of unescaped labels, and no trailing dot or NUL byte */
+#define DNS_HOSTNAME_MAX 253
+
+/* Maximum length of a full hostname, on the wire, including the final NUL byte */
+#define DNS_WIRE_FOMAT_HOSTNAME_MAX 255
+
+/* Maximum number of labels per valid hostname */
+#define DNS_N_LABELS_MAX 127
 
 int dns_label_unescape(const char **name, char *dest, size_t sz);
 int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
-int dns_label_escape(const char *p, size_t l, char **ret);
+int dns_label_escape(const char *p, size_t l, char *dest, size_t sz);
+int dns_label_escape_new(const char *p, size_t l, char **ret);
+
+static inline int dns_name_parent(const char **name) {
+        return dns_label_unescape(name, NULL, DNS_LABEL_MAX);
+}
 
 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);
@@ -61,9 +81,30 @@ extern const struct hash_ops dns_name_hash_ops;
 int dns_name_between(const char *a, const char *b, const char *c);
 int dns_name_equal(const char *x, const char *y);
 int dns_name_endswith(const char *name, const char *suffix);
+int dns_name_startswith(const char *name, const char *prefix);
+
+int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);
 
 int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
 int dns_name_address(const char *p, int *family, union in_addr_union *a);
 
-int dns_name_root(const char *name);
-int dns_name_single_label(const char *name);
+bool dns_name_is_root(const char *name);
+bool dns_name_is_single_label(const char *name);
+
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical);
+
+bool dns_srv_type_is_valid(const char *name);
+bool dns_service_name_is_valid(const char *name);
+
+int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
+int dns_service_split(const char *joined, char **name, char **type, char **domain);
+
+int dns_name_suffix(const char *name, unsigned n_labels, const char **ret);
+int dns_name_count_labels(const char *name);
+
+int dns_name_skip(const char *a, unsigned n_labels, const char **ret);
+int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
+
+int dns_name_common_suffix(const char *a, const char *b, const char **ret);
+
+int dns_name_apply_idna(const char *name, char **ret);
index 0d44401cc2ed914fd5ad976ea62a0642b9fae0ea..cc1acd6f235e1697f788776bbde19a8173bed91b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
 #include "alloc-util.h"
 #include "conf-files.h"
 #include "dropin.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio-label.h"
+#include "hashmap.h"
+#include "log.h"
+#include "macro.h"
 #include "mkdir.h"
 #include "path-util.h"
+#include "set.h"
 #include "string-util.h"
 #include "strv.h"
-#include "util.h"
+#include "unit-name.h"
 
 int drop_in_file(const char *dir, const char *unit, unsigned level,
                  const char *name, char **_p, char **_q) {
@@ -146,7 +154,7 @@ static int iterate_dir(
 
                 errno = 0;
                 de = readdir(d);
-                if (!de && errno != 0)
+                if (!de && errno > 0)
                         return log_error_errno(errno, "Failed to read directory %s: %m", path);
 
                 if (!de)
index d4531fca2da9c1feec0f4cbbdc0660aedf6ca2b3..c1936f397b44d18627632509ba82ed1378c9deb4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "hashmap.h"
 #include "macro.h"
 #include "set.h"
 #include "unit-name.h"
index 89deeb9b550137001ebb8a61b799a3bd7ae90c90..8631a5a5d9fa4a0eff51a6ac81d25a6b84b93f8f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
+#include "sd-id128.h"
+
 #include "alloc-util.h"
 #include "dirent-util.h"
 #include "efivars.h"
 #include "fd-util.h"
 #include "io-util.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "stdio-util.h"
+#include "time-util.h"
 #include "utf8.h"
 #include "util.h"
 #include "virt.h"
index e953a12737e066caf02eb7749bc80e6f2e031e16..b61d14c4ec161d6c7510ee20b054bd0f267b6116 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 
 #include "sd-id128.h"
+
 #include "time-util.h"
 
 #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
index 5acfb0191b45e7323511e1e294c072fd066b6b0b..0d3da2e6d2e25db96540ac2f08c90fada3f6ed68 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <alloca.h>
 #include <arpa/inet.h>
+#include <endian.h>
+#include <errno.h>
 #include <net/if.h>
-#include <sys/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/socket.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter/nf_nat.h>
 #include <linux/netfilter/xt_addrtype.h>
@@ -29,7 +32,8 @@
 
 #include "alloc-util.h"
 #include "firewall-util.h"
-#include "util.h"
+#include "in-addr-util.h"
+#include "macro.h"
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free);
 
index 93152e3978c9b51abc1c39191b4fe3f0f780783d..c39b34cf8f83c77fa3dbf3facc581e114490928f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+#include <stdint.h>
+
 #include "in-addr-util.h"
 
 #ifdef HAVE_LIBIPTC
index eb2845cddf4f8b4eb23b9db080ad97434853b1e9..a4e0cd32670db599513ddb0d0a0a95c784603964 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "alloc-util.h"
 #include "device-nodes.h"
 #include "fstab-util.h"
+#include "macro.h"
 #include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
index 5ebea4401983ec770e97ce998b847f3778081979..679f6902f79c3d41a75466d52125682e3414433d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 9998c6441605b827dee50226a8d3648fc7706fb4..cd3c35cd5509593b62ae23b4eeb9908ab05949c3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -19,6 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fileio.h"
 #include "fstab-util.h"
 #include "generator.h"
+#include "log.h"
+#include "macro.h"
 #include "mkdir.h"
-#include "mount-util.h"
 #include "path-util.h"
 #include "special.h"
 #include "string-util.h"
+#include "time-util.h"
 #include "unit-name.h"
 #include "util.h"
 
@@ -187,7 +188,6 @@ int generator_write_timeouts(
 
         return write_drop_in_format(dir, unit, 50, "device-timeout",
                                     "# Automatically generated by %s\n\n"
-                                    "[Unit]\nJobTimeoutSec=" USEC_FMT,
-                                    program_invocation_short_name,
-                                    u / USEC_PER_SEC);
+                                    "[Unit]\nJobTimeoutSec=%s",
+                                    program_invocation_short_name, timeout);
 }
index 6c3f38abbae517d19a8ea549672b34d518acbafd..a734e139700bb643b387f65d8d905b835876b2f1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index add1df420f6160da847d1b637e067bed36caf922..52ab29ed5f75b9c1acc1e934b9deb2502f76e666 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -25,7 +23,7 @@
 
 #include "sd-id128.h"
 
-/* We only support root disk discovery for x86, x86-64 and ARM for
+/* We only support root disk discovery for x86, x86-64, Itanium and ARM for
  * now, since EFI for anything else doesn't really exist, and we only
  * care for root partitions on the same disk as the EFI ESP. */
 
@@ -33,6 +31,7 @@
 #define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09)
 #define GPT_ROOT_ARM    SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3)
 #define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae)
+#define GPT_ROOT_IA64   SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97)
 
 #define GPT_ESP         SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b)
 #define GPT_SWAP        SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
 #  define GPT_ROOT_NATIVE GPT_ROOT_X86
 #endif
 
+#if defined(__ia64__)
+#  define GPT_ROOT_NATIVE GPT_ROOT_IA64
+#endif
+
 #if defined(__aarch64__) && (__BYTE_ORDER != __BIG_ENDIAN)
 #  define GPT_ROOT_NATIVE GPT_ROOT_ARM_64
 #  define GPT_ROOT_SECONDARY GPT_ROOT_ARM
index 6c1954bbff28dff4a72fbd962386db882aba09dc..789064d6539f5425fa8bcda9a8bd640ffb596ce3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d38216170624dfcfdf52f3804b293664293707ec..5be94761fdfbdccc7ab43f1fd0780d1a1647f20a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index ddc8c00a2d5644930bd71c919f03fd74ee42a223..ab701ad8b22c41136e18e18b4a99b68a42286dcc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <string.h>
+
 #include "alloc-util.h"
 #include "btrfs-util.h"
 #include "import-util.h"
+#include "log.h"
+#include "macro.h"
 #include "path-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -155,58 +158,6 @@ int raw_strip_suffixes(const char *p, char **ret) {
         return 0;
 }
 
-bool dkr_digest_is_valid(const char *digest) {
-        /* 7 chars for prefix, 64 chars for the digest itself */
-        if (strlen(digest) != 71)
-                return false;
-
-        return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef");
-}
-
-bool dkr_ref_is_valid(const char *ref) {
-        const char *colon;
-
-        if (isempty(ref))
-                return false;
-
-        colon = strchr(ref, ':');
-        if (!colon)
-                return filename_is_valid(ref);
-
-        return dkr_digest_is_valid(ref);
-}
-
-bool dkr_name_is_valid(const char *name) {
-        const char *slash, *p;
-
-        if (isempty(name))
-                return false;
-
-        slash = strchr(name, '/');
-        if (!slash)
-                return false;
-
-        if (!filename_is_valid(slash + 1))
-                return false;
-
-        p = strndupa(name, slash - name);
-        if (!filename_is_valid(p))
-                return false;
-
-        return true;
-}
-
-bool dkr_id_is_valid(const char *id) {
-
-        if (!filename_is_valid(id))
-                return false;
-
-        if (!in_charset(id, "0123456789abcdef"))
-                return false;
-
-        return true;
-}
-
 int import_assign_pool_quota_and_warn(const char *path) {
         int r;
 
index 9120a5119f47739b42586670b0217a054455c0f4..77b17d91f3c66c47829bb226294f4984668bd5ec 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -42,10 +40,4 @@ ImportVerify import_verify_from_string(const char *s) _pure_;
 int tar_strip_suffixes(const char *name, char **ret);
 int raw_strip_suffixes(const char *name, char **ret);
 
-bool dkr_name_is_valid(const char *name);
-bool dkr_id_is_valid(const char *id);
-bool dkr_ref_is_valid(const char *ref);
-bool dkr_digest_is_valid(const char *digest);
-#define dkr_tag_is_valid(tag) filename_is_valid(tag)
-
 int import_assign_pool_quota_and_warn(const char *path);
index 74b909d34d742dc397fb9efd89b987ceb7ae573d..88143361dabe8ea61e9c52244ad04215556671d3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 
-#include "alloc-util.h"
 #include "formats-util.h"
 #include "install-printf.h"
+#include "install.h"
+#include "macro.h"
 #include "specifier.h"
 #include "unit-name.h"
 #include "user-util.h"
-#include "util.h"
 
 static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
         UnitFileInstallInfo *i = userdata;
index 655033782423ded67032616e0971e4e06395296f..acf519f4f75bf143011548c21f4c4ea24aa4e0e5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 17e03e59cd4da58641911b50007d69fc1d73a551..ef8f485cae7d1fd479ef1f8988b2b060b546dd0a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fnmatch.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "conf-files.h"
 #include "conf-parser.h"
 #include "dirent-util.h"
+#include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "hashmap.h"
 #include "install-printf.h"
 #include "install.h"
+#include "log.h"
+#include "macro.h"
 #include "mkdir.h"
 #include "path-lookup.h"
 #include "path-util.h"
@@ -45,7 +52,6 @@
 #include "string-util.h"
 #include "strv.h"
 #include "unit-name.h"
-#include "util.h"
 
 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
 
index 45a417df92af892c28c6d81bfaaf8dd97e5f716b..c1a43e23e70d147a45f5a1b20fc032a5dc8f62c8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -30,7 +28,10 @@ typedef struct UnitFileChange UnitFileChange;
 typedef struct UnitFileList UnitFileList;
 typedef struct UnitFileInstallInfo UnitFileInstallInfo;
 
+#include <stdbool.h>
+
 #include "hashmap.h"
+#include "macro.h"
 #include "path-lookup.h"
 #include "strv.h"
 #include "unit-name.h"
index 0313b0946f38f455dbf90352797ca4c9c76bc3e5..5eb3bd35c79c6e4b5bf6d9b1b52fb352ed0b06d2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <syslog.h>
 #include <time.h>
+#include <unistd.h>
+
+#include "sd-id128.h"
+#include "sd-journal.h"
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "journal-internal.h"
 #include "log.h"
 #include "logs-show.h"
+#include "macro.h"
+#include "output-mode.h"
 #include "parse-util.h"
 #include "process-util.h"
+#include "sparse-endian.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "terminal-util.h"
+#include "time-util.h"
 #include "utf8.h"
 #include "util.h"
 
@@ -70,12 +80,11 @@ static int print_catalog(FILE *f, sd_journal *j) {
 
 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
         size_t fl, nl;
-        void *buf;
+        char *buf;
 
         assert(data);
         assert(field);
         assert(target);
-        assert(target_size);
 
         fl = strlen(field);
         if (length < fl)
@@ -85,16 +94,18 @@ static int parse_field(const void *data, size_t length, const char *field, char
                 return 0;
 
         nl = length - fl;
-        buf = malloc(nl+1);
+        buf = new(char, nl+1);
         if (!buf)
                 return log_oom();
 
         memcpy(buf, (const char*) data + fl, nl);
-        ((char*)buf)[nl] = 0;
+        buf[nl] = 0;
 
         free(*target);
         *target = buf;
-        *target_size = nl;
+
+        if (target_size)
+                *target_size = nl;
 
         return 1;
 }
@@ -403,7 +414,7 @@ static int output_verbose(
         const void *data;
         size_t length;
         _cleanup_free_ char *cursor = NULL;
-        uint64_t realtime;
+        uint64_t realtime = 0;
         char ts[FORMAT_TIMESTAMP_MAX + 7];
         int r;
 
@@ -419,16 +430,15 @@ static int output_verbose(
                 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m");
         else {
                 _cleanup_free_ char *value = NULL;
-                size_t size;
 
-                r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
+                r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, NULL);
                 if (r < 0)
-                        log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
-                else {
-                        r = safe_atou64(value, &realtime);
-                        if (r < 0)
-                                log_debug_errno(r, "Failed to parse realtime timestamp: %m");
-                }
+                        return r;
+                assert(r > 0);
+
+                r = safe_atou64(value, &realtime);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to parse realtime timestamp: %m");
         }
 
         if (r < 0) {
@@ -1241,7 +1251,7 @@ int show_journal_by_unit(
                 bool system_unit,
                 bool *ellipsized) {
 
-        _cleanup_journal_close_ sd_journal*j = NULL;
+        _cleanup_(sd_journal_closep) sd_journal *j = NULL;
         int r;
 
         assert(mode >= 0);
index 569e1faa55acea78237ee278179f09e472c197dc..9765a24ff24bd971de4bb815a0843a7c26f87baa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 ***/
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <sys/types.h>
 
 #include "sd-journal.h"
 
-#include "util.h"
+#include "macro.h"
 #include "output-mode.h"
+#include "time-util.h"
+#include "util.h"
 
 int output_journal(
                 FILE *f,
index 2c1da0a40d51ccc0cef05709633b009afb98244e..ed8a29c5756278a288efdaab8687bd612afadf8e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <linux/fs.h>
-#include <sys/statfs.h>
-
 #include "alloc-util.h"
 #include "btrfs-util.h"
 #include "chattr-util.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
+#include "hashmap.h"
+#include "lockfile-util.h"
+#include "log.h"
+#include "macro.h"
 #include "machine-image.h"
 #include "mkdir.h"
 #include "path-util.h"
@@ -37,7 +44,9 @@
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
+#include "time-util.h"
 #include "utf8.h"
+#include "util.h"
 #include "xattr-util.h"
 
 static const char image_search_path[] =
index f041600fbfb6d1ea9257e000bc5c676b2dcc3251..31b720d50cc5619d93c969b0a0ade9495342d044 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "time-util.h"
-#include "lockfile-util.h"
+#include <stdbool.h>
+#include <stdint.h>
+
 #include "hashmap.h"
+#include "lockfile-util.h"
+#include "macro.h"
+#include "time-util.h"
 
 typedef enum ImageType {
         IMAGE_DIRECTORY,
index 4172a63fd056ddd507fa3fa85515648c0575bcb6..e5674e4137773e84042668d69ef9fab7bbd75c29 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/loop.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/statvfs.h>
-#include <sys/vfs.h>
+#include <unistd.h>
+
+#include "sd-bus-protocol.h"
+#include "sd-bus.h"
 
 #include "alloc-util.h"
 #include "btrfs-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "lockfile-util.h"
+#include "log.h"
 #include "machine-pool.h"
+#include "macro.h"
+#include "missing.h"
 #include "mkdir.h"
 #include "mount-util.h"
 #include "parse-util.h"
@@ -39,7 +53,6 @@
 #include "signal-util.h"
 #include "stat-util.h"
 #include "string-util.h"
-#include "util.h"
 
 #define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL)
 #define VAR_LIB_MACHINES_FREE_MIN (1024UL*1024UL*750UL)
index fe01d3d47c96e6c885481a7b3bd37492217f06a3..40fe5ecb3aa76059978d7ae3877605b12da83a8c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdint.h>
+
 #include "sd-bus.h"
 
 /* Grow the /var/lib/machines directory after each 10MiB written */
diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h
deleted file mode 100644 (file)
index 3657aa5..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <nss.h>
-#include <netdb.h>
-#include <resolv.h>
-#include <pwd.h>
-#include <grp.h>
-
-
-#define NSS_GETHOSTBYNAME_PROTOTYPES(module)            \
-enum nss_status _nss_##module##_gethostbyname4_r(       \
-                const char *name,                       \
-                struct gaih_addrtuple **pat,            \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop,             \
-                int32_t *ttlp) _public_;                \
-enum nss_status _nss_##module##_gethostbyname3_r(       \
-                const char *name,                       \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop,             \
-                int32_t *ttlp,                          \
-                char **canonp) _public_;                \
-enum nss_status _nss_##module##_gethostbyname2_r(       \
-                const char *name,                       \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) _public_;   \
-enum nss_status _nss_##module##_gethostbyname_r(        \
-                const char *name,                       \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) _public_
-
-#define NSS_GETHOSTBYADDR_PROTOTYPES(module)            \
-enum nss_status _nss_##module##_gethostbyaddr2_r(       \
-                const void* addr, socklen_t len,        \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop,             \
-                int32_t *ttlp) _public_;                \
-enum nss_status _nss_##module##_gethostbyaddr_r(        \
-                const void* addr, socklen_t len,        \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) _public_
-
-#define NSS_GETHOSTBYNAME_FALLBACKS(module)             \
-enum nss_status _nss_##module##_gethostbyname2_r(       \
-                const char *name,                       \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) {           \
-        return _nss_##module##_gethostbyname3_r(        \
-                        name,                           \
-                        af,                             \
-                        host,                           \
-                        buffer, buflen,                 \
-                        errnop, h_errnop,               \
-                        NULL,                           \
-                        NULL);                          \
-}                                                       \
-enum nss_status _nss_##module##_gethostbyname_r(        \
-                const char *name,                       \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) {           \
-        enum nss_status ret = NSS_STATUS_NOTFOUND;      \
-                                                        \
-        if (_res.options & RES_USE_INET6)               \
-                ret = _nss_##module##_gethostbyname3_r( \
-                        name,                           \
-                        AF_INET6,                       \
-                        host,                           \
-                        buffer, buflen,                 \
-                        errnop, h_errnop,               \
-                        NULL,                           \
-                        NULL);                          \
-        if (ret == NSS_STATUS_NOTFOUND)                 \
-                ret = _nss_##module##_gethostbyname3_r( \
-                        name,                           \
-                        AF_INET,                        \
-                        host,                           \
-                        buffer, buflen,                 \
-                        errnop, h_errnop,               \
-                        NULL,                           \
-                        NULL);                          \
-       return ret;                                      \
-}                                                       \
-struct __useless_struct_to_allow_trailing_semicolon__
-
-#define NSS_GETHOSTBYADDR_FALLBACKS(module)             \
-enum nss_status _nss_##module##_gethostbyaddr_r(        \
-                const void* addr, socklen_t len,        \
-                int af,                                 \
-                struct hostent *host,                   \
-                char *buffer, size_t buflen,            \
-                int *errnop, int *h_errnop) {           \
-        return _nss_##module##_gethostbyaddr2_r(        \
-                        addr, len,                      \
-                        af,                             \
-                        host,                           \
-                        buffer, buflen,                 \
-                        errnop, h_errnop,               \
-                        NULL);                          \
-}                                                       \
-struct __useless_struct_to_allow_trailing_semicolon__
-
-#define NSS_GETPW_PROTOTYPES(module)                    \
-enum nss_status _nss_##module##_getpwnam_r(             \
-                const char *name,                       \
-                struct passwd *pwd,                     \
-                char *buffer, size_t buflen,            \
-                int *errnop) _public_;                  \
-enum nss_status _nss_mymachines_getpwuid_r(             \
-                uid_t uid,                              \
-                struct passwd *pwd,                     \
-                char *buffer, size_t buflen,            \
-                int *errnop) _public_
-
-#define NSS_GETGR_PROTOTYPES(module)                    \
-enum nss_status _nss_##module##_getgrnam_r(             \
-                const char *name,                       \
-                struct group *gr,                       \
-                char *buffer, size_t buflen,            \
-                int *errnop) _public_;                  \
-enum nss_status _nss_##module##_getgrgid_r(             \
-                gid_t gid,                              \
-                struct group *gr,                       \
-                char *buffer, size_t buflen,            \
-                int *errnop) _public_
index 81d7f05d91e2aaebdac5251ab2af7fcc036afe82..c5470e7c1b1af145c1f39746df8a7ceca3fc4070 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index d149bc1722d5ded57abe0ba202c82b2ab9adb6a0..05b2b15e407366b46087b8524f90f1988bd8914d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/prctl.h>
 #include "copy.h"
 #include "fd-util.h"
 #include "locale-util.h"
+#include "log.h"
 #include "macro.h"
 #include "pager.h"
 #include "process-util.h"
 #include "signal-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
-#include "util.h"
 
 static pid_t pager_pid = 0;
 
index 67446170d0337d7f853d26e6c0c4b30c475be1a3..9fb05796bb085fdd603ca5389c64fd4c65cb771f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 4a82bd18cde3ca86ec6e60bb831b96b9f337a35b..5410620725331167e8800bba9af77e8afdec8799 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -26,6 +24,8 @@
 
 #include "alloc-util.h"
 #include "install.h"
+#include "log.h"
+#include "macro.h"
 #include "path-lookup.h"
 #include "path-util.h"
 #include "string-util.h"
index e35c8d3c046a83dd892a977afa1a286fe5a12bdc..26c83d61111224f4f266260951ff326cc8991fe8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
 #include "macro.h"
 
 typedef struct LookupPaths {
index 2666b8f7e22ffb7fac8f63d1d364fd6ddff58d88..061d31f4de8ef21855bef746bca994043af09aee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <limits.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/epoll.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
 #include <termios.h>
+#include <unistd.h>
+
+#include "sd-event.h"
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "log.h"
+#include "macro.h"
 #include "ptyfwd.h"
-#include "util.h"
+#include "time-util.h"
 
 struct PTYForward {
         sd_event *event;
index 9b3214221bd2990a206ffc00d5b81a845da72278..a046eb4e5e31feb2b28287234a16e2f0e22f11fa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -25,6 +23,8 @@
 
 #include "sd-event.h"
 
+#include "macro.h"
+
 typedef struct PTYForward PTYForward;
 
 typedef enum PTYForwardFlags {
diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c
new file mode 100644 (file)
index 0000000..e2da81b
--- /dev/null
@@ -0,0 +1,39 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "conf-parser.h"
+#include "resolve-util.h"
+#include "string-table.h"
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting");
+
+static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
+        [RESOLVE_SUPPORT_NO] = "no",
+        [RESOLVE_SUPPORT_YES] = "yes",
+        [RESOLVE_SUPPORT_RESOLVE] = "resolve",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES);
+
+static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
+        [DNSSEC_NO] = "no",
+        [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade",
+        [DNSSEC_YES] = "yes",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h
new file mode 100644 (file)
index 0000000..8636a6c
--- /dev/null
@@ -0,0 +1,60 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "macro.h"
+
+typedef enum ResolveSupport ResolveSupport;
+typedef enum DnssecMode DnssecMode;
+
+enum ResolveSupport {
+        RESOLVE_SUPPORT_NO,
+        RESOLVE_SUPPORT_YES,
+        RESOLVE_SUPPORT_RESOLVE,
+        _RESOLVE_SUPPORT_MAX,
+        _RESOLVE_SUPPORT_INVALID = -1
+};
+
+enum DnssecMode {
+        /* No DNSSEC validation is done */
+        DNSSEC_NO,
+
+        /* Validate locally, if the server knows DO, but if not,
+         * don't. Don't trust the AD bit. If the server doesn't do
+         * DNSSEC properly, downgrade to non-DNSSEC operation. Of
+         * course, we then are vulnerable to a downgrade attack, but
+         * that's life and what is configured. */
+        DNSSEC_ALLOW_DOWNGRADE,
+
+        /* Insist on DNSSEC server support, and rather fail than downgrading. */
+        DNSSEC_YES,
+
+        _DNSSEC_MODE_MAX,
+        _DNSSEC_MODE_INVALID = -1
+};
+
+int config_parse_resolve_support(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_dnssec_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+const char* resolve_support_to_string(ResolveSupport p) _const_;
+ResolveSupport resolve_support_from_string(const char *s) _pure_;
+
+const char* dnssec_mode_to_string(DnssecMode p) _const_;
+DnssecMode dnssec_mode_from_string(const char *s) _pure_;
index 09baf51661c3ba5efa5421d89d418304d552751b..cebe0fce2aa1d0a23cb5ef0c40bc18084341ae37 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
 #include <seccomp.h>
+#include <stddef.h>
 
+#include "macro.h"
 #include "seccomp-util.h"
 #include "string-util.h"
-#include "util.h"
 
 const char* seccomp_arch_to_string(uint32_t c) {
 
index 60d97154ec282edfc295aba514594d75dd4d2484..4ed2afc1b235fb82c5081613c5688a671ac6fe13 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,6 +20,7 @@
 ***/
 
 #include <seccomp.h>
+#include <stdint.h>
 
 const char* seccomp_arch_to_string(uint32_t c);
 int seccomp_arch_from_string(const char *n, uint32_t *ret);
index 39b836d0535403c0c598ee8998dd6ecf5627d1c5..a0aef66bc820bc3cac8e6fb95a2b5c1c3842d102 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
 #include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "conf-parser.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "log.h"
+#include "macro.h"
 #include "parse-util.h"
 #include "sleep-config.h"
 #include "string-util.h"
 #include "strv.h"
-#include "util.h"
 
 #define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0)
 
index 5eda18ee3884d0d4f11129c0bc6367ccdd4e714a..51f4621844d26aae453d86b1cc7f6d6584794baa 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3fcea61873bc0eb2a6ff35e61ae43bae3ab22a7d..a46b7525f03226ecc0327ed6908ecf6aa228a85d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 31b4beab585dbac57807453f01f924c8056107cd..fb0749b13f2953d3983c1ab754bc298b5d1f1558 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 8ea6cb830bfc7ea9c1b8849a37749b57179cbf1c..cf3c8ad5a346680961a80a895d5d244a932bf4f0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include "fd-util.h"
 #include "io-util.h"
 #include "log.h"
+#include "macro.h"
 #include "process-util.h"
 #include "spawn-polkit-agent.h"
 #include "stdio-util.h"
+#include "time-util.h"
 #include "util.h"
 
 #ifdef ENABLE_POLKIT
index c3bc1b845e60bf531e9feccbf0868267c71f5634..42b2989ded64719bf9b47063db5f82ff79461834 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index c5c4a4d7d7fad41bde406909cf40c86660aa1344..1c17eb52514490a8caffb4ea77d4b4142e50b237 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/utsname.h>
 
+#include "sd-id128.h"
+
 #include "alloc-util.h"
 #include "hostname-util.h"
 #include "macro.h"
 #include "specifier.h"
 #include "string-util.h"
-#include "util.h"
 
 /*
  * Generic infrastructure for replacing %x style specifiers in
index fca206f665fa7dd5986d4a88ed82823d3964452d..6b1623ee6110d3ba14c935387bbac3bda7e3316c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index fc885f6cb8140f2a79e81f7b16354916215477d7..47d3a5a1fa21a4f92abc336d4bd74953fe68b619 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdbool.h>
-#include <string.h>
+#include <stdio.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include "base-filesystem.h"
 #include "fd-util.h"
+#include "log.h"
 #include "missing.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "rm-rf.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "switch-root.h"
 #include "user-util.h"
@@ -75,7 +76,7 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot,
                 char new_mount[PATH_MAX];
                 struct stat sb;
 
-                snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
+                xsprintf(new_mount, "%s%s", new_root, i);
 
                 mkdir_p_label(new_mount, 0755);
 
index adf893a922e8219b362063d96a49bf382efd39b6..a7a080b3e849bd6a482c987cbb5cf8703d6a5901 100644 (file)
@@ -1,7 +1,6 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
+#include <stdbool.h>
 /***
   This file is part of systemd.
 
index 70caa542e740a6aa047c22650fd0280782b577fd..e1ccb3294c5bd05aa66a85084b06c31bf6acc98c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 #include "fileio.h"
 #include "log.h"
+#include "macro.h"
 #include "string-util.h"
 #include "sysctl-util.h"
-#include "util.h"
 
 char *sysctl_normalize(char *s) {
         char *n;
index 2ee6454e52f282033677a04f537a14da1bae9857..2decb39f5835fbaa63d768366e8b1f8c0c1ac108 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 74f1716fe08ee9af42fc7bd1c6f7bdcd1ceef840..228e51010481c30087f48ea7651f68b066a19e11 100644 (file)
@@ -28,18 +28,25 @@ static inline void _test_table(const char *name,
                                reverse_t reverse,
                                int size,
                                bool sparse) {
-        int i;
+        int i, boring = 0;
 
         for (i = -1; i < size + 1; i++) {
                 const char* val = lookup(i);
                 int rev;
 
-                if (val)
+                if (val) {
                         rev = reverse(val);
-                else
+                        boring = 0;
+                } else {
                         rev = reverse("--no-such--value----");
+                        boring += i >= 0;
+                }
+
+                if (boring < 1 || i == size)
+                        printf("%s: %d → %s → %d\n", name, i, val, rev);
+                else if (boring == 1)
+                        printf("%*s  ...\n", (int) strlen(name), "");
 
-                printf("%s: %d → %s → %d\n", name, i, val, rev);
                 assert_se(!(i >= 0 && i < size ?
                             sparse ? rev != i && rev != -1 : val == NULL || rev != i :
                             val != NULL || rev != -1));
index f758ce13e4ef29bd8f9c8c5903b8a81fe857077d..ca0889f8a6a52f3a9fe47756fd489152e4c984d2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 079dd8752cceead399f81c0e8195ea8312a1848f..eb251492c3719dc91aa2e6b707e53d6dbb9a8bf7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macro.h"
 #include "uid-range.h"
 #include "user-util.h"
-#include "util.h"
 
 static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) {
         assert(range);
index 45335e939fd819aaace61fd13e7bdcc4a5d72f1b..4044eb4c9cd3ce2ff1e9f63f8384e0a117fff86c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
index 13b32a0509b5b6ee33cddc1faae131e87022e993..9750dcd81722f0ba25843e520784b7374f61d398 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <errno.h>
 #include <fcntl.h>
 #include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
 #include <sys/utsname.h>
 #include <unistd.h>
 #include <utmpx.h>
@@ -34,7 +36,9 @@
 #include "path-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
+#include "time-util.h"
 #include "user-util.h"
+#include "util.h"
 #include "utmp-wtmp.h"
 
 int utmp_get_runlevel(int *runlevel, int *previous) {
index e0ceb873ac2a3f3859aa73f51b13a3be7efc13ab..438e270a26b48e215fec54843a46e675fb08d0f1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "time-util.h"
 #include "util.h"
 
 #ifdef HAVE_UTMP
index 7131e94cdb77789b384382c7c0265cadfaf3a98f..4f3e0125f33a0814d3dc190be9a2e2627e8e74fc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <syslog.h>
 #include <unistd.h>
 #include <linux/watchdog.h>
 
 #include "fd-util.h"
 #include "log.h"
+#include "time-util.h"
 #include "watchdog.h"
 
 static int watchdog_fd = -1;
index b748b15857ba4b893bc3a03331cf14df9b92153c..f6ec178ea1cdfb1bfb33f8cf1e47822041391ca5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,6 +19,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
+#include "time-util.h"
 #include "util.h"
 
 int watchdog_set_timeout(usec_t *usec);
index 95de369817382fbd556b23027dfc0226ad5810fc..c8f0742183febdc3053b62b511bc63460571e61d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ba82adadb425601f039ed910dd5c3fd0e55723c7..99d4b62139b8ebc5307dc03a3fc5fd0464f31c41 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -505,7 +503,7 @@ static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdat
                 if (errno != -EAGAIN)
                         log_warning_errno(errno, "Failed to accept() socket: %m");
         } else {
-                getpeername_pretty(nfd, &peer);
+                getpeername_pretty(nfd, true, &peer);
                 log_debug("New connection from %s", strna(peer));
 
                 r = add_connection_socket(context, nfd);
index 25b5ff52eab6a3adff91a52db656c874761edc0a..ce7c26e7d3dc353b548246a61dd65f7bda318936 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 6c2f53774dede2d608497225d3a6d81de10ba961..a3d677f068eb7b46a661de1bd6bc76fdc7cc13ee 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 51b82d57dbf7b44f2e9ec8725deeba82c9496be7..908ccabf8ac0387883ff4e0abd5a57c8eb61f5d5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -247,7 +245,7 @@ static OutputFlags get_output_flags(void) {
                 arg_all * OUTPUT_SHOW_ALL |
                 arg_full * OUTPUT_FULL_WIDTH |
                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
-                on_tty() * OUTPUT_COLOR |
+                colors_enabled() * OUTPUT_COLOR |
                 !arg_quiet * OUTPUT_WARN_CUTOFF;
 }
 
@@ -530,9 +528,9 @@ static int get_unit_list(
                 int c,
                 sd_bus_message **_reply) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         size_t size = c;
         int r;
         UnitInfo u;
@@ -637,7 +635,7 @@ static int get_unit_list_recursive(
                         return log_error_errno(r, "Failed to get machine names: %m");
 
                 STRV_FOREACH(i, machines) {
-                        _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
+                        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
                         int k;
 
                         r = sd_bus_open_system_machine(&container, *i);
@@ -699,7 +697,7 @@ static int get_triggered_units(
                 const char* path,
                 char*** ret) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -725,8 +723,8 @@ static int get_listening(
                 const char* unit_path,
                 char*** listening) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *type, *path;
         int r, n = 0;
 
@@ -962,7 +960,7 @@ static int get_next_elapse(
                 const char *path,
                 dual_timestamp *next) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         dual_timestamp t;
         int r;
 
@@ -1003,7 +1001,7 @@ static int get_last_trigger(
                 const char *path,
                 usec_t *last) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
@@ -1358,7 +1356,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
 }
 
 static int list_unit_files(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ UnitFileList *units = NULL;
         UnitFileList *unit;
         size_t size = 0;
@@ -1404,7 +1402,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
                 assert(c <= n_units);
                 hashmap_free(h);
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 sd_bus *bus;
 
                 r = acquire_bus(BUS_MANAGER, &bus);
@@ -1516,8 +1514,8 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha
                 [DEPENDENCY_BEFORE]  = "Before\0",
         };
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **ret = NULL;
         _cleanup_free_ char *path = NULL;
         int r;
@@ -1742,7 +1740,7 @@ static int compare_machine_info(const void *a, const void *b) {
 }
 
 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
-        _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
         int r;
 
         assert(mi);
@@ -1930,7 +1928,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
 }
 
 static int get_default(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *_path = NULL;
         const char *path;
         int r;
@@ -1942,7 +1940,7 @@ static int get_default(int argc, char *argv[], void *userdata) {
                 path = _path;
 
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 sd_bus *bus;
 
                 r = acquire_bus(BUS_MANAGER, &bus);
@@ -1979,7 +1977,7 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha
 
         for (i = 0; i < n_changes; i++) {
                 if (changes[i].type == UNIT_FILE_SYMLINK)
-                        log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
+                        log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
                 else
                         log_info("Removed symlink %s.", changes[i].path);
         }
@@ -2010,8 +2008,8 @@ static int set_default(int argc, char *argv[], void *userdata) {
                 unit_file_changes_free(changes, n_changes);
                 r = 0;
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 sd_bus *bus;
 
                 polkit_agent_open_if_enabled();
@@ -2128,8 +2126,8 @@ static bool output_show_job(struct job_info *job, char **patterns) {
 }
 
 static int list_jobs(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *name, *type, *state, *job_path, *unit_path;
         _cleanup_free_ struct job_info *jobs = NULL;
         size_t size = 0;
@@ -2200,7 +2198,7 @@ static int cancel_job(int argc, char *argv[], void *userdata) {
                 return r;
 
         STRV_FOREACH(name, strv_skip(argv, 1)) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 uint32_t id;
                 int q;
 
@@ -2228,7 +2226,7 @@ static int cancel_job(int argc, char *argv[], void *userdata) {
 }
 
 static int need_daemon_reload(sd_bus *bus, const char *unit) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *path;
         int b, r;
 
@@ -2324,43 +2322,13 @@ static int unit_find_paths(
         assert(lp);
 
         if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 _cleanup_free_ char *unit = NULL;
-                char *unit_load_error_name, *unit_load_error_message;
 
                 unit = unit_dbus_path_from_name(unit_name);
                 if (!unit)
                         return log_oom();
 
-                if (need_daemon_reload(bus, unit_name) > 0)
-                        warn_unit_file_changed(unit_name);
-
-                r = sd_bus_get_property(
-                                bus,
-                                "org.freedesktop.systemd1",
-                                unit,
-                                "org.freedesktop.systemd1.Unit",
-                                "LoadError",
-                                &error,
-                                &unit_load_error,
-                                "(ss)");
-                if (r < 0)
-                        return log_error_errno(r, "Failed to get LoadError: %s", bus_error_message(&error, r));
-
-                r = sd_bus_message_read(
-                                unit_load_error,
-                                "(ss)",
-                                &unit_load_error_name,
-                                &unit_load_error_message);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                if (!isempty(unit_load_error_name)) {
-                        log_error("Unit %s is not loaded: %s", unit_name, unit_load_error_message);
-                        return 0;
-                }
-
                 r = sd_bus_get_property_string(
                                 bus,
                                 "org.freedesktop.systemd1",
@@ -2440,19 +2408,16 @@ static int unit_find_paths(
 }
 
 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_free_ char *n = NULL, *state = NULL;
-        const char *path;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_free_ char *buf = NULL;
+        const char *path, *state;
         int r;
 
         assert(name);
 
-        r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n);
-        if (r < 0)
-                return log_error_errno(r, "Failed to mangle unit name: %m");
-
-        /* We don't use unit_dbus_path_from_name() directly since we
-         * don't want to load the unit if it isn't loaded. */
+        /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
+         * isn't loaded. */
 
         r = sd_bus_call_method(
                         bus,
@@ -2460,31 +2425,34 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
                         "GetUnit",
-                        NULL,
+                        &error,
                         &reply,
-                        "s", n);
+                        "s", name);
         if (r < 0) {
-                if (!quiet)
-                        puts("unknown");
-                return 0;
-        }
+                if (!sd_bus_error_has_name(&error,  BUS_ERROR_NO_SUCH_UNIT))
+                        return log_error_errno(r, "Failed to retrieve unit: %s", bus_error_message(&error, r));
 
-        r = sd_bus_message_read(reply, "o", &path);
-        if (r < 0)
-                return bus_log_parse_error(r);
+                /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
+                 * considered inactive. */
+                state = "inactive";
 
-        r = sd_bus_get_property_string(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        path,
-                        "org.freedesktop.systemd1.Unit",
-                        "ActiveState",
-                        NULL,
-                        &state);
-        if (r < 0) {
-                if (!quiet)
-                        puts("unknown");
-                return 0;
+        } else {
+                r = sd_bus_message_read(reply, "o", &path);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = sd_bus_get_property_string(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                path,
+                                "org.freedesktop.systemd1.Unit",
+                                "ActiveState",
+                                &error,
+                                &buf);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
+
+                state = buf;
         }
 
         if (!quiet)
@@ -2497,7 +2465,7 @@ static int check_triggering_units(
                 sd_bus *bus,
                 const char *name) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
         _cleanup_strv_free_ char **triggered_by = NULL;
         bool print_warning_label = true;
@@ -2568,6 +2536,7 @@ static const struct {
         { "try-restart",           "TryRestartUnit" },
         { "condrestart",           "TryRestartUnit" },
         { "reload-or-restart",     "ReloadOrRestartUnit" },
+        { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
         { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
         { "condreload",            "ReloadOrTryRestartUnit" },
         { "force-reload",          "ReloadOrTryRestartUnit" }
@@ -2601,7 +2570,7 @@ static int start_unit_one(
                 sd_bus_error *error,
                 BusWaitForJobs *w) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *path;
         int r;
 
@@ -2631,7 +2600,13 @@ static int start_unit_one(
 
                 verb = method_to_verb(method);
 
-                return log_error_errno(r, "Failed to %s %s: %s", verb, name, bus_error_message(error, r));
+                log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
+
+                if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
+                    !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
+                        log_error("See system logs and 'systemctl status %s' for details.", name);
+
+                return r;
         }
 
         r = sd_bus_message_read(reply, "o", &path);
@@ -2680,16 +2655,27 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
         /* Query the manager only if any of the names are a glob, since
          * this is fairly expensive */
         if (!strv_isempty(globs)) {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 _cleanup_free_ UnitInfo *unit_infos = NULL;
+                size_t allocated, n;
 
                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
                 if (r < 0)
                         return r;
 
-                for (i = 0; i < r; i++)
-                        if (strv_extend(&mangled, unit_infos[i].id) < 0)
+                n = strv_length(mangled);
+                allocated = n + 1;
+
+                for (i = 0; i < r; i++) {
+                        if (!GREEDY_REALLOC(mangled, allocated, n+2))
                                 return log_oom();
+
+                        mangled[n] = strdup(unit_infos[i].id);
+                        if (!mangled[n])
+                                return log_oom();
+
+                        mangled[++n] = NULL;
+                }
         }
 
         *ret = mangled;
@@ -2783,7 +2769,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
         }
 
         STRV_FOREACH(name, names) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 int q;
 
                 q = start_unit_one(bus, method, *name, mode, &error, w);
@@ -2794,7 +2780,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
         if (!arg_no_block) {
                 int q;
 
-                q = bus_wait_for_jobs(w, arg_quiet);
+                q = bus_wait_for_jobs(w, arg_quiet, arg_scope != UNIT_FILE_SYSTEM ? "--user" : NULL);
                 if (q < 0)
                         return q;
 
@@ -2810,7 +2796,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
 
 static int logind_set_wall_message(void) {
 #ifdef HAVE_LOGIND
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         _cleanup_free_ char *m = NULL;
         int r;
@@ -2846,7 +2832,7 @@ static int logind_set_wall_message(void) {
  * through PolicyKit */
 static int logind_reboot(enum action a) {
 #ifdef HAVE_LOGIND
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *method, *description;
         sd_bus *bus;
         int r;
@@ -2909,7 +2895,7 @@ static int logind_reboot(enum action a) {
 
 static int logind_check_inhibitors(enum action a) {
 #ifdef HAVE_LOGIND
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **sessions = NULL;
         const char *what, *who, *why, *mode;
         uint32_t uid, pid;
@@ -3025,7 +3011,7 @@ static int logind_check_inhibitors(enum action a) {
 
 static int logind_prepare_firmware_setup(void) {
 #ifdef HAVE_LOGIND
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
 
@@ -3071,7 +3057,7 @@ static int prepare_firmware_setup(void) {
 }
 
 static int set_exit_code(uint8_t code) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
 
@@ -3177,6 +3163,7 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
         sd_bus *bus;
         char **name;
         int r;
+        bool found = false;
 
         r = acquire_bus(BUS_MANAGER, &bus);
         if (r < 0)
@@ -3192,11 +3179,13 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
                 state = check_one_unit(bus, *name, good_states, arg_quiet);
                 if (state < 0)
                         return state;
-                if (state == 0)
-                        r = code;
+                if (state > 0)
+                        found = true;
         }
 
-        return r;
+        /* use the given return code for the case that we won't find
+         * any unit which matches the list */
+        return found ? 0 : code;
 }
 
 static int check_unit_active(int argc, char *argv[], void *userdata) {
@@ -3232,7 +3221,7 @@ static int kill_unit(int argc, char *argv[], void *userdata) {
                 return log_error_errno(r, "Failed to expand names: %m");
 
         STRV_FOREACH(name, names) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 q = sd_bus_call_method(
                                 bus,
@@ -3360,6 +3349,7 @@ typedef struct UnitStatusInfo {
         usec_t inactive_enter_timestamp;
 
         bool need_daemon_reload;
+        bool transient;
 
         /* Service */
         pid_t main_pid;
@@ -3459,7 +3449,7 @@ static void print_status_info(
 
         path = i->source_path ? i->source_path : i->fragment_path;
 
-        if (i->load_error)
+        if (i->load_error != 0)
                 printf("   Loaded: %s%s%s (Reason: %s)\n",
                        on, strna(i->load_state), off, i->load_error);
         else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
@@ -3475,6 +3465,9 @@ static void print_status_info(
                 printf("   Loaded: %s%s%s\n",
                        on, strna(i->load_state), off);
 
+        if (i->transient)
+                printf("Transient: yes\n");
+
         if (!strv_isempty(i->dropin_paths)) {
                 _cleanup_free_ char *dir = NULL;
                 bool last = false;
@@ -3839,6 +3832,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
                         i->condition_result = b;
                 else if (streq(name, "AssertResult"))
                         i->assert_result = b;
+                else if (streq(name, "Transient"))
+                        i->transient = b;
 
                 break;
         }
@@ -4388,8 +4383,8 @@ static int show_one(
                 bool *new_line,
                 bool *ellipsized) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         UnitStatusInfo info = {
                 .memory_current = (uint64_t) -1,
                 .memory_limit = (uint64_t) -1,
@@ -4505,8 +4500,8 @@ static int get_unit_dbus_path_by_pid(
                 uint32_t pid,
                 char **unit) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         char *u;
         int r;
 
@@ -4541,7 +4536,7 @@ static int show_all(
                 bool *new_line,
                 bool *ellipsized) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ UnitInfo *unit_infos = NULL;
         const UnitInfo *u;
         unsigned c;
@@ -4646,8 +4641,7 @@ static int show(int argc, char *argv[], void *userdata) {
                 return -EINVAL;
         }
 
-        if (show_properties)
-                pager_open_if_enabled();
+        pager_open_if_enabled();
 
         if (show_status)
                 /* Increase max number of open files to 16K if we can, we
@@ -4841,8 +4835,8 @@ static int cat(int argc, char *argv[], void *userdata) {
 }
 
 static int set_property(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *n = NULL;
         sd_bus *bus;
         char **i;
@@ -4877,17 +4871,9 @@ static int set_property(int argc, char *argv[], void *userdata) {
                 return bus_log_create_error(r);
 
         STRV_FOREACH(i, strv_skip(argv, 2)) {
-                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
                 r = bus_append_unit_property_assignment(m, *i);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
         }
 
         r = sd_bus_message_close_container(m);
@@ -4902,7 +4888,7 @@ static int set_property(int argc, char *argv[], void *userdata) {
 }
 
 static int daemon_reload(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *method;
         sd_bus *bus;
         int r;
@@ -4976,7 +4962,7 @@ static int reset_failed(int argc, char *argv[], void *userdata) {
                 return log_error_errno(r, "Failed to expand names: %m");
 
         STRV_FOREACH(name, names) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 q = sd_bus_call_method(
                                 bus,
@@ -4998,8 +4984,8 @@ static int reset_failed(int argc, char *argv[], void *userdata) {
 }
 
 static int show_environment(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *text;
         sd_bus *bus;
         int r;
@@ -5039,7 +5025,7 @@ static int show_environment(int argc, char *argv[], void *userdata) {
 }
 
 static int switch_root(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *cmdline_init = NULL;
         const char *root, *init;
         sd_bus *bus;
@@ -5106,8 +5092,8 @@ static int switch_root(int argc, char *argv[], void *userdata) {
 }
 
 static int set_environment(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         const char *method;
         sd_bus *bus;
         int r;
@@ -5147,8 +5133,8 @@ static int set_environment(int argc, char *argv[], void *userdata) {
 }
 
 static int import_environment(int argc, char *argv[], void *userdata) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         sd_bus *bus;
         int r;
 
@@ -5443,8 +5429,8 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
 
                 r = 0;
         } else {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 int expect_carries_install_info = false;
                 bool send_force = true, send_preset_mode = false;
                 const char *method;
@@ -5610,8 +5596,8 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
                 unit_file_changes_free(changes, n_changes);
 
         } else {
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 sd_bus *bus;
 
                 polkit_agent_open_if_enabled();
@@ -5674,8 +5660,8 @@ static int preset_all(int argc, char *argv[], void *userdata) {
                 r = 0;
 
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 sd_bus *bus;
 
                 polkit_agent_open_if_enabled();
@@ -5753,7 +5739,7 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
                 }
 
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 sd_bus *bus;
 
                 r = acquire_bus(BUS_MANAGER, &bus);
@@ -5761,7 +5747,7 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
                         return r;
 
                 STRV_FOREACH(name, names) {
-                        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                         const char *s;
 
                         r = sd_bus_call_method(
@@ -5796,7 +5782,7 @@ static int is_system_running(int argc, char *argv[], void *userdata) {
         sd_bus *bus;
         int r;
 
-        if (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted()) {
+        if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
                 if (!arg_quiet)
                         puts("offline");
                 return EXIT_FAILURE;
@@ -6239,8 +6225,8 @@ static void systemctl_help(void) {
                "  try-restart NAME...             Restart one or more units if active\n"
                "  reload-or-restart NAME...       Reload one or more units if possible,\n"
                "                                  otherwise start or restart\n"
-               "  reload-or-try-restart NAME...   Reload one or more units if possible,\n"
-               "                                  otherwise restart if active\n"
+               "  try-reload-or-restart NAME...   If active, reload one or more units,\n"
+               "                                  if supported, otherwise restart\n"
                "  isolate NAME                    Start one unit and stop all others\n"
                "  kill NAME...                    Send signal to processes of a unit\n"
                "  is-active PATTERN...            Check whether units are active\n"
@@ -6545,8 +6531,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         return version();
 
                 case 't': {
-                        if (isempty(optarg))
-                                return log_error_errno(r, "--type requires arguments.");
+                        if (isempty(optarg)) {
+                                log_error("--type requires arguments.");
+                                return -EINVAL;
+                        }
 
                         p = optarg;
                         for(;;) {
@@ -6778,8 +6766,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_STATE: {
-                        if (isempty(optarg))
-                                return log_error_errno(r, "--signal requires arguments.");
+                        if (isempty(optarg)) {
+                                log_error("--signal requires arguments.");
+                                return -EINVAL;
+                        }
 
                         p = optarg;
                         for(;;) {
@@ -7325,70 +7315,71 @@ static int talk_initctl(void) {
 static int systemctl_main(int argc, char *argv[]) {
 
         static const Verb verbs[] = {
-                { "list-units",            VERB_ANY, VERB_ANY, VERB_DEFAULT, list_units        },
-                { "list-unit-files",       VERB_ANY, VERB_ANY, 0,            list_unit_files   },
-                { "list-sockets",          VERB_ANY, VERB_ANY, 0,            list_sockets      },
-                { "list-timers",           VERB_ANY, VERB_ANY, 0,            list_timers       },
-                { "list-jobs",             VERB_ANY, VERB_ANY, 0,            list_jobs         },
-                { "list-machines",         VERB_ANY, VERB_ANY, 0,            list_machines     },
-                { "clear-jobs",            VERB_ANY, 1,        0,            daemon_reload     },
-                { "cancel",                VERB_ANY, VERB_ANY, 0,            cancel_job        },
-                { "start",                 2,        VERB_ANY, 0,            start_unit        },
-                { "stop",                  2,        VERB_ANY, 0,            start_unit        },
-                { "condstop",              2,        VERB_ANY, 0,            start_unit        }, /* For compatibility with ALTLinux */
-                { "reload",                2,        VERB_ANY, 0,            start_unit        },
-                { "restart",               2,        VERB_ANY, 0,            start_unit        },
-                { "try-restart",           2,        VERB_ANY, 0,            start_unit        },
-                { "reload-or-restart",     2,        VERB_ANY, 0,            start_unit        },
-                { "reload-or-try-restart", 2,        VERB_ANY, 0,            start_unit        },
-                { "force-reload",          2,        VERB_ANY, 0,            start_unit        }, /* For compatibility with SysV */
-                { "condreload",            2,        VERB_ANY, 0,            start_unit        }, /* For compatibility with ALTLinux */
-                { "condrestart",           2,        VERB_ANY, 0,            start_unit        }, /* For compatibility with RH */
-                { "isolate",               2,        2,        0,            start_unit        },
-                { "kill",                  2,        VERB_ANY, 0,            kill_unit         },
-                { "is-active",             2,        VERB_ANY, 0,            check_unit_active },
-                { "check",                 2,        VERB_ANY, 0,            check_unit_active },
-                { "is-failed",             2,        VERB_ANY, 0,            check_unit_failed },
-                { "show",                  VERB_ANY, VERB_ANY, 0,            show              },
-                { "cat",                   2,        VERB_ANY, 0,            cat               },
-                { "status",                VERB_ANY, VERB_ANY, 0,            show              },
-                { "help",                  VERB_ANY, VERB_ANY, 0,            show              },
-                { "daemon-reload",         VERB_ANY, 1,        0,            daemon_reload     },
-                { "daemon-reexec",         VERB_ANY, 1,        0,            daemon_reload     },
-                { "show-environment",      VERB_ANY, 1,        0,            show_environment  },
-                { "set-environment",       2,        VERB_ANY, 0,            set_environment   },
-                { "unset-environment",     2,        VERB_ANY, 0,            set_environment   },
-                { "import-environment",    VERB_ANY, VERB_ANY, 0,            import_environment},
-                { "halt",                  VERB_ANY, 1,        0,            start_special     },
-                { "poweroff",              VERB_ANY, 1,        0,            start_special     },
-                { "reboot",                VERB_ANY, 2,        0,            start_special     },
-                { "kexec",                 VERB_ANY, 1,        0,            start_special     },
-                { "suspend",               VERB_ANY, 1,        0,            start_special     },
-                { "hibernate",             VERB_ANY, 1,        0,            start_special     },
-                { "hybrid-sleep",          VERB_ANY, 1,        0,            start_special     },
-                { "default",               VERB_ANY, 1,        0,            start_special     },
-                { "rescue",                VERB_ANY, 1,        0,            start_special     },
-                { "emergency",             VERB_ANY, 1,        0,            start_special     },
-                { "exit",                  VERB_ANY, 2,        0,            start_special     },
-                { "reset-failed",          VERB_ANY, VERB_ANY, 0,            reset_failed      },
-                { "enable",                2,        VERB_ANY, 0,            enable_unit       },
-                { "disable",               2,        VERB_ANY, 0,            enable_unit       },
-                { "is-enabled",            2,        VERB_ANY, 0,            unit_is_enabled   },
-                { "reenable",              2,        VERB_ANY, 0,            enable_unit       },
-                { "preset",                2,        VERB_ANY, 0,            enable_unit       },
-                { "preset-all",            VERB_ANY, 1,        0,            preset_all        },
-                { "mask",                  2,        VERB_ANY, 0,            enable_unit       },
-                { "unmask",                2,        VERB_ANY, 0,            enable_unit       },
-                { "link",                  2,        VERB_ANY, 0,            enable_unit       },
-                { "switch-root",           2,        VERB_ANY, 0,            switch_root       },
-                { "list-dependencies",     VERB_ANY, 2,        0,            list_dependencies },
-                { "set-default",           2,        2,        0,            set_default       },
-                { "get-default",           VERB_ANY, 1,        0,            get_default,      },
-                { "set-property",          3,        VERB_ANY, 0,            set_property      },
-                { "is-system-running",     VERB_ANY, 1,        0,            is_system_running },
-                { "add-wants",             3,        VERB_ANY, 0,            add_dependency    },
-                { "add-requires",          3,        VERB_ANY, 0,            add_dependency    },
-                { "edit",                  2,        VERB_ANY, 0,            edit              },
+                { "list-units",            VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units },
+                { "list-unit-files",       VERB_ANY, VERB_ANY, 0,             list_unit_files   },
+                { "list-sockets",          VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets      },
+                { "list-timers",           VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers       },
+                { "list-jobs",             VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs         },
+                { "list-machines",         VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines     },
+                { "clear-jobs",            VERB_ANY, 1,        VERB_NOCHROOT, daemon_reload     },
+                { "cancel",                VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job        },
+                { "start",                 2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "stop",                  2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "condstop",              2,        VERB_ANY, VERB_NOCHROOT, start_unit        }, /* For compatibility with ALTLinux */
+                { "reload",                2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "restart",               2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "try-restart",           2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "reload-or-restart",     2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "reload-or-try-restart", 2,        VERB_ANY, VERB_NOCHROOT, start_unit        }, /* For compatbility with old systemctl <= 228 */
+                { "try-reload-or-restart", 2,        VERB_ANY, VERB_NOCHROOT, start_unit        },
+                { "force-reload",          2,        VERB_ANY, VERB_NOCHROOT, start_unit        }, /* For compatibility with SysV */
+                { "condreload",            2,        VERB_ANY, VERB_NOCHROOT, start_unit        }, /* For compatibility with ALTLinux */
+                { "condrestart",           2,        VERB_ANY, VERB_NOCHROOT, start_unit        }, /* For compatibility with RH */
+                { "isolate",               2,        2,        VERB_NOCHROOT, start_unit        },
+                { "kill",                  2,        VERB_ANY, VERB_NOCHROOT, kill_unit         },
+                { "is-active",             2,        VERB_ANY, VERB_NOCHROOT, check_unit_active },
+                { "check",                 2,        VERB_ANY, VERB_NOCHROOT, check_unit_active },
+                { "is-failed",             2,        VERB_ANY, VERB_NOCHROOT, check_unit_failed },
+                { "show",                  VERB_ANY, VERB_ANY, VERB_NOCHROOT, show              },
+                { "cat",                   2,        VERB_ANY, VERB_NOCHROOT, cat               },
+                { "status",                VERB_ANY, VERB_ANY, VERB_NOCHROOT, show              },
+                { "help",                  VERB_ANY, VERB_ANY, VERB_NOCHROOT, show              },
+                { "daemon-reload",         VERB_ANY, 1,        VERB_NOCHROOT, daemon_reload     },
+                { "daemon-reexec",         VERB_ANY, 1,        VERB_NOCHROOT, daemon_reload     },
+                { "show-environment",      VERB_ANY, 1,        VERB_NOCHROOT, show_environment  },
+                { "set-environment",       2,        VERB_ANY, VERB_NOCHROOT, set_environment   },
+                { "unset-environment",     2,        VERB_ANY, VERB_NOCHROOT, set_environment   },
+                { "import-environment",    VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment},
+                { "halt",                  VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "poweroff",              VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "reboot",                VERB_ANY, 2,        VERB_NOCHROOT, start_special     },
+                { "kexec",                 VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "suspend",               VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "hibernate",             VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "hybrid-sleep",          VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "default",               VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "rescue",                VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "emergency",             VERB_ANY, 1,        VERB_NOCHROOT, start_special     },
+                { "exit",                  VERB_ANY, 2,        VERB_NOCHROOT, start_special     },
+                { "reset-failed",          VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed      },
+                { "enable",                2,        VERB_ANY, 0,             enable_unit       },
+                { "disable",               2,        VERB_ANY, 0,             enable_unit       },
+                { "is-enabled",            2,        VERB_ANY, 0,             unit_is_enabled   },
+                { "reenable",              2,        VERB_ANY, 0,             enable_unit       },
+                { "preset",                2,        VERB_ANY, 0,             enable_unit       },
+                { "preset-all",            VERB_ANY, 1,        0,             preset_all        },
+                { "mask",                  2,        VERB_ANY, 0,             enable_unit       },
+                { "unmask",                2,        VERB_ANY, 0,             enable_unit       },
+                { "link",                  2,        VERB_ANY, 0,             enable_unit       },
+                { "switch-root",           2,        VERB_ANY, VERB_NOCHROOT, switch_root       },
+                { "list-dependencies",     VERB_ANY, 2,        VERB_NOCHROOT, list_dependencies },
+                { "set-default",           2,        2,        0,             set_default       },
+                { "get-default",           VERB_ANY, 1,        0,             get_default,      },
+                { "set-property",          3,        VERB_ANY, VERB_NOCHROOT, set_property      },
+                { "is-system-running",     VERB_ANY, 1,        0,             is_system_running },
+                { "add-wants",             3,        VERB_ANY, 0,             add_dependency    },
+                { "add-requires",          3,        VERB_ANY, 0,             add_dependency    },
+                { "edit",                  2,        VERB_ANY, VERB_NOCHROOT, edit              },
                 {}
         };
 
@@ -7470,7 +7461,7 @@ static int halt_now(enum action a) {
 static int logind_schedule_shutdown(void) {
 
 #ifdef HAVE_LOGIND
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char date[FORMAT_TIMESTAMP_MAX];
         const char *action;
         sd_bus *bus;
@@ -7598,7 +7589,7 @@ static int runlevel_main(void) {
 
 static int logind_cancel_shutdown(void) {
 #ifdef HAVE_LOGIND
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
 
@@ -7642,7 +7633,7 @@ int main(int argc, char*argv[]) {
         if (r <= 0)
                 goto finish;
 
-        if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
+        if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
                 log_info("Running in chroot, ignoring request.");
                 r = 0;
                 goto finish;
index 896a027eb5027a32f1d28a629455518fce60b3d6..2d4e1f26e1ebfe92c55fb56af52573f7fd221127 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdcommonhfoo
 #define foosdcommonhfoo
 
 #  ifdef __cplusplus
 #    define _SD_BEGIN_DECLARATIONS                              \
         extern "C" {                                            \
-        struct __useless_struct_to_allow_trailing_semicolon__
+        struct _sd_useless_struct_to_allow_trailing_semicolon_
 #  else
 #    define _SD_BEGIN_DECLARATIONS                              \
-        struct __useless_struct_to_allow_trailing_semicolon__
+        struct _sd_useless_struct_to_allow_trailing_semicolon_
 #  endif
 #endif
 
 #  ifdef __cplusplus
 #    define _SD_END_DECLARATIONS                                \
         }                                                       \
-        struct __useless_struct_to_allow_trailing_semicolon__
+        struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_
 #  else
 #    define _SD_END_DECLARATIONS                                \
-        struct __useless_struct_to_allow_trailing_semicolon__
+        struct _sd_useless_struct_to_allow_trailing_semicolon_
 #  endif
 #endif
 
+#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func)             \
+        static inline void func##p(type **p) {                  \
+                if (*p)                                         \
+                        func(*p);                               \
+        }                                                       \
+        struct _sd_useless_struct_to_allow_trailing_semicolon_
+
 #endif
index 5185a48b31ea422bfcf01ad415c489f5103c0711..47b256d5b9f2246ce5141ff9da2654e1f800f943 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdbusprotocolhfoo
 #define foosdbusprotocolhfoo
 
index c5d05a2db29283ea968c85dc98be1cae3427b1ed..6ad6d519796d1d48c38a0db65e85c0c779842706 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdbusvtablehfoo
 #define foosdbusvtablehfoo
 
index 43cf247cdfdd29260f45daf88801f5f6b49ad11f..2a2ef0eb987c31984f1e3e7e0d6b480590dd8dfe 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdbushfoo
 #define foosdbushfoo
 
@@ -27,8 +25,9 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 
-#include "sd-id128.h"
 #include "sd-event.h"
+#include "sd-id128.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -444,6 +443,14 @@ const char* sd_bus_track_contains(sd_bus_track *track, const char *names);
 const char* sd_bus_track_first(sd_bus_track *track);
 const char* sd_bus_track_next(sd_bus_track *track);
 
+/* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_slot, sd_bus_slot_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_message, sd_bus_message_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_creds, sd_bus_creds_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_track, sd_bus_track_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 214e77cab14e95c43c12b0485b66bc8302f6c054..e6787b0a64cd95ddebdf5eedc81e1473a66247f2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddaemonhfoo
 #define foosddaemonhfoo
 
@@ -22,8 +20,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
index fc117258213499350c0ebcce6d3888c980e3ef17..5bfca6ececabb36252211d82b168517b50811047 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddevicehfoo
 #define foosddevicehfoo
 
@@ -23,8 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
@@ -94,6 +92,9 @@ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const c
 int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent);
 int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device, sd_device_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device_enumerator, sd_device_enumerator_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index c0146158f3798fa1909652993bfb57d3466232d7..2b865a80e1c3c820dd4c80009a65411ced7c4c3a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcpclienthfoo
 #define foosddhcpclienthfoo
 
@@ -27,8 +25,8 @@
 #include <netinet/in.h>
 #include <sys/types.h>
 
-#include "sd-event.h"
 #include "sd-dhcp-lease.h"
+#include "sd-event.h"
 
 #include "_sd-common.h"
 
@@ -42,6 +40,48 @@ enum {
         SD_DHCP_CLIENT_EVENT_RENEW              = 4,
 };
 
+enum {
+        SD_DHCP_OPTION_PAD                         = 0,
+        SD_DHCP_OPTION_SUBNET_MASK                 = 1,
+        SD_DHCP_OPTION_TIME_OFFSET                 = 2,
+        SD_DHCP_OPTION_ROUTER                      = 3,
+        SD_DHCP_OPTION_DOMAIN_NAME_SERVER          = 6,
+        SD_DHCP_OPTION_HOST_NAME                   = 12,
+        SD_DHCP_OPTION_BOOT_FILE_SIZE              = 13,
+        SD_DHCP_OPTION_DOMAIN_NAME                 = 15,
+        SD_DHCP_OPTION_ROOT_PATH                   = 17,
+        SD_DHCP_OPTION_ENABLE_IP_FORWARDING        = 19,
+        SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL     = 20,
+        SD_DHCP_OPTION_POLICY_FILTER               = 21,
+        SD_DHCP_OPTION_INTERFACE_MDR               = 22,
+        SD_DHCP_OPTION_INTERFACE_TTL               = 23,
+        SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
+        SD_DHCP_OPTION_INTERFACE_MTU               = 26,
+        SD_DHCP_OPTION_BROADCAST                   = 28,
+        SD_DHCP_OPTION_STATIC_ROUTE                = 33,
+        SD_DHCP_OPTION_NTP_SERVER                  = 42,
+        SD_DHCP_OPTION_VENDOR_SPECIFIC             = 43,
+        SD_DHCP_OPTION_REQUESTED_IP_ADDRESS        = 50,
+        SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME       = 51,
+        SD_DHCP_OPTION_OVERLOAD                    = 52,
+        SD_DHCP_OPTION_MESSAGE_TYPE                = 53,
+        SD_DHCP_OPTION_SERVER_IDENTIFIER           = 54,
+        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST      = 55,
+        SD_DHCP_OPTION_ERROR_MESSAGE               = 56,
+        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE        = 57,
+        SD_DHCP_OPTION_RENEWAL_T1_TIME             = 58,
+        SD_DHCP_OPTION_REBINDING_T2_TIME           = 59,
+        SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,
+        SD_DHCP_OPTION_CLIENT_IDENTIFIER           = 61,
+        SD_DHCP_OPTION_FQDN                        = 81,
+        SD_DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
+        SD_DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
+        SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
+        SD_DHCP_OPTION_PRIVATE_BASE                = 224,
+        SD_DHCP_OPTION_PRIVATE_LAST                = 254,
+        SD_DHCP_OPTION_END                         = 255,
+};
+
 typedef struct sd_dhcp_client sd_dhcp_client;
 
 typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,
@@ -49,7 +89,6 @@ typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,
 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
                                 void *userdata);
 
-
 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
                                        const struct in_addr *last_address);
@@ -78,6 +117,8 @@ int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int pri
 int sd_dhcp_client_detach_event(sd_dhcp_client *client);
 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 38222594e7bd90d18eede4e6d3e7588e5bd6b079..2f565ca825a30ba718ed2572bcc99732526b4d47 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcpleasehfoo
 #define foosddhcpleasehfoo
 
@@ -33,7 +31,7 @@
 _SD_BEGIN_DECLARATIONS;
 
 typedef struct sd_dhcp_lease sd_dhcp_lease;
-struct sd_dhcp_route;
+typedef struct sd_dhcp_route sd_dhcp_route;
 
 sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease);
 sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
@@ -53,11 +51,17 @@ 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_hostname(sd_dhcp_lease *lease, const char **hostname);
 int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes);
+int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes);
 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
 int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
 int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
 
+int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
+int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
+int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 55bceb1ea59a8d57ee957f89fa1c92fe2b8a383e..8658197e80f29701aea630a6d0433bd7fa0ac5b2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcpserverhfoo
 #define foosddhcpserverhfoo
 
@@ -27,6 +25,7 @@
 #include <netinet/in.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -58,6 +57,8 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
 
 int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 0ca6c07de4fae2ed4f80f616753130f897c06faf..9608060830b775af6dd8c0f5126d0e7baef1985b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcp6clienthfoo
 #define foosddhcp6clienthfoo
 
@@ -26,8 +24,8 @@
 #include <net/ethernet.h>
 #include <sys/types.h>
 
-#include "sd-event.h"
 #include "sd-dhcp6-lease.h"
+#include "sd-event.h"
 
 #include "_sd-common.h"
 
@@ -41,6 +39,41 @@ enum {
         SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST       = 13,
 };
 
+enum {
+        SD_DHCP6_OPTION_CLIENTID                   = 1,
+        SD_DHCP6_OPTION_SERVERID                   = 2,
+        SD_DHCP6_OPTION_IA_NA                      = 3,
+        SD_DHCP6_OPTION_IA_TA                      = 4,
+        SD_DHCP6_OPTION_IAADDR                     = 5,
+        SD_DHCP6_OPTION_ORO                        = 6,
+        SD_DHCP6_OPTION_PREFERENCE                 = 7,
+        SD_DHCP6_OPTION_ELAPSED_TIME               = 8,
+        SD_DHCP6_OPTION_RELAY_MSG                  = 9,
+        /* option code 10 is unassigned */
+        SD_DHCP6_OPTION_AUTH                       = 11,
+        SD_DHCP6_OPTION_UNICAST                    = 12,
+        SD_DHCP6_OPTION_STATUS_CODE                = 13,
+        SD_DHCP6_OPTION_RAPID_COMMIT               = 14,
+        SD_DHCP6_OPTION_USER_CLASS                 = 15,
+        SD_DHCP6_OPTION_VENDOR_CLASS               = 16,
+        SD_DHCP6_OPTION_VENDOR_OPTS                = 17,
+        SD_DHCP6_OPTION_INTERFACE_ID               = 18,
+        SD_DHCP6_OPTION_RECONF_MSG                 = 19,
+        SD_DHCP6_OPTION_RECONF_ACCEPT              = 20,
+
+        SD_DHCP6_OPTION_DNS_SERVERS                = 23,  /* RFC 3646 */
+        SD_DHCP6_OPTION_DOMAIN_LIST                = 24,  /* RFC 3646 */
+
+        SD_DHCP6_OPTION_SNTP_SERVERS               = 31,  /* RFC 4075, deprecated */
+
+        /* option code 35 is unassigned */
+
+        SD_DHCP6_OPTION_NTP_SERVER                 = 56,  /* RFC 5908 */
+
+        /* option codes 89-142 are unassigned */
+        /* option codes 144-65535 are unassigned */
+};
+
 typedef struct sd_dhcp6_client sd_dhcp6_client;
 
 typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event,
@@ -72,6 +105,8 @@ sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
 sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client);
 int sd_dhcp6_client_new(sd_dhcp6_client **ret);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_client, sd_dhcp6_client_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 3fc0ee4bed3719617634d6e4eabe2166ff2ffeb8..184fbb8e0d8cfdc45a36b80489a251d5e882af73 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosddhcp6leasehfoo
 #define foosddhcp6leasehfoo
 
@@ -47,6 +45,8 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn);
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_lease, sd_dhcp6_lease_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 565de5495aebdfc768cfc369cc1ea8205393ead7..1ea97e47f88fcbea897868ae2b5b05065563c29e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdeventhfoo
 #define foosdeventhfoo
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
-#include <sys/signalfd.h>
-#include <sys/epoll.h>
 #include <inttypes.h>
 #include <signal.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
@@ -56,7 +54,8 @@ enum {
         SD_EVENT_PENDING,
         SD_EVENT_RUNNING,
         SD_EVENT_EXITING,
-        SD_EVENT_FINISHED
+        SD_EVENT_FINISHED,
+        SD_EVENT_PREPARING,
 };
 
 enum {
@@ -87,9 +86,9 @@ int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callb
 int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
 
 int sd_event_prepare(sd_event *e);
-int sd_event_wait(sd_event *e, uint64_t timeout);
+int sd_event_wait(sd_event *e, uint64_t usec);
 int sd_event_dispatch(sd_event *e);
-int sd_event_run(sd_event *e, uint64_t timeout);
+int sd_event_run(sd_event *e, uint64_t usec);
 int sd_event_loop(sd_event *e);
 int sd_event_exit(sd_event *e, int code);
 
@@ -130,6 +129,10 @@ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);
 int sd_event_source_get_signal(sd_event_source *s);
 int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
 
+/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 49269a073ae1ffa27115b95e3c4a7e3215be89a0..7105920492394fd0b7aec4a63f47dd38c93da0fe 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdhwdbhfoo
 #define foosdhwdbhfoo
 
@@ -44,6 +42,8 @@ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value);
         if (sd_hwdb_seek(hwdb, modalias) < 0) { }                       \
         else while (sd_hwdb_enumerate(hwdb, &(key), &(value)) > 0)
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_hwdb, sd_hwdb_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 9f445278bbf6481399ca9c16d736893bd46c00f6..a3bf5897b81d0cefadfe5c8a288032a53c7e11a7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdid128hfoo
 #define foosdid128hfoo
 
index 6337d614525046d624736e0c4e2ae5421d75bc8a..3a2219c82c9a9d61cee82b986f5847f3c8a5f3d5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdipv4acdfoo
 #define foosdipv4acdfoo
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <netinet/in.h>
 #include <net/ethernet.h>
+#include <netinet/in.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -52,7 +51,9 @@ int sd_ipv4acd_start(sd_ipv4acd *ll);
 int sd_ipv4acd_stop(sd_ipv4acd *ll);
 sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll);
 sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll);
-int sd_ipv4acd_new (sd_ipv4acd **ret);
+int sd_ipv4acd_new(sd_ipv4acd **ret);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref);
 
 _SD_END_DECLARATIONS;
 
index 2949f1dfb284de3ce7ba61ac10f11d2cb7a1cdf1..67c566fe0d2b0dab38412ce1879243ca892eaeb0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdipv4llfoo
 #define foosdipv4llfoo
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <netinet/in.h>
 #include <net/ethernet.h>
+#include <netinet/in.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -54,6 +53,8 @@ sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll);
 sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll);
 int sd_ipv4ll_new (sd_ipv4ll **ret);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 00237a21589f9d7715aa1117666ba0f281db6368..abb9eca57689295beeed2f8eae316e1304299aba 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdjournalhfoo
 #define foosdjournalhfoo
 
 ***/
 
 #include <inttypes.h>
-#include <sys/types.h>
 #include <stdarg.h>
+#include <sys/types.h>
 #include <sys/uio.h>
 #include <syslog.h>
 
 #include "sd-id128.h"
+
 #include "_sd-common.h"
 
 /* Journal APIs. See sd-journal(3) for more information. */
@@ -128,6 +127,9 @@ int sd_journal_query_unique(sd_journal *j, const char *field);
 int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l);
 void sd_journal_restart_unique(sd_journal *j);
 
+int sd_journal_enumerate_fields(sd_journal *j, const char **field);
+void sd_journal_restart_fields(sd_journal *j);
+
 int sd_journal_get_fd(sd_journal *j);
 int sd_journal_get_events(sd_journal *j);
 int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec);
@@ -138,22 +140,33 @@ int sd_journal_reliable_fd(sd_journal *j);
 int sd_journal_get_catalog(sd_journal *j, char **text);
 int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
 
-/* the inverse condition avoids ambiguity of danling 'else' after the macro */
+int sd_journal_has_runtime_files(sd_journal *j);
+int sd_journal_has_persistent_files(sd_journal *j);
+
+/* The inverse condition avoids ambiguity of dangling 'else' after the macro */
 #define SD_JOURNAL_FOREACH(j)                                           \
         if (sd_journal_seek_head(j) < 0) { }                            \
         else while (sd_journal_next(j) > 0)
 
-/* the inverse condition avoids ambiguity of danling 'else' after the macro */
+/* The inverse condition avoids ambiguity of dangling 'else' after the macro */
 #define SD_JOURNAL_FOREACH_BACKWARDS(j)                                 \
         if (sd_journal_seek_tail(j) < 0) { }                            \
         else while (sd_journal_previous(j) > 0)
 
+/* Iterate through the data fields of the current journal entry */
 #define SD_JOURNAL_FOREACH_DATA(j, data, l)                             \
         for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
 
+/* Iterate through the all known values of a specific field */
 #define SD_JOURNAL_FOREACH_UNIQUE(j, data, l)                           \
         for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; )
 
+/* Iterate through all known field names */
+#define SD_JOURNAL_FOREACH_FIELD(j, field) \
+        for (sd_journal_restart_fields(j); sd_journal_enumerate_fields((j), &(field)) > 0; )
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_journal, sd_journal_close);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 31651ce132f2af0c7dcb77b70ed0a62eea119551..ea952ef187b02506c6174e00da9c788f9e32a63b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdlldphfoo
 #define foosdlldphfoo
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <net/ethernet.h>
 #include <inttypes.h>
+#include <net/ethernet.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -47,7 +46,7 @@ typedef struct sd_lldp_packet sd_lldp_packet;
 typedef void (*sd_lldp_cb_t)(sd_lldp *lldp, int event, void *userdata);
 
 int sd_lldp_new(int ifindex, const char *ifname, const struct ether_addr *mac, sd_lldp **ret);
-void sd_lldp_free(sd_lldp *lldp);
+sd_lldp* sd_lldp_unref(sd_lldp *lldp);
 
 int sd_lldp_start(sd_lldp *lldp);
 int sd_lldp_stop(sd_lldp *lldp);
@@ -80,6 +79,9 @@ int sd_lldp_packet_get_destination_type(sd_lldp_packet *tlv, int *dest);
 
 int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_packet, sd_lldp_packet_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 59c6eedcda5f6702dca85b3e8d8e6dd78aec979d..3c10ff032fe7cab39b50df3f26eee52f0a3397ad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdloginhfoo
 #define foosdloginhfoo
 
@@ -22,8 +20,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
@@ -240,6 +238,8 @@ int sd_login_monitor_get_events(sd_login_monitor *m);
 /* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */
 int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_login_monitor, sd_login_monitor_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 8aedaec6d1b69101fbb70e7cfd7d919f8b539f59..8a72576ec8327ae9d69c38e10dab2985293e646d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdmessageshfoo
 #define foosdmessageshfoo
 
@@ -23,6 +21,7 @@
 ***/
 
 #include "sd-id128.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -85,6 +84,10 @@ _SD_BEGIN_DECLARATIONS;
 
 #define SD_MESSAGE_BOOTCHART        SD_ID128_MAKE(9f,26,aa,56,2c,f4,40,c2,b1,6c,77,3d,04,79,b5,18)
 
+#define SD_MESSAGE_DNSSEC_FAILURE   SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d)
+#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65)
+#define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57)
+
 _SD_END_DECLARATIONS;
 
 #endif
index 80e24325f7dc263712d9099bf843f6f8c42158da..762947531dfbb7a9e627265f4b8820f6a8ba29dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdndiscfoo
 #define foosdndiscfoo
 
@@ -26,6 +24,7 @@
 #include <net/ethernet.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -78,6 +77,8 @@ int sd_ndisc_router_discovery_start(sd_ndisc *nd);
         be16toh((address).s6_addr16[6]),        \
         be16toh((address).s6_addr16[7])
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 2960deda0a4a8b107644b057ac241a129aab0a1a..b4798d2476ca91caba5bb5582210f74a78f3058f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdnetlinkhfoo
 #define foosdnetlinkhfoo
 
 ***/
 
 #include <inttypes.h>
-#include <netinet/in.h>
 #include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/rtnetlink.h>
 #include <linux/neighbour.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -73,6 +72,7 @@ int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type);
 int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data);
 int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data);
 int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data);
+int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len);
 int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data);
 int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data);
 int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data);
@@ -153,6 +153,9 @@ 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);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 4179015fbfd068f3e52a48929e8c752d0b0e750e..e20d12c44dd5887480473644cfd89386c99a01e7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdnetworkhfoo
 #define foosdnetworkhfoo
 
@@ -23,8 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
 #include <inttypes.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
@@ -64,8 +62,11 @@ int sd_network_get_dns(char ***dns);
  * representations of IP addresses */
 int sd_network_get_ntp(char ***ntp);
 
-/* Get the search/routing domains for all links. */
-int sd_network_get_domains(char ***domains);
+/* Get the search domains for all links. */
+int sd_network_get_search_domains(char ***domains);
+
+/* Get the search domains for all links. */
+int sd_network_get_route_domains(char ***domains);
 
 /* Get setup state from ifindex.
  * Possible states:
@@ -111,10 +112,34 @@ int sd_network_link_get_ntp(int ifindex, char ***addr);
  */
 int sd_network_link_get_llmnr(int ifindex, char **llmnr);
 
+/* Indicates whether or not MulticastDNS should be enabled for the
+ * link.
+ * Possible levels of support: yes, no, resolve
+ * Possible return codes:
+ *   -ENODATA: networkd is not aware of the link
+ */
+int sd_network_link_get_mdns(int ifindex, char **mdns);
+
+/* Indicates whether or not DNSSEC should be enabled for the link
+ * Possible levels of support: yes, no, allow-downgrade
+ * Possible return codes:
+ *   -ENODATA: networkd is not aware of the link
+ */
+int sd_network_link_get_dnssec(int ifindex, char **dnssec);
+
+/* Returns the list of per-interface DNSSEC negative trust anchors
+ * Possible return codes:
+ *   -ENODATA: networkd is not aware of the link, or has no such data
+ */
+int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta);
+
 int sd_network_link_get_lldp(int ifindex, char **lldp);
 
-/* Get the DNS domain names for a given link. */
-int sd_network_link_get_domains(int ifindex, char ***domains);
+/* Get the search DNS domain names for a given link. */
+int sd_network_link_get_search_domains(int ifindex, char ***domains);
+
+/* Get the route DNS domain names for a given link. */
+int sd_network_link_get_route_domains(int ifindex, char ***domains);
 
 /* Get the CARRIERS to which current link is bound to. */
 int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
@@ -125,10 +150,6 @@ int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
 /* Get the timezone that was learnt on a specific link. */
 int sd_network_link_get_timezone(int ifindex, char **timezone);
 
-/* Returns whether or not domains that don't match any link should be resolved
- * on this link. 1 for yes, 0 for no and negative value for error */
-int sd_network_link_get_wildcard_domain(int ifindex);
-
 /* Monitor object */
 typedef struct sd_network_monitor sd_network_monitor;
 
@@ -150,6 +171,8 @@ int sd_network_monitor_get_events(sd_network_monitor *m);
 /* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */
 int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_network_monitor, sd_network_monitor_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 32803036332fd83f5b844f3a04f81182cd081203..be6abdcd03efb82220580a2aa43ff01410752717 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdpathhfoo
 #define foosdpathhfoo
 
index 82c4b39efe1ab3434b5143f9955737f075456772..903b917f70162abec62743df24b56e0b4d57b0dc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdresolvehfoo
 #define foosdresolvehfoo
 
@@ -28,6 +26,7 @@
 #include <sys/types.h>
 
 #include "sd-event.h"
+
 #include "_sd-common.h"
 
 _SD_BEGIN_DECLARATIONS;
@@ -43,9 +42,9 @@ typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, co
 typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
 
 enum {
-        SD_RESOLVE_GET_HOST = 1ULL,
-        SD_RESOLVE_GET_SERVICE = 2ULL,
-        SD_RESOLVE_GET_BOTH = 3ULL
+        SD_RESOLVE_GET_HOST = UINT64_C(1),
+        SD_RESOLVE_GET_SERVICE = UINT64_C(2),
+        SD_RESOLVE_GET_BOTH = UINT64_C(3),
 };
 
 int sd_resolve_default(sd_resolve **ret);
@@ -110,6 +109,9 @@ void *sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata);
 
 sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q);
 
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve, sd_resolve_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve_query, sd_resolve_query_unref);
+
 _SD_END_DECLARATIONS;
 
 #endif
index 205ee42213b9456ed02dea574580ac103257ff70..67819838787d2e74d544215375794897ab57dcb5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #ifndef foosdutf8hfoo
 #define foosdutf8hfoo
 
index 675f94906b2dd89eae7e22ae82ada54ff972fe00..863c6283236fb5259fd2f2c698c81a7061f5f327 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -280,7 +278,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) {
 
                         errno = 0;
                         if (putgrent(&t, group) != 0)
-                                return errno ? -errno : -EIO;
+                                return errno > 0 ? -errno : -EIO;
 
                         return 1;
                 }
@@ -288,7 +286,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) {
 
         errno = 0;
         if (putgrent(gr, group) != 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
@@ -330,7 +328,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
 
                         errno = 0;
                         if (putsgent(&t, gshadow) != 0)
-                                return errno ? -errno : -EIO;
+                                return errno > 0 ? -errno : -EIO;
 
                         return 1;
                 }
@@ -338,7 +336,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
 
         errno = 0;
         if (putsgent(sg, gshadow) != 0)
-                return errno ? -errno : -EIO;
+                return errno > 0 ? -errno : -EIO;
 
         return 0;
 }
@@ -410,11 +408,13 @@ static int write_files(void) {
 
                                 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 (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;
                                 }
@@ -482,6 +482,7 @@ static int write_files(void) {
 
                                 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;
                                 }
@@ -548,11 +549,13 @@ static int write_files(void) {
 
                                 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;
                                 }
 
                                 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;
                                 }
index 50755485070021a4b5bc0392ffc4b61d2f2a7c02..5a6818a79d72d05cdf4cc83c81602c16051b18e8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -161,7 +159,6 @@ static int add_alias(const char *service, const char *alias) {
 }
 
 static int generate_unit_file(SysvStub *s) {
-        _cleanup_free_ char *before = NULL, *after = NULL, *wants = NULL, *conflicts = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         const char *unit;
         char **p;
@@ -174,14 +171,6 @@ static int generate_unit_file(SysvStub *s) {
 
         unit = strjoina(arg_dest, "/", s->name);
 
-        before = strv_join(s->before, " ");
-        after = strv_join(s->after, " ");
-        wants = strv_join(s->wants, " ");
-        conflicts = strv_join(s->conflicts, " ");
-
-        if (!before || !after || !wants || !conflicts)
-                return log_oom();
-
         /* We might already have a symlink with the same name from a Provides:,
          * or from backup files like /etc/init.d/foo.bak. Real scripts always win,
          * so remove an existing link */
@@ -204,14 +193,14 @@ static int generate_unit_file(SysvStub *s) {
         if (s->description)
                 fprintf(f, "Description=%s\n", s->description);
 
-        if (!isempty(before))
-                fprintf(f, "Before=%s\n", before);
-        if (!isempty(after))
-                fprintf(f, "After=%s\n", after);
-        if (!isempty(wants))
-                fprintf(f, "Wants=%s\n", wants);
-        if (!isempty(conflicts))
-                fprintf(f, "Conflicts=%s\n", conflicts);
+        STRV_FOREACH(p, s->before)
+                fprintf(f, "Before=%s\n", *p);
+        STRV_FOREACH(p, s->after)
+                fprintf(f, "After=%s\n", *p);
+        STRV_FOREACH(p, s->wants)
+                fprintf(f, "Wants=%s\n", *p);
+        STRV_FOREACH(p, s->conflicts)
+                fprintf(f, "Conflicts=%s\n", *p);
 
         fprintf(f,
                 "\n[Service]\n"
diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c
new file mode 100644 (file)
index 0000000..430dda8
--- /dev/null
@@ -0,0 +1,85 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2015 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 <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "acl-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "string-util.h"
+#include "user-util.h"
+
+static void test_add_acls_for_user(void) {
+        char fn[] = "/tmp/test-empty.XXXXXX";
+        _cleanup_close_ int fd = -1;
+        char *cmd;
+        uid_t uid;
+        int r;
+
+        fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
+        assert_se(fd >= 0);
+
+        /* Use the mode that user journal files use */
+        assert_se(fchmod(fd, 0640) == 0);
+
+        cmd = strjoina("ls -l ", fn);
+        assert_se(system(cmd) == 0);
+
+        cmd = strjoina("getfacl -p ", fn);
+        assert_se(system(cmd) == 0);
+
+        if (getuid() == 0) {
+                const char *nobody = "nobody";
+                r = get_user_creds(&nobody, &uid, NULL, NULL, NULL);
+                if (r < 0)
+                        uid = 0;
+        } else
+                uid = getuid();
+
+        r = add_acls_for_user(fd, uid);
+        assert_se(r >= 0);
+
+        cmd = strjoina("ls -l ", fn);
+        assert_se(system(cmd) == 0);
+
+        cmd = strjoina("getfacl -p ", fn);
+        assert_se(system(cmd) == 0);
+
+        /* set the acls again */
+
+        r = add_acls_for_user(fd, uid);
+        assert_se(r >= 0);
+
+        cmd = strjoina("ls -l ", fn);
+        assert_se(system(cmd) == 0);
+
+        cmd = strjoina("getfacl -p ", fn);
+        assert_se(system(cmd) == 0);
+
+        unlink(fn);
+}
+
+int main(int argc, char **argv) {
+        test_add_acls_for_user();
+
+        return 0;
+}
index 35479d67c1c796d9822f0fab5431108480977406..f41e488d9950a7b33ec25ce216d9b6fed8801b8f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
new file mode 100644 (file)
index 0000000..8666659
--- /dev/null
@@ -0,0 +1,38 @@
+/***
+  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 "alloc-util.h"
+#include "ask-password-api.h"
+#include "log.h"
+
+static void ask_password(void) {
+        int r;
+        _cleanup_free_ char *ret;
+
+        r = ask_password_tty("hello?", "da key", 0, 0, NULL, &ret);
+        assert(r >= 0);
+
+        log_info("Got %s", ret);
+}
+
+int main(int argc, char **argv) {
+        log_parse_environment();
+
+        ask_password();
+}
index f37cb49c85718670995740817f4ade6ed9b8a6f3..e6aa3b5cfe9cccee48758886d422c72c92bddf62 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index fab33d20c7db543262c33a512146a3b5c1365d18..d2add5880cc1f625ac5b6836e0703f6742b2caaf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 33356f8387ad4bcc8968f12f8db8e87713e0a2d1..ce29d884123a53f37dd866faf0a9207bf02ed044 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 70819b0371c0043458a3e7c7d31c016a3fb9d10d..8754cb3381542f95ebcb997e7f648e1585adada9 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -75,7 +73,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_
 
         u = after;
         r = calendar_spec_next_usec(c, after, &u);
-        printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
+        printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u));
         if (expect != (usec_t)-1)
                 assert_se(r >= 0 && u == expect);
         else
@@ -123,6 +121,9 @@ int main(int argc, char* argv[]) {
         test_one("annually", "*-01-01 00:00:00");
         test_one("*:2/3", "*-*-* *:02/3:00");
         test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC");
+        test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001");
+        test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
+        test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000");
 
         test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
         test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
@@ -131,11 +132,19 @@ int main(int argc, char* argv[]) {
         test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000);
         test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000);
         test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000);
+        test_next("2016-03-27 03:17:00.420000001 UTC", "EET", 12345, 1459048620420000);
+        test_next("2016-03-27 03:17:00.4200005 UTC", "EET", 12345, 1459048620420001);
+        test_next("2015-11-13 09:11:23.42", "EET", 12345, 1447398683420000);
+        test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000);
+        test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000);
 
         assert_se(calendar_spec_from_string("test", &c) < 0);
         assert_se(calendar_spec_from_string("", &c) < 0);
         assert_se(calendar_spec_from_string("7", &c) < 0);
         assert_se(calendar_spec_from_string("121212:1:2", &c) < 0);
+        assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0);
+        assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0);
+        assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0);
 
         return 0;
 }
index 4418bafda6e6aa95e70454e4683408fa561f6e85..4132ec56fd01887805fe22bcb512dd922f4d70fd 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index fc8d3ffe0d2bb4200874928cb75ff6c52015f670..629bb63c81c3da7b9498f220541cdc8d602b0087 100644 (file)
@@ -20,6 +20,7 @@
 #include <netinet/in.h>
 #include <pwd.h>
 #include <sys/capability.h>
+#include <sys/prctl.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -66,8 +67,9 @@ static void show_capabilities(void) {
         cap_free(text);
 }
 
-static int setup_tests(void) {
+static int setup_tests(bool *run_ambient) {
         struct passwd *nobody;
+        int r;
 
         nobody = getpwnam("nobody");
         if (!nobody) {
@@ -77,6 +79,18 @@ static int setup_tests(void) {
         test_uid = nobody->pw_uid;
         test_gid = nobody->pw_gid;
 
+        *run_ambient = false;
+
+        r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+
+        /* There's support for PR_CAP_AMBIENT if the prctl() call
+         * succeeded or error code was something else than EINVAL. The
+         * EINVAL check should be good enough to rule out false
+         * positives. */
+
+        if (r >= 0 || errno != EINVAL)
+                *run_ambient = true;
+
         return 0;
 }
 
@@ -140,8 +154,53 @@ static void test_have_effective_cap(void) {
         assert_se(!have_effective_cap(CAP_CHOWN));
 }
 
+static void test_update_inherited_set(void) {
+        cap_t caps;
+        uint64_t set = 0;
+        cap_flag_value_t fv;
+
+        caps = cap_get_proc();
+        assert_se(caps);
+        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+        assert(fv == CAP_CLEAR);
+
+        set = (UINT64_C(1) << CAP_CHOWN);
+
+        assert_se(!capability_update_inherited_set(caps, set));
+        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+        assert(fv == CAP_SET);
+
+        cap_free(caps);
+}
+
+static void test_set_ambient_caps(void) {
+        cap_t caps;
+        uint64_t set = 0;
+        cap_flag_value_t fv;
+
+        caps = cap_get_proc();
+        assert_se(caps);
+        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+        assert(fv == CAP_CLEAR);
+        cap_free(caps);
+
+        assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0);
+
+        set = (UINT64_C(1) << CAP_CHOWN);
+
+        assert_se(!capability_ambient_set_apply(set, true));
+
+        caps = cap_get_proc();
+        assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv));
+        assert(fv == CAP_SET);
+        cap_free(caps);
+
+        assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 1);
+}
+
 int main(int argc, char *argv[]) {
         int r;
+        bool run_ambient;
 
         log_parse_environment();
         log_open();
@@ -149,14 +208,19 @@ int main(int argc, char *argv[]) {
         if (getuid() != 0)
                 return EXIT_TEST_SKIP;
 
-        r = setup_tests();
+        r = setup_tests(&run_ambient);
         if (r < 0)
                 return -r;
 
         show_capabilities();
 
         test_drop_privileges();
+        test_update_inherited_set();
+
         fork_test(test_have_effective_cap);
 
+        if (run_ambient)
+                fork_test(test_set_ambient_caps);
+
         return 0;
 }
index 27460135226a1c9862e2eb4f8fc7f0550ff5915f..ad15075a5b49d55f987d7f024891ffbbdebddbda 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -40,6 +38,7 @@ static int test_cgroup_mask(void) {
                 puts("manager_new: Permission denied. Skipping test.");
                 return EXIT_TEST_SKIP;
         }
+        assert_se(r >= 0);
 
         /* Turn off all kinds of default accouning, so that we can
          * verify the masks resulting of our configuration and nothing
index a48b324e2603070a7f74375c67d53fd352da1f83..43f890617233f110f33905d36189ed37ff3d2f7d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c20a29ba1f83ff7d671d5a0e8379891b2ef99949..72c32d9c8f7b50bc12933cf88cf65b15c97a1e01 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f224c6cdd8c11ab3cd19b39bb822748dbbe0f44e..8903d10db72524511a785bbc220a0200bf6245ae 100644 (file)
@@ -203,7 +203,7 @@ static void test_condition_test_security(void) {
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
-        assert_se(condition_test(condition) != mac_selinux_use());
+        assert_se(condition_test(condition) != mac_selinux_have());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "ima", false, false);
index 86ac513d4f51f7026ef2dad958bd1a419ea4e346..03b3a9fa5c30e5181d6c851f8368ec29b01fc6e7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 45fb554445eae2778579bfbc09a67c9691e1b974..4ce00f4b1fe5813c38edf9602635d6fb856a149b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c6d8bf82eaa8e0fc8b546e5605b1b693d2c0f8f1..7f497bb7d5b85ee8f23e3a843ec6bd40f5118643 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 static void test_should_pass(const char *p) {
         usec_t t, q;
-        char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
+        char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp;
 
         assert_se(parse_timestamp(p, &t) >= 0);
         format_timestamp_us(buf, sizeof(buf), t);
         log_info("%s", buf);
 
         /* Chop off timezone */
-        *strrchr(buf, ' ') = 0;
+        sp = strrchr(buf, ' ');
+        assert_se(sp);
+        *sp = 0;
 
         assert_se(parse_timestamp(buf, &q) >= 0);
         assert_se(q == t);
index 646b168cc0e3a10c2489fd0963039aa3321865a0..af75b389485ebd4cad37e4c96faf156475aed6d7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d5778748a05036722f3a8bb1a0197880d310adc4..a9d09f59bcb4eb005542c011e373f0104a5d1ef7 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,7 +37,7 @@ static void test_dns_label_unescape_one(const char *what, const char *expect, si
 
 static void test_dns_label_unescape(void) {
         test_dns_label_unescape_one("hallo", "hallo", 6, 5);
-        test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC);
+        test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS);
         test_dns_label_unescape_one("", "", 10, 0);
         test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12);
         test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5);
@@ -52,6 +50,66 @@ static void test_dns_label_unescape(void) {
         test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
 }
 
+static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
+        uint8_t buffer[buffer_sz];
+        int r;
+
+        r = dns_name_to_wire_format(what, buffer, buffer_sz, false);
+        assert_se(r == ret);
+
+        if (r < 0)
+                return;
+
+        assert_se(!memcmp(buffer, expect, r));
+}
+
+static void test_dns_name_to_wire_format(void) {
+        static const char out0[] = { 0 };
+        static const char out1[] = { 3, 'f', 'o', 'o', 0 };
+        static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+        static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
+                                     3, 'a', '1', '2', 0 };
+
+        test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0));
+
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
+        test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
+
+        test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
+        test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
+
+        test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
+
+        test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", NULL, 500, -EINVAL);
+        test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", out4, sizeof(out4), sizeof(out4));
+}
+
 static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
         char buffer[buffer_sz];
         const char *label;
@@ -72,7 +130,7 @@ static void test_dns_label_unescape_suffix_one(const char *what, const char *exp
 
 static void test_dns_label_unescape_suffix(void) {
         test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0);
-        test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOSPC, -ENOSPC);
+        test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOBUFS, -ENOBUFS);
         test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0);
         test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0);
         test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5);
@@ -80,9 +138,9 @@ static void test_dns_label_unescape_suffix(void) {
         test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL);
         test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo  ", "", 20, 7, 0);
         test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0);
-        test_dns_label_unescape_suffix_one("..", "", "", 20, 0, 0);
+        test_dns_label_unescape_suffix_one("..", "", "", 20, 0, -EINVAL);
         test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL);
-        test_dns_label_unescape_suffix_one("foobar.", "", "foobar", 20, 0, 6);
+        test_dns_label_unescape_suffix_one("foobar.", "foobar", "", 20, 6, 0);
         test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0);
         test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3);
         test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL);
@@ -96,7 +154,7 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
         _cleanup_free_ char *t = NULL;
         int r;
 
-        r = dns_label_escape(what, l, &t);
+        r = dns_label_escape_new(what, l, &t);
         assert_se(r == ret);
 
         if (r < 0)
@@ -106,9 +164,9 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
 }
 
 static void test_dns_label_escape(void) {
-        test_dns_label_escape_one("", 0, "", 0);
+        test_dns_label_escape_one("", 0, NULL, -EINVAL);
         test_dns_label_escape_one("hallo", 5, "hallo", 5);
-        test_dns_label_escape_one("hallo", 6, NULL, -EINVAL);
+        test_dns_label_escape_one("hallo", 6, "hallo\\000", 9);
         test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31);
 }
 
@@ -126,15 +184,15 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
 }
 
 static void test_dns_name_normalize(void) {
-        test_dns_name_normalize_one("", "", 0);
+        test_dns_name_normalize_one("", ".", 0);
         test_dns_name_normalize_one("f", "f", 0);
         test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
         test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
-        test_dns_name_normalize_one("\\000", NULL, -EINVAL);
+        test_dns_name_normalize_one("\\000", "\\000", 0);
         test_dns_name_normalize_one("..", NULL, -EINVAL);
         test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
         test_dns_name_normalize_one("foobar.", "foobar", 0);
-        test_dns_name_normalize_one(".", "", 0);
+        test_dns_name_normalize_one(".", ".", 0);
 }
 
 static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
@@ -156,7 +214,7 @@ static void test_dns_name_equal(void) {
         test_dns_name_equal_one("abc.def", "CBA.def", false);
         test_dns_name_equal_one("", "xxx", false);
         test_dns_name_equal_one("ab", "a", false);
-        test_dns_name_equal_one("\\000", "xxxx", -EINVAL);
+        test_dns_name_equal_one("\\000", "\\000", true);
         test_dns_name_equal_one(".", "", true);
         test_dns_name_equal_one(".", ".", true);
         test_dns_name_equal_one("..", "..", -EINVAL);
@@ -216,21 +274,40 @@ static void test_dns_name_endswith(void) {
         test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
 }
 
-static void test_dns_name_root(void) {
-        assert_se(dns_name_root("") == true);
-        assert_se(dns_name_root(".") == true);
-        assert_se(dns_name_root("xxx") == false);
-        assert_se(dns_name_root("xxx.") == false);
-        assert_se(dns_name_root("..") == -EINVAL);
+static void test_dns_name_startswith_one(const char *a, const char *b, int ret) {
+        assert_se(dns_name_startswith(a, b) == ret);
 }
 
-static void test_dns_name_single_label(void) {
-        assert_se(dns_name_single_label("") == false);
-        assert_se(dns_name_single_label(".") == false);
-        assert_se(dns_name_single_label("..") == -EINVAL);
-        assert_se(dns_name_single_label("x") == true);
-        assert_se(dns_name_single_label("x.") == true);
-        assert_se(dns_name_single_label("xx.yy") == false);
+static void test_dns_name_startswith(void) {
+        test_dns_name_startswith_one("", "", true);
+        test_dns_name_startswith_one("", "xxx", false);
+        test_dns_name_startswith_one("xxx", "", true);
+        test_dns_name_startswith_one("x", "x", true);
+        test_dns_name_startswith_one("x", "y", false);
+        test_dns_name_startswith_one("x.y", "x.y", true);
+        test_dns_name_startswith_one("x.y", "y.x", false);
+        test_dns_name_startswith_one("x.y", "x", true);
+        test_dns_name_startswith_one("x.y", "X", true);
+        test_dns_name_startswith_one("x.y", "y", false);
+        test_dns_name_startswith_one("x.y", "", true);
+        test_dns_name_startswith_one("x.y", "X", true);
+}
+
+static void test_dns_name_is_root(void) {
+        assert_se(dns_name_is_root(""));
+        assert_se(dns_name_is_root("."));
+        assert_se(!dns_name_is_root("xxx"));
+        assert_se(!dns_name_is_root("xxx."));
+        assert_se(!dns_name_is_root(".."));
+}
+
+static void test_dns_name_is_single_label(void) {
+        assert_se(!dns_name_is_single_label(""));
+        assert_se(!dns_name_is_single_label("."));
+        assert_se(!dns_name_is_single_label(".."));
+        assert_se(dns_name_is_single_label("x"));
+        assert_se(dns_name_is_single_label("x."));
+        assert_se(!dns_name_is_single_label("xx.yy"));
 }
 
 static void test_dns_name_reverse_one(const char *address, const char *name) {
@@ -261,10 +338,18 @@ static void test_dns_name_concat_one(const char *a, const char *b, int r, const
 }
 
 static void test_dns_name_concat(void) {
+        test_dns_name_concat_one("", "", 0, ".");
+        test_dns_name_concat_one(".", "", 0, ".");
+        test_dns_name_concat_one("", ".", 0, ".");
+        test_dns_name_concat_one(".", ".", 0, ".");
         test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
         test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
         test_dns_name_concat_one("foo", NULL, 0, "foo");
+        test_dns_name_concat_one("foo", ".", 0, "foo");
         test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
+        test_dns_name_concat_one(NULL, NULL, 0, ".");
+        test_dns_name_concat_one(NULL, ".", 0, ".");
+        test_dns_name_concat_one(NULL, "foo", 0, "foo");
 }
 
 static void test_dns_name_is_valid_one(const char *s, int ret) {
@@ -284,6 +369,259 @@ static void test_dns_name_is_valid(void) {
         test_dns_name_is_valid_one("\\zbar", 0);
         test_dns_name_is_valid_one("ä", 1);
         test_dns_name_is_valid_one("\n", 0);
+
+        /* 256 characters*/
+        test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345", 0);
+
+        /* 255 characters*/
+        test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a1234", 0);
+
+        /* 254 characters*/
+        test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", 0);
+
+        /* 253 characters*/
+        test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", 1);
+
+        /* label of 64 chars length */
+        test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0);
+
+        /* label of 63 chars length */
+        test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1);
+}
+
+static void test_dns_service_name_is_valid(void) {
+        assert_se(dns_service_name_is_valid("Lennart's Compüter"));
+        assert_se(dns_service_name_is_valid("piff.paff"));
+
+        assert_se(!dns_service_name_is_valid(NULL));
+        assert_se(!dns_service_name_is_valid(""));
+        assert_se(!dns_service_name_is_valid("foo\nbar"));
+        assert_se(!dns_service_name_is_valid("foo\201bar"));
+        assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters"));
+}
+
+static void test_dns_srv_type_is_valid(void) {
+
+        assert_se(dns_srv_type_is_valid("_http._tcp"));
+        assert_se(dns_srv_type_is_valid("_foo-bar._tcp"));
+        assert_se(dns_srv_type_is_valid("_w._udp"));
+        assert_se(dns_srv_type_is_valid("_a800._tcp"));
+        assert_se(dns_srv_type_is_valid("_a-800._tcp"));
+
+        assert_se(!dns_srv_type_is_valid(NULL));
+        assert_se(!dns_srv_type_is_valid(""));
+        assert_se(!dns_srv_type_is_valid("x"));
+        assert_se(!dns_srv_type_is_valid("_foo"));
+        assert_se(!dns_srv_type_is_valid("_tcp"));
+        assert_se(!dns_srv_type_is_valid("_"));
+        assert_se(!dns_srv_type_is_valid("_foo."));
+        assert_se(!dns_srv_type_is_valid("_föo._tcp"));
+        assert_se(!dns_srv_type_is_valid("_f\no._tcp"));
+        assert_se(!dns_srv_type_is_valid("_800._tcp"));
+        assert_se(!dns_srv_type_is_valid("_-800._tcp"));
+        assert_se(!dns_srv_type_is_valid("_-foo._tcp"));
+        assert_se(!dns_srv_type_is_valid("_piep._foo._udp"));
+}
+
+static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) {
+        _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
+
+        assert_se(dns_service_join(a, b, c, &t) == r);
+        assert_se(streq_ptr(t, d));
+
+        if (r < 0)
+                return;
+
+        assert_se(dns_service_split(t, &x, &y, &z) >= 0);
+        assert_se(streq_ptr(a, x));
+        assert_se(streq_ptr(b, y));
+        assert_se(dns_name_equal(c, z) > 0);
+}
+
+static void test_dns_service_join(void) {
+        test_dns_service_join_one("", "", "", -EINVAL, NULL);
+        test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL);
+        test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL);
+        test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL);
+        test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL);
+
+        test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp");
+        test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp");
+        test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo");
+        test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo");
+        test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com");
+        test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com");
+}
+
+static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) {
+        _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
+
+        assert_se(dns_service_split(joined, &x, &y, &z) == r);
+        assert_se(streq_ptr(x, a));
+        assert_se(streq_ptr(y, b));
+        assert_se(streq_ptr(z, c));
+
+        if (r < 0)
+                return;
+
+        if (y) {
+                assert_se(dns_service_join(x, y, z, &t) == 0);
+                assert_se(dns_name_equal(joined, t) > 0);
+        } else
+                assert_se(!x && dns_name_equal(z, joined) > 0);
+}
+
+static void test_dns_service_split(void) {
+        test_dns_service_split_one("", NULL, NULL, ".", 0);
+        test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
+        test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
+        test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
+        test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
+        test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
+        test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
+}
+
+static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) {
+        _cleanup_free_ char *s = NULL;
+
+        assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r);
+        assert_se(streq_ptr(s, result));
+}
+
+static void test_dns_name_change_suffix(void) {
+        test_dns_name_change_suffix_one("foo.bar", "bar", "waldo", 1, "foo.waldo");
+        test_dns_name_change_suffix_one("foo.bar.waldi.quux", "foo.bar.waldi.quux", "piff.paff", 1, "piff.paff");
+        test_dns_name_change_suffix_one("foo.bar.waldi.quux", "bar.waldi.quux", "piff.paff", 1, "foo.piff.paff");
+        test_dns_name_change_suffix_one("foo.bar.waldi.quux", "waldi.quux", "piff.paff", 1, "foo.bar.piff.paff");
+        test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
+        test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
+        test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
+        test_dns_name_change_suffix_one("", "", "", 1, ".");
+        test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
+}
+
+static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) {
+        const char *p = NULL;
+
+        assert_se(ret == dns_name_suffix(name, n_labels, &p));
+        assert_se(streq_ptr(p, result));
+}
+
+static void test_dns_name_suffix(void) {
+        test_dns_name_suffix_one("foo.bar", 2, "foo.bar", 0);
+        test_dns_name_suffix_one("foo.bar", 1, "bar", 1);
+        test_dns_name_suffix_one("foo.bar", 0, "", 2);
+        test_dns_name_suffix_one("foo.bar", 3, NULL, -EINVAL);
+        test_dns_name_suffix_one("foo.bar", 4, NULL, -EINVAL);
+
+        test_dns_name_suffix_one("bar", 1, "bar", 0);
+        test_dns_name_suffix_one("bar", 0, "", 1);
+        test_dns_name_suffix_one("bar", 2, NULL, -EINVAL);
+        test_dns_name_suffix_one("bar", 3, NULL, -EINVAL);
+
+        test_dns_name_suffix_one("", 0, "", 0);
+        test_dns_name_suffix_one("", 1, NULL, -EINVAL);
+        test_dns_name_suffix_one("", 2, NULL, -EINVAL);
+}
+
+static void test_dns_name_count_labels_one(const char *name, int n) {
+        assert_se(dns_name_count_labels(name) == n);
+}
+
+static void test_dns_name_count_labels(void) {
+        test_dns_name_count_labels_one("foo.bar.quux.", 3);
+        test_dns_name_count_labels_one("foo.bar.quux", 3);
+        test_dns_name_count_labels_one("foo.bar.", 2);
+        test_dns_name_count_labels_one("foo.bar", 2);
+        test_dns_name_count_labels_one("foo.", 1);
+        test_dns_name_count_labels_one("foo", 1);
+        test_dns_name_count_labels_one("", 0);
+        test_dns_name_count_labels_one(".", 0);
+        test_dns_name_count_labels_one("..", -EINVAL);
+}
+
+static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) {
+        assert_se(dns_name_equal_skip(a, n_labels, b) == ret);
+}
+
+static void test_dns_name_equal_skip(void) {
+        test_dns_name_equal_skip_one("foo", 0, "bar", 0);
+        test_dns_name_equal_skip_one("foo", 0, "foo", 1);
+        test_dns_name_equal_skip_one("foo", 1, "foo", 0);
+        test_dns_name_equal_skip_one("foo", 2, "foo", 0);
+
+        test_dns_name_equal_skip_one("foo.bar", 0, "foo.bar", 1);
+        test_dns_name_equal_skip_one("foo.bar", 1, "foo.bar", 0);
+        test_dns_name_equal_skip_one("foo.bar", 2, "foo.bar", 0);
+        test_dns_name_equal_skip_one("foo.bar", 3, "foo.bar", 0);
+
+        test_dns_name_equal_skip_one("foo.bar", 0, "bar", 0);
+        test_dns_name_equal_skip_one("foo.bar", 1, "bar", 1);
+        test_dns_name_equal_skip_one("foo.bar", 2, "bar", 0);
+        test_dns_name_equal_skip_one("foo.bar", 3, "bar", 0);
+
+        test_dns_name_equal_skip_one("foo.bar", 0, "", 0);
+        test_dns_name_equal_skip_one("foo.bar", 1, "", 0);
+        test_dns_name_equal_skip_one("foo.bar", 2, "", 1);
+        test_dns_name_equal_skip_one("foo.bar", 3, "", 0);
+
+        test_dns_name_equal_skip_one("", 0, "", 1);
+        test_dns_name_equal_skip_one("", 1, "", 0);
+        test_dns_name_equal_skip_one("", 1, "foo", 0);
+        test_dns_name_equal_skip_one("", 2, "foo", 0);
+}
+
+static void test_dns_name_compare_func(void) {
+        assert_se(dns_name_compare_func("", "") == 0);
+        assert_se(dns_name_compare_func("", ".") == 0);
+        assert_se(dns_name_compare_func(".", "") == 0);
+        assert_se(dns_name_compare_func("foo", "foo.") == 0);
+        assert_se(dns_name_compare_func("foo.", "foo") == 0);
+        assert_se(dns_name_compare_func("foo", "foo") == 0);
+        assert_se(dns_name_compare_func("foo.", "foo.") == 0);
+        assert_se(dns_name_compare_func("heise.de", "HEISE.DE.") == 0);
+
+        assert_se(dns_name_compare_func("de.", "heise.de") != 0);
+}
+
+static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) {
+        const char *c;
+
+        assert_se(dns_name_common_suffix(a, b, &c) >= 0);
+        assert_se(streq(c, result));
+}
+
+static void test_dns_name_common_suffix(void) {
+        test_dns_name_common_suffix_one("", "", "");
+        test_dns_name_common_suffix_one("foo", "", "");
+        test_dns_name_common_suffix_one("", "foo", "");
+        test_dns_name_common_suffix_one("foo", "bar", "");
+        test_dns_name_common_suffix_one("bar", "foo", "");
+        test_dns_name_common_suffix_one("foo", "foo", "foo");
+        test_dns_name_common_suffix_one("quux.foo", "foo", "foo");
+        test_dns_name_common_suffix_one("foo", "quux.foo", "foo");
+        test_dns_name_common_suffix_one("this.is.a.short.sentence", "this.is.another.short.sentence", "short.sentence");
+        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
+        _cleanup_free_ char *buf = NULL;
+        assert_se(dns_name_apply_idna(s, &buf) >= 0);
+        assert_se(dns_name_equal(buf, result) > 0);
+#endif
+}
+
+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");
 }
 
 int main(int argc, char *argv[]) {
@@ -294,12 +632,25 @@ int main(int argc, char *argv[]) {
         test_dns_name_normalize();
         test_dns_name_equal();
         test_dns_name_endswith();
+        test_dns_name_startswith();
         test_dns_name_between();
-        test_dns_name_root();
-        test_dns_name_single_label();
+        test_dns_name_is_root();
+        test_dns_name_is_single_label();
         test_dns_name_reverse();
         test_dns_name_concat();
         test_dns_name_is_valid();
+        test_dns_name_to_wire_format();
+        test_dns_service_name_is_valid();
+        test_dns_srv_type_is_valid();
+        test_dns_service_join();
+        test_dns_service_split();
+        test_dns_name_change_suffix();
+        test_dns_name_suffix();
+        test_dns_name_count_labels();
+        test_dns_name_equal_skip();
+        test_dns_name_compare_func();
+        test_dns_name_common_suffix();
+        test_dns_name_apply_idna();
 
         return 0;
 }
index c597d5aecd25e215930fdc4511f1df79a10f513c..d4f09b08a5879bd6a05110868827ecb2b8db348a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 4f14c587883d5c2de1763c09d1ad9915cebacf19..ca66f5b684693e7464b4131565962fd0cd48a1d1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 
 #include "bus-util.h"
 #include "manager.h"
+#include "test-helper.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
         Manager *m = NULL;
         Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
         FILE *serial = NULL;
@@ -38,8 +37,8 @@ int main(int argc, char *argv[]) {
         /* prepare the test */
         assert_se(set_unit_path(TEST_DIR) >= 0);
         r = manager_new(MANAGER_USER, true, &m);
-        if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
-                printf("Skipping test: manager_new: %s", strerror(-r));
+        if (MANAGER_SKIP_TEST(r)) {
+                printf("Skipping test: manager_new: %s\n", strerror(-r));
                 return EXIT_TEST_SKIP;
         }
         assert_se(r >= 0);
index c1315bbf9ff8c3120779d2697d02942044d69a71..264acc6ea64bebdece0c4516eb996122a7af50c2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 03ec0fcfc75456db6cc760996aa8a0a79bbf6884..92857cb5e2067e432329eb92d9e56686c47bcf5c 100644 (file)
@@ -20,6 +20,7 @@
 #include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 
 #include "fileio.h"
@@ -29,6 +30,7 @@
 #include "mkdir.h"
 #include "path-util.h"
 #include "rm-rf.h"
+#include "test-helper.h"
 #include "unit.h"
 #include "util.h"
 
@@ -223,6 +225,20 @@ static void test_exec_capabilityboundingset(Manager *m) {
         test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
 }
 
+static void test_exec_capabilityambientset(Manager *m) {
+        int r;
+
+        /* Check if the kernel has support for ambient capabilities. Run
+         * the tests only if that's the case. Clearing all ambient
+         * capabilities is fine, since we are expecting them to be unset
+         * in the first place for the tests. */
+        r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+        if (r >= 0 || errno != EINVAL) {
+                test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
+                test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
+        }
+}
+
 static void test_exec_privatenetwork(Manager *m) {
         int r;
 
@@ -265,6 +281,7 @@ int main(int argc, char *argv[]) {
                 test_exec_umask,
                 test_exec_runtimedirectory,
                 test_exec_capabilityboundingset,
+                test_exec_capabilityambientset,
                 test_exec_oomscoreadjust,
                 test_exec_ioschedulingclass,
                 NULL,
@@ -296,8 +313,8 @@ int main(int argc, char *argv[]) {
         assert_se(unsetenv("VAR3") == 0);
 
         r = manager_new(MANAGER_USER, true, &m);
-        if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
-                printf("Skipping test: manager_new: %s", strerror(-r));
+        if (MANAGER_SKIP_TEST(r)) {
+                printf("Skipping test: manager_new: %s\n", strerror(-r));
                 return EXIT_TEST_SKIP;
         }
         assert_se(r >= 0);
index 65d3a0a96e818493abe1d38883f3d3f71f9622aa..7a23fa7b7b0f885f568584d03213a2c7d4e66aca 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 871c71e171a9758fd7f95ad29e20ea253003d6be..5586a2d6c1ec83f29426e67fb12101b0f59d44fc 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ff66bde094712c0303e43704902c9d15cccb2138..77e809c5bfd1f37a4965ea88da824f77ebb5cedb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 27816ac7796a5c6f54f0bc1cb24b8f942ef446bd..ea3d1a6909655f1a4430045ace10e920684e00ad 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f75dd3374ad3e674e4e4e5a468baa6f2bead9741..ddb10f88fd1956010a6cc411b89f9073d6d3bf77 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
 
 #include "sd-daemon.h"
 
+#include "macro.h"
+
 #define TEST_REQ_RUNNING_SYSTEMD(x)                                 \
         if (sd_booted() > 0) {                                      \
                 x;                                                  \
         } else {                                                    \
                 printf("systemd not booted skipping '%s'\n", #x);   \
         }
+
+#define MANAGER_SKIP_TEST(r)                                    \
+        IN_SET(r,                                               \
+               -EPERM,                                          \
+               -EACCES,                                         \
+               -EADDRINUSE,                                     \
+               -EHOSTDOWN,                                      \
+               -ENOENT,                                         \
+               -ENOMEDIUM /* cannot determine cgroup */         \
+               )
index 590175433c3c0e7ea4bd30f6456723c71cab3a48..17fde9f27eecfba906b4cb4435ae099c17b0e08a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index dd50c5148cccabdb642eaa2ae58a6c95a8ef7790..b38507df5d60c4296bb725c81b6150f04fbc7bc0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 32cf3f80ca6e73ae54cc98521623503b57a56c7e..96aa008c06ed49c2aea669c266aba90c09947c4e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 08fde94f7f011808f3fa2cf9031aaef6ca6b08f7..cd250ca7b874a6608cc876c39e0a8058e25cac32 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index ef6f1efb896417a8e499f1dc8fa7b594c84723d7..874d617621c2205e129c0681cdfb60f9dad5a9c5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5841cb3fb1d25ab4fc11e4213fa622c7bae30d41..2464d32458c15634665dd4246fb1c54ef9d32f09 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 75ce3a349e3ef71f712716266fb50848de5fa742..7f0b9f253cbdca7589255927f6fe8527813f8fc1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3995224eea888790fde0186820b92378abad803d..3fe2f58d04f290910aedec67a608c7679ce32d9a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 350eaf734dd1d040829707aea5aafd06e0c452c6..a7eb60e8cf99da043b5bcbc64cf53785f6b06d7e 100644 (file)
@@ -1,4 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 /***
   This file is part of systemd.
 
@@ -25,6 +24,7 @@
 
 #include "libudev.h"
 
+#include "stdio-util.h"
 #include "string-util.h"
 #include "udev-util.h"
 #include "util.h"
@@ -460,7 +460,7 @@ int main(int argc, char *argv[]) {
 
         /* add sys path if needed */
         if (!startswith(syspath, "/sys")) {
-                snprintf(path, sizeof(path), "/sys/%s", syspath);
+                xsprintf(path, "/sys/%s", syspath);
                 syspath = path;
         }
 
index a01df9b04929ee75db1aaf44a0521f2e63e3d982..55a2f9d23b9dcda7f028083725eec84c181d0cd8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 556938a0f897060ff748be6c850b1e8f9e6dff7e..2748395adec6ec13dcf44bbe7656f41df65f7386 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 5a12e959d4350b090403aba7654571b2b93e967a..0b2f9e9173fa7cbb902a918db93a66ec517db2c1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index a1e8774063ce6e73f35342a2eae2c2d414923195..79ff6ae74db6e7099507ce256b54fb507b1143be 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1175114a3a9911202b02081a7d4151d56792a20d..cf627be6c54de7ac6088f3c116457c2cbca49631 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f0d5d71083fbba6cba1f4456593287f6ef7d1ede..7d8677e17c516c03b9dbfe81afb24917877a9a5e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 65cb894ff7df5a8bbf2e1b620f85c9260bb6de2d..268da002a949281e70ca2eea8a092af1f9357930 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 3f0f0264abf01e4537c2c53900e784ba7f8fd258..53a585290ab20d63306ead38a1768834f43593b8 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8302bdd28302a0f0e4525fe933d73f15e5a1afeb..7a3b145414900b6740417c2a4a67d24b1fbe5a33 100644 (file)
@@ -29,6 +29,7 @@
 #include "rm-rf.h"
 #include "string-util.h"
 #include "strv.h"
+#include "test-helper.h"
 #include "unit.h"
 #include "util.h"
 
@@ -44,8 +45,8 @@ static int setup_test(Manager **m) {
         assert_se(m);
 
         r = manager_new(MANAGER_USER, true, &tmp);
-        if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
-                printf("Skipping test: manager_new: %s", strerror(-r));
+        if (MANAGER_SKIP_TEST(r)) {
+                printf("Skipping test: manager_new: %s\n", strerror(-r));
                 return -EXIT_TEST_SKIP;
         }
         assert_se(r >= 0);
index 07273ffe7921422eb60796a5ead7cfc2092959cc..d81880a6556efbf513ce68b1dc4957cd1731b018 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/test/test-rbtree.c b/src/test/test-rbtree.c
new file mode 100644 (file)
index 0000000..8ae416c
--- /dev/null
@@ -0,0 +1,362 @@
+/***
+  This file is part of systemd. See COPYING for details.
+
+  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/>.
+***/
+
+/*
+ * Tests for RB-Tree
+ */
+
+#undef NDEBUG
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "c-rbtree.h"
+
+/* verify that all API calls are exported */
+static void test_api(void) {
+        CRBTree t = {};
+        CRBNode n = C_RBNODE_INIT(n);
+
+        assert(!c_rbnode_is_linked(&n));
+
+        /* init, is_linked, add, remove, remove_init */
+
+        c_rbtree_add(&t, NULL, &t.root, &n);
+        assert(c_rbnode_is_linked(&n));
+
+        c_rbtree_remove_init(&t, &n);
+        assert(!c_rbnode_is_linked(&n));
+
+        c_rbtree_add(&t, NULL, &t.root, &n);
+        assert(c_rbnode_is_linked(&n));
+
+        c_rbtree_remove(&t, &n);
+        assert(c_rbnode_is_linked(&n)); /* @n wasn't touched */
+
+        c_rbnode_init(&n);
+        assert(!c_rbnode_is_linked(&n));
+
+        /* first, last, leftmost, rightmost, next, prev */
+
+        assert(!c_rbtree_first(&t));
+        assert(!c_rbtree_last(&t));
+        assert(&n == c_rbnode_leftmost(&n));
+        assert(&n == c_rbnode_rightmost(&n));
+        assert(!c_rbnode_next(&n));
+        assert(!c_rbnode_prev(&n));
+}
+
+/* copied from c-rbtree.c, relies on internal representation */
+static inline _Bool c_rbnode_is_red(CRBNode *n) {
+        return !((unsigned long)n->__parent_and_color & 1UL);
+}
+
+/* copied from c-rbtree.c, relies on internal representation */
+static inline _Bool c_rbnode_is_black(CRBNode *n) {
+        return !!((unsigned long)n->__parent_and_color & 1UL);
+}
+
+static size_t validate(CRBTree *t) {
+        unsigned int i_black, n_black;
+        CRBNode *n, *p, *o;
+        size_t count = 0;
+
+        assert(t);
+        assert(!t->root || c_rbnode_is_black(t->root));
+
+        /* traverse to left-most child, count black nodes */
+        i_black = 0;
+        n = t->root;
+        while (n && n->left) {
+                if (c_rbnode_is_black(n))
+                        ++i_black;
+                n = n->left;
+        }
+        n_black = i_black;
+
+        /*
+         * Traverse tree and verify correctness:
+         *  1) A node is either red or black
+         *  2) The root is black
+         *  3) All leaves are black
+         *  4) Every red node must have two black child nodes
+         *  5) Every path to a leaf contains the same number of black nodes
+         *
+         * Note that NULL nodes are considered black, which is why we don't
+         * check for 3).
+         */
+        o = NULL;
+        while (n) {
+                ++count;
+
+                /* verify natural order */
+                assert(n > o);
+                o = n;
+
+                /* verify consistency */
+                assert(!n->right || c_rbnode_parent(n->right) == n);
+                assert(!n->left || c_rbnode_parent(n->left) == n);
+
+                /* verify 2) */
+                if (!c_rbnode_parent(n))
+                        assert(c_rbnode_is_black(n));
+
+                if (c_rbnode_is_red(n)) {
+                        /* verify 4) */
+                        assert(!n->left || c_rbnode_is_black(n->left));
+                        assert(!n->right || c_rbnode_is_black(n->right));
+                } else {
+                        /* verify 1) */
+                        assert(c_rbnode_is_black(n));
+                }
+
+                /* verify 5) */
+                if (!n->left && !n->right)
+                        assert(i_black == n_black);
+
+                /* get next node */
+                if (n->right) {
+                        n = n->right;
+                        if (c_rbnode_is_black(n))
+                                ++i_black;
+
+                        while (n->left) {
+                                n = n->left;
+                                if (c_rbnode_is_black(n))
+                                        ++i_black;
+                        }
+                } else {
+                        while ((p = c_rbnode_parent(n)) && n == p->right) {
+                                n = p;
+                                if (c_rbnode_is_black(p->right))
+                                        --i_black;
+                        }
+
+                        n = p;
+                        if (p && c_rbnode_is_black(p->left))
+                                --i_black;
+                }
+        }
+
+        return count;
+}
+
+static void insert(CRBTree *t, CRBNode *n) {
+        CRBNode **i, *p;
+
+        assert(t);
+        assert(n);
+        assert(!c_rbnode_is_linked(n));
+
+        i = &t->root;
+        p = NULL;
+        while (*i) {
+                p = *i;
+                if (n < *i) {
+                        i = &(*i)->left;
+                } else {
+                        assert(n > *i);
+                        i = &(*i)->right;
+                }
+        }
+
+        c_rbtree_add(t, p, i, n);
+}
+
+static void shuffle(void **nodes, size_t n_memb) {
+        unsigned int i, j;
+        void *t;
+
+        for (i = 0; i < n_memb; ++i) {
+                j = rand() % n_memb;
+                t = nodes[j];
+                nodes[j] = nodes[i];
+                nodes[i] = t;
+        }
+}
+
+/* run some pseudo-random tests on the tree */
+static void test_shuffle(void) {
+        CRBNode *nodes[256];
+        CRBTree t = {};
+        unsigned int i, j;
+        size_t n;
+
+        /* allocate and initialize all nodes */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                nodes[i] = malloc(sizeof(*nodes[i]));
+                assert(nodes[i]);
+                c_rbnode_init(nodes[i]);
+        }
+
+        /* shuffle nodes and validate *empty* tree */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+        n = validate(&t);
+        assert(n == 0);
+
+        /* add all nodes and validate after each insertion */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                insert(&t, nodes[i]);
+                n = validate(&t);
+                assert(n == i + 1);
+        }
+
+        /* shuffle nodes again */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+
+        /* remove all nodes (in different order) and validate on each round */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                c_rbtree_remove(&t, nodes[i]);
+                n = validate(&t);
+                assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
+                c_rbnode_init(nodes[i]);
+        }
+
+        /* shuffle nodes and validate *empty* tree again */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+        n = validate(&t);
+        assert(n == 0);
+
+        /* add all nodes again */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                insert(&t, nodes[i]);
+                n = validate(&t);
+                assert(n == i + 1);
+        }
+
+        /* 4 times, remove half of the nodes and add them again */
+        for (j = 0; j < 4; ++j) {
+                /* shuffle nodes again */
+                shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+
+                /* remove half of the nodes */
+                for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) {
+                        c_rbtree_remove(&t, nodes[i]);
+                        n = validate(&t);
+                        assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
+                        c_rbnode_init(nodes[i]);
+                }
+
+                /* shuffle the removed half */
+                shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes) / 2);
+
+                /* add the removed half again */
+                for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) {
+                        insert(&t, nodes[i]);
+                        n = validate(&t);
+                        assert(n == sizeof(nodes) / sizeof(*nodes) / 2 + i + 1);
+                }
+        }
+
+        /* shuffle nodes again */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+
+        /* remove all */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                c_rbtree_remove(&t, nodes[i]);
+                n = validate(&t);
+                assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1);
+                c_rbnode_init(nodes[i]);
+        }
+
+        /* free nodes again */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i)
+                free(nodes[i]);
+}
+
+typedef struct {
+        unsigned long key;
+        CRBNode rb;
+} Node;
+
+#define node_from_rb(_rb) ((Node *)((char *)(_rb) - offsetof(Node, rb)))
+
+static int compare(CRBTree *t, void *k, CRBNode *n) {
+        unsigned long key = (unsigned long)k;
+        Node *node = node_from_rb(n);
+
+        return (key < node->key) ? -1 : (key > node->key) ? 1 : 0;
+}
+
+/* run tests against the c_rbtree_find*() helpers */
+static void test_map(void) {
+        CRBNode **slot, *p;
+        CRBTree t = {};
+        Node *nodes[2048];
+        unsigned long i;
+
+        /* allocate and initialize all nodes */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                nodes[i] = malloc(sizeof(*nodes[i]));
+                assert(nodes[i]);
+                nodes[i]->key = i;
+                c_rbnode_init(&nodes[i]->rb);
+        }
+
+        /* shuffle nodes */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+
+        /* add all nodes, and verify that each node is linked */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                assert(!c_rbnode_is_linked(&nodes[i]->rb));
+                assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
+
+                slot = c_rbtree_find_slot(&t, compare, (void *)nodes[i]->key, &p);
+                assert(slot);
+                c_rbtree_add(&t, p, slot, &nodes[i]->rb);
+
+                assert(c_rbnode_is_linked(&nodes[i]->rb));
+                assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
+        }
+
+        /* shuffle nodes again */
+        shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes));
+
+        /* remove all nodes (in different order) */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) {
+                assert(c_rbnode_is_linked(&nodes[i]->rb));
+                assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
+
+                c_rbtree_remove_init(&t, &nodes[i]->rb);
+
+                assert(!c_rbnode_is_linked(&nodes[i]->rb));
+                assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb));
+        }
+
+        /* free nodes again */
+        for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i)
+                free(nodes[i]);
+}
+
+int main(int argc, char **argv) {
+        unsigned int i;
+
+        /* we want stable tests, so use fixed seed */
+        srand(0xdeadbeef);
+
+        test_api();
+
+        /*
+         * The tests are pseudo random; run them multiple times, each run will
+         * have different orders and thus different results.
+         */
+        for (i = 0; i < 4; ++i) {
+                test_shuffle();
+                test_map();
+        }
+
+        return 0;
+}
index 2de2091561d0b7e5a1258539f31b994851b48c55..297effce793ecd7470ca23061f158d9be0cc64a4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c
new file mode 100644 (file)
index 0000000..d9ac936
--- /dev/null
@@ -0,0 +1,104 @@
+/***
+  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.
+
+  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 <sys/resource.h>
+
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "macro.h"
+#include "rlimit-util.h"
+#include "string-util.h"
+#include "util.h"
+
+static void test_rlimit_parse_format(int resource, const char *string, rlim_t soft, rlim_t hard, int ret, const char *formatted) {
+        _cleanup_free_ char *f = NULL;
+        struct rlimit rl = {
+                .rlim_cur = 4711,
+                .rlim_max = 4712,
+        }, rl2 = {
+                .rlim_cur = 4713,
+                .rlim_max = 4714
+        };
+
+        assert_se(rlimit_parse(resource, string, &rl) == ret);
+        if (ret < 0)
+                return;
+
+        assert_se(rl.rlim_cur == soft);
+        assert_se(rl.rlim_max == hard);
+
+        assert_se(rlimit_format(&rl, &f) >= 0);
+        assert_se(streq(formatted, f));
+
+        assert_se(rlimit_parse(resource, formatted, &rl2) >= 0);
+        assert_se(memcmp(&rl, &rl2, sizeof(struct rlimit)) == 0);
+}
+
+int main(int argc, char *argv[]) {
+        struct rlimit old, new, high;
+        struct rlimit err = {
+                .rlim_cur = 10,
+                .rlim_max = 5,
+        };
+
+        log_parse_environment();
+        log_open();
+
+        assert_se(drop_capability(CAP_SYS_RESOURCE) == 0);
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+        new.rlim_cur = MIN(5U, old.rlim_max);
+        new.rlim_max = old.rlim_max;
+        assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0);
+
+        assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE);
+        assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1);
+
+        assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE"));
+        assert_se(rlimit_to_string(-1) == NULL);
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+        assert_se(setrlimit_closest(RLIMIT_NOFILE, &old) == 0);
+        assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+        assert_se(old.rlim_cur == new.rlim_cur);
+        assert_se(old.rlim_max == new.rlim_max);
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+        high = RLIMIT_MAKE_CONST(old.rlim_max == RLIM_INFINITY ? old.rlim_max : old.rlim_max + 1);
+        assert_se(setrlimit_closest(RLIMIT_NOFILE, &high) == 0);
+        assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+        assert_se(new.rlim_max == old.rlim_max);
+        assert_se(new.rlim_cur == new.rlim_max);
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
+        assert_se(setrlimit_closest(RLIMIT_NOFILE, &err) == -EINVAL);
+        assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0);
+        assert_se(old.rlim_cur == new.rlim_cur);
+        assert_se(old.rlim_max == new.rlim_max);
+
+        test_rlimit_parse_format(RLIMIT_NOFILE, "4:5", 4, 5, 0, "4:5");
+        test_rlimit_parse_format(RLIMIT_NOFILE, "6", 6, 6, 0, "6");
+        test_rlimit_parse_format(RLIMIT_NOFILE, "infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity");
+        test_rlimit_parse_format(RLIMIT_NOFILE, "infinity:infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity");
+        test_rlimit_parse_format(RLIMIT_NOFILE, "8:infinity", 8, RLIM_INFINITY, 0, "8:infinity");
+        test_rlimit_parse_format(RLIMIT_CPU, "25min:13h", (25*USEC_PER_MINUTE) / USEC_PER_SEC, (13*USEC_PER_HOUR) / USEC_PER_SEC, 0, "1500:46800");
+        test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL);
+        test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL);
+        test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL);
+
+        return 0;
+}
index 8396ae60f3de0c0860fb78d5522ae8af15a9edc7..7f515b53d878ca8bf7b2131313966ca75420cc96 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,6 +21,7 @@
 
 #include "macro.h"
 #include "manager.h"
+#include "test-helper.h"
 
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
@@ -35,8 +34,8 @@ int main(int argc, char *argv[]) {
         /* prepare the test */
         assert_se(set_unit_path(TEST_DIR) >= 0);
         r = manager_new(MANAGER_USER, true, &m);
-        if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
-                printf("Skipping test: manager_new: %s", strerror(-r));
+        if (MANAGER_SKIP_TEST(r)) {
+                printf("Skipping test: manager_new: %s\n", strerror(-r));
                 return EXIT_TEST_SKIP;
         }
         assert_se(r >= 0);
index b3ccc7509d55f11482e108e8397ca78ba9be4735..17b81747be8fdc730dcb2f8b803a1ce5504e220f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
new file mode 100644 (file)
index 0000000..3083501
--- /dev/null
@@ -0,0 +1,49 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 "signal-util.h"
+
+static void test_block_signals(void) {
+        sigset_t ss;
+
+        assert_se(sigprocmask(0, NULL, &ss) >= 0);
+
+        assert_se(sigismember(&ss, SIGUSR1) == 0);
+        assert_se(sigismember(&ss, SIGALRM) == 0);
+        assert_se(sigismember(&ss, SIGVTALRM) == 0);
+
+        {
+                BLOCK_SIGNALS(SIGUSR1, SIGVTALRM);
+
+                assert_se(sigprocmask(0, NULL, &ss) >= 0);
+                assert_se(sigismember(&ss, SIGUSR1) == 1);
+                assert_se(sigismember(&ss, SIGALRM) == 0);
+                assert_se(sigismember(&ss, SIGVTALRM) == 1);
+
+        }
+
+        assert_se(sigprocmask(0, NULL, &ss) >= 0);
+        assert_se(sigismember(&ss, SIGUSR1) == 0);
+        assert_se(sigismember(&ss, SIGALRM) == 0);
+        assert_se(sigismember(&ss, SIGVTALRM) == 0);
+}
+
+int main(int argc, char *argv[]) {
+        test_block_signals();
+}
index a571a95a70c442afd78455d6a99d52354f3a296c..caae911f305c7a8ced2867558ddb013ca60ffe4d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -30,7 +28,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
         unsigned i, j;
 
         out = siphash24(in, len, key);
-        assert_se(out == htole64(0xa129ca6149be45e5));
+        assert_se(out == 0xa129ca6149be45e5);
 
         /* verify the internal state as given in the above paper */
         siphash24_init(&state, key);
@@ -44,7 +42,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
         assert_se(state.v2 == 0x634cb3577b01fd3d);
         assert_se(state.v3 == 0xa5224d6f55c7d9c8);
         out = siphash24_finalize(&state);
-        assert_se(out == htole64(0xa129ca6149be45e5));
+        assert_se(out == 0xa129ca6149be45e5);
         assert_se(state.v0 == 0xf6bcd53893fecff1);
         assert_se(state.v1 == 0x54b9964c7ea0d937);
         assert_se(state.v2 == 0x1b38329c099bb55a);
@@ -59,7 +57,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
                         siphash24_compress(&in[i], j - i, &state);
                         siphash24_compress(&in[j], len - j, &state);
                         out = siphash24_finalize(&state);
-                        assert_se(out == htole64(0xa129ca6149be45e5));
+                        assert_se(out == 0xa129ca6149be45e5);
                 }
         }
         return 0;
index fb115ce4f3e7a7f26337e4a20bc3688a6165e805..97b6f3015dd209af866915471a1f00a63ada6a05 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 1d8eda0c15583122cc1221288db496cf70ecaebb..513218c39701add1e006bf0f8c672f6bcc101adf 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 25444c794acbb636cfb72a509dd7b7288b84528f..9b48e9599878245aa8d4afaa03f066a9a1e7a401 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -55,7 +53,53 @@ static void test_string_erase(void) {
         assert_se(streq(string_erase(x), "xxxxxxxxx"));
 }
 
+static void test_ascii_strcasecmp_n(void) {
+
+        assert_se(ascii_strcasecmp_n("", "", 0) == 0);
+        assert_se(ascii_strcasecmp_n("", "", 1) == 0);
+        assert_se(ascii_strcasecmp_n("", "a", 1) < 0);
+        assert_se(ascii_strcasecmp_n("", "a", 2) < 0);
+        assert_se(ascii_strcasecmp_n("a", "", 1) > 0);
+        assert_se(ascii_strcasecmp_n("a", "", 2) > 0);
+        assert_se(ascii_strcasecmp_n("a", "a", 1) == 0);
+        assert_se(ascii_strcasecmp_n("a", "a", 2) == 0);
+        assert_se(ascii_strcasecmp_n("a", "b", 1) < 0);
+        assert_se(ascii_strcasecmp_n("a", "b", 2) < 0);
+        assert_se(ascii_strcasecmp_n("b", "a", 1) > 0);
+        assert_se(ascii_strcasecmp_n("b", "a", 2) > 0);
+        assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0);
+        assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0);
+        assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0);
+        assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0);
+        assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0);
+
+        assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0);
+        assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0);
+        assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0);
+        assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0);
+        assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0);
+}
+
+static void test_ascii_strcasecmp_nn(void) {
+        assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
+        assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
+        assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
+        assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0);
+
+        assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0);
+        assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0);
+        assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0);
+        assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0);
+        assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0);
+
+        assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0);
+        assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0);
+        assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
+}
+
 int main(int argc, char *argv[]) {
         test_string_erase();
+        test_ascii_strcasecmp_n();
+        test_ascii_strcasecmp_nn();
         return 0;
 }
index 10fc98ced55b9d4054509909e8fc26b0c216673c..72b0f6fc1112585f05b91cd734c8dadffacc8c9b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c27f15283ec91ea4e9455bedda4b56ef8a73c774..2b2f76cc7f935aee48721793874c2c298e6a2995 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e411d479ab81c3a17228620086b85064490bece5..9bea7701314c659fafa8e2c7d73a10233fa1c512 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 8896b2c92bb5fa51c3b7d621b1200f74fbc47f05..9062c3f3c1cbc22c1615fbd74e205c69f1b3b5c6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -176,12 +174,36 @@ static void test_get_timezones(void) {
         r = get_timezones(&zones);
         assert_se(r == 0);
 
-        STRV_FOREACH(zone, zones) {
+        STRV_FOREACH(zone, zones)
                 assert_se(timezone_is_valid(*zone));
-        }
+}
+
+static void test_usec_add(void) {
+        assert_se(usec_add(0, 0) == 0);
+        assert_se(usec_add(1, 4) == 5);
+        assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY);
+        assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY);
+        assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3);
+        assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY);
+        assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY);
+        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);
 }
 
 int main(int argc, char *argv[]) {
+        uintmax_t x;
+
         test_parse_sec();
         test_parse_time();
         test_parse_nsec();
@@ -190,6 +212,16 @@ int main(int argc, char *argv[]) {
         test_format_timespan(USEC_PER_SEC);
         test_timezone_is_valid();
         test_get_timezones();
+        test_usec_add();
+        test_usec_sub();
+
+        /* Ensure time_t is signed */
+        assert_cc((time_t) -1 < (time_t) 1);
+
+        /* Ensure TIME_T_MAX works correctly */
+        x = (uintmax_t) TIME_T_MAX;
+        x ++;
+        assert((time_t) x < 0);
 
         return 0;
 }
index a8bd722e443c730098bb5605b5ca4e2384a52d32..d7223dd2bfa056dedab7b78bd2e0e5cb540257b5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -28,6 +26,8 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
+#include "fs-util.h"
+#include "log.h"
 #include "string-util.h"
 #include "util.h"
 
@@ -35,20 +35,29 @@ int main(int argc, char** argv) {
         const char *p = argv[1] ?: "/tmp";
         char *pattern = strjoina(p, "/systemd-test-XXXXXX");
         _cleanup_close_ int fd, fd2;
-        _cleanup_free_ char *cmd, *cmd2;
+        _cleanup_free_ char *cmd, *cmd2, *ans, *ans2;
+
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
 
         fd = open_tmpfile(p, O_RDWR|O_CLOEXEC);
         assert_se(fd >= 0);
 
         assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd) > 0);
-        system(cmd);
+        (void) system(cmd);
+        assert_se(readlink_malloc(cmd + 6, &ans) >= 0);
+        log_debug("link1: %s", ans);
+        assert_se(endswith(ans, " (deleted)"));
 
         fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC);
         assert_se(fd >= 0);
         assert_se(unlink(pattern) == 0);
 
         assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd2) > 0);
-        system(cmd2);
+        (void) system(cmd2);
+        assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0);
+        log_debug("link2: %s", ans2);
+        assert_se(endswith(ans2, " (deleted)"));
 
         return 0;
 }
index 4dcf10e26db46a59e61f405eb4a5b52dd83c1c38..41f06a5cecad44ac9a4fddc309c139efc185e88f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index c3973a316e08a596e0a32c75153e226c90733028..b0c343590d86d21a836bcabc1024bb23b90dc1d5 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -28,6 +26,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "capability-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "hashmap.h"
@@ -111,17 +110,30 @@ static void test_config_parse_exec(void) {
 
         ExecCommand *c = NULL, *c1;
         const char *ccc;
+        Manager *m = NULL;
+        Unit *u = NULL;
+
+        r = manager_new(MANAGER_USER, true, &m);
+        if (MANAGER_SKIP_TEST(r)) {
+                printf("Skipping test: manager_new: %s\n", strerror(-r));
+                return;
+        }
+
+        assert_se(r >= 0);
+        assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+        assert_se(u = unit_new(m, sizeof(Service)));
 
         log_info("/* basic test */");
         r = config_parse_exec(NULL, "fake", 1, "section", 1,
                               "LValue", 0, "/RValue r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
 
         r = config_parse_exec(NULL, "fake", 2, "section", 1,
                               "LValue", 0, "/RValue///slashes r1///",
-                              &c, NULL);
+                              &c, u);
 
         log_info("/* test slashes */");
         assert_se(r >= 0);
@@ -131,14 +143,14 @@ static void test_config_parse_exec(void) {
         log_info("/* trailing slash */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/RValue/ argv0 r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* honour_argv0 */");
         r = config_parse_exec(NULL, "fake", 3, "section", 1,
                               "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
@@ -146,21 +158,21 @@ static void test_config_parse_exec(void) {
         log_info("/* honour_argv0, no args */");
         r = config_parse_exec(NULL, "fake", 3, "section", 1,
                               "LValue", 0, "@/RValue",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* no command, whitespace only, reset */");
         r = config_parse_exec(NULL, "fake", 3, "section", 1,
                               "LValue", 0, "    ",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c == NULL);
 
         log_info("/* ignore && honour_argv0 */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "-@/RValue///slashes3 argv0a r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c;
         check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
@@ -168,7 +180,7 @@ static void test_config_parse_exec(void) {
         log_info("/* ignore && honour_argv0 */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "@-/RValue///slashes4 argv0b r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
@@ -176,14 +188,14 @@ static void test_config_parse_exec(void) {
         log_info("/* ignore && ignore */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "--/RValue argv0 r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* ignore && ignore (2) */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "-@-/RValue argv0 r1",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
@@ -192,7 +204,7 @@ static void test_config_parse_exec(void) {
                               "LValue", 0,
                               "-@/RValue argv0 r1 ; "
                               "/goo/goo boo",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -205,7 +217,7 @@ static void test_config_parse_exec(void) {
                               "LValue", 0,
                               "-@/RValue argv0 r1 ; ; "
                               "/goo/goo boo",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -217,7 +229,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "-@/RValue argv0 r1 ; ",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -228,7 +240,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "-@/RValue argv0 r1 ;",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
@@ -239,7 +251,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "-@/RValue argv0 r1 ';'",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
@@ -248,7 +260,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/bin/find \\;",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -257,7 +269,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/sbin/find \\; /x",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -267,7 +279,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/sbin/find \\;x",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -277,7 +289,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/bin/find \\073",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -286,7 +298,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/bin/find \";\"",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
@@ -295,7 +307,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/sbin/find \";\" /x",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -305,7 +317,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "\"/PATH WITH SPACES/daemon\" -1 -2",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -315,7 +327,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "\"/PATH WITH SPACES/daemon -1 -2\"",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -325,7 +337,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -335,7 +347,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -345,7 +357,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1,
@@ -359,7 +371,7 @@ static void test_config_parse_exec(void) {
                 log_info("/* invalid character: \\%c */", *ccc);
                 r = config_parse_exec(NULL, "fake", 4, "section", 1,
                                       "LValue", 0, path,
-                                      &c, NULL);
+                                      &c, u);
                 assert_se(r == 0);
                 assert_se(c1->command_next == NULL);
         }
@@ -367,7 +379,7 @@ static void test_config_parse_exec(void) {
         log_info("/* valid character: \\s */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path\\s",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
@@ -376,7 +388,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 5, "section", 1,
                               "LValue", 0,
                               "/bin/grep '\\w+\\K'",
-                              &c, NULL);
+                              &c, u);
         assert_se(r >= 0);
         c1 = c1->command_next;
         check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
@@ -386,46 +398,49 @@ static void test_config_parse_exec(void) {
         /* backslash is invalid */
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path\\",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* missing ending ' */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path 'foo",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         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, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* invalid space between modifiers */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "- /path",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* only modifiers, no path */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "-",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c1->command_next == NULL);
 
         log_info("/* empty argument, reset */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "",
-                              &c, NULL);
+                              &c, u);
         assert_se(r == 0);
         assert_se(c == NULL);
 
         exec_command_free_list(c);
+
+        unit_free(u);
+        manager_free(m);
 }
 
 #define env_file_1                              \
@@ -625,8 +640,8 @@ static uint64_t make_cap(int cap) {
         return ((uint64_t) 1ULL << (uint64_t) cap);
 }
 
-static void test_config_parse_bounding_set(void) {
-        /* int config_parse_bounding_set(
+static void test_config_parse_capability_set(void) {
+        /* int config_parse_capability_set(
                  const char *unit,
                  const char *filename,
                  unsigned line,
@@ -638,38 +653,38 @@ static void test_config_parse_bounding_set(void) {
                  void *data,
                  void *userdata) */
         int r;
-        uint64_t capability_bounding_set_drop = 0;
+        uint64_t capability_bounding_set = 0;
 
-        r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+        r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
                               "CapabilityBoundingSet", 0, "CAP_NET_RAW",
-                              &capability_bounding_set_drop, NULL);
+                              &capability_bounding_set, NULL);
         assert_se(r >= 0);
-        assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW));
+        assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
 
-        r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+        r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
                               "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
-                              &capability_bounding_set_drop, NULL);
+                              &capability_bounding_set, NULL);
         assert_se(r >= 0);
-        assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+        assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
 
-        r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+        r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
                               "CapabilityBoundingSet", 0, "",
-                              &capability_bounding_set_drop, NULL);
+                              &capability_bounding_set, NULL);
         assert_se(r >= 0);
-        assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL));
+        assert_se(capability_bounding_set == UINT64_C(0));
 
-        r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+        r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
                               "CapabilityBoundingSet", 0, "~",
-                              &capability_bounding_set_drop, NULL);
+                              &capability_bounding_set, NULL);
         assert_se(r >= 0);
-        assert_se(capability_bounding_set_drop == (uint64_t) 0ULL);
+        assert_se(cap_test_all(capability_bounding_set));
 
-        capability_bounding_set_drop = 0;
-        r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+        capability_bounding_set = 0;
+        r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
                               "CapabilityBoundingSet", 0, "  'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
-                              &capability_bounding_set_drop, NULL);
+                              &capability_bounding_set, NULL);
         assert_se(r >= 0);
-        assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+        assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
 }
 
 static void test_config_parse_rlimit(void) {
@@ -680,51 +695,105 @@ static void test_config_parse_rlimit(void) {
         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
 
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
+
         assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_NOFILE]);
         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
         assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
 
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
+
+        rl[RLIMIT_NOFILE]->rlim_cur = 10;
+        rl[RLIMIT_NOFILE]->rlim_max = 20;
+
+        /* Invalid values don't change rl */
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_NOFILE]);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
+        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
+
         rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
 
-        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_CPU]);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
 
-        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_CPU]);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
 
-        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_CPU]);
+        assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
+        assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_CPU]);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
 
-        assert_se(config_parse_sec_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_CPU]);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
         assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
 
         rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
 
-        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_RTTIME]);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
 
-        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_RTTIME]);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_RTTIME]);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_RTTIME]);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
+
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+        assert_se(rl[RLIMIT_RTTIME]);
+        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
 
-        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_RTTIME]);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
 
-        assert_se(config_parse_usec_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
         assert_se(rl[RLIMIT_RTTIME]);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
         assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
@@ -778,7 +847,7 @@ int main(int argc, char *argv[]) {
 
         r = test_unit_file_get_set();
         test_config_parse_exec();
-        test_config_parse_bounding_set();
+        test_config_parse_capability_set();
         test_config_parse_rlimit();
         test_config_parse_pass_environ();
         test_load_env_file_1();
index 842ca40102ca514602289e8cded3febc54c7e7ab..3de94ef4253e46cecdc378aa2b3f3883c16ed14c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -27,6 +25,7 @@
 #include <string.h>
 
 #include "alloc-util.h"
+#include "glob-util.h"
 #include "hostname-util.h"
 #include "macro.h"
 #include "manager.h"
@@ -66,26 +65,26 @@ static void test_unit_name_is_valid(void) {
         assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY));
 }
 
-static void test_u_n_r_i_one(const char *pattern, const char *repl, const char *expected, int ret) {
+static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) {
         _cleanup_free_ char *t = NULL;
         assert_se(unit_name_replace_instance(pattern, repl, &t) == ret);
         puts(strna(t));
         assert_se(streq_ptr(t, expected));
 }
 
-static void test_u_n_r_i(void) {
+static void test_unit_name_replace_instance(void) {
         puts("-------------------------------------------------");
-        test_u_n_r_i_one("foo@.service", "waldo", "foo@waldo.service", 0);
-        test_u_n_r_i_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
-        test_u_n_r_i_one("xyz", "waldo", NULL, -EINVAL);
-        test_u_n_r_i_one("", "waldo", NULL, -EINVAL);
-        test_u_n_r_i_one("foo.service", "waldo", NULL, -EINVAL);
-        test_u_n_r_i_one(".service", "waldo", NULL, -EINVAL);
-        test_u_n_r_i_one("foo@", "waldo", NULL, -EINVAL);
-        test_u_n_r_i_one("@bar", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0);
+        test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
+        test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one("", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one("foo.service", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one(".service", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one("foo@", "waldo", NULL, -EINVAL);
+        test_unit_name_replace_instance_one("@bar", "waldo", NULL, -EINVAL);
 }
 
-static void test_u_n_f_p_one(const char *path, const char *suffix, const char *expected, int ret) {
+static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) {
         _cleanup_free_ char *t = NULL;
 
         assert_se(unit_name_from_path(path, suffix, &t) == ret);
@@ -100,19 +99,19 @@ static void test_u_n_f_p_one(const char *path, const char *suffix, const char *e
         }
 }
 
-static void test_u_n_f_p(void) {
+static void test_unit_name_from_path(void) {
         puts("-------------------------------------------------");
-        test_u_n_f_p_one("/waldo", ".mount", "waldo.mount", 0);
-        test_u_n_f_p_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
-        test_u_n_f_p_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
-        test_u_n_f_p_one("", ".mount", "-.mount", 0);
-        test_u_n_f_p_one("/", ".mount", "-.mount", 0);
-        test_u_n_f_p_one("///", ".mount", "-.mount", 0);
-        test_u_n_f_p_one("/foo/../bar", ".mount", NULL, -EINVAL);
-        test_u_n_f_p_one("/foo/./bar", ".mount", NULL, -EINVAL);
+        test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0);
+        test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
+        test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
+        test_unit_name_from_path_one("", ".mount", "-.mount", 0);
+        test_unit_name_from_path_one("/", ".mount", "-.mount", 0);
+        test_unit_name_from_path_one("///", ".mount", "-.mount", 0);
+        test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL);
+        test_unit_name_from_path_one("/foo/./bar", ".mount", NULL, -EINVAL);
 }
 
-static void test_u_n_f_p_i_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) {
+static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) {
         _cleanup_free_ char *t = NULL;
 
         assert_se(unit_name_from_path_instance(pattern, path, suffix, &t) == ret);
@@ -128,65 +127,71 @@ static void test_u_n_f_p_i_one(const char *pattern, const char *path, const char
         }
 }
 
-static void test_u_n_f_p_i(void) {
+static void test_unit_name_from_path_instance(void) {
         puts("-------------------------------------------------");
 
-        test_u_n_f_p_i_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
-        test_u_n_f_p_i_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
-        test_u_n_f_p_i_one("waldo", "/", ".mount", "waldo@-.mount", 0);
-        test_u_n_f_p_i_one("waldo", "", ".mount", "waldo@-.mount", 0);
-        test_u_n_f_p_i_one("waldo", "///", ".mount", "waldo@-.mount", 0);
-        test_u_n_f_p_i_one("waldo", "..", ".mount", NULL, -EINVAL);
-        test_u_n_f_p_i_one("waldo", "/foo", ".waldi", NULL, -EINVAL);
-        test_u_n_f_p_i_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "", ".mount", "waldo@-.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "///", ".mount", "waldo@-.mount", 0);
+        test_unit_name_from_path_instance_one("waldo", "..", ".mount", NULL, -EINVAL);
+        test_unit_name_from_path_instance_one("waldo", "/foo", ".waldi", NULL, -EINVAL);
+        test_unit_name_from_path_instance_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
 }
 
-static void test_u_n_t_p_one(const char *unit, const char *path, int ret) {
+static void test_unit_name_to_path_one(const char *unit, const char *path, int ret) {
         _cleanup_free_ char *p = NULL;
 
         assert_se(unit_name_to_path(unit, &p) == ret);
         assert_se(streq_ptr(path, p));
 }
 
-static void test_u_n_t_p(void) {
-        test_u_n_t_p_one("home.mount", "/home", 0);
-        test_u_n_t_p_one("home-lennart.mount", "/home/lennart", 0);
-        test_u_n_t_p_one("home-lennart-.mount", NULL, -EINVAL);
-        test_u_n_t_p_one("-home-lennart.mount", NULL, -EINVAL);
-        test_u_n_t_p_one("-home--lennart.mount", NULL, -EINVAL);
-        test_u_n_t_p_one("home-..-lennart.mount", NULL, -EINVAL);
-        test_u_n_t_p_one("", NULL, -EINVAL);
-        test_u_n_t_p_one("home/foo", NULL, -EINVAL);
+static void test_unit_name_to_path(void) {
+        test_unit_name_to_path_one("home.mount", "/home", 0);
+        test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0);
+        test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL);
+        test_unit_name_to_path_one("-home-lennart.mount", NULL, -EINVAL);
+        test_unit_name_to_path_one("-home--lennart.mount", NULL, -EINVAL);
+        test_unit_name_to_path_one("home-..-lennart.mount", NULL, -EINVAL);
+        test_unit_name_to_path_one("", NULL, -EINVAL);
+        test_unit_name_to_path_one("home/foo", NULL, -EINVAL);
 }
 
-static void test_u_n_m_one(const char *pattern, const char *expect, int ret) {
+static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pattern, const char *expect, int ret) {
         _cleanup_free_ char *t = NULL;
 
-        assert_se(unit_name_mangle(pattern, UNIT_NAME_NOGLOB, &t) == ret);
+        assert_se(unit_name_mangle(pattern, allow_globs, &t) == ret);
         puts(strna(t));
         assert_se(streq_ptr(t, expect));
 
         if (t) {
                 _cleanup_free_ char *k = NULL;
 
-                assert_se(unit_name_is_valid(t, UNIT_NAME_ANY));
+                assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) ||
+                          (allow_globs == UNIT_NAME_GLOB && string_is_glob(t)));
 
-                assert_se(unit_name_mangle(t, UNIT_NAME_NOGLOB, &k) == 0);
+                assert_se(unit_name_mangle(t, allow_globs, &k) == 0);
                 assert_se(streq_ptr(t, k));
         }
 }
 
-static void test_u_n_m(void) {
+static void test_unit_name_mangle(void) {
         puts("-------------------------------------------------");
-        test_u_n_m_one("foo.service", "foo.service", 0);
-        test_u_n_m_one("/home", "home.mount", 1);
-        test_u_n_m_one("/dev/sda", "dev-sda.device", 1);
-        test_u_n_m_one("üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
-        test_u_n_m_one("foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
-        test_u_n_m_one("_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
-        test_u_n_m_one("_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
-        test_u_n_m_one("xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
-        test_u_n_m_one("", NULL, -EINVAL);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foo.service", "foo.service", 0);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/home", "home.mount", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/dev/sda", "dev-sda.device", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
+        test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "", NULL, -EINVAL);
+
+        test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo.service", "foo.service", 0);
+        test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo", "foo.service", 1);
+        test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo*", "foo*", 0);
+        test_unit_name_mangle_one(UNIT_NAME_GLOB, "ü*", "\\xc3\\xbc*", 1);
 }
 
 static int test_unit_printf(void) {
@@ -460,11 +465,11 @@ static void test_unit_name_path_unescape(void) {
 int main(int argc, char* argv[]) {
         int rc = 0;
         test_unit_name_is_valid();
-        test_u_n_r_i();
-        test_u_n_f_p();
-        test_u_n_f_p_i();
-        test_u_n_m();
-        test_u_n_t_p();
+        test_unit_name_replace_instance();
+        test_unit_name_from_path();
+        test_unit_name_from_path_instance();
+        test_unit_name_mangle();
+        test_unit_name_to_path();
         TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
         test_unit_instance_is_valid();
         test_unit_prefix_is_valid();
index 09d37087e5ca7d79121d8a3877bbbd3ccfce7687..42c6a8d5e235f373d34995e8750d359b87ecb62d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index e98be5763ca1edb4706174b30f6c0afaa759d8ef..1ce5a5a24d0b18fd1ad366c36cd3cb7f023c06c4 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f6ed55878cc383b0e3b58e131f614fd56778b956..9a8a2657900d267d3d30e0cffbd982eb0252a738 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -545,38 +543,31 @@ static void test_unbase32hexmem(void) {
 static void test_base64mem(void) {
         char *b64;
 
-        b64 = base64mem("", strlen(""));
-        assert_se(b64);
+        assert_se(base64mem("", strlen(""), &b64) == 0);
         assert_se(streq(b64, ""));
         free(b64);
 
-        b64 = base64mem("f", strlen("f"));
-        assert_se(b64);
+        assert_se(base64mem("f", strlen("f"), &b64) == 4);
         assert_se(streq(b64, "Zg=="));
         free(b64);
 
-        b64 = base64mem("fo", strlen("fo"));
-        assert_se(b64);
+        assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
         assert_se(streq(b64, "Zm8="));
         free(b64);
 
-        b64 = base64mem("foo", strlen("foo"));
-        assert_se(b64);
+        assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
         assert_se(streq(b64, "Zm9v"));
         free(b64);
 
-        b64 = base64mem("foob", strlen("foob"));
-        assert_se(b64);
+        assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
         assert_se(streq(b64, "Zm9vYg=="));
         free(b64);
 
-        b64 = base64mem("fooba", strlen("fooba"));
-        assert_se(b64);
+        assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
         assert_se(streq(b64, "Zm9vYmE="));
         free(b64);
 
-        b64 = base64mem("foobar", strlen("foobar"));
-        assert_se(b64);
+        assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
         assert_se(streq(b64, "Zm9vYmFy"));
         free(b64);
 }
index d10d9f49af35a7a53338771b4980d1aa9b6d079e..e3c19647fc97f3f431dcfe0d9b31928cb6625d49 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 548d75a3c302aee0f9aabd208b880ae0a00f0938..b0b72fa78ae560e9dc67e8694f9b4f1f68b1629f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 564d72773a2e725d5429d2cd649a73e533e438d9..097963b41b951d26951b42594a5121185f671697 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -193,7 +191,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_time(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool relative = false, interactive = arg_ask_password;
         usec_t t;
         int r;
@@ -224,7 +222,7 @@ static int set_time(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_timezone(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(args);
@@ -247,7 +245,7 @@ static int set_timezone(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r, b;
 
         assert(args);
@@ -276,7 +274,7 @@ static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
 }
 
 static int set_ntp(sd_bus *bus, char **args, unsigned n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int b, r;
 
         assert(args);
@@ -490,7 +488,7 @@ static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
index 968ef8a7880f5fd88bcc78dba154b0174209fbc2..2a10135fbabced59cdcf38a92c8badef8a616e16 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -33,7 +31,6 @@
 #include "bus-util.h"
 #include "clock-util.h"
 #include "def.h"
-#include "event-util.h"
 #include "fileio-label.h"
 #include "fs-util.h"
 #include "path-util.h"
@@ -167,8 +164,8 @@ static int context_write_data_local_rtc(Context *c) {
 }
 
 static int context_read_ntp(Context *c, sd_bus *bus) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         const char *s;
         int r;
 
@@ -650,7 +647,7 @@ static const sd_bus_vtable timedate_vtable[] = {
 };
 
 static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         assert(c);
@@ -681,8 +678,8 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
 
 int main(int argc, char *argv[]) {
         Context context = {};
-        _cleanup_event_unref_ sd_event *event = NULL;
-        _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         log_set_target(LOG_TARGET_AUTO);
index 5881bc0c452c2437c4910471b9747208037f5e48..20c64a3354a63bfac410608d0d571292cff9a2a1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 56466fe462a9c518d69efff3cb366f4b992915b9..cba0724b1b8607c11f36e8a597f3e2fc2dbd86d3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,7 +20,6 @@
 ***/
 
 #include "conf-parser.h"
-
 #include "timesyncd-manager.h"
 
 const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length);
index 8dca538b3bb2d2306466808eb10592705499f6c0..d5e16db3a036a4904f43f093fdea9ddbb824b90b 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -372,7 +370,8 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
         if (r < 0)
                 return -errno;
 
-        touch("/var/lib/systemd/clock");
+        /* If touch fails, there isn't much we can do. Maybe it'll work next time. */
+        (void) touch("/var/lib/systemd/clock");
 
         m->drift_ppm = tmx.freq / 65536;
 
index 090b2fcba88433c71ee46a719878e93110ba82df..efe3e60d3e4ef694d4b556ce977470b71b7ee24e 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -22,8 +20,9 @@
 ***/
 
 #include "sd-event.h"
-#include "sd-resolve.h"
 #include "sd-network.h"
+#include "sd-resolve.h"
+
 #include "list.h"
 #include "ratelimit.h"
 
index f98e6b4cf0052eefde2a008f02a93cb2e737e797..6bda86fe6ebbb8820466a4f54025d480e972619c 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index 18c44445e1e53aed4e73d6d4d65e9e45beff43a6..8a19e41d670967924ea14933e8f957c3499b9535 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 #pragma once
 
 /***
@@ -21,8 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "socket-util.h"
 #include "list.h"
+#include "socket-util.h"
 
 typedef struct ServerAddress ServerAddress;
 typedef struct ServerName ServerName;
index 7f70eaaea0f8d93a421d54dd1e1693bae5e8ce02..23e19159e0bef9805dd246a21a63c0611af204a0 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index f9a759e2232f914919cc440d8304bcc625f4bf0e..7b105a6bd402e7b4583e4197067e771d77fc93a3 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -1075,7 +1073,7 @@ static int item_do_children(Item *i, const char *path, action_t action) {
                 errno = 0;
                 de = readdir(d);
                 if (!de) {
-                        if (errno != 0 && r == 0)
+                        if (errno > 0 && r == 0)
                                 r = -errno;
 
                         break;
@@ -1153,6 +1151,7 @@ static int create_item(Item *i) {
         _cleanup_free_ char *resolved = NULL;
         struct stat st;
         int r = 0;
+        int q = 0;
         CreationMode creation;
 
         assert(i);
@@ -1279,27 +1278,23 @@ static int create_item(Item *i) {
 
                 if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
                         r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
-                        if (r == -ENOTTY) {
+                        if (r == -ENOTTY)
                                 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of unsupported file system or because directory is not a subvolume: %m", i->path);
-                                return 0;
-                        }
-                        if (r == -EROFS) {
+                        else if (r == -EROFS)
                                 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of read-only file system: %m", i->path);
-                                return 0;
-                        }
-                        if (r == -ENOPROTOOPT) {
+                        else if (r == -ENOPROTOOPT)
                                 log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because quota support is disabled: %m", i->path);
-                                return 0;
-                        }
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
-                        if (r > 0)
+                        else if (r < 0)
+                                q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
+                        else if (r > 0)
                                 log_debug("Adjusted quota for subvolume \"%s\".", i->path);
-                        if (r == 0)
+                        else if (r == 0)
                                 log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
                 }
 
                 r = path_set_perms(i, i->path);
+                if (q < 0)
+                        return q;
                 if (r < 0)
                         return r;
 
index 8cfe10330d5e077148d896d0434817c701595676..7b67831e540a93a9d9b5bdf3331c204f7d8fc2ed 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -240,10 +238,50 @@ finish:
         return r;
 }
 
+static int send_passwords(const char *socket_name, char **passwords) {
+        _cleanup_free_ char *packet = NULL;
+        _cleanup_close_ int socket_fd = -1;
+        union sockaddr_union sa = { .un.sun_family = AF_UNIX };
+        size_t packet_length = 1;
+        char **p, *d;
+        int r;
+
+        assert(socket_name);
+
+        STRV_FOREACH(p, passwords)
+                packet_length += strlen(*p) + 1;
+
+        packet = new(char, packet_length);
+        if (!packet)
+                return -ENOMEM;
+
+        packet[0] = '+';
+
+        d = packet + 1;
+        STRV_FOREACH(p, passwords)
+                d = stpcpy(d, *p) + 1;
+
+        socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+        if (socket_fd < 0) {
+                r = log_debug_errno(errno, "socket(): %m");
+                goto finish;
+        }
+
+        strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
+
+        r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa,
+                   offsetof(struct sockaddr_un, sun_path) + strlen(socket_name));
+        if (r < 0)
+                r = log_debug_errno(errno, "sendto(): %m");
+
+finish:
+        memory_erase(packet, packet_length);
+        return r;
+}
+
 static int parse_password(const char *filename, char **wall) {
-        _cleanup_free_ char *socket_name = NULL, *message = NULL, *packet = NULL;
+        _cleanup_free_ char *socket_name = NULL, *message = NULL;
         bool accept_cached = false, echo = false;
-        size_t packet_length = 0;
         uint64_t not_after = 0;
         unsigned pid = 0;
 
@@ -298,8 +336,7 @@ static int parse_password(const char *filename, char **wall) {
                 *wall = _wall;
 
         } else {
-                union sockaddr_union sa = {};
-                _cleanup_close_ int socket_fd = -1;
+                _cleanup_strv_free_erase_ char **passwords = NULL;
 
                 assert(arg_action == ACTION_QUERY ||
                        arg_action == ACTION_WATCH);
@@ -311,32 +348,10 @@ static int parse_password(const char *filename, char **wall) {
                         return 0;
                 }
 
-                if (arg_plymouth) {
-                        _cleanup_strv_free_erase_ char **passwords = NULL;
-
+                if (arg_plymouth)
                         r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords);
-                        if (r >= 0) {
-                                char **p;
-
-                                packet_length = 1;
-                                STRV_FOREACH(p, passwords)
-                                        packet_length += strlen(*p) + 1;
-
-                                packet = new(char, packet_length);
-                                if (!packet)
-                                        r = -ENOMEM;
-                                else {
-                                        char *d = packet + 1;
-
-                                        STRV_FOREACH(p, passwords)
-                                                d = stpcpy(d, *p) + 1;
-
-                                        packet[0] = '+';
-                                }
-                        }
-
-                } else {
-                        _cleanup_string_free_erase_ char *password = NULL;
+                else {
+                        char *password = NULL;
                         int tty_fd = -1;
 
                         if (arg_console) {
@@ -356,48 +371,26 @@ static int parse_password(const char *filename, char **wall) {
                                 release_terminal();
                         }
 
-                        if (r >= 0) {
-                                packet_length = 1 + strlen(password) + 1;
-                                packet = new(char, packet_length);
-                                if (!packet)
-                                        r = -ENOMEM;
-                                else {
-                                        packet[0] = '+';
-                                        strcpy(packet + 1, password);
-                                }
-                        }
-                }
+                        if (r >= 0)
+                                r = strv_push(&passwords, password);
 
-                if (IN_SET(r, -ETIME, -ENOENT)) {
-                        /* If the query went away, that's OK */
-                        r = 0;
-                        goto finish;
-                }
-                if (r < 0) {
-                        log_error_errno(r, "Failed to query password: %m");
-                        goto finish;
+                        if (r < 0)
+                                string_free_erase(password);
                 }
 
-                socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
-                if (socket_fd < 0) {
-                        r = log_error_errno(errno, "socket(): %m");
-                        goto finish;
-                }
+                /* If the query went away, that's OK */
+                if (IN_SET(r, -ETIME, -ENOENT))
+                        return 0;
 
-                sa.un.sun_family = AF_UNIX;
-                strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
+                if (r < 0)
+                        return log_error_errno(r, "Failed to query password: %m");
 
-                r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name));
-                memory_erase(packet, packet_length);
+                r = send_passwords(socket_name, passwords);
                 if (r < 0)
-                        return log_error_errno(errno, "Failed to send: %m");
+                        return log_error_errno(r, "Failed to send: %m");
         }
 
         return 0;
-
-finish:
-        memory_erase(packet, packet_length);
-        return r;
 }
 
 static int wall_tty_block(void) {
index b6c95cd4524e08a8a89f12873cc9e5b8d247a181..349585b634e4ef21b29bf0ff3b72880c68ff66b6 100644 (file)
@@ -27,6 +27,7 @@
 #include "alloc-util.h"
 #include "libudev-private.h"
 #include "macro.h"
+#include "stdio-util.h"
 #include "string-util.h"
 
 #define BUFSIZE 16
@@ -91,7 +92,7 @@ static int prepare(char *dir, char *filename)
         if (r < 0 && errno != EEXIST)
                 return -errno;
 
-        snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
+        xsprintf(buf, "%s/%s", dir, filename);
 
         fd = open(buf,O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR);
         if (fd < 0)
index 0647008d90df2810c7dbac425f3372f42dc5817e..c00ff79123d6d400b831968c3b98bca8952c4f52 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
index 690b1a65aa0e4392671aa9736a47aae1a2263710..2e6e1d7150ce0b0f8e12efe1408e7fc443cbb664 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
index 77d9bf995ad63f9d7fc0ead1b0891df8b5a40ff4..15145fc5ebe6e0fa795600a8b68aa571f14734c1 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
index 4fcbee8b926c18a605f35499d74804bf117a0a73..f525fe211634cd01d0147ed3270871093681268a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
  This file is part of systemd.
 
index 3f99ae772445dfdc53831999acca0612a71c0d70..3bf1a9420013c95a2b299198c9fbecf02125b89a 100644 (file)
@@ -24,25 +24,25 @@ struct scsi_ioctl_command {
 /*
  * Default 5 second timeout
  */
-#define DEF_TIMEOUT        5000
+#define DEF_TIMEOUT 5000
 
-#define SENSE_BUFF_LEN        32
+#define SENSE_BUFF_LEN 32
 
 /*
  * The request buffer size passed to the SCSI INQUIRY commands, use 254,
  * as this is a nice value for some devices, especially some of the usb
  * mass storage devices.
  */
-#define        SCSI_INQ_BUFF_LEN        254
+#define SCSI_INQ_BUFF_LEN 254
 
 /*
  * SCSI INQUIRY vendor and model (really product) lengths.
  */
-#define VENDOR_LENGTH        8
-#define        MODEL_LENGTH        16
+#define VENDOR_LENGTH 8
+#define MODEL_LENGTH 16
 
-#define INQUIRY_CMD     0x12
-#define INQUIRY_CMDLEN  6
+#define INQUIRY_CMD 0x12
+#define INQUIRY_CMDLEN 6
 
 /*
  * INQUIRY VPD page 0x83 identifier descriptor related values. Reference the
@@ -52,34 +52,34 @@ struct scsi_ioctl_command {
 /*
  * id type values of id descriptors. These are assumed to fit in 4 bits.
  */
-#define SCSI_ID_VENDOR_SPECIFIC        0
-#define SCSI_ID_T10_VENDOR        1
-#define SCSI_ID_EUI_64                2
-#define SCSI_ID_NAA                3
-#define SCSI_ID_RELPORT                4
+#define SCSI_ID_VENDOR_SPECIFIC 0
+#define SCSI_ID_T10_VENDOR      1
+#define SCSI_ID_EUI_64          2
+#define SCSI_ID_NAA             3
+#define SCSI_ID_RELPORT         4
 #define SCSI_ID_TGTGROUP        5
 #define SCSI_ID_LUNGROUP        6
-#define SCSI_ID_MD5                7
-#define SCSI_ID_NAME                8
+#define SCSI_ID_MD5             7
+#define SCSI_ID_NAME            8
 
 /*
  * Supported NAA values. These fit in 4 bits, so the "don't care" value
  * cannot conflict with real values.
  */
-#define        SCSI_ID_NAA_DONT_CARE                0xff
-#define        SCSI_ID_NAA_IEEE_REG                5
-#define        SCSI_ID_NAA_IEEE_REG_EXTENDED        6
+#define SCSI_ID_NAA_DONT_CARE         0xff
+#define SCSI_ID_NAA_IEEE_REG          0x05
+#define SCSI_ID_NAA_IEEE_REG_EXTENDED 0x06
 
 /*
  * Supported Code Set values.
  */
-#define        SCSI_ID_BINARY        1
-#define        SCSI_ID_ASCII        2
+#define SCSI_ID_BINARY 1
+#define SCSI_ID_ASCII  2
 
 struct scsi_id_search_values {
-        u_char        id_type;
-        u_char        naa_type;
-        u_char        code_set;
+        u_char id_type;
+        u_char naa_type;
+        u_char code_set;
 };
 
 /*
@@ -87,13 +87,13 @@ struct scsi_id_search_values {
  * used a 1 bit right and masked version of these. So now CHECK_CONDITION
  * and friends (in <scsi/scsi.h>) are deprecated.
  */
-#define SCSI_CHECK_CONDITION 0x2
-#define SCSI_CONDITION_MET 0x4
-#define SCSI_BUSY 0x8
-#define SCSI_IMMEDIATE 0x10
+#define SCSI_CHECK_CONDITION         0x02
+#define SCSI_CONDITION_MET           0x04
+#define SCSI_BUSY                    0x08
+#define SCSI_IMMEDIATE               0x10
 #define SCSI_IMMEDIATE_CONDITION_MET 0x14
-#define SCSI_RESERVATION_CONFLICT 0x18
-#define SCSI_COMMAND_TERMINATED 0x22
-#define SCSI_TASK_SET_FULL 0x28
-#define SCSI_ACA_ACTIVE 0x30
-#define SCSI_TASK_ABORTED 0x40
+#define SCSI_RESERVATION_CONFLICT    0x18
+#define SCSI_COMMAND_TERMINATED      0x22
+#define SCSI_TASK_SET_FULL           0x28
+#define SCSI_ACA_ACTIVE              0x30
+#define SCSI_TASK_ABORTED            0x40
index c7ef783684b88ac8d744dde0bfd89e907df018c6..e079e286986e1a0eac443ed22fd301e83d43520c 100644 (file)
  * is normally one or some small number of descriptors.
  */
 static const struct scsi_id_search_values id_search_list[] = {
-        { SCSI_ID_TGTGROUP,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_BINARY },
-        { SCSI_ID_NAA,        SCSI_ID_NAA_IEEE_REG_EXTENDED,        SCSI_ID_BINARY },
-        { SCSI_ID_NAA,        SCSI_ID_NAA_IEEE_REG_EXTENDED,        SCSI_ID_ASCII },
-        { SCSI_ID_NAA,        SCSI_ID_NAA_IEEE_REG,        SCSI_ID_BINARY },
-        { SCSI_ID_NAA,        SCSI_ID_NAA_IEEE_REG,        SCSI_ID_ASCII },
+        { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE,         SCSI_ID_BINARY },
+        { SCSI_ID_NAA,      SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY },
+        { SCSI_ID_NAA,      SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII  },
+        { SCSI_ID_NAA,      SCSI_ID_NAA_IEEE_REG,          SCSI_ID_BINARY },
+        { SCSI_ID_NAA,      SCSI_ID_NAA_IEEE_REG,          SCSI_ID_ASCII  },
         /*
          * Devices already exist using NAA values that are now marked
          * reserved. These should not conflict with other values, or it is
@@ -64,14 +64,14 @@ static const struct scsi_id_search_values id_search_list[] = {
          * non-IEEE descriptors in a random order will get different
          * names.
          */
-        { SCSI_ID_NAA,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_BINARY },
-        { SCSI_ID_NAA,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_ASCII },
-        { SCSI_ID_EUI_64,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_BINARY },
-        { SCSI_ID_EUI_64,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_ASCII },
-        { SCSI_ID_T10_VENDOR,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_BINARY },
-        { SCSI_ID_T10_VENDOR,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_ASCII },
-        { SCSI_ID_VENDOR_SPECIFIC,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_BINARY },
-        { SCSI_ID_VENDOR_SPECIFIC,        SCSI_ID_NAA_DONT_CARE,        SCSI_ID_ASCII },
+        { SCSI_ID_NAA,             SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
+        { SCSI_ID_NAA,             SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII  },
+        { SCSI_ID_EUI_64,          SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
+        { SCSI_ID_EUI_64,          SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII  },
+        { SCSI_ID_T10_VENDOR,      SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
+        { SCSI_ID_T10_VENDOR,      SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII  },
+        { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
+        { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII  },
 };
 
 static const char hex_str[]="0123456789abcdef";
@@ -81,21 +81,21 @@ static const char hex_str[]="0123456789abcdef";
  * are used here.
  */
 
-#define DID_NO_CONNECT                        0x01        /* Unable to connect before timeout */
-#define DID_BUS_BUSY                        0x02        /* Bus remain busy until timeout */
-#define DID_TIME_OUT                        0x03        /* Timed out for some other reason */
-#define DRIVER_TIMEOUT                        0x06
-#define DRIVER_SENSE                        0x08        /* Sense_buffer has been set */
+#define DID_NO_CONNECT               0x01        /* Unable to connect before timeout */
+#define DID_BUS_BUSY                 0x02        /* Bus remain busy until timeout */
+#define DID_TIME_OUT                 0x03        /* Timed out for some other reason */
+#define DRIVER_TIMEOUT               0x06
+#define DRIVER_SENSE                 0x08        /* Sense_buffer has been set */
 
 /* The following "category" function returns one of the following */
 #define SG_ERR_CAT_CLEAN                0        /* No errors or other information */
 #define SG_ERR_CAT_MEDIA_CHANGED        1        /* interpreted from sense buffer */
 #define SG_ERR_CAT_RESET                2        /* interpreted from sense buffer */
-#define SG_ERR_CAT_TIMEOUT                3
-#define SG_ERR_CAT_RECOVERED                4        /* Successful command after recovered err */
-#define SG_ERR_CAT_NOTSUPPORTED                5        /* Illegal / unsupported command */
-#define SG_ERR_CAT_SENSE                98        /* Something else in the sense buffer */
-#define SG_ERR_CAT_OTHER                99        /* Some other error/warning */
+#define SG_ERR_CAT_TIMEOUT              3
+#define SG_ERR_CAT_RECOVERED            4        /* Successful command after recovered err */
+#define SG_ERR_CAT_NOTSUPPORTED         5        /* Illegal / unsupported command */
+#define SG_ERR_CAT_SENSE               98        /* Something else in the sense buffer */
+#define SG_ERR_CAT_OTHER               99        /* Some other error/warning */
 
 static int do_scsi_page80_inquiry(struct udev *udev,
                                   struct scsi_id_device *dev_scsi, int fd,
@@ -212,7 +212,7 @@ static int scsi_dump_sense(struct udev *udev,
                 s = sense_buffer[7] + 8;
                 if (sb_len < s) {
                         log_debug("%s: sense buffer too small %d bytes, %d bytes too short",
-                            dev_scsi->kernel, sb_len, s - sb_len);
+                                  dev_scsi->kernel, sb_len, s - sb_len);
                         return -1;
                 }
                 if ((code == 0x0) || (code == 0x1)) {
@@ -222,7 +222,7 @@ static int scsi_dump_sense(struct udev *udev,
                                  * Possible?
                                  */
                                 log_debug("%s: sense result too" " small %d bytes",
-                                    dev_scsi->kernel, s);
+                                          dev_scsi->kernel, s);
                                 return -1;
                         }
                         asc = sense_buffer[12];
@@ -233,15 +233,15 @@ static int scsi_dump_sense(struct udev *udev,
                         ascq = sense_buffer[3];
                 } else {
                         log_debug("%s: invalid sense code 0x%x",
-                            dev_scsi->kernel, code);
+                                  dev_scsi->kernel, code);
                         return -1;
                 }
                 log_debug("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
-                    dev_scsi->kernel, sense_key, asc, ascq);
+                          dev_scsi->kernel, sense_key, asc, ascq);
         } else {
                 if (sb_len < 4) {
                         log_debug("%s: sense buffer too small %d bytes, %d bytes too short",
-                            dev_scsi->kernel, sb_len, 4 - sb_len);
+                                  dev_scsi->kernel, sb_len, 4 - sb_len);
                         return -1;
                 }
 
@@ -249,9 +249,9 @@ static int scsi_dump_sense(struct udev *udev,
                         log_debug("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
                 else
                         log_debug("%s: sense = %2x %2x",
-                            dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
+                                  dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
                 log_debug("%s: non-extended sense class %d code 0x%0x",
-                    dev_scsi->kernel, sense_class, code);
+                          dev_scsi->kernel, sense_class, code);
 
         }
 
@@ -282,7 +282,7 @@ static int scsi_dump(struct udev *udev,
         }
 
         log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
-            dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
+                  dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
         if (io->status == SCSI_CHECK_CONDITION)
                 return scsi_dump_sense(udev, dev_scsi, io->sbp, io->sb_len_wr);
         else
@@ -302,8 +302,7 @@ static int scsi_dump_v4(struct udev *udev,
         }
 
         log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x",
-            dev_scsi->kernel, io->driver_status, io->transport_status,
-             io->device_status);
+                  dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status);
         if (io->device_status == SCSI_CHECK_CONDITION)
                 return scsi_dump_sense(udev, dev_scsi, (unsigned char *)(uintptr_t)io->response,
                                        io->response_len);
@@ -399,7 +398,7 @@ resend:
 error:
         if (retval < 0)
                 log_debug("%s: Unable to get INQUIRY vpd %d page 0x%x.",
-                    dev_scsi->kernel, evpd, page);
+                          dev_scsi->kernel, evpd, page);
 
         return retval;
 }
@@ -421,7 +420,7 @@ static int do_scsi_page0_inquiry(struct udev *udev,
                 return 1;
         }
         if (buffer[3] > len) {
-                log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel,         buffer[3]);
+                log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]);
                 return 1;
         }
 
@@ -464,7 +463,7 @@ static int prepend_vendor_model(struct udev *udev,
          */
         if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
                 log_debug("%s: expected length %d, got length %d",
-                     dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
+                          dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
                 return -1;
         }
         return ind;
@@ -529,7 +528,7 @@ static int check_fill_0x83_id(struct udev *udev,
 
         if (max_len < len) {
                 log_debug("%s: length %d too short - need %d",
-                    dev_scsi->kernel, max_len, len);
+                          dev_scsi->kernel, max_len, len);
                 return 1;
         }
 
@@ -785,7 +784,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
         len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
         if (max_len < len) {
                 log_debug("%s: length %d too short - need %d",
-                     dev_scsi->kernel, max_len, len);
+                          dev_scsi->kernel, max_len, len);
                 return 1;
         }
         /*
index d0e47ec6d888ae217f7b1ffbf07a1c2f844ed346..ed0ea5ce5f10bd1bb920c334e526aaac7894590b 100644 (file)
@@ -122,7 +122,7 @@ static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) {
         errno = 0;
         pl = blkid_probe_get_partitions(pr);
         if (!pl)
-                return errno ? -errno : -ENOMEM;
+                return errno > 0 ? -errno : -ENOMEM;
 
         nvals = blkid_partlist_numof_partitions(pl);
         for (i = 0; i < nvals; i++) {
index fddafbd4dc1b811a7b8a4e6022e2dea43586a772..3a3d8a1770038ae11316c2ec845e21c031311c85 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/input.h>
 
 #include "fd-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "udev.h"
 #include "util.h"
@@ -64,8 +65,8 @@ static void extract_info(struct udev_device *dev, const char *devpath, bool test
         if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0)
                 return;
 
-        snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo));
-        snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo));
+        xsprintf(width, "%d", abs_size_mm(&xabsinfo));
+        xsprintf(height, "%d", abs_size_mm(&yabsinfo));
 
         udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width);
         udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height);
@@ -91,7 +92,7 @@ static void get_cap_mask(struct udev_device *dev,
         if (!v)
                 v = "";
 
-        snprintf(text, sizeof(text), "%s", v);
+        xsprintf(text, "%s", v);
         log_debug("%s raw kernel attribute: %s", attr, text);
 
         memzero(bitmask, bitmask_size);
@@ -113,7 +114,8 @@ static void get_cap_mask(struct udev_device *dev,
 
         if (test) {
                 /* printf pattern with the right unsigned long number of hex chars */
-                snprintf(text, sizeof(text), "  bit %%4u: %%0%zulX\n", 2 * sizeof(unsigned long));
+                xsprintf(text, "  bit %%4u: %%0%zulX\n",
+                         2 * sizeof(unsigned long));
                 log_debug("%s decoded bit map:", attr);
                 val = bitmask_size / sizeof (unsigned long);
                 /* skip over leading zeros */
@@ -203,12 +205,12 @@ static bool test_pointers(struct udev_device *dev,
                         /* This path is taken by VMware's USB mouse, which has
                          * absolute axes, but no touch/pressure button. */
                         is_mouse = true;
-                else if (has_touch)
+                else if (has_touch || is_direct)
                         is_touchscreen = true;
                 else if (has_joystick_axes_or_buttons)
                         is_joystick = true;
         }
-        if (has_mt_coordinates && is_direct)
+        if (has_mt_coordinates && (is_direct || has_touch))
                 is_touchscreen = true;
 
         if (has_rel_coordinates && has_mouse_button)
index bf5c9c6b779a31d1ce286bbf958327ddeffc5217..8b1bcefe2dfe854e0b82ea880cd918469ae5d88a 100644 (file)
@@ -34,7 +34,7 @@
  *
  * Type of names:
  *   b<number>                             -- BCMA bus core number
- *   ccw<name>                             -- CCW bus group name
+ *   c<bus_id>                             -- CCW bus group name, without leading zeros [s390]
  *   o<index>[d<dev_port>]                 -- on-board device index number
  *   s<slot>[f<function>][d<dev_port>]     -- hotplug slot index number
  *   x<MAC>                                -- MAC address
 
 #include "fd-util.h"
 #include "fileio.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "udev.h"
 
+#define ONBOARD_INDEX_MAX (16*1024-1)
+
 enum netname_type{
         NET_UNDEF,
         NET_PCI,
@@ -149,6 +152,13 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
         if (idx <= 0)
                 return -EINVAL;
 
+        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for
+         * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary
+         * cut-off, which is somewhere beyond the realistic number of physical network interface a system might
+         * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */
+        if (idx > ONBOARD_INDEX_MAX)
+                return -ENOENT;
+
         /* kernel provided port index for multiple ports on a single PCI function */
         attr = udev_device_get_sysattr_value(dev, "dev_port");
         if (attr)
@@ -226,7 +236,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
                 err = -ENOENT;
                 goto out;
         }
-        snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci));
+        xsprintf(slots, "%s/slots", udev_device_get_syspath(pci));
         dir = opendir(slots);
         if (!dir) {
                 err = -errno;
@@ -245,7 +255,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
                         continue;
                 if (i < 1)
                         continue;
-                snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name);
+                xsprintf(str, "%s/%s/address", slots, dent->d_name);
                 if (read_one_line_file(str, &address) >= 0) {
                         /* match slot address with device by stripping the function */
                         if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address)))
@@ -378,7 +388,7 @@ static int names_bcma(struct udev_device *dev, struct netnames *names) {
                 return -EINVAL;
         /* suppress the common core == 0 */
         if (core > 0)
-                snprintf(names->bcma_core, sizeof(names->bcma_core), "b%u", core);
+                xsprintf(names->bcma_core, "b%u", core);
 
         names->type = NET_BCMA;
         return 0;
@@ -418,8 +428,15 @@ static int names_ccw(struct  udev_device *dev, struct netnames *names) {
         if (!bus_id_len || bus_id_len < 8 || bus_id_len > 9)
                 return -EINVAL;
 
+        /* Strip leading zeros from the bus id for aesthetic purposes. This
+         * keeps the ccw names stable, yet much shorter in general case of
+         * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is
+         * not prepended when it is zero.
+         */
+        bus_id += strspn(bus_id, ".0");
+
         /* Store the CCW bus-ID for use as network device name */
-        rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "ccw%s", bus_id);
+        rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "c%s", bus_id);
         if (rc >= 0 && rc < (int)sizeof(names->ccw_group))
                 names->type = NET_CCWGROUP;
         return 0;
@@ -467,9 +484,9 @@ static int ieee_oui(struct udev_device *dev, struct netnames *names, bool test)
         /* skip commonly misused 00:00:00 (Xerox) prefix */
         if (memcmp(names->mac, "\0\0\0", 3) == 0)
                 return -EINVAL;
-        snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X",
-                 names->mac[0], names->mac[1], names->mac[2],
-                 names->mac[3], names->mac[4], names->mac[5]);
+        xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X", names->mac[0],
+                 names->mac[1], names->mac[2], names->mac[3], names->mac[4],
+                 names->mac[5]);
         udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
         return 0;
 }
@@ -521,7 +538,7 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool
         if (err >= 0 && names.mac_valid) {
                 char str[IFNAMSIZ];
 
-                snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
+                xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix,
                          names.mac[0], names.mac[1], names.mac[2],
                          names.mac[3], names.mac[4], names.mac[5]);
                 udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
index f72894b5c58bdaafdbb94ea28329b2fd19ab8f71..8e477751358b8323ab3f0f647d35983bddbd878d 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index aa18c7e4207cd6f5de4e2b5752147296b328f7d4..b6ed45d8bae4f18bdc0bba10fead34c13a031e06 100644 (file)
@@ -663,6 +663,12 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
                         path_prepend(&path, "xen-%s", udev_device_get_sysname(parent));
                         parent = skip_subsystem(parent, "xen");
                         supported_parent = true;
+                } else if (streq(subsys, "virtio")) {
+                        while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent)))
+                                parent = udev_device_get_parent(parent);
+                        path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent));
+                        supported_transport = true;
+                        supported_parent = true;
                 } else if (streq(subsys, "scm")) {
                         path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
                         parent = skip_subsystem(parent, "scm");
index 5d6542d3ad4854e60be9817429b3d5e0fb5e778a..8d601c9c2c4e5c43597a1e511d5d537a66ed94bd 100644 (file)
@@ -31,7 +31,6 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "formats-util.h"
 #include "netlink-util.h"
@@ -638,7 +637,7 @@ static int spawn_wait(struct udev_event *event,
                 .pid = pid,
                 .accept_failure = accept_failure,
         };
-        _cleanup_event_unref_ sd_event *e = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
         int r, ret;
 
         r = sd_event_new(&e);
@@ -849,11 +848,11 @@ void udev_event_execute_rules(struct udev_event *event,
                         /* disable watch during event processing */
                         if (major(udev_device_get_devnum(dev)) != 0)
                                 udev_watch_end(event->udev, event->dev_db);
-                }
 
-                if (major(udev_device_get_devnum(dev)) == 0 &&
-                    streq(udev_device_get_action(dev), "move"))
-                        udev_device_copy_properties(dev, event->dev_db);
+                        if (major(udev_device_get_devnum(dev)) == 0 &&
+                            streq(udev_device_get_action(dev), "move"))
+                                udev_device_copy_properties(dev, event->dev_db);
+                }
 
                 udev_rules_apply_to_event(rules, event,
                                           timeout_usec, timeout_warn_usec,
index c2edf2c5cdcc694cd19003393777fcf62e934bad..5d2997fd8ff8971fe1d104e4fe74e34fb4b07f18 100644 (file)
@@ -29,6 +29,7 @@
 #include "fs-util.h"
 #include "selinux-util.h"
 #include "smack-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "udev.h"
 
@@ -346,9 +347,10 @@ void udev_node_add(struct udev_device *dev, bool apply,
                 return;
 
         /* always add /dev/{block,char}/$major:$minor */
-        snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
+        xsprintf(filename, "/dev/%s/%u:%u",
                  streq(udev_device_get_subsystem(dev), "block") ? "block" : "char",
-                 major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
+                 major(udev_device_get_devnum(dev)),
+                 minor(udev_device_get_devnum(dev)));
         node_symlink(dev, udev_device_get_devnode(dev), filename);
 
         /* create/update symlinks, add symlinks to name index */
@@ -365,8 +367,9 @@ void udev_node_remove(struct udev_device *dev) {
                 link_update(dev, udev_list_entry_get_name(list_entry), false);
 
         /* remove /dev/{block,char}/$major:$minor */
-        snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
+        xsprintf(filename, "/dev/%s/%u:%u",
                  streq(udev_device_get_subsystem(dev), "block") ? "block" : "char",
-                 major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
+                 major(udev_device_get_devnum(dev)),
+                 minor(udev_device_get_devnum(dev)));
         unlink(filename);
 }
index f1fdccaed88417fdb817635de78cd55518ae3f43..9ce5e975de9f06cfc325e06d9978bd54e17bba3b 100644 (file)
@@ -24,6 +24,7 @@
 #include <sys/inotify.h>
 #include <unistd.h>
 
+#include "stdio-util.h"
 #include "udev.h"
 
 static int inotify_fd = -1;
@@ -103,7 +104,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) {
                 return;
         }
 
-        snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+        xsprintf(filename, "/run/udev/watch/%d", wd);
         mkdir_parents(filename, 0755);
         unlink(filename);
         r = symlink(udev_device_get_id_filename(dev), filename);
@@ -127,7 +128,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev) {
         log_debug("removing watch on '%s'", udev_device_get_devnode(dev));
         inotify_rm_watch(inotify_fd, wd);
 
-        snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+        xsprintf(filename, "/run/udev/watch/%d", wd);
         unlink(filename);
 
         udev_device_set_watch_handle(dev, -1);
@@ -141,7 +142,7 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd) {
         if (inotify_fd < 0 || wd < 0)
                 return NULL;
 
-        snprintf(filename, sizeof(filename), "/run/udev/watch/%d", wd);
+        xsprintf(filename, "/run/udev/watch/%d", wd);
         len = readlink(filename, device, sizeof(device));
         if (len <= 0 || (size_t)len == sizeof(device))
                 return NULL;
index 031a099d77b9f07b6c83af90d0865e694d37d483..948ad0f5a5f951558e6aa29dbd7106c45bbc88ce 100644 (file)
@@ -665,7 +665,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
         }
 
         if (test) {
-                _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+                _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
                 int r;
 
                 r = sd_hwdb_new(&hwdb);
index 60f122ebdab69ece78f88c2130d1bf44ce84f2b3..7bd2c1ea4237cbefc587fe9a4606a8dc1fc22bf6 100644 (file)
@@ -1,4 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 /*
  * Copyright (C) 2007-2012 Kay Sievers <kay@vrfy.org>
  *
index 6d9d7651538d233446055df85eea4f14019c567a..2c1c4a967b79b1fb9a9b071896903652d760c6f1 100644 (file)
@@ -47,7 +47,6 @@
 #include "cgroup-util.h"
 #include "cpu-set-util.h"
 #include "dev-setup.h"
-#include "event-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "formats-util.h"
@@ -350,7 +349,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
         switch (pid) {
         case 0: {
                 struct udev_device *dev = NULL;
-                _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+                _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
                 int fd_monitor;
                 _cleanup_close_ int fd_signal = -1, fd_ep = -1;
                 struct epoll_event ep_signal = { .events = EPOLLIN };
@@ -1651,7 +1650,8 @@ exit:
 
 int main(int argc, char *argv[]) {
         _cleanup_free_ char *cgroup = NULL;
-        int r, fd_ctrl, fd_uevent;
+        int fd_ctrl = -1, fd_uevent = -1;
+        int r;
 
         log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
index 4c44d5061370a0e7000e8e3e29e0d1a456f8e26f..931e583785ad2f452af025a234f46963bb94c242 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
index d50063cbcdd161620170a6199c47f93493c6ecce..8ae4a8a8336046de5d62aa0e5028b64287bab915 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -48,7 +46,7 @@ typedef struct Context {
 } Context;
 
 static usec_t get_startup_time(Context *c) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         usec_t t = 0;
         int r;
 
@@ -85,7 +83,7 @@ static int get_current_runlevel(Context *c) {
                 { '1', SPECIAL_RESCUE_TARGET     },
         };
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
         unsigned i;
 
index 252cbdb26cf50ec8cde5ad1e91956a4d7ed3047f..8bf44e21009d180edee23fe389531bcfb4b6865a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -23,7 +21,9 @@
 #include <unistd.h>
 
 #include "fileio.h"
+#include "fileio-label.h"
 #include "log.h"
+#include "selinux-util.h"
 #include "string-util.h"
 #include "util.h"
 
@@ -40,6 +40,8 @@ int main(int argc, char*argv[]) {
 
         umask(0022);
 
+        mac_selinux_init(NULL);
+
         if (streq(argv[1], "start")) {
                 int r = 0;
 
@@ -65,7 +67,7 @@ int main(int argc, char*argv[]) {
         } else if (streq(argv[1], "stop")) {
                 int r;
 
-                r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+                r = write_string_file_atomic_label("/run/nologin", "System is going down.");
                 if (r < 0) {
                         log_error_errno(r, "Failed to create /run/nologin: %m");
                         return EXIT_FAILURE;
@@ -76,5 +78,7 @@ int main(int argc, char*argv[]) {
                 return EXIT_FAILURE;
         }
 
+        mac_selinux_finish();
+
         return EXIT_SUCCESS;
 }
index a5f4529cfdbd1c4c88aeb758a9f3f5e4efed1355..8a1b824e65d9bfa1fe1feb362fafc090bafbc48f 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -39,6 +37,7 @@
 #include "log.h"
 #include "process-util.h"
 #include "signal-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
 #include "util.h"
@@ -215,11 +214,11 @@ static void font_copy_to_all_vcs(int fd) {
                         continue;
 
                 /* skip non-allocated ttys */
-                snprintf(vcname, sizeof(vcname), "/dev/vcs%i", i);
+                xsprintf(vcname, "/dev/vcs%i", i);
                 if (access(vcname, F_OK) < 0)
                         continue;
 
-                snprintf(vcname, sizeof(vcname), "/dev/tty%i", i);
+                xsprintf(vcname, "/dev/tty%i", i);
                 vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC);
                 if (vcfd < 0)
                         continue;
index 5e04c821b60df686791ab53b50abdb390281eb8d..5a25de45128d3f2eaf0a2b4c69712317b8dc0419 100644 (file)
@@ -9,4 +9,4 @@
 # and systemd-coredump(8) and core(5) for the explanation of the
 # setting below.
 
-kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %e
+kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %e
index bb3aaaf821950e6a0eb99e7c3922a56bb2e41f67..c065034d2986b560f72bde58dde159f7fae082a3 100644 (file)
@@ -1,2 +1,3 @@
 /basic.conf
 /systemd.conf
+/systemd-remote.conf
index 823d6cb200118a10c795fd14496fd429c52a8995..b2dc5ebd4ffd43304792fcd0943a3aa7b1df7c53 100644 (file)
@@ -19,7 +19,6 @@ g wheel   -     -            -
 
 # Access to certain kernel and userspace facilities
 g kmem    -     -            -
-g lock    -     -            -
 g tty     @TTY_GID@     -            -
 g utmp    -     -            -
 
diff --git a/sysusers.d/systemd-remote.conf b/sysusers.d/systemd-remote.conf
deleted file mode 100644 (file)
index 15969e9..0000000
+++ /dev/null
@@ -1,10 +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.
-
-u systemd-journal-gateway - "systemd Journal Gateway"
-u systemd-journal-remote  - "systemd Journal Remote"
-u systemd-journal-upload  - "systemd Journal Upload"
diff --git a/sysusers.d/systemd-remote.conf.m4 b/sysusers.d/systemd-remote.conf.m4
new file mode 100644 (file)
index 0000000..0e9d71c
--- /dev/null
@@ -0,0 +1,14 @@
+#  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.
+
+m4_ifdef(`HAVE_MICROHTTPD',
+u systemd-journal-gateway - "systemd Journal Gateway"
+u systemd-journal-remote  - "systemd Journal Remote"
+)m4_dnl
+m4_ifdef(`HAVE_LIBCURL',
+u systemd-journal-upload  - "systemd Journal Upload"
+)m4_dnl
index 81b1d79c374a01d1238b1945086adff85f430ae4..317240a9fdd76abe2fd66a7b81b7d59f5ee2ba3f 100644 (file)
@@ -16,3 +16,6 @@ u systemd-resolve   - "systemd Resolver"
 m4_ifdef(`ENABLE_TIMESYNCD',
 u systemd-timesync  - "systemd Time Synchronization"
 )m4_dnl
+m4_ifdef(`ENABLE_COREDUMP',
+u systemd-coredump  - "systemd Core Dumper"
+)m4_dnl
index 5c7aca43a8e6a5e4557e783e4a4cade1fbe1ad3a..fa7e73ce3ad17343c638bef03a5a891b97e028e3 100644 (file)
@@ -36,7 +36,7 @@ you can even skip the "clean" and "setup" if you want to run the machine again.
 $ sudo make KERNEL_APPEND="systemd.unit=multi-user.target" run
 
 You can specify a different kernel and initramfs with $KERNEL_BIN and $INITRD.
-(Fedora's default kernel path and initramfs are used by default)
+(Fedora's or Debian's default kernel path and initramfs are used by default)
 
 $ sudo make KERNEL_BIN=/boot/vmlinuz-foo INITRD=/boot/initramfs-bar clean check
 
index b6b474393daa8c7c049d9f093a9f17523b88ea6b..6963d8c88df5c6c486ab272de11658f6b9b07bbc 100755 (executable)
@@ -11,7 +11,7 @@ check_result_qemu() {
     mount ${LOOPDEV}p1 $TESTDIR/root
     [[ -e $TESTDIR/root/testok ]] && ret=0
     [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
-    [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR
+    cp -a $TESTDIR/root/var/log/journal $TESTDIR
     umount $TESTDIR/root
     [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
     ls -l $TESTDIR/journal/*/*.journal
@@ -58,9 +58,16 @@ Type=oneshot
 EOF
 
         setup_testsuite
-    )
+    ) || return 1
     setup_nspawn_root
 
+    # mask some services that we do not want to run in these tests
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
 }
index 2997da06ff1e42855376e841dee147044181a9f0..242090c76119d249d4d5d05172a64e204b448611 100755 (executable)
@@ -13,7 +13,7 @@ check_result_qemu() {
     [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
     cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
     mount /dev/mapper/varcrypt $TESTDIR/root/var
-    [[ -f $TESTDIR/root/var/log/journal ]] && cp -a $TESTDIR/root/var/log/journal $TESTDIR
+    cp -a $TESTDIR/root/var/log/journal $TESTDIR
     umount $TESTDIR/root/var
     umount $TESTDIR/root
     cryptsetup luksClose /dev/mapper/varcrypt
@@ -76,8 +76,7 @@ EOF
         cat >>$initdir/etc/fstab <<EOF
 /dev/mapper/varcrypt    /var    ext3    defaults 0 1
 EOF
-    )
-    setup_nspawn_root
+    ) || return 1
 
     ddebug "umount $TESTDIR/root/var"
     umount $TESTDIR/root/var
index 42d475fe2fbaef2dbe8db279d9595ac0bae56538..0c7d4439a202f2862db63dd74f657ee4e308d26d 100755 (executable)
@@ -4,9 +4,12 @@
 # installed job.
 
 systemctl start --no-block hello-after-sleep.target
-# sleep is now running, hello/start is waiting. Verify that:
+
 systemctl list-jobs > /root/list-jobs.txt
-grep 'sleep\.service.*running' /root/list-jobs.txt || exit 1
+while ! grep 'sleep\.service.*running' /root/list-jobs.txt; do
+    systemctl list-jobs > /root/list-jobs.txt
+done
+
 grep 'hello\.service.*waiting' /root/list-jobs.txt || exit 1
 
 # This is supposed to finish quickly, not wait for sleep to finish.
@@ -47,4 +50,3 @@ systemctl stop --job-mode=replace-irreversibly unstoppable.service || exit 1
 systemctl start unstoppable.service || exit 1
 
 touch /testok
-exit 0
index 41e02e2c8acc67ba7b99a4c6060e04946bec029d..83393435f0a48126443cd0f11d28281f8569c6f5 100755 (executable)
@@ -63,7 +63,7 @@ EOF
         cp test-jobs.sh $initdir/
 
         setup_testsuite
-    )
+    ) || return 1
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
diff --git a/test/TEST-04-JOURNAL/Makefile b/test/TEST-04-JOURNAL/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
new file mode 100755 (executable)
index 0000000..6646ecc
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -x
+set -e
+set -o pipefail
+
+# Test stdout stream
+
+# Skip empty lines
+ID=$(journalctl --new-id128 | sed -n 2p)
+>/expected
+printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+ID=$(journalctl --new-id128 | sed -n 2p)
+>/expected
+printf $'<5>\n<6>\n<7>\n' | systemd-cat -t "$ID" --level-prefix true
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+# Remove trailing spaces
+ID=$(journalctl --new-id128 | sed -n 2p)
+printf "Trailing spaces\n">/expected
+printf $'<5>Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix true
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+ID=$(journalctl --new-id128 | sed -n 2p)
+printf "Trailing spaces\n">/expected
+printf $'Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix false
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+# Don't remove leading spaces
+ID=$(journalctl --new-id128 | sed -n 2p)
+printf $' \t Leading spaces\n'>/expected
+printf $'<5> \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix true
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+ID=$(journalctl --new-id128 | sed -n 2p)
+printf $' \t Leading spaces\n'>/expected
+printf $' \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix false
+journalctl --sync
+journalctl -b -o cat -t "$ID" >/output
+cmp /expected /output
+
+# Don't lose streams on restart
+systemctl start forever-print-hola
+sleep 3
+systemctl restart systemd-journald
+sleep 3
+systemctl stop forever-print-hola
+[[ ! -f "/i-lose-my-logs" ]]
+
+touch /testok
diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh
new file mode 100755 (executable)
index 0000000..1a14f76
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="Journal-related tests"
+
+. $TEST_BASE_DIR/test-functions
+
+check_result_qemu() {
+    ret=1
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+    [[ -e $TESTDIR/root/testok ]] && ret=0
+    [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+    cp -a $TESTDIR/root/var/log/journal $TESTDIR
+    umount $TESTDIR/root
+    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+    ls -l $TESTDIR/journal/*/*.journal
+    test -s $TESTDIR/failed && ret=$(($ret+1))
+    return $ret
+}
+
+test_run() {
+    if run_qemu; then
+        check_result_qemu || return 1
+    else
+        dwarn "can't run QEMU, skipping"
+    fi
+    if check_nspawn; then
+        run_nspawn
+        check_result_nspawn || return 1
+    else
+        dwarn "can't run systemd-nspawn, skipping"
+    fi
+    return 0
+}
+
+test_setup() {
+    create_empty_image
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+
+    # Create what will eventually be our root filesystem onto an overlay
+    (
+        LOG_LEVEL=5
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+        setup_basic_environment
+
+        # setup the testsuite service
+        cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-journal.sh
+Type=oneshot
+EOF
+
+        cat >$initdir/etc/systemd/system/forever-print-hola.service <<EOF
+[Unit]
+Description=ForeverPrintHola service
+
+[Service]
+Type=simple
+ExecStart=/bin/sh -x -c 'while :; do printf "Hola\n" || touch /i-lose-my-logs; sleep 1; done'
+EOF
+
+        cp test-journal.sh $initdir/
+
+        setup_testsuite
+    ) || return 1
+    setup_nspawn_root
+
+    ddebug "umount $TESTDIR/root"
+    umount $TESTDIR/root
+}
+
+test_cleanup() {
+    umount $TESTDIR/root 2>/dev/null
+    [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+    return 0
+}
+
+do_test "$@"
diff --git a/test/TEST-05-RLIMITS/Makefile b/test/TEST-05-RLIMITS/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-05-RLIMITS/test-rlimits.sh b/test/TEST-05-RLIMITS/test-rlimits.sh
new file mode 100755 (executable)
index 0000000..ba665c5
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -x
+set -e
+set -o pipefail
+
+[[ "$(systemctl show -p DefaultLimitNOFILESoft)" = "DefaultLimitNOFILESoft=10000" ]]
+[[ "$(systemctl show -p DefaultLimitNOFILE)" = "DefaultLimitNOFILE=16384" ]]
+
+[[ "$(systemctl show -p LimitNOFILESoft testsuite.service)" = "LimitNOFILESoft=10000" ]]
+[[ "$(systemctl show -p LimitNOFILE testsuite.service)" = "LimitNOFILE=16384" ]]
+
+[[ "$(ulimit -n -S)" = "10000" ]]
+[[ "$(ulimit -n -H)" = "16384" ]]
+
+touch /testok
diff --git a/test/TEST-05-RLIMITS/test.sh b/test/TEST-05-RLIMITS/test.sh
new file mode 100755 (executable)
index 0000000..6eaa0b8
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="Resource limits-related tests"
+
+. $TEST_BASE_DIR/test-functions
+
+check_result_qemu() {
+    ret=1
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+    [[ -e $TESTDIR/root/testok ]] && ret=0
+    [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+    cp -a $TESTDIR/root/var/log/journal $TESTDIR
+    umount $TESTDIR/root
+    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+    ls -l $TESTDIR/journal/*/*.journal
+    test -s $TESTDIR/failed && ret=$(($ret+1))
+    return $ret
+}
+
+test_run() {
+    if run_qemu; then
+        check_result_qemu || return 1
+    else
+        dwarn "can't run QEMU, skipping"
+    fi
+    if check_nspawn; then
+        run_nspawn
+        check_result_nspawn || return 1
+    else
+        dwarn "can't run systemd-nspawn, skipping"
+    fi
+    return 0
+}
+
+test_setup() {
+    create_empty_image
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+
+    # Create what will eventually be our root filesystem onto an overlay
+    (
+        LOG_LEVEL=5
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+        setup_basic_environment
+
+        cat >$initdir/etc/systemd/system.conf <<EOF
+[Manager]
+DefaultLimitNOFILE=10000:16384
+EOF
+
+        # setup the testsuite service
+        cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-rlimits.sh
+Type=oneshot
+EOF
+
+        cp test-rlimits.sh $initdir/
+
+        setup_testsuite
+    ) || return 1
+    setup_nspawn_root
+
+    ddebug "umount $TESTDIR/root"
+    umount $TESTDIR/root
+}
+
+test_cleanup() {
+    umount $TESTDIR/root 2>/dev/null
+    [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+    return 0
+}
+
+do_test "$@"
diff --git a/test/TEST-06-SELINUX/Makefile b/test/TEST-06-SELINUX/Makefile
new file mode 100644 (file)
index 0000000..5e89a29
--- /dev/null
@@ -0,0 +1,10 @@
+all:
+       @make -s --no-print-directory -C ../.. all
+       @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all
+setup:
+       @make --no-print-directory -C ../.. all
+       @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup
+clean:
+       @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean
+run:
+       @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run
diff --git a/test/TEST-06-SELINUX/systemd_test.if b/test/TEST-06-SELINUX/systemd_test.if
new file mode 100644 (file)
index 0000000..25c91ad
--- /dev/null
@@ -0,0 +1,8 @@
+template(`systemd_test_base_template', `
+       gen_require(`
+               attribute systemd_test_domain_type;
+       ')
+
+       type $1_t, systemd_test_domain_type;
+       domain_type($1_t)
+')
diff --git a/test/TEST-06-SELINUX/systemd_test.te b/test/TEST-06-SELINUX/systemd_test.te
new file mode 100644 (file)
index 0000000..ff01c09
--- /dev/null
@@ -0,0 +1,50 @@
+policy_module(systemd_test, 0.0.1)
+
+# declarations
+attribute systemd_test_domain_type;
+
+systemd_test_base_template(systemd_test)
+systemd_test_base_template(systemd_test_status)
+systemd_test_base_template(systemd_test_start)
+systemd_test_base_template(systemd_test_stop)
+systemd_test_base_template(systemd_test_reload)
+
+# systemd_test_domain_type
+
+require {
+       role system_r;
+       role unconfined_r;
+       type bin_t;
+       type initrc_t;
+       type systemd_systemctl_exec_t;
+       type unconfined_service_t;
+}
+
+role system_r types systemd_test_domain_type;
+role unconfined_r types systemd_test_domain_type;
+
+allow systemd_test_domain_type bin_t: file entrypoint;
+allow systemd_test_domain_type systemd_systemctl_exec_t: file entrypoint;
+allow initrc_t systemd_test_domain_type: process transition;
+allow unconfined_service_t systemd_test_domain_type: process transition;
+corecmd_exec_bin(systemd_test_domain_type)
+init_signal_script(systemd_test_domain_type)
+init_sigchld_script(systemd_test_domain_type)
+systemd_exec_systemctl(systemd_test_domain_type)
+userdom_use_user_ttys(systemd_test_domain_type)
+userdom_use_user_ptys(systemd_test_domain_type)
+
+optional_policy(`
+       dbus_system_bus_client(systemd_test_domain_type)
+       init_dbus_chat(systemd_test_domain_type)
+')
+
+# systemd_test_*_t
+require {
+       type systemd_unit_file_t;
+}
+
+allow systemd_test_status_t systemd_unit_file_t: service { status };
+allow systemd_test_start_t systemd_unit_file_t: service { start };
+allow systemd_test_stop_t systemd_unit_file_t: service { stop };
+allow systemd_test_reload_t systemd_unit_file_t: service { reload };
diff --git a/test/TEST-06-SELINUX/test-selinux-checks.sh b/test/TEST-06-SELINUX/test-selinux-checks.sh
new file mode 100755 (executable)
index 0000000..153fab3
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -x
+set -e
+set -o pipefail
+
+echo 1 >/sys/fs/selinux/enforce
+runcon -t systemd_test_start_t systemctl start hola
+runcon -t systemd_test_reload_t systemctl reload hola
+runcon -t systemd_test_stop_t systemctl stop hola
+
+touch /testok
diff --git a/test/TEST-06-SELINUX/test.sh b/test/TEST-06-SELINUX/test.sh
new file mode 100755 (executable)
index 0000000..4f5895b
--- /dev/null
@@ -0,0 +1,135 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="SELinux tests"
+
+# Requirements:
+# Fedora 23
+# selinux-policy-targeted
+# selinux-policy-devel
+
+. $TEST_BASE_DIR/test-functions
+SETUP_SELINUX=yes
+KERNEL_APPEND="$KERNEL_APPEND selinux=1"
+
+check_result_qemu() {
+    ret=1
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+    [[ -e $TESTDIR/root/testok ]] && ret=0
+    [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+    cp -a $TESTDIR/root/var/log/journal $TESTDIR
+    umount $TESTDIR/root
+    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
+    ls -l $TESTDIR/journal/*/*.journal
+    test -s $TESTDIR/failed && ret=$(($ret+1))
+    return $ret
+}
+
+test_run() {
+    if run_qemu; then
+        check_result_qemu || return 1
+    else
+        dwarn "can't run QEMU, skipping"
+    fi
+    return 0
+}
+
+test_setup() {
+    create_empty_image
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+
+    # Create what will eventually be our root filesystem onto an overlay
+    (
+        LOG_LEVEL=5
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+        setup_basic_environment
+
+        # setup the testsuite service
+        cat <<EOF >$initdir/etc/systemd/system/testsuite.service
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-selinux-checks.sh
+Type=oneshot
+EOF
+
+        cat <<EOF >$initdir/etc/systemd/system/hola.service
+[Service]
+Type=oneshot
+ExecStart=/bin/echo Start Hola
+ExecReload=/bin/echo Reload Hola
+ExecStop=/bin/echo Stop Hola
+RemainAfterExit=yes
+EOF
+
+        setup_testsuite
+
+        cat <<EOF >$initdir/etc/systemd/system/load-systemd-test-module.service
+[Unit]
+Description=Load systemd-test module
+DefaultDependencies=no
+Requires=local-fs.target
+Conflicts=shutdown.target
+After=local-fs.target
+Before=sysinit.target shutdown.target autorelabel.service
+ConditionSecurity=selinux
+ConditionPathExists=|/.load-systemd-test-module
+
+[Service]
+ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile load  && rm /.load-systemd-test-module'
+Type=oneshot
+TimeoutSec=0
+RemainAfterExit=yes
+EOF
+
+        touch $initdir/.load-systemd-test-module
+        mkdir -p $initdir/etc/systemd/system/basic.target.wants
+        ln -fs load-systemd-test-module.service $initdir/etc/systemd/system/basic.target.wants/load-systemd-test-module.service
+
+        local _modules_dir=/var/lib/selinux
+        rm -rf $initdir/$_modules_dir
+        if ! cp -ar $_modules_dir $initdir/$_modules_dir; then
+            dfatal "Failed to copy $_modules_dir"
+            exit 1
+        fi
+
+        local _policy_headers_dir=/usr/share/selinux/devel
+        rm -rf $initdir/$_policy_headers_dir
+        inst_dir /usr/share/selinux
+        if ! cp -ar $_policy_headers_dir $initdir/$_policy_headers_dir; then
+            dfatal "Failed to copy $_policy_headers_dir"
+            exit 1
+        fi
+
+        mkdir $initdir/systemd-test-module
+        cp systemd_test.te $initdir/systemd-test-module
+        cp systemd_test.if $initdir/systemd-test-module
+        cp test-selinux-checks.sh $initdir
+        dracut_install -o sesearch
+        dracut_install runcon
+        dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile
+    ) || return 1
+
+    # mask some services that we do not want to run in these tests
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+    ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+    ddebug "umount $TESTDIR/root"
+    umount $TESTDIR/root
+}
+
+test_cleanup() {
+    umount $TESTDIR/root 2>/dev/null
+    [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+    return 0
+}
+
+do_test "$@"
diff --git a/test/TEST-07-ISSUE-1981/Makefile b/test/TEST-07-ISSUE-1981/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-07-ISSUE-1981/test-segfault.sh b/test/TEST-07-ISSUE-1981/test-segfault.sh
new file mode 100755 (executable)
index 0000000..48f05d8
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -x
+set -e
+
+>/failed
+
+cat <<'EOL' >/lib/systemd/system/my.service
+[Service]
+Type=oneshot
+ExecStart=/bin/echo Timer runs me
+EOL
+
+cat <<'EOL' >/lib/systemd/system/my.timer
+[Timer]
+OnBootSec=10s
+OnUnitInactiveSec=1h
+EOL
+
+systemctl unmask my.timer
+
+systemctl start my.timer
+
+mkdir -p /etc/systemd/system/my.timer.d/
+cat <<'EOL' >/etc/systemd/system/my.timer.d/override.conf
+[Timer]
+OnBootSec=10s
+OnUnitInactiveSec=1h
+EOL
+
+systemctl daemon-reload
+
+systemctl mask my.timer
+
+touch /testok
+rm /failed
diff --git a/test/TEST-07-ISSUE-1981/test.sh b/test/TEST-07-ISSUE-1981/test.sh
new file mode 100755 (executable)
index 0000000..dcb6ece
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/1981"
+
+. $TEST_BASE_DIR/test-functions
+
+test_run() {
+    dwarn "skipping QEMU"
+    if check_nspawn; then
+        timeout --foreground 30s systemd-nspawn --kill-signal=SIGKILL --boot --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
+        check_result_nspawn || return 1
+    else
+        dwarn "can't run systemd-nspawn, skipping"
+    fi
+    return 0
+}
+
+test_setup() {
+    create_empty_image
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+
+    # Create what will eventually be our root filesystem onto an overlay
+    (
+        LOG_LEVEL=5
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+        setup_basic_environment
+
+        # setup the testsuite service
+        cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+After=multi-user.target
+
+[Service]
+ExecStart=/test-segfault.sh
+Type=oneshot
+EOF
+
+        cp test-segfault.sh $initdir/
+
+        setup_testsuite
+    ) || return 1
+    setup_nspawn_root
+
+    ddebug "umount $TESTDIR/root"
+    umount $TESTDIR/root
+}
+
+test_cleanup() {
+    umount $TESTDIR/root 2>/dev/null
+    [[ $LOOPDEV ]] && losetup -d $LOOPDEV
+    return 0
+}
+
+do_test "$@"
diff --git a/test/networkd-test.py b/test/networkd-test.py
new file mode 100755 (executable)
index 0000000..d76ab50
--- /dev/null
@@ -0,0 +1,371 @@
+#!/usr/bin/env python3
+#
+# networkd integration test
+# This uses temporary configuration in /run and temporary veth devices, and
+# does not write anything on disk or change any system configuration;
+# but it assumes (and checks at the beginning) that networkd is not currently
+# running.
+# This can be run on a normal installation, in QEMU, nspawn, or LXC.
+# ATTENTION: This uses the *installed* networkd, not the one from the built
+# source tree.
+#
+# (C) 2015 Canonical Ltd.
+# Author: Martin Pitt <martin.pitt@ubuntu.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/>.
+
+import os
+import sys
+import time
+import unittest
+import tempfile
+import subprocess
+import shutil
+
+networkd_active = subprocess.call(['systemctl', 'is-active', '--quiet',
+                                   'systemd-networkd']) == 0
+have_dnsmasq = shutil.which('dnsmasq')
+
+
+@unittest.skipIf(networkd_active,
+                 'networkd is already active')
+class ClientTestBase:
+    def setUp(self):
+        self.iface = 'test_eth42'
+        self.if_router = 'router_eth42'
+        self.workdir_obj = tempfile.TemporaryDirectory()
+        self.workdir = self.workdir_obj.name
+        self.config = '/run/systemd/network/test_eth42.network'
+        os.makedirs(os.path.dirname(self.config), exist_ok=True)
+
+        # avoid "Failed to open /dev/tty" errors in containers
+        os.environ['SYSTEMD_LOG_TARGET'] = 'journal'
+
+        # determine path to systemd-networkd-wait-online
+        for p in ['/usr/lib/systemd/systemd-networkd-wait-online',
+                  '/lib/systemd/systemd-networkd-wait-online']:
+            if os.path.exists(p):
+                self.networkd_wait_online = p
+                break
+        else:
+            self.fail('systemd-networkd-wait-online not found')
+
+        # get current journal cursor
+        out = subprocess.check_output(['journalctl', '-b', '--quiet',
+                                       '--no-pager', '-n0', '--show-cursor'],
+                                      universal_newlines=True)
+        self.assertTrue(out.startswith('-- cursor:'))
+        self.journal_cursor = out.split()[-1]
+
+    def tearDown(self):
+        self.shutdown_iface()
+        if os.path.exists(self.config):
+            os.unlink(self.config)
+        subprocess.call(['systemctl', 'stop', 'systemd-networkd'])
+
+    def show_journal(self, unit):
+        '''Show journal of given unit since start of the test'''
+
+        print('---- %s ----' % unit)
+        sys.stdout.flush()
+        subprocess.call(['journalctl', '-b', '--no-pager', '--quiet',
+                         '--cursor', self.journal_cursor, '-u', unit])
+
+    def create_iface(self, ipv6=False):
+        '''Create test interface with DHCP server behind it'''
+
+        raise NotImplementedError('must be implemented by a subclass')
+
+    def shutdown_iface(self):
+        '''Remove test interface and stop DHCP server'''
+
+        raise NotImplementedError('must be implemented by a subclass')
+
+    def print_server_log(self):
+        '''Print DHCP server log for debugging failures'''
+
+        raise NotImplementedError('must be implemented by a subclass')
+
+    def do_test(self, coldplug=True, ipv6=False, extra_opts='',
+                online_timeout=10, dhcp_mode='yes'):
+        with open(self.config, 'w') as f:
+            f.write('''[Match]
+Name=%s
+[Network]
+DHCP=%s
+%s''' % (self.iface, dhcp_mode, extra_opts))
+
+        if coldplug:
+            # create interface first, then start networkd
+            self.create_iface(ipv6=ipv6)
+            subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+        else:
+            # start networkd first, then create interface
+            subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+            self.create_iface(ipv6=ipv6)
+
+        try:
+            subprocess.check_call([self.networkd_wait_online, '--interface',
+                                   self.iface, '--timeout=%i' % online_timeout])
+
+            if ipv6:
+                # check iface state and IP 6 address; FIXME: we need to wait a bit
+                # longer, as the iface is "configured" already with IPv4 *or*
+                # IPv6, but we want to wait for both
+                for timeout in range(10):
+                    out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface])
+                    if b'state UP' in out and b'inet6 2600' in out and b'inet 192.168' in out:
+                        break
+                    time.sleep(1)
+                else:
+                    self.fail('timed out waiting for IPv6 configuration')
+
+                self.assertRegex(out, b'inet6 2600::.* scope global .*dynamic')
+                self.assertRegex(out, b'inet6 fe80::.* scope link')
+            else:
+                # should have link-local address on IPv6 only
+                out = subprocess.check_output(['ip', '-6', 'a', 'show', 'dev', self.iface])
+                self.assertRegex(out, b'inet6 fe80::.* scope link')
+                self.assertNotIn(b'scope global', out)
+
+            # should have IPv4 address
+            out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface])
+            self.assertIn(b'state UP', out)
+            self.assertRegex(out, b'inet 192.168.5.\d+/.* scope global dynamic')
+
+            # check networkctl state
+            out = subprocess.check_output(['networkctl'])
+            self.assertRegex(out, ('%s\s+ether\s+routable\s+unmanaged' % self.if_router).encode())
+            self.assertRegex(out, ('%s\s+ether\s+routable\s+configured' % self.iface).encode())
+
+            out = subprocess.check_output(['networkctl', 'status', self.iface])
+            self.assertRegex(out, b'Type:\s+ether')
+            self.assertRegex(out, b'State:\s+routable.*configured')
+            self.assertRegex(out, b'Address:\s+192.168.5.\d+')
+            if ipv6:
+                self.assertRegex(out, b'2600::')
+            else:
+                self.assertNotIn(b'2600::', out)
+            self.assertRegex(out, b'fe80::')
+            self.assertRegex(out, b'Gateway:\s+192.168.5.1')
+            self.assertRegex(out, b'DNS:\s+192.168.5.1')
+        except (AssertionError, subprocess.CalledProcessError):
+            # show networkd status, journal, and DHCP server log on failure
+            with open(self.config) as f:
+                print('\n---- %s ----\n%s' % (self.config, f.read()))
+            print('---- interface status ----')
+            sys.stdout.flush()
+            subprocess.call(['ip', 'a', 'show', 'dev', self.iface])
+            print('---- networkctl status %s ----' % self.iface)
+            sys.stdout.flush()
+            subprocess.call(['networkctl', 'status', self.iface])
+            self.show_journal('systemd-networkd.service')
+            self.print_server_log()
+            raise
+
+        # verify resolv.conf if it gets dynamically managed
+        if os.path.islink('/etc/resolv.conf'):
+            for timeout in range(50):
+                with open('/etc/resolv.conf') as f:
+                    contents = f.read()
+                if 'nameserver 192.168.5.1\n' in contents:
+                    break
+                # resolv.conf can have at most three nameservers; if we already
+                # have three different ones, that's also okay
+                if contents.count('nameserver ') >= 3:
+                    break
+                time.sleep(0.1)
+            else:
+                self.fail('nameserver 192.168.5.1 not found in /etc/resolv.conf')
+
+        if not coldplug:
+            # check post-down.d hook
+            self.shutdown_iface()
+
+    def test_coldplug_dhcp_yes_ip4(self):
+        # we have a 12s timeout on RA, so we need to wait longer
+        self.do_test(coldplug=True, ipv6=False, online_timeout=15)
+
+    def test_coldplug_dhcp_yes_ip4_no_ra(self):
+        # with disabling RA explicitly things should be fast
+        self.do_test(coldplug=True, ipv6=False,
+                     extra_opts='IPv6AcceptRouterAdvertisements=False')
+
+    def test_coldplug_dhcp_ip4_only(self):
+        # we have a 12s timeout on RA, so we need to wait longer
+        self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4',
+                     online_timeout=15)
+
+    def test_coldplug_dhcp_ip4_only_no_ra(self):
+        # with disabling RA explicitly things should be fast
+        self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4',
+                     extra_opts='IPv6AcceptRouterAdvertisements=False')
+
+    def test_coldplug_dhcp_ip6(self):
+        self.do_test(coldplug=True, ipv6=True)
+
+    def test_hotplug_dhcp_ip4(self):
+        # With IPv4 only we have a 12s timeout on RA, so we need to wait longer
+        self.do_test(coldplug=False, ipv6=False, online_timeout=15)
+
+    def test_hotplug_dhcp_ip6(self):
+        self.do_test(coldplug=False, ipv6=True)
+
+
+@unittest.skipUnless(have_dnsmasq, 'dnsmasq not installed')
+class DnsmasqClientTest(ClientTestBase, unittest.TestCase):
+    '''Test networkd client against dnsmasq'''
+
+    def setUp(self):
+        super().setUp()
+        self.dnsmasq = None
+
+    def create_iface(self, ipv6=False):
+        '''Create test interface with DHCP server behind it'''
+
+        # add veth pair
+        subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, 'type',
+                               'veth', 'peer', 'name', self.if_router])
+
+        # give our router an IP
+        subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router])
+        subprocess.check_call(['ip', 'a', 'add', '192.168.5.1/24', 'dev', self.if_router])
+        if ipv6:
+            subprocess.check_call(['ip', 'a', 'add', '2600::1/64', 'dev', self.if_router])
+        subprocess.check_call(['ip', 'link', 'set', self.if_router, 'up'])
+
+        # add DHCP server
+        self.dnsmasq_log = os.path.join(self.workdir, 'dnsmasq.log')
+        lease_file = os.path.join(self.workdir, 'dnsmasq.leases')
+        if ipv6:
+            extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20']
+        else:
+            extra_opts = []
+        self.dnsmasq = subprocess.Popen(
+            ['dnsmasq', '--keep-in-foreground', '--log-queries',
+             '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null',
+             '--dhcp-leasefile=' + lease_file, '--bind-interfaces',
+             '--interface=' + self.if_router, '--except-interface=lo',
+             '--dhcp-range=192.168.5.10,192.168.5.200'] + extra_opts)
+
+    def shutdown_iface(self):
+        '''Remove test interface and stop DHCP server'''
+
+        if self.if_router:
+            subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router])
+            self.if_router = None
+        if self.dnsmasq:
+            self.dnsmasq.kill()
+            self.dnsmasq.wait()
+            self.dnsmasq = None
+
+    def print_server_log(self):
+        '''Print DHCP server log for debugging failures'''
+
+        with open(self.dnsmasq_log) as f:
+            sys.stdout.write('\n\n---- dnsmasq log ----\n%s\n------\n\n' % f.read())
+
+
+class NetworkdClientTest(ClientTestBase, unittest.TestCase):
+    '''Test networkd client against networkd server'''
+
+    def setUp(self):
+        super().setUp()
+        self.dnsmasq = None
+
+    def create_iface(self, ipv6=False):
+        '''Create test interface with DHCP server behind it'''
+
+        # run "router-side" networkd in own mount namespace to shield it from
+        # "client-side" configuration and networkd
+        (fd, script) = tempfile.mkstemp(prefix='networkd-router.sh')
+        self.addCleanup(os.remove, script)
+        with os.fdopen(fd, 'w+') as f:
+            f.write('''#!/bin/sh -eu
+mkdir -p /run/systemd/network
+mkdir -p /run/systemd/netif
+mount -t tmpfs none /run/systemd/network
+mount -t tmpfs none /run/systemd/netif
+[ ! -e /run/dbus ] || mount -t tmpfs none /run/dbus
+# create router/client veth pair
+cat << EOF > /run/systemd/network/test.netdev
+[NetDev]
+Name=%(ifr)s
+Kind=veth
+
+[Peer]
+Name=%(ifc)s
+EOF
+
+cat << EOF > /run/systemd/network/test.network
+[Match]
+Name=%(ifr)s
+
+[Network]
+Address=192.168.5.1/24
+%(addr6)s
+DHCPServer=yes
+
+[DHCPServer]
+PoolOffset=10
+PoolSize=50
+DNS=192.168.5.1
+EOF
+
+# run networkd as in systemd-networkd.service
+exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//; p}')
+''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or ''})
+
+            os.fchmod(fd, 0o755)
+
+        subprocess.check_call(['systemd-run', '--unit=networkd-test-router.service',
+                               '-p', 'InaccessibleDirectories=-/etc/systemd/network',
+                               '-p', 'InaccessibleDirectories=-/run/systemd/network',
+                               '-p', 'InaccessibleDirectories=-/run/systemd/netif',
+                               '--service-type=notify', script])
+
+        # wait until devices got created
+        for timeout in range(50):
+            out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router])
+            if b'state UP' in out and b'scope global' in out:
+                break
+            time.sleep(0.1)
+
+    def shutdown_iface(self):
+        '''Remove test interface and stop DHCP server'''
+
+        if self.if_router:
+            subprocess.check_call(['systemctl', 'stop', 'networkd-test-router.service'])
+            # ensure failed transient unit does not stay around
+            subprocess.call(['systemctl', 'reset-failed', 'networkd-test-router.service'])
+            subprocess.call(['ip', 'link', 'del', 'dev', self.if_router])
+            self.if_router = None
+
+    def print_server_log(self):
+        '''Print DHCP server log for debugging failures'''
+
+        self.show_journal('networkd-test-router.service')
+
+    @unittest.skip('networkd does not have DHCPv6 server support')
+    def test_hotplug_dhcp_ip6(self):
+        pass
+
+    @unittest.skip('networkd does not have DHCPv6 server support')
+    def test_coldplug_dhcp_ip6(self):
+        pass
+
+
+if __name__ == '__main__':
+    unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
+                                                     verbosity=2))
index 49ee8027b2e1cba42a8312d56de4bb65d4a2d470..052c77d182a2eba730d3aeaf52b1ab90d937f006 100644 (file)
Binary files a/test/sys.tar.xz and b/test/sys.tar.xz differ
index 721e53a4ee322f3a89a00ffbb51e58f229b5b670..aca5f1eec658d2e719b03a8bebc80d1acefd2086 100644 (file)
@@ -23,6 +23,7 @@ import subprocess
 import tempfile
 import shutil
 from glob import glob
+import collections
 
 try:
     from configparser import RawConfigParser
@@ -32,6 +33,12 @@ except ImportError:
 
 sysv_generator = os.path.join(os.environ.get('builddir', '.'), 'systemd-sysv-generator')
 
+class MultiDict(collections.OrderedDict):
+    def __setitem__(self, key, value):
+        if isinstance(value, list) and key in self:
+            self[key].extend(value)
+        else:
+            super(MultiDict, self).__setitem__(key, value)
 
 class SysvGeneratorTest(unittest.TestCase):
     def setUp(self):
@@ -77,7 +84,14 @@ class SysvGeneratorTest(unittest.TestCase):
         for service in glob(self.out_dir + '/*.service'):
             if os.path.islink(service):
                 continue
-            cp = RawConfigParser()
+            try:
+                # for python3 we need here strict=False to parse multiple
+                # lines with the same key
+                cp = RawConfigParser(dict_type=MultiDict, strict=False)
+            except TypeError:
+                # RawConfigParser in python2 does not have the strict option
+                # but it allows multiple lines with the same key by default
+                cp = RawConfigParser(dict_type=MultiDict)
             cp.optionxform = lambda o: o  # don't lower-case option names
             with open(service) as f:
                 cp.readfp(f)
@@ -224,7 +238,7 @@ class SysvGeneratorTest(unittest.TestCase):
         s = self.run_generator()[1]['foo.service']
         self.assertEqual(set(s.options('Unit')),
                          set(['Documentation', 'SourcePath', 'Description', 'After']))
-        self.assertEqual(s.get('Unit', 'After'), 'nss-lookup.target rpcbind.target')
+        self.assertEqual(s.get('Unit', 'After').split(), ['nss-lookup.target', 'rpcbind.target'])
 
     def test_lsb_deps(self):
         '''LSB header dependencies to other services'''
diff --git a/test/test-execute/exec-capabilityambientset-merge.service b/test/test-execute/exec-capabilityambientset-merge.service
new file mode 100644 (file)
index 0000000..6496438
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"'
+Type=oneshot
+User=nobody
+AmbientCapabilities=CAP_NET_ADMIN
+AmbientCapabilities=CAP_NET_RAW
diff --git a/test/test-execute/exec-capabilityambientset.service b/test/test-execute/exec-capabilityambientset.service
new file mode 100644 (file)
index 0000000..d63f884
--- /dev/null
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"'
+Type=oneshot
+User=nobody
+AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
index a6eea662fc49c869629556b17d351e361148239a..6667e0524fa29d14f645b5f456db4b0c558046de 100644 (file)
@@ -13,8 +13,8 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
     ROOTLIBDIR=/usr/lib/systemd
 fi
 
-BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe"
-DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname"
+BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm"
+DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
 
 function find_qemu_bin() {
     # SUSE and Red Hat call the binary qemu-kvm
@@ -51,8 +51,11 @@ run_qemu() {
             && KERNEL_BIN="/boot/$MACHINE_ID/$KERNEL_VER/linux"
     fi
 
+    default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img
+    default_debian_initrd=/boot/initrd.img-${KERNEL_VER}
     [ "$KERNEL_BIN" ] || KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER
-    [ "$INITRD" ]     || INITRD=/boot/initramfs-${KERNEL_VER}.img
+    [ "$INITRD" ]     || { [ -e "$default_fedora_initrd" ] && INITRD=$default_fedora_initrd; }
+    [ "$INITRD" ]     || { [ "$LOOKS_LIKE_DEBIAN" ] && [ -e "$default_debian_initrd" ] && INITRD=$default_debian_initrd; }
     [ "$QEMU_SMP" ]   || QEMU_SMP=1
 
     find_qemu_bin || return 1
@@ -68,8 +71,7 @@ selinux=0 \
 $KERNEL_APPEND \
 "
 
-    QEMU_OPTIONS="-machine accel=kvm:tcg \
--smp $QEMU_SMP \
+    QEMU_OPTIONS="-smp $QEMU_SMP \
 -net none \
 -m 512M \
 -nographic \
@@ -80,13 +82,17 @@ $KERNEL_APPEND \
         QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
     fi
 
+    if [ -c /dev/kvm ]; then
+        QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
+    fi
+
     ( set -x
       $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND" $TESTDIR/rootdisk.img ) || return 1
 }
 
 run_nspawn() {
     set -x
-    ../../systemd-nspawn --boot --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
+    ../../systemd-nspawn --register=no --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND
 }
 
 setup_basic_environment() {
@@ -105,21 +111,105 @@ setup_basic_environment() {
     install_keymaps
     install_terminfo
     install_execs
+    install_fsck
     install_plymouth
     install_debug_tools
     install_ld_so_conf
+    setup_selinux
     strip_binaries
     install_depmod_files
     generate_module_dependencies
-    # softlink mtab
-    ln -fs /proc/self/mounts $initdir/etc/mtab
+}
+
+setup_selinux() {
+    # don't forget KERNEL_APPEND='... selinux=1 ...'
+    if [[ "$SETUP_SELINUX" != "yes" ]]; then
+        ddebug "Don't setup SELinux"
+        return 0
+    fi
+    ddebug "Setup SELinux"
+    local _conf_dir=/etc/selinux
+    local _fixfiles_tools="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles"
+
+    rm -rf $initdir/$_conf_dir
+    if ! cp -ar $_conf_dir $initdir/$_conf_dir; then
+        dfatal "Failed to copy $_conf_dir"
+        exit 1
+    fi
+
+    cat <<EOF >$initdir/etc/systemd/system/autorelabel.service
+[Unit]
+Description=Relabel all filesystems
+DefaultDependencies=no
+Requires=local-fs.target
+Conflicts=shutdown.target
+After=local-fs.target
+Before=sysinit.target shutdown.target
+ConditionSecurity=selinux
+ConditionPathExists=|/.autorelabel
+
+[Service]
+ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && fixfiles -f -F relabel && rm /.autorelabel && systemctl --force reboot'
+Type=oneshot
+TimeoutSec=0
+RemainAfterExit=yes
+EOF
+
+    touch $initdir/.autorelabel
+    mkdir -p $initdir/etc/systemd/system/basic.target.wants
+    ln -fs autorelabel.service $initdir/etc/systemd/system/basic.target.wants/autorelabel.service
+
+    dracut_install $_fixfiles_tools
+    dracut_install fixfiles
+    dracut_install sestatus
+}
+
+install_valgrind() {
+    if ! type -p valgrind; then
+        dfatal "Failed to install valgrind"
+        exit 1
+    fi
+
+    local _valgrind_bins=$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/')
+    dracut_install $_valgrind_bins
+
+    local _valgrind_libs=$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')
+    dracut_install $_valgrind_libs
+
+    local _valgrind_dbg_and_supp=$(
+        strace -e open valgrind /bin/true 2>&1 >/dev/null |
+        perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }'
+    )
+    dracut_install $_valgrind_dbg_and_supp
+}
+
+create_valgrind_wrapper() {
+    local _valgrind_wrapper=$initdir/$ROOTLIBDIR/systemd-under-valgrind
+    ddebug "Create $_valgrind_wrapper"
+    cat >$_valgrind_wrapper <<EOF
+#!/bin/bash
+
+exec valgrind --leak-check=full --log-file=/valgrind.out $ROOTLIBDIR/systemd "\$@"
+EOF
+    chmod 0755 $_valgrind_wrapper
+}
+
+install_fsck() {
+    dracut_install /sbin/fsck*
+    dracut_install -o /bin/fsck*
 }
 
 install_dmevent() {
     instmods dm_crypt =crypto
     type -P dmeventd >/dev/null && dracut_install dmeventd
     inst_libdir_file "libdevmapper-event.so*"
-    inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
+    if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
+        # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
+        # see https://anonscm.debian.org/cgit/pkg-lvm/lvm2.git/tree/debian/patches/0007-udev.patch
+        inst_rules 55-dm.rules 60-persistent-storage-dm.rules
+    else
+        inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
+    fi
 }
 
 install_systemd() {
@@ -142,12 +232,12 @@ install_missing_libraries() {
 create_empty_image() {
     rm -f "$TESTDIR/rootdisk.img"
     # Create the blank file to use as a root filesystem
-    dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=300
+    dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=400
     LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img)
     [ -b "$LOOPDEV" ] || return 1
     echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
     sfdisk "$LOOPDEV" <<EOF
-,290M
+,390M
 ,
 EOF
 
@@ -166,6 +256,10 @@ check_result_nspawn() {
 }
 
 strip_binaries() {
+    if [[ "$STRIP_BINARIES" = "no" ]]; then
+        ddebug "Don't strip binaries"
+        return 0
+    fi
     ddebug "Strip binaries"
     find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | xargs strip --strip-unneeded | ddebug
 }
@@ -285,6 +379,10 @@ install_pam() {
         inst $file
     done
 
+    # pam_unix depends on unix_chkpwd.
+    # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
+    dracut_install -o unix_chkpwd
+
     [[ "$LOOKS_LIKE_DEBIAN" ]] &&
         cp /etc/pam.d/systemd-user $initdir/etc/pam.d/
 }
@@ -1128,7 +1226,7 @@ inst_libdir_file() {
 }
 
 check_nspawn() {
-    [[ -d /sys/fs/cgroup/systemd ]]
+    [[ -d /run/systemd/system ]]
 }
 
 
index 0a8930357005749ad209654596dab3ea8617e7b7..638c3e8f4e211e75e860bd78c12c163548e7d10e 100755 (executable)
@@ -700,7 +700,7 @@ EOF
                 desc            => "big major number test",
                 devpath         => "/devices/virtual/misc/misc-fake1",
                 exp_name        => "node",
-                exp_majorminor  => "4095:1",
+                exp_majorminor  => "511:1",
                 rules                => <<EOF
 KERNEL=="misc-fake1", SYMLINK+="node"
 EOF
@@ -709,7 +709,7 @@ EOF
                 desc            => "big major and big minor number test",
                 devpath         => "/devices/virtual/misc/misc-fake89999",
                 exp_name        => "node",
-                exp_majorminor  => "4095:89999",
+                exp_majorminor  => "511:89999",
                 rules           => <<EOF
 KERNEL=="misc-fake89999", SYMLINK+="node"
 EOF
index 3cb0c63815a1a830d5e1b632692d0c27ba10e7c3..62e2ae0986234974d4bb89997f3ca73fda7144a6 100644 (file)
@@ -18,14 +18,6 @@ L /var/lock - - - - ../run/lock
 
 d /run/lock/subsys 0755 root root -
 
-# /run/lock/lockdev is used to serialize access to tty devices via
-# LCK..xxx style lock files, For more information see:
-# http://lists.freedesktop.org/archives/systemd-devel/2011-March/001823.html
-# On modern systems a BSD file lock is a better choice if
-# serialization is needed on those devices.
-
-d /run/lock/lockdev 0775 root lock -
-
 # /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the
 # kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and
 # 'quotacheck.mode=force'
index 1b8973a8891014df4da0c177fa8e8cd0a322a189..e19230f648e582b490b8e326811ade6e84bcbe57 100644 (file)
@@ -7,5 +7,7 @@
 
 # See tmpfiles.d(5) for details
 
-z /var/log/journal/remote 2755 root systemd-journal-remote - -
-z /run/log/journal/remote 2755 root systemd-journal-remote - -
+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 - -
index d9d51af9292b373ba8bf821dd599138b5bbe3b6d..0575408dbe21729c07b328aaa539e430300e5ba0 100644 (file)
@@ -33,9 +33,13 @@ A+ /run/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
 
 z /var/log/journal 2755 root systemd-journal - -
 z /var/log/journal/%m 2755 root systemd-journal - -
+z /var/log/journal/%m/system.journal 0640 root systemd-journal - -
 m4_ifdef(`HAVE_ACL',``
+a+ /var/log/journal    - - - - d:group:adm:r-x,d:group:wheel:r-x
+a+ /var/log/journal    - - - - group:adm:r-x,group:wheel:r-x
 a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
 a+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
+a+ /var/log/journal/%m/system.journal - - - - group:adm:r--,group:wheel:r--
 '')m4_dnl
 
 d /var/lib/systemd 0755 root root -
index 17b1325bba62647e4e2b74d74415dcfa8a7e1c12..8091683feed9a572dcf1ec5adc1c9b6d4f539b4d 100755 (executable)
@@ -268,6 +268,7 @@ def _make_section(template, name, directives, formatting):
             b = tree.SubElement(para, 'citerefentry')
             c = tree.SubElement(b, 'refentrytitle')
             c.text = manpage
+            c.attrib['target'] = varname
             d = tree.SubElement(b, 'manvolnum')
             d.text = manvolume
         entry.tail = '\n\n'
index c89740df05ca12240b05007c998a858f5d6325c6..2fff20a052cda92fdeadc15f2e4988f5adc87e3e 100644 (file)
@@ -25,6 +25,7 @@
 /systemd-binfmt.service
 /systemd-bootchart.service
 /systemd-bus-proxyd.service
+/systemd-coredump@.service
 /systemd-firstboot.service
 /systemd-fsck-root.service
 /systemd-fsck@.service
index e0e1e604f81d54b57b646c67dce559399abd2837..3e3527f894478528cbf65caf47b3da1cf80b8314 100644 (file)
@@ -10,8 +10,11 @@ Description=Basic System
 Documentation=man:systemd.special(7)
 Requires=sysinit.target
 Wants=sockets.target timers.target paths.target slices.target
-After=sysinit.target sockets.target paths.target slices.target
+After=sysinit.target sockets.target paths.target slices.target tmp.mount
 
 # We support /var, /tmp, /var/tmp, being on NFS, but we don't pull in
-# remote-fs.target by default, hence explicitly pull /var in here.
-RequiresMountsFor=/var /tmp /var/tmp
+# remote-fs.target by default, hence pull them in explicitly here. Note that we
+# require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as
+# we support that unit being masked, and this should not be considered an error.
+RequiresMountsFor=/var /var/tmp
+Wants=tmp.mount
index 5c807228294e099a319b8d0561e3bf78820bf20d..a345ec25d43fb97d6c5b08416e88f80e0c6f3ad1 100644 (file)
@@ -16,7 +16,7 @@ Before=getty.target
 
 [Service]
 Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
 ExecStart=-@SULOGIN@
 ExecStopPost=-@SYSTEMCTL@ poweroff
 Type=idle
index 5c11ca7d35023fc06b1831fca01f88f8218b43f4..8d29f96ca62c90160a838c2a8849d66df7e93e9a 100644 (file)
@@ -12,6 +12,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 Before=sysinit.target
 ConditionPathExists=/proc/sys/fs/mqueue
+ConditionCapability=CAP_SYS_ADMIN
 
 [Mount]
 What=mqueue
index 8dc3cbdede3fb234778f2fbbc0ed64c3384189fc..fb390eacfedfee931ea1ad863b81268fe4e1e81b 100644 (file)
@@ -15,7 +15,7 @@ Before=shutdown.target
 
 [Service]
 Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
 ExecStartPre=-/bin/plymouth --wait quit
 ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\ntry again to boot into default mode.'
 ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default"
index 0934a8751f3c9d6e77d72452430bd3af4fac0a9c..a9c8df11841ad40b81c6deb249de47a3f1ea399c 100644 (file)
@@ -10,7 +10,7 @@ Description=Create list of required static device nodes for the current kernel
 DefaultDependencies=no
 Before=sysinit.target systemd-tmpfiles-setup-dev.service
 ConditionCapability=CAP_SYS_MODULE
-ConditionPathExists=/lib/modules/%v/modules.devname
+ConditionFileNotEmpty=/lib/modules/%v/modules.devname
 
 [Service]
 Type=oneshot
index 432e4f3c8458ee7dd8423248528f107d04854fea..92553f61ddf642b5b47f6a2915883105c7b6fd6a 100644 (file)
@@ -15,9 +15,9 @@ Before=shutdown.target
 
 [Service]
 Environment=HOME=/root
-WorkingDirectory=/root
+WorkingDirectory=-/root
 ExecStartPre=-/bin/plymouth quit
-ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.'
+ExecStartPre=-/bin/echo -e 'Welcome to 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"
 Type=idle
 StandardInput=tty-force
index ebd93e2cda84a710ef8c44317dc748c5b61a1181..e940beb09f6f825884381a498fbcd8328e29e428 100644 (file)
@@ -11,6 +11,7 @@ Documentation=https://www.kernel.org/doc/Documentation/filesystems/fuse.txt
 Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 ConditionPathExists=/sys/fs/fuse/connections
+ConditionCapability=CAP_SYS_ADMIN
 After=systemd-modules-load.service
 Before=sysinit.target
 
diff --git a/units/systemd-coredump.socket b/units/systemd-coredump.socket
new file mode 100644 (file)
index 0000000..4cb2460
--- /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.
+
+[Unit]
+Description=Process Core Dump Socket
+Documentation=man:systemd-coredump(8)
+DefaultDependencies=no
+
+[Socket]
+ListenSequentialPacket=/run/systemd/coredump
+SocketMode=0600
+Accept=yes
+MaxConnections=16
diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
new file mode 100644 (file)
index 0000000..588c8d6
--- /dev/null
@@ -0,0 +1,24 @@
+#  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.
+
+[Unit]
+Description=Process Core Dump
+Documentation=man:systemd-coredump(8)
+DefaultDependencies=no
+RequiresMountsFor=/var/lib/systemd/coredump
+Conflicts=shutdown.target
+After=systemd-remount-fs.service systemd-journald.socket
+Requires=systemd-journald.socket
+Before=shutdown.target
+
+[Service]
+ExecStart=-@rootlibexecdir@/systemd-coredump
+Nice=9
+OOMScoreAdjust=500
+PrivateNetwork=yes
+ProtectSystem=full
+RuntimeMaxSec=5min
index 987220e554208dbf6a0a2eaa4b06d6453a7f8899..f4f845841da0f80a7c54447a764084b3c7d66d98 100644 (file)
@@ -7,6 +7,7 @@
 
 [Unit]
 Description=Journal Gateway Service
+Documentation=man:systemd-journal-gatewayd(8)
 Requires=systemd-journal-gatewayd.socket
 
 [Service]
index fd11058ab4ae5210b481c2a5a0a019b01a255a88..79d9b04210130cdb8e55759b00f2749d63d27d5d 100644 (file)
@@ -7,6 +7,7 @@
 
 [Unit]
 Description=Journal Gateway Service Socket
+Documentation=man:systemd-journal-gatewayd(8)
 
 [Socket]
 ListenStream=19531
index 2928a230211737402b4ffa830458b0a5fcf67a9d..fdf3da4b642ebfe9c4e4a43261e7411621fbfe00 100644 (file)
@@ -7,6 +7,7 @@
 
 [Unit]
 Description=Journal Remote Sink Service
+Documentation=man:systemd-journal-remote(8) man:journal-remote.conf(5)
 Requires=systemd-journal-remote.socket
 
 [Service]
index a757673a621b13504a5fa53089b21b9008f21830..1f488ff425d1b02b6246bddbdddbbaa1ab8c5b86 100644 (file)
@@ -7,12 +7,14 @@
 
 [Unit]
 Description=Journal Remote Upload Service
+Documentation=man:systemd-journal-upload(8)
 After=network.target
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-journal-upload \
           --save-state
 User=systemd-journal-upload
+SupplementaryGroups=systemd-journal
 PrivateTmp=yes
 PrivateDevices=yes
 WatchdogSec=3min
index 1e21d51aaef5b1833577b6bd2db6c2536bc87898..66aba4f98508e4f69b6b1c973647b7cd6b22e278 100644 (file)
@@ -17,3 +17,4 @@ ExecStart=-@rootlibexecdir@/systemd --user
 Slice=user-%i.slice
 KillMode=mixed
 Delegate=yes
+TasksMax=infinity