summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/activate/activate.c10
-rw-r--r--src/analyze/analyze-verify.c2
-rw-r--r--src/analyze/analyze-verify.h4
-rw-r--r--src/analyze/analyze.c18
-rw-r--r--src/ask-password/ask-password.c11
-rw-r--r--src/basic/MurmurHash2.c2
-rw-r--r--src/basic/architecture.c (renamed from src/shared/architecture.c)0
-rw-r--r--src/basic/architecture.h (renamed from src/shared/architecture.h)20
-rw-r--r--src/basic/btrfs-util.h4
-rw-r--r--src/basic/c-rbtree.c5
-rw-r--r--src/basic/calendarspec.c22
-rw-r--r--src/basic/cgroup-util.c49
-rw-r--r--src/basic/cgroup-util.h2
-rw-r--r--src/basic/clock-util.c11
-rw-r--r--src/basic/clock-util.h2
-rw-r--r--src/basic/copy.c63
-rw-r--r--src/basic/ether-addr-util.c12
-rw-r--r--src/basic/ether-addr-util.h10
-rw-r--r--src/basic/extract-word.c14
-rw-r--r--src/basic/fileio.c16
-rw-r--r--src/basic/formats-util.h2
-rw-r--r--src/basic/gunicode.h4
-rw-r--r--src/basic/hashmap.c14
-rw-r--r--src/basic/hexdecoct.c10
-rw-r--r--src/basic/hostname-util.c36
-rw-r--r--src/basic/hostname-util.h1
-rw-r--r--src/basic/io-util.c2
-rw-r--r--src/basic/io-util.h2
-rw-r--r--src/basic/list.h14
-rw-r--r--src/basic/locale-util.c2
-rw-r--r--src/basic/log.h3
-rw-r--r--src/basic/login-util.h4
-rw-r--r--src/basic/macro.h15
-rw-r--r--src/basic/missing.h230
-rw-r--r--src/basic/missing_syscall.h310
-rw-r--r--src/basic/mount-util.c4
-rw-r--r--src/basic/parse-util.c2
-rw-r--r--src/basic/process-util.c77
-rw-r--r--src/basic/selinux-util.c34
-rw-r--r--src/basic/selinux-util.h2
-rw-r--r--src/basic/set.h3
-rw-r--r--src/basic/sigbus.h4
-rw-r--r--src/basic/signal-util.h8
-rw-r--r--src/basic/socket-label.c34
-rw-r--r--src/basic/socket-util.c2
-rw-r--r--src/basic/stdio-util.h2
-rw-r--r--src/basic/strbuf.c6
-rw-r--r--src/basic/string-util.c2
-rw-r--r--src/basic/time-util.c54
-rw-r--r--src/basic/utf8.c2
-rw-r--r--src/basic/utf8.h1
-rw-r--r--src/basic/util.h1
-rw-r--r--src/basic/virt.c74
-rw-r--r--src/basic/xattr-util.c2
-rw-r--r--src/boot/efi/splash.c4
l---------src/bootchart/Makefile1
-rw-r--r--src/bootchart/bootchart.c531
-rw-r--r--src/bootchart/bootchart.conf26
-rw-r--r--src/bootchart/bootchart.h119
-rw-r--r--src/bootchart/store.c555
-rw-r--r--src/bootchart/svg.c1375
-rw-r--r--src/cgls/cgls.c2
-rw-r--r--src/core/cgroup.c6
-rw-r--r--src/core/dbus-manager.c2
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/execute.c20
-rw-r--r--src/core/failure-action.c6
-rw-r--r--src/core/job.c32
-rw-r--r--src/core/load-fragment.c26
-rw-r--r--src/core/main.c44
-rw-r--r--src/core/manager.c36
-rw-r--r--src/core/mount-setup.c2
-rw-r--r--src/core/mount.c26
-rw-r--r--src/core/scope.c3
-rw-r--r--src/core/selinux-setup.c2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/slice.c8
-rw-r--r--src/core/smack-setup.c2
-rw-r--r--src/core/socket.c12
-rw-r--r--src/core/transaction.c9
-rw-r--r--src/core/umount.c5
-rw-r--r--src/core/unit.c6
-rw-r--r--src/coredump/coredumpctl.c6
-rw-r--r--src/coredump/stacktrace.c4
-rw-r--r--src/cryptsetup/cryptsetup.c8
-rw-r--r--src/delta/delta.c12
-rw-r--r--src/firstboot/firstboot.c12
-rw-r--r--src/fstab-generator/fstab-generator.c4
-rw-r--r--src/hostname/hostnamed.c2
-rw-r--r--src/import/import-common.c4
-rw-r--r--src/import/pull-raw.c6
-rw-r--r--src/import/pull-tar.c6
-rw-r--r--src/initctl/initctl.c2
-rw-r--r--src/journal-remote/browse.html2
-rw-r--r--src/journal-remote/journal-remote-parse.h4
-rw-r--r--src/journal-remote/journal-remote-write.c2
-rw-r--r--src/journal-remote/journal-remote-write.h5
-rw-r--r--src/journal-remote/journal-remote.c6
-rw-r--r--src/journal-remote/journal-remote.h5
-rw-r--r--src/journal-remote/journal-upload-journal.c18
-rw-r--r--src/journal-remote/journal-upload.c2
-rw-r--r--src/journal-remote/microhttpd-util.h4
-rw-r--r--src/journal/catalog.c83
-rw-r--r--src/journal/compress.c5
-rw-r--r--src/journal/journal-file.c263
-rw-r--r--src/journal/journal-file.h21
-rw-r--r--src/journal/journal-send.c2
-rw-r--r--src/journal/journal-vacuum.c8
-rw-r--r--src/journal/journal-verify.c20
-rw-r--r--src/journal/journalctl.c28
-rw-r--r--src/journal/journald-audit.c6
-rw-r--r--src/journal/journald-kmsg.c2
-rw-r--r--src/journal/journald-rate-limit.c4
-rw-r--r--src/journal/journald-server.c40
-rw-r--r--src/journal/journald-server.h2
-rw-r--r--src/journal/journald-stream.c4
-rw-r--r--src/journal/mmap-cache.c8
-rw-r--r--src/journal/sd-journal.c23
-rw-r--r--src/journal/test-catalog.c2
-rw-r--r--src/journal/test-compress-benchmark.c2
-rw-r--r--src/journal/test-journal-enum.c2
-rw-r--r--src/journal/test-journal-flush.c4
-rw-r--r--src/journal/test-journal-interleaving.c10
-rw-r--r--src/journal/test-journal-stream.c12
-rw-r--r--src/journal/test-journal-verify.c12
-rw-r--r--src/journal/test-journal.c24
-rw-r--r--src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/libsystemd-network/dhcp-identifier.h43
-rw-r--r--src/libsystemd-network/dhcp-internal.h4
-rw-r--r--src/libsystemd-network/dhcp-option.c6
-rw-r--r--src/libsystemd-network/dhcp-packet.c2
-rw-r--r--src/libsystemd-network/dhcp-server-internal.h4
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h7
-rw-r--r--src/libsystemd-network/lldp-internal.c360
-rw-r--r--src/libsystemd-network/lldp-internal.h78
-rw-r--r--src/libsystemd-network/lldp-neighbor.c794
-rw-r--r--src/libsystemd-network/lldp-neighbor.h106
-rw-r--r--src/libsystemd-network/lldp-network.c35
-rw-r--r--src/libsystemd-network/lldp-network.h4
-rw-r--r--src/libsystemd-network/lldp-port.c116
-rw-r--r--src/libsystemd-network/lldp-port.h69
-rw-r--r--src/libsystemd-network/lldp-tlv.c638
-rw-r--r--src/libsystemd-network/lldp-tlv.h94
-rw-r--r--src/libsystemd-network/lldp.h126
-rw-r--r--src/libsystemd-network/network-internal.c33
-rw-r--r--src/libsystemd-network/network-internal.h4
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c57
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c16
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c54
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c8
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c8
-rw-r--r--src/libsystemd-network/sd-lldp.c898
-rw-r--r--src/libsystemd-network/sd-ndisc.c2
-rw-r--r--src/libsystemd-network/test-lldp.c339
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c2
-rw-r--r--src/libsystemd/sd-bus/bus-message.c29
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c4
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c2
-rw-r--r--src/libsystemd/sd-bus/bus-track.c2
-rw-r--r--src/libsystemd/sd-bus/busctl.c25
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c17
-rw-r--r--src/libsystemd/sd-bus/test-bus-error.c2
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c2
-rw-r--r--src/libsystemd/sd-device/device-internal.h4
-rw-r--r--src/libsystemd/sd-device/device-private.c6
-rw-r--r--src/libsystemd/sd-device/sd-device.c26
-rw-r--r--src/libsystemd/sd-event/sd-event.c4
-rw-r--r--src/libsystemd/sd-event/test-event.c2
-rw-r--r--src/libsystemd/sd-hwdb/hwdb-internal.h3
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c23
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c12
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c2
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c4
-rw-r--r--src/libsystemd/sd-netlink/test-netlink.c6
-rw-r--r--src/libsystemd/sd-network/sd-network.c105
-rw-r--r--src/libsystemd/sd-path/sd-path.c9
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c8
-rw-r--r--src/libudev/libudev-device-internal.h4
-rw-r--r--src/libudev/libudev-enumerate.c2
-rw-r--r--src/libudev/libudev.h1
-rw-r--r--src/locale/localectl.c20
-rw-r--r--src/locale/localed.c4
-rw-r--r--src/login/70-uaccess.rules6
-rw-r--r--src/login/loginctl.c20
-rw-r--r--src/login/logind-utmp.c2
-rw-r--r--src/login/logind.c2
-rw-r--r--src/machine/machine-dbus.c1
-rw-r--r--src/machine/machine.c2
-rw-r--r--src/machine/machinectl.c24
-rw-r--r--src/machine/machined-dbus.c2
-rw-r--r--src/network/networkctl.c952
-rw-r--r--src/network/networkd-conf.c155
-rw-r--r--src/network/networkd-conf.h36
-rw-r--r--src/network/networkd-dhcp4.c24
-rw-r--r--src/network/networkd-dhcp6.c17
-rw-r--r--src/network/networkd-fdb.c6
-rw-r--r--src/network/networkd-gperf.gperf18
-rw-r--r--src/network/networkd-ipv4ll.c2
-rw-r--r--src/network/networkd-link.c370
-rw-r--r--src/network/networkd-link.h14
-rw-r--r--src/network/networkd-lldp-tx.c346
-rw-r--r--src/network/networkd-lldp-tx.h (renamed from src/bootchart/store.h)19
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-ndisc.c27
-rw-r--r--src/network/networkd-netdev-bond.c2
-rw-r--r--src/network/networkd-netdev-bridge.h4
-rw-r--r--src/network/networkd-netdev-dummy.h4
-rw-r--r--src/network/networkd-netdev-ipvlan.h4
-rw-r--r--src/network/networkd-netdev-macvlan.h4
-rw-r--r--src/network/networkd-netdev-tunnel.c12
-rw-r--r--src/network/networkd-netdev-tunnel.h4
-rw-r--r--src/network/networkd-netdev-tuntap.c5
-rw-r--r--src/network/networkd-netdev-tuntap.h4
-rw-r--r--src/network/networkd-netdev-veth.h4
-rw-r--r--src/network/networkd-netdev-vlan.h4
-rw-r--r--src/network/networkd-netdev-vxlan.c6
-rw-r--r--src/network/networkd-netdev-vxlan.h4
-rw-r--r--src/network/networkd-netdev.h4
-rw-r--r--src/network/networkd-network-gperf.gperf7
-rw-r--r--src/network/networkd-network.c23
-rw-r--r--src/network/networkd-network.h23
-rw-r--r--src/network/networkd-wait-online.h4
-rw-r--r--src/network/networkd.c5
-rw-r--r--src/network/networkd.h12
-rw-r--r--src/nspawn/nspawn-cgroup.c9
-rw-r--r--src/nspawn/nspawn-mount.c25
-rw-r--r--src/nspawn/nspawn-network.c2
-rw-r--r--src/nspawn/nspawn.c20
-rw-r--r--src/nss-mymachines/nss-mymachines.c2
-rw-r--r--src/nss-resolve/nss-resolve.c2
-rw-r--r--src/resolve/dns-type.h4
-rw-r--r--src/resolve/resolve-tool.c120
-rw-r--r--src/resolve/resolved-bus.c11
-rw-r--r--src/resolve/resolved-conf.c4
-rw-r--r--src/resolve/resolved-dns-answer.c6
-rw-r--r--src/resolve/resolved-dns-cache.c8
-rw-r--r--src/resolve/resolved-dns-packet.c6
-rw-r--r--src/resolve/resolved-dns-query.c7
-rw-r--r--src/resolve/resolved-dns-rr.c33
-rw-r--r--src/resolve/resolved-dns-rr.h2
-rw-r--r--src/resolve/resolved-dns-server.c8
-rw-r--r--src/resolve/resolved-dns-transaction.c66
-rw-r--r--src/resolve/resolved-dns-transaction.h6
-rw-r--r--src/resolve/resolved-dns-zone.c5
-rw-r--r--src/resolve/resolved-etc-hosts.c2
-rw-r--r--src/resolve/resolved-llmnr.c2
-rw-r--r--src/resolve/resolved-resolv-conf.c4
-rw-r--r--src/resolve/resolved.c2
-rw-r--r--src/resolve/test-dns-packet.c1
-rw-r--r--src/resolve/test-dnssec.c2
-rw-r--r--src/run/run.c14
-rw-r--r--src/shared/acpi-fpdt.c6
-rw-r--r--src/shared/bus-util.c8
-rw-r--r--src/shared/condition.c2
-rw-r--r--src/shared/conf-parser.c13
-rw-r--r--src/shared/conf-parser.h2
-rw-r--r--src/shared/dns-domain.c6
-rw-r--r--src/shared/dns-domain.h5
-rw-r--r--src/shared/gcrypt-util.c6
-rw-r--r--src/shared/gcrypt-util.h14
-rw-r--r--src/shared/gpt.h4
-rw-r--r--src/shared/install-printf.h4
-rw-r--r--src/shared/logs-show.c2
-rw-r--r--src/shared/machine-image.c1
-rw-r--r--src/shared/machine-pool.c9
-rw-r--r--src/shared/pager.c5
-rw-r--r--src/shared/pager.h2
-rw-r--r--src/shared/ptyfwd.c5
-rw-r--r--src/shared/sleep-config.c2
-rw-r--r--src/shared/sleep-config.h4
-rw-r--r--src/shared/uid-range.c2
-rw-r--r--src/socket-proxy/socket-proxyd.c2
-rw-r--r--src/stdio-bridge/stdio-bridge.c7
-rw-r--r--src/systemctl/systemctl.c173
-rw-r--r--src/systemd/_sd-common.h2
-rw-r--r--src/systemd/sd-bus-protocol.h2
-rw-r--r--src/systemd/sd-bus-vtable.h2
-rw-r--r--src/systemd/sd-bus.h4
-rw-r--r--src/systemd/sd-device.h1
-rw-r--r--src/systemd/sd-dhcp-client.h8
-rw-r--r--src/systemd/sd-dhcp-server.h2
-rw-r--r--src/systemd/sd-dhcp6-client.h12
-rw-r--r--src/systemd/sd-event.h6
-rw-r--r--src/systemd/sd-id128.h4
-rw-r--r--src/systemd/sd-ipv4acd.h6
-rw-r--r--src/systemd/sd-ipv4ll.h6
-rw-r--r--src/systemd/sd-journal.h2
-rw-r--r--src/systemd/sd-lldp.h159
-rw-r--r--src/systemd/sd-messages.h2
-rw-r--r--src/systemd/sd-ndisc.h2
-rw-r--r--src/systemd/sd-netlink.h4
-rw-r--r--src/systemd/sd-network.h12
-rw-r--r--src/systemd/sd-resolve.h2
-rw-r--r--src/sysusers/sysusers.c2
-rw-r--r--src/sysv-generator/sysv-generator.c2
-rw-r--r--src/test/test-alloc-util.c55
-rw-r--r--src/test/test-boot-timestamps.c51
-rw-r--r--src/test/test-calendarspec.c1
-rw-r--r--src/test/test-clock.c96
-rw-r--r--src/test/test-conf-parser.c9
-rw-r--r--src/test/test-copy.c61
-rw-r--r--src/test/test-cpu-set-util.c143
-rw-r--r--src/test/test-daemon.c10
-rw-r--r--src/test/test-env-util.c (renamed from src/test/test-env-replace.c)30
-rw-r--r--src/test/test-escape.c114
-rw-r--r--src/test/test-execute.c86
-rw-r--r--src/test/test-fd-util.c103
-rw-r--r--src/test/test-fileio.c133
-rw-r--r--src/test/test-fs-util.c91
-rw-r--r--src/test/test-fstab-util.c37
-rw-r--r--src/test/test-glob-util.c (renamed from src/bootchart/svg.h)49
-rw-r--r--src/test/test-hashmap-plain.c15
-rw-r--r--src/test/test-hexdecoct.c387
-rw-r--r--src/test/test-io-util.c69
-rw-r--r--src/test/test-ipcrm.c11
-rw-r--r--src/test/test-libudev.c267
-rw-r--r--src/test/test-loopback.c4
-rw-r--r--src/test/test-netlink-manual.c6
-rw-r--r--src/test/test-path-util.c46
-rw-r--r--src/test/test-path.c2
-rw-r--r--src/test/test-proc-cmdline.c52
-rw-r--r--src/test/test-process-util.c26
-rw-r--r--src/test/test-selinux.c122
-rw-r--r--src/test/test-signal-util.c18
-rw-r--r--src/test/test-siphash24.c47
-rw-r--r--src/test/test-sizeof.c53
-rw-r--r--src/test/test-stat-util.c68
-rw-r--r--src/test/test-string-util.c265
-rw-r--r--src/test/test-strv.c21
-rw-r--r--src/test/test-time.c2
-rw-r--r--src/test/test-udev.c2
-rw-r--r--src/test/test-unit-file.c2
-rw-r--r--src/test/test-user-util.c27
-rw-r--r--src/test/test-util.c1441
-rw-r--r--src/test/test-web-util.c39
-rw-r--r--src/test/test-xattr-util.c69
-rw-r--r--src/timedate/timedatectl.c10
-rw-r--r--src/timedate/timedated.c48
-rw-r--r--src/timesync/timesyncd.c2
-rw-r--r--src/tmpfiles/tmpfiles.c11
-rw-r--r--src/udev/mtd_probe/mtd_probe.h4
-rw-r--r--src/udev/mtd_probe/probe_smartmedia.c2
-rw-r--r--src/udev/net/ethtool-util.h4
-rw-r--r--src/udev/net/link-config.c1
-rw-r--r--src/udev/net/link-config.h4
-rw-r--r--src/udev/scsi_id/scsi.h4
-rw-r--r--src/udev/scsi_id/scsi_id.h4
-rw-r--r--src/udev/udev-builtin-input_id.c2
-rw-r--r--src/udev/udev-builtin-path_id.c2
-rw-r--r--src/udev/udev-rules.c622
-rw-r--r--src/udev/udev.h11
-rw-r--r--src/udev/udevadm-monitor.c2
-rw-r--r--src/udev/udevadm-test.c2
-rw-r--r--src/udev/udevadm-util.h4
-rw-r--r--src/udev/udevadm.c2
-rw-r--r--src/udev/udevd.c2
-rw-r--r--src/update-done/update-done.c2
-rw-r--r--src/user-sessions/user-sessions.c2
360 files changed, 7867 insertions, 9141 deletions
diff --git a/src/activate/activate.c b/src/activate/activate.c
index 23244fdc62..8ac8dd8e72 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -77,7 +77,7 @@ static int open_sockets(int *epoll_fd, bool accept) {
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -105,7 +105,7 @@ static int open_sockets(int *epoll_fd, bool accept) {
}
assert(fd == SD_LISTEN_FDS_START + count);
- count ++;
+ count++;
}
if (arg_listen)
@@ -176,7 +176,7 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (!envp[n_env])
return log_oom();
- n_env ++;
+ n_env++;
}
}
@@ -191,7 +191,7 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (!envp[n_env])
return log_oom();
- n_env ++;
+ n_env++;
}
if (arg_inetd) {
@@ -385,7 +385,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hl:aE:d", options, NULL)) >= 0)
switch(c) {
case 'h':
help();
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
index d36c8db3d4..b83f559e7d 100644
--- a/src/analyze/analyze-verify.c
+++ b/src/analyze/analyze-verify.c
@@ -290,7 +290,7 @@ int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man)
if (r == 0)
r = k;
} else
- count ++;
+ count++;
}
for (i = 0; i < count; i++) {
diff --git a/src/analyze/analyze-verify.h b/src/analyze/analyze-verify.h
index 54adad93e1..27c253a562 100644
--- a/src/analyze/analyze-verify.h
+++ b/src/analyze/analyze-verify.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <stdbool.h>
#include "path-lookup.h"
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index a847084781..42754a2741 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -60,7 +60,7 @@
svg(" <text class=\"%s\" x=\"%.03f\" y=\"%.03f\">", (b) ? "left" : "right", SCALE_X * (x) + (b ? 5.0 : -5.0), SCALE_Y * (y) + 14.0); \
svg(format, ## __VA_ARGS__); \
svg("</text>\n"); \
- } while(false)
+ } while (false)
static enum dot {
DEP_ALL,
@@ -123,14 +123,6 @@ struct host_info {
char *architecture;
};
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -965,7 +957,7 @@ static int analyze_critical_chain(sd_bus *bus, char *names[]) {
}
unit_times_hashmap = h;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
puts("The time after the unit is active or started is printed after the \"@\" character.\n"
"The time the unit takes to start is printed after the \"+\" character.\n");
@@ -993,7 +985,7 @@ static int analyze_blame(sd_bus *bus) {
qsort(times, n, sizeof(struct unit_times), compare_unit_time);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
for (i = 0; i < (unsigned) n; i++) {
char ts[FORMAT_TIMESPAN_MAX];
@@ -1206,7 +1198,7 @@ static int dump(sd_bus *bus, char **args) {
return -E2BIG;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -1284,7 +1276,7 @@ static int set_log_target(sd_bus *bus, char **args) {
static void help(void) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Profile systemd, show unit dependencies, check unit files.\n\n"
diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
index adc9286612..6d53dd982c 100644
--- a/src/ask-password/ask-password.c
+++ b/src/ask-password/ask-password.c
@@ -34,6 +34,7 @@ static const char *arg_keyname = NULL;
static char *arg_message = NULL;
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static bool arg_multiple = false;
+static bool arg_no_output = false;
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
static void help(void) {
@@ -48,6 +49,7 @@ static void help(void) {
" --no-tty Ask question via agent even on TTY\n"
" --accept-cached Accept cached passwords\n"
" --multiple List multiple passwords if available\n"
+ " --no-output Do not print password to standard output\n"
, program_invocation_short_name);
}
@@ -62,6 +64,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_MULTIPLE,
ARG_ID,
ARG_KEYNAME,
+ ARG_NO_OUTPUT,
};
static const struct option options[] = {
@@ -74,6 +77,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "multiple", no_argument, NULL, ARG_MULTIPLE },
{ "id", required_argument, NULL, ARG_ID },
{ "keyname", required_argument, NULL, ARG_KEYNAME },
+ { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
{}
};
@@ -125,6 +129,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_keyname = optarg;
break;
+ case ARG_NO_OUTPUT:
+ arg_no_output = true;
+ break;
+
case '?':
return -EINVAL;
@@ -166,7 +174,8 @@ int main(int argc, char *argv[]) {
}
STRV_FOREACH(p, l) {
- puts(*p);
+ if (!arg_no_output)
+ puts(*p);
if (!arg_multiple)
break;
diff --git a/src/basic/MurmurHash2.c b/src/basic/MurmurHash2.c
index 2f4149dbe9..9020793930 100644
--- a/src/basic/MurmurHash2.c
+++ b/src/basic/MurmurHash2.c
@@ -50,7 +50,7 @@ uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
const unsigned char * data = (const unsigned char *)key;
- while(len >= 4)
+ while (len >= 4)
{
uint32_t k = *(uint32_t*)data;
diff --git a/src/shared/architecture.c b/src/basic/architecture.c
index a9ecfc1cd6..a9ecfc1cd6 100644
--- a/src/shared/architecture.c
+++ b/src/basic/architecture.c
diff --git a/src/shared/architecture.h b/src/basic/architecture.h
index 26679e28c6..c22cbc8279 100644
--- a/src/shared/architecture.h
+++ b/src/basic/architecture.h
@@ -77,20 +77,20 @@ int uname_architecture(void);
#if defined(__x86_64__)
# define native_architecture() ARCHITECTURE_X86_64
# define LIB_ARCH_TUPLE "x86_64-linux-gnu"
-# define PROC_CPUINFO_MODEL "model name"
+# define SECONDARY_ARCHITECTURE ARCHITECTURE_X86
#elif defined(__i386__)
# define native_architecture() ARCHITECTURE_X86
# define LIB_ARCH_TUPLE "i386-linux-gnu"
-# define PROC_CPUINFO_MODEL "model name"
#elif defined(__powerpc64__)
# if __BYTE_ORDER == __BIG_ENDIAN
# define native_architecture() ARCHITECTURE_PPC64
# define LIB_ARCH_TUPLE "ppc64-linux-gnu"
+# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC
# else
# define native_architecture() ARCHITECTURE_PPC64_LE
# define LIB_ARCH_TUPLE "powerpc64le-linux-gnu"
+# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC_LE
# endif
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__powerpc__)
# if __BYTE_ORDER == __BIG_ENDIAN
# define native_architecture() ARCHITECTURE_PPC
@@ -99,32 +99,28 @@ int uname_architecture(void);
# define native_architecture() ARCHITECTURE_PPC_LE
# error "Missing LIB_ARCH_TUPLE for PPCLE"
# endif
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__ia64__)
# define native_architecture() ARCHITECTURE_IA64
# define LIB_ARCH_TUPLE "ia64-linux-gnu"
#elif defined(__hppa64__)
# define native_architecture() ARCHITECTURE_PARISC64
# error "Missing LIB_ARCH_TUPLE for HPPA64"
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__hppa__)
# define native_architecture() ARCHITECTURE_PARISC
# define LIB_ARCH_TUPLE "hppa‑linux‑gnu"
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__s390x__)
# define native_architecture() ARCHITECTURE_S390X
# define LIB_ARCH_TUPLE "s390x-linux-gnu"
+# define SECONDARY_ARCHITECTURE ARCHITECTURE_S390
#elif defined(__s390__)
# define native_architecture() ARCHITECTURE_S390
# define LIB_ARCH_TUPLE "s390-linux-gnu"
#elif defined(__sparc64__)
# define native_architecture() ARCHITECTURE_SPARC64
# define LIB_ARCH_TUPLE "sparc64-linux-gnu"
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__sparc__)
# define native_architecture() ARCHITECTURE_SPARC
# define LIB_ARCH_TUPLE "sparc-linux-gnu"
-# define PROC_CPUINFO_MODEL "cpu"
#elif defined(__mips64__)
# if __BYTE_ORDER == __BIG_ENDIAN
# define native_architecture() ARCHITECTURE_MIPS64
@@ -133,7 +129,6 @@ int uname_architecture(void);
# define native_architecture() ARCHITECTURE_MIPS64_LE
# error "Missing LIB_ARCH_TUPLE for MIPS64_LE"
# endif
-# define PROC_CPUINFO_MODEL "cpu model"
#elif defined(__mips__)
# if __BYTE_ORDER == __BIG_ENDIAN
# define native_architecture() ARCHITECTURE_MIPS
@@ -142,7 +137,6 @@ int uname_architecture(void);
# define native_architecture() ARCHITECTURE_MIPS_LE
# define LIB_ARCH_TUPLE "mipsel-linux-gnu"
# endif
-# define PROC_CPUINFO_MODEL "cpu model"
#elif defined(__alpha__)
# define native_architecture() ARCHITECTURE_ALPHA
# define LIB_ARCH_TUPLE "alpha-linux-gnu"
@@ -178,7 +172,6 @@ int uname_architecture(void);
# define LIB_ARCH_TUPLE "arm-linux-gnu"
# endif
# endif
-# define PROC_CPUINFO_MODEL "model name"
#elif defined(__sh64__)
# define native_architecture() ARCHITECTURE_SH64
# error "Missing LIB_ARCH_TUPLE for SH64"
@@ -198,10 +191,5 @@ int uname_architecture(void);
# error "Please register your architecture here!"
#endif
-#ifndef PROC_CPUINFO_MODEL
-#warning "PROC_CPUINFO_MODEL not defined for your architecture"
-#define PROC_CPUINFO_MODEL "model name"
-#endif
-
const char *architecture_to_string(int a) _const_;
int architecture_from_string(const char *s) _pure_;
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index 37802c2565..1d852d502c 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
diff --git a/src/basic/c-rbtree.c b/src/basic/c-rbtree.c
index 914d7e5229..cf5a7242df 100644
--- a/src/basic/c-rbtree.c
+++ b/src/basic/c-rbtree.c
@@ -195,11 +195,6 @@ static inline void c_rbnode_set_parent_and_color(CRBNode *n, CRBNode *p, unsigne
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));
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 775879076d..6e0bab9b94 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -114,7 +114,7 @@ static void sort_chain(CalendarComponent **c) {
static void fix_year(CalendarComponent *c) {
/* Turns 12 → 2012, 89 → 1989 */
- while(c) {
+ while (c) {
CalendarComponent *n = c->next;
if (c->value >= 0 && c->value < 70)
@@ -978,7 +978,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
for (;;) {
/* Normalize the current date */
- mktime_or_timegm(&c, spec->utc);
+ (void) mktime_or_timegm(&c, spec->utc);
c.tm_isdst = -1;
c.tm_year += 1900;
@@ -990,8 +990,10 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
}
- if (r < 0 || tm_out_of_bounds(&c, spec->utc))
+ if (r < 0)
return r;
+ if (tm_out_of_bounds(&c, spec->utc))
+ return -ENOENT;
c.tm_mon += 1;
r = find_matching_component(spec->month, &c.tm_mon);
@@ -1002,7 +1004,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
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_year++;
c.tm_mon = 0;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
@@ -1013,7 +1015,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
if (r > 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_mon++;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
@@ -1027,18 +1029,18 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
r = find_matching_component(spec->hour, &c.tm_hour);
if (r > 0)
- c.tm_min = c.tm_sec = 0;
+ c.tm_min = c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_mday ++;
+ c.tm_mday++;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
r = find_matching_component(spec->minute, &c.tm_min);
if (r > 0)
- c.tm_sec = 0;
+ c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_hour ++;
+ c.tm_hour++;
c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
@@ -1049,7 +1051,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
c.tm_sec /= USEC_PER_SEC;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_min ++;
+ c.tm_min++;
c.tm_sec = tm_usec = 0;
continue;
}
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 6ef00d51df..5043180747 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -101,6 +101,39 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
return 1;
}
+int cg_read_event(const char *controller, const char *path, const char *event,
+ char **val)
+{
+ _cleanup_free_ char *events = NULL, *content = NULL;
+ char *p, *line;
+ int r;
+
+ r = cg_get_path(controller, path, "cgroup.events", &events);
+ if (r < 0)
+ return r;
+
+ r = read_full_file(events, &content, NULL);
+ if (r < 0)
+ return r;
+
+ p = content;
+ while ((line = strsep(&p, "\n"))) {
+ char *key;
+
+ key = strsep(&line, " ");
+ if (!key || !line)
+ return -EINVAL;
+
+ if (strcmp(key, event))
+ continue;
+
+ *val = strdup(line);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
_cleanup_free_ char *fs = NULL;
int r;
@@ -1007,18 +1040,12 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
return unified;
if (unified > 0) {
- _cleanup_free_ char *populated = NULL, *t = NULL;
+ _cleanup_free_ char *t = NULL;
/* On the unified hierarchy we can check empty state
- * via the "cgroup.populated" attribute. */
+ * via the "populated" attribute of "cgroup.events". */
- r = cg_get_path(controller, path, "cgroup.populated", &populated);
- if (r < 0)
- return r;
-
- r = read_one_line_file(populated, &t);
- if (r == -ENOENT)
- return 1;
+ r = cg_read_event(controller, path, "populated", &t);
if (r < 0)
return r;
@@ -1248,7 +1275,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
return 0;
}
-int cg_path_decode_unit(const char *cgroup, char **unit){
+int cg_path_decode_unit(const char *cgroup, char **unit) {
char *c, *s;
size_t n;
@@ -2129,7 +2156,7 @@ int cg_unified(void) {
if (statfs("/sys/fs/cgroup/", &fs) < 0)
return -errno;
- if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
unified_cache = true;
else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
unified_cache = false;
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index ad1edd9cdb..4254e51e5d 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -96,6 +96,8 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
int cg_read_pid(FILE *f, pid_t *_pid);
+int cg_read_event(const char *controller, const char *path, const char *event,
+ char **val);
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
int cg_read_subgroup(DIR *d, char **fn);
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
index 507e757ff0..7fe8d35ea5 100644
--- a/src/basic/clock-util.c
+++ b/src/basic/clock-util.c
@@ -69,9 +69,12 @@ int clock_set_hwclock(const struct tm *tm) {
return 0;
}
-int clock_is_localtime(void) {
+int clock_is_localtime(const char* adjtime_path) {
_cleanup_fclose_ FILE *f;
+ if (adjtime_path == NULL)
+ adjtime_path = "/etc/adjtime";
+
/*
* The third line of adjtime is "UTC" or "LOCAL" or nothing.
* # /etc/adjtime
@@ -79,7 +82,7 @@ int clock_is_localtime(void) {
* 0
* UTC
*/
- f = fopen("/etc/adjtime", "re");
+ f = fopen(adjtime_path, "re");
if (f) {
char line[LINE_MAX];
bool b;
@@ -88,7 +91,8 @@ int clock_is_localtime(void) {
fgets(line, sizeof(line), f) &&
fgets(line, sizeof(line), f);
if (!b)
- return -EIO;
+ /* less than three lines -> default to UTC */
+ return 0;
truncate_nl(line);
return streq(line, "LOCAL");
@@ -96,6 +100,7 @@ int clock_is_localtime(void) {
} else if (errno != ENOENT)
return -errno;
+ /* adjtime not present -> default to UTC */
return 0;
}
diff --git a/src/basic/clock-util.h b/src/basic/clock-util.h
index f471f2abcf..8830cd2f38 100644
--- a/src/basic/clock-util.h
+++ b/src/basic/clock-util.h
@@ -21,7 +21,7 @@
#include <time.h>
-int clock_is_localtime(void);
+int clock_is_localtime(const char* adjtime_path);
int clock_set_timezone(int *min);
int clock_reset_timewarp(void);
int clock_get_hwclock(struct tm *tm);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 519b412941..41dc8ca79a 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -40,17 +40,38 @@
#include "fs-util.h"
#include "io-util.h"
#include "macro.h"
+#include "missing.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "umask-util.h"
#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+ static int have = -1;
+ ssize_t r;
+
+ if (have == false)
+ return -ENOSYS;
+
+ r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+ if (_unlikely_(have < 0))
+ have = r >= 0 || errno != ENOSYS;
+ if (r >= 0)
+ return r;
+ else
+ return -errno;
+}
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
- bool try_sendfile = true, try_splice = true;
+ bool try_cfr = true, try_sendfile = true, try_splice = true;
int r;
+ size_t m = SSIZE_MAX; /* that the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
@@ -67,11 +88,9 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
}
for (;;) {
- size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes != (uint64_t) -1) {
-
if (max_bytes <= 0)
return 1; /* return > 0 if we hit the max_bytes limit */
@@ -79,44 +98,59 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
m = (size_t) max_bytes;
}
+ /* First try copy_file_range(), unless we already tried */
+ if (try_cfr) {
+ n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+ if (n < 0) {
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV))
+ return n;
+
+ try_cfr = false;
+ /* use fallback below */
+ } else if (n == 0) /* EOF */
+ break;
+ else
+ /* Success! */
+ goto next;
+ }
+
/* First try sendfile(), unless we already tried */
if (try_sendfile) {
-
n = sendfile(fdt, fdf, NULL, m);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_sendfile = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
- /* The try splice, unless we already tried */
+ /* Then try splice, unless we already tried */
if (try_splice) {
n = splice(fdf, NULL, fdt, NULL, m, 0);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_splice = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
/* As a fallback just copy bits by hand */
{
- uint8_t buf[m];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
- n = read(fdf, buf, m);
+ n = read(fdf, buf, sizeof buf);
if (n < 0)
return -errno;
if (n == 0) /* EOF */
@@ -132,6 +166,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
assert(max_bytes >= (uint64_t) n);
max_bytes -= n;
}
+ /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+ * so reduce our maximum by the amount we already copied,
+ * but don't go below our copy buffer size, unless we are
+ * close the the limit of bytes we are allowed to copy. */
+ m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c
index ded6d31f4b..a4d8d656da 100644
--- a/src/basic/ether-addr-util.c
+++ b/src/basic/ether-addr-util.c
@@ -42,3 +42,15 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
return buffer;
}
+
+bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+ assert(a);
+ assert(b);
+
+ return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
+ a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
+ a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
+ a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
+ a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
+ a->ether_addr_octet[5] == b->ether_addr_octet[5];
+}
diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h
index 4487149efd..074363793e 100644
--- a/src/basic/ether-addr-util.h
+++ b/src/basic/ether-addr-util.h
@@ -20,10 +20,18 @@
***/
#include <net/ethernet.h>
+#include <stdbool.h>
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
#define ETHER_ADDR_TO_STRING_MAX (3*6)
-
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
+
+bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
+
+#define ETHER_ADDR_NULL ((const struct ether_addr){})
+
+static inline bool ether_addr_is_null(const struct ether_addr *addr) {
+ return ether_addr_equal(addr, &ETHER_ADDR_NULL);
+}
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index ee35d2a0ec..d6c1228463 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -63,12 +63,12 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
if (!GREEDY_REALLOC(s, allocated, sz+1))
return -ENOMEM;
- for (;; (*p) ++, c = **p) {
+ for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
else if (strchr(separators, c)) {
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
- (*p) ++;
+ (*p)++;
goto finish_force_next;
}
} else {
@@ -81,7 +81,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
}
}
- for (;; (*p) ++, c = **p) {
+ for (;; (*p)++, c = **p) {
if (backslash) {
if (!GREEDY_REALLOC(s, allocated, sz+7))
return -ENOMEM;
@@ -129,7 +129,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
backslash = false;
} else if (quote) { /* inside either single or double quotes */
- for (;; (*p) ++, c = **p) {
+ for (;; (*p)++, c = **p) {
if (c == 0) {
if (flags & EXTRACT_RELAX)
goto finish_force_terminate;
@@ -149,7 +149,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
}
} else {
- for (;; (*p) ++, c = **p) {
+ for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
@@ -160,11 +160,11 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
break;
} else if (strchr(separators, c)) {
if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
- (*p) ++;
+ (*p)++;
goto finish_force_next;
}
/* Skip additional coalesced separators. */
- for (;; (*p) ++, c = **p) {
+ for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
if (!strchr(separators, c))
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index e43ca6d29e..69590941e5 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -352,7 +352,7 @@ static int parse_env_file_internal(
case KEY:
if (strchr(newline, c)) {
state = PRE_KEY;
- line ++;
+ line++;
n_key = 0;
} else if (c == '=') {
state = PRE_VALUE;
@@ -376,7 +376,7 @@ static int parse_env_file_internal(
case PRE_VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
- line ++;
+ line++;
key[n_key] = 0;
if (value)
@@ -416,7 +416,7 @@ static int parse_env_file_internal(
case VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
- line ++;
+ line++;
key[n_key] = 0;
@@ -535,7 +535,7 @@ static int parse_env_file_internal(
state = COMMENT_ESCAPE;
else if (strchr(newline, c)) {
state = PRE_KEY;
- line ++;
+ line++;
}
break;
@@ -588,7 +588,7 @@ static int parse_env_file_push(
va_list aq, *ap = userdata;
if (!utf8_is_valid(key)) {
- _cleanup_free_ char *p;
+ _cleanup_free_ char *p = NULL;
p = utf8_escape_invalid(key);
log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
@@ -596,7 +596,7 @@ static int parse_env_file_push(
}
if (value && !utf8_is_valid(value)) {
- _cleanup_free_ char *p;
+ _cleanup_free_ char *p = NULL;
p = utf8_escape_invalid(value);
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
@@ -908,7 +908,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
/* Back off one char if there's nothing but whitespace
and zeros */
if (!*t || isspace(*t))
- t --;
+ t--;
}
len = strcspn(t, terminator);
@@ -1069,7 +1069,7 @@ int fflush_and_check(FILE *f) {
/* This is much like like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern, int flags) {
- _cleanup_umask_ mode_t u;
+ _cleanup_umask_ mode_t u = 0;
int fd;
assert(pattern);
diff --git a/src/basic/formats-util.h b/src/basic/formats-util.h
index ce516b117d..9b4e8e98fa 100644
--- a/src/basic/formats-util.h
+++ b/src/basic/formats-util.h
@@ -49,7 +49,7 @@
#if SIZEOF_TIME_T == 8
# define PRI_TIME PRIi64
#elif SIZEOF_TIME_T == 4
-# define PRI_TIME PRIu32
+# define PRI_TIME "li"
#else
# error Unknown time_t size
#endif
diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h
index b03aa43160..5975bc8fc9 100644
--- a/src/basic/gunicode.h
+++ b/src/basic/gunicode.h
@@ -1,11 +1,11 @@
+#pragma once
+
/* gunicode.h - Unicode manipulation functions
*
* Copyright (C) 1999, 2000 Tom Tromey
* Copyright 2000, 2005 Red Hat, Inc.
*/
-#pragma once
-
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 6f1a049d47..85b8d812b3 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -176,7 +176,7 @@ enum HashmapType {
};
struct _packed_ indirect_storage {
- char *storage; /* where buckets and DIBs are stored */
+ void *storage; /* where buckets and DIBs are stored */
uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
unsigned n_entries; /* number of stored entries */
@@ -193,7 +193,7 @@ struct direct_storage {
/* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
* That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
* or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
- char storage[sizeof(struct indirect_storage)];
+ uint8_t storage[sizeof(struct indirect_storage)];
};
#define DIRECT_BUCKETS(entry_t) \
@@ -302,7 +302,7 @@ static void n_entries_dec(HashmapBase *h) {
h->n_direct_entries--;
}
-static char *storage_ptr(HashmapBase *h) {
+static void *storage_ptr(HashmapBase *h) {
return h->has_indirect ? h->indirect.storage
: h->direct.storage;
}
@@ -347,7 +347,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
return (struct hashmap_base_entry*)
- (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
+ ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
}
static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
@@ -381,7 +381,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_
static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
return (dib_raw_t*)
- (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
+ ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
}
static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
@@ -1028,7 +1028,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
*/
static int resize_buckets(HashmapBase *h, unsigned entries_add) {
struct swap_entries swap;
- char *new_storage;
+ void *new_storage;
dib_raw_t *old_dibs, *new_dibs;
const struct hashmap_type_info *hi;
unsigned idx, optimal_idx;
@@ -1095,7 +1095,7 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add) {
h->indirect.n_buckets = (1U << new_shift) /
(hi->entry_size + sizeof(dib_raw_t));
- old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
+ old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets);
new_dibs = dib_raw_ptr(h);
/*
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index d7ad8d41f2..c5bda6c4d6 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -276,8 +276,8 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
if (padding) {
/* strip the padding */
while (l > 0 && p[l - 1] == '=' && pad < 7) {
- pad ++;
- l --;
+ pad++;
+ l--;
}
}
@@ -505,7 +505,7 @@ int unbase64char(char c) {
if (c == '+')
return offset;
- offset ++;
+ offset++;
if (c == '/')
return offset;
@@ -621,9 +621,9 @@ int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
/* strip the padding */
if (l > 0 && p[l - 1] == '=')
- l --;
+ l--;
if (l > 0 && p[l - 1] == '=')
- l --;
+ l--;
/* a group of four input bytes needs three output bytes, in case of
padding we need to add two or three extra bytes */
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 4fe6a725aa..13c3bb6446 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <bits/local_lim.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -49,6 +48,10 @@ bool hostname_is_set(void) {
char* gethostname_malloc(void) {
struct utsname u;
+ /* This call tries to return something useful, either the actual hostname
+ * or it makes something up. The only reason it might fail is OOM.
+ * It might even return "localhost" if that's set. */
+
assert_se(uname(&u) >= 0);
if (isempty(u.nodename) || streq(u.nodename, "(none)"))
@@ -57,6 +60,31 @@ char* gethostname_malloc(void) {
return strdup(u.nodename);
}
+int gethostname_strict(char **ret) {
+ struct utsname u;
+ char *k;
+
+ /* This call will rather fail than make up a name. It will not return "localhost" either. */
+
+ assert_se(uname(&u) >= 0);
+
+ if (isempty(u.nodename))
+ return -ENXIO;
+
+ if (streq(u.nodename, "(none)"))
+ return -ENXIO;
+
+ if (is_localhost(u.nodename))
+ return -ENXIO;
+
+ k = strdup(u.nodename);
+ if (!k)
+ return -ENOMEM;
+
+ *ret = k;
+ return 0;
+}
+
static bool hostname_valid_char(char c) {
return
(c >= 'a' && c <= 'z') ||
@@ -96,7 +124,7 @@ bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
return false;
dot = true;
- n_dots ++;
+ n_dots++;
} else {
if (!hostname_valid_char(*p))
return false;
@@ -122,6 +150,8 @@ char* hostname_cleanup(char *s) {
assert(s);
+ strshorten(s, HOST_NAME_MAX);
+
for (p = s, d = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
@@ -141,8 +171,6 @@ char* hostname_cleanup(char *s) {
else
*d = 0;
- strshorten(s, HOST_NAME_MAX);
-
return s;
}
diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h
index d062eddea1..7af4e6c7ec 100644
--- a/src/basic/hostname-util.h
+++ b/src/basic/hostname-util.h
@@ -26,6 +26,7 @@
bool hostname_is_set(void);
char* gethostname_malloc(void);
+int gethostname_strict(char **ret);
bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
char* hostname_cleanup(char *s);
diff --git a/src/basic/io-util.c b/src/basic/io-util.c
index 3ec8d61236..0037a37f2a 100644
--- a/src/basic/io-util.c
+++ b/src/basic/io-util.c
@@ -249,7 +249,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
} else if (n > 0)
q += n;
else
- q ++;
+ q++;
}
if (q > w) {
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index 142c940d92..4684ed3bfc 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -46,7 +46,7 @@ ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
char *_s = (char *)(s); \
_i->iov_base = _s; \
_i->iov_len = strlen(_s); \
- } while(false)
+ } while (false)
static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
unsigned j;
diff --git a/src/basic/list.h b/src/basic/list.h
index c68185f587..5962aa4211 100644
--- a/src/basic/list.h
+++ b/src/basic/list.h
@@ -32,7 +32,7 @@
#define LIST_HEAD_INIT(head) \
do { \
(head) = NULL; } \
- while(false)
+ while (false)
/* Initialize a list item */
#define LIST_INIT(name,item) \
@@ -40,7 +40,7 @@
typeof(*(item)) *_item = (item); \
assert(_item); \
_item->name##_prev = _item->name##_next = NULL; \
- } while(false)
+ } while (false)
/* Prepend an item to the list */
#define LIST_PREPEND(name,head,item) \
@@ -51,7 +51,7 @@
_item->name##_next->name##_prev = _item; \
_item->name##_prev = NULL; \
*_head = _item; \
- } while(false)
+ } while (false)
/* Append an item to the list */
#define LIST_APPEND(name,head,item) \
@@ -59,7 +59,7 @@
typeof(*(head)) *_tail; \
LIST_FIND_TAIL(name,head,_tail); \
LIST_INSERT_AFTER(name,head,_tail,item); \
- } while(false)
+ } while (false)
/* Remove an item from the list */
#define LIST_REMOVE(name,head,item) \
@@ -75,7 +75,7 @@
*_head = _item->name##_next; \
} \
_item->name##_next = _item->name##_prev = NULL; \
- } while(false)
+ } while (false)
/* Find the head of the list */
#define LIST_FIND_HEAD(name,item,head) \
@@ -119,7 +119,7 @@
_b->name##_prev = _a; \
_a->name##_next = _b; \
} \
- } while(false)
+ } while (false)
/* Insert an item before another one (a = where, b = what) */
#define LIST_INSERT_BEFORE(name,head,a,b) \
@@ -145,7 +145,7 @@
_b->name##_next = _a; \
_a->name##_prev = _b; \
} \
- } while(false)
+ } while (false)
#define LIST_JUST_US(name,item) \
(!(item)->name##_prev && !(item)->name##_next) \
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index cda6b2895d..eaad25e65b 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -153,6 +153,8 @@ static int add_locales_from_libdir (Set *locales) {
FOREACH_DIRENT(entry, dir, return -errno) {
char *z;
+ dirent_ensure_type(dir, entry);
+
if (entry->d_type != DT_DIR)
continue;
diff --git a/src/basic/log.h b/src/basic/log.h
index 60ddead74c..b6356228d9 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -193,7 +193,7 @@ void log_assert_failed_return(
#ifdef LOG_TRACE
# define log_trace(...) log_debug(__VA_ARGS__)
#else
-# define log_trace(...) do {} while(0)
+# define log_trace(...) do {} while (0)
#endif
/* Structured logging */
@@ -246,5 +246,4 @@ int log_syntax_internal(
log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
"String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
} \
- -EINVAL; \
})
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index 89a337d7c1..b01ee25c88 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <stdbool.h>
#include <unistd.h>
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 2695d0edb7..e41aa4260f 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -23,10 +23,15 @@
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
-#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#ifdef __clang__
+# define _alloc_(...)
+#else
+# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#endif
#define _sentinel_ __attribute__ ((sentinel))
#define _unused_ __attribute__ ((unused))
#define _destructor_ __attribute__ ((destructor))
@@ -224,7 +229,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
/* We override the glibc assert() here. */
#undef assert
#ifdef NDEBUG
-#define assert(expr) do {} while(false)
+#define assert(expr) do {} while (false)
#else
#define assert(expr) assert_message_se(expr, #expr)
#endif
@@ -361,6 +366,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
_found; \
})
+#define SWAP_TWO(x, y) do { \
+ typeof(x) _t = (x); \
+ (x) = (y); \
+ (y) = (_t); \
+ } while (false)
+
/* Define C11 thread_local attribute even on older gcc compiler
* version */
#ifndef thread_local
diff --git a/src/basic/missing.h b/src/basic/missing.h
index f3d32362bd..66cd5921ad 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -31,6 +31,7 @@
#include <linux/neighbour.h>
#include <linux/oom.h>
#include <linux/rtnetlink.h>
+#include <net/ethernet.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/syscall.h>
@@ -134,84 +135,6 @@
#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);
-}
-#endif
-
-#ifndef __NR_memfd_create
-# if defined __x86_64__
-# define __NR_memfd_create 319
-# elif defined __arm__
-# define __NR_memfd_create 385
-# elif defined __aarch64__
-# define __NR_memfd_create 279
-# elif defined __s390__
-# define __NR_memfd_create 350
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_memfd_create 4354
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_memfd_create 6318
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_memfd_create 5314
-# endif
-# elif defined __i386__
-# define __NR_memfd_create 356
-# else
-# warning "__NR_memfd_create unknown for your architecture"
-# define __NR_memfd_create 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
- return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-# if defined __x86_64__
-# define __NR_getrandom 318
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__arm__)
-# define __NR_getrandom 384
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom 4353
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom 6317
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom 5313
-# endif
-# else
-# warning "__NR_getrandom unknown for your architecture"
-# define __NR_getrandom 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
- return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
@@ -514,6 +437,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define CGROUP_SUPER_MAGIC 0x27e0eb
#endif
+#ifndef CGROUP2_SUPER_MAGIC
+#define CGROUP2_SUPER_MAGIC 0x63677270
+#endif
+
#ifndef TMPFS_MAGIC
#define TMPFS_MAGIC 0x01021994
#endif
@@ -526,12 +453,6 @@ struct btrfs_ioctl_quota_ctl_args {
#define MS_PRIVATE (1 << 18)
#endif
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
#ifndef SCM_SECURITY
#define SCM_SECURITY 0x03
#endif
@@ -560,32 +481,6 @@ static inline pid_t gettid(void) {
#define MAX_HANDLE_SZ 128
#endif
-#ifndef __NR_name_to_handle_at
-# if defined(__x86_64__)
-# define __NR_name_to_handle_at 303
-# elif defined(__i386__)
-# define __NR_name_to_handle_at 341
-# elif defined(__arm__)
-# define __NR_name_to_handle_at 370
-# elif defined(__powerpc__)
-# define __NR_name_to_handle_at 345
-# else
-# error "__NR_name_to_handle_at is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
- unsigned int handle_bytes;
- int handle_type;
- unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
@@ -634,22 +529,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
#endif
-#ifndef __NR_setns
-# if defined(__x86_64__)
-# define __NR_setns 308
-# elif defined(__i386__)
-# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
- return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
#if !HAVE_DECL_LO_FLAGS_PARTSCAN
#define LO_FLAGS_PARTSCAN 8
#endif
@@ -883,13 +762,16 @@ static inline int setns(int fd, int nstype) {
#define IFLA_BRPORT_FAST_LEAVE 7
#define IFLA_BRPORT_LEARNING 8
#define IFLA_BRPORT_UNICAST_FLOOD 9
-#define IFLA_BRPORT_PROXYARP 10
#define IFLA_BRPORT_LEARNING_SYNC 11
#define __IFLA_BRPORT_MAX 12
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
#endif
+#if !HAVE_DECL_IFLA_BRPORT_PROXYARP
+#define IFLA_BRPORT_PROXYARP 10
+#endif
+
#if !HAVE_DECL_NDA_IFINDEX
#define NDA_UNSPEC 0
#define NDA_DST 1
@@ -1014,69 +896,10 @@ static inline int setns(int fd, int nstype) {
#define CAP_AUDIT_READ 37
#endif
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
- /* On s390 and cris the order of the first and second arguments
- * of the raw clone() system call is reversed. */
- return (int) syscall(__NR_clone, child_stack, flags);
-#else
- return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
- return (pid_t) syscall(__NR_getxpid);
-#else
- return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
-#if !HAVE_DECL_RENAMEAT2
-
-#ifndef __NR_renameat2
-# if defined __x86_64__
-# define __NR_renameat2 316
-# elif defined __arm__
-# define __NR_renameat2 382
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_renameat2 4351
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_renameat2 6315
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_renameat2 5311
-# endif
-# elif defined __i386__
-# define __NR_renameat2 353
-# else
-# warning "__NR_renameat2 unknown for your architecture"
-# define __NR_renameat2 0xffffffff
-# endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
- return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE (1 << 0)
#endif
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
- return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KCMP_FILE
#define KCMP_FILE 0
#endif
@@ -1093,35 +916,6 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
typedef int32_t key_serial_t;
#endif
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
- return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
- return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
- return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KEYCTL_READ
#define KEYCTL_READ 11
#endif
@@ -1168,4 +962,10 @@ static inline key_serial_t request_key(const char *type, const char *description
#define char16_t uint16_t
#endif
+#ifndef ETHERTYPE_LLDP
+#define ETHERTYPE_LLDP 0x88cc
#endif
+
+#endif
+
+#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
new file mode 100644
index 0000000000..d502d3b9ca
--- /dev/null
+++ b/src/basic/missing_syscall.h
@@ -0,0 +1,310 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ 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/>.
+***/
+
+/* Missing glibc definitions to access certain kernel APIs */
+
+#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);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_MEMFD_CREATE
+# ifndef __NR_memfd_create
+# if defined __x86_64__
+# define __NR_memfd_create 319
+# elif defined __arm__
+# define __NR_memfd_create 385
+# elif defined __aarch64__
+# define __NR_memfd_create 279
+# elif defined __s390__
+# define __NR_memfd_create 350
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_memfd_create 4354
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_memfd_create 6318
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_memfd_create 5314
+# endif
+# elif defined __i386__
+# define __NR_memfd_create 356
+# else
+# warning "__NR_memfd_create unknown for your architecture"
+# endif
+# endif
+
+static inline int memfd_create(const char *name, unsigned int flags) {
+# ifdef __NR_memfd_create
+ return syscall(__NR_memfd_create, name, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETRANDOM
+# ifndef __NR_getrandom
+# if defined __x86_64__
+# define __NR_getrandom 318
+# elif defined(__i386__)
+# define __NR_getrandom 355
+# elif defined(__arm__)
+# define __NR_getrandom 384
+# elif defined(__aarch64__)
+# define __NR_getrandom 278
+# elif defined(__ia64__)
+# define __NR_getrandom 1339
+# elif defined(__m68k__)
+# define __NR_getrandom 352
+# elif defined(__s390x__)
+# define __NR_getrandom 349
+# elif defined(__powerpc__)
+# define __NR_getrandom 359
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_getrandom 4353
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_getrandom 6317
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_getrandom 5313
+# endif
+# else
+# warning "__NR_getrandom unknown for your architecture"
+# endif
+# endif
+
+static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+# ifdef __NR_getrandom
+ return syscall(__NR_getrandom, buffer, count, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETTID
+static inline pid_t gettid(void) {
+ return (pid_t) syscall(SYS_gettid);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_NAME_TO_HANDLE_AT
+# ifndef __NR_name_to_handle_at
+# if defined(__x86_64__)
+# define __NR_name_to_handle_at 303
+# elif defined(__i386__)
+# define __NR_name_to_handle_at 341
+# elif defined(__arm__)
+# define __NR_name_to_handle_at 370
+# elif defined(__powerpc__)
+# define __NR_name_to_handle_at 345
+# else
+# error "__NR_name_to_handle_at is not defined"
+# endif
+# endif
+
+struct file_handle {
+ unsigned int handle_bytes;
+ int handle_type;
+ unsigned char f_handle[0];
+};
+
+static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
+# ifdef __NR_name_to_handle_at
+ return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_SETNS
+# ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# else
+# error "__NR_setns is not defined"
+# endif
+# endif
+
+static inline int setns(int fd, int nstype) {
+# ifdef __NR_setns
+ return syscall(__NR_setns, fd, nstype);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+static inline int raw_clone(unsigned long flags, void *child_stack) {
+#if defined(__s390__) || defined(__CRIS__)
+ /* On s390 and cris the order of the first and second arguments
+ * of the raw clone() system call is reversed. */
+ return (int) syscall(__NR_clone, child_stack, flags);
+#else
+ return (int) syscall(__NR_clone, flags, child_stack);
+#endif
+}
+
+/* ======================================================================= */
+
+static inline pid_t raw_getpid(void) {
+#if defined(__alpha__)
+ return (pid_t) syscall(__NR_getxpid);
+#else
+ return (pid_t) syscall(__NR_getpid);
+#endif
+}
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_RENAMEAT2
+# ifndef __NR_renameat2
+# if defined __x86_64__
+# define __NR_renameat2 316
+# elif defined __arm__
+# define __NR_renameat2 382
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_renameat2 4351
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_renameat2 6315
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_renameat2 5311
+# endif
+# elif defined __i386__
+# define __NR_renameat2 353
+# else
+# warning "__NR_renameat2 unknown for your architecture"
+# endif
+# endif
+
+static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
+# ifdef __NR_renameat2
+ return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KCMP
+static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+# ifdef __NR_kcmp
+ return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KEYCTL
+static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+# ifdef __NR_keyctl
+ return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
+# ifdef __NR_add_key
+ return syscall(__NR_add_key, type, description, payload, plen, ringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
+# ifdef __NR_request_key
+ return syscall(__NR_request_key, type, description, callout_info, destringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_COPY_FILE_RANGE
+# ifndef __NR_copy_file_range
+# if defined(__x86_64__)
+# define __NR_copy_file_range 326
+# elif defined(__i386__)
+# define __NR_copy_file_range 377
+# elif defined __s390__
+# define __NR_copy_file_range 375
+# elif defined __arm__
+# define __NR_copy_file_range 391
+# elif defined __aarch64__
+# define __NR_copy_file_range 285
+# else
+# warning "__NR_copy_file_range not defined for your architecture"
+# endif
+# endif
+
+static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+# ifdef __NR_copy_file_range
+ return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 33f2ee96d8..5faa2eba05 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -47,7 +47,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
if ((flags & AT_EMPTY_PATH) && isempty(filename))
xsprintf(path, "/proc/self/fdinfo/%i", fd);
else {
- subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
if (subfd < 0)
return -errno;
@@ -230,7 +230,7 @@ int path_is_mount_point(const char *t, int flags) {
if (!parent)
return -ENOMEM;
- fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+ fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return -errno;
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index a3cb81b040..6c11b605a9 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -505,7 +505,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
s = *p;
/* accept any number of digits, strtoull is limted to 19 */
- for(i=0; i < digits; i++,s++) {
+ for (i=0; i < digits; i++,s++) {
if (*s < '0' || *s > '9') {
if (i == 0)
return -EINVAL;
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 189ef9ab60..ae3f6109ad 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -38,6 +38,7 @@
#endif
#include "alloc-util.h"
+#include "architecture.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -205,7 +206,7 @@ void rename_process(const char name[8]) {
* "systemd"). If you pass a longer string it will be
* truncated */
- prctl(PR_SET_NAME, name);
+ (void) prctl(PR_SET_NAME, name);
if (program_invocation_name)
strncpy(program_invocation_name, name, strlen(program_invocation_name));
@@ -674,75 +675,43 @@ bool oom_score_adjust_is_valid(int oa) {
}
unsigned long personality_from_string(const char *p) {
+ int architecture;
- /* Parse a personality specifier. We introduce our own
- * identifiers that indicate specific ABIs, rather than just
- * hints regarding the register size, since we want to keep
- * things open for multiple locally supported ABIs for the
- * same register size. We try to reuse the ABI identifiers
- * used by libseccomp. */
+ if (!p)
+ return PERSONALITY_INVALID;
-#if defined(__x86_64__)
+ /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
+ * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
+ * the same register size. */
- if (streq(p, "x86"))
- return PER_LINUX32;
+ architecture = architecture_from_string(p);
+ if (architecture < 0)
+ return PERSONALITY_INVALID;
- if (streq(p, "x86-64"))
+ if (architecture == native_architecture())
return PER_LINUX;
-
-#elif defined(__i386__)
-
- if (streq(p, "x86"))
- return PER_LINUX;
-
-#elif defined(__s390x__)
-
- if (streq(p, "s390"))
+#ifdef SECONDARY_ARCHITECTURE
+ if (architecture == SECONDARY_ARCHITECTURE)
return PER_LINUX32;
-
- if (streq(p, "s390x"))
- return PER_LINUX;
-
-#elif defined(__s390__)
-
- if (streq(p, "s390"))
- return PER_LINUX;
#endif
return PERSONALITY_INVALID;
}
const char* personality_to_string(unsigned long p) {
-
-#if defined(__x86_64__)
-
- if (p == PER_LINUX32)
- return "x86";
-
- if (p == PER_LINUX)
- return "x86-64";
-
-#elif defined(__i386__)
-
- if (p == PER_LINUX)
- return "x86";
-
-#elif defined(__s390x__)
+ int architecture = _ARCHITECTURE_INVALID;
if (p == PER_LINUX)
- return "s390x";
-
- if (p == PER_LINUX32)
- return "s390";
-
-#elif defined(__s390__)
-
- if (p == PER_LINUX)
- return "s390";
-
+ architecture = native_architecture();
+#ifdef SECONDARY_ARCHITECTURE
+ else if (p == PER_LINUX32)
+ architecture = SECONDARY_ARCHITECTURE;
#endif
- return NULL;
+ if (architecture < 0)
+ return NULL;
+
+ return architecture_to_string(architecture);
}
void valgrind_summary_hack(void) {
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 6c63b9d652..10c2f39369 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -80,31 +80,23 @@ void mac_selinux_retest(void) {
#endif
}
-int mac_selinux_init(const char *prefix) {
+int mac_selinux_init(void) {
int r = 0;
#ifdef HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
- if (!mac_selinux_use())
+ if (label_hnd)
return 0;
- if (label_hnd)
+ if (!mac_selinux_use())
return 0;
before_mallinfo = mallinfo();
before_timestamp = now(CLOCK_MONOTONIC);
- if (prefix) {
- struct selinux_opt options[] = {
- { .type = SELABEL_OPT_SUBSET, .value = prefix },
- };
-
- label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
- } else
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
+ label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd) {
log_enforcing("Failed to initialize SELinux context: %m");
r = security_getenforce() == 1 ? -errno : 0;
@@ -160,7 +152,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return 0;
if (r >= 0) {
- r = lsetfilecon(path, fcon);
+ r = lsetfilecon_raw(path, fcon);
/* If the FS doesn't support labels, then exit without warning */
if (r < 0 && errno == EOPNOTSUPP)
@@ -225,7 +217,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
return -errno;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -270,7 +262,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
if (r < 0)
return -errno;
- r = getpeercon(socket_fd, &peercon);
+ r = getpeercon_raw(socket_fd, &peercon);
if (r < 0)
return -errno;
@@ -304,7 +296,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
return -ENOMEM;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -358,7 +350,7 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
log_enforcing("Failed to determine SELinux security context for %s: %m", path);
} else {
- if (setfscreatecon(filecon) >= 0)
+ if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
@@ -379,7 +371,7 @@ void mac_selinux_create_file_clear(void) {
if (!mac_selinux_use())
return;
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
#endif
}
@@ -410,7 +402,7 @@ void mac_selinux_create_socket_clear(void) {
if (!mac_selinux_use())
return;
- setsockcreatecon(NULL);
+ setsockcreatecon_raw(NULL);
#endif
}
@@ -469,7 +461,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
return -errno;
} else {
- if (setfscreatecon(fcon) < 0) {
+ if (setfscreatecon_raw(fcon) < 0) {
log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
@@ -480,7 +472,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
return r;
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 27e8edb41b..ce6bc8e44c 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -29,7 +29,7 @@ bool mac_selinux_use(void);
bool mac_selinux_have(void);
void mac_selinux_retest(void);
-int mac_selinux_init(const char *prefix);
+int mac_selinux_init(void);
void mac_selinux_finish(void);
int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
diff --git a/src/basic/set.h b/src/basic/set.h
index 2bff5062da..e0d9dd001c 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -126,6 +126,9 @@ int set_put_strdupv(Set *s, char **l);
#define SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
+#define SET_FOREACH_MOVE(e, d, s) \
+ for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )
+
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
diff --git a/src/basic/sigbus.h b/src/basic/sigbus.h
index cce9eb201b..980243d9ce 100644
--- a/src/basic/sigbus.h
+++ b/src/basic/sigbus.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
void sigbus_install(void);
void sigbus_reset(void);
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
index 72b10e8712..a7322ff26a 100644
--- a/src/basic/signal-util.h
+++ b/src/basic/signal-util.h
@@ -44,9 +44,9 @@ 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; \
+#define BLOCK_SIGNALS(...) \
+ _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \
+ sigset_t t; \
assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
- t; \
+ t; \
})
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 35e9573aa4..6d1dc83874 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -23,7 +23,6 @@
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
@@ -35,6 +34,7 @@
#include "mkdir.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "umask-util.h"
int socket_address_listen(
const SocketAddress *a,
@@ -112,28 +112,24 @@ int socket_address_listen(
return -errno;
if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
- mode_t old_mask;
-
/* Create parents */
- mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
+ (void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
/* Enforce the right access mode for the socket */
- old_mask = umask(~ socket_mode);
-
- r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0 && errno == EADDRINUSE) {
- /* Unlink and try again */
- unlink(a->sockaddr.un.sun_path);
- r = bind(fd, &a->sockaddr.sa, a->size);
+ RUN_WITH_UMASK(~socket_mode) {
+ r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
+ if (r == -EADDRINUSE) {
+ /* Unlink and try again */
+ unlink(a->sockaddr.un.sun_path);
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ } else if (r < 0)
+ return r;
}
-
- umask(old_mask);
- } else
- r = bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0)
- return -errno;
+ } else {
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ }
if (socket_address_can_accept(a))
if (listen(fd, backlog) < 0)
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 58512686e3..0f38f9a0f3 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -942,7 +942,7 @@ ssize_t next_datagram_size_fd(int fd) {
int k;
/* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
- * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD dosn't
+ * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
* do. This difference is actually of major importance as we need to be sure that the size returned here
* actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
* the wrong size. */
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
index 0a675571ff..bd1144b4c9 100644
--- a/src/basic/stdio-util.h
+++ b/src/basic/stdio-util.h
@@ -73,4 +73,4 @@ do { \
assert_not_reached("Unknown format string argument."); \
} \
} \
-} while(false)
+} while (false)
diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c
index 77220c0251..797f00cf71 100644
--- a/src/basic/strbuf.c
+++ b/src/basic/strbuf.c
@@ -121,7 +121,7 @@ static void bubbleinsert(struct strbuf_node *node,
sizeof(struct strbuf_child_entry) * (node->children_count - left));
node->children[left] = new;
- node->children_count ++;
+ node->children_count++;
}
/* add string, return the index/offset into the buffer */
@@ -156,6 +156,10 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
return off;
}
+ /* bsearch is not allowed on a NULL sequence */
+ if (node->children_count == 0)
+ break;
+
/* lookup child node */
c = s[len - 1 - depth];
search.c = c;
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 0bde55f9d5..293a15f9c0 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -477,7 +477,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
}
if (k > x) /* last character was wide and went over quota */
- x ++;
+ x++;
for (j = s + old_length; k < new_length && j > i; ) {
char32_t c;
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 0b4f5ab5b9..7ca764abeb 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -139,8 +139,7 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
usec_t timespec_load(const struct timespec *ts) {
assert(ts);
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
+ if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
return USEC_INFINITY;
if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
@@ -154,13 +153,13 @@ usec_t timespec_load(const struct timespec *ts) {
static nsec_t timespec_load_nsec(const struct timespec *ts) {
assert(ts);
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
+ if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
return NSEC_INFINITY;
- return
- (nsec_t) ts->tv_sec * NSEC_PER_SEC +
- (nsec_t) ts->tv_nsec;
+ if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
+ return NSEC_INFINITY;
+
+ return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec;
}
struct timespec *timespec_store(struct timespec *ts, usec_t u) {
@@ -577,12 +576,12 @@ int parse_timestamp(const char *t, usec_t *usec) {
goto from_tm;
} else if (streq(t, "yesterday")) {
- tm.tm_mday --;
+ tm.tm_mday--;
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
goto from_tm;
} else if (streq(t, "tomorrow")) {
- tm.tm_mday ++;
+ tm.tm_mday++;
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
goto from_tm;
}
@@ -705,8 +704,7 @@ finish:
return 0;
}
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
-
+static char* extract_multiplier(char *p, usec_t *multiplier) {
static const struct {
const char *suffix;
usec_t usec;
@@ -740,7 +738,22 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
{ "usec", 1ULL },
{ "us", 1ULL },
};
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+ char *e;
+
+ e = startswith(p, table[i].suffix);
+ if (e) {
+ *multiplier = table[i].usec;
+ return e;
+ }
+ }
+
+ return p;
+}
+int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
const char *p, *s;
usec_t r = 0;
bool something = false;
@@ -765,8 +778,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
for (;;) {
long long l, z = 0;
char *e;
- unsigned i, n = 0;
- usec_t multiplier, k;
+ unsigned n = 0;
+ usec_t multiplier = default_unit, k;
p += strspn(p, WHITESPACE);
@@ -779,10 +792,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
errno = 0;
l = strtoll(p, &e, 10);
-
if (errno > 0)
return -errno;
-
if (l < 0)
return -ERANGE;
@@ -806,18 +817,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
return -EINVAL;
e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- multiplier = table[i].usec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table)) {
- multiplier = default_unit;
- p = e;
- }
+ p = extract_multiplier(e, &multiplier);
something = true;
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index 629db123cd..6eae2b983d 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -241,7 +241,7 @@ char *utf8_escape_non_printable(const char *str) {
*(s++) = hexchar((int) *str);
str += 1;
- len --;
+ len--;
}
}
} else {
diff --git a/src/basic/utf8.h b/src/basic/utf8.h
index 12c272d66e..f9b9c9468b 100644
--- a/src/basic/utf8.h
+++ b/src/basic/utf8.h
@@ -28,6 +28,7 @@
#include "missing.h"
#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
+#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
bool unichar_is_valid(char32_t c);
diff --git a/src/basic/util.h b/src/basic/util.h
index e095254b57..286db05159 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -36,6 +36,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 19b6318e3d..e6c5a095a0 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -98,6 +98,8 @@ static int detect_vm_cpuid(void) {
: "0" (eax)
);
+ log_debug("Virtualization found, CPUID=%s", sig.text);
+
for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
if (streq(sig.text, cpuid_vendor_table[j].cpuid))
return cpuid_vendor_table[j].id;
@@ -105,6 +107,7 @@ static int detect_vm_cpuid(void) {
return VIRTUALIZATION_VM_OTHER;
}
#endif
+ log_debug("No virtualization found in CPUID");
return VIRTUALIZATION_NONE;
}
@@ -121,19 +124,25 @@ static int detect_vm_device_tree(void) {
dir = opendir("/proc/device-tree");
if (!dir) {
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ log_debug_errno(errno, "/proc/device-tree: %m");
return VIRTUALIZATION_NONE;
+ }
return -errno;
}
FOREACH_DIRENT(dent, dir, return -errno)
- if (strstr(dent->d_name, "fw-cfg"))
+ if (strstr(dent->d_name, "fw-cfg")) {
+ log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
return VIRTUALIZATION_QEMU;
+ }
+ log_debug("No virtualization found in /proc/device-tree/*");
return VIRTUALIZATION_NONE;
} else if (r < 0)
return r;
+ log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
if (streq(hvtype, "linux,kvm"))
return VIRTUALIZATION_KVM;
else if (strstr(hvtype, "xen"))
@@ -141,6 +150,7 @@ static int detect_vm_device_tree(void) {
else
return VIRTUALIZATION_VM_OTHER;
#else
+ log_debug("This platform does not support /proc/device-tree");
return VIRTUALIZATION_NONE;
#endif
}
@@ -184,30 +194,58 @@ static int detect_vm_dmi(void) {
return r;
}
+
+
for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
- if (startswith(s, dmi_vendor_table[j].vendor))
+ if (startswith(s, dmi_vendor_table[j].vendor)) {
+ log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
return dmi_vendor_table[j].id;
+ }
}
#endif
+ log_debug("No virtualization found in DMI");
+
return VIRTUALIZATION_NONE;
}
static int detect_vm_xen(void) {
+ /* Check for Dom0 will be executed later in detect_vm_xen_dom0
+ Thats why we dont check the content of /proc/xen/capabilities here. */
+ if (access("/proc/xen/capabilities", F_OK) < 0) {
+ log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+ return VIRTUALIZATION_NONE;
+ }
+
+ log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
+ return VIRTUALIZATION_XEN;
+
+}
+
+static bool detect_vm_xen_dom0(void) {
_cleanup_free_ char *domcap = NULL;
char *cap, *i;
int r;
r = read_one_line_file("/proc/xen/capabilities", &domcap);
- if (r == -ENOENT)
- return VIRTUALIZATION_NONE;
+ if (r == -ENOENT) {
+ log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+ return false;
+ }
+ if (r < 0)
+ return r;
i = domcap;
while ((cap = strsep(&i, ",")))
if (streq(cap, "control_d"))
break;
+ if (!cap) {
+ log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
+ return false;
+ }
- return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
+ log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
+ return true;
}
static int detect_vm_hypervisor(void) {
@@ -220,6 +258,8 @@ static int detect_vm_hypervisor(void) {
if (r < 0)
return r;
+ log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
+
if (streq(hvtype, "xen"))
return VIRTUALIZATION_XEN;
else
@@ -234,9 +274,13 @@ static int detect_vm_uml(void) {
r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
if (r < 0)
return r;
- if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n"))
+
+ if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
+ log_debug("UML virtualization found in /proc/cpuinfo");
return VIRTUALIZATION_UML;
+ }
+ log_debug("No virtualization found in /proc/cpuinfo (%s)", cpuinfo_contents);
return VIRTUALIZATION_NONE;
}
@@ -252,11 +296,13 @@ static int detect_vm_zvm(void) {
if (r < 0)
return r;
+ log_debug("Virtualization %s found in /proc/sysinfo", t);
if (streq(t, "z/VM"))
return VIRTUALIZATION_ZVM;
else
return VIRTUALIZATION_KVM;
#else
+ log_debug("This platform does not support /proc/sysinfo");
return VIRTUALIZATION_NONE;
#endif
}
@@ -324,7 +370,14 @@ int detect_vm(void) {
return r;
finish:
+ /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
+ * In order to detect the Dom0 as not virtualization we need to
+ * double-check it */
+ if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
+ r = VIRTUALIZATION_NONE;
+
cached_found = r;
+ log_debug("Found VM virtualization %s", virtualization_to_string(r));
return r;
}
@@ -412,6 +465,7 @@ int detect_container(void) {
r = VIRTUALIZATION_CONTAINER_OTHER;
finish:
+ log_debug("Found container virtualization %s", virtualization_to_string(r));
cached_found = r;
return r;
}
@@ -420,10 +474,10 @@ int detect_virtualization(void) {
int r;
r = detect_container();
- if (r != 0)
- return r;
+ if (r == 0)
+ r = detect_vm();
- return detect_vm();
+ return r;
}
int running_in_chroot(void) {
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
index 8d7f14f382..8256899eda 100644
--- a/src/basic/xattr-util.c
+++ b/src/basic/xattr-util.c
@@ -110,7 +110,7 @@ ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute,
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
- fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c
index b1cc2c0b72..c0ef7f64fe 100644
--- a/src/boot/efi/splash.c
+++ b/src/boot/efi/splash.c
@@ -281,9 +281,9 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
if (EFI_ERROR(err))
goto err;
- if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
+ if (dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
- if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
+ if (dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2;
uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
diff --git a/src/bootchart/Makefile b/src/bootchart/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/bootchart/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
deleted file mode 100644
index 77d158f5f9..0000000000
--- a/src/bootchart/bootchart.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.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/>.
- ***/
-
-/***
-
- Many thanks to those who contributed ideas and code:
- - Ziga Mahkovec - Original bootchart author
- - Anders Norgaard - PyBootchartgui
- - Michael Meeks - bootchart2
- - Scott James Remnant - Ubuntu C-based logger
- - Arjan van der Ven - for the idea to merge bootgraph.pl functionality
-
- ***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "sd-journal.h"
-
-#include "alloc-util.h"
-#include "bootchart.h"
-#include "conf-parser.h"
-#include "def.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "io-util.h"
-#include "list.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "store.h"
-#include "string-util.h"
-#include "strxcpyx.h"
-#include "svg.h"
-#include "util.h"
-
-static int exiting = 0;
-
-#define DEFAULT_SAMPLES_LEN 500
-#define DEFAULT_HZ 25.0
-#define DEFAULT_SCALE_X 100.0 /* 100px = 1sec */
-#define DEFAULT_SCALE_Y 20.0 /* 16px = 1 process bar */
-#define DEFAULT_INIT ROOTLIBEXECDIR "/systemd"
-#define DEFAULT_OUTPUT "/run/log"
-
-/* graph defaults */
-bool arg_entropy = false;
-bool arg_initcall = true;
-bool arg_relative = false;
-bool arg_filter = true;
-bool arg_show_cmdline = false;
-bool arg_show_cgroup = false;
-bool arg_pss = false;
-bool arg_percpu = false;
-int arg_samples_len = DEFAULT_SAMPLES_LEN; /* we record len+1 (1 start sample) */
-double arg_hz = DEFAULT_HZ;
-double arg_scale_x = DEFAULT_SCALE_X;
-double arg_scale_y = DEFAULT_SCALE_Y;
-
-char arg_init_path[PATH_MAX] = DEFAULT_INIT;
-char arg_output_path[PATH_MAX] = DEFAULT_OUTPUT;
-
-static void signal_handler(int sig) {
- exiting = 1;
-}
-
-#define BOOTCHART_MAX (16*1024*1024)
-
-static void parse_conf(void) {
- char *init = NULL, *output = NULL;
- const ConfigTableItem items[] = {
- { "Bootchart", "Samples", config_parse_int, 0, &arg_samples_len },
- { "Bootchart", "Frequency", config_parse_double, 0, &arg_hz },
- { "Bootchart", "Relative", config_parse_bool, 0, &arg_relative },
- { "Bootchart", "Filter", config_parse_bool, 0, &arg_filter },
- { "Bootchart", "Output", config_parse_path, 0, &output },
- { "Bootchart", "Init", config_parse_path, 0, &init },
- { "Bootchart", "PlotMemoryUsage", config_parse_bool, 0, &arg_pss },
- { "Bootchart", "PlotEntropyGraph", config_parse_bool, 0, &arg_entropy },
- { "Bootchart", "ScaleX", config_parse_double, 0, &arg_scale_x },
- { "Bootchart", "ScaleY", config_parse_double, 0, &arg_scale_y },
- { "Bootchart", "ControlGroup", config_parse_bool, 0, &arg_show_cgroup },
- { "Bootchart", "PerCPU", config_parse_bool, 0, &arg_percpu },
- { NULL, NULL, NULL, 0, NULL }
- };
-
- config_parse_many(PKGSYSCONFDIR "/bootchart.conf",
- CONF_PATHS_NULSTR("systemd/bootchart.conf.d"),
- NULL, config_item_table_lookup, items, true, NULL);
-
- if (init != NULL)
- strscpy(arg_init_path, sizeof(arg_init_path), init);
- if (output != NULL)
- strscpy(arg_output_path, sizeof(arg_output_path), output);
-}
-
-static void help(void) {
- printf("Usage: %s [OPTIONS]\n\n"
- "Options:\n"
- " -r --rel Record time relative to recording\n"
- " -f --freq=FREQ Sample frequency [%g]\n"
- " -n --samples=N Stop sampling at [%d] samples\n"
- " -x --scale-x=N Scale the graph horizontally [%g] \n"
- " -y --scale-y=N Scale the graph vertically [%g] \n"
- " -p --pss Enable PSS graph (CPU intensive)\n"
- " -e --entropy Enable the entropy_avail graph\n"
- " -o --output=PATH Path to output files [%s]\n"
- " -i --init=PATH Path to init executable [%s]\n"
- " -F --no-filter Disable filtering of unimportant or ephemeral processes\n"
- " -C --cmdline Display full command lines with arguments\n"
- " -c --control-group Display process control group\n"
- " --per-cpu Draw each CPU utilization and wait bar also\n"
- " -h --help Display this message\n\n"
- "See bootchart.conf for more information.\n",
- program_invocation_short_name,
- DEFAULT_HZ,
- DEFAULT_SAMPLES_LEN,
- DEFAULT_SCALE_X,
- DEFAULT_SCALE_Y,
- DEFAULT_OUTPUT,
- DEFAULT_INIT);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_PERCPU = 0x100,
- };
-
- static const struct option options[] = {
- {"rel", no_argument, NULL, 'r' },
- {"freq", required_argument, NULL, 'f' },
- {"samples", required_argument, NULL, 'n' },
- {"pss", no_argument, NULL, 'p' },
- {"output", required_argument, NULL, 'o' },
- {"init", required_argument, NULL, 'i' },
- {"no-filter", no_argument, NULL, 'F' },
- {"cmdline", no_argument, NULL, 'C' },
- {"control-group", no_argument, NULL, 'c' },
- {"help", no_argument, NULL, 'h' },
- {"scale-x", required_argument, NULL, 'x' },
- {"scale-y", required_argument, NULL, 'y' },
- {"entropy", no_argument, NULL, 'e' },
- {"per-cpu", no_argument, NULL, ARG_PERCPU},
- {}
- };
- int c, r;
-
- if (getpid() == 1)
- opterr = 0;
-
- while ((c = getopt_long(argc, argv, "erpf:n:o:i:FCchx:y:", options, NULL)) >= 0)
- switch (c) {
-
- case 'r':
- arg_relative = true;
- break;
- case 'f':
- r = safe_atod(optarg, &arg_hz);
- if (r < 0)
- log_warning_errno(r, "failed to parse --freq/-f argument '%s': %m",
- optarg);
- break;
- case 'F':
- arg_filter = false;
- break;
- case 'C':
- arg_show_cmdline = true;
- break;
- case 'c':
- arg_show_cgroup = true;
- break;
- case 'n':
- r = safe_atoi(optarg, &arg_samples_len);
- if (r < 0)
- log_warning_errno(r, "failed to parse --samples/-n argument '%s': %m",
- optarg);
- break;
- case 'o':
- path_kill_slashes(optarg);
- strscpy(arg_output_path, sizeof(arg_output_path), optarg);
- break;
- case 'i':
- path_kill_slashes(optarg);
- strscpy(arg_init_path, sizeof(arg_init_path), optarg);
- break;
- case 'p':
- arg_pss = true;
- break;
- case 'x':
- r = safe_atod(optarg, &arg_scale_x);
- if (r < 0)
- log_warning_errno(r, "failed to parse --scale-x/-x argument '%s': %m",
- optarg);
- break;
- case 'y':
- r = safe_atod(optarg, &arg_scale_y);
- if (r < 0)
- log_warning_errno(r, "failed to parse --scale-y/-y argument '%s': %m",
- optarg);
- break;
- case 'e':
- arg_entropy = true;
- break;
- case ARG_PERCPU:
- arg_percpu = true;
- break;
- case 'h':
- help();
- return 0;
- case '?':
- if (getpid() != 1)
- return -EINVAL;
- else
- return 0;
- default:
- assert_not_reached("Unhandled option code.");
- }
-
- if (arg_hz <= 0) {
- log_error("Frequency needs to be > 0");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int do_journal_append(char *file) {
- _cleanup_free_ char *bootchart_message = NULL;
- _cleanup_free_ char *bootchart_file = NULL;
- _cleanup_free_ char *p = NULL;
- _cleanup_close_ int fd = -1;
- struct iovec iovec[5];
- int r, j = 0;
- ssize_t n;
-
- bootchart_file = strappend("BOOTCHART_FILE=", file);
- if (!bootchart_file)
- return log_oom();
-
- IOVEC_SET_STRING(iovec[j++], bootchart_file);
- IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=9f26aa562cf440c2b16c773d0479b518");
- IOVEC_SET_STRING(iovec[j++], "PRIORITY=7");
- bootchart_message = strjoin("MESSAGE=Bootchart created: ", file, NULL);
- if (!bootchart_message)
- return log_oom();
-
- IOVEC_SET_STRING(iovec[j++], bootchart_message);
-
- p = malloc(10 + BOOTCHART_MAX);
- if (!p)
- return log_oom();
-
- memcpy(p, "BOOTCHART=", 10);
-
- fd = open(file, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return log_error_errno(errno, "Failed to open bootchart data \"%s\": %m", file);
-
- n = loop_read(fd, p + 10, BOOTCHART_MAX, false);
- if (n < 0)
- return log_error_errno(n, "Failed to read bootchart data: %m");
-
- iovec[j].iov_base = p;
- iovec[j].iov_len = 10 + n;
- j++;
-
- r = sd_journal_sendv(iovec, j);
- if (r < 0)
- log_error_errno(r, "Failed to send bootchart: %m");
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- static struct list_sample_data *sampledata;
- _cleanup_closedir_ DIR *proc = NULL;
- _cleanup_free_ char *build = NULL;
- _cleanup_fclose_ FILE *of = NULL;
- _cleanup_close_ int sysfd = -1;
- struct ps_struct *ps_first;
- double graph_start;
- double log_start;
- double interval;
- char output_file[PATH_MAX];
- char datestr[200];
- int pscount = 0;
- int n_cpus = 0;
- int overrun = 0;
- time_t t = 0;
- int r, samples;
- struct ps_struct *ps;
- struct rlimit rlim;
- struct list_sample_data *head;
- struct sigaction sig = {
- .sa_handler = signal_handler,
- };
-
- parse_conf();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- return EXIT_FAILURE;
-
- if (r == 0)
- return EXIT_SUCCESS;
-
- /*
- * If the kernel executed us through init=/usr/lib/systemd/systemd-bootchart, then
- * fork:
- * - parent execs executable specified via init_path[] (/usr/lib/systemd/systemd by default) as pid=1
- * - child logs data
- */
- if (getpid() == 1) {
- if (fork())
- /* parent */
- execl(arg_init_path, arg_init_path, NULL);
- }
- argv[0][0] = '@';
-
- rlim.rlim_cur = 4096;
- rlim.rlim_max = 4096;
- (void) setrlimit(RLIMIT_NOFILE, &rlim);
-
- /* start with empty ps LL */
- ps_first = new0(struct ps_struct, 1);
- if (!ps_first) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- /* handle TERM/INT nicely */
- sigaction(SIGHUP, &sig, NULL);
-
- interval = (1.0 / arg_hz) * 1000000000.0;
-
- if (arg_relative)
- graph_start = log_start = gettime_ns();
- else {
- struct timespec n;
- double uptime;
-
- clock_gettime(clock_boottime_or_monotonic(), &n);
- uptime = (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC));
-
- log_start = gettime_ns();
- graph_start = log_start - uptime;
- }
-
- if (graph_start < 0.0) {
- log_error("Failed to setup graph start time.\n\n"
- "The system uptime probably includes time that the system was suspended. "
- "Use --rel to bypass this issue.");
- return EXIT_FAILURE;
- }
-
- LIST_HEAD_INIT(head);
-
- /* main program loop */
- for (samples = 0; !exiting && samples < arg_samples_len; samples++) {
- int res;
- double sample_stop;
- double elapsed;
- double timeleft;
-
- sampledata = new0(struct list_sample_data, 1);
- if (sampledata == NULL) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- sampledata->sampletime = gettime_ns();
- sampledata->counter = samples;
-
- if (sysfd < 0)
- sysfd = open("/sys", O_RDONLY|O_CLOEXEC);
-
- if (!build) {
- if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &build, NULL) == -ENOENT)
- parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
- }
-
- if (proc)
- rewinddir(proc);
- else
- proc = opendir("/proc");
-
- /* wait for /proc to become available, discarding samples */
- if (proc) {
- r = log_sample(proc, samples, ps_first, &sampledata, &pscount, &n_cpus);
- if (r < 0)
- return EXIT_FAILURE;
- }
-
- sample_stop = gettime_ns();
-
- elapsed = (sample_stop - sampledata->sampletime) * 1000000000.0;
- timeleft = interval - elapsed;
-
- /*
- * check if we have not consumed our entire timeslice. If we
- * do, don't sleep and take a new sample right away.
- * we'll lose all the missed samples and overrun our total
- * time
- */
- if (timeleft > 0) {
- struct timespec req;
-
- req.tv_sec = (time_t)(timeleft / 1000000000.0);
- req.tv_nsec = (long)(timeleft - (req.tv_sec * 1000000000.0));
-
- res = nanosleep(&req, NULL);
- if (res) {
- if (errno == EINTR)
- /* caught signal, probably HUP! */
- break;
- log_error_errno(errno, "nanosleep() failed: %m");
- return EXIT_FAILURE;
- }
- } else {
- overrun++;
- /* calculate how many samples we lost and scrap them */
- arg_samples_len -= (int)(-timeleft / interval);
- }
- LIST_PREPEND(link, head, sampledata);
- }
-
- /* do some cleanup, close fd's */
- ps = ps_first;
- while (ps->next_ps) {
- ps = ps->next_ps;
- ps->schedstat = safe_close(ps->schedstat);
- ps->sched = safe_close(ps->sched);
- ps->smaps = safe_fclose(ps->smaps);
- }
-
- if (!of) {
- t = time(NULL);
- r = strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t));
- assert_se(r > 0);
-
- snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", arg_output_path, datestr);
- of = fopen(output_file, "we");
- }
-
- if (!of) {
- log_error("Error opening output file '%s': %m\n", output_file);
- return EXIT_FAILURE;
- }
-
- r = svg_do(of, strna(build), head, ps_first,
- samples, pscount, n_cpus, graph_start,
- log_start, interval, overrun);
-
- if (r < 0) {
- log_error_errno(r, "Error generating svg file: %m");
- return EXIT_FAILURE;
- }
-
- log_info("systemd-bootchart wrote %s\n", output_file);
-
- r = do_journal_append(output_file);
- if (r < 0)
- return EXIT_FAILURE;
-
- /* nitpic cleanups */
- ps = ps_first->next_ps;
- while (ps->next_ps) {
- struct ps_struct *old;
-
- old = ps;
- old->sample = ps->first;
- ps = ps->next_ps;
- while (old->sample->next) {
- struct ps_sched_struct *oldsample = old->sample;
-
- old->sample = old->sample->next;
- free(oldsample);
- }
- free(old->cgroup);
- free(old->sample);
- free(old);
- }
-
- free(ps->cgroup);
- free(ps->sample);
- free(ps);
-
- sampledata = head;
- while (sampledata->link_prev) {
- struct list_sample_data *old_sampledata = sampledata;
- sampledata = sampledata->link_prev;
- free(old_sampledata);
- }
- free(sampledata);
-
- /* don't complain when overrun once, happens most commonly on 1st sample */
- if (overrun > 1)
- log_warning("systemd-bootchart: sample time overrun %i times\n", overrun);
-
- return 0;
-}
diff --git a/src/bootchart/bootchart.conf b/src/bootchart/bootchart.conf
deleted file mode 100644
index 4f5e50936e..0000000000
--- a/src/bootchart/bootchart.conf
+++ /dev/null
@@ -1,26 +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 bootchart.conf(5) for details.
-
-[Bootchart]
-#Samples=500
-#Frequency=25
-#Relative=no
-#Filter=yes
-#Output=<folder name, defaults to /run/log>
-#Init=/path/to/init-binary
-#PlotMemoryUsage=no
-#PlotEntropyGraph=no
-#ScaleX=100
-#ScaleY=20
-#ControlGroup=no
-#PerCPU=no
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
deleted file mode 100644
index 1b445b954b..0000000000
--- a/src/bootchart/bootchart.h
+++ /dev/null
@@ -1,119 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "list.h"
-
-#define MAXCPUS 16
-#define MAXPIDS 65535
-
-struct block_stat_struct {
- /* /proc/vmstat pgpgin & pgpgout */
- int bi;
- int bo;
-};
-
-struct cpu_stat_sample_struct {
- /* /proc/schedstat fields 10 & 11 (after name) */
- double runtime;
- double waittime;
-};
-
-/* per process, per sample data we will log */
-struct ps_sched_struct {
- /* /proc/<n>/schedstat fields 1 & 2 */
- double runtime;
- double waittime;
- int pss;
- struct list_sample_data *sampledata;
- struct ps_sched_struct *next;
- struct ps_sched_struct *prev;
- struct ps_sched_struct *cross; /* cross pointer */
- struct ps_struct *ps_new;
-};
-
-struct list_sample_data {
- double runtime[MAXCPUS];
- double waittime[MAXCPUS];
- double sampletime;
- int entropy_avail;
- struct block_stat_struct blockstat;
- LIST_FIELDS(struct list_sample_data, link); /* DLL */
- int counter;
-};
-
-/* process info */
-struct ps_struct {
- struct ps_struct *next_ps; /* SLL pointer */
- struct ps_struct *parent; /* ppid ref */
- struct ps_struct *children; /* children */
- struct ps_struct *next; /* siblings */
-
- /* must match - otherwise it's a new process with same PID */
- char name[256];
- int pid;
- int ppid;
- char *cgroup;
-
- /* cache fd's */
- int sched;
- int schedstat;
- FILE *smaps;
-
- /* pointers to first/last seen timestamps */
- struct ps_sched_struct *first;
- struct ps_sched_struct *last;
-
- /* records actual start time, may be way before bootchart runs */
- double starttime;
-
- /* record human readable total cpu time */
- double total;
-
- /* largest PSS size found */
- int pss_max;
-
- /* for drawing connection lines later */
- double pos_x;
- double pos_y;
-
- struct ps_sched_struct *sample;
-};
-
-extern bool arg_relative;
-extern bool arg_filter;
-extern bool arg_show_cmdline;
-extern bool arg_show_cgroup;
-extern bool arg_pss;
-extern bool arg_entropy;
-extern bool arg_percpu;
-extern bool arg_initcall;
-extern int arg_samples_len;
-extern double arg_hz;
-extern double arg_scale_x;
-extern double arg_scale_y;
-
-extern char arg_output_path[PATH_MAX];
-extern char arg_init_path[PATH_MAX];
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
deleted file mode 100644
index 42cb8043ce..0000000000
--- a/src/bootchart/store.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "bootchart.h"
-#include "cgroup-util.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "parse-util.h"
-#include "store.h"
-#include "string-util.h"
-#include "strxcpyx.h"
-#include "time-util.h"
-#include "util.h"
-
-/*
- * Alloc a static 4k buffer for stdio - primarily used to increase
- * PSS buffering from the default 1k stdin buffer to reduce
- * read() overhead.
- */
-static char smaps_buf[4096];
-static int skip = 0;
-
-double gettime_ns(void) {
- struct timespec n;
-
- clock_gettime(CLOCK_MONOTONIC, &n);
-
- return (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC));
-}
-
-static char *bufgetline(char *buf) {
- char *c;
-
- if (!buf)
- return NULL;
-
- c = strchr(buf, '\n');
- if (c)
- c++;
-
- return c;
-}
-
-static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) {
- char filename[PATH_MAX];
- _cleanup_close_ int fd = -1;
- ssize_t n;
-
- sprintf(filename, "%d/cmdline", pid);
- fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- n = read(fd, buffer, buf_len-1);
- if (n > 0) {
- int i;
- for (i = 0; i < n; i++)
- if (buffer[i] == '\0')
- buffer[i] = ' ';
- buffer[n] = '\0';
- }
-
- return 0;
-}
-
-int log_sample(DIR *proc,
- int sample,
- struct ps_struct *ps_first,
- struct list_sample_data **ptr,
- int *pscount,
- int *cpus) {
-
- static int vmstat = -1;
- _cleanup_free_ char *buf_schedstat = NULL;
- char buf[4096];
- char key[256];
- char val[256];
- char rt[256];
- char wt[256];
- char *m;
- int r;
- int c;
- int p;
- int mod;
- static int e_fd = -1;
- ssize_t s;
- ssize_t n;
- struct dirent *ent;
- int fd;
- struct list_sample_data *sampledata;
- struct ps_sched_struct *ps_prev = NULL;
- int procfd;
- int taskfd = -1;
-
- sampledata = *ptr;
-
- procfd = dirfd(proc);
- if (procfd < 0)
- return -errno;
-
- if (vmstat < 0) {
- /* block stuff */
- vmstat = openat(procfd, "vmstat", O_RDONLY|O_CLOEXEC);
- if (vmstat < 0)
- return log_error_errno(errno, "Failed to open /proc/vmstat: %m");
- }
-
- n = pread(vmstat, buf, sizeof(buf) - 1, 0);
- if (n <= 0) {
- vmstat = safe_close(vmstat);
- if (n < 0)
- return -errno;
- return -ENODATA;
- }
-
- buf[n] = '\0';
-
- m = buf;
- while (m) {
- if (sscanf(m, "%s %s", key, val) < 2)
- goto vmstat_next;
- if (streq(key, "pgpgin"))
- sampledata->blockstat.bi = atoi(val);
- if (streq(key, "pgpgout")) {
- sampledata->blockstat.bo = atoi(val);
- break;
- }
-vmstat_next:
- m = bufgetline(m);
- if (!m)
- break;
- }
-
- /* Parse "/proc/schedstat" for overall CPU utilization */
- r = read_full_file("/proc/schedstat", &buf_schedstat, NULL);
- if (r < 0)
- return log_error_errno(r, "Unable to read schedstat: %m");
-
- m = buf_schedstat;
- while (m) {
- if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3)
- goto schedstat_next;
-
- if (strstr(key, "cpu")) {
- r = safe_atoi((const char*)(key+3), &c);
- if (r < 0 || c > MAXCPUS -1)
- /* Oops, we only have room for MAXCPUS data */
- break;
- sampledata->runtime[c] = atoll(rt);
- sampledata->waittime[c] = atoll(wt);
-
- if (c == *cpus)
- *cpus = c + 1;
- }
-schedstat_next:
- m = bufgetline(m);
- if (!m)
- break;
- }
-
- if (arg_entropy) {
- if (e_fd < 0) {
- e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY|O_CLOEXEC);
- if (e_fd < 0)
- return log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m");
- }
-
- n = pread(e_fd, buf, sizeof(buf) - 1, 0);
- if (n <= 0) {
- e_fd = safe_close(e_fd);
- } else {
- buf[n] = '\0';
- sampledata->entropy_avail = atoi(buf);
- }
- }
-
- while ((ent = readdir(proc)) != NULL) {
- char filename[PATH_MAX];
- int pid;
- struct ps_struct *ps;
-
- if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9'))
- continue;
-
- pid = atoi(ent->d_name);
-
- if (pid >= MAXPIDS)
- continue;
-
- ps = ps_first;
- while (ps->next_ps) {
- ps = ps->next_ps;
- if (ps->pid == pid)
- break;
- }
-
- /* end of our LL? then append a new record */
- if (ps->pid != pid) {
- _cleanup_fclose_ FILE *st = NULL;
- char t[32];
- struct ps_struct *parent;
-
- ps->next_ps = new0(struct ps_struct, 1);
- if (!ps->next_ps)
- return log_oom();
-
- ps = ps->next_ps;
- ps->pid = pid;
- ps->sched = -1;
- ps->schedstat = -1;
-
- ps->sample = new0(struct ps_sched_struct, 1);
- if (!ps->sample)
- return log_oom();
-
- ps->sample->sampledata = sampledata;
-
- (*pscount)++;
-
- /* mark our first sample */
- ps->first = ps->last = ps->sample;
- ps->sample->runtime = atoll(rt);
- ps->sample->waittime = atoll(wt);
-
- /* get name, start time */
- if (ps->sched < 0) {
- sprintf(filename, "%d/sched", pid);
- ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (ps->sched < 0)
- continue;
- }
-
- s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
- if (s <= 0) {
- ps->sched = safe_close(ps->sched);
- continue;
- }
- buf[s] = '\0';
-
- if (!sscanf(buf, "%s %*s %*s", key))
- continue;
-
- strscpy(ps->name, sizeof(ps->name), key);
-
- /* cmdline */
- if (arg_show_cmdline)
- pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
-
- /* discard line 2 */
- m = bufgetline(buf);
- if (!m)
- continue;
-
- m = bufgetline(m);
- if (!m)
- continue;
-
- if (!sscanf(m, "%*s %*s %s", t))
- continue;
-
- r = safe_atod(t, &ps->starttime);
- if (r < 0)
- continue;
-
- ps->starttime /= 1000.0;
-
- if (arg_show_cgroup)
- /* if this fails, that's OK */
- cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER,
- ps->pid, &ps->cgroup);
-
- /* ppid */
- sprintf(filename, "%d/stat", pid);
- fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- continue;
-
- st = fdopen(fd, "re");
- if (!st) {
- close(fd);
- continue;
- }
-
- if (!fscanf(st, "%*s %*s %*s %i", &p))
- continue;
-
- ps->ppid = p;
-
- /*
- * setup child pointers
- *
- * these are used to paint the tree coherently later
- * each parent has a LL of children, and a LL of siblings
- */
- if (pid == 1)
- continue; /* nothing to do for init atm */
-
- /* kthreadd has ppid=0, which breaks our tree ordering */
- if (ps->ppid == 0)
- ps->ppid = 1;
-
- parent = ps_first;
- while ((parent->next_ps && parent->pid != ps->ppid))
- parent = parent->next_ps;
-
- if (parent->pid != ps->ppid) {
- /* orphan */
- ps->ppid = 1;
- parent = ps_first->next_ps;
- }
-
- ps->parent = parent;
-
- if (!parent->children) {
- /* it's the first child */
- parent->children = ps;
- } else {
- /* walk all children and append */
- struct ps_struct *children;
- children = parent->children;
- while (children->next)
- children = children->next;
-
- children->next = ps;
- }
- }
-
- /* else -> found pid, append data in ps */
-
- /* below here is all continuous logging parts - we get here on every
- * iteration */
-
- /* rt, wt */
- if (ps->schedstat < 0) {
- sprintf(filename, "%d/schedstat", pid);
- ps->schedstat = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (ps->schedstat < 0)
- continue;
- }
-
- s = pread(ps->schedstat, buf, sizeof(buf) - 1, 0);
- if (s <= 0) {
- /* clean up our file descriptors - assume that the process exited */
- close(ps->schedstat);
- ps->schedstat = -1;
- ps->sched = safe_close(ps->sched);
- continue;
- }
-
- buf[s] = '\0';
-
- if (!sscanf(buf, "%s %s %*s", rt, wt))
- continue;
-
- ps->sample->next = new0(struct ps_sched_struct, 1);
- if (!ps->sample->next)
- return log_oom();
-
- ps->sample->next->prev = ps->sample;
- ps->sample = ps->sample->next;
- ps->last = ps->sample;
- ps->sample->runtime = atoll(rt);
- ps->sample->waittime = atoll(wt);
- ps->sample->sampledata = sampledata;
- ps->sample->ps_new = ps;
- if (ps_prev)
- ps_prev->cross = ps->sample;
-
- ps_prev = ps->sample;
- ps->total = (ps->last->runtime - ps->first->runtime)
- / 1000000000.0;
-
- /* Take into account CPU runtime/waittime spent in non-main threads of the process
- * by parsing "/proc/[pid]/task/[tid]/schedstat" for all [tid] != [pid]
- * See https://github.com/systemd/systemd/issues/139
- */
-
- /* Browse directory "/proc/[pid]/task" to know the thread ids of process [pid] */
- snprintf(filename, sizeof(filename), PID_FMT "/task", pid);
- taskfd = openat(procfd, filename, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
- if (taskfd >= 0) {
- _cleanup_closedir_ DIR *taskdir = NULL;
-
- taskdir = fdopendir(taskfd);
- if (!taskdir) {
- safe_close(taskfd);
- return -errno;
- }
- FOREACH_DIRENT(ent, taskdir, break) {
- int tid = -1;
- _cleanup_close_ int tid_schedstat = -1;
- long long delta_rt;
- long long delta_wt;
-
- if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9'))
- continue;
-
- /* Skip main thread as it was already accounted */
- r = safe_atoi(ent->d_name, &tid);
- if (r < 0 || tid == pid)
- continue;
-
- /* Parse "/proc/[pid]/task/[tid]/schedstat" */
- snprintf(filename, sizeof(filename), PID_FMT "/schedstat", tid);
- tid_schedstat = openat(taskfd, filename, O_RDONLY|O_CLOEXEC);
-
- if (tid_schedstat == -1)
- continue;
-
- s = pread(tid_schedstat, buf, sizeof(buf) - 1, 0);
- if (s <= 0)
- continue;
- buf[s] = '\0';
-
- if (!sscanf(buf, "%s %s %*s", rt, wt))
- continue;
-
- r = safe_atolli(rt, &delta_rt);
- if (r < 0)
- continue;
- r = safe_atolli(rt, &delta_wt);
- if (r < 0)
- continue;
- ps->sample->runtime += delta_rt;
- ps->sample->waittime += delta_wt;
- }
- }
-
- if (!arg_pss)
- goto catch_rename;
-
- /* Pss */
- if (!ps->smaps) {
- sprintf(filename, "%d/smaps", pid);
- fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- continue;
- ps->smaps = fdopen(fd, "re");
- if (!ps->smaps) {
- close(fd);
- continue;
- }
- setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
- } else {
- rewind(ps->smaps);
- }
-
- /* test to see if we need to skip another field */
- if (skip == 0) {
- if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
- continue;
- }
- if (fread(buf, 1, 28 * 15, ps->smaps) != (28 * 15)) {
- continue;
- }
- if (buf[392] == 'V') {
- skip = 2;
- }
- else {
- skip = 1;
- }
- rewind(ps->smaps);
- }
-
- while (1) {
- int pss_kb;
-
- /* skip one line, this contains the object mapped. */
- if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
- break;
- }
- /* then there's a 28 char 14 line block */
- if (fread(buf, 1, 28 * 14, ps->smaps) != 28 * 14) {
- break;
- }
- pss_kb = atoi(&buf[61]);
- ps->sample->pss += pss_kb;
-
- /* skip one more line if this is a newer kernel */
- if (skip == 2) {
- if (fgets(buf, sizeof(buf), ps->smaps) == NULL)
- break;
- }
- }
-
- if (ps->sample->pss > ps->pss_max)
- ps->pss_max = ps->sample->pss;
-
-catch_rename:
- /* catch process rename, try to randomize time */
- mod = (arg_hz < 4.0) ? 4.0 : (arg_hz / 4.0);
- if (((sample - ps->pid) + pid) % (int)(mod) == 0) {
-
- /* re-fetch name */
- /* get name, start time */
- if (ps->sched < 0) {
- sprintf(filename, "%d/sched", pid);
- ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
- if (ps->sched < 0)
- continue;
- }
-
- s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
- if (s <= 0) {
- /* clean up file descriptors */
- ps->sched = safe_close(ps->sched);
- ps->schedstat = safe_close(ps->schedstat);
- continue;
- }
-
- buf[s] = '\0';
-
- if (!sscanf(buf, "%s %*s %*s", key))
- continue;
-
- strscpy(ps->name, sizeof(ps->name), key);
-
- /* cmdline */
- if (arg_show_cmdline)
- pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
- }
- }
-
- return 0;
-}
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
deleted file mode 100644
index f2af535061..0000000000
--- a/src/bootchart/svg.c
+++ /dev/null
@@ -1,1375 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/utsname.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "architecture.h"
-#include "bootchart.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "list.h"
-#include "macro.h"
-#include "stdio-util.h"
-#include "store.h"
-#include "svg.h"
-#include "utf8.h"
-#include "util.h"
-
-#define time_to_graph(t) ((t) * arg_scale_x)
-#define ps_to_graph(n) ((n) * arg_scale_y)
-#define kb_to_graph(m) ((m) * arg_scale_y * 0.0001)
-#define to_color(n) (192.0 - ((n) * 192.0))
-
-static const char * const colorwheel[12] = {
- "rgb(255,32,32)", // red
- "rgb(32,192,192)", // cyan
- "rgb(255,128,32)", // orange
- "rgb(128,32,192)", // blue-violet
- "rgb(255,255,32)", // yellow
- "rgb(192,32,128)", // red-violet
- "rgb(32,255,32)", // green
- "rgb(255,64,32)", // red-orange
- "rgb(32,32,255)", // blue
- "rgb(255,192,32)", // yellow-orange
- "rgb(192,32,192)", // violet
- "rgb(32,192,32)" // yellow-green
-};
-
-static double idletime = -1.0;
-static int pfiltered = 0;
-static int pcount = 0;
-static int kcount = 0;
-static double psize = 0;
-static double ksize = 0;
-static double esize = 0;
-static struct list_sample_data *sampledata;
-static struct list_sample_data *prev_sampledata;
-
-static void svg_header(FILE *of, struct list_sample_data *head, double graph_start, int n_cpus) {
- double w;
- double h;
- struct list_sample_data *sampledata_last;
-
- assert(head);
-
- sampledata_last = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- sampledata_last = sampledata;
- }
-
- /* min width is about 1600px due to the label */
- w = 150.0 + 10.0 + time_to_graph(sampledata_last->sampletime - graph_start);
- w = ((w < 1600.0) ? 1600.0 : w);
-
- /* height is variable based on pss, psize, ksize */
- h = 400.0 + (arg_scale_y * 30.0) /* base graphs and title */
- + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */
- + psize + ksize + esize + (n_cpus * 15 * arg_scale_y);
-
- fprintf(of, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
- fprintf(of, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
- fprintf(of, "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
-
- //fprintf(of, "<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
- fprintf(of, "<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ", w, h);
- fprintf(of, "xmlns=\"http://www.w3.org/2000/svg\">\n\n");
-
- /* write some basic info as a comment, including some help */
- fprintf(of, "<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
- fprintf(of, "<!-- such as Chrome, Chromium, or Firefox. Other applications that -->\n");
- fprintf(of, "<!-- render these files properly but more slowly are ImageMagick, gimp, -->\n");
- fprintf(of, "<!-- inkscape, etc. To display the files on your system, just point -->\n");
- fprintf(of, "<!-- your browser to file:///run/log/ and click. This bootchart was -->\n\n");
-
- fprintf(of, "<!-- generated by bootchart version %s, running with options: -->\n", VERSION);
- fprintf(of, "<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len);
- fprintf(of, "<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y);
- fprintf(of, "<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter);
- fprintf(of, "<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy);
- fprintf(of, "<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path);
-
- /* style sheet */
- fprintf(of, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
-
- fprintf(of, " rect { stroke-width: 1; }\n");
- fprintf(of, " rect.bg { fill: rgb(255,255,255); }\n");
- fprintf(of, " rect.cpu { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
- fprintf(of, " rect.wait { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
- fprintf(of, " rect.bi { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
- fprintf(of, " rect.bo { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
- fprintf(of, " rect.ps { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
- fprintf(of, " rect.krnl { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
- fprintf(of, " rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
- fprintf(of, " rect.clrw { stroke-width: 0; fill-opacity: 0.7;}\n");
- fprintf(of, " line { stroke: rgb(64,64,64); stroke-width: 1; }\n");
- fprintf(of, "// line.sec1 { }\n");
- fprintf(of, " line.sec5 { stroke-width: 2; }\n");
- fprintf(of, " line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
- fprintf(of, " line.dot { stroke-dasharray: 2 4; }\n");
- fprintf(of, " line.idle { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
-
- fprintf(of, " .run { font-size: 8; font-style: italic; }\n");
- fprintf(of, " text { font-family: Verdana, Helvetica; font-size: 10; }\n");
- fprintf(of, " text.sec { font-size: 8; }\n");
- fprintf(of, " text.t1 { font-size: 24; }\n");
- fprintf(of, " text.t2 { font-size: 12; }\n");
- fprintf(of, " text.idle { font-size: 18; }\n");
-
- fprintf(of, " ]]>\n </style>\n</defs>\n\n");
-}
-
-static int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) {
- _cleanup_free_ char *cmdline = NULL;
- _cleanup_free_ char *model = NULL;
- _cleanup_free_ char *buf = NULL;
- char date[256] = "Unknown";
- const char *cpu;
- char *c;
- time_t t;
- int r;
- struct utsname uts;
-
- r = read_one_line_file("/proc/cmdline", &cmdline);
- if (r < 0) {
- log_error_errno(r, "Unable to read cmdline: %m");
- return r;
- }
-
- /* extract root fs so we can find disk model name in sysfs */
- /* FIXME: this works only in the simple case */
- c = strstr(cmdline, "root=/dev/");
- if (c) {
- char rootbdev[4];
- char filename[32];
-
- strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
- rootbdev[3] = '\0';
- xsprintf(filename, "/sys/block/%s/device/model", rootbdev);
-
- r = read_one_line_file(filename, &model);
- if (r < 0)
- log_info("Error reading disk model for %s: %m\n", rootbdev);
- }
-
- /* various utsname parameters */
- r = uname(&uts);
- if (r < 0) {
- log_error("Error getting uname info\n");
- return -errno;
- }
-
- /* date */
- t = time(NULL);
- r = strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
- assert_se(r > 0);
-
- /* CPU type */
- r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf);
- if (r < 0)
- cpu = "Unknown";
- else
- cpu = buf;
-
- fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
- uts.nodename, date);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
- uts.sysname, uts.release, uts.version, uts.machine);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
- if (model)
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
-
- if (idletime >= 0.0)
- fprintf(of, "%.03fs", idletime);
- else
- fprintf(of, "Not detected");
-
- fprintf(of, "</text>\n");
- fprintf(of, "<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
- arg_hz, arg_samples_len, overrun, pscount, pfiltered);
-
- return 0;
-}
-
-static void svg_graph_box(FILE *of, struct list_sample_data *head, int height, double graph_start) {
- double d = 0.0;
- int i = 0;
- double finalsample = 0.0;
- struct list_sample_data *sampledata_last;
-
- sampledata_last = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- sampledata_last = sampledata;
- }
-
- finalsample = sampledata_last->sampletime;
-
- /* outside box, fill */
- fprintf(of, "<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(0.0),
- time_to_graph(finalsample - graph_start),
- ps_to_graph(height));
-
- for (d = graph_start; d <= finalsample;
- d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) {
- /* lines for each second */
- if (i % 50 == 0)
- fprintf(of, " <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- time_to_graph(d - graph_start),
- time_to_graph(d - graph_start),
- ps_to_graph(height));
- else if (i % 10 == 0)
- fprintf(of, " <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- time_to_graph(d - graph_start),
- time_to_graph(d - graph_start),
- ps_to_graph(height));
- else
- fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- time_to_graph(d - graph_start),
- time_to_graph(d - graph_start),
- ps_to_graph(height));
-
- /* time label */
- if (i % 10 == 0)
- fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
- time_to_graph(d - graph_start),
- -5.0, d - graph_start);
-
- i++;
- }
-}
-
-/* xml comments must not contain "--" */
-static char* xml_comment_encode(const char* name) {
- char *enc_name, *p;
-
- enc_name = strdup(name);
- if (!enc_name)
- return NULL;
-
- for (p = enc_name; *p; p++)
- if (p[0] == '-' && p[1] == '-')
- p[1] = '_';
-
- return enc_name;
-}
-
-static void svg_pss_graph(FILE *of,
- struct list_sample_data *head,
- struct ps_struct *ps_first,
- double graph_start) {
- struct ps_struct *ps;
- int i;
- struct list_sample_data *sampledata_last;
-
- sampledata_last = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- sampledata_last = sampledata;
- }
-
-
- fprintf(of, "\n\n<!-- Pss memory size graph -->\n");
-
- fprintf(of, "\n <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
-
- /* vsize 1000 == 1000mb */
- svg_graph_box(of, head, 100, graph_start);
- /* draw some hlines for usable memory sizes */
- for (i = 100000; i < 1000000; i += 100000) {
- fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
- time_to_graph(.0),
- kb_to_graph(i),
- time_to_graph(sampledata_last->sampletime - graph_start),
- kb_to_graph(i));
- fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
- time_to_graph(sampledata_last->sampletime - graph_start) + 5,
- kb_to_graph(i), (1000000 - i) / 1000);
- }
- fprintf(of, "\n");
-
- /* now plot the graph itself */
- i = 1;
- prev_sampledata = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int bottom;
- int top;
- struct ps_sched_struct *cross_place;
-
- bottom = 0;
- top = 0;
-
- /* put all the small pss blocks into the bottom */
- ps = ps_first;
- while (ps->next_ps) {
- ps = ps->next_ps;
- if (!ps)
- continue;
- ps->sample = ps->first;
- while (ps->sample->next) {
- ps->sample = ps->sample->next;
- if (ps->sample->sampledata == sampledata)
- break;
- }
- if (ps->sample->sampledata == sampledata) {
- if (ps->sample->pss <= (100 * arg_scale_y))
- top += ps->sample->pss;
- break;
- }
- }
- while (ps->sample->cross) {
- cross_place = ps->sample->cross;
- ps = ps->sample->cross->ps_new;
- ps->sample = cross_place;
- if (ps->sample->pss <= (100 * arg_scale_y))
- top += ps->sample->pss;
- }
-
- fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- "rgb(64,64,64)",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- kb_to_graph(1000000.0 - top),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- kb_to_graph(top - bottom));
- bottom = top;
-
- /* now plot the ones that are of significant size */
- ps = ps_first;
- while (ps->next_ps) {
- ps = ps->next_ps;
- if (!ps)
- continue;
- ps->sample = ps->first;
- while (ps->sample->next) {
- ps->sample = ps->sample->next;
- if (ps->sample->sampledata == sampledata)
- break;
- }
- /* don't draw anything smaller than 2mb */
- if (ps->sample->sampledata != sampledata)
- continue;
- if (ps->sample->pss > (100 * arg_scale_y)) {
- top = bottom + ps->sample->pss;
- fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- colorwheel[ps->pid % 12],
- time_to_graph(prev_sampledata->sampletime - graph_start),
- kb_to_graph(1000000.0 - top),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- kb_to_graph(top - bottom));
- bottom = top;
- }
- break;
- }
-
- while ((cross_place = ps->sample->cross)) {
- ps = ps->sample->cross->ps_new;
- ps->sample = cross_place;
- if (ps->sample->pss > (100 * arg_scale_y)) {
- top = bottom + ps->sample->pss;
- fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- colorwheel[ps->pid % 12],
- time_to_graph(prev_sampledata->sampletime - graph_start),
- kb_to_graph(1000000.0 - top),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- kb_to_graph(top - bottom));
- bottom = top;
- }
- }
-
- prev_sampledata = sampledata;
- i++;
- }
-
- /* overlay all the text labels */
- i = 1;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int bottom;
- int top = 0;
- struct ps_sched_struct *prev_sample;
- struct ps_sched_struct *cross_place;
-
- /* put all the small pss blocks into the bottom */
- ps = ps_first->next_ps;
- while (ps->next_ps) {
- ps = ps->next_ps;
- if (!ps)
- continue;
-
- ps->sample = ps->first;
- while (ps->sample->next) {
- ps->sample = ps->sample->next;
- if (ps->sample->sampledata == sampledata)
- break;
- }
-
- if (ps->sample->sampledata == sampledata) {
- if (ps->sample->pss <= (100 * arg_scale_y))
- top += ps->sample->pss;
-
- break;
- }
- }
-
- while ((cross_place = ps->sample->cross)) {
- ps = ps->sample->cross->ps_new;
- ps->sample = cross_place;
- if (ps->sample->pss <= (100 * arg_scale_y))
- top += ps->sample->pss;
- }
- bottom = top;
-
- /* now plot the ones that are of significant size */
- ps = ps_first;
- while (ps->next_ps) {
- prev_sample = ps->sample;
- ps = ps->next_ps;
- if (!ps)
- continue;
- ps->sample = ps->first;
- while (ps->sample->next) {
- prev_sample = ps->sample;
- ps->sample = ps->sample->next;
- if (ps->sample->sampledata == sampledata)
- break;
- }
- /* don't draw anything smaller than 2mb */
- if (ps->sample->sampledata == sampledata) {
- if (ps->sample->pss > (100 * arg_scale_y)) {
- top = bottom + ps->sample->pss;
- /* draw a label with the process / PID */
- if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
- fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
- time_to_graph(sampledata->sampletime - graph_start),
- kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
- ps->name, ps->pid);
- bottom = top;
- }
- break;
- }
- }
- while ((cross_place = ps->sample->cross)) {
- ps = ps->sample->cross->ps_new;
- ps->sample = cross_place;
- prev_sample = ps->sample->prev;
- if (ps->sample->pss > (100 * arg_scale_y)) {
- top = bottom + ps->sample->pss;
- /* draw a label with the process / PID */
- if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
- fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
- time_to_graph(sampledata->sampletime - graph_start),
- kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
- ps->name, ps->pid);
- bottom = top;
- }
- }
-
- i++;
- }
-
- /* debug output - full data dump */
- fprintf(of, "\n\n<!-- PSS map - csv format -->\n");
- ps = ps_first;
- while (ps->next_ps) {
- _cleanup_free_ char *enc_name = NULL;
- ps = ps->next_ps;
- if (!ps)
- continue;
-
- enc_name = xml_comment_encode(ps->name);
- if (!enc_name)
- continue;
-
- fprintf(of, "<!-- %s [%d] pss=", enc_name, ps->pid);
-
- ps->sample = ps->first;
- while (ps->sample->next) {
- ps->sample = ps->sample->next;
- fprintf(of, "%d," , ps->sample->pss);
- }
-
- fprintf(of, " -->\n");
- }
-
-}
-
-static void svg_io_bi_bar(FILE *of,
- struct list_sample_data *head,
- int n_samples,
- double graph_start,
- double interval) {
-
- double max = 0.0;
- double range;
- int max_here = 0;
- int i;
- int k;
- struct list_sample_data *start_sampledata;
- struct list_sample_data *stop_sampledata;
-
- fprintf(of, "<!-- IO utilization graph - In -->\n");
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
-
- /*
- * calculate rounding range
- *
- * We need to round IO data since IO block data is not updated on
- * each poll. Applying a smoothing function loses some burst data,
- * so keep the smoothing range short.
- */
- range = 0.25 / (1.0 / arg_hz);
- if (range < 2.0)
- range = 2.0; /* no smoothing */
-
- /* surrounding box */
- svg_graph_box(of, head, 5, graph_start);
-
- /* find the max IO first */
- i = 1;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int start;
- int stop;
- int diff;
- double tot;
-
- start = MAX(i - ((range / 2) - 1), 0);
- stop = MIN(i + (range / 2), n_samples - 1);
- diff = (stop - start);
-
- start_sampledata = sampledata;
- stop_sampledata = sampledata;
-
- for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++)
- start_sampledata = start_sampledata->link_next;
-
- for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
- stop_sampledata = stop_sampledata->link_prev;
-
- tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
-
- if (tot > max) {
- max = tot;
- max_here = i;
- }
-
- tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
-
- if (tot > max)
- max = tot;
-
- i++;
- }
-
- /* plot bi */
- i = 1;
- prev_sampledata = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int start;
- int stop;
- int diff;
- double tot;
- double pbi = 0;
-
- start = MAX(i - ((range / 2) - 1), 0);
- stop = MIN(i + (range / 2), n_samples);
- diff = (stop - start);
-
- start_sampledata = sampledata;
- stop_sampledata = sampledata;
-
- for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
- start_sampledata = start_sampledata->link_next;
-
- for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
- stop_sampledata = stop_sampledata->link_prev;
-
- tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
-
- if (max > 0)
- pbi = tot / max;
-
- if (pbi > 0.001)
- fprintf(of, "<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- pbi * (arg_scale_y * 5));
-
- /* labels around highest value */
- if (i == max_here)
- fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
- time_to_graph(sampledata->sampletime - graph_start) + 5,
- ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
- max / 1024.0 / (interval / 1000000000.0));
-
- i++;
- prev_sampledata = sampledata;
- }
-}
-
-static void svg_io_bo_bar(FILE *of,
- struct list_sample_data *head,
- int n_samples,
- double graph_start,
- double interval) {
- double max = 0.0;
- double range;
- int max_here = 0;
- int i;
- int k;
- struct list_sample_data *start_sampledata;
- struct list_sample_data *stop_sampledata;
-
- fprintf(of, "<!-- IO utilization graph - out -->\n");
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
-
- /*
- * calculate rounding range
- *
- * We need to round IO data since IO block data is not updated on
- * each poll. Applying a smoothing function loses some burst data,
- * so keep the smoothing range short.
- */
- range = 0.25 / (1.0 / arg_hz);
- if (range < 2.0)
- range = 2.0; /* no smoothing */
-
- /* surrounding box */
- svg_graph_box(of, head, 5, graph_start);
-
- /* find the max IO first */
- i = 0;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int start;
- int stop;
- int diff;
- double tot;
-
- start = MAX(i - ((range / 2) - 1), 0);
- stop = MIN(i + (range / 2), n_samples - 1);
- diff = (stop - start);
-
- start_sampledata = sampledata;
- stop_sampledata = sampledata;
-
- for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++)
- start_sampledata = start_sampledata->link_next;
-
- for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
- stop_sampledata = stop_sampledata->link_prev;
-
- tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
- if (tot > max)
- max = tot;
-
- tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
- if (tot > max) {
- max = tot;
- max_here = i;
- }
-
- i++;
- }
-
- /* plot bo */
- prev_sampledata = head;
- i = 1;
-
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int start, stop, diff;
- double tot, pbo;
-
- pbo = 0;
-
- start = MAX(i - ((range / 2) - 1), 0);
- stop = MIN(i + (range / 2), n_samples);
- diff = (stop - start);
-
- start_sampledata = sampledata;
- stop_sampledata = sampledata;
-
- for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
- start_sampledata = start_sampledata->link_next;
-
- for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
- stop_sampledata = stop_sampledata->link_prev;
-
- tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
- / diff;
-
- if (max > 0)
- pbo = tot / max;
-
- if (pbo > 0.001)
- fprintf(of, "<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- pbo * (arg_scale_y * 5));
-
- /* labels around highest bo value */
- if (i == max_here)
- fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
- time_to_graph(sampledata->sampletime - graph_start) + 5,
- ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
- max / 1024.0 / (interval / 1000000000.0));
-
- i++;
- prev_sampledata = sampledata;
- }
-}
-
-static void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
-
- fprintf(of, "<!-- CPU utilization graph -->\n");
-
- if (cpu_num < 0)
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
- else
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
-
- /* surrounding box */
- svg_graph_box(of, head, 5, graph_start);
-
- /* bars for each sample, proportional to the CPU util. */
- prev_sampledata = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int c;
- double trt;
- double ptrt;
-
- ptrt = trt = 0.0;
-
- if (cpu_num < 0)
- for (c = 0; c < n_cpus; c++)
- trt += sampledata->runtime[c] - prev_sampledata->runtime[c];
- else
- trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num];
-
- trt = trt / 1000000000.0;
-
- if (cpu_num < 0)
- trt = trt / (double)n_cpus;
-
- if (trt > 0.0)
- ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime);
-
- if (ptrt > 1.0)
- ptrt = 1.0;
-
- if (ptrt > 0.001)
- fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- ptrt * (arg_scale_y * 5));
-
- prev_sampledata = sampledata;
- }
-}
-
-static void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
-
- fprintf(of, "<!-- Wait time aggregation box -->\n");
-
- if (cpu_num < 0)
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
- else
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
-
- /* surrounding box */
- svg_graph_box(of, head, 5, graph_start);
-
- /* bars for each sample, proportional to the CPU util. */
- prev_sampledata = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- int c;
- double twt;
- double ptwt;
-
- ptwt = twt = 0.0;
-
- if (cpu_num < 0)
- for (c = 0; c < n_cpus; c++)
- twt += sampledata->waittime[c] - prev_sampledata->waittime[c];
- else
- twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num];
-
- twt = twt / 1000000000.0;
-
- if (cpu_num < 0)
- twt = twt / (double)n_cpus;
-
- if (twt > 0.0)
- ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime);
-
- if (ptwt > 1.0)
- ptwt = 1.0;
-
- if (ptwt > 0.001)
- fprintf(of, "<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- ptwt * (arg_scale_y * 5));
-
- prev_sampledata = sampledata;
- }
-}
-
-static void svg_entropy_bar(FILE *of, struct list_sample_data *head, double graph_start) {
-
- fprintf(of, "<!-- entropy pool graph -->\n");
-
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
- /* surrounding box */
- svg_graph_box(of, head, 5, graph_start);
-
- /* bars for each sample, scale 0-4096 */
- prev_sampledata = head;
- LIST_FOREACH_BEFORE(link, sampledata, head) {
- fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev_sampledata->sampletime - graph_start),
- ((arg_scale_y * 5) - ((sampledata->entropy_avail / 4096.) * (arg_scale_y * 5))),
- time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
- (sampledata->entropy_avail / 4096.) * (arg_scale_y * 5));
- prev_sampledata = sampledata;
- }
-}
-
-static struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_first) {
- /*
- * walk the list of processes and return the next one to be
- * painted
- */
- if (ps == ps_first)
- return ps->next_ps;
-
- /* go deep */
- if (ps->children)
- return ps->children;
-
- /* find siblings */
- if (ps->next)
- return ps->next;
-
- /* go back for parent siblings */
- for (;;) {
- if (ps->parent && ps->parent->next)
- return ps->parent->next;
-
- ps = ps->parent;
- if (!ps)
- return ps;
- }
-
- return NULL;
-}
-
-static bool ps_filter(struct ps_struct *ps) {
- if (!arg_filter)
- return false;
-
- /* can't draw data when there is only 1 sample (need start + stop) */
- if (ps->first == ps->last)
- return true;
-
- /* don't filter kthreadd */
- if (ps->pid == 2)
- return false;
-
- /* drop stuff that doesn't use any real CPU time */
- if (ps->total <= 0.001)
- return true;
-
- return 0;
-}
-
-static void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) {
- _cleanup_pclose_ FILE *f = NULL;
- double t;
- char func[256];
- int ret;
- int usecs;
-
- /* can't plot initcall when disabled or in relative mode */
- if (!arg_initcall || arg_relative) {
- kcount = 0;
- return;
- }
-
- if (!count_only) {
- fprintf(of, "<!-- initcall -->\n");
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
- /* surrounding box */
- svg_graph_box(of, head, kcount, graph_start);
- }
-
- kcount = 0;
-
- /*
- * Initcall graphing - parses dmesg buffer and displays kernel threads
- * This somewhat uses the same methods and scaling to show processes
- * but looks a lot simpler. It's overlaid entirely onto the PS graph
- * when appropriate.
- */
-
- f = popen("dmesg", "r");
- if (!f)
- return;
-
- while (!feof(f)) {
- int c;
- int z = 0;
- char l[256];
-
- if (fgets(l, sizeof(l) - 1, f) == NULL)
- continue;
-
- c = sscanf(l, "[%lf] initcall %s %*s %d %*s %d %*s",
- &t, func, &ret, &usecs);
- if (c != 4) {
- /* also parse initcalls done by module loading */
- c = sscanf(l, "[%lf] initcall %s %*s %*s %d %*s %d %*s",
- &t, func, &ret, &usecs);
- if (c != 4)
- continue;
- }
-
- /* chop the +0xXX/0xXX stuff */
- while(func[z] != '+')
- z++;
- func[z] = 0;
-
- if (count_only) {
- /* filter out irrelevant stuff */
- if (usecs >= 1000)
- kcount++;
- continue;
- }
-
- fprintf(of, "<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
- func, t, usecs, ret);
-
- if (usecs < 1000)
- continue;
-
- /* rect */
- fprintf(of, " <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(t - (usecs / 1000000.0)),
- ps_to_graph(kcount),
- time_to_graph(usecs / 1000000.0),
- ps_to_graph(1));
-
- /* label */
- fprintf(of, " <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
- time_to_graph(t - (usecs / 1000000.0)) + 5,
- ps_to_graph(kcount) + 15,
- func, usecs / 1000000.0);
-
- kcount++;
- }
-}
-
-static void svg_ps_bars(FILE *of,
- struct list_sample_data *head,
- int n_samples,
- int n_cpus,
- struct ps_struct *ps_first,
- double graph_start,
- double interval) {
-
- struct ps_struct *ps;
- int i = 0;
- int j = 0;
- int pid;
- double w = 0.0;
-
- fprintf(of, "<!-- Process graph -->\n");
- fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
-
- /* surrounding box */
- svg_graph_box(of, head, pcount, graph_start);
-
- /* pass 2 - ps boxes */
- ps = ps_first;
- while ((ps = get_next_ps(ps, ps_first))) {
- _cleanup_free_ char *enc_name = NULL, *escaped = NULL;
- double endtime;
- double starttime;
- int t;
-
- if (!utf8_is_printable(ps->name, strlen(ps->name)))
- escaped = utf8_escape_non_printable(ps->name);
-
- enc_name = xml_comment_encode(escaped ? escaped : ps->name);
- if (!enc_name)
- continue;
-
- /* leave some trace of what we actually filtered etc. */
- fprintf(of, "<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
- ps->ppid, ps->total);
-
- starttime = ps->first->sampledata->sampletime;
-
- if (!ps_filter(ps)) {
- /* remember where _to_ our children need to draw a line */
- ps->pos_x = time_to_graph(starttime - graph_start);
- ps->pos_y = ps_to_graph(j+1); /* bottom left corner */
- } else if (ps->parent){
- /* hook children to our parent coords instead */
- ps->pos_x = ps->parent->pos_x;
- ps->pos_y = ps->parent->pos_y;
-
- /* if this is the last child, we might still need to draw a connecting line */
- if ((!ps->next) && (ps->parent))
- fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- ps->parent->pos_x,
- ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
- ps->parent->pos_x,
- ps->parent->pos_y);
- continue;
- }
-
- endtime = ps->last->sampledata->sampletime;
- fprintf(of, " <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(starttime - graph_start),
- ps_to_graph(j),
- time_to_graph(ps->last->sampledata->sampletime - starttime),
- ps_to_graph(1));
-
- /* paint cpu load over these */
- ps->sample = ps->first;
- t = 1;
- while (ps->sample->next) {
- double rt, prt;
- double wt, wrt;
- struct ps_sched_struct *prev;
-
- prev = ps->sample;
- ps->sample = ps->sample->next;
-
- /* calculate over interval */
- rt = ps->sample->runtime - prev->runtime;
- wt = ps->sample->waittime - prev->waittime;
-
- prt = (rt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime);
- wrt = (wt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime);
-
- /* this can happen if timekeeping isn't accurate enough */
- if (prt > 1.0)
- prt = 1.0;
- if (wrt > 1.0)
- wrt = 1.0;
-
- if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */
- continue;
-
- fprintf(of, " <rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev->sampledata->sampletime - graph_start),
- ps_to_graph(j),
- time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
- ps_to_graph(wrt));
-
- /* draw cpu over wait - TODO figure out how/why run + wait > interval */
- fprintf(of, " <rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
- time_to_graph(prev->sampledata->sampletime - graph_start),
- ps_to_graph(j + (1.0 - prt)),
- time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
- ps_to_graph(prt));
- t++;
- }
-
- /* determine where to display the process name */
- if ((endtime - starttime) < 1.5)
- /* too small to fit label inside the box */
- w = endtime;
- else
- w = starttime;
-
- /* text label of process name */
- fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan> %s</text>\n",
- time_to_graph(w - graph_start) + 5.0,
- ps_to_graph(j) + 14.0,
- escaped ? escaped : ps->name,
- ps->pid,
- (ps->last->runtime - ps->first->runtime) / 1000000000.0,
- arg_show_cgroup ? ps->cgroup : "");
- /* paint lines to the parent process */
- if (ps->parent) {
- /* horizontal part */
- fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- time_to_graph(starttime - graph_start),
- ps_to_graph(j) + 10.0,
- ps->parent->pos_x,
- ps_to_graph(j) + 10.0);
-
- /* one vertical line connecting all the horizontal ones up */
- if (!ps->next)
- fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- ps->parent->pos_x,
- ps_to_graph(j) + 10.0,
- ps->parent->pos_x,
- ps->parent->pos_y);
- }
-
- j++; /* count boxes */
-
- fprintf(of, "\n");
- }
-
- /* last pass - determine when idle */
- pid = getpid();
- /* make sure we start counting from the point where we actually have
- * data: assume that bootchart's first sample is when data started
- */
-
- ps = ps_first;
- while (ps->next_ps) {
- ps = ps->next_ps;
- if (ps->pid == pid)
- break;
- }
-
- /* need to know last node first */
- ps->sample = ps->first;
- i = ps->sample->next->sampledata->counter;
-
- while (ps->sample->next && i<(n_samples-(arg_hz/2))) {
- double crt;
- double brt;
- int c;
- int ii;
- struct ps_sched_struct *sample_hz;
-
- ps->sample = ps->sample->next;
- sample_hz = ps->sample;
- for (ii = 0; (ii < (int)arg_hz/2) && sample_hz->next; ii++)
- sample_hz = sample_hz->next;
-
- /* subtract bootchart cpu utilization from total */
- crt = 0.0;
- for (c = 0; c < n_cpus; c++)
- crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c];
-
- brt = sample_hz->runtime - ps->sample->runtime;
- /*
- * our definition of "idle":
- *
- * if for (hz / 2) we've used less CPU than (interval / 2) ...
- * defaults to 4.0%, which experimentally, is where atom idles
- */
- if ((crt - brt) < (interval / 2.0)) {
- idletime = ps->sample->sampledata->sampletime - graph_start;
- fprintf(of, "\n<!-- idle detected at %.03f seconds -->\n", idletime);
- fprintf(of, "<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
- time_to_graph(idletime),
- -arg_scale_y,
- time_to_graph(idletime),
- ps_to_graph(pcount) + arg_scale_y);
- fprintf(of, "<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n",
- time_to_graph(idletime) + 5.0,
- ps_to_graph(pcount) + arg_scale_y,
- idletime);
- break;
- }
-
- i++;
- }
-}
-
-static void svg_top_ten_cpu(FILE *of, struct ps_struct *ps_first) {
- struct ps_struct *top[10];
- struct ps_struct emptyps = {};
- struct ps_struct *ps;
- int n, m;
-
- for (n = 0; n < (int) ELEMENTSOF(top); n++)
- top[n] = &emptyps;
-
- /* walk all ps's and setup ptrs */
- ps = ps_first;
- while ((ps = get_next_ps(ps, ps_first))) {
- for (n = 0; n < 10; n++) {
- if (ps->total <= top[n]->total)
- continue;
- /* cascade insert */
- for (m = 9; m > n; m--)
- top[m] = top[m-1];
- top[n] = ps;
- break;
- }
- }
-
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
- for (n = 0; n < 10; n++)
- fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
- 20 + (n * 13),
- top[n]->total,
- top[n]->name,
- top[n]->pid);
-}
-
-static void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) {
- struct ps_struct *top[10];
- struct ps_struct emptyps = {};
- struct ps_struct *ps;
- int n, m;
-
- for (n = 0; n < (int) ELEMENTSOF(top); n++)
- top[n] = &emptyps;
-
- /* walk all ps's and setup ptrs */
- ps = ps_first;
- while ((ps = get_next_ps(ps, ps_first))) {
- for (n = 0; n < 10; n++) {
- if (ps->pss_max <= top[n]->pss_max)
- continue;
-
- /* cascade insert */
- for (m = 9; m > n; m--)
- top[m] = top[m-1];
- top[n] = ps;
- break;
- }
- }
-
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
- for (n = 0; n < 10; n++)
- fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
- 20 + (n * 13),
- top[n]->pss_max,
- top[n]->name,
- top[n]->pid);
-}
-
-int svg_do(FILE *of,
- const char *build,
- struct list_sample_data *head,
- struct ps_struct *ps_first,
- int n_samples,
- int pscount,
- int n_cpus,
- double graph_start,
- double log_start,
- double interval,
- int overrun) {
-
- struct ps_struct *ps;
- double offset = 7;
- int r, c;
-
- sampledata = head;
- LIST_FIND_TAIL(link, sampledata, head);
- ps = ps_first;
-
- /* count initcall thread count first */
- svg_do_initcall(of, head, 1, graph_start);
- ksize = kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0;
-
- /* then count processes */
- while ((ps = get_next_ps(ps, ps_first))) {
- if (!ps_filter(ps))
- pcount++;
- else
- pfiltered++;
- }
- psize = ps_to_graph(pcount) + (arg_scale_y * 2);
-
- esize = (arg_entropy ? arg_scale_y * 7 : 0);
-
- /* after this, we can draw the header with proper sizing */
- svg_header(of, head, graph_start, arg_percpu ? n_cpus : 0);
- fprintf(of, "<rect class=\"bg\" width=\"100%%\" height=\"100%%\" />\n\n");
-
- fprintf(of, "<g transform=\"translate(10,400)\">\n");
- svg_io_bi_bar(of, head, n_samples, graph_start, interval);
- fprintf(of, "</g>\n\n");
-
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
- svg_io_bo_bar(of, head, n_samples, graph_start, interval);
- fprintf(of, "</g>\n\n");
-
- for (c = -1; c < (arg_percpu ? n_cpus : 0); c++) {
- offset += 7;
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
- svg_cpu_bar(of, head, n_cpus, c, graph_start);
- fprintf(of, "</g>\n\n");
-
- offset += 7;
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
- svg_wait_bar(of, head, n_cpus, c, graph_start);
- fprintf(of, "</g>\n\n");
- }
-
- if (kcount) {
- offset += 7;
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
- svg_do_initcall(of, head, 0, graph_start);
- fprintf(of, "</g>\n\n");
- }
-
- offset += 7;
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize);
- svg_ps_bars(of, head, n_samples, n_cpus, ps_first, graph_start, interval);
- fprintf(of, "</g>\n\n");
-
- fprintf(of, "<g transform=\"translate(10, 0)\">\n");
- r = svg_title(of, build, pscount, log_start, overrun);
- fprintf(of, "</g>\n\n");
-
- if (r < 0)
- return r;
-
- fprintf(of, "<g transform=\"translate(10,200)\">\n");
- svg_top_ten_cpu(of, ps_first);
- fprintf(of, "</g>\n\n");
-
- if (arg_entropy) {
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
- svg_entropy_bar(of, head, graph_start);
- fprintf(of, "</g>\n\n");
- }
-
- if (arg_pss) {
- fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize);
- svg_pss_graph(of, head, ps_first, graph_start);
- fprintf(of, "</g>\n\n");
-
- fprintf(of, "<g transform=\"translate(410,200)\">\n");
- svg_top_ten_pss(of, ps_first);
- fprintf(of, "</g>\n\n");
- }
-
- /* fprintf footer */
- fprintf(of, "\n</svg>\n");
-
- return 0;
-}
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index b839fadd04..d6fb10cac5 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -184,7 +184,7 @@ int main(int argc, char *argv[]) {
goto finish;
if (!arg_no_pager) {
- r = pager_open(false);
+ r = pager_open(arg_no_pager, false);
if (r > 0 && arg_full < 0)
arg_full = true;
}
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 39235a95f6..9c34928052 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -765,7 +765,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
}
int unit_watch_cgroup(Unit *u) {
- _cleanup_free_ char *populated = NULL;
+ _cleanup_free_ char *events = NULL;
int r;
assert(u);
@@ -791,11 +791,11 @@ int unit_watch_cgroup(Unit *u) {
if (r < 0)
return log_oom();
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
if (r < 0)
return log_oom();
- u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, populated, IN_MODIFY);
+ u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
if (u->cgroup_inotify_wd < 0) {
if (errno == ENOENT) /* If the directory is already
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index f939196397..00372b92b4 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -139,7 +139,7 @@ static int property_get_tainted(
if (access("/proc/cgroups", F_OK) < 0)
e = stpcpy(e, "cgroups-missing:");
- if (clock_is_localtime() > 0)
+ if (clock_is_localtime(NULL) > 0)
e = stpcpy(e, "local-hwclock:");
/* remove the last ':' */
diff --git a/src/core/device.c b/src/core/device.c
index d201dc5e4b..28e4039da2 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -318,7 +318,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
* 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) {
+ if (dev && 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)) {
diff --git a/src/core/execute.c b/src/core/execute.c
index 184c72dbe7..ac2ac39892 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -24,6 +24,7 @@
#include <poll.h>
#include <signal.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/socket.h>
@@ -1824,6 +1825,11 @@ static int exec_child(
if (params->apply_permissions) {
+ bool use_address_families = context->address_families_whitelist ||
+ !set_isempty(context->address_families);
+ bool use_syscall_filter = context->syscall_whitelist ||
+ !set_isempty(context->syscall_filter) ||
+ !set_isempty(context->syscall_archs);
int secure_bits = context->secure_bits;
for (i = 0; i < _RLIMIT_MAX; i++) {
@@ -1876,7 +1882,7 @@ static int exec_child(
* also to the context secure_bits so that we don't try to
* drop the bit away next. */
- secure_bits |= 1<<SECURE_KEEP_CAPS;
+ secure_bits |= 1<<SECURE_KEEP_CAPS;
}
}
@@ -1890,15 +1896,15 @@ static int exec_child(
return -errno;
}
- if (context->no_new_privileges)
+ if (context->no_new_privileges ||
+ (!have_effective_cap(CAP_SYS_ADMIN) && (use_address_families || use_syscall_filter)))
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
*exit_status = EXIT_NO_NEW_PRIVILEGES;
return -errno;
}
#ifdef HAVE_SECCOMP
- if (context->address_families_whitelist ||
- !set_isempty(context->address_families)) {
+ if (use_address_families) {
r = apply_address_families(context);
if (r < 0) {
*exit_status = EXIT_ADDRESS_FAMILIES;
@@ -1906,9 +1912,7 @@ static int exec_child(
}
}
- if (context->syscall_whitelist ||
- !set_isempty(context->syscall_filter) ||
- !set_isempty(context->syscall_archs)) {
+ if (use_syscall_filter) {
r = apply_seccomp(context);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
@@ -2237,7 +2241,7 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
if (fn[0] == '-') {
ignore = true;
- fn ++;
+ fn++;
}
if (!path_is_absolute(fn)) {
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index 39f5519ca1..bb2bc3f399 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -62,7 +62,8 @@ int failure_action(
log_and_status(m, "Rebooting as result of failure.");
update_reboot_param_file(reboot_arg);
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
@@ -89,7 +90,8 @@ int failure_action(
case FAILURE_ACTION_POWEROFF:
log_and_status(m, "Powering off as result of failure.");
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
case FAILURE_ACTION_POWEROFF_FORCE:
diff --git a/src/core/job.c b/src/core/job.c
index 97304c4d05..5557a6a942 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -222,7 +222,7 @@ Job* job_install(Job *j) {
*pj = j;
j->installed = true;
- j->manager->n_installed_jobs ++;
+ j->manager->n_installed_jobs++;
log_unit_debug(j->unit,
"Installed new job %s/%s as %u",
j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
@@ -645,7 +645,7 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Stopped %s.",
[JOB_FAILED] = "Stopped (with error) %s.",
- [JOB_TIMEOUT] = "Timed out stoppping %s.",
+ [JOB_TIMEOUT] = "Timed out stopping %s.",
};
static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Reloaded %s.",
@@ -690,17 +690,20 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
}
static void job_print_status_message(Unit *u, JobType t, JobResult result) {
- static const char* const job_result_status_table[_JOB_RESULT_MAX] = {
- [JOB_DONE] = ANSI_GREEN " OK " ANSI_NORMAL,
- [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED " TIME " ANSI_NORMAL,
- [JOB_FAILED] = ANSI_HIGHLIGHT_RED "FAILED" ANSI_NORMAL,
- [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW "DEPEND" ANSI_NORMAL,
- [JOB_SKIPPED] = ANSI_HIGHLIGHT " INFO " ANSI_NORMAL,
- [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW "ASSERT" ANSI_NORMAL,
- [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW "UNSUPP" ANSI_NORMAL,
+ static struct {
+ const char *color, *word;
+ } const statuses[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = {ANSI_GREEN, " OK "},
+ [JOB_TIMEOUT] = {ANSI_HIGHLIGHT_RED, " TIME "},
+ [JOB_FAILED] = {ANSI_HIGHLIGHT_RED, "FAILED"},
+ [JOB_DEPENDENCY] = {ANSI_HIGHLIGHT_YELLOW, "DEPEND"},
+ [JOB_SKIPPED] = {ANSI_HIGHLIGHT, " INFO "},
+ [JOB_ASSERT] = {ANSI_HIGHLIGHT_YELLOW, "ASSERT"},
+ [JOB_UNSUPPORTED] = {ANSI_HIGHLIGHT_YELLOW, "UNSUPP"},
};
const char *format;
+ const char *status;
assert(u);
assert(t >= 0);
@@ -714,11 +717,16 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
if (!format)
return;
+ if (log_get_show_color())
+ status = strjoina(statuses[result].color, statuses[result].word, ANSI_NORMAL);
+ else
+ status = statuses[result].word;
+
if (result != JOB_DONE)
manager_flip_auto_status(u->manager, true);
DISABLE_WARNING_FORMAT_NONLITERAL;
- unit_status_printf(u, job_result_status_table[result], format);
+ unit_status_printf(u, status, format);
REENABLE_WARNING;
if (t == JOB_START && result == JOB_FAILED) {
@@ -856,7 +864,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
}
if (result == JOB_FAILED || result == JOB_INVALID)
- j->manager->n_failed_jobs ++;
+ j->manager->n_failed_jobs++;
job_uninstall(j);
job_free(j);
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 4a65d174b8..d078924c5b 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -119,7 +119,7 @@ int config_parse_unit_deps(
assert(rvalue);
p = rvalue;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
int r;
@@ -620,7 +620,7 @@ int config_parse_exec(
separate_argv0 = true;
else
break;
- f ++;
+ f++;
}
if (isempty(f)) {
@@ -668,7 +668,7 @@ int config_parse_exec(
/* Check explicitly for an unquoted semicolon as
* command separator token. */
if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) {
- p ++;
+ p++;
p += strspn(p, WHITESPACE);
semicolon = true;
break;
@@ -1599,7 +1599,7 @@ int config_parse_service_sockets(
assert(data);
p = rvalue;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, 0);
@@ -3361,7 +3361,7 @@ int config_parse_protect_home(
ProtectHome h;
h = protect_home_from_string(rvalue);
- if (h < 0){
+ if (h < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
return 0;
}
@@ -3404,7 +3404,7 @@ int config_parse_protect_system(
ProtectSystem s;
s = protect_system_from_string(rvalue);
- if (s < 0){
+ if (s < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
return 0;
}
@@ -3507,7 +3507,19 @@ static int merge_by_names(Unit **u, Set *names, const char *id) {
* ours? Then let's try it the other way
* round */
- other = manager_get_unit((*u)->manager, k);
+ /* If the symlink name we are looking at is unit template, then
+ we must search for instance of this template */
+ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE)) {
+ _cleanup_free_ char *instance = NULL;
+
+ r = unit_name_replace_instance(k, (*u)->instance, &instance);
+ if (r < 0)
+ return r;
+
+ other = manager_get_unit((*u)->manager, instance);
+ } else
+ other = manager_get_unit((*u)->manager, k);
+
free(k);
if (other) {
diff --git a/src/core/main.c b/src/core/main.c
index c725a686f1..56df32426a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -102,7 +102,7 @@ static bool arg_crash_reboot = false;
static bool arg_confirm_spawn = false;
static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
static bool arg_switched_root = false;
-static int arg_no_pager = -1;
+static bool arg_no_pager = false;
static char ***arg_join_controllers = NULL;
static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
@@ -127,14 +127,6 @@ 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) {
-
- if (arg_no_pager <= 0)
- return;
-
- pager_open(false);
-}
-
noreturn static void freeze_or_reboot(void) {
if (arg_crash_reboot) {
@@ -883,8 +875,6 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_TEST:
arg_action = ACTION_TEST;
- if (arg_no_pager < 0)
- arg_no_pager = true;
break;
case ARG_NO_PAGER:
@@ -994,8 +984,6 @@ static int parse_argv(int argc, char *argv[]) {
case 'h':
arg_action = ACTION_HELP;
- if (arg_no_pager < 0)
- arg_no_pager = true;
break;
case 'D':
@@ -1073,7 +1061,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
return log_error_errno(r, "Failed to create serialization file: %m");
/* Make sure nothing is really destructed when we shut down */
- m->n_reloading ++;
+ m->n_reloading++;
bus_manager_send_reloading(m, true);
fds = fdset_new();
@@ -1230,10 +1218,15 @@ static int status_welcome(void) {
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file: %m");
- return status_printf(NULL, false, false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- isempty(ansi_color) ? "1" : ansi_color,
- isempty(pretty_name) ? "Linux" : pretty_name);
+ if (log_get_show_color())
+ return status_printf(NULL, false, false,
+ "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+ isempty(ansi_color) ? "1" : ansi_color,
+ isempty(pretty_name) ? "Linux" : pretty_name);
+ else
+ return status_printf(NULL, false, false,
+ "\nWelcome to %s!\n",
+ isempty(pretty_name) ? "Linux" : pretty_name);
}
static int write_container_id(void) {
@@ -1381,13 +1374,13 @@ int main(int argc, char *argv[]) {
dual_timestamp_get(&security_finish_timestamp);
}
- if (mac_selinux_init(NULL) < 0) {
+ if (mac_selinux_init() < 0) {
error_message = "Failed to initialize SELinux policy";
goto finish;
}
if (!skip_setup) {
- if (clock_is_localtime() > 0) {
+ if (clock_is_localtime(NULL) > 0) {
int min;
/*
@@ -1447,9 +1440,7 @@ int main(int argc, char *argv[]) {
/* clear the kernel timestamp,
* because we are in a container */
- kernel_timestamp.monotonic = 0ULL;
- kernel_timestamp.realtime = 0ULL;
-
+ kernel_timestamp = DUAL_TIMESTAMP_NULL;
} else {
/* Running as user instance */
arg_running_as = MANAGER_USER;
@@ -1548,7 +1539,8 @@ int main(int argc, char *argv[]) {
if (arg_action == ACTION_TEST)
skip_setup = true;
- pager_open_if_enabled();
+ if (arg_action == ACTION_TEST || arg_action == ACTION_HELP)
+ pager_open(arg_no_pager, false);
if (arg_action == ACTION_HELP) {
retval = help();
@@ -1672,7 +1664,7 @@ int main(int argc, char *argv[]) {
test_usr();
}
- if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
+ if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
watchdog_set_timeout(&arg_runtime_watchdog);
if (arg_timer_slack_nsec != NSEC_INFINITY)
@@ -2103,7 +2095,7 @@ finish:
assert(pos < ELEMENTSOF(command_line));
- if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
+ if (arm_reboot_watchdog && arg_shutdown_watchdog > 0 && arg_shutdown_watchdog != USEC_INFINITY) {
char *e;
/* If we reboot let's set the shutdown
diff --git a/src/core/manager.c b/src/core/manager.c
index f36cf5e320..e739795e70 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1137,7 +1137,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
* this is already known, so we increase the counter here
* already */
if (serialization)
- m->n_reloading ++;
+ m->n_reloading++;
/* First, enumerate what we can from all config files */
dual_timestamp_get(&m->units_load_start_timestamp);
@@ -1171,7 +1171,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (serialization) {
assert(m->n_reloading > 0);
- m->n_reloading --;
+ m->n_reloading--;
/* Let's wait for the UnitNew/JobNew messages being
* sent, before we notify that the reload is
@@ -1333,8 +1333,12 @@ int manager_load_unit_prepare(
t = unit_name_to_type(name);
- if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+ if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE))
+ return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is missing the instance name.", name);
+
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
+ }
ret = manager_get_unit(m, name);
if (ret) {
@@ -1631,7 +1635,9 @@ static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) {
log_unit_debug(u, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
unit_unwatch_pid(u, si->si_pid);
- UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
+
+ if (UNIT_VTABLE(u)->sigchld_event)
+ UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
}
static int manager_dispatch_sigchld(Manager *m) {
@@ -2016,7 +2022,7 @@ int manager_loop(Manager *m) {
while (m->exit_code == MANAGER_OK) {
usec_t wait_usec;
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM)
+ if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM)
watchdog_ping();
if (!ratelimit_test(&rl)) {
@@ -2041,7 +2047,7 @@ int manager_loop(Manager *m) {
continue;
/* Sleep for half the watchdog time */
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) {
+ if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && m->running_as == MANAGER_SYSTEM) {
wait_usec = m->runtime_watchdog / 2;
if (wait_usec <= 0)
wait_usec = 1;
@@ -2231,7 +2237,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
assert(f);
assert(fds);
- m->n_reloading ++;
+ m->n_reloading++;
fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id);
fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
@@ -2301,13 +2307,13 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
r = unit_serialize(u, f, fds, !switching_root);
if (r < 0) {
- m->n_reloading --;
+ m->n_reloading--;
return r;
}
}
assert(m->n_reloading > 0);
- m->n_reloading --;
+ m->n_reloading--;
if (ferror(f))
return -EIO;
@@ -2327,7 +2333,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
log_debug("Deserializing state...");
- m->n_reloading ++;
+ m->n_reloading++;
for (;;) {
char line[LINE_MAX], *l;
@@ -2495,7 +2501,7 @@ finish:
r = -EIO;
assert(m->n_reloading > 0);
- m->n_reloading --;
+ m->n_reloading--;
return r;
}
@@ -2511,23 +2517,23 @@ int manager_reload(Manager *m) {
if (r < 0)
return r;
- m->n_reloading ++;
+ m->n_reloading++;
bus_manager_send_reloading(m, true);
fds = fdset_new();
if (!fds) {
- m->n_reloading --;
+ m->n_reloading--;
return -ENOMEM;
}
r = manager_serialize(m, f, fds, false);
if (r < 0) {
- m->n_reloading --;
+ m->n_reloading--;
return r;
}
if (fseeko(f, 0, SEEK_SET) < 0) {
- m->n_reloading --;
+ m->n_reloading--;
return -errno;
}
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index de1a361cc4..32fe51c67e 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -94,7 +94,7 @@ static const MountPoint mount_table[] = {
#endif
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "cgroup", "/sys/fs/cgroup", "cgroup", "__DEVEL__sane_behavior", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ { "cgroup", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER },
{ "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
diff --git a/src/core/mount.c b/src/core/mount.c
index 93d2bd595c..0fd880df5d 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -104,6 +104,14 @@ static bool mount_is_auto(const MountParameters *p) {
return !fstab_test_option(p->options, "noauto\0");
}
+static bool mount_is_automount(const MountParameters *p) {
+ assert(p);
+
+ return fstab_test_option(p->options,
+ "comment=systemd.automount\0"
+ "x-systemd.automount\0");
+}
+
static bool needs_quota(const MountParameters *p) {
assert(p);
@@ -328,7 +336,8 @@ static int mount_add_device_links(Mount *m) {
if (path_equal(m->where, "/"))
return 0;
- if (mount_is_auto(p) && UNIT(m)->manager->running_as == MANAGER_SYSTEM)
+ if (mount_is_auto(p) && !mount_is_automount(p) &&
+ UNIT(m)->manager->running_as == MANAGER_SYSTEM)
device_wants_mount = true;
r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
@@ -369,7 +378,8 @@ static bool should_umount(Mount *m) {
MountParameters *p;
if (path_equal(m->where, "/") ||
- path_equal(m->where, "/usr"))
+ path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs"))
return false;
p = get_mount_parameters(m);
@@ -393,13 +403,15 @@ static int mount_add_default_dependencies(Mount *m) {
if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
return 0;
- /* We do not add any default dependencies to / and /usr, since
- * they are guaranteed to stay mounted the whole time, since
- * our system is on it. Also, don't bother with anything
- * mounted below virtual file systems, it's also going to be
- * virtual, and hence not worth the effort. */
+ /* We do not add any default dependencies to /, /usr or
+ * /run/initramfs/, since they are guaranteed to stay
+ * mounted the whole time, since our system is on it.
+ * Also, don't bother with anything mounted below virtual
+ * file systems, it's also going to be virtual, and hence
+ * not worth the effort. */
if (path_equal(m->where, "/") ||
path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs") ||
path_startswith(m->where, "/proc") ||
path_startswith(m->where, "/sys") ||
path_startswith(m->where, "/dev"))
diff --git a/src/core/scope.c b/src/core/scope.c
index c5d0ecef04..361695c3f9 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -50,8 +50,7 @@ static void scope_init(Unit *u) {
assert(u->load_state == UNIT_STUB);
s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
-
- UNIT(s)->ignore_on_isolate = true;
+ u->ignore_on_isolate = true;
}
static void scope_done(Unit *u) {
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 9a115a4387..4072df58e6 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -88,7 +88,7 @@ int mac_selinux_setup(bool *loaded_policy) {
log_open();
log_error("Failed to compute init label, ignoring.");
} else {
- r = setcon(label);
+ r = setcon_raw(label);
log_open();
if (r < 0)
diff --git a/src/core/service.c b/src/core/service.c
index 1f6d821db3..5d58b0b752 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -942,7 +942,7 @@ static void service_set_state(Service *s, ServiceState state) {
if (ec && exec_context_may_touch_console(ec)) {
Manager *m = UNIT(s)->manager;
- m->n_on_console --;
+ m->n_on_console--;
if (m->n_on_console == 0)
/* unset no_console_output flag, since the console is free */
m->no_console_output = false;
diff --git a/src/core/slice.c b/src/core/slice.c
index d65364c6f4..667f61bde5 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -34,6 +34,13 @@ static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
[SLICE_ACTIVE] = UNIT_ACTIVE
};
+static void slice_init(Unit *u) {
+ assert(u);
+ assert(u->load_state == UNIT_STUB);
+
+ u->ignore_on_isolate = true;
+}
+
static void slice_set_state(Slice *t, SliceState state) {
SliceState old_state;
assert(t);
@@ -305,6 +312,7 @@ const UnitVTable slice_vtable = {
.no_instances = true,
.can_transient = true,
+ .init = slice_init,
.load = slice_load,
.coldplug = slice_coldplug,
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index 0c26e85460..5a6d11cfa1 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -261,7 +261,7 @@ static int write_netlabel_rules(const char* srcdir) {
}
}
- return r;
+ return r;
}
#endif
diff --git a/src/core/socket.c b/src/core/socket.c
index a1cb54d77a..dd515a17a5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1341,8 +1341,12 @@ static int socket_open_fds(Socket *s) {
break;
case SOCKET_USB_FUNCTION:
+ {
+ _cleanup_free_ char *ep = NULL;
- p->fd = usbffs_address_create(p->path);
+ ep = path_make_absolute("ep0", p->path);
+
+ p->fd = usbffs_address_create(ep);
if (p->fd < 0) {
r = p->fd;
goto rollback;
@@ -1357,7 +1361,7 @@ static int socket_open_fds(Socket *s) {
goto rollback;
break;
-
+ }
default:
assert_not_reached("Unknown port type");
}
@@ -1979,7 +1983,7 @@ static void socket_enter_running(Socket *s, int cfd) {
service = SERVICE(UNIT_DEREF(s->service));
unit_ref_unset(&s->service);
- s->n_accepted ++;
+ s->n_accepted++;
UNIT(service)->no_gc = false;
@@ -1990,7 +1994,7 @@ static void socket_enter_running(Socket *s, int cfd) {
goto fail;
cfd = -1;
- s->n_connections ++;
+ s->n_connections++;
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
if (r < 0)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index b28fc76785..c894001cf9 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -391,6 +391,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
if (delete) {
+ const char *status;
/* logging for j not k here here to provide consistent narrative */
log_unit_warning(j->unit,
"Breaking ordering cycle by deleting job %s/%s",
@@ -399,7 +400,13 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"Job %s/%s deleted to break ordering cycle starting with %s/%s",
delete->unit->id, job_type_to_string(delete->type),
j->unit->id, job_type_to_string(j->type));
- unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL,
+
+ if (log_get_show_color())
+ status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
+ else
+ status = " SKIP ";
+
+ unit_status_printf(delete->unit, status,
"Ordering cycle found, skipping %s");
transaction_delete_unit(tr, delete->unit);
return -EAGAIN;
diff --git a/src/core/umount.c b/src/core/umount.c
index a458768e7d..c21a2be54e 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -412,6 +412,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
#ifndef HAVE_SPLIT_USR
|| path_equal(m->path, "/usr")
#endif
+ || path_startswith(m->path, "/run/initramfs")
)
continue;
@@ -472,7 +473,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) {
major(root_st.st_dev) != 0 &&
lstat(m->path, &loopback_st) >= 0 &&
root_st.st_dev == loopback_st.st_rdev) {
- n_failed ++;
+ n_failed++;
continue;
}
@@ -507,7 +508,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed) {
if (k >= 0 &&
major(root_st.st_dev) != 0 &&
root_st.st_dev == m->devnum) {
- n_failed ++;
+ n_failed++;
continue;
}
diff --git a/src/core/unit.c b/src/core/unit.c
index 3c4f85e744..af38beb0c3 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -364,7 +364,7 @@ void unit_add_to_gc_queue(Unit *u) {
LIST_PREPEND(gc_queue, u->manager->gc_queue, u);
u->in_gc_queue = true;
- u->manager->n_in_gc_queue ++;
+ u->manager->n_in_gc_queue++;
}
void unit_add_to_dbus_queue(Unit *u) {
@@ -1864,13 +1864,13 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
ec = unit_get_exec_context(u);
if (ec && exec_context_may_touch_console(ec)) {
if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
- m->n_on_console --;
+ m->n_on_console--;
if (m->n_on_console == 0)
/* unset no_console_output flag, since the console is free */
m->no_console_output = false;
} else
- m->n_on_console ++;
+ m->n_on_console++;
}
}
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index 0034a1a0ac..dac800ebef 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -54,7 +54,7 @@ static enum {
} arg_action = ACTION_LIST;
static const char* arg_field = NULL;
static const char *arg_directory = NULL;
-static int arg_no_pager = false;
+static bool arg_no_pager = false;
static int arg_no_legend = false;
static int arg_one = false;
static FILE* arg_output = NULL;
@@ -852,9 +852,7 @@ int main(int argc, char *argv[]) {
case ACTION_LIST:
case ACTION_INFO:
- if (!arg_no_pager)
- pager_open(false);
-
+ pager_open(arg_no_pager, false);
r = dump_list(j);
break;
diff --git a/src/coredump/stacktrace.c b/src/coredump/stacktrace.c
index 68806992fc..cc4dad9465 100644
--- a/src/coredump/stacktrace.c
+++ b/src/coredump/stacktrace.c
@@ -91,7 +91,7 @@ static int frame_callback(Dwfl_Frame *frame, void *userdata) {
}
fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname));
- c->n_frame ++;
+ c->n_frame++;
return DWARF_CB_OK;
}
@@ -117,7 +117,7 @@ static int thread_callback(Dwfl_Thread *thread, void *userdata) {
if (dwfl_thread_getframes(thread, frame_callback, c) < 0)
return DWARF_CB_ABORT;
- c->n_thread ++;
+ c->n_thread++;
return DWARF_CB_OK;
}
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index 2ef966257a..9927621ea0 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -719,8 +719,12 @@ int main(int argc, char *argv[]) {
int k;
k = crypt_init_by_name(&cd, argv[2]);
- if (k) {
- log_error_errno(k, "crypt_init() failed: %m");
+ if (k == -ENODEV) {
+ log_info("Volume %s already inactive.", argv[2]);
+ r = EXIT_SUCCESS;
+ goto finish;
+ } else if (k) {
+ log_error_errno(k, "crypt_init_by_name() failed: %m");
goto finish;
}
diff --git a/src/delta/delta.c b/src/delta/delta.c
index a54fc89de6..b4f0ecff2d 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -85,14 +85,6 @@ static enum {
(SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED)
} arg_flags = 0;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static int equivalent(const char *a, const char *b) {
_cleanup_free_ char *x = NULL, *y = NULL;
@@ -431,7 +423,7 @@ finish:
hashmap_free_free(top);
hashmap_free_free(bottom);
- HASHMAP_FOREACH_KEY(h, key, drops, i){
+ HASHMAP_FOREACH_KEY(h, key, drops, i) {
hashmap_free_free(hashmap_remove(drops, key));
hashmap_remove(drops, key);
free(key);
@@ -610,7 +602,7 @@ int main(int argc, char *argv[]) {
else if (arg_diff)
arg_flags |= SHOW_OVERRIDDEN;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (optind < argc) {
int i;
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 7790ab865d..435e3805c4 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -245,7 +245,7 @@ static int process_locale(void) {
int r;
etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
- if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localeconf, F_OK) >= 0)
return 0;
if (arg_copy_locale && arg_root) {
@@ -319,7 +319,7 @@ static int process_timezone(void) {
int r;
etc_localtime = prefix_roota(arg_root, "/etc/localtime");
- if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localtime, F_OK) >= 0)
return 0;
if (arg_copy_timezone && arg_root) {
@@ -399,7 +399,7 @@ static int process_hostname(void) {
int r;
etc_hostname = prefix_roota(arg_root, "/etc/hostname");
- if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_hostname, F_OK) >= 0)
return 0;
r = prompt_hostname();
@@ -424,7 +424,7 @@ static int process_machine_id(void) {
int r;
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
- if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_machine_id, F_OK) >= 0)
return 0;
if (sd_id128_equal(arg_machine_id, SD_ID128_NULL))
@@ -450,7 +450,7 @@ static int prompt_root_password(void) {
return 0;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
print_welcome();
@@ -533,7 +533,7 @@ static int process_root_password(void) {
int r;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
mkdir_parents(etc_shadow, 0755);
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 97a48764ae..6f576b5ecf 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -336,8 +336,8 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", unit);
- if (!noauto) {
- lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
+ if (!noauto && !automount) {
+ lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", name, NULL);
if (!lnk)
return log_oom();
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index c37e32e96b..d11756e615 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -706,7 +706,7 @@ int main(int argc, char *argv[]) {
log_open();
umask(0022);
- mac_selinux_init("/etc");
+ mac_selinux_init();
if (argc != 1) {
log_error("This program takes no arguments.");
diff --git a/src/import/import-common.c b/src/import/import-common.c
index 18a30be36d..287a3382a1 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -136,7 +136,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL);
+ execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
@@ -210,7 +210,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "-C", path, "-c", ".", NULL);
+ execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 8a16602c3e..8993402821 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -355,10 +355,12 @@ static int raw_pull_make_local_copy(RawPull *i) {
r = copy_file_atomic(i->settings_path, local_settings, 0644, i->force_local, 0);
if (r == -EEXIST)
log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
- else if (r < 0 && r != -ENOENT)
+ else if (r == -ENOENT)
+ log_debug_errno(r, "Skipping creation of settings file, since none was found.");
+ else if (r < 0)
log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
else
- log_info("Created new settings file '%s.nspawn'", i->local);
+ log_info("Created new settings file %s.", local_settings);
}
return 0;
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index afb13366f0..8c61c46f73 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -251,10 +251,12 @@ static int tar_pull_make_local_copy(TarPull *i) {
r = copy_file_atomic(i->settings_path, local_settings, 0664, i->force_local, 0);
if (r == -EEXIST)
log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
- else if (r < 0 && r != -ENOENT)
+ else if (r == -ENOENT)
+ log_debug_errno(r, "Skipping creation of settings file, since none was found.");
+ else if (r < 0)
log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
else
- log_info("Created new settings file '%s.nspawn'", i->local);
+ log_info("Created new settings file %s.", local_settings);
}
return 0;
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 3e57afb997..41b2237d16 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -314,7 +314,7 @@ static int server_init(Server *s, unsigned n_sockets) {
f->fd = fd;
LIST_PREPEND(fifo, s->fifos, f);
f->server = s;
- s->n_fifos ++;
+ s->n_fifos++;
}
r = bus_connect_system_systemd(&s->bus);
diff --git a/src/journal-remote/browse.html b/src/journal-remote/browse.html
index 3594f70c87..32848c7673 100644
--- a/src/journal-remote/browse.html
+++ b/src/journal-remote/browse.html
@@ -391,7 +391,7 @@
entry = document.getElementById("tableentry");
var buf = "";
- for (var key in d){
+ for (var key in d) {
var data = d[key];
if (data == null)
diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h
index 0b8b6af736..1740a21f92 100644
--- a/src/journal-remote/journal-remote-parse.h
+++ b/src/journal-remote/journal-remote-parse.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "sd-event.h"
#include "journal-remote-write.h"
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
index 5fab74e5cc..7bba52566e 100644
--- a/src/journal-remote/journal-remote-write.c
+++ b/src/journal-remote/journal-remote-write.c
@@ -54,7 +54,7 @@ void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
**********************************************************************/
static int do_rotate(JournalFile **f, bool compress, bool seal) {
- int r = journal_file_rotate(f, compress, seal);
+ int r = journal_file_rotate(f, compress, seal, NULL);
if (r < 0) {
if (*f)
log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h
index 6b645a353c..53ba45fc04 100644
--- a/src/journal-remote/journal-remote-write.h
+++ b/src/journal-remote/journal-remote-write.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,9 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
-
#include "journal-file.h"
typedef struct RemoteServer RemoteServer;
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 3ce6fe27b3..35a1e55f9e 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -203,7 +203,7 @@ static int open_output(Writer *w, const char* host) {
O_RDWR|O_CREAT, 0640,
arg_compress, arg_seal,
&w->metrics,
- w->mmap,
+ w->mmap, NULL,
NULL, &w->journal);
if (r < 0)
log_error_errno(r, "Failed to open output journal %s: %m",
@@ -434,7 +434,7 @@ static int add_raw_socket(RemoteServer *s, int fd) {
return r;
fd_ = -1;
- s->active ++;
+ s->active++;
return 0;
}
@@ -742,7 +742,7 @@ static int setup_microhttpd_server(RemoteServer *s,
goto error;
}
- s->active ++;
+ s->active++;
return 0;
error:
diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h
index 6466a1c101..30ad7df996 100644
--- a/src/journal-remote/journal-remote.h
+++ b/src/journal-remote/journal-remote.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,9 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
-
#include "sd-event.h"
#include "hashmap.h"
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index fc8f63c9e3..e61b6bc68f 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -52,7 +52,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
/* not enough space */
return pos;
- u->entry_state ++;
+ u->entry_state++;
if (pos + r == size) {
/* exactly one character short, but we don't need it */
@@ -76,7 +76,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
/* not enough space */
return pos;
- u->entry_state ++;
+ u->entry_state++;
if (r + pos == size) {
/* exactly one character short, but we don't need it */
@@ -101,7 +101,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
/* not enough space */
return pos;
- u->entry_state ++;
+ u->entry_state++;
if (r + pos == size) {
/* exactly one character short, but we don't need it */
@@ -126,7 +126,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
/* not enough space */
return pos;
- u->entry_state ++;
+ u->entry_state++;
if (r + pos == size) {
/* exactly one character short, but we don't need it */
@@ -156,7 +156,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
continue;
}
- u->entry_state ++;
+ u->entry_state++;
} /* fall through */
case ENTRY_TEXT_FIELD:
@@ -206,7 +206,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
pos += len + 1;
u->field_pos = len + 1;
- u->entry_state ++;
+ u->entry_state++;
} /* fall through */
case ENTRY_BINARY_FIELD_SIZE: {
@@ -220,7 +220,7 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
memcpy(buf + pos, &le64, 8);
pos += 8;
- u->entry_state ++;
+ u->entry_state++;
continue;
}
@@ -230,8 +230,8 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
return pos;
buf[pos++] = '\n';
- u->entry_state ++;
- u->entries_sent ++;
+ u->entry_state++;
+ u->entries_sent++;
return pos;
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 440563e7d3..6e1c3bb9ef 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -75,7 +75,7 @@ static void close_fd_input(Uploader *u);
curl_easy_strerror(code)); \
cmd; \
} \
- } while(0)
+ } while (0)
static size_t output_callback(char *buf,
size_t size,
diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
index 70c4d29c0f..ea160f212b 100644
--- a/src/journal-remote/microhttpd-util.h
+++ b/src/journal-remote/microhttpd-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <microhttpd.h>
#include <stdarg.h>
diff --git a/src/journal/catalog.c b/src/journal/catalog.c
index 164a3a15f2..886f6efd8b 100644
--- a/src/journal/catalog.c
+++ b/src/journal/catalog.c
@@ -164,14 +164,14 @@ static int finish_item(
Hashmap *h,
sd_id128_t id,
const char *language,
- char *payload) {
+ char *payload, size_t payload_size) {
_cleanup_free_ CatalogItem *i = NULL;
- _cleanup_free_ char *combined = NULL, *prev = NULL;
- int r;
+ _cleanup_free_ char *prev = NULL, *combined = NULL;
assert(h);
assert(payload);
+ assert(payload_size > 0);
i = new0(CatalogItem, 1);
if (!i)
@@ -184,23 +184,25 @@ static int finish_item(
}
prev = hashmap_get(h, i);
-
- /* Already have such an item, combine them */
if (prev) {
+ /* Already have such an item, combine them */
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 */
+ if (hashmap_update(h, i, combined) < 0)
+ return log_oom();
+ combined = NULL;
} else {
- r = hashmap_put(h, i, payload);
- if (r < 0)
- return r;
+ /* A new item */
+ combined = memdup(payload, payload_size + 1);
+ if (!combined)
+ return log_oom();
+
+ if (hashmap_put(h, i, combined) < 0)
+ return log_oom();
i = NULL;
+ combined = NULL;
}
return 0;
@@ -215,7 +217,7 @@ int catalog_file_lang(const char* filename, char **lang) {
beg = end - 1;
while (beg > filename && *beg != '.' && *beg != '/' && end - beg < 32)
- beg --;
+ beg--;
if (*beg != '.' || end <= beg + 1)
return 0;
@@ -262,6 +264,7 @@ static int catalog_entry_lang(const char* filename, int line,
int catalog_import_file(Hashmap *h, const char *path) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *payload = NULL;
+ size_t payload_size = 0, payload_allocated = 0;
unsigned n = 0;
sd_id128_t id;
_cleanup_free_ char *deflang = NULL, *lang = NULL;
@@ -283,8 +286,7 @@ int catalog_import_file(Hashmap *h, const char *path) {
for (;;) {
char line[LINE_MAX];
- size_t a, b, c;
- char *t;
+ size_t line_len;
if (!fgets(line, sizeof(line), f)) {
if (feof(f))
@@ -323,17 +325,23 @@ int catalog_import_file(Hashmap *h, const char *path) {
if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
if (got_id) {
- r = finish_item(h, id, lang ?: deflang, payload);
+ if (payload_size == 0) {
+ log_error("[%s:%u] No payload text.", path, n);
+ return -EINVAL;
+ }
+
+ r = finish_item(h, id, lang ?: deflang, payload, payload_size);
if (r < 0)
return r;
- payload = NULL;
lang = mfree(lang);
+ payload_size = 0;
}
if (with_language) {
- t = strstrip(line + 2 + 1 + 32 + 1);
+ char *t;
+ t = strstrip(line + 2 + 1 + 32 + 1);
r = catalog_entry_lang(path, n, t, deflang, &lang);
if (r < 0)
return r;
@@ -343,9 +351,6 @@ int catalog_import_file(Hashmap *h, const char *path) {
empty_line = false;
id = jd;
- if (payload)
- payload[0] = '\0';
-
continue;
}
}
@@ -356,34 +361,30 @@ int catalog_import_file(Hashmap *h, const char *path) {
return -EINVAL;
}
- a = payload ? strlen(payload) : 0;
- b = strlen(line);
-
- c = a + (empty_line ? 1 : 0) + b + 1 + 1;
- t = realloc(payload, c);
- if (!t)
+ line_len = strlen(line);
+ if (!GREEDY_REALLOC(payload, payload_allocated,
+ payload_size + (empty_line ? 1 : 0) + line_len + 1 + 1))
return log_oom();
- if (empty_line) {
- t[a] = '\n';
- memcpy(t + a + 1, line, b);
- t[a+b+1] = '\n';
- t[a+b+2] = 0;
- } else {
- memcpy(t + a, line, b);
- t[a+b] = '\n';
- t[a+b+1] = 0;
- }
+ if (empty_line)
+ payload[payload_size++] = '\n';
+ memcpy(payload + payload_size, line, line_len);
+ payload_size += line_len;
+ payload[payload_size++] = '\n';
+ payload[payload_size] = '\0';
- payload = t;
empty_line = false;
}
if (got_id) {
- r = finish_item(h, id, lang ?: deflang, payload);
+ if (payload_size == 0) {
+ log_error("[%s:%u] No payload text.", path, n);
+ return -EINVAL;
+ }
+
+ r = finish_item(h, id, lang ?: deflang, payload, payload_size);
if (r < 0)
return r;
- payload = NULL;
}
return 0;
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 1933b87b00..c43849c46a 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -17,6 +17,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -498,7 +499,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
total_out += n;
if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
- log_debug("Compressed stream longer than %zd bytes", max_bytes);
+ log_debug("Compressed stream longer than %"PRIu64" bytes", max_bytes);
return -EFBIG;
}
@@ -649,7 +650,7 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
total_out += produced;
if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
- log_debug("Decompressed stream longer than %zd bytes", max_bytes);
+ log_debug("Decompressed stream longer than %"PRIu64" bytes", max_bytes);
r = -EFBIG;
goto cleanup;
}
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 994d1ec5d8..bed825cdc3 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/fs.h>
+#include <pthread.h>
#include <stddef.h>
#include <sys/mman.h>
#include <sys/statvfs.h>
@@ -38,6 +39,7 @@
#include "parse-util.h"
#include "random-util.h"
#include "sd-event.h"
+#include "set.h"
#include "string-util.h"
#include "xattr-util.h"
@@ -86,33 +88,127 @@
/* The mmap context to use for the header we pick as one above the last defined typed */
#define CONTEXT_HEADER _OBJECT_TYPE_MAX
-static int journal_file_set_online(JournalFile *f) {
+/* This may be called from a separate thread to prevent blocking the caller for the duration of fsync().
+ * As a result we use atomic operations on f->offline_state for inter-thread communications with
+ * journal_file_set_offline() and journal_file_set_online(). */
+static void journal_file_set_offline_internal(JournalFile *f) {
assert(f);
+ assert(f->fd >= 0);
+ assert(f->header);
- if (!f->writable)
- return -EPERM;
+ for (;;) {
+ switch (f->offline_state) {
+ case OFFLINE_CANCEL:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_DONE))
+ continue;
+ return;
- if (!(f->fd >= 0 && f->header))
- return -EINVAL;
+ case OFFLINE_AGAIN_FROM_SYNCING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_SYNCING))
+ continue;
+ break;
+
+ case OFFLINE_AGAIN_FROM_OFFLINING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_SYNCING))
+ continue;
+ break;
+
+ case OFFLINE_SYNCING:
+ (void) fsync(f->fd);
+
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_OFFLINING))
+ continue;
+
+ f->header->state = STATE_OFFLINE;
+ (void) fsync(f->fd);
+ break;
+
+ case OFFLINE_OFFLINING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_DONE))
+ continue;
+ /* fall through */
+
+ case OFFLINE_DONE:
+ return;
+
+ case OFFLINE_JOINED:
+ log_debug("OFFLINE_JOINED unexpected offline state for journal_file_set_offline_internal()");
+ return;
+ }
+ }
+}
+
+static void * journal_file_set_offline_thread(void *arg) {
+ JournalFile *f = arg;
+
+ journal_file_set_offline_internal(f);
+
+ return NULL;
+}
+
+static int journal_file_set_offline_thread_join(JournalFile *f) {
+ int r;
+
+ assert(f);
+
+ if (f->offline_state == OFFLINE_JOINED)
+ return 0;
+
+ r = pthread_join(f->offline_thread, NULL);
+ if (r)
+ return -r;
+
+ f->offline_state = OFFLINE_JOINED;
if (mmap_cache_got_sigbus(f->mmap, f->fd))
return -EIO;
- switch (f->header->state) {
- case STATE_ONLINE:
- return 0;
+ return 0;
+}
- case STATE_OFFLINE:
- f->header->state = STATE_ONLINE;
- fsync(f->fd);
- return 0;
+/* Trigger a restart if the offline thread is mid-flight in a restartable state. */
+static bool journal_file_set_offline_try_restart(JournalFile *f) {
+ for (;;) {
+ switch (f->offline_state) {
+ case OFFLINE_AGAIN_FROM_SYNCING:
+ case OFFLINE_AGAIN_FROM_OFFLINING:
+ return true;
+
+ case OFFLINE_CANCEL:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_AGAIN_FROM_SYNCING))
+ continue;
+ return true;
+
+ case OFFLINE_SYNCING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_AGAIN_FROM_SYNCING))
+ continue;
+ return true;
+
+ case OFFLINE_OFFLINING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_AGAIN_FROM_OFFLINING))
+ continue;
+ return true;
default:
- return -EINVAL;
+ return false;
+ }
}
}
-int journal_file_set_offline(JournalFile *f) {
+/* Sets a journal offline.
+ *
+ * If wait is false then an offline is dispatched in a separate thread for a
+ * subsequent journal_file_set_offline() or journal_file_set_online() of the
+ * same journal to synchronize with.
+ *
+ * If wait is true, then either an existing offline thread will be restarted
+ * and joined, or if none exists the offline is simply performed in this
+ * context without involving another thread.
+ */
+int journal_file_set_offline(JournalFile *f, bool wait) {
+ bool restarted;
+ int r;
+
assert(f);
if (!f->writable)
@@ -124,19 +220,109 @@ int journal_file_set_offline(JournalFile *f) {
if (f->header->state != STATE_ONLINE)
return 0;
- fsync(f->fd);
+ /* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */
+ restarted = journal_file_set_offline_try_restart(f);
+ if ((restarted && wait) || !restarted) {
+ r = journal_file_set_offline_thread_join(f);
+ if (r < 0)
+ return r;
+ }
- if (mmap_cache_got_sigbus(f->mmap, f->fd))
- return -EIO;
+ if (restarted)
+ return 0;
+
+ /* Initiate a new offline. */
+ f->offline_state = OFFLINE_SYNCING;
+
+ if (wait) /* Without using a thread if waiting. */
+ journal_file_set_offline_internal(f);
+ else {
+ r = pthread_create(&f->offline_thread, NULL, journal_file_set_offline_thread, f);
+ if (r > 0) {
+ f->offline_state = OFFLINE_JOINED;
+ return -r;
+ }
+ }
+
+ return 0;
+}
+
+static int journal_file_set_online(JournalFile *f) {
+ bool joined = false;
- f->header->state = STATE_OFFLINE;
+ assert(f);
+
+ if (!f->writable)
+ return -EPERM;
+
+ if (!(f->fd >= 0 && f->header))
+ return -EINVAL;
+
+ while (!joined) {
+ switch (f->offline_state) {
+ case OFFLINE_JOINED:
+ /* No offline thread, no need to wait. */
+ joined = true;
+ break;
+
+ case OFFLINE_SYNCING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_CANCEL))
+ continue;
+ /* Canceled syncing prior to offlining, no need to wait. */
+ break;
+
+ case OFFLINE_AGAIN_FROM_SYNCING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_CANCEL))
+ continue;
+ /* Canceled restart from syncing, no need to wait. */
+ break;
+
+ case OFFLINE_AGAIN_FROM_OFFLINING:
+ if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_CANCEL))
+ continue;
+ /* Canceled restart from offlining, must wait for offlining to complete however. */
+
+ /* fall through to wait */
+ default: {
+ int r;
+
+ r = journal_file_set_offline_thread_join(f);
+ if (r < 0)
+ return r;
+
+ joined = true;
+ break;
+ }
+ }
+ }
if (mmap_cache_got_sigbus(f->mmap, f->fd))
return -EIO;
- fsync(f->fd);
+ switch (f->header->state) {
+ case STATE_ONLINE:
+ return 0;
- return 0;
+ case STATE_OFFLINE:
+ f->header->state = STATE_ONLINE;
+ (void) fsync(f->fd);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+bool journal_file_is_offlining(JournalFile *f) {
+ assert(f);
+
+ __sync_synchronize();
+
+ if (f->offline_state == OFFLINE_DONE ||
+ f->offline_state == OFFLINE_JOINED)
+ return false;
+
+ return true;
}
JournalFile* journal_file_close(JournalFile *f) {
@@ -159,7 +345,7 @@ JournalFile* journal_file_close(JournalFile *f) {
sd_event_source_unref(f->post_change_timer);
}
- journal_file_set_offline(f);
+ journal_file_set_offline(f, true);
if (f->mmap && f->fd >= 0)
mmap_cache_close_fd(f->mmap, f->fd);
@@ -203,6 +389,15 @@ JournalFile* journal_file_close(JournalFile *f) {
return NULL;
}
+void journal_file_close_set(Set *s) {
+ JournalFile *f;
+
+ assert(s);
+
+ while ((f = set_steal_first(s)))
+ (void) journal_file_close(f);
+}
+
static int journal_file_init_header(JournalFile *f, JournalFile *template) {
Header h = {};
ssize_t k;
@@ -263,7 +458,7 @@ static int journal_file_refresh_header(JournalFile *f) {
r = journal_file_set_online(f);
/* Sync the online state to disk */
- fsync(f->fd);
+ (void) fsync(f->fd);
return r;
}
@@ -1977,7 +2172,7 @@ static int generic_array_bisect_plus_one(
goto found;
if (r > 0 && idx)
- (*idx) ++;
+ (*idx)++;
return r;
@@ -2710,6 +2905,7 @@ int journal_file_open(
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
+ Set *deferred_closes,
JournalFile *template,
JournalFile **ret) {
@@ -2829,6 +3025,9 @@ int journal_file_open(
f->header = h;
if (!newly_created) {
+ if (deferred_closes)
+ journal_file_close_set(deferred_closes);
+
r = journal_file_verify_header(f);
if (r < 0)
goto fail;
@@ -2898,12 +3097,12 @@ fail:
if (f->fd >= 0 && mmap_cache_got_sigbus(f->mmap, f->fd))
r = -EIO;
- journal_file_close(f);
+ (void) journal_file_close(f);
return r;
}
-int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
+int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred_closes) {
_cleanup_free_ char *p = NULL;
size_t l;
JournalFile *old_file, *new_file = NULL;
@@ -2943,8 +3142,13 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
* we archive them */
old_file->defrag_on_close = true;
- r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
- journal_file_close(old_file);
+ r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, deferred_closes, old_file, &new_file);
+
+ if (deferred_closes &&
+ set_put(deferred_closes, old_file) >= 0)
+ (void) journal_file_set_offline(old_file, false);
+ else
+ (void) journal_file_close(old_file);
*f = new_file;
return r;
@@ -2958,6 +3162,7 @@ int journal_file_open_reliably(
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
+ Set *deferred_closes,
JournalFile *template,
JournalFile **ret) {
@@ -2965,7 +3170,7 @@ int journal_file_open_reliably(
size_t l;
_cleanup_free_ char *p = NULL;
- r = journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret);
+ r = journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
if (!IN_SET(r,
-EBADMSG, /* corrupted */
-ENODATA, /* truncated */
@@ -3006,7 +3211,7 @@ int journal_file_open_reliably(
log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
- return journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret);
+ return journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
}
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 07b9561b8a..9ad6013359 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -63,6 +63,16 @@ typedef enum LocationType {
LOCATION_SEEK
} LocationType;
+typedef enum OfflineState {
+ OFFLINE_JOINED,
+ OFFLINE_SYNCING,
+ OFFLINE_OFFLINING,
+ OFFLINE_CANCEL,
+ OFFLINE_AGAIN_FROM_SYNCING,
+ OFFLINE_AGAIN_FROM_OFFLINING,
+ OFFLINE_DONE
+} OfflineState;
+
typedef struct JournalFile {
int fd;
@@ -105,6 +115,9 @@ typedef struct JournalFile {
OrderedHashmap *chain_cache;
+ pthread_t offline_thread;
+ volatile OfflineState offline_state;
+
#if defined(HAVE_XZ) || defined(HAVE_LZ4)
void *compress_buffer;
size_t compress_buffer_size;
@@ -136,11 +149,14 @@ int journal_file_open(
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
+ Set *deferred_closes,
JournalFile *template,
JournalFile **ret);
-int journal_file_set_offline(JournalFile *f);
+int journal_file_set_offline(JournalFile *f, bool wait);
+bool journal_file_is_offlining(JournalFile *f);
JournalFile* journal_file_close(JournalFile *j);
+void journal_file_close_set(Set *s);
int journal_file_open_reliably(
const char *fname,
@@ -150,6 +166,7 @@ int journal_file_open_reliably(
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
+ Set *deferred_closes,
JournalFile *template,
JournalFile **ret);
@@ -223,7 +240,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
void journal_file_dump(JournalFile *f);
void journal_file_print_header(JournalFile *f);
-int journal_file_rotate(JournalFile **f, bool compress, bool seal);
+int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred_closes);
void journal_file_post_change(JournalFile *f);
int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t);
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index c7d670f4ff..a79846146a 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -50,7 +50,7 @@
*_f = alloca(_fl + 10); \
memcpy(*_f, "CODE_FUNC=", 10); \
memcpy(*_f + 10, _func, _fl); \
- } while(false)
+ } while (false)
/* We open a single fd, and we'll share it with the current process,
* all its threads, and all its subprocesses. This means we need to
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 05e97620ae..f09dc66e03 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -239,13 +239,13 @@ int journal_directory_vacuum(
/* Vacuum corrupted files */
if (q < 1 + 16 + 1 + 16 + 8 + 1) {
- n_active_files ++;
+ n_active_files++;
continue;
}
if (de->d_name[q-1-8-16-1] != '-' ||
de->d_name[q-1-8-16-1-16-1] != '@') {
- n_active_files ++;
+ n_active_files++;
continue;
}
@@ -256,7 +256,7 @@ int journal_directory_vacuum(
}
if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) {
- n_active_files ++;
+ n_active_files++;
continue;
}
@@ -302,7 +302,7 @@ int journal_directory_vacuum(
list[n_list].realtime = realtime;
list[n_list].seqnum_id = seqnum_id;
list[n_list].have_seqnum = have_seqnum;
- n_list ++;
+ n_list++;
p = NULL;
sum += size;
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index b968e89bb8..a1241c9bcf 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -97,20 +97,20 @@ static void flush_progress(void) {
fflush(stdout);
}
-#define debug(_offset, _fmt, ...) do{ \
+#define debug(_offset, _fmt, ...) do { \
flush_progress(); \
log_debug(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \
- } while(0)
+ } while (0)
-#define warning(_offset, _fmt, ...) do{ \
+#define warning(_offset, _fmt, ...) do { \
flush_progress(); \
log_warning(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \
- } while(0)
+ } while (0)
-#define error(_offset, _fmt, ...) do{ \
+#define error(_offset, _fmt, ...) do { \
flush_progress(); \
log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
- } while(0)
+ } while (0)
static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
uint64_t i;
@@ -894,7 +894,7 @@ int journal_file_verify(
goto fail;
}
- n_objects ++;
+ n_objects++;
r = journal_file_object_verify(f, p, o);
if (r < 0) {
@@ -991,7 +991,7 @@ int journal_file_verify(
entry_realtime = le64toh(o->entry.realtime);
entry_realtime_set = true;
- n_entries ++;
+ n_entries++;
break;
case OBJECT_DATA_HASH_TABLE:
@@ -1131,11 +1131,11 @@ int journal_file_verify(
last_epoch = le64toh(o->tag.epoch);
- n_tags ++;
+ n_tags++;
break;
default:
- n_weird ++;
+ n_weird++;
}
if (p == le64toh(f->header->tail_object_offset)) {
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 273242bea6..fd2cb99410 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -225,14 +225,6 @@ static int add_matches_for_device(sd_journal *j, const char *devpath) {
return 0;
}
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(arg_pager_end);
-}
-
static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) {
if (arg_utc)
@@ -278,7 +270,7 @@ static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset
static void help(void) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, arg_pager_end);
printf("%s [OPTIONS...] [MATCHES...]\n\n"
"Query the journal.\n\n"
@@ -1183,7 +1175,7 @@ static int list_boots(sd_journal *j) {
if (count == 0)
return count;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, arg_pager_end);
/* numbers are one less, but we need an extra char for the sign */
w = DECIMAL_STR_WIDTH(count - 1) + 1;
@@ -1363,7 +1355,7 @@ static int add_units(sd_journal *j) {
r = sd_journal_add_disjunction(j);
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -1383,7 +1375,7 @@ static int add_units(sd_journal *j) {
r = sd_journal_add_disjunction(j);
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -1408,7 +1400,7 @@ static int add_units(sd_journal *j) {
r = sd_journal_add_disjunction(j);
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -1428,7 +1420,7 @@ static int add_units(sd_journal *j) {
r = sd_journal_add_disjunction(j);
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -2061,7 +2053,7 @@ int main(int argc, char *argv[]) {
} else {
bool oneline = arg_action == ACTION_LIST_CATALOG;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, arg_pager_end);
if (optind < argc)
r = catalog_list_items(stdout, database, oneline, argv + optind);
@@ -2181,7 +2173,7 @@ int main(int argc, char *argv[]) {
SD_JOURNAL_FOREACH_FIELD(j, field) {
printf("%s\n", field);
- n_shown ++;
+ n_shown++;
}
r = 0;
@@ -2273,7 +2265,7 @@ int main(int argc, char *argv[]) {
else
printf("%.*s\n", (int) size, (const char*) data);
- n_shown ++;
+ n_shown++;
}
r = 0;
@@ -2368,7 +2360,7 @@ int main(int argc, char *argv[]) {
}
if (!arg_follow)
- pager_open_if_enabled();
+ pager_open(arg_no_pager, arg_pager_end);
if (!arg_quiet) {
usec_t start, end;
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index b2eb8a33ef..a433c91c54 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -63,7 +63,7 @@ static int map_simple_field(const char *field, const char **p, struct iovec **io
(*iov)[*n_iov].iov_base = c;
(*iov)[*n_iov].iov_len = l;
- (*n_iov) ++;
+ (*n_iov)++;
*p = e;
c = NULL;
@@ -142,7 +142,7 @@ static int map_string_field_internal(const char *field, const char **p, struct i
(*iov)[*n_iov].iov_base = c;
(*iov)[*n_iov].iov_len = l;
- (*n_iov) ++;
+ (*n_iov)++;
*p = e;
c = NULL;
@@ -200,7 +200,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec **
}
strcpy(t, "=");
- e ++;
+ e++;
r = map_simple_field(c, &e, iov, n_iov_allocated, n_iov);
if (r < 0)
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index eb1ac90e98..f64abdd431 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -201,7 +201,7 @@ static void dev_kmsg_record(Server *s, const char *p, size_t l) {
if (*k != ' ')
break;
- k ++, l --;
+ k++, l--;
e = memchr(k, '\n', l);
if (!e)
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
index 6f6a90fe4e..fce799a6ce 100644
--- a/src/journal/journald-rate-limit.c
+++ b/src/journal/journald-rate-limit.c
@@ -104,7 +104,7 @@ static void journal_rate_limit_group_free(JournalRateLimitGroup *g) {
LIST_REMOVE(lru, g->parent->lru, g);
LIST_REMOVE(bucket, g->parent->buckets[g->hash % BUCKETS_MAX], g);
- g->parent->n_groups --;
+ g->parent->n_groups--;
}
free(g->id);
@@ -168,7 +168,7 @@ static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r,
LIST_PREPEND(lru, r->lru, g);
if (!g->lru_next)
r->lru_tail = g;
- r->n_groups ++;
+ r->n_groups++;
g->parent = r;
return g;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index ee2db8d29f..2939322925 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -251,15 +251,15 @@ static int open_journal(
assert(ret);
if (reliably)
- r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f);
+ r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
else
- r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f);
+ r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
if (r < 0)
return r;
r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
if (r < 0) {
- journal_file_close(f);
+ (void) journal_file_close(f);
return r;
}
@@ -302,7 +302,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
/* Too many open? Then let's close one */
f = ordered_hashmap_steal_first(s->user_journals);
assert(f);
- journal_file_close(f);
+ (void) journal_file_close(f);
}
r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &f);
@@ -313,7 +313,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f);
if (r < 0) {
- journal_file_close(f);
+ (void) journal_file_close(f);
return s->system_journal;
}
@@ -333,7 +333,7 @@ static int do_rotate(
if (!*f)
return -EINVAL;
- r = journal_file_rotate(f, s->compress, seal);
+ r = journal_file_rotate(f, s->compress, seal, s->deferred_closes);
if (r < 0)
if (*f)
log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
@@ -364,6 +364,13 @@ void server_rotate(Server *s) {
/* Old file has been closed and deallocated */
ordered_hashmap_remove(s->user_journals, k);
}
+
+ /* Perform any deferred closes which aren't still offlining. */
+ SET_FOREACH(f, s->deferred_closes, i)
+ if (!journal_file_is_offlining(f)) {
+ (void) set_remove(s->deferred_closes, f);
+ (void) journal_file_close(f);
+ }
}
void server_sync(Server *s) {
@@ -372,13 +379,13 @@ void server_sync(Server *s) {
int r;
if (s->system_journal) {
- r = journal_file_set_offline(s->system_journal);
+ r = journal_file_set_offline(s->system_journal, false);
if (r < 0)
log_warning_errno(r, "Failed to sync system journal, ignoring: %m");
}
ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) {
- r = journal_file_set_offline(f);
+ r = journal_file_set_offline(f, false);
if (r < 0)
log_warning_errno(r, "Failed to sync user journal, ignoring: %m");
}
@@ -1400,7 +1407,7 @@ static int server_parse_proc_cmdline(Server *s) {
}
p = line;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
@@ -1765,6 +1772,10 @@ int server_init(Server *s) {
if (!s->mmap)
return log_oom();
+ s->deferred_closes = set_new(NULL);
+ if (!s->deferred_closes)
+ return log_oom();
+
r = sd_event_default(&s->event);
if (r < 0)
return log_error_errno(r, "Failed to create event loop: %m");
@@ -1918,17 +1929,22 @@ void server_done(Server *s) {
JournalFile *f;
assert(s);
+ if (s->deferred_closes) {
+ journal_file_close_set(s->deferred_closes);
+ set_free(s->deferred_closes);
+ }
+
while (s->stdout_streams)
stdout_stream_free(s->stdout_streams);
if (s->system_journal)
- journal_file_close(s->system_journal);
+ (void) journal_file_close(s->system_journal);
if (s->runtime_journal)
- journal_file_close(s->runtime_journal);
+ (void) journal_file_close(s->runtime_journal);
while ((f = ordered_hashmap_steal_first(s->user_journals)))
- journal_file_close(f);
+ (void) journal_file_close(f);
ordered_hashmap_free(s->user_journals);
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index b9551dda1b..e025a4cf90 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -130,6 +130,8 @@ struct Server {
MMapCache *mmap;
+ Set *deferred_closes;
+
struct udev *udev;
uint64_t *kernel_seqnum;
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 6e8b405b53..59352bcb3f 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -96,7 +96,7 @@ void stdout_stream_free(StdoutStream *s) {
if (s->server) {
assert(s->server->n_stdout_streams > 0);
- s->server->n_stdout_streams --;
+ s->server->n_stdout_streams--;
LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
if (s->in_notify_queue)
@@ -511,7 +511,7 @@ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
stream->server = s;
LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
- s->n_stdout_streams ++;
+ s->n_stdout_streams++;
if (ret)
*ret = stream;
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 9c0ce8ccbf..6bcd9b6ac8 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -107,7 +107,7 @@ MMapCache* mmap_cache_ref(MMapCache *m) {
assert(m);
assert(m->n_ref > 0);
- m->n_ref ++;
+ m->n_ref++;
return m;
}
@@ -361,7 +361,7 @@ MMapCache* mmap_cache_unref(MMapCache *m) {
assert(m->n_ref > 0);
- m->n_ref --;
+ m->n_ref--;
if (m->n_ref == 0)
mmap_cache_free(m);
@@ -598,14 +598,14 @@ int mmap_cache_get(
/* Check whether the current context is the right one already */
r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
if (r != 0) {
- m->n_hit ++;
+ m->n_hit++;
return r;
}
/* Search for a matching mmap */
r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
if (r != 0) {
- m->n_hit ++;
+ m->n_hit++;
return r;
}
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 5a2a28a8d4..3c21d4129e 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <linux/magic.h>
#include <poll.h>
#include <stddef.h>
@@ -1063,7 +1064,7 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
if (r < 0)
return r;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *item = NULL;
unsigned long long ll;
sd_id128_t id;
@@ -1248,7 +1249,7 @@ static int add_any_file(sd_journal *j, const char *path) {
goto fail;
}
- r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
+ r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
if (r < 0) {
log_debug_errno(r, "Failed to open journal file %s: %m", path);
goto fail;
@@ -1258,7 +1259,7 @@ static int add_any_file(sd_journal *j, const char *path) {
r = ordered_hashmap_put(j->files, f->path, f);
if (r < 0) {
- journal_file_close(f);
+ (void) journal_file_close(f);
goto fail;
}
@@ -1266,7 +1267,7 @@ static int add_any_file(sd_journal *j, const char *path) {
check_network(j, f->fd);
- j->current_invalidate_counter ++;
+ j->current_invalidate_counter++;
return 0;
@@ -1343,9 +1344,9 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
j->fields_file_lost = true;
}
- journal_file_close(f);
+ (void) journal_file_close(f);
- j->current_invalidate_counter ++;
+ j->current_invalidate_counter++;
}
static int dirname_is_machine_id(const char *fn) {
@@ -1410,7 +1411,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
}
path = NULL; /* avoid freeing in cleanup */
- j->current_invalidate_counter ++;
+ j->current_invalidate_counter++;
log_debug("Directory %s added.", m->path);
@@ -1495,7 +1496,7 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
goto fail;
}
- j->current_invalidate_counter ++;
+ j->current_invalidate_counter++;
log_debug("Root directory %s added.", m->path);
@@ -1784,7 +1785,7 @@ _public_ void sd_journal_close(sd_journal *j) {
sd_journal_flush_matches(j);
while ((f = ordered_hashmap_steal_first(j->files)))
- journal_file_close(f);
+ (void) journal_file_close(f);
ordered_hashmap_free(j->files);
@@ -1957,7 +1958,7 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
&f->compress_buffer, &f->compress_buffer_size,
field, field_length, '=');
if (r < 0)
- log_debug_errno(r, "Cannot decompress %s object of length %zu at offset "OFSfmt": %m",
+ log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
object_compressed_to_string(compression), l, p);
else if (r > 0) {
@@ -2078,7 +2079,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
if (r < 0)
return r;
- j->current_field ++;
+ j->current_field++;
return 1;
}
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
index da6fcbca4d..898c876450 100644
--- a/src/journal/test-catalog.c
+++ b/src/journal/test-catalog.c
@@ -103,6 +103,8 @@ static void test_catalog_import_one(void) {
assert_se(hashmap_size(h) == 1);
HASHMAP_FOREACH(payload, h, j) {
+ printf("expect: %s\n", expect);
+ printf("actual: %s\n", payload);
assert_se(streq(expect, payload));
}
}
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index 5b2d130cd6..0ef6d36a50 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -105,6 +105,8 @@ static void test_compress_decompress(const char* label, const char* type,
int r;
size = permute(i);
+ if (size == 0)
+ continue;
log_debug("%s %zu %zu", type, i, size);
diff --git a/src/journal/test-journal-enum.c b/src/journal/test-journal-enum.c
index e5e9d9dcb3..354c2c3c00 100644
--- a/src/journal/test-journal-enum.c
+++ b/src/journal/test-journal-enum.c
@@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
printf("%.*s\n", (int) l, (char*) d);
- n ++;
+ n++;
if (n >= 10)
break;
}
diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c
index 7bd9c40366..93dc0e0d81 100644
--- a/src/journal/test-journal-flush.c
+++ b/src/journal/test-journal-flush.c
@@ -38,7 +38,7 @@ int main(int argc, char *argv[]) {
assert_se(mkdtemp(dn));
fn = strappend(dn, "/test.journal");
- r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, &new_journal);
+ r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, NULL, &new_journal);
assert_se(r >= 0);
r = sd_journal_open(&j, 0);
@@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
sd_journal_close(j);
- journal_file_close(new_journal);
+ (void) journal_file_close(new_journal);
unlink(fn);
assert_se(rmdir(dn) == 0);
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index 7f94990888..f887f43f0d 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -52,12 +52,12 @@ noreturn static void log_assert_errno(const char *text, int eno, const char *fil
static JournalFile *test_open(const char *name) {
JournalFile *f;
- assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
+ assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, NULL, &f));
return f;
}
static void test_close(JournalFile *f) {
- journal_file_close (f);
+ (void) journal_file_close (f);
}
static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
@@ -217,7 +217,7 @@ static void test_sequence_numbers(void) {
assert_se(chdir(t) >= 0);
assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
- true, false, NULL, NULL, NULL, &one) == 0);
+ true, false, NULL, NULL, NULL, NULL, &one) == 0);
append_number(one, 1, &seqnum);
printf("seqnum=%"PRIu64"\n", seqnum);
@@ -234,7 +234,7 @@ static void test_sequence_numbers(void) {
memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
- true, false, NULL, NULL, one, &two) == 0);
+ true, false, NULL, NULL, NULL, one, &two) == 0);
assert_se(two->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id));
@@ -265,7 +265,7 @@ static void test_sequence_numbers(void) {
seqnum = 0;
assert_se(journal_file_open("two.journal", O_RDWR, 0,
- true, false, NULL, NULL, NULL, &two) == 0);
+ true, false, NULL, NULL, NULL, NULL, &two) == 0);
assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
index 4e6f8c0f7b..839ea5a9a5 100644
--- a/src/journal/test-journal-stream.c
+++ b/src/journal/test-journal-stream.c
@@ -92,9 +92,9 @@ int main(int argc, char *argv[]) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &one) == 0);
- assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &two) == 0);
- assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &three) == 0);
+ assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &one) == 0);
+ assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &two) == 0);
+ assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &three) == 0);
for (i = 0; i < N_ENTRIES; i++) {
char *p, *q;
@@ -133,9 +133,9 @@ int main(int argc, char *argv[]) {
free(q);
}
- journal_file_close(one);
- journal_file_close(two);
- journal_file_close(three);
+ (void) journal_file_close(one);
+ (void) journal_file_close(two);
+ (void) journal_file_close(three);
assert_se(sd_journal_open_directory(&j, t, 0) >= 0);
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index a26c624f41..6b4643cd25 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -55,12 +55,12 @@ static int raw_verify(const char *fn, const char *verification_key) {
JournalFile *f;
int r;
- r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f);
+ r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f);
if (r < 0)
return r;
r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false);
- journal_file_close(f);
+ (void) journal_file_close(f);
return r;
}
@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
log_info("Generating...");
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
for (n = 0; n < N_ENTRIES; n++) {
struct iovec iovec;
@@ -107,11 +107,11 @@ int main(int argc, char *argv[]) {
free(test);
}
- journal_file_close(f);
+ (void) journal_file_close(f);
log_info("Verifying...");
- assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
/* journal_file_print_header(f); */
journal_file_dump(f);
@@ -123,7 +123,7 @@ int main(int argc, char *argv[]) {
format_timestamp(b, sizeof(b), to),
format_timespan(c, sizeof(c), total > to ? total - to : 0, 0));
- journal_file_close(f);
+ (void) journal_file_close(f);
if (verification_key) {
log_info("Toggling bits...");
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index 0334b1cd1a..ea685af782 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -42,7 +42,7 @@ static void test_non_empty(void) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f) == 0);
dual_timestamp_get(&ts);
@@ -104,10 +104,10 @@ static void test_non_empty(void) {
assert_se(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0);
- journal_file_rotate(&f, true, true);
- journal_file_rotate(&f, true, true);
+ journal_file_rotate(&f, true, true, NULL);
+ journal_file_rotate(&f, true, true, NULL);
- journal_file_close(f);
+ (void) journal_file_close(f);
log_info("Done...");
@@ -131,13 +131,13 @@ static void test_empty(void) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, &f1) == 0);
+ assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, NULL, &f1) == 0);
- assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f2) == 0);
+ assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &f2) == 0);
- assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, &f3) == 0);
+ assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, NULL, &f3) == 0);
- assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f4) == 0);
+ assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f4) == 0);
journal_file_print_header(f1);
puts("");
@@ -158,10 +158,10 @@ static void test_empty(void) {
assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
- journal_file_close(f1);
- journal_file_close(f2);
- journal_file_close(f3);
- journal_file_close(f4);
+ (void) journal_file_close(f1);
+ (void) journal_file_close(f2);
+ (void) journal_file_close(f3);
+ (void) journal_file_close(f4);
}
int main(int argc, char *argv[]) {
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 1d9ec7be82..4f7d4d8bf2 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -43,7 +43,7 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
if (r < 0)
return r;
- unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
+ unaligned_write_be16(&duid->type, DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
*len = sizeof(duid->type) + sizeof(duid->en);
diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h
index 93f06f5938..e6486b78f8 100644
--- a/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libsystemd-network/dhcp-identifier.h
@@ -25,13 +25,23 @@
#include "sparse-endian.h"
#include "unaligned.h"
+typedef enum DUIDType {
+ DUID_TYPE_RAW = 0,
+ DUID_TYPE_LLT = 1,
+ DUID_TYPE_EN = 2,
+ DUID_TYPE_LL = 3,
+ DUID_TYPE_UUID = 4,
+ _DUID_TYPE_MAX,
+ _DUID_TYPE_INVALID = -1,
+} DUIDType;
+
/* RFC 3315 section 9.1:
* A DUID can be no more than 128 octets long (not including the type code).
*/
#define MAX_DUID_LEN 128
struct duid {
- uint16_t type;
+ be16_t type;
union {
struct {
/* DHCP6_DUID_LLT */
@@ -61,3 +71,34 @@ struct duid {
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
+
+static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+ struct duid d;
+
+ assert(duid_len > 0);
+
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (duid_len <= sizeof(d.llt))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_EN:
+ if (duid_len != sizeof(d.en))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_LL:
+ if (duid_len <= sizeof(d.ll))
+ return -EINVAL;
+ break;
+ case DUID_TYPE_UUID:
+ if (duid_len != sizeof(d.uuid))
+ return -EINVAL;
+ break;
+ default:
+ if (duid_len > sizeof(d.raw))
+ return -EINVAL;
+ /* accept unknown type in order to be forward compatible */
+ break;
+ }
+ return 0;
+}
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index a3b842cda3..4662b0d847 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -42,10 +42,10 @@ int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload,
uint8_t code, size_t optlen, const void *optval);
-typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
+typedef int (*dhcp_option_callback_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, char **error_message);
+int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_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,
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index b0ea7576bf..c105196334 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -34,7 +34,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
if (code != SD_DHCP_OPTION_END)
/* always make sure there is space for an END option */
- size --;
+ size--;
switch (code) {
@@ -135,7 +135,7 @@ 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, char **error_message, dhcp_option_cb_t cb,
+ uint8_t *message_type, char **error_message, dhcp_option_callback_t cb,
void *userdata) {
uint8_t code, len;
const uint8_t *option;
@@ -221,7 +221,7 @@ 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, char **_error_message) {
+int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **_error_message) {
_cleanup_free_ char *error_message = NULL;
uint8_t overload = 0;
uint8_t message_type = 0;
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 8d75d49691..8be774061d 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -66,7 +66,7 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) {
/* wrap around in one's complement */
sum++;
- buf_64 ++;
+ buf_64++;
}
if (len % sizeof(uint64_t)) {
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index bf123f1439..adb557167a 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -18,8 +20,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "sd-dhcp-server.h"
#include "sd-event.h"
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index ee4bdfb07f..2487c470ab 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -62,13 +62,6 @@ enum {
#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC
#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC
-enum {
- DHCP6_DUID_LLT = 1,
- DHCP6_DUID_EN = 2,
- DHCP6_DUID_LL = 3,
- DHCP6_DUID_UUID = 4,
-};
-
enum DHCP6State {
DHCP6_STATE_STOPPED = 0,
DHCP6_STATE_INFORMATION_REQUEST = 1,
diff --git a/src/libsystemd-network/lldp-internal.c b/src/libsystemd-network/lldp-internal.c
deleted file mode 100644
index c8740ce5f0..0000000000
--- a/src/libsystemd-network/lldp-internal.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/***
- 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/>.
-***/
-
-#include "sd-lldp.h"
-
-#include "alloc-util.h"
-#include "lldp-internal.h"
-
-/* We store maximum 1K chassis entries */
-#define LLDP_MIB_MAX_CHASSIS 1024
-
-/* Maximum Ports can be attached to any chassis */
-#define LLDP_MIB_MAX_PORT_PER_CHASSIS 32
-
-/* 10.5.5.2.2 mibUpdateObjects ()
- * The mibUpdateObjects () procedure updates the MIB objects corresponding to
- * the TLVs contained in the received LLDPDU for the LLDP remote system
- * indicated by the LLDP remote systems update process defined in 10.3.5 */
-
-int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv) {
- lldp_neighbour_port *p;
- uint16_t length, ttl;
- uint8_t *data;
- uint8_t type;
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(tlv, -EINVAL);
-
- r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length);
- if (r < 0)
- return r;
-
- /* Update the packet if we already have */
- LIST_FOREACH(port, p, c->ports) {
-
- if ((p->type == type && p->length == length && !memcmp(p->data, data, p->length))) {
-
- r = sd_lldp_packet_read_ttl(tlv, &ttl);
- if (r < 0)
- return r;
-
- p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic());
-
- sd_lldp_packet_unref(p->packet);
- p->packet = tlv;
-
- prioq_reshuffle(p->c->by_expiry, p, &p->prioq_idx);
-
- return 0;
- }
- }
-
- return -1;
-}
-
-int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv) {
- lldp_neighbour_port *p, *q;
- uint8_t *data;
- uint16_t length;
- uint8_t type;
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(tlv, -EINVAL);
-
- r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length);
- if (r < 0)
- return r;
-
- LIST_FOREACH_SAFE(port, p, q, c->ports) {
-
- /* Find the port */
- if (p->type == type && p->length == length && !memcmp(p->data, data, p->length)) {
- lldp_neighbour_port_remove_and_free(p);
- break;
- }
- }
-
- return 0;
-}
-
-int lldp_mib_add_objects(Prioq *by_expiry,
- Hashmap *neighbour_mib,
- tlv_packet *tlv) {
- _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL;
- _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL;
- lldp_chassis_id chassis_id;
- bool new_chassis = false;
- uint8_t subtype, *data;
- uint16_t ttl, length;
- int r;
-
- assert_return(by_expiry, -EINVAL);
- assert_return(neighbour_mib, -EINVAL);
- assert_return(tlv, -EINVAL);
-
- r = sd_lldp_packet_read_chassis_id(tlv, &subtype, &data, &length);
- if (r < 0)
- goto drop;
-
- r = sd_lldp_packet_read_ttl(tlv, &ttl);
- if (r < 0)
- goto drop;
-
- /* Make hash key */
- chassis_id.type = subtype;
- chassis_id.length = length;
- chassis_id.data = data;
-
- /* Try to find the Chassis */
- c = hashmap_get(neighbour_mib, &chassis_id);
- if (!c) {
-
- /* Don't create chassis if ttl 0 is received . Silently drop it */
- if (ttl == 0) {
- log_lldp("TTL value 0 received. Skiping Chassis creation.");
- goto drop;
- }
-
- /* Admission Control: Can we store this packet ? */
- if (hashmap_size(neighbour_mib) >= LLDP_MIB_MAX_CHASSIS) {
-
- log_lldp("Exceeding number of chassie: %d. Dropping ...",
- hashmap_size(neighbour_mib));
- goto drop;
- }
-
- r = lldp_chassis_new(tlv, by_expiry, neighbour_mib, &c);
- if (r < 0)
- goto drop;
-
- new_chassis = true;
-
- r = hashmap_put(neighbour_mib, &c->chassis_id, c);
- if (r < 0)
- goto drop;
-
- } else {
-
- /* When the TTL field is set to zero, the receiving LLDP agent is notified all
- * system information associated with the LLDP agent/port is to be deleted */
- if (ttl == 0) {
- log_lldp("TTL value 0 received . Deleting associated Port ...");
-
- lldp_mib_remove_objects(c, tlv);
-
- c = NULL;
- goto drop;
- }
-
- /* if we already have this port just update it */
- r = lldp_mib_update_objects(c, tlv);
- if (r >= 0) {
- c = NULL;
- return r;
- }
-
- /* Admission Control: Can this port attached to the existing chassis ? */
- if (c->n_ref >= LLDP_MIB_MAX_PORT_PER_CHASSIS) {
- log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", c->n_ref);
-
- c = NULL;
- goto drop;
- }
- }
-
- /* This is a new port */
- r = lldp_neighbour_port_new(c, tlv, &p);
- if (r < 0)
- goto drop;
-
- r = prioq_put(c->by_expiry, p, &p->prioq_idx);
- if (r < 0)
- goto drop;
-
- /* Attach new port to chassis */
- LIST_PREPEND(port, c->ports, p);
- c->n_ref ++;
-
- p = NULL;
- c = NULL;
-
- return 0;
-
- drop:
- sd_lldp_packet_unref(tlv);
-
- if (new_chassis)
- hashmap_remove(neighbour_mib, &c->chassis_id);
-
- return r;
-}
-
-void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p) {
- lldp_chassis *c;
-
- assert(p);
- assert(p->c);
-
- c = p->c;
-
- prioq_remove(c->by_expiry, p, &p->prioq_idx);
-
- LIST_REMOVE(port, c->ports, p);
- lldp_neighbour_port_free(p);
-
- /* Drop the Chassis if no port is attached */
- c->n_ref --;
- if (c->n_ref <= 1) {
- hashmap_remove(c->neighbour_mib, &c->chassis_id);
- lldp_chassis_free(c);
- }
-}
-
-void lldp_neighbour_port_free(lldp_neighbour_port *p) {
-
- if(!p)
- return;
-
- sd_lldp_packet_unref(p->packet);
-
- free(p->data);
- free(p);
-}
-
-int lldp_neighbour_port_new(lldp_chassis *c,
- tlv_packet *tlv,
- lldp_neighbour_port **ret) {
- _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL;
- uint16_t length, ttl;
- uint8_t *data;
- uint8_t type;
- int r;
-
- assert(tlv);
-
- r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length);
- if (r < 0)
- return r;
-
- r = sd_lldp_packet_read_ttl(tlv, &ttl);
- if (r < 0)
- return r;
-
- p = new0(lldp_neighbour_port, 1);
- if (!p)
- return -ENOMEM;
-
- p->c = c;
- p->type = type;
- p->length = length;
- p->packet = tlv;
- p->prioq_idx = PRIOQ_IDX_NULL;
- p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic());
-
- p->data = memdup(data, length);
- if (!p->data)
- return -ENOMEM;
-
- *ret = p;
- p = NULL;
-
- return 0;
-}
-
-void lldp_chassis_free(lldp_chassis *c) {
-
- if (!c)
- return;
-
- if (c->n_ref > 1)
- return;
-
- free(c->chassis_id.data);
- free(c);
-}
-
-int lldp_chassis_new(tlv_packet *tlv,
- Prioq *by_expiry,
- Hashmap *neighbour_mib,
- lldp_chassis **ret) {
- _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL;
- uint16_t length;
- uint8_t *data;
- uint8_t type;
- int r;
-
- assert(tlv);
-
- r = sd_lldp_packet_read_chassis_id(tlv, &type, &data, &length);
- if (r < 0)
- return r;
-
- c = new0(lldp_chassis, 1);
- if (!c)
- return -ENOMEM;
-
- c->n_ref = 1;
- c->chassis_id.type = type;
- c->chassis_id.length = length;
-
- c->chassis_id.data = memdup(data, length);
- if (!c->chassis_id.data)
- return -ENOMEM;
-
- LIST_HEAD_INIT(c->ports);
-
- c->by_expiry = by_expiry;
- c->neighbour_mib = neighbour_mib;
-
- *ret = c;
- c = NULL;
-
- return 0;
-}
-
-int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(sd_lldp_packet_unrefp) tlv_packet *packet = NULL;
- tlv_packet *p;
- uint16_t length;
- int r;
-
- assert(fd);
- assert(userdata);
-
- r = tlv_packet_new(&packet);
- if (r < 0)
- return r;
-
- length = read(fd, &packet->pdu, sizeof(packet->pdu));
-
- /* Silently drop the packet */
- if ((size_t) length > ETHER_MAX_LEN)
- return 0;
-
- packet->userdata = userdata;
-
- p = packet;
- packet = NULL;
-
- return lldp_handle_packet(p, (uint16_t) length);
-}
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
index 15b4a11b15..7592bc4305 100644
--- a/src/libsystemd-network/lldp-internal.h
+++ b/src/libsystemd-network/lldp-internal.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -18,74 +20,34 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "sd-event.h"
+#include "sd-lldp.h"
-#include "list.h"
-#include "lldp-tlv.h"
+#include "hashmap.h"
#include "log.h"
#include "prioq.h"
-typedef struct lldp_neighbour_port lldp_neighbour_port;
-typedef struct lldp_chassis lldp_chassis;
-typedef struct lldp_chassis_id lldp_chassis_id;
-typedef struct lldp_agent_statistics lldp_agent_statistics;
+struct sd_lldp {
+ int ifindex;
+ int fd;
-struct lldp_neighbour_port {
- uint8_t type;
- uint8_t *data;
+ sd_event *event;
+ int64_t event_priority;
+ sd_event_source *io_event_source;
+ sd_event_source *timer_event_source;
- uint16_t length;
- usec_t until;
+ Prioq *neighbor_by_expiry;
+ Hashmap *neighbor_by_id;
- unsigned prioq_idx;
+ uint64_t neighbors_max;
- lldp_chassis *c;
- tlv_packet *packet;
+ sd_lldp_callback_t callback;
+ void *userdata;
- LIST_FIELDS(lldp_neighbour_port, port);
-};
+ uint16_t capability_mask;
-int lldp_neighbour_port_new(lldp_chassis *c, tlv_packet *tlv, lldp_neighbour_port **ret);
-void lldp_neighbour_port_free(lldp_neighbour_port *p);
-void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_neighbour_port *, lldp_neighbour_port_free);
-#define _cleanup_lldp_neighbour_port_free_ _cleanup_(lldp_neighbour_port_freep)
-
-struct lldp_chassis_id {
- uint8_t type;
- uint16_t length;
-
- uint8_t *data;
+ struct ether_addr filter_address;
};
-struct lldp_chassis {
- unsigned n_ref;
-
- lldp_chassis_id chassis_id;
-
- Prioq *by_expiry;
- Hashmap *neighbour_mib;
-
- LIST_HEAD(lldp_neighbour_port, ports);
-};
-
-int lldp_chassis_new(tlv_packet *tlv,
- Prioq *by_expiry,
- Hashmap *neighbour_mib,
- lldp_chassis **ret);
-
-void lldp_chassis_free(lldp_chassis *c);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_chassis *, lldp_chassis_free);
-#define _cleanup_lldp_chassis_free_ _cleanup_(lldp_chassis_freep)
-
-int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv);
-int lldp_mib_add_objects(Prioq *by_expiry, Hashmap *neighbour_mib, tlv_packet *tlv);
-int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv);
-
-int lldp_handle_packet(tlv_packet *m, uint16_t length);
-int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata);
-#define log_lldp(fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
+#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
+#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__)
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
new file mode 100644
index 0000000000..6a716430e3
--- /dev/null
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -0,0 +1,794 @@
+/***
+ 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 "escape.h"
+#include "ether-addr-util.h"
+#include "hexdecoct.h"
+#include "in-addr-util.h"
+#include "lldp-internal.h"
+#include "lldp-neighbor.h"
+#include "unaligned.h"
+
+static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
+ const LLDPNeighborID *id = p;
+
+ siphash24_compress(id->chassis_id, id->chassis_id_size, state);
+ siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state);
+ siphash24_compress(id->port_id, id->port_id_size, state);
+ siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state);
+}
+
+static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
+ const LLDPNeighborID *x = a, *y = b;
+ int r;
+
+ r = memcmp(x->chassis_id, y->chassis_id, MIN(x->chassis_id_size, y->chassis_id_size));
+ if (r != 0)
+ return r;
+
+ if (x->chassis_id_size < y->chassis_id_size)
+ return -1;
+
+ if (x->chassis_id_size > y->chassis_id_size)
+ return 1;
+
+ r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size));
+ if (r != 0)
+ return r;
+
+ if (x->port_id_size < y->port_id_size)
+ return -1;
+ if (x->port_id_size > y->port_id_size)
+ return 1;
+
+ return 0;
+}
+
+const struct hash_ops lldp_neighbor_id_hash_ops = {
+ .hash = lldp_neighbor_id_hash_func,
+ .compare = lldp_neighbor_id_compare_func
+};
+
+int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
+ const sd_lldp_neighbor *x = a, *y = b;
+
+ if (x->until < y->until)
+ return -1;
+
+ if (x->until > y->until)
+ return 1;
+
+ return 0;
+}
+
+_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) {
+ if (!n)
+ return NULL;
+
+ assert(n->n_ref > 0 || n->lldp);
+ n->n_ref++;
+
+ return n;
+}
+
+static void lldp_neighbor_free(sd_lldp_neighbor *n) {
+ assert(n);
+
+ free(n->id.port_id);
+ free(n->id.chassis_id);
+ free(n->port_description);
+ free(n->system_name);
+ free(n->system_description);
+ free(n->chassis_id_as_string);
+ free(n->port_id_as_string);
+ free(n);
+}
+
+_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) {
+
+ /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from
+ * the sd_lldp object. */
+
+ if (!n)
+ return NULL;
+
+ assert(n->n_ref > 0);
+ n->n_ref--;
+
+ if (n->n_ref <= 0 && !n->lldp)
+ lldp_neighbor_free(n);
+
+ return NULL;
+}
+
+sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) {
+
+ /* Removes the neighbor object from the LLDP object, and frees it if it also has no other reference. */
+
+ if (!n)
+ return NULL;
+
+ if (!n->lldp)
+ return NULL;
+
+ assert_se(hashmap_remove(n->lldp->neighbor_by_id, &n->id) == n);
+ assert_se(prioq_remove(n->lldp->neighbor_by_expiry, n, &n->prioq_idx) >= 0);
+
+ n->lldp = NULL;
+
+ if (n->n_ref <= 0)
+ lldp_neighbor_free(n);
+
+ return NULL;
+}
+
+sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) {
+ sd_lldp_neighbor *n;
+
+ n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size);
+ if (!n)
+ return NULL;
+
+ n->raw_size = raw_size;
+ n->n_ref = 1;
+
+ return n;
+}
+
+static int parse_string(char **s, const void *q, size_t n) {
+ const char *p = q;
+ char *k;
+
+ assert(s);
+ assert(p || n == 0);
+
+ if (*s) {
+ log_lldp("Found duplicate string, ignoring field.");
+ return 0;
+ }
+
+ /* Strip trailing NULs, just to be nice */
+ while (n > 0 && p[n-1] == 0)
+ n--;
+
+ if (n <= 0) /* Ignore empty strings */
+ return 0;
+
+ /* Look for inner NULs */
+ if (memchr(p, 0, n)) {
+ log_lldp("Found inner NUL in string, ignoring field.");
+ return 0;
+ }
+
+ /* Let's escape weird chars, for security reasons */
+ k = cescape_length(p, n);
+ if (!k)
+ return -ENOMEM;
+
+ free(*s);
+ *s = k;
+
+ return 1;
+}
+
+int lldp_neighbor_parse(sd_lldp_neighbor *n) {
+ struct ether_header h;
+ const uint8_t *p;
+ size_t left;
+ int r;
+
+ assert(n);
+
+ if (n->raw_size < sizeof(struct ether_header)) {
+ log_lldp("Recieved truncated packet, ignoring.");
+ return -EBADMSG;
+ }
+
+ memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h));
+
+ if (h.ether_type != htobe16(ETHERTYPE_LLDP)) {
+ log_lldp("Received packet with wrong type, ignoring.");
+ return -EBADMSG;
+ }
+
+ if (h.ether_dhost[0] != 0x01 ||
+ h.ether_dhost[1] != 0x80 ||
+ h.ether_dhost[2] != 0xc2 ||
+ h.ether_dhost[3] != 0x00 ||
+ h.ether_dhost[4] != 0x00 ||
+ !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) {
+ log_lldp("Received packet with wrong destination address, ignoring.");
+ return -EBADMSG;
+ }
+
+ memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr));
+ memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr));
+
+ p = (const uint8_t*) LLDP_NEIGHBOR_RAW(n) + sizeof(struct ether_header);
+ left = n->raw_size - sizeof(struct ether_header);
+
+ for (;;) {
+ uint8_t type;
+ uint16_t length;
+
+ if (left < 2) {
+ log_lldp("TLV lacks header, ignoring.");
+ return -EBADMSG;
+ }
+
+ type = p[0] >> 1;
+ length = p[1] + (((uint16_t) (p[0] & 1)) << 8);
+ p += 2, left -= 2;
+
+ if (left < length) {
+ log_lldp("TLV truncated, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ switch (type) {
+
+ case SD_LLDP_TYPE_END:
+ if (length != 0) {
+ log_lldp("End marker TLV not zero-sized, ignoring datagram.");
+ return -EBADMSG;
+ }
+ if (left != 0) {
+ log_lldp("Trailing garbage in datagram, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ goto end_marker;
+
+ case SD_LLDP_TYPE_CHASSIS_ID:
+ if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */
+ log_lldp("Chassis ID field size out of range, ignoring datagram.");
+ return -EBADMSG;
+ }
+ if (n->id.chassis_id) {
+ log_lldp("Duplicate chassis ID field, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ n->id.chassis_id = memdup(p, length);
+ if (!n->id.chassis_id)
+ return -ENOMEM;
+
+ n->id.chassis_id_size = length;
+ break;
+
+ case SD_LLDP_TYPE_PORT_ID:
+ if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */
+ log_lldp("Port ID field size out of range, ignoring datagram.");
+ return -EBADMSG;
+ }
+ if (n->id.port_id) {
+ log_lldp("Duplicate port ID field, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ n->id.port_id = memdup(p, length);
+ if (!n->id.port_id)
+ return -ENOMEM;
+
+ n->id.port_id_size = length;
+ break;
+
+ case SD_LLDP_TYPE_TTL:
+ if (length != 2) {
+ log_lldp("TTL field has wrong size, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ if (n->has_ttl) {
+ log_lldp("Duplicate TTL field, ignoring datagram.");
+ return -EBADMSG;
+ }
+
+ n->ttl = unaligned_read_be16(p);
+ n->has_ttl = true;
+ break;
+
+ case SD_LLDP_TYPE_PORT_DESCRIPTION:
+ r = parse_string(&n->port_description, p, length);
+ if (r < 0)
+ return r;
+ break;
+
+ case SD_LLDP_TYPE_SYSTEM_NAME:
+ r = parse_string(&n->system_name, p, length);
+ if (r < 0)
+ return r;
+ break;
+
+ case SD_LLDP_TYPE_SYSTEM_DESCRIPTION:
+ r = parse_string(&n->system_description, p, length);
+ if (r < 0)
+ return r;
+ break;
+
+ case SD_LLDP_TYPE_SYSTEM_CAPABILITIES:
+ if (length != 4)
+ log_lldp("System capabilities field has wrong size, ignoring.");
+ else {
+ n->system_capabilities = unaligned_read_be16(p);
+ n->enabled_capabilities = unaligned_read_be16(p + 2);
+ n->has_capabilities = true;
+ }
+
+ break;
+
+ case SD_LLDP_TYPE_PRIVATE:
+ if (length < 4)
+ log_lldp("Found private TLV that is too short, ignoring.");
+
+ break;
+ }
+
+
+ p += length, left -= length;
+ }
+
+end_marker:
+ if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) {
+ log_lldp("One or more mandatory TLV missing in datagram. Ignoring.");
+ return -EBADMSG;
+
+ }
+
+ n->rindex = sizeof(struct ether_header);
+
+ return 0;
+}
+
+void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) {
+ assert(n);
+
+ if (n->ttl > 0)
+ n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC);
+ else
+ n->until = 0;
+
+ if (n->lldp)
+ prioq_reshuffle(n->lldp->neighbor_by_expiry, n, &n->prioq_idx);
+}
+
+bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) {
+ if (a == b)
+ return true;
+
+ if (!a || !b)
+ return false;
+
+ if (a->raw_size != b->raw_size)
+ return false;
+
+ return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0;
+}
+
+_public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) {
+ assert_return(n, -EINVAL);
+ assert_return(address, -EINVAL);
+
+ *address = n->source_address;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) {
+ assert_return(n, -EINVAL);
+ assert_return(address, -EINVAL);
+
+ *address = n->destination_address;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(size, -EINVAL);
+
+ *ret = LLDP_NEIGHBOR_RAW(n);
+ *size = n->raw_size;
+
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) {
+ assert_return(n, -EINVAL);
+ assert_return(type, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(size, -EINVAL);
+
+ assert(n->id.chassis_id_size > 0);
+
+ *type = *(uint8_t*) n->id.chassis_id;
+ *ret = (uint8_t*) n->id.chassis_id + 1;
+ *size = n->id.chassis_id_size - 1;
+
+ return 0;
+}
+
+static int format_mac_address(const void *data, size_t sz, char **ret) {
+ struct ether_addr a;
+ char *k;
+
+ assert(data || sz <= 0);
+
+ if (sz != 7)
+ return 0;
+
+ memcpy(&a, (uint8_t*) data + 1, sizeof(a));
+
+ k = new(char, ETHER_ADDR_TO_STRING_MAX);
+ if (!k)
+ return -ENOMEM;
+
+ *ret = ether_addr_to_string(&a, k);
+ return 1;
+}
+
+static int format_network_address(const void *data, size_t sz, char **ret) {
+ union in_addr_union a;
+ int family, r;
+
+ if (sz == 6 && ((uint8_t*) data)[1] == 1) {
+ memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in));
+ family = AF_INET;
+ } else if (sz == 18 && ((uint8_t*) data)[1] == 2) {
+ memcpy(&a.in6, (uint8_t*) data + 2, sizeof(a.in6));
+ family = AF_INET6;
+ } else
+ return 0;
+
+ r = in_addr_to_string(family, &a, ret);
+ if (r < 0)
+ return r;
+ return 1;
+}
+
+_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) {
+ char *k;
+ int r;
+
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (n->chassis_id_as_string) {
+ *ret = n->chassis_id_as_string;
+ return 0;
+ }
+
+ assert(n->id.chassis_id_size > 0);
+
+ switch (*(uint8_t*) n->id.chassis_id) {
+
+ case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
+ case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
+ case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
+ case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
+ case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
+ k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1);
+ if (!k)
+ return -ENOMEM;
+
+ goto done;
+
+ case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
+ r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ goto done;
+
+ break;
+
+ case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
+ r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ goto done;
+
+ break;
+ }
+
+ /* Generic fallback */
+ k = hexmem(n->id.chassis_id, n->id.chassis_id_size);
+ if (!k)
+ return -ENOMEM;
+
+done:
+ *ret = n->chassis_id_as_string = k;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) {
+ assert_return(n, -EINVAL);
+ assert_return(type, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(size, -EINVAL);
+
+ assert(n->id.port_id_size > 0);
+
+ *type = *(uint8_t*) n->id.port_id;
+ *ret = (uint8_t*) n->id.port_id + 1;
+ *size = n->id.port_id_size - 1;
+
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) {
+ char *k;
+ int r;
+
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (n->port_id_as_string) {
+ *ret = n->port_id_as_string;
+ return 0;
+ }
+
+ assert(n->id.port_id_size > 0);
+
+ switch (*(uint8_t*) n->id.port_id) {
+
+ case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
+ case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT:
+ case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME:
+ case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
+ k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1);
+ if (!k)
+ return -ENOMEM;
+
+ goto done;
+
+ case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS:
+ r = format_mac_address(n->id.port_id, n->id.port_id_size, &k);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ goto done;
+
+ break;
+
+ case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
+ r = format_network_address(n->id.port_id, n->id.port_id_size, &k);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ goto done;
+
+ break;
+ }
+
+ /* Generic fallback */
+ k = hexmem(n->id.port_id, n->id.port_id_size);
+ if (!k)
+ return -ENOMEM;
+
+done:
+ *ret = n->port_id_as_string = k;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ *ret = n->ttl;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (!n->system_name)
+ return -ENODATA;
+
+ *ret = n->system_name;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (!n->system_description)
+ return -ENODATA;
+
+ *ret = n->system_description;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (!n->port_description)
+ return -ENODATA;
+
+ *ret = n->port_description;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (!n->has_capabilities)
+ return -ENODATA;
+
+ *ret = n->system_capabilities;
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) {
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ if (!n->has_capabilities)
+ return -ENODATA;
+
+ *ret = n->enabled_capabilities;
+ return 0;
+}
+
+int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+ int r;
+
+ assert_return(ret, -EINVAL);
+ assert_return(raw || raw_size <= 0, -EINVAL);
+
+ n = lldp_neighbor_new(raw_size);
+ if (!n)
+ return -ENOMEM;
+
+ memcpy(LLDP_NEIGHBOR_RAW(n), raw, raw_size);
+ r = lldp_neighbor_parse(n);
+ if (r < 0)
+ return r;
+
+ *ret = n;
+ n = 0;
+
+ return r;
+}
+
+_public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) {
+ assert_return(n, -EINVAL);
+
+ assert(n->raw_size >= sizeof(struct ether_header));
+ n->rindex = sizeof(struct ether_header);
+
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
+ size_t length;
+
+ assert_return(n, -EINVAL);
+
+ if (n->rindex == n->raw_size) /* EOF */
+ return -ESPIPE;
+
+ if (n->rindex + 2 > n->raw_size) /* Truncated message */
+ return -EBADMSG;
+
+ length = LLDP_NEIGHBOR_LENGTH(n);
+ if (n->rindex + 2 + length > n->raw_size)
+ return -EBADMSG;
+
+ n->rindex += 2 + length;
+ return n->rindex < n->raw_size;
+}
+
+_public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) {
+ assert_return(n, -EINVAL);
+ assert_return(type, -EINVAL);
+
+ if (n->rindex == n->raw_size) /* EOF */
+ return -ESPIPE;
+
+ if (n->rindex + 2 > n->raw_size)
+ return -EBADMSG;
+
+ *type = LLDP_NEIGHBOR_TYPE(n);
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) {
+ uint8_t k;
+ int r;
+
+ assert_return(n, -EINVAL);
+
+ r = sd_lldp_neighbor_tlv_get_type(n, &k);
+ if (r < 0)
+ return r;
+
+ return type == k;
+}
+
+_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype) {
+ const uint8_t *d;
+ size_t length;
+ int r;
+
+ assert_return(n, -EINVAL);
+ assert_return(oui, -EINVAL);
+ assert_return(subtype, -EINVAL);
+
+ r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENXIO;
+
+ length = LLDP_NEIGHBOR_LENGTH(n);
+ if (length < 4)
+ return -EBADMSG;
+
+ if (n->rindex + 2 + length > n->raw_size)
+ return -EBADMSG;
+
+ d = LLDP_NEIGHBOR_DATA(n);
+ memcpy(oui, d, 3);
+ *subtype = d[3];
+
+ return 0;
+}
+
+_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype) {
+ uint8_t k[3], st;
+ int r;
+
+ r = sd_lldp_neighbor_tlv_get_oui(n, k, &st);
+ if (r == -ENXIO)
+ return 0;
+ if (r < 0)
+ return r;
+
+ return memcmp(k, oui, 3) == 0 && st == subtype;
+}
+
+_public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) {
+ size_t length;
+
+ assert_return(n, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(size, -EINVAL);
+
+ /* Note that this returns the full TLV, including the TLV header */
+
+ if (n->rindex + 2 > n->raw_size)
+ return -EBADMSG;
+
+ length = LLDP_NEIGHBOR_LENGTH(n);
+
+ if (n->rindex + 2 + length > n->raw_size)
+ return -EBADMSG;
+
+ *ret = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex;
+ *size = length + 2;
+
+ return 0;
+}
diff --git a/src/libsystemd-network/lldp-neighbor.h b/src/libsystemd-network/lldp-neighbor.h
new file mode 100644
index 0000000000..f203bfa604
--- /dev/null
+++ b/src/libsystemd-network/lldp-neighbor.h
@@ -0,0 +1,106 @@
+#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 <inttypes.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "sd-lldp.h"
+
+#include "hash-funcs.h"
+#include "lldp-internal.h"
+#include "time-util.h"
+
+typedef struct LLDPNeighborID {
+ /* The spec calls this an "MSAP identifier" */
+ void *chassis_id;
+ size_t chassis_id_size;
+
+ void *port_id;
+ size_t port_id_size;
+} LLDPNeighborID;
+
+struct sd_lldp_neighbor {
+ /* Neighbor objects stay around as long as they are linked into an "sd_lldp" object or n_ref > 0. */
+ sd_lldp *lldp;
+ unsigned n_ref;
+
+ usec_t until;
+ unsigned prioq_idx;
+
+ struct ether_addr source_address;
+ struct ether_addr destination_address;
+
+ LLDPNeighborID id;
+
+ /* The raw packet size. The data is appended to the object, accessible via LLDP_NEIGHBOR_RAW() */
+ size_t raw_size;
+
+ /* The current read index for the iterative TLV interface */
+ size_t rindex;
+
+ /* And a couple of fields parsed out. */
+ bool has_ttl:1;
+ bool has_capabilities:1;
+ bool has_port_vlan_id:1;
+
+ uint16_t ttl;
+
+ uint16_t system_capabilities;
+ uint16_t enabled_capabilities;
+
+ char *port_description;
+ char *system_name;
+ char *system_description;
+
+ uint16_t port_vlan_id;
+
+ char *chassis_id_as_string;
+ char *port_id_as_string;
+};
+
+static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) {
+ return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor));
+}
+
+static inline uint8_t LLDP_NEIGHBOR_TYPE(const sd_lldp_neighbor *n) {
+ return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1;
+}
+
+static inline size_t LLDP_NEIGHBOR_LENGTH(const sd_lldp_neighbor *n) {
+ uint8_t *p;
+
+ p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex;
+ return p[1] + (((size_t) (p[0] & 1)) << 8);
+}
+
+static inline void* LLDP_NEIGHBOR_DATA(const sd_lldp_neighbor *n) {
+ return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2;
+}
+
+extern const struct hash_ops lldp_neighbor_id_hash_ops;
+int lldp_neighbor_prioq_compare_func(const void *a, const void *b);
+
+sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n);
+sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size);
+int lldp_neighbor_parse(sd_lldp_neighbor *n);
+void lldp_neighbor_start_ttl(sd_lldp_neighbor *n);
+bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b);
diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c
index 42058c4449..f031760351 100644
--- a/src/libsystemd-network/lldp-network.c
+++ b/src/libsystemd-network/lldp-network.c
@@ -19,65 +19,58 @@
***/
#include <linux/filter.h>
-#include <linux/if_ether.h>
+#include <netinet/if_ether.h>
#include "fd-util.h"
-#include "lldp-internal.h"
#include "lldp-network.h"
-#include "lldp-tlv.h"
#include "socket-util.h"
int lldp_network_bind_raw_socket(int ifindex) {
- typedef struct LLDPFrame {
- struct ethhdr hdr;
- uint8_t tlvs[0];
- } LLDPFrame;
- struct sock_filter filter[] = {
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest)), /* A <- 4 bytes of destination MAC */
+ static const struct sock_filter filter[] = {
+ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */
BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */
- BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */
BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */
- BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_proto)), /* A <- protocol */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */
BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */
BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */
};
- struct sock_fprog fprog = {
+ static const struct sock_fprog fprog = {
.len = ELEMENTSOF(filter),
- .filter = filter
+ .filter = (struct sock_filter*) filter,
};
- _cleanup_close_ int s = -1;
-
union sockaddr_union saddrll = {
.ll.sll_family = AF_PACKET,
.ll.sll_ifindex = ifindex,
};
+ _cleanup_close_ int fd = -1;
int r;
assert(ifindex > 0);
- s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (s < 0)
+ fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htons(ETHERTYPE_LLDP));
+ if (fd < 0)
return -errno;
- r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
+ r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
if (r < 0)
return -errno;
- r = bind(s, &saddrll.sa, sizeof(saddrll.ll));
+ r = bind(fd, &saddrll.sa, sizeof(saddrll.ll));
if (r < 0)
return -errno;
- r = s;
- s = -1;
+ r = fd;
+ fd = -1;
return r;
}
diff --git a/src/libsystemd-network/lldp-network.h b/src/libsystemd-network/lldp-network.h
index dcf31faa95..c4cf8c79f1 100644
--- a/src/libsystemd-network/lldp-network.h
+++ b/src/libsystemd-network/lldp-network.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -18,8 +20,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "sd-event.h"
int lldp_network_bind_raw_socket(int ifindex);
diff --git a/src/libsystemd-network/lldp-port.c b/src/libsystemd-network/lldp-port.c
deleted file mode 100644
index c86f62a6c2..0000000000
--- a/src/libsystemd-network/lldp-port.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/***
- 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/>.
-***/
-
-#include "alloc-util.h"
-#include "async.h"
-#include "lldp-internal.h"
-#include "lldp-network.h"
-#include "lldp-port.h"
-
-int lldp_port_start(lldp_port *p) {
- int r;
-
- assert_return(p, -EINVAL);
-
- r = lldp_network_bind_raw_socket(p->ifindex);
- if (r < 0)
- return r;
-
- p->rawfd = r;
-
- r = sd_event_add_io(p->event, &p->lldp_port_rx,
- p->rawfd, EPOLLIN, lldp_receive_packet, p);
- if (r < 0) {
- log_debug_errno(r, "Failed to allocate event source: %m");
- goto fail;
- }
-
- r = sd_event_source_set_priority(p->lldp_port_rx, p->event_priority);
- if (r < 0) {
- log_debug_errno(r, "Failed to set event priority: %m");
- goto fail;
- }
-
- r = sd_event_source_set_description(p->lldp_port_rx, "lldp-port-rx");
- if (r < 0) {
- log_debug_errno(r, "Failed to set event name: %m");
- goto fail;
- }
-
- return 0;
-
-fail:
- lldp_port_stop(p);
-
- return r;
-}
-
-int lldp_port_stop(lldp_port *p) {
-
- assert_return(p, -EINVAL);
-
- p->rawfd = asynchronous_close(p->rawfd);
- p->lldp_port_rx = sd_event_source_unref(p->lldp_port_rx);
-
- return 0;
-}
-
-void lldp_port_free(lldp_port *p) {
- if (!p)
- return;
-
- lldp_port_stop(p);
-
- free(p->ifname);
- free(p);
-}
-
-int lldp_port_new(int ifindex,
- const char *ifname,
- const struct ether_addr *addr,
- void *userdata,
- lldp_port **ret) {
- _cleanup_free_ lldp_port *p = NULL;
-
- assert_return(ifindex, -EINVAL);
- assert_return(ifname, -EINVAL);
- assert_return(addr, -EINVAL);
-
- p = new0(lldp_port, 1);
- if (!p)
- return -ENOMEM;
-
- p->rawfd = -1;
- p->ifindex = ifindex;
-
- p->ifname = strdup(ifname);
- if (!p->ifname)
- return -ENOMEM;
-
- memcpy(&p->mac, addr, ETH_ALEN);
-
- p->userdata = userdata;
-
- *ret = p;
-
- p = NULL;
-
- return 0;
-}
diff --git a/src/libsystemd-network/lldp-port.h b/src/libsystemd-network/lldp-port.h
deleted file mode 100644
index 96092f8df9..0000000000
--- a/src/libsystemd-network/lldp-port.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/***
- 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
-
-#include <net/ethernet.h>
-
-#include "sd-event.h"
-#include "sd-lldp.h"
-
-#include "util.h"
-
-typedef struct lldp_port lldp_port;
-
-typedef enum LLDPPortStatus {
- LLDP_PORT_STATUS_NONE,
- LLDP_PORT_STATUS_ENABLED,
- LLDP_PORT_STATUS_DISABLED,
- _LLDP_PORT_STATUS_MAX,
- _LLDP_PORT_STATUS_INVALID = -1,
-} LLDPPortStatus;
-
-struct lldp_port {
- LLDPPortStatus status;
-
- int ifindex;
- char *ifname;
-
- struct ether_addr mac;
-
- int rawfd;
-
- sd_event *event;
- sd_event_source *lldp_port_rx;
-
- int event_priority;
-
- void *userdata;
-};
-
-int lldp_port_new(int ifindex,
- const char *ifname,
- const struct ether_addr *addr,
- void *userdata,
- lldp_port **ret);
-void lldp_port_free(lldp_port *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_port*, lldp_port_free);
-#define _cleanup_lldp_port_free_ _cleanup_(lldp_port_freep)
-
-int lldp_port_start(lldp_port *p);
-int lldp_port_stop(lldp_port *p);
diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
deleted file mode 100644
index 9170b50691..0000000000
--- a/src/libsystemd-network/lldp-tlv.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/***
- 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/>.
-***/
-
-#include <arpa/inet.h>
-#include <net/ethernet.h>
-
-#include "alloc-util.h"
-#include "lldp-tlv.h"
-#include "macro.h"
-
-int tlv_section_new(tlv_section **ret) {
- tlv_section *s;
-
- s = new0(tlv_section, 1);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
-
- return 0;
-}
-
-void tlv_section_free(tlv_section *m) {
-
- if (!m)
- return;
-
- free(m);
-}
-
-int tlv_packet_new(tlv_packet **ret) {
- tlv_packet *m;
-
- m = new0(tlv_packet, 1);
- if (!m)
- return -ENOMEM;
-
- LIST_HEAD_INIT(m->sections);
- m->n_ref = 1;
-
- *ret = m;
-
- return 0;
-}
-
-tlv_packet *sd_lldp_packet_ref(tlv_packet *m) {
-
- if (!m)
- return NULL;
-
- assert(m->n_ref > 0);
- m->n_ref++;
-
- return m;
-}
-
-tlv_packet *sd_lldp_packet_unref(tlv_packet *m) {
- tlv_section *s, *n;
-
- if (!m)
- return NULL;
-
- assert(m->n_ref > 0);
- m->n_ref--;
-
- if (m->n_ref > 0)
- return m;
-
- LIST_FOREACH_SAFE(section, s, n, m->sections)
- tlv_section_free(s);
-
- free(m);
- return NULL;
-}
-
-int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length) {
- uint8_t *p;
-
- assert_return(m, -EINVAL);
- assert_return(data, -EINVAL);
- assert_return(data_length, -EINVAL);
-
- if (m->length + data_length > ETHER_MAX_LEN)
- return -ENOMEM;
-
- p = m->pdu + m->length;
- memcpy(p, data, data_length);
- m->length += data_length;
-
- return 0;
-}
-
-int tlv_packet_append_u8(tlv_packet *m, uint8_t data) {
-
- assert_return(m, -EINVAL);
-
- return tlv_packet_append_bytes(m, &data, sizeof(uint8_t));
-}
-
-int tlv_packet_append_u16(tlv_packet *m, uint16_t data) {
- uint16_t type;
-
- assert_return(m, -EINVAL);
-
- type = htons(data);
-
- return tlv_packet_append_bytes(m, &type, sizeof(uint16_t));
-}
-
-int tlv_packet_append_u32(tlv_packet *m, uint32_t data) {
- uint32_t type;
-
- assert_return(m, -EINVAL);
-
- type = htonl(data);
-
- return tlv_packet_append_bytes(m, &type, sizeof(uint32_t));
-}
-
-int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size) {
-
- assert_return(m, -EINVAL);
-
- return tlv_packet_append_bytes(m, data, size);
-}
-
-int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type) {
-
- assert_return(m, -EINVAL);
-
- m->container_pos = m->pdu + m->length;
-
- return tlv_packet_append_u16(m, type << 9);
-}
-
-int lldp_tlv_packet_close_container(tlv_packet *m) {
- uint16_t type;
-
- assert_return(m, -EINVAL);
- assert_return(m->container_pos, -EINVAL);
-
- memcpy(&type, m->container_pos, sizeof(uint16_t));
-
- type |= htons(((m->pdu + m->length) - (m->container_pos + 2)) & 0x01ff);
- memcpy(m->container_pos, &type, sizeof(uint16_t));
-
- return 0;
-}
-
-static inline int tlv_packet_read_internal(tlv_section *m, void **data) {
-
- assert_return(m->read_pos, -EINVAL);
-
- *data = m->read_pos;
-
- return 0;
-}
-
-int tlv_packet_read_u8(tlv_packet *m, uint8_t *data) {
- void *val = NULL;
- int r;
-
- assert_return(m, -EINVAL);
-
- r = tlv_packet_read_internal(m->container, &val);
- if (r < 0)
- return r;
-
- memcpy(data, val, sizeof(uint8_t));
-
- m->container->read_pos ++;
-
- return 0;
-}
-
-int tlv_packet_read_u16(tlv_packet *m, uint16_t *data) {
- uint16_t t;
- void *val = NULL;
- int r;
-
- assert_return(m, -EINVAL);
-
- r = tlv_packet_read_internal(m->container, &val);
- if (r < 0)
- return r;
-
- memcpy(&t, val, sizeof(uint16_t));
- *data = ntohs(t);
-
- m->container->read_pos += 2;
-
- return 0;
-}
-
-int tlv_packet_read_u32(tlv_packet *m, uint32_t *data) {
- uint32_t t;
- void *val;
- int r;
-
- assert_return(m, -EINVAL);
-
- r = tlv_packet_read_internal(m->container, &val);
- if (r < 0)
- return r;
-
- memcpy(&t, val, sizeof(uint32_t));
- *data = ntohl(t);
-
- m->container->read_pos += 4;
-
- return r;
-}
-
-int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) {
- void *val = NULL;
- int r;
-
- assert_return(m, -EINVAL);
-
- r = tlv_packet_read_internal(m->container, &val);
- if (r < 0)
- return r;
-
- *data = (char *) val;
- *data_length = m->container->data + m->container->length - m->container->read_pos;
-
- m->container->read_pos += *data_length;
-
- return 0;
-}
-
-int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length) {
- void *val = NULL;
- int r;
-
- assert_return(m, -EINVAL);
-
- r = tlv_packet_read_internal(m->container, &val);
- if (r < 0)
- return r;
-
- *data = (uint8_t *) val;
- *data_length = m->container->data + m->container->length - m->container->read_pos;
-
- m->container->read_pos += *data_length;
-
- return 0;
-}
-
-/* parse raw TLV packet */
-int tlv_packet_parse_pdu(tlv_packet *m, uint16_t size) {
- tlv_section *section, *tail;
- uint16_t t, l;
- uint8_t *p;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(size, -EINVAL);
-
- p = m->pdu;
-
- /* extract Ethernet header */
- memcpy(&m->mac, p, ETH_ALEN);
- p += sizeof(struct ether_header);
-
- for (l = 0; l <= size; ) {
- r = tlv_section_new(&section);
- if (r < 0)
- return r;
-
- memcpy(&t, p, sizeof(uint16_t));
-
- section->type = ntohs(t) >> 9;
- section->length = ntohs(t) & 0x01ff;
-
- if (section->type == LLDP_TYPE_END || section->type >=_LLDP_TYPE_MAX) {
- tlv_section_free(section);
- break;
- }
-
- p += 2;
-
- if (section->type == LLDP_TYPE_PRIVATE &&
- section->length >= LLDP_OUI_LEN + 1) {
- section->oui = p;
- p += LLDP_OUI_LEN;
- section->subtype = *p++;
-
- section->length -= LLDP_OUI_LEN + 1;
- l += LLDP_OUI_LEN + 1;
- }
-
- section->data = p;
-
- LIST_FIND_TAIL(section, m->sections, tail);
- LIST_INSERT_AFTER(section, m->sections, tail, section);
-
- p += section->length;
- l += (section->length + 2);
- }
-
- return 0;
-}
-
-int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type) {
- tlv_section *s;
-
- assert_return(m, -EINVAL);
- assert_return(type != LLDP_TYPE_PRIVATE, -EINVAL);
-
- LIST_FOREACH(section, s, m->sections)
- if (s->type == type)
- break;
- if (!s)
- return -1;
-
- m->container = s;
-
- m->container->read_pos = s->data;
- if (!m->container->read_pos) {
- m->container = NULL;
- return -1;
- }
-
- return 0;
-}
-
-int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype) {
- tlv_section *s;
-
- assert_return(m, -EINVAL);
- assert_return(oui, -EINVAL);
-
- LIST_FOREACH(section, s, m->sections) {
- if (s->type == LLDP_TYPE_PRIVATE &&
- s->oui &&
- s->subtype == subtype &&
- !memcmp(s->oui, oui, LLDP_OUI_LEN))
- break;
- }
-
- if (!s)
- return -1;
-
- m->container = s;
-
- m->container->read_pos = s->data;
- if (!m->container->read_pos) {
- m->container = NULL;
- return -1;
- }
-
- return 0;
-}
-
-int lldp_tlv_packet_exit_container(tlv_packet *m) {
- assert_return(m, -EINVAL);
-
- m->container = 0;
-
- return 0;
-}
-
-static int lldp_tlv_packet_read_u16_tlv(tlv_packet *tlv, uint16_t type, uint16_t *value) {
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container(tlv, type);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u16(tlv, value);
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-static int lldp_tlv_packet_read_string_tlv(tlv_packet *tlv, uint16_t type, char **data, uint16_t *length) {
- char *s;
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container(tlv, type);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_string(tlv, &s, length);
- if (r < 0)
- goto out;
-
- *data = (char *) s;
-
- out:
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_chassis_id(tlv_packet *tlv,
- uint8_t *type,
- uint8_t **data,
- uint16_t *length) {
- uint8_t subtype;
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_CHASSIS_ID);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u8(tlv, &subtype);
- if (r < 0)
- goto out;
-
- switch (subtype) {
- case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
-
- r = tlv_packet_read_bytes(tlv, data, length);
- if (r < 0)
- goto out;
-
- break;
- default:
- r = -EOPNOTSUPP;
- break;
- }
-
- *type = subtype;
-
- out:
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_port_id(tlv_packet *tlv,
- uint8_t *type,
- uint8_t **data,
- uint16_t *length) {
- uint8_t subtype;
- char *s;
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_PORT_ID);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u8(tlv, &subtype);
- if (r < 0)
- goto out;
-
- switch (subtype) {
- case LLDP_PORT_SUBTYPE_PORT_COMPONENT:
- case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
- case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
- case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
-
- r = tlv_packet_read_string(tlv, &s, length);
- if (r < 0)
- goto out;
-
- *data = (uint8_t *) s;
-
- break;
- case LLDP_PORT_SUBTYPE_MAC_ADDRESS:
-
- r = tlv_packet_read_bytes(tlv, data, length);
- if (r < 0)
- goto out;
-
- break;
- default:
- r = -EOPNOTSUPP;
- break;
- }
-
- *type = subtype;
-
- out:
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_ttl(tlv_packet *tlv, uint16_t *ttl) {
- return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_TTL, ttl);
-}
-
-int sd_lldp_packet_read_system_name(tlv_packet *tlv,
- char **data,
- uint16_t *length) {
- return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_NAME, data, length);
-}
-
-int sd_lldp_packet_read_system_description(tlv_packet *tlv,
- char **data,
- uint16_t *length) {
- return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_DESCRIPTION, data, length);
-}
-
-int sd_lldp_packet_read_port_description(tlv_packet *tlv,
- char **data,
- uint16_t *length) {
- return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_PORT_DESCRIPTION, data, length);
-}
-
-int sd_lldp_packet_read_system_capability(tlv_packet *tlv, uint16_t *data) {
- return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_SYSTEM_CAPABILITIES, data);
-}
-
-int sd_lldp_packet_read_port_vlan_id(tlv_packet *tlv, uint16_t *id) {
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u16(tlv, id);
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id) {
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u8(tlv, flags);
- if (r >= 0)
- r = tlv_packet_read_u16(tlv, id);
-
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_vlan_name(tlv_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length) {
- int r, r2;
- uint8_t len = 0;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_VLAN_NAME);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u16(tlv, vlan_id);
- if (r >= 0)
- r = tlv_packet_read_u8(tlv, &len);
- if (r >= 0)
- r = tlv_packet_read_string(tlv, name, length);
-
- if (r >= 0 && len < *length)
- *length = len;
-
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_management_vid(tlv_packet *tlv, uint16_t *id) {
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u16(tlv, id);
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id) {
- int r, r2;
-
- assert_return(tlv, -EINVAL);
-
- r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION);
- if (r < 0)
- return r;
-
- r = tlv_packet_read_u8(tlv, status);
- if (r >= 0)
- r = tlv_packet_read_u32(tlv, id);
-
- r2 = lldp_tlv_packet_exit_container(tlv);
-
- return r < 0 ? r : r2;
-}
-
-int sd_lldp_packet_get_destination_type(tlv_packet *tlv, int *dest) {
- assert_return(tlv, -EINVAL);
- assert_return(dest, -EINVAL);
-
- /* 802.1AB-2009, Table 7-1 */
- if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_BRIDGE, ETH_ALEN))
- *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE;
- else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE, ETH_ALEN))
- *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE;
- else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE, ETH_ALEN))
- *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE;
- else
- return -EINVAL;
-
- return 0;
-}
diff --git a/src/libsystemd-network/lldp-tlv.h b/src/libsystemd-network/lldp-tlv.h
deleted file mode 100644
index 8e7706c612..0000000000
--- a/src/libsystemd-network/lldp-tlv.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/***
- 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
-
-#include <net/ethernet.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;
-
-#define LLDP_OUI_LEN 3
-
-struct sd_lldp_section {
- uint16_t type;
- uint16_t length;
- uint8_t *oui;
- uint8_t subtype;
-
- uint8_t *read_pos;
- uint8_t *data;
-
- LIST_FIELDS(tlv_section, section);
-};
-
-#define LLDP_MAC_NEAREST_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
-#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }
-#define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }
-
-int tlv_section_new(tlv_section **ret);
-void tlv_section_free(tlv_section *ret);
-
-struct sd_lldp_packet {
- unsigned n_ref;
-
- uint16_t type;
- uint16_t length;
- usec_t ts;
-
- uint8_t *container_pos;
- uint8_t pdu[ETHER_MAX_LEN];
-
- void *userdata;
-
- struct ether_addr mac;
- tlv_section *container;
-
- LIST_HEAD(tlv_section, sections);
-};
-
-int tlv_packet_new(tlv_packet **ret);
-
-int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type);
-int lldp_tlv_packet_close_container(tlv_packet *m);
-
-int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length);
-int tlv_packet_append_u8(tlv_packet *m, uint8_t data);
-int tlv_packet_append_u16(tlv_packet *m, uint16_t data);
-int tlv_packet_append_u32(tlv_packet *m, uint32_t data);
-int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size);
-
-int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type);
-int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype);
-int lldp_tlv_packet_exit_container(tlv_packet *m);
-
-int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length);
-int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length);
-int tlv_packet_read_u8(tlv_packet *m, uint8_t *data);
-int tlv_packet_read_u16(tlv_packet *m, uint16_t *data);
-int tlv_packet_read_u32(tlv_packet *m, uint32_t *data);
-
-int tlv_packet_parse_pdu(tlv_packet *t, uint16_t size);
diff --git a/src/libsystemd-network/lldp.h b/src/libsystemd-network/lldp.h
deleted file mode 100644
index d2c7164633..0000000000
--- a/src/libsystemd-network/lldp.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/***
- 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 LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
-
-#define ETHERTYPE_LLDP 0x88cc
-
-/* IEEE 802.3AB Clause 9: TLV Types */
-typedef enum LLDPTypes {
- LLDP_TYPE_END = 0,
- LLDP_TYPE_CHASSIS_ID = 1,
- LLDP_TYPE_PORT_ID = 2,
- LLDP_TYPE_TTL = 3,
- LLDP_TYPE_PORT_DESCRIPTION = 4,
- LLDP_TYPE_SYSTEM_NAME = 5,
- LLDP_TYPE_SYSTEM_DESCRIPTION = 6,
- LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
- LLDP_TYPE_MGMT_ADDRESS = 8,
- LLDP_TYPE_PRIVATE = 127,
- _LLDP_TYPE_MAX,
- _LLDP_TYPE_INVALID = -1,
-} LLDPTypes;
-
-/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
-typedef enum LLDPChassisSubtypes {
- LLDP_CHASSIS_SUBTYPE_RESERVED = 0,
- LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1,
- LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2,
- LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3,
- LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4,
- LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5,
- LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6,
- LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7,
- _LLDP_CHASSIS_SUBTYPE_MAX,
- _LLDP_CHASSIS_SUBTYPE_INVALID = -1,
-} LLDPChassisSubtypes;
-
-/* IEEE 802.3AB Clause 9.5.3: Port subtype */
-typedef enum LLDPPortSubtypes {
- LLDP_PORT_SUBTYPE_RESERVED = 0,
- LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1,
- LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2,
- LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3,
- LLDP_PORT_SUBTYPE_NETWORK = 4,
- LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5,
- LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
- LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
- _LLDP_PORT_SUBTYPE_MAX,
- _LLDP_PORT_SUBTYPE_INVALID = -1
-} LLDPPortSubtypes;
-
-typedef enum LLDPSystemCapabilities {
- LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0,
- LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
- LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2,
- LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3,
- LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4,
- LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5,
- LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6,
- LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7,
- LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8,
- LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9,
- LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10,
- _LLDP_SYSTEM_CAPABILITIES_MAX,
- _LLDP_SYSTEM_CAPABILITIES_INVALID = -1,
-} LLDPSystemCapabilities;
-
-typedef enum LLDPMedSubtype {
- LLDP_MED_SUBTYPE_RESERVED = 0,
- LLDP_MED_SUBTYPE_CAPABILITIES = 1,
- LLDP_MED_SUBTYPE_NETWORK_POLICY = 2,
- LLDP_MED_SUBTYPE_LOCATION_ID = 3,
- LLDP_MED_SUBTYPE_EXTENDED_PVMDI = 4,
- LLDP_MED_SUBTYPE_INV_HWREV = 5,
- LLDP_MED_SUBTYPE_INV_FWREV = 6,
- LLDP_MED_SUBTYPE_INV_SWREV = 7,
- LLDP_MED_SUBTYPE_INV_SERIAL = 8,
- LLDP_MED_SUBTYPE_INV_MANUFACTURER = 9,
- LLDP_MED_SUBTYPE_INV_MODELNAME = 10,
- LLDP_MED_SUBTYPE_INV_ASSETID = 11,
- _LLDP_MED_SUBTYPE_MAX,
- _LLDP_MED_SUBTYPE_INVALID = -1,
-} LLDPMedSubtype;
-
-typedef enum LLDPMedCapability {
- LLDP_MED_CAPABILITY_CAPAPILITIES = 1 << 0,
- LLDP_MED_CAPABILITY_NETWORK_POLICY = 1 << 1,
- LLDP_MED_CAPABILITY_LOCATION_ID = 1 << 2,
- LLDP_MED_CAPABILITY_EXTENDED_PSE = 1 << 3,
- LLDP_MED_CAPABILITY_EXTENDED_PD = 1 << 4,
- LLDP_MED_CAPABILITY_INVENTORY = 1 << 5,
- LLDP_MED_CAPABILITY_MAX,
- LLDP_MED_CAPABILITY_INVALID = -1,
-} LLDPMedCapability;
-
-#define LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
-#define LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
-
-enum {
- LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID = 1,
- LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID = 2,
- LLDP_OUI_SUBTYPE_802_1_VLAN_NAME = 3,
- LLDP_OUI_SUBTYPE_802_1_PROTOCOL_IDENTITY = 4,
- LLDP_OUI_SUBTYPE_802_1_VID_USAGE_DIGEST = 5,
- LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID = 6,
- LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION = 7,
-};
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index fdafcd84d8..0e2d757b2b 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -335,6 +335,35 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
+int config_parse_iaid(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ uint32_t iaid;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &iaid);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
+ return r;
+ }
+
+ *((uint32_t *)data) = iaid;
+
+ return 0;
+}
+
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;
@@ -375,7 +404,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
if (r <= 0)
continue;
- size ++;
+ size++;
}
*ret = addresses;
@@ -482,7 +511,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
return -ENOMEM;
entry = strndup(word, len);
- if(!entry)
+ if (!entry)
return -ENOMEM;
tok = entry;
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index c8a531ab0f..72432774d7 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -62,6 +62,10 @@ int config_parse_ifalias(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_iaid(const char *unit, const char *filename, unsigned line,
+ const char *section, unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data, void *userdata);
+
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 62099dd3f4..287b6e26fa 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -82,7 +82,7 @@ struct sd_dhcp_client {
} _packed_ ll;
struct {
/* 255: Node-specific (RFC 4361) */
- uint32_t iaid;
+ be32_t iaid;
struct duid duid;
} _packed_ ns;
struct {
@@ -101,7 +101,7 @@ struct sd_dhcp_client {
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
sd_event_source *timeout_expire;
- sd_dhcp_client_cb_t cb;
+ sd_dhcp_client_callback_t cb;
void *userdata;
sd_dhcp_lease *lease;
usec_t start_delay;
@@ -121,7 +121,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
uint32_t revents, void *userdata);
static void client_stop(sd_dhcp_client *client, int error);
-int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
+int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
void *userdata) {
assert_return(client, -EINVAL);
@@ -298,6 +298,52 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
return 0;
}
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+ uint16_t duid_type, uint8_t *duid, size_t duid_len) {
+ DHCP_CLIENT_DONT_DESTROY(client);
+ int r;
+ assert_return(client, -EINVAL);
+ zero(client->client_id);
+
+ client->client_id.type = 255;
+
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = htobe32(iaid);
+
+ /* If DUID is not configured, generate DUID-EN. */
+ if (duid_len == 0) {
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
+ &duid_len);
+ if (r < 0)
+ return r;
+ } else {
+ r = dhcp_validate_duid_len(client->client_id.type, duid_len);
+ if (r < 0)
+ return r;
+ client->client_id.ns.duid.type = htobe16(duid_type);
+ memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
+ duid_len += sizeof(client->client_id.ns.duid.type);
+ }
+
+ client->client_id_len = sizeof(client->client_id.type) + duid_len +
+ sizeof(client->client_id.ns.iaid);
+
+ if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+ log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+ client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
+ sd_dhcp_client_start(client);
+ }
+
+ return 0;
+}
+
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL;
@@ -408,7 +454,7 @@ static void client_stop(sd_dhcp_client *client, int error) {
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
uint8_t type, size_t *_optlen, size_t *_optoffset) {
- _cleanup_free_ DHCPPacket *packet;
+ _cleanup_free_ DHCPPacket *packet = NULL;
size_t optlen, optoffset, size;
be16_t max_size;
usec_t time_now;
@@ -1691,8 +1737,7 @@ int sd_dhcp_client_stop(sd_dhcp_client *client) {
return 0;
}
-int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
- int priority) {
+int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) {
int r;
assert_return(client, -EINVAL);
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 7a119fd488..ef50ed17a1 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -825,7 +825,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
if (r >= 0) {
- _cleanup_free_ char *client_id_hex;
+ _cleanup_free_ char *client_id_hex = NULL;
client_id_hex = hexmem(client_id, client_id_len);
if (!client_id_hex) {
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 54ff1a3f28..9adf8ec19d 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -208,8 +208,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
return 0;
}
-int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event,
- int priority) {
+int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) {
int r;
assert_return(server, -EINVAL);
@@ -281,10 +280,11 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
}
static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
+ uint16_t destination_port,
DHCPMessage *message, size_t len) {
union sockaddr_union dest = {
.in.sin_family = AF_INET,
- .in.sin_port = htobe16(DHCP_PORT_CLIENT),
+ .in.sin_port = htobe16(destination_port),
.in.sin_addr.s_addr = destination,
};
struct iovec iov = {
@@ -343,6 +343,7 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
DHCPRequest *req, DHCPPacket *packet,
int type, size_t optoffset) {
be32_t destination = INADDR_ANY;
+ uint16_t destination_port = DHCP_PORT_CLIENT;
int r;
assert(server);
@@ -387,17 +388,19 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
*/
if (req->message->giaddr) {
destination = req->message->giaddr;
+ destination_port = DHCP_PORT_SERVER;
if (type == DHCP_NAK)
packet->dhcp.flags = htobe16(0x8000);
} else if (req->message->ciaddr && type != DHCP_NAK)
destination = req->message->ciaddr;
if (destination != INADDR_ANY)
- return dhcp_server_send_udp(server, destination, &packet->dhcp,
+ return dhcp_server_send_udp(server, destination,
+ destination_port, &packet->dhcp,
sizeof(DHCPMessage) + optoffset);
else if (requested_broadcast(req) || type == DHCP_NAK)
return dhcp_server_send_udp(server, INADDR_BROADCAST,
- &packet->dhcp,
+ destination_port, &packet->dhcp,
sizeof(DHCPMessage) + optoffset);
else
/* we cannot send UDP packet to specific MAC address when the
@@ -580,7 +583,8 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN);
- r = dhcp_server_send_udp(server, address, &packet->dhcp,
+ r = dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT,
+ &packet->dhcp,
sizeof(DHCPMessage) + optoffset);
if (r < 0)
return r;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 7d56d4cc60..ee4fb4fc1e 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -64,7 +64,7 @@ struct sd_dhcp6_client {
uint8_t retransmit_count;
sd_event_source *timeout_resend;
sd_event_source *timeout_resend_expire;
- sd_dhcp6_client_cb_t cb;
+ sd_dhcp6_client_callback_t cb;
void *userdata;
struct duid duid;
size_t duid_len;
@@ -111,7 +111,7 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
-int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
+int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) {
assert_return(client, -EINVAL);
client->cb = cb;
@@ -180,41 +180,29 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
}
-int sd_dhcp6_client_set_duid(
- sd_dhcp6_client *client,
- uint16_t type,
- uint8_t *duid, size_t duid_len) {
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+ uint8_t *duid, size_t duid_len) {
+ int r;
assert_return(client, -EINVAL);
- assert_return(duid, -EINVAL);
- assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
-
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
- switch (type) {
- case DHCP6_DUID_LLT:
- if (duid_len <= sizeof(client->duid.llt))
- return -EINVAL;
- break;
- case DHCP6_DUID_EN:
- if (duid_len != sizeof(client->duid.en))
- return -EINVAL;
- break;
- case DHCP6_DUID_LL:
- if (duid_len <= sizeof(client->duid.ll))
- return -EINVAL;
- break;
- case DHCP6_DUID_UUID:
- if (duid_len != sizeof(client->duid.uuid))
- return -EINVAL;
- break;
- default:
- /* accept unknown type in order to be forward compatible */
- break;
+ if (duid_len > 0) {
+ r = dhcp_validate_duid_len(duid_type, duid_len);
+ if (r < 0)
+ return r;
+ client->duid.type = htobe16(duid_type);
+ memcpy(&client->duid.raw.data, duid, duid_len);
+ client->duid_len = duid_len + sizeof(client->duid.type);
}
- client->duid.type = htobe16(type);
- memcpy(&client->duid.raw.data, duid, duid_len);
- client->duid_len = duid_len + sizeof(client->duid.type);
+ return 0;
+}
+
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
+ assert_return(client, -EINVAL);
+ assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+
+ client->ia_na.id = htobe32(iaid);
return 0;
}
@@ -1204,7 +1192,7 @@ error:
return r;
}
-int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {
+int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) {
int r;
assert_return(client, -EINVAL);
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index f7880a891c..cc7436db6b 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -92,7 +92,7 @@ struct sd_ipv4acd {
struct ether_addr mac_addr;
sd_event *event;
int event_priority;
- sd_ipv4acd_cb_t cb;
+ sd_ipv4acd_callback_t cb;
void* userdata;
};
@@ -428,7 +428,7 @@ int sd_ipv4acd_detach_event(sd_ipv4acd *ll) {
return 0;
}
-int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) {
+int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority) {
int r;
assert_return(ll, -EINVAL);
@@ -447,7 +447,7 @@ int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) {
return 0;
}
-int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) {
+int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata) {
assert_return(ll, -EINVAL);
ll->cb = cb;
@@ -456,7 +456,7 @@ int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata)
return 0;
}
-int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address){
+int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address) {
assert_return(ll, -EINVAL);
assert_return(address, -EINVAL);
assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index db6cf22aaa..2a06418c53 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -52,7 +52,7 @@ struct sd_ipv4ll {
/* External */
be32_t claimed_address;
- sd_ipv4ll_cb_t cb;
+ sd_ipv4ll_callback_t cb;
void* userdata;
};
@@ -160,7 +160,7 @@ int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
return sd_ipv4acd_detach_event(ll->acd);
}
-int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) {
+int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) {
int r;
assert_return(ll, -EINVAL);
@@ -172,7 +172,7 @@ int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) {
return 0;
}
-int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) {
+int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) {
assert_return(ll, -EINVAL);
ll->cb = cb;
@@ -181,7 +181,7 @@ int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) {
return 0;
}
-int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){
+int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) {
assert_return(ll, -EINVAL);
assert_return(address, -EINVAL);
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 885ca62425..9d4587c80e 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -1,21 +1,21 @@
/***
- This file is part of systemd.
+ This file is part of systemd.
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ 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 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.
+ 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/>.
+ 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>
@@ -24,733 +24,473 @@
#include "alloc-util.h"
#include "fd-util.h"
-#include "fileio.h"
-#include "hashmap.h"
#include "lldp-internal.h"
-#include "lldp-port.h"
-#include "lldp-tlv.h"
-#include "prioq.h"
-#include "siphash24.h"
-#include "string-util.h"
-
-typedef enum LLDPAgentRXState {
- LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL = 4,
- LLDP_AGENT_RX_DELETE_AGED_INFO,
- LLDP_AGENT_RX_LLDP_INITIALIZE,
- LLDP_AGENT_RX_WAIT_FOR_FRAME,
- LLDP_AGENT_RX_RX_FRAME,
- LLDP_AGENT_RX_DELETE_INFO,
- LLDP_AGENT_RX_UPDATE_INFO,
- _LLDP_AGENT_RX_STATE_MAX,
- _LLDP_AGENT_RX_INVALID = -1,
-} LLDPAgentRXState;
-
-/* Section 10.5.2.2 Reception counters */
-struct lldp_agent_statistics {
- uint64_t stats_ageouts_total;
- uint64_t stats_frames_discarded_total;
- uint64_t stats_frames_in_errors_total;
- uint64_t stats_frames_in_total;
- uint64_t stats_tlvs_discarded_total;
- uint64_t stats_tlvs_unrecognized_total;
-};
-
-struct sd_lldp {
- lldp_port *port;
-
- Prioq *by_expiry;
- Hashmap *neighbour_mib;
-
- sd_lldp_cb_t cb;
-
- void *userdata;
-
- LLDPAgentRXState rx_state;
- lldp_agent_statistics statistics;
-};
-
-static void chassis_id_hash_func(const void *p, struct siphash *state) {
- const lldp_chassis_id *id = p;
-
- assert(id);
- assert(id->data);
-
- siphash24_compress(&id->length, sizeof(id->length), state);
- siphash24_compress(id->data, id->length, state);
-}
+#include "lldp-neighbor.h"
+#include "lldp-network.h"
+#include "socket-util.h"
+#include "ether-addr-util.h"
-static int chassis_id_compare_func(const void *_a, const void *_b) {
- const lldp_chassis_id *a, *b;
+#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
- a = _a;
- b = _b;
+static void lldp_flush_neighbors(sd_lldp *lldp) {
+ sd_lldp_neighbor *n;
- assert(!a->length || a->data);
- assert(!b->length || b->data);
+ assert(lldp);
- if (a->type != b->type)
- return -1;
+ while ((n = hashmap_first(lldp->neighbor_by_id)))
+ lldp_neighbor_unlink(n);
+}
- if (a->length != b->length)
- return a->length < b->length ? -1 : 1;
+static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
+ assert(lldp);
+ assert(n);
- return memcmp(a->data, b->data, a->length);
-}
+ log_lldp("Invoking callback for '%c'.", event);
-static const struct hash_ops chassis_id_hash_ops = {
- .hash = chassis_id_hash_func,
- .compare = chassis_id_compare_func
-};
+ if (!lldp->callback)
+ return;
-static void lldp_mib_delete_objects(sd_lldp *lldp);
-static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state);
-static void lldp_run_state_machine(sd_lldp *ll);
+ lldp->callback(lldp, event, n, lldp->userdata);
+}
-static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) {
- int r;
+static int lldp_make_space(sd_lldp *lldp, size_t extra) {
+ usec_t t = USEC_INFINITY;
+ bool changed = false;
assert(lldp);
- assert(tlv);
-
- /* Remove expired packets */
- if (prioq_size(lldp->by_expiry) > 0) {
- lldp_set_state(lldp, LLDP_AGENT_RX_DELETE_INFO);
+ /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries
+ * are free. */
- lldp_mib_delete_objects(lldp);
- }
+ for (;;) {
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
- r = lldp_mib_add_objects(lldp->by_expiry, lldp->neighbour_mib, tlv);
- if (r < 0)
- goto out;
+ n = prioq_peek(lldp->neighbor_by_expiry);
+ if (!n)
+ break;
- lldp_set_state(lldp, LLDP_AGENT_RX_UPDATE_INFO);
+ sd_lldp_neighbor_ref(n);
- log_lldp("Packet added. MIB size: %d , PQ size: %d",
- hashmap_size(lldp->neighbour_mib),
- prioq_size(lldp->by_expiry));
+ if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra))
+ goto remove_one;
- lldp->statistics.stats_frames_in_total ++;
+ if (t == USEC_INFINITY)
+ t = now(clock_boottime_or_monotonic());
- out:
- if (r < 0)
- log_lldp("Receive frame failed: %s", strerror(-r));
+ if (n->until > t)
+ break;
- lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME);
+ remove_one:
+ lldp_neighbor_unlink(n);
+ lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
+ changed = true;
+ }
- return 0;
+ return changed;
}
-/* 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;
- lldp_port *port;
- uint8_t *p, *q;
- sd_lldp *lldp;
- int r;
-
- assert(tlv);
- assert(length > 0);
-
- port = (lldp_port *) tlv->userdata;
- lldp = (sd_lldp *) port->userdata;
-
- if (lldp->port->status == LLDP_PORT_STATUS_DISABLED) {
- log_lldp("Port: %s is disabled. Dropping.", lldp->port->ifname);
- goto out;
- }
+static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
+ assert(lldp);
+ assert(n);
- lldp_set_state(lldp, LLDP_AGENT_RX_RX_FRAME);
+ /* Don't keep data with a zero TTL */
+ if (n->ttl <= 0)
+ return false;
- p = tlv->pdu;
- p += sizeof(struct ether_header);
+ /* Filter out data from the filter address */
+ if (!ether_addr_is_null(&lldp->filter_address) &&
+ ether_addr_equal(&lldp->filter_address, &n->source_address))
+ return false;
- for (i = 1, l = 0; l <= length; i++) {
+ /* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with
+ * no caps field set. */
+ if (n->has_capabilities &&
+ (n->enabled_capabilities & lldp->capability_mask) == 0)
+ return false;
- memcpy(&t, p, sizeof(uint16_t));
+ /* Keep everything else */
+ return true;
+}
- type = ntohs(t) >> 9;
- len = ntohs(t) & 0x01ff;
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
- if (type == LLDP_TYPE_END) {
- if (len != 0) {
- log_lldp("TLV type end must be length 0 (not %d). Dropping.", len);
+static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL;
+ bool keep;
+ int r;
- malformed = true;
- goto out;
- }
+ assert(lldp);
+ assert(n);
+ assert(!n->lldp);
- end = true;
+ keep = lldp_keep_neighbor(lldp, n);
- break;
- } else if (type >=_LLDP_TYPE_MAX) {
- log_lldp("TLV type: %d not recognized. Dropping.", type);
+ /* First retrieve the old entry for this MSAP */
+ old = hashmap_get(lldp->neighbor_by_id, &n->id);
+ if (old) {
+ sd_lldp_neighbor_ref(old);
- malformed = true;
- goto out;
+ if (!keep) {
+ lldp_neighbor_unlink(old);
+ lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
+ return 0;
}
- /* skip type and length encoding */
- p += 2;
- q = p;
-
- p += len;
- l += (len + 2);
+ if (lldp_neighbor_equal(n, old)) {
+ /* Is this equal, then restart the TTL counter, but don't do anyting else. */
+ lldp_start_timer(lldp, old);
+ lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
+ return 0;
+ }
- if (i <= 3) {
- if (i != type) {
- log_lldp("TLV missing or out of order. Dropping.");
+ /* Data changed, remove the old entry, and add a new one */
+ lldp_neighbor_unlink(old);
- malformed = true;
- goto out;
- }
- }
+ } else if (!keep)
+ return 0;
- switch(type) {
- case LLDP_TYPE_CHASSIS_ID:
+ /* Then, make room for at least one new neighbor */
+ lldp_make_space(lldp, 1);
- if (len < 2) {
- log_lldp("Received malformed Chassis ID TLV length: %d. Dropping.", len);
+ r = hashmap_put(lldp->neighbor_by_id, &n->id, n);
+ if (r < 0)
+ goto finish;
- malformed = true;
- goto out;
- }
+ r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx);
+ if (r < 0) {
+ assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n);
+ goto finish;
+ }
- if (chassis_id) {
- log_lldp("Duplicate Chassis ID TLV found. Dropping.");
+ n->lldp = lldp;
- malformed = true;
- goto out;
- }
+ lldp_start_timer(lldp, n);
+ lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
- /* 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);
+ return 1;
- malformed = true;
- goto out;
+finish:
+ if (old)
+ lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
- }
+ return r;
+}
- chassis_id = true;
+static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) {
+ int r;
- break;
- case LLDP_TYPE_PORT_ID:
+ assert(lldp);
+ assert(n);
- if (len < 2) {
- log_lldp("Received malformed Port ID TLV length: %d. Dropping.", len);
+ r = lldp_neighbor_parse(n);
+ if (r == -EBADMSG) /* Ignore bad messages */
+ return 0;
+ if (r < 0)
+ return r;
- malformed = true;
- goto out;
- }
+ r = lldp_add_neighbor(lldp, n);
+ if (r < 0) {
+ log_lldp_errno(r, "Failed to add datagram. Ignoring.");
+ return 0;
+ }
- if (port_id) {
- log_lldp("Duplicate Port ID TLV found. Dropping.");
+ log_lldp("Successfully processed LLDP datagram.");
+ return 0;
+}
- malformed = true;
- goto out;
- }
+static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+ ssize_t space, length;
+ sd_lldp *lldp = userdata;
- /* 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);
+ assert(fd >= 0);
+ assert(lldp);
- malformed = true;
- goto out;
+ space = next_datagram_size_fd(fd);
+ if (space < 0)
+ return log_lldp_errno(space, "Failed to determine datagram size to read: %m");
- }
+ n = lldp_neighbor_new(space);
+ if (!n)
+ return -ENOMEM;
- port_id = true;
+ length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
+ if (length < 0)
+ return log_lldp_errno(errno, "Failed to read LLDP datagram: %m");
- break;
- case LLDP_TYPE_TTL:
+ if ((size_t) length != n->raw_size) {
+ log_lldp("Packet size mismatch.");
+ return -EINVAL;
+ }
- if(len != 2) {
- log_lldp("Received invalid TTL TLV lenth: %d. Dropping.", len);
+ return lldp_handle_datagram(lldp, n);
+}
- malformed = true;
- goto out;
- }
+_public_ int sd_lldp_start(sd_lldp *lldp) {
+ int r;
- if (ttl) {
- log_lldp("Duplicate TTL TLV found. Dropping.");
+ assert_return(lldp, -EINVAL);
- malformed = true;
- goto out;
- }
+ if (lldp->fd >= 0)
+ return 0;
- ttl = true;
+ assert(!lldp->io_event_source);
- break;
- case LLDP_TYPE_SYSTEM_NAME:
+ lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex);
+ if (lldp->fd < 0)
+ return lldp->fd;
- /* 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 (lldp->event) {
+ r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
+ if (r < 0)
+ goto fail;
- if (system_name) {
- log_lldp("Duplicate system name found. Dropping.");
- malformed = true;
- goto out;
- }
+ r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
+ if (r < 0)
+ goto fail;
- system_name = true;
+ (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
+ }
- 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:
+ return 1;
- if (len == 0) {
- log_lldp("TLV type: %d length 0 received. Dropping.", type);
+fail:
+ lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
+ lldp->fd = safe_close(lldp->fd);
- malformed = true;
- goto out;
- }
- break;
- }
- }
+ return r;
+}
- if(!chassis_id || !port_id || !ttl || !end) {
- log_lldp("One or more mandatory TLV missing. Dropping.");
+_public_ int sd_lldp_stop(sd_lldp *lldp) {
+ assert_return(lldp, -EINVAL);
- malformed = true;
- goto out;
+ if (lldp->fd < 0)
+ return 0;
- }
+ lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
+ lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
+ lldp->fd = safe_close(lldp->fd);
- r = tlv_packet_parse_pdu(tlv, length);
- if (r < 0) {
- log_lldp("Failed to parse the TLV. Dropping.");
+ lldp_flush_neighbors(lldp);
- malformed = true;
- goto out;
- }
+ return 1;
+}
- return lldp_receive_frame(lldp, tlv);
+_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) {
+ int r;
- out:
- lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME);
+ assert_return(lldp, -EINVAL);
+ assert_return(lldp->fd < 0, -EBUSY);
+ assert_return(!lldp->event, -EBUSY);
- if (malformed) {
- lldp->statistics.stats_frames_discarded_total ++;
- lldp->statistics.stats_frames_in_errors_total ++;
+ if (event)
+ lldp->event = sd_event_ref(event);
+ else {
+ r = sd_event_default(&lldp->event);
+ if (r < 0)
+ return r;
}
- sd_lldp_packet_unref(tlv);
+ lldp->event_priority = priority;
return 0;
}
-static int ttl_expiry_item_prioq_compare_func(const void *a, const void *b) {
- const lldp_neighbour_port *p = a, *q = b;
+_public_ int sd_lldp_detach_event(sd_lldp *lldp) {
- if (p->until < q->until)
- return -1;
-
- if (p->until > q->until)
- return 1;
+ assert_return(lldp, -EINVAL);
+ assert_return(lldp->fd < 0, -EBUSY);
+ lldp->event = sd_event_unref(lldp->event);
return 0;
}
-static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state) {
-
- assert(lldp);
- assert(state < _LLDP_AGENT_RX_STATE_MAX);
+_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
+ assert_return(lldp, -EINVAL);
- lldp->rx_state = state;
+ lldp->callback = cb;
+ lldp->userdata = userdata;
- lldp_run_state_machine(lldp);
+ return 0;
}
-static void lldp_run_state_machine(sd_lldp *lldp) {
- if (!lldp->cb)
- return;
-
- switch (lldp->rx_state) {
- case LLDP_AGENT_RX_UPDATE_INFO:
- lldp->cb(lldp, SD_LLDP_EVENT_UPDATE_INFO, lldp->userdata);
- break;
- default:
- break;
- }
-}
+_public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
-/* 10.5.5.2.1 mibDeleteObjects ()
- * The mibDeleteObjects () procedure deletes all information in the LLDP remote
- * systems MIB associated with the MSAP identifier if an LLDPDU is received with
- * an rxTTL value of zero (see 10.3.2) or the timing counter rxInfoTTL expires. */
+ if (!lldp)
+ return NULL;
-static void lldp_mib_delete_objects(sd_lldp *lldp) {
- lldp_neighbour_port *p;
- usec_t t = 0;
+ lldp_flush_neighbors(lldp);
- /* Remove all entries that are past their TTL */
- for (;;) {
+ hashmap_free(lldp->neighbor_by_id);
+ prioq_free(lldp->neighbor_by_expiry);
- if (prioq_size(lldp->by_expiry) <= 0)
- break;
+ sd_event_source_unref(lldp->io_event_source);
+ sd_event_source_unref(lldp->timer_event_source);
+ sd_event_unref(lldp->event);
+ safe_close(lldp->fd);
- p = prioq_peek(lldp->by_expiry);
- if (!p)
- break;
+ free(lldp);
- if (t <= 0)
- t = now(clock_boottime_or_monotonic());
+ return NULL;
+}
- if (p->until > t)
- break;
+_public_ int sd_lldp_new(sd_lldp **ret, int ifindex) {
+ _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
+ int r;
- lldp_neighbour_port_remove_and_free(p);
+ assert_return(ret, -EINVAL);
+ assert_return(ifindex > 0, -EINVAL);
- lldp->statistics.stats_ageouts_total ++;
- }
-}
+ lldp = new0(sd_lldp, 1);
+ if (!lldp)
+ return -ENOMEM;
-static void lldp_mib_objects_flush(sd_lldp *lldp) {
- lldp_neighbour_port *p, *q;
- lldp_chassis *c;
+ lldp->fd = -1;
+ lldp->ifindex = ifindex;
+ lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX;
+ lldp->capability_mask = (uint16_t) -1;
- assert(lldp);
- assert(lldp->neighbour_mib);
- assert(lldp->by_expiry);
+ lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_id_hash_ops);
+ if (!lldp->neighbor_by_id)
+ return -ENOMEM;
- /* Drop all packets */
- while ((c = hashmap_steal_first(lldp->neighbour_mib))) {
+ r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func);
+ if (r < 0)
+ return r;
- LIST_FOREACH_SAFE(port, p, q, c->ports) {
- lldp_neighbour_port_remove_and_free(p);
- }
- }
+ *ret = lldp;
+ lldp = NULL;
- assert(hashmap_size(lldp->neighbour_mib) == 0);
- assert(prioq_size(lldp->by_expiry) == 0);
+ return 0;
}
-int sd_lldp_save(sd_lldp *lldp, const char *lldp_file) {
- _cleanup_free_ char *temp_path = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- uint8_t *mac, *port_id, type;
- lldp_neighbour_port *p;
- uint16_t data = 0, length = 0;
- char buf[LINE_MAX];
- lldp_chassis *c;
- usec_t time;
- Iterator i;
- int r;
+static int neighbor_compare_func(const void *a, const void *b) {
+ const sd_lldp_neighbor * const*x = a, * const *y = b;
- assert(lldp);
- assert(lldp_file);
+ return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
+}
- r = fopen_temporary(lldp_file, &f, &temp_path);
- if (r < 0)
- goto fail;
-
- fchmod(fileno(f), 0644);
-
- HASHMAP_FOREACH(c, lldp->neighbour_mib, i) {
- LIST_FOREACH(port, p, c->ports) {
- _cleanup_free_ char *s = NULL;
- char *k, *t;
-
- r = sd_lldp_packet_read_chassis_id(p->packet, &type, &mac, &length);
- if (r < 0)
- continue;
-
- sprintf(buf, "'_Chassis=%02x:%02x:%02x:%02x:%02x:%02x' '_CType=%d' ",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type);
-
- s = strdup(buf);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = sd_lldp_packet_read_port_id(p->packet, &type, &port_id, &length);
- if (r < 0)
- continue;
-
- if (type != LLDP_PORT_SUBTYPE_MAC_ADDRESS) {
- k = strndup((char *) port_id, length -1);
- if (!k) {
- r = -ENOMEM;
- goto fail;
- }
-
- sprintf(buf, "'_Port=%s' '_PType=%d' ", k , type);
- free(k);
- } else {
- mac = port_id;
- sprintf(buf, "'_Port=%02x:%02x:%02x:%02x:%02x:%02x' '_PType=%d' ",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type);
- }
-
- k = strappend(s, buf);
- if (!k) {
- r = -ENOMEM;
- goto fail;
- }
-
- free(s);
- s = k;
-
- time = now(clock_boottime_or_monotonic());
-
- /* Don't write expired packets */
- if (time - p->until <= 0)
- continue;
-
- sprintf(buf, "'_TTL="USEC_FMT"' ", p->until);
-
- k = strappend(s, buf);
- if (!k) {
- r = -ENOMEM;
- goto fail;
- }
-
- free(s);
- s = k;
-
- r = sd_lldp_packet_read_system_name(p->packet, &k, &length);
- if (r < 0)
- k = strappend(s, "'_NAME=N/A' ");
- else {
- t = strndup(k, length);
- if (!t) {
- r = -ENOMEM;
- goto fail;
- }
-
- k = strjoin(s, "'_NAME=", t, "' ", NULL);
- free(t);
- }
-
- if (!k) {
- r = -ENOMEM;
- goto fail;
- }
-
- free(s);
- s = k;
-
- (void) sd_lldp_packet_read_system_capability(p->packet, &data);
-
- sprintf(buf, "'_CAP=%x'", data);
-
- k = strappend(s, buf);
- if (!k) {
- r = -ENOMEM;
- goto fail;
- }
-
- free(s);
- s = k;
-
- fprintf(f, "%s\n", s);
- }
- }
+static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
+ sd_lldp *lldp = userdata;
+ int r, q;
- r = fflush_and_check(f);
+ r = lldp_make_space(lldp, 0);
if (r < 0)
- goto fail;
+ return log_lldp_errno(r, "Failed to make space: %m");
- if (rename(temp_path, lldp_file) < 0) {
- r = -errno;
- goto fail;
- }
+ q = lldp_start_timer(lldp, NULL);
+ if (q < 0)
+ return log_lldp_errno(q, "Failed to restart timer: %m");
return 0;
-
- fail:
- if (temp_path)
- (void) unlink(temp_path);
-
- return log_error_errno(r, "Failed to save lldp data %s: %m", lldp_file);
}
-int sd_lldp_start(sd_lldp *lldp) {
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
+ sd_lldp_neighbor *n;
int r;
- assert_return(lldp, -EINVAL);
- assert_return(lldp->port, -EINVAL);
+ assert(lldp);
- lldp->port->status = LLDP_PORT_STATUS_ENABLED;
+ if (neighbor)
+ lldp_neighbor_start_ttl(neighbor);
- lldp_set_state(lldp, LLDP_AGENT_RX_LLDP_INITIALIZE);
+ n = prioq_peek(lldp->neighbor_by_expiry);
+ if (!n) {
- r = lldp_port_start(lldp->port);
- if (r < 0) {
- log_lldp("Failed to start Port : %s , %s",
- lldp->port->ifname,
- strerror(-r));
+ if (lldp->timer_event_source)
+ return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF);
- lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL);
-
- return r;
+ return 0;
}
- lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME);
-
- return 0;
-}
-
-int sd_lldp_stop(sd_lldp *lldp) {
- int r;
+ if (lldp->timer_event_source) {
+ r = sd_event_source_set_time(lldp->timer_event_source, n->until);
+ if (r < 0)
+ return r;
- assert_return(lldp, -EINVAL);
- assert_return(lldp->port, -EINVAL);
+ return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT);
+ }
- lldp->port->status = LLDP_PORT_STATUS_DISABLED;
+ if (!lldp->event)
+ return 0;
- r = lldp_port_stop(lldp->port);
+ r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp);
if (r < 0)
return r;
- lldp_mib_objects_flush(lldp);
+ r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority);
+ if (r < 0)
+ return r;
+ (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer");
return 0;
}
-int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority) {
- int r;
+_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
+ sd_lldp_neighbor **l = NULL, *n;
+ Iterator i;
+ int k = 0, r;
assert_return(lldp, -EINVAL);
- assert_return(!lldp->port->event, -EBUSY);
+ assert_return(ret, -EINVAL);
- if (event)
- lldp->port->event = sd_event_ref(event);
- else {
- r = sd_event_default(&lldp->port->event);
- if (r < 0)
- return r;
+ if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */
+ *ret = NULL;
+ return 0;
}
- lldp->port->event_priority = priority;
+ l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id));
+ if (!l)
+ return -ENOMEM;
- return 0;
-}
+ r = lldp_start_timer(lldp, NULL);
+ if (r < 0) {
+ free(l);
+ return r;
+ }
-int sd_lldp_detach_event(sd_lldp *lldp) {
+ HASHMAP_FOREACH(n, lldp->neighbor_by_id, i)
+ l[k++] = sd_lldp_neighbor_ref(n);
- assert_return(lldp, -EINVAL);
+ assert((size_t) k == hashmap_size(lldp->neighbor_by_id));
- lldp->port->event = sd_event_unref(lldp->port->event);
+ /* Return things in a stable order */
+ qsort(l, k, sizeof(sd_lldp_neighbor*), neighbor_compare_func);
+ *ret = l;
- return 0;
+ return k;
}
-int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata) {
+_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) {
assert_return(lldp, -EINVAL);
+ assert_return(m <= 0, -EINVAL);
- lldp->cb = cb;
- lldp->userdata = userdata;
+ lldp->neighbors_max = m;
+ lldp_make_space(lldp, 0);
return 0;
}
-sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
-
- if (!lldp)
- return NULL;
-
- /* Drop all packets */
- lldp_mib_objects_flush(lldp);
-
- lldp_port_free(lldp->port);
-
- hashmap_free(lldp->neighbour_mib);
- 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_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
- int r;
-
- assert_return(ret, -EINVAL);
- assert_return(ifindex > 0, -EINVAL);
- assert_return(ifname, -EINVAL);
- assert_return(mac, -EINVAL);
-
- lldp = new0(sd_lldp, 1);
- if (!lldp)
- return -ENOMEM;
-
- r = lldp_port_new(ifindex, ifname, mac, lldp, &lldp->port);
- if (r < 0)
- return r;
-
- lldp->neighbour_mib = hashmap_new(&chassis_id_hash_ops);
- if (!lldp->neighbour_mib)
- return -ENOMEM;
-
- r = prioq_ensure_allocated(&lldp->by_expiry,
- ttl_expiry_item_prioq_compare_func);
- if (r < 0)
- return r;
-
- lldp->rx_state = LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL;
+_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) {
+ assert_return(lldp, -EINVAL);
+ assert_return(mask != 0, -EINVAL);
- *ret = lldp;
- lldp = NULL;
+ lldp->capability_mask = mask;
return 0;
}
-int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs) {
- lldp_neighbour_port *p;
- lldp_chassis *c;
- Iterator iter;
- unsigned count = 0, i;
-
+_public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) {
assert_return(lldp, -EINVAL);
- assert_return(tlvs, -EINVAL);
- HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) {
- LIST_FOREACH(port, p, c->ports)
- count++;
- }
+ /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
+ * that our own can be filtered out here. */
- if (!count) {
- *tlvs = NULL;
+ if (!addr) {
+ zero(lldp->filter_address);
return 0;
}
- *tlvs = new(sd_lldp_packet *, count);
- if (!*tlvs)
- return -ENOMEM;
-
- i = 0;
- HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) {
- LIST_FOREACH(port, p, c->ports)
- (*tlvs)[i++] = sd_lldp_packet_ref(p->packet);
- }
-
- return count;
+ lldp->filter_address = *addr;
+ return 0;
}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index bae6a49fe6..fb4ef55673 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -166,7 +166,7 @@ int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr) {
}
-int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority) {
+int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority) {
int r;
assert_return(nd, -EINVAL);
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index b8490073dd..1aae2253c0 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -22,6 +22,7 @@
#include <net/ethernet.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include "sd-event.h"
#include "sd-lldp.h"
@@ -29,8 +30,6 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "lldp-network.h"
-#include "lldp-tlv.h"
-#include "lldp.h"
#include "macro.h"
#include "string-util.h"
@@ -38,211 +37,8 @@
#define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
#define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
-static int test_fd[2];
-
-static struct ether_addr mac_addr = {
- .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
-};
-
-static int lldp_build_tlv_packet(tlv_packet **ret) {
- _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),
- };
-
- /* Append Ethernet header */
- memcpy(&ether.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
- memcpy(&ether.ether_shost, &mac_addr, ETHER_ADDR_LEN);
-
- assert_se(tlv_packet_new(&m) >= 0);
-
- assert_se(tlv_packet_append_bytes(m, &ether, sizeof(struct ether_header)) >= 0);
-
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
-
- assert_se(tlv_packet_append_u8(m, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS) >= 0);
- assert_se(tlv_packet_append_bytes(m, &mac_addr, ETHER_ADDR_LEN) >= 0);
-
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- /* port name */
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0);
-
- assert_se(tlv_packet_append_u8(m, LLDP_PORT_SUBTYPE_INTERFACE_NAME) >= 0);
- assert_se(tlv_packet_append_bytes(m, TEST_LLDP_PORT, strlen(TEST_LLDP_PORT) + 1) >= 0);
-
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- /* ttl */
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0);
-
- assert_se(tlv_packet_append_u16(m, 170) >= 0);
-
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- /* system name */
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
-
- assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_NAME,
- strlen(TEST_LLDP_TYPE_SYSTEM_NAME)) >= 0);
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- /* system descrition */
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
-
- assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC,
- strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0);
-
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- /* Mark end of packet */
- assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_END) >= 0);
- assert_se(lldp_tlv_packet_close_container(m) >= 0);
-
- *ret = m;
-
- m = NULL;
-
- return 0;
-}
-
-static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) {
- uint8_t *p, subtype;
- uint16_t length;
-
- assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
- assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
-
- switch (subtype) {
- case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
-
- *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS;
- assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0);
-
- assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0);
-
- break;
- default:
- assert_not_reached("Unhandled option");
- }
-
- assert_se(lldp_tlv_packet_exit_container(m) >= 0);
-
- return 0;
-}
-
-static int lldp_parse_port_id_tlv(tlv_packet *m) {
- _cleanup_free_ char *p = NULL;
- char *str = NULL;
- uint16_t length;
- uint8_t subtype;
-
- assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
-
- assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
-
- switch (subtype) {
- case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
- assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
-
- p = strndup(str, length-1);
- assert_se(p);
-
- assert_se(streq(p, TEST_LLDP_PORT) == 1);
- break;
- default:
- assert_not_reached("Unhandled option");
- }
-
- assert_se(lldp_tlv_packet_exit_container(m) >= 0);
-
- return 0;
-}
-
-static int lldp_parse_system_name_tlv(tlv_packet *m) {
- _cleanup_free_ char *p = NULL;
- char *str = NULL;
- uint16_t length;
-
- assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
- assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
-
- p = strndup(str, length);
- assert_se(p);
-
- assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
-
- assert_se(lldp_tlv_packet_exit_container(m) >= 0);
-
- return 1;
-}
-
-static int lldp_parse_system_desc_tlv(tlv_packet *m) {
- _cleanup_free_ char *p = NULL;
- char *str = NULL;
- uint16_t length;
-
- assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
- assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
-
- p = strndup(str, length);
- assert_se(p);
-
- assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
-
- assert_se(lldp_tlv_packet_exit_container(m) >= 0);
-
- return 0;
-}
-
-static int lldp_parse_ttl_tlv(tlv_packet *m) {
- uint16_t ttl;
-
- assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
- assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
-
- assert_se(ttl == 170);
-
- assert_se(lldp_tlv_packet_exit_container(m) >= 0);
-
- return 0;
-}
-
-static int lldp_get_destination_type(tlv_packet *m) {
- int dest;
-
- assert_se(sd_lldp_packet_get_destination_type(m, &dest) >= 0);
- assert_se(dest == SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE);
-
- return 0;
-}
-
-static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
- uint8_t subtype;
-
- assert_se(tlv_packet_parse_pdu(m, len) >= 0);
- assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0);
- assert_se(lldp_parse_port_id_tlv(m) >= 0);
- assert_se(lldp_parse_system_name_tlv(m) >= 0);
- assert_se(lldp_parse_ttl_tlv(m) >= 0);
- assert_se(lldp_parse_system_desc_tlv(m) >= 0);
-
- assert_se(lldp_get_destination_type(m) >= 0);
-
- return 0;
-}
-
-static void test_parser(void) {
- _cleanup_(sd_lldp_packet_unrefp) tlv_packet *tlv = NULL;
-
- /* form a packet */
- lldp_build_tlv_packet(&tlv);
- /* parse the packet */
- tlv_packet_parse_pdu(tlv, tlv->length);
- /* verify */
- lldp_parse_tlv_packet(tlv, tlv->length);
-}
+static int test_fd[2] = { -1, -1 };
+static int lldp_handler_calls;
int lldp_network_bind_raw_socket(int ifindex) {
if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
@@ -251,28 +47,27 @@ int lldp_network_bind_raw_socket(int ifindex) {
return test_fd[0];
}
-static int lldp_handler_calls;
-static void lldp_handler (sd_lldp *lldp, int event, void *userdata) {
+static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
lldp_handler_calls++;
}
-static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_cb_t cb, void *cb_data) {
+static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) {
int r;
- r = sd_lldp_new(42, "dummy", &mac_addr, lldp);
- if (r)
+ r = sd_lldp_new(lldp, 42);
+ if (r < 0)
return r;
r = sd_lldp_attach_event(*lldp, e, 0);
- if (r)
+ if (r < 0)
return r;
r = sd_lldp_set_callback(*lldp, cb, cb_data);
- if (r)
+ if (r < 0)
return r;
r = sd_lldp_start(*lldp);
- if (r)
+ if (r < 0)
return r;
return 0;
@@ -282,11 +77,11 @@ static int stop_lldp(sd_lldp *lldp) {
int r;
r = sd_lldp_stop(lldp);
- if (r)
+ if (r < 0)
return r;
r = sd_lldp_detach_event(lldp);
- if (r)
+ if (r < 0)
return r;
sd_lldp_unref(lldp);
@@ -296,13 +91,8 @@ static int stop_lldp(sd_lldp *lldp) {
}
static void test_receive_basic_packet(sd_event *e) {
- sd_lldp *lldp;
- sd_lldp_packet **packets;
- uint8_t type, *data;
- uint16_t length, ttl;
- int dest_type;
- char *str;
- uint8_t frame[] = {
+
+ static const uint8_t frame[] = {
/* Ethernet header */
0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
@@ -319,51 +109,53 @@ static void test_receive_basic_packet(sd_event *e) {
0x00, 0x00 /* End Of LLDPDU */
};
+ sd_lldp *lldp;
+ sd_lldp_neighbor **neighbors;
+ uint8_t type;
+ const void *data;
+ uint16_t ttl;
+ size_t length;
+ const char *str;
+
lldp_handler_calls = 0;
assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
sd_event_run(e, 0);
assert_se(lldp_handler_calls == 1);
- assert_se(sd_lldp_get_packets(lldp, &packets) == 1);
+ assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
- assert_se(sd_lldp_packet_read_chassis_id(packets[0], &type, &data, &length) == 0);
- assert_se(type == LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
+ assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0);
+ assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
assert_se(length == ETH_ALEN);
assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN));
- assert_se(sd_lldp_packet_read_port_id(packets[0], &type, &data, &length) == 0);
- assert_se(type == LLDP_PORT_SUBTYPE_INTERFACE_NAME);
+ assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0);
+ assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME);
assert_se(length == 3);
assert_se(strneq((char *) data, "1/3", 3));
- assert_se(sd_lldp_packet_read_port_description(packets[0], &str, &length) == 0);
- assert_se(length == 4);
- assert_se(strneq(str, "Port", 4));
+ assert_se(sd_lldp_neighbor_get_port_description(neighbors[0], &str) == 0);
+ assert_se(streq(str, "Port"));
- assert_se(sd_lldp_packet_read_system_name(packets[0], &str, &length) == 0);
- assert_se(length == 3);
- assert_se(strneq(str, "SYS", 3));
+ assert_se(sd_lldp_neighbor_get_system_name(neighbors[0], &str) == 0);
+ assert_se(streq(str, "SYS"));
- assert_se(sd_lldp_packet_read_system_description(packets[0], &str, &length) == 0);
- assert_se(length == 4); /* This is the real length in the TLV packet */
- assert_se(strneq(str, "foo", 3));
+ assert_se(sd_lldp_neighbor_get_system_description(neighbors[0], &str) == 0);
+ assert_se(streq(str, "foo"));
- assert_se(sd_lldp_packet_read_ttl(packets[0], &ttl) == 0);
+ assert_se(sd_lldp_neighbor_get_ttl(neighbors[0], &ttl) == 0);
assert_se(ttl == 120);
- assert_se(sd_lldp_packet_get_destination_type(packets[0], &dest_type) == 0);
- assert_se(dest_type == SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE);
-
- sd_lldp_packet_unref(packets[0]);
- free(packets);
+ sd_lldp_neighbor_unref(neighbors[0]);
+ free(neighbors);
assert_se(stop_lldp(lldp) == 0);
}
static void test_receive_incomplete_packet(sd_event *e) {
sd_lldp *lldp;
- sd_lldp_packet **packets;
+ sd_lldp_neighbor **neighbors;
uint8_t frame[] = {
/* Ethernet header */
0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
@@ -383,18 +175,14 @@ static void test_receive_incomplete_packet(sd_event *e) {
assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
sd_event_run(e, 0);
assert_se(lldp_handler_calls == 0);
- assert_se(sd_lldp_get_packets(lldp, &packets) == 0);
+ assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 0);
assert_se(stop_lldp(lldp) == 0);
}
static void test_receive_oui_packet(sd_event *e) {
sd_lldp *lldp;
- sd_lldp_packet **packets;
- uint32_t id32;
- uint16_t id16, len;
- uint8_t flags;
- char *str;
+ sd_lldp_neighbor **neighbors;
uint8_t frame[] = {
/* Ethernet header */
0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/
@@ -426,29 +214,30 @@ static void test_receive_oui_packet(sd_event *e) {
assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
sd_event_run(e, 0);
assert_se(lldp_handler_calls == 1);
- assert_se(sd_lldp_get_packets(lldp, &packets) == 1);
-
- assert_se(sd_lldp_packet_read_port_vlan_id(packets[0], &id16) == 0);
- assert_se(id16 == 0x1234);
-
- assert_se(sd_lldp_packet_read_port_protocol_vlan_id(packets[0], &flags, &id16) == 0);
- assert_se(flags == 1);
- assert_se(id16 == 0x7788);
-
- assert_se(sd_lldp_packet_read_vlan_name(packets[0], &id16, &str, &len) == 0);
- assert_se(id16 == 0x1234);
- assert_se(len == 6);
- assert_se(strneq(str, "Vlan51", 6));
-
- assert_se(sd_lldp_packet_read_management_vid(packets[0], &id16) == 0);
- assert_se(id16 == 0x0102);
-
- assert_se(sd_lldp_packet_read_link_aggregation(packets[0], &flags, &id32) == 0);
- assert_se(flags == 1);
- assert_se(id32 == 0x00140012);
-
- sd_lldp_packet_unref(packets[0]);
- free(packets);
+ assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
+
+ assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
+ assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
+ assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
+
+ sd_lldp_neighbor_unref(neighbors[0]);
+ free(neighbors);
assert_se(stop_lldp(lldp) == 0);
}
@@ -456,7 +245,7 @@ static void test_receive_oui_packet(sd_event *e) {
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
- test_parser();
+ log_set_max_level(LOG_DEBUG);
/* LLDP reception tests */
assert_se(sd_event_new(&e) == 0);
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 7c81e7a25d..5964a01c4f 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -198,7 +198,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
else if (type == SD_BUS_TYPE_DICT_ENTRY)
fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
- level ++;
+ level++;
continue;
}
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index c2e913f62a..b8958ec7bb 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1131,10 +1131,7 @@ _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
assert_return(!m->sealed, -EPERM);
assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
- else
- m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
return 0;
}
@@ -1143,10 +1140,7 @@ _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
- else
- m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
return 0;
}
@@ -1155,10 +1149,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
- else
- m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
return 0;
}
@@ -1198,7 +1189,7 @@ struct bus_body_part *message_append_part(sd_bus_message *m) {
part->memfd = -1;
m->body_end = part;
- m->n_body_parts ++;
+ m->n_body_parts++;
return part;
}
@@ -1643,7 +1634,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
}
if (type == SD_BUS_TYPE_UNIX_FD)
- m->n_fds ++;
+ m->n_fds++;
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index++;
@@ -2387,9 +2378,9 @@ int bus_message_append_ap(
t = types;
if (n_array != (unsigned) -1)
- n_array --;
+ n_array--;
else {
- types ++;
+ types++;
n_struct--;
}
@@ -3866,7 +3857,7 @@ static int build_struct_offsets(
if (r < 0)
return r;
if (r == 0 && p[n] != 0) /* except the last item */
- n_variable ++;
+ n_variable++;
n_total++;
p += n;
@@ -4466,9 +4457,9 @@ static int message_read_ap(
t = types;
if (n_array != (unsigned) -1)
- n_array --;
+ n_array--;
else {
- types ++;
+ types++;
n_struct--;
}
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 1f285ae8a6..9bd07ffcab 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -145,7 +145,7 @@ static int add_enumerated_to_set(
continue;
}
- if (!object_path_is_valid(*k)){
+ if (!object_path_is_valid(*k)) {
free(*k);
r = -EINVAL;
continue;
@@ -337,7 +337,7 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
if (cap == 0)
cap = CAP_SYS_ADMIN;
else
- cap --;
+ cap--;
r = sd_bus_query_sender_privilege(m, cap);
if (r < 0)
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index a8c74011bf..8e9074c7df 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -206,7 +206,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
assert(slot->n_ref > 0);
if (slot->n_ref > 1) {
- slot->n_ref --;
+ slot->n_ref--;
return NULL;
}
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 13d0aef4b5..f1e2a06050 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -60,7 +60,7 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
i->iov_base = NULL;
i->iov_len = 0;
- (*idx) ++;
+ (*idx)++;
}
}
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index bdbf7d4a85..1f436fe560 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -129,7 +129,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
assert(track->n_ref > 0);
if (track->n_ref > 1) {
- track->n_ref --;
+ track->n_ref--;
return NULL;
}
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 772ab62d5b..56bd5863a8 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -62,15 +62,6 @@ static bool arg_allow_interactive_authorization = true;
static bool arg_augment_creds = true;
static usec_t arg_timeout = 0;
-static void pager_open_if_enabled(void) {
-
- /* Cache result before we open the pager */
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
@@ -95,7 +86,7 @@ static int list_bus_names(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to list names: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
names = hashmap_new(&string_hash_ops);
if (!names)
@@ -289,7 +280,7 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
static void print_tree(const char *prefix, char **l) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
prefix = strempty(prefix);
@@ -409,7 +400,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
p = NULL;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
l = set_get_strv(done);
if (!l)
@@ -438,7 +429,7 @@ static int tree(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to get name list: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
STRV_FOREACH(i, names) {
int q;
@@ -468,7 +459,7 @@ static int tree(sd_bus *bus, char **argv) {
printf("\n");
if (argv[2]) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
@@ -992,7 +983,7 @@ static int introspect(sd_bus *bus, char **argv) {
return bus_log_parse_error(r);
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
name_width = strlen("NAME");
type_width = strlen("TYPE");
@@ -1559,7 +1550,7 @@ static int call(sd_bus *bus, char *argv[]) {
if (r == 0 && !arg_quiet) {
if (arg_verbose) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, 0);
if (r < 0)
@@ -1614,7 +1605,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
return bus_log_parse_error(r);
if (arg_verbose) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
if (r < 0)
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index c6f626d8aa..862f26aad7 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -313,10 +313,7 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (b)
- bus->creds_mask |= mask;
- else
- bus->creds_mask &= ~mask;
+ SET_FLAG(bus->creds_mask, mask, b);
/* The well knowns we need unconditionally, so that matches can work */
bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
@@ -530,7 +527,7 @@ static void skip_address_key(const char **p) {
*p += strcspn(*p, ",");
if (**p == ',')
- (*p) ++;
+ (*p)++;
}
static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
@@ -695,7 +692,7 @@ static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
goto fail;
}
- (*p) ++;
+ (*p)++;
if (ul >= n_argv) {
if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
@@ -1668,7 +1665,7 @@ static int dispatch_wqueue(sd_bus *bus) {
* it got full, then all bets are off
* anyway. */
- bus->wqueue_size --;
+ bus->wqueue_size--;
sd_bus_message_unref(bus->wqueue[0]);
memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
bus->windex = 0;
@@ -1717,7 +1714,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
/* Dispatch a queued message */
*m = bus->rqueue[0];
- bus->rqueue_size --;
+ bus->rqueue_size--;
memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
return 1;
}
@@ -1809,7 +1806,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
return -ENOMEM;
- bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m);
+ bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
}
finish:
@@ -2257,7 +2254,7 @@ static int process_timeout(sd_bus *bus) {
slot = container_of(c, sd_bus_slot, reply_callback);
- bus->iteration_counter ++;
+ bus->iteration_counter++;
bus->current_message = m;
bus->current_slot = sd_bus_slot_ref(slot);
diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c
index 46d18abd29..66a3874f10 100644
--- a/src/libsystemd/sd-bus/test-bus-error.c
+++ b/src/libsystemd/sd-bus/test-bus-error.c
@@ -146,7 +146,7 @@ static void dump_mapping_table(void) {
}
printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
- m ++;
+ m++;
}
printf("---------------------------\n");
}
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 4e50b61979..bd1c7f15ff 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -465,7 +465,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
have_pid = pid != 0 && pid != getpid();
if (n_fds > 0 || have_pid) {
- /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
+ /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
msghdr.msg_controllen =
(n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
(have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0);
diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h
index b96441de56..ab222e27de 100644
--- a/src/libsystemd/sd-device/device-internal.h
+++ b/src/libsystemd/sd-device/device-internal.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -18,8 +20,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "hashmap.h"
#include "set.h"
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index f2af3ab3ae..9082d377f4 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -890,7 +890,7 @@ void device_cleanup_tags(sd_device *device) {
set_free_free(device->tags);
device->tags = NULL;
device->property_tags_outdated = true;
- device->tags_generation ++;
+ device->tags_generation++;
}
void device_cleanup_devlinks(sd_device *device) {
@@ -899,7 +899,7 @@ void device_cleanup_devlinks(sd_device *device) {
set_free_free(device->devlinks);
device->devlinks = NULL;
device->property_devlinks_outdated = true;
- device->devlinks_generation ++;
+ device->devlinks_generation++;
}
void device_remove_tag(sd_device *device, const char *tag) {
@@ -908,7 +908,7 @@ void device_remove_tag(sd_device *device, const char *tag) {
free(set_remove(device->tags, tag));
device->property_tags_outdated = true;
- device->tags_generation ++;
+ device->tags_generation++;
}
static int device_tag(sd_device *device, const char *tag, bool add) {
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 9633e46ce0..8657e61cd9 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -136,7 +136,7 @@ int device_add_property_aux(sd_device *device, const char *_key, const char *_va
}
if (!db) {
- device->properties_generation ++;
+ device->properties_generation++;
device->properties_buf_outdated = true;
}
@@ -309,7 +309,7 @@ _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *s
if (name[len] == '/')
name[len] = '!';
- len ++;
+ len++;
}
syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name);
@@ -669,7 +669,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
return -EINVAL;
sysname[0] = '\0';
- sysname ++;
+ sysname++;
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
}
@@ -971,7 +971,7 @@ static int device_set_sysname(sd_device *device) {
pos = strrchr(device->devpath, '/');
if (!pos)
return -EINVAL;
- pos ++;
+ pos++;
/* devpath is not a root directory */
if (*pos == '\0' || pos <= device->devpath)
@@ -986,7 +986,7 @@ static int device_set_sysname(sd_device *device) {
if (sysname[len] == '!')
sysname[len] = '/';
- len ++;
+ len++;
}
/* trailing number */
@@ -1066,7 +1066,7 @@ int device_add_tag(sd_device *device, const char *tag) {
if (r < 0)
return r;
- device->tags_generation ++;
+ device->tags_generation++;
device->property_tags_outdated = true;
return 0;
@@ -1086,7 +1086,7 @@ int device_add_devlink(sd_device *device, const char *devlink) {
if (r < 0)
return r;
- device->devlinks_generation ++;
+ device->devlinks_generation++;
device->property_devlinks_outdated = true;
return 0;
@@ -1397,7 +1397,7 @@ _public_ const char *sd_device_get_tag_first(sd_device *device) {
device->tags_iterator_generation = device->tags_generation;
device->tags_iterator = ITERATOR_FIRST;
- set_iterate(device->tags, &device->tags_iterator, &v);
+ (void) set_iterate(device->tags, &device->tags_iterator, &v);
return v;
}
@@ -1411,7 +1411,7 @@ _public_ const char *sd_device_get_tag_next(sd_device *device) {
if (device->tags_iterator_generation != device->tags_generation)
return NULL;
- set_iterate(device->tags, &device->tags_iterator, &v);
+ (void) set_iterate(device->tags, &device->tags_iterator, &v);
return v;
}
@@ -1425,7 +1425,7 @@ _public_ const char *sd_device_get_devlink_first(sd_device *device) {
device->devlinks_iterator_generation = device->devlinks_generation;
device->devlinks_iterator = ITERATOR_FIRST;
- set_iterate(device->devlinks, &device->devlinks_iterator, &v);
+ (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
return v;
}
@@ -1439,7 +1439,7 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) {
if (device->devlinks_iterator_generation != device->devlinks_generation)
return NULL;
- set_iterate(device->devlinks, &device->devlinks_iterator, &v);
+ (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
return v;
}
@@ -1606,7 +1606,7 @@ _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
device->sysattrs_iterator = ITERATOR_FIRST;
- set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
+ (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
return v;
}
@@ -1618,7 +1618,7 @@ _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
if (!device->sysattrs_read)
return NULL;
- set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
+ (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
return v;
}
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 2b46a1ff06..841358ed03 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -951,7 +951,7 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
sd_event_ref(e);
LIST_PREPEND(sources, e->sources, s);
- e->n_sources ++;
+ e->n_sources++;
return s;
}
@@ -1235,7 +1235,7 @@ _public_ int sd_event_add_child(
return r;
}
- e->n_enabled_child_sources ++;
+ e->n_enabled_child_sources++;
r = event_make_signal_data(e, SIGCHLD, NULL);
if (r < 0) {
diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c
index daea4126f8..fd31588b8f 100644
--- a/src/libsystemd/sd-event/test-event.c
+++ b/src/libsystemd/sd-event/test-event.c
@@ -291,7 +291,7 @@ static int n_rtqueue = 0;
static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
last_rtqueue_sigval = si->ssi_int;
- n_rtqueue ++;
+ n_rtqueue++;
return 0;
}
diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h
index 13fddfc8ad..8ffb5e5c74 100644
--- a/src/libsystemd/sd-hwdb/hwdb-internal.h
+++ b/src/libsystemd/sd-hwdb/hwdb-internal.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -16,7 +18,6 @@
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 "sparse-endian.h"
#include "util.h"
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 3a866fdafe..f56798674c 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -34,7 +34,7 @@
#include "util.h"
#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
-#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
+#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
@@ -107,10 +107,7 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
m->hdr->nlmsg_type == RTM_GETNEIGH,
-EINVAL);
- if (dump)
- m->hdr->nlmsg_flags |= NLM_F_DUMP;
- else
- m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
+ SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
return 0;
}
@@ -467,7 +464,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
if (r < 0)
return r;
- m->containers[m->n_containers ++].offset = r;
+ m->containers[m->n_containers++].offset = r;
return 0;
}
@@ -498,7 +495,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
if (r < 0)
return r;
- m->containers[m->n_containers ++].offset = r;
+ m->containers[m->n_containers++].offset = r;
return 0;
}
@@ -510,7 +507,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m) {
assert_return(m->n_containers > 0, -EINVAL);
m->containers[m->n_containers].type_system = NULL;
- m->n_containers --;
+ m->n_containers--;
return 0;
}
@@ -528,7 +525,7 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t
attribute = &m->containers[m->n_containers].attributes[type];
- if(!attribute->offset)
+ if (!attribute->offset)
return -ENODATA;
rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
@@ -735,7 +732,7 @@ static int netlink_container_parse(sd_netlink_message *m,
_cleanup_free_ struct netlink_attribute *attributes = NULL;
attributes = new0(struct netlink_attribute, count);
- if(!attributes)
+ if (!attributes)
return -ENOMEM;
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
@@ -842,7 +839,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
else
size = (size_t)r;
- m->n_containers ++;
+ m->n_containers++;
r = netlink_container_parse(m,
&m->containers[m->n_containers],
@@ -850,7 +847,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
container,
size);
if (r < 0) {
- m->n_containers --;
+ m->n_containers--;
return r;
}
@@ -867,7 +864,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes);
m->containers[m->n_containers].type_system = NULL;
- m->n_containers --;
+ m->n_containers--;
return 0;
}
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 590fc53fc7..c165fa3359 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -82,7 +82,7 @@ static int broadcast_groups_get(sd_netlink *nl) {
return r;
for (i = 0; i < len; i++) {
- for (j = 0; j < sizeof(uint32_t) * 8; j ++) {
+ for (j = 0; j < sizeof(uint32_t) * 8; j++) {
uint32_t offset;
unsigned group;
@@ -168,7 +168,7 @@ int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
n_ref = broadcast_group_get_ref(nl, group);
- n_ref ++;
+ n_ref++;
r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
if (r < 0)
@@ -216,7 +216,7 @@ int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
assert(n_ref > 0);
- n_ref --;
+ n_ref--;
r = broadcast_group_set_ref(nl, group, n_ref);
if (r < 0)
@@ -444,14 +444,14 @@ int socket_read_message(sd_netlink *rtnl) {
if (r < 0)
return r;
- rtnl->rqueue[rtnl->rqueue_size ++] = first;
+ rtnl->rqueue[rtnl->rqueue_size++] = first;
first = NULL;
if (multi_part && (i < rtnl->rqueue_partial_size)) {
/* remove the message form the partial read queue */
memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1));
- rtnl->rqueue_partial_size --;
+ rtnl->rqueue_partial_size--;
}
return 1;
@@ -465,7 +465,7 @@ int socket_read_message(sd_netlink *rtnl) {
if (r < 0)
return r;
- rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
+ rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = first;
}
first = NULL;
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 090552f576..255526bf32 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -616,7 +616,7 @@ int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) {
return 0;
}
-int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type) {
+int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type) {
struct ifinfomsg *ifi;
assert_return(m, -EINVAL);
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index 4833815b43..91701405a5 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -279,7 +279,7 @@ static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
/* Dispatch a queued message */
*message = rtnl->rqueue[0];
- rtnl->rqueue_size --;
+ rtnl->rqueue_size--;
memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size);
return 1;
@@ -774,7 +774,7 @@ static int prepare_callback(sd_event_source *s, void *userdata) {
return 1;
}
-int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int priority) {
+int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int64_t priority) {
int r;
assert_return(rtnl, -EINVAL);
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index de5e0ffc8f..f9b6787187 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -234,7 +234,7 @@ static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
int *counter = userdata;
int r;
- (*counter) --;
+ (*counter)--;
r = sd_netlink_message_get_errno(m);
@@ -276,10 +276,10 @@ static void test_pipe(int ifindex) {
assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
- counter ++;
+ counter++;
assert_se(sd_netlink_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
- counter ++;
+ counter++;
assert_se(sd_netlink_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
while (counter > 0) {
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 62051992ef..f8e18f23fd 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -31,6 +31,7 @@
#include "fs-util.h"
#include "macro.h"
#include "parse-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -102,16 +103,16 @@ _public_ int sd_network_get_route_domains(char ***ret) {
}
static int network_link_get_string(int ifindex, const char *field, char **ret) {
- _cleanup_free_ char *s = NULL, *p = NULL;
+ char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
+ _cleanup_free_ char *s = NULL;
int r;
assert_return(ifindex > 0, -EINVAL);
assert_return(ret, -EINVAL);
- if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0)
- return -ENOMEM;
+ xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
- r = parse_env_file(p, NEWLINE, field, &s, NULL);
+ r = parse_env_file(path, NEWLINE, field, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -126,17 +127,16 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) {
}
static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
- _cleanup_free_ char *p = NULL, *s = NULL;
+ char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
_cleanup_strv_free_ char **a = NULL;
+ _cleanup_free_ char *s = 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);
+ xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
+ r = parse_env_file(path, NEWLINE, key, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -187,32 +187,7 @@ _public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char
return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
}
-_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
- _cleanup_free_ char *s = NULL, *p = NULL;
- size_t size;
- int r;
-
- assert_return(ifindex > 0, -EINVAL);
- assert_return(lldp, -EINVAL);
-
- if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
- return -ENOMEM;
-
- r = read_full_file(p, &s, &size);
- if (r == -ENOENT)
- return -ENODATA;
- if (r < 0)
- return r;
- if (size <= 0)
- return -ENODATA;
-
- *lldp = s;
- s = NULL;
-
- return 0;
-}
-
-int sd_network_link_get_timezone(int ifindex, char **ret) {
+_public_ int sd_network_link_get_timezone(int ifindex, char **ret) {
return network_link_get_string(ifindex, "TIMEZONE", ret);
}
@@ -232,12 +207,64 @@ _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_to(int ifindex, char ***ret) {
- return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
+static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) {
+ char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
+ _cleanup_free_ int *ifis = NULL;
+ _cleanup_free_ char *s = NULL;
+ size_t allocated = 0, c = 0;
+ const char *x;
+ int r;
+
+ assert_return(ifindex > 0, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
+ r = parse_env_file(path, NEWLINE, key, &s, NULL);
+ if (r == -ENOENT)
+ return -ENODATA;
+ if (r < 0)
+ return r;
+ if (isempty(s)) {
+ *ret = NULL;
+ return 0;
+ }
+
+ x = s;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&x, &word, NULL, 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ r = parse_ifindex(word, &ifindex);
+ if (r < 0)
+ return r;
+
+ if (!GREEDY_REALLOC(ifis, allocated, c + 1))
+ return -ENOMEM;
+
+ ifis[c++] = ifindex;
+ }
+
+ if (!GREEDY_REALLOC(ifis, allocated, c + 1))
+ return -ENOMEM;
+ ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice*/
+
+ *ret = ifis;
+ ifis = NULL;
+
+ return c;
+}
+
+_public_ int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) {
+ return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret);
}
-_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
- return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
+_public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) {
+ return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret);
}
static inline int MONITOR_TO_FD(sd_network_monitor *m) {
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 480f1ad065..b7aec1f20a 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -89,7 +89,8 @@ static int from_home_dir(const char *envname, const char *suffix, char **buffer,
static int from_user_dir(const char *field, char **buffer, const char **ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *b = NULL;
- const char *fn = NULL;
+ _cleanup_free_ const char *fn = NULL;
+ const char *c = NULL;
char line[LINE_MAX];
size_t n;
int r;
@@ -98,10 +99,14 @@ static int from_user_dir(const char *field, char **buffer, const char **ret) {
assert(buffer);
assert(ret);
- r = from_home_dir(NULL, ".config/user-dirs.dirs", &b, &fn);
+ r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c);
if (r < 0)
return r;
+ fn = strappend(c, "/user-dirs.dirs");
+ if (!fn)
+ return -ENOMEM;
+
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index de17a6112e..37585048b8 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -403,7 +403,7 @@ static void* thread_worker(void *p) {
assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
/* Assign a pretty name to this thread */
- prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
+ (void) prctl(PR_SET_NAME, (unsigned long) "sd-resolve");
while (!resolve->dead) {
union {
@@ -447,7 +447,7 @@ static int start_threads(sd_resolve *resolve, unsigned extra) {
if (r != 0)
return -r;
- resolve->n_valid_workers ++;
+ resolve->n_valid_workers++;
}
return 0;
@@ -657,7 +657,7 @@ static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {
assert(q->resolve == resolve);
q->done = true;
- resolve->n_done ++;
+ resolve->n_done++;
resolve->current = sd_resolve_query_ref(q);
@@ -1191,7 +1191,7 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd
return 1;
}
-_public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) {
+_public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) {
int r;
assert_return(resolve, -EINVAL);
diff --git a/src/libudev/libudev-device-internal.h b/src/libudev/libudev-device-internal.h
index 40d59201cf..0e9af8ec09 100644
--- a/src/libudev/libudev-device-internal.h
+++ b/src/libudev/libudev-device-internal.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -18,8 +20,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "libudev.h"
#include "sd-device.h"
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index e416e178b4..3b8abfb260 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -112,7 +112,7 @@ _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
**/
_public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) {
if (udev_enumerate)
- udev_enumerate->refcount ++;
+ udev_enumerate->refcount++;
return udev_enumerate;
}
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index eb58740d26..3f6d0ed16c 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -21,6 +21,7 @@
#define _LIBUDEV_H_
#include <stdarg.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#ifdef __cplusplus
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 365c79aa51..4865335349 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -46,14 +46,6 @@ static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static char *arg_host = NULL;
static bool arg_convert = true;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static void polkit_agent_open_if_enabled(void) {
/* Open the polkit agent as a child process if necessary */
@@ -124,11 +116,11 @@ static void print_overridden_variables(void) {
if (variables[j]) {
if (print_warning) {
log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
- " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
+ " Command Line: %s=%s", locale_variable_to_string(j), variables[j]);
print_warning = false;
} else
- log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
+ log_warning(" %s=%s", locale_variable_to_string(j), variables[j]);
}
finish:
for (j = 0; j < _VARIABLE_LC_MAX; j++)
@@ -139,7 +131,7 @@ static void print_status_info(StatusInfo *i) {
assert(i);
if (strv_isempty(i->locale))
- puts(" System Locale: n/a\n");
+ puts(" System Locale: n/a");
else {
char **j;
@@ -239,7 +231,7 @@ static int list_locales(sd_bus *bus, char **args, unsigned n) {
if (r < 0)
return log_error_errno(r, "Failed to read list of locales: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
strv_print(l);
return 0;
@@ -341,7 +333,7 @@ static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
strv_sort(l);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
strv_print(l);
@@ -479,7 +471,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
strv_sort(list);
strv_uniq(list);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
strv_print(list);
return 0;
diff --git a/src/locale/localed.c b/src/locale/localed.c
index f0fe59cc67..46405ca68a 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -542,7 +542,7 @@ static int read_next_mapping(const char* filename,
return 0;
}
- (*n) ++;
+ (*n)++;
l = strstrip(line);
if (l[0] == 0 || l[0] == '#')
@@ -1296,7 +1296,7 @@ int main(int argc, char *argv[]) {
log_open();
umask(0022);
- mac_selinux_init("/etc");
+ mac_selinux_init();
if (argc != 1) {
log_error("This program takes no arguments.");
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
index 694df2cfc8..886c5bfcdf 100644
--- a/src/login/70-uaccess.rules
+++ b/src/login/70-uaccess.rules
@@ -42,8 +42,9 @@ SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
-# DRI video devices
+# DRI and frame buffer video devices
SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess"
+SUBSYSTEM=="graphics", KERNEL=="fb*", TAG+="uaccess"
# KVM
SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
@@ -75,4 +76,7 @@ SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
# software-defined radio communication devices
ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
+# 3D printers, CNC machines, laser cutters, 3D scanners, etc.
+ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
+
LABEL="uaccess_end"
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 6ad3d089bd..c9a5cd796b 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -59,14 +59,6 @@ static bool arg_ask_password = true;
static unsigned arg_lines = 10;
static OutputMode arg_output = OUTPUT_SHORT;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static void polkit_agent_open_if_enabled(void) {
/* Open the polkit agent as a child process if necessary */
@@ -101,7 +93,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -148,7 +140,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -194,7 +186,7 @@ static int list_seats(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -858,7 +850,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -914,7 +906,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -974,7 +966,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index 11a91c3947..29ab00eb1f 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -65,7 +65,7 @@ bool logind_wall_tty_filter(const char *tty, void *userdata) {
assert(m);
- if (!startswith(tty, "/dev/"))
+ if (!startswith(tty, "/dev/") || !m->scheduled_shutdown_tty)
return true;
return !streq(tty + 5, m->scheduled_shutdown_tty);
diff --git a/src/login/logind.c b/src/login/logind.c
index 933602eb08..d5f6757bd3 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1126,7 +1126,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = mac_selinux_init("/run");
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "Could not initialize labelling: %m");
goto finish;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 71f20b3f07..c5bbf2fbde 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <string.h>
#include <sys/mount.h>
+#include <sys/wait.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
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 7a7a1bb42b..7d4270a8ff 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -310,7 +310,7 @@ int machine_load(Machine *m) {
int *ni = NULL;
p = netif;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
int ifi;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 4853139321..e49c90fd1b 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -80,14 +80,6 @@ static const char* arg_format = NULL;
static const char *arg_uid = NULL;
static char **arg_setenv = NULL;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static void polkit_agent_open_if_enabled(void) {
/* Open the polkit agent as a child process if necessary */
@@ -135,7 +127,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
assert(bus);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -180,7 +172,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (l > max_service)
max_service = l;
- n_machines ++;
+ n_machines++;
}
if (r < 0)
return bus_log_parse_error(r);
@@ -238,7 +230,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
assert(bus);
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -707,7 +699,7 @@ static int show_machine(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (properties && argc <= 1) {
@@ -956,7 +948,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (argc <= 1) {
@@ -1763,7 +1755,7 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
- log_error("Failed transfer image: %s", bus_error_message(&error, -r));
+ log_error("Failed to transfer image: %s", bus_error_message(&error, -r));
return r;
}
@@ -2189,7 +2181,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
double progress;
int r;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -2236,7 +2228,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
if (id > max_id)
max_id = id;
- n_transfers ++;
+ n_transfers++;
}
if (r < 0)
return bus_log_parse_error(r);
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index b933099330..20894433e7 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -1212,7 +1212,7 @@ int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_err
r = unit_name_from_dbus_path(path, &unit);
if (r == -EINVAL) /* not for a unit */
return 0;
- if (r < 0){
+ if (r < 0) {
log_oom();
return 0;
}
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 60724fce80..b22a0f648a 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -23,6 +23,7 @@
#include "sd-device.h"
#include "sd-hwdb.h"
+#include "sd-lldp.h"
#include "sd-netlink.h"
#include "sd-network.h"
@@ -30,18 +31,20 @@
#include "arphrd-list.h"
#include "device-util.h"
#include "ether-addr-util.h"
+#include "fd-util.h"
#include "hwdb-util.h"
-#include "lldp.h"
#include "local-addresses.h"
#include "locale-util.h"
#include "netlink-util.h"
#include "pager.h"
#include "parse-util.h"
#include "socket-util.h"
+#include "sparse-endian.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "strxcpyx.h"
#include "terminal-util.h"
#include "util.h"
#include "verbs.h"
@@ -50,15 +53,7 @@ static bool arg_no_pager = false;
static bool arg_legend = true;
static bool arg_all = false;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
-static int link_get_type_string(int iftype, sd_device *d, char **ret) {
+static int link_get_type_string(unsigned short iftype, sd_device *d, char **ret) {
const char *t;
char *p;
@@ -70,7 +65,7 @@ static int link_get_type_string(int iftype, sd_device *d, char **ret) {
* to show a more useful type string for
* them */
- (void)sd_device_get_devtype(d, &devtype);
+ (void) sd_device_get_devtype(d, &devtype);
if (streq_ptr(devtype, "wlan"))
id = "wlan";
@@ -103,10 +98,46 @@ static int link_get_type_string(int iftype, sd_device *d, char **ret) {
return 0;
}
+static void operational_state_to_color(const char *state, const char **on, const char **off) {
+ assert(on);
+ assert(off);
+
+ if (streq_ptr(state, "routable")) {
+ *on = ansi_highlight_green();
+ *off = ansi_normal();
+ } else if (streq_ptr(state, "degraded")) {
+ *on = ansi_highlight_yellow();
+ *off = ansi_normal();
+ } else
+ *on = *off = "";
+}
+
+static void setup_state_to_color(const char *state, const char **on, const char **off) {
+ assert(on);
+ assert(off);
+
+ if (streq_ptr(state, "configured")) {
+ *on = ansi_highlight_green();
+ *off = ansi_normal();
+ } else if (streq_ptr(state, "configuring")) {
+ *on = ansi_highlight_yellow();
+ *off = ansi_normal();
+ } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
+ *on = ansi_highlight_red();
+ *off = ansi_normal();
+ } else
+ *on = *off = "";
+}
+
typedef struct LinkInfo {
- const char *name;
+ char name[IFNAMSIZ+1];
int ifindex;
- unsigned iftype;
+ unsigned short iftype;
+ struct ether_addr mac_address;
+ uint32_t mtu;
+
+ bool has_mac_address:1;
+ bool has_mtu:1;
} LinkInfo;
static int link_info_compare(const void *a, const void *b) {
@@ -115,44 +146,84 @@ static int link_info_compare(const void *a, const void *b) {
return x->ifindex - y->ifindex;
}
-static int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) {
+static int decode_link(sd_netlink_message *m, LinkInfo *info) {
+ const char *name;
+ uint16_t type;
+ int r;
+
+ assert(m);
+ assert(info);
+
+ r = sd_netlink_message_get_type(m, &type);
+ if (r < 0)
+ return r;
+
+ if (type != RTM_NEWLINK)
+ return 0;
+
+ r = sd_rtnl_message_link_get_ifindex(m, &info->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_read_string(m, IFLA_IFNAME, &name);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_message_link_get_type(m, &info->iftype);
+ if (r < 0)
+ return r;
+
+ strscpy(info->name, sizeof info->name, name);
+
+ info->has_mac_address =
+ sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 &&
+ memcmp(&info->mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0;
+
+ info->has_mtu =
+ sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) &&
+ info->mtu > 0;
+
+ return 1;
+}
+
+static int acquire_link_info_strv(sd_netlink *rtnl, char **l, LinkInfo **ret) {
_cleanup_free_ LinkInfo *links = NULL;
- size_t size = 0, c = 0;
- sd_netlink_message *i;
+ char **i;
+ size_t c = 0;
int r;
- for (i = m; i; i = sd_netlink_message_next(i)) {
- const char *name;
- unsigned iftype;
- uint16_t type;
- int ifindex;
+ assert(rtnl);
+ assert(ret);
- r = sd_netlink_message_get_type(i, &type);
- if (r < 0)
- return r;
+ links = new(LinkInfo, strv_length(l));
+ if (!links)
+ return log_oom();
- if (type != RTM_NEWLINK)
- continue;
+ STRV_FOREACH(i, l) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+ int ifindex;
+
+ if (parse_ifindex(*i, &ifindex) >= 0)
+ r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
+ else {
+ r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
+ if (r < 0)
+ return rtnl_log_create_error(r);
- r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
+ r = sd_netlink_message_append_string(req, IFLA_IFNAME, *i);
+ }
if (r < 0)
- return r;
+ return rtnl_log_create_error(r);
- r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
+ r = sd_netlink_call(rtnl, req, 0, &reply);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to request link: %m");
- r = sd_rtnl_message_link_get_type(i, &iftype);
+ r = decode_link(reply, links + c);
if (r < 0)
return r;
-
- if (!GREEDY_REALLOC(links, size, c+1))
- return -ENOMEM;
-
- links[c].name = name;
- links[c].ifindex = ifindex;
- links[c].iftype = iftype;
- c++;
+ if (r > 0)
+ c++;
}
qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
@@ -163,48 +234,15 @@ static int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) {
return (int) c;
}
-static void operational_state_to_color(const char *state, const char **on, const char **off) {
- assert(on);
- assert(off);
-
- if (streq_ptr(state, "routable")) {
- *on = ansi_highlight_green();
- *off = ansi_normal();
- } else if (streq_ptr(state, "degraded")) {
- *on = ansi_highlight_yellow();
- *off = ansi_normal();
- } else
- *on = *off = "";
-}
-
-static void setup_state_to_color(const char *state, const char **on, const char **off) {
- assert(on);
- assert(off);
-
- if (streq_ptr(state, "configured")) {
- *on = ansi_highlight_green();
- *off = ansi_normal();
- } else if (streq_ptr(state, "configuring")) {
- *on = ansi_highlight_yellow();
- *off = ansi_normal();
- } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
- *on = ansi_highlight_red();
- *off = ansi_normal();
- } else
- *on = *off = "";
-}
-
-static int list_links(int argc, char *argv[], void *userdata) {
+static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) {
_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;
-
- pager_open_if_enabled();
+ size_t allocated = 0, c = 0;
+ sd_netlink_message *i;
+ int r;
- r = sd_netlink_open(&rtnl);
- if (r < 0)
- return log_error_errno(r, "Failed to connect to netlink: %m");
+ assert(rtnl);
+ assert(ret);
r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
@@ -218,12 +256,50 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to enumerate links: %m");
- if (arg_legend)
- printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
+ for (i = reply; i; i = sd_netlink_message_next(i)) {
+ if (!GREEDY_REALLOC(links, allocated, c+1))
+ return -ENOMEM;
+
+ r = decode_link(i, links + c);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ c++;
+ }
- c = decode_and_sort_links(reply, &links);
+ qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
+
+ *ret = links;
+ links = NULL;
+
+ return (int) c;
+}
+
+static int list_links(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_free_ LinkInfo *links = NULL;
+ int c, i, r;
+
+ r = sd_netlink_open(&rtnl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to netlink: %m");
+
+ if (argc > 1)
+ c = acquire_link_info_strv(rtnl, argv + 1, &links);
+ else
+ c = acquire_link_info_all(rtnl, &links);
if (c < 0)
- return rtnl_log_parse_error(c);
+ return c;
+
+ pager_open(arg_no_pager, false);
+
+ if (arg_legend)
+ printf("%3s %-16s %-18s %-11s %-10s\n",
+ "IDX",
+ "LINK",
+ "TYPE",
+ "OPERATIONAL",
+ "SETUP");
for (i = 0; i < c; i++) {
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
@@ -233,16 +309,18 @@ static int list_links(int argc, char *argv[], void *userdata) {
char devid[2 + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *t = NULL;
- sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
+ (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
- sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
+ r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
+ if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
+ setup_state = strdup("unmanaged");
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
- sprintf(devid, "n%i", links[i].ifindex);
- (void)sd_device_new_from_device_id(&d, devid);
+ xsprintf(devid, "n%i", links[i].ifindex);
+ (void) sd_device_new_from_device_id(&d, devid);
- link_get_type_string(links[i].iftype, d, &t);
+ (void) link_get_type_string(links[i].iftype, d, &t);
printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n",
links[i].ifindex, links[i].name, strna(t),
@@ -257,7 +335,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
}
/* IEEE Organizationally Unique Identifier vendor string */
-static int ieee_oui(sd_hwdb *hwdb, struct ether_addr *mac, char **ret) {
+static int ieee_oui(sd_hwdb *hwdb, const struct ether_addr *mac, char **ret) {
const char *description;
char modalias[strlen("OUI:XXYYXXYYXXYY") + 1], *desc;
int r;
@@ -404,6 +482,9 @@ static int dump_gateways(
_cleanup_free_ struct local_address *local = NULL;
int r, n, i;
+ assert(rtnl);
+ assert(prefix);
+
n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
if (n < 0)
return n;
@@ -453,6 +534,9 @@ static int dump_addresses(
_cleanup_free_ struct local_address *local = NULL;
int r, n, i;
+ assert(rtnl);
+ assert(prefix);
+
n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
if (n < 0)
return n;
@@ -485,6 +569,116 @@ static int dump_addresses(
return 0;
}
+static int open_lldp_neighbors(int ifindex, FILE **ret) {
+ _cleanup_free_ char *p = NULL;
+ FILE *f;
+
+ if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0)
+ return -ENOMEM;
+
+ f = fopen(p, "re");
+ if (!f)
+ return -errno;
+
+ *ret = f;
+ return 0;
+}
+
+static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) {
+ _cleanup_free_ void *raw = NULL;
+ size_t l;
+ le64_t u;
+ int r;
+
+ assert(f);
+ assert(ret);
+
+ l = fread(&u, 1, sizeof(u), f);
+ if (l == 0 && feof(f))
+ return 0;
+ if (l != sizeof(u))
+ return -EBADMSG;
+
+ raw = new(uint8_t, le64toh(u));
+ if (!raw)
+ return -ENOMEM;
+
+ if (fread(raw, 1, le64toh(u), f) != le64toh(u))
+ return -EBADMSG;
+
+ r = sd_lldp_neighbor_from_raw(ret, raw, le64toh(u));
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static int dump_lldp_neighbors(const char *prefix, int ifindex) {
+ _cleanup_fclose_ FILE *f = NULL;
+ int r, c = 0;
+
+ assert(prefix);
+ assert(ifindex > 0);
+
+ r = open_lldp_neighbors(ifindex, &f);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ const char *system_name = NULL, *port_id = NULL, *port_description = NULL;
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+
+ r = next_lldp_neighbor(f, &n);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ printf("%*s",
+ (int) strlen(prefix),
+ c == 0 ? prefix : "");
+
+ (void) sd_lldp_neighbor_get_system_name(n, &system_name);
+ (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
+ (void) sd_lldp_neighbor_get_port_description(n, &port_description);
+
+ printf("%s on port %s", strna(system_name), strna(port_id));
+
+ if (!isempty(port_description))
+ printf(" (%s)", port_description);
+
+ putchar('\n');
+
+ c++;
+ }
+
+ return c;
+}
+
+static void dump_ifindexes(const char *prefix, const int *ifindexes) {
+ unsigned c;
+
+ assert(prefix);
+
+ if (!ifindexes || ifindexes[0] <= 0)
+ return;
+
+ for (c = 0; ifindexes[c] > 0; c++) {
+ char name[IF_NAMESIZE+1];
+
+ printf("%*s",
+ (int) strlen(prefix),
+ c == 0 ? prefix : "");
+
+ if (if_indextoname(ifindexes[c], name))
+ fputs(name, stdout);
+ else
+ printf("%i", ifindexes[c]);
+
+ fputc('\n', stdout);
+ }
+}
+
static void dump_list(const char *prefix, char **l) {
char **i;
@@ -502,85 +696,36 @@ static void dump_list(const char *prefix, char **l) {
static int link_status_one(
sd_netlink *rtnl,
sd_hwdb *hwdb,
- const char *name) {
+ const LinkInfo *info) {
+
_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_(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;
const char *on_color_operational, *off_color_operational,
*on_color_setup, *off_color_setup;
- _cleanup_strv_free_ char **carrier_bound_to = NULL;
- _cleanup_strv_free_ char **carrier_bound_by = NULL;
- struct ether_addr e;
- unsigned iftype;
- int r, ifindex;
- bool have_mac;
- uint32_t mtu;
+ _cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
+ int r;
assert(rtnl);
- assert(name);
-
- if (parse_ifindex(name, &ifindex) >= 0)
- r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
- else {
- r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
- if (r < 0)
- return rtnl_log_create_error(r);
-
- r = sd_netlink_message_append_string(req, IFLA_IFNAME, name);
- }
+ assert(info);
- if (r < 0)
- return rtnl_log_create_error(r);
-
- r = sd_netlink_call(rtnl, req, 0, &reply);
- if (r < 0)
- return log_error_errno(r, "Failed to query link: %m");
-
- r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
- if (r < 0)
- return rtnl_log_parse_error(r);
-
- r = sd_netlink_message_read_string(reply, IFLA_IFNAME, &name);
- if (r < 0)
- return rtnl_log_parse_error(r);
-
- r = sd_rtnl_message_link_get_type(reply, &iftype);
- if (r < 0)
- 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;
-
- for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++)
- if (*p != 0) {
- all_zeroes = false;
- break;
- }
-
- if (all_zeroes)
- have_mac = false;
- }
-
- (void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
-
- (void) sd_network_link_get_operational_state(ifindex, &operational_state);
+ (void) sd_network_link_get_operational_state(info->ifindex, &operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
- (void) sd_network_link_get_setup_state(ifindex, &setup_state);
+ r = sd_network_link_get_setup_state(info->ifindex, &setup_state);
+ if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
+ setup_state = strdup("unmanaged");
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
- (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);
+ (void) sd_network_link_get_dns(info->ifindex, &dns);
+ (void) sd_network_link_get_search_domains(info->ifindex, &search_domains);
+ (void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
+ (void) sd_network_link_get_ntp(info->ifindex, &ntp);
- sprintf(devid, "n%i", ifindex);
+ xsprintf(devid, "n%i", info->ifindex);
(void) sd_device_new_from_device_id(&d, devid);
@@ -598,14 +743,14 @@ static int link_status_one(
(void) sd_device_get_property_value(d, "ID_MODEL", &model);
}
- link_get_type_string(iftype, d, &t);
+ (void) link_get_type_string(info->iftype, d, &t);
- sd_network_link_get_network_file(ifindex, &network);
+ (void) sd_network_link_get_network_file(info->ifindex, &network);
- sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to);
- sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by);
+ (void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to);
+ (void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by);
- printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
+ printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, info->ifindex, info->name);
printf(" Link File: %s\n"
" Network File: %s\n"
@@ -626,23 +771,23 @@ static int link_status_one(
if (model)
printf(" Model: %s\n", model);
- if (have_mac) {
+ if (info->has_mac_address) {
_cleanup_free_ char *description = NULL;
char ea[ETHER_ADDR_TO_STRING_MAX];
- ieee_oui(hwdb, &e, &description);
+ (void) ieee_oui(hwdb, &info->mac_address, &description);
if (description)
- printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description);
+ printf(" HW Address: %s (%s)\n", ether_addr_to_string(&info->mac_address, ea), description);
else
- printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
+ printf(" HW Address: %s\n", ether_addr_to_string(&info->mac_address, ea));
}
- if (mtu > 0)
- printf(" MTU: %u\n", mtu);
+ if (info->has_mtu)
+ printf(" MTU: %u\n", info->mtu);
- dump_addresses(rtnl, " Address: ", ifindex);
- dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
+ (void) dump_addresses(rtnl, " Address: ", info->ifindex);
+ (void) dump_gateways(rtnl, hwdb, " Gateway: ", info->ifindex);
dump_list(" DNS: ", dns);
dump_list(" Search Domains: ", search_domains);
@@ -650,362 +795,237 @@ static int link_status_one(
dump_list(" NTP: ", ntp);
- dump_list("Carrier Bound To: ", carrier_bound_to);
- dump_list("Carrier Bound By: ", carrier_bound_by);
+ dump_ifindexes("Carrier Bound To: ", carrier_bound_to);
+ dump_ifindexes("Carrier Bound By: ", carrier_bound_by);
- (void) sd_network_link_get_timezone(ifindex, &tz);
+ (void) sd_network_link_get_timezone(info->ifindex, &tz);
if (tz)
- printf(" Time Zone: %s", tz);
+ printf(" Time Zone: %s\n", tz);
+
+ (void) dump_lldp_neighbors(" Connected To: ", info->ifindex);
return 0;
}
-static int link_status(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- char **name;
- int r;
-
- r = sd_netlink_open(&rtnl);
- if (r < 0)
- return log_error_errno(r, "Failed to connect to netlink: %m");
-
- r = sd_hwdb_new(&hwdb);
- if (r < 0)
- log_debug_errno(r, "Failed to open hardware database: %m");
-
- if (argc <= 1 && !arg_all) {
- _cleanup_free_ char *operational_state = 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",
- 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);
-
- sd_network_get_dns(&dns);
- dump_list(" DNS: ", dns);
-
- sd_network_get_search_domains(&search_domains);
- dump_list("Search Domains: ", search_domains);
-
- sd_network_get_route_domains(&route_domains);
- dump_list(" Route Domains: ", route_domains);
-
- sd_network_get_ntp(&ntp);
- dump_list(" NTP: ", ntp);
-
- return 0;
- }
+static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
+ _cleanup_free_ char *operational_state = NULL;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
+ const char *on_color_operational, *off_color_operational;
- pager_open_if_enabled();
+ assert(rtnl);
- if (arg_all) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- _cleanup_free_ LinkInfo *links = NULL;
- int c, i;
+ (void) sd_network_get_operational_state(&operational_state);
+ operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
- r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
- if (r < 0)
- return rtnl_log_create_error(r);
+ 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);
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return rtnl_log_create_error(r);
+ (void) dump_addresses(rtnl, " Address: ", 0);
+ (void) dump_gateways(rtnl, hwdb, " Gateway: ", 0);
- r = sd_netlink_call(rtnl, req, 0, &reply);
- if (r < 0)
- return log_error_errno(r, "Failed to enumerate links: %m");
+ (void) sd_network_get_dns(&dns);
+ dump_list(" DNS: ", dns);
- c = decode_and_sort_links(reply, &links);
- if (c < 0)
- return rtnl_log_parse_error(c);
+ (void) sd_network_get_search_domains(&search_domains);
+ dump_list("Search Domains: ", search_domains);
- for (i = 0; i < c; i++) {
- if (i > 0)
- fputc('\n', stdout);
+ (void) sd_network_get_route_domains(&route_domains);
+ dump_list(" Route Domains: ", route_domains);
- link_status_one(rtnl, hwdb, links[i].name);
- }
- } else {
- STRV_FOREACH(name, argv + 1) {
- if (name != argv + 1)
- fputc('\n', stdout);
-
- link_status_one(rtnl, hwdb, *name);
- }
- }
+ (void) sd_network_get_ntp(&ntp);
+ dump_list(" NTP: ", ntp);
return 0;
}
-const char *lldp_system_capability_to_string(LLDPSystemCapabilities d) _const_;
-LLDPSystemCapabilities lldp_system_capability_from_string(const char *d) _pure_;
-
-static const char* const lldp_system_capability_table[_LLDP_SYSTEM_CAPABILITIES_MAX + 1] = {
- [LLDP_SYSTEM_CAPABILITIES_OTHER] = "O",
- [LLDP_SYSTEM_CAPABILITIES_REPEATER] = "P",
- [LLDP_SYSTEM_CAPABILITIES_BRIDGE] = "B",
- [LLDP_SYSTEM_CAPABILITIES_WLAN_AP] = "W",
- [LLDP_SYSTEM_CAPABILITIES_ROUTER] = "R",
- [LLDP_SYSTEM_CAPABILITIES_PHONE] = "T",
- [LLDP_SYSTEM_CAPABILITIES_DOCSIS] = "D",
- [LLDP_SYSTEM_CAPABILITIES_STATION] = "A",
- [LLDP_SYSTEM_CAPABILITIES_CVLAN] = "C",
- [LLDP_SYSTEM_CAPABILITIES_SVLAN] = "S",
- [LLDP_SYSTEM_CAPABILITIES_TPMR] = "M",
- [_LLDP_SYSTEM_CAPABILITIES_MAX] = "N/A",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(lldp_system_capability, LLDPSystemCapabilities);
-
-static char *lldp_system_caps(uint16_t cap) {
- _cleanup_free_ char *s = NULL, *t = NULL;
- char *capability;
-
- t = strdup("[ ");
- if (!t)
- return NULL;
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_OTHER) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_OTHER), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_REPEATER) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_REPEATER), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_BRIDGE) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_BRIDGE), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_WLAN_AP) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_WLAN_AP), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
-
- if (cap & LLDP_SYSTEM_CAPABILITIES_PHONE) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_PHONE), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
+static int link_status(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
+ _cleanup_free_ LinkInfo *links = NULL;
+ int r, c, i;
- if (cap & LLDP_SYSTEM_CAPABILITIES_DOCSIS) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_DOCSIS), " ", NULL);
- if (!s)
- return NULL;
+ pager_open(arg_no_pager, false);
- free(t);
- t = s;
- }
+ r = sd_netlink_open(&rtnl);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to netlink: %m");
- if (cap & LLDP_SYSTEM_CAPABILITIES_STATION) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_STATION), " ", NULL);
- if (!s)
- return NULL;
+ r = sd_hwdb_new(&hwdb);
+ if (r < 0)
+ log_debug_errno(r, "Failed to open hardware database: %m");
- free(t);
- t = s;
- }
+ if (arg_all)
+ c = acquire_link_info_all(rtnl, &links);
+ else if (argc <= 1)
+ return system_status(rtnl, hwdb);
+ else
+ c = acquire_link_info_strv(rtnl, argv + 1, &links);
+ if (c < 0)
+ return c;
- if (cap & LLDP_SYSTEM_CAPABILITIES_CVLAN) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_CVLAN), " ", NULL);
- if (!s)
- return NULL;
+ for (i = 0; i < c; i++) {
+ if (i > 0)
+ fputc('\n', stdout);
- free(t);
- t = s;
+ link_status_one(rtnl, hwdb, links + i);
}
- if (cap & LLDP_SYSTEM_CAPABILITIES_SVLAN) {
- s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_SVLAN), " ", NULL);
- if (!s)
- return NULL;
-
- free(t);
- t = s;
- }
+ return 0;
+}
- if (cap & LLDP_SYSTEM_CAPABILITIES_TPMR) {
- s = strappend(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_TPMR));
- if (!s)
- return NULL;
+static char *lldp_capabilities_to_string(uint16_t x) {
+ static const char characters[] = {
+ 'o', 'p', 'b', 'w', 'r', 't', 'd', 'a', 'c', 's', 'm',
+ };
+ char *ret;
+ unsigned i;
- free(t);
- }
+ ret = new(char, ELEMENTSOF(characters) + 1);
+ if (!ret)
+ return NULL;
- if (!s) {
- s = strappend(t, lldp_system_capability_to_string(_LLDP_SYSTEM_CAPABILITIES_MAX));
- if (!s)
- return NULL;
+ for (i = 0; i < ELEMENTSOF(characters); i++)
+ ret[i] = (x & (1U << i)) ? characters[i] : '.';
- free(t);
- }
+ ret[i] = 0;
+ return ret;
+}
- t = strappend(s, "]");
- if (!t)
- return NULL;
+static void lldp_capabilities_legend(uint16_t x) {
+ unsigned w, i, cols = columns();
+ static const char* const table[] = {
+ "o - Other",
+ "p - Repeater",
+ "b - Bridge",
+ "w - WLAN Access Point",
+ "r - Router",
+ "t - Telephone",
+ "d - DOCSIS cable device",
+ "a - Station",
+ "c - Customer VLAN",
+ "s - Service VLAN",
+ "m - Two-port MAC Relay (TPMR)",
+ };
- free(s);
- capability = t;
+ if (x == 0)
+ return;
- s = NULL;
- t = NULL;
+ printf("\nCapability Flags:\n");
+ for (w = 0, i = 0; i < ELEMENTSOF(table); i++)
+ if (x & (1U << i) || arg_all) {
+ bool newline;
- return capability;
+ newline = w + strlen(table[i]) + (w == 0 ? 0 : 2) > cols;
+ if (newline)
+ w = 0;
+ w += printf("%s%s%s", newline ? "\n" : "", w == 0 ? "" : "; ", table[i]);
+ }
+ puts("");
}
static int link_lldp_status(int argc, char *argv[], void *userdata) {
- _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;
- int i, r, c, j;
- const char *p;
- char **s;
-
- pager_open_if_enabled();
+ int i, r, c, m = 0;
+ uint16_t all = 0;
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
- r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
- if (r < 0)
- return rtnl_log_create_error(r);
-
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return rtnl_log_create_error(r);
-
- r = sd_netlink_call(rtnl, req, 0, &reply);
- if (r < 0)
- return log_error_errno(r, "Failed to enumerate links: %m");
-
- c = decode_and_sort_links(reply, &links);
+ if (argc > 1)
+ c = acquire_link_info_strv(rtnl, argv + 1, &links);
+ else
+ c = acquire_link_info_all(rtnl, &links);
if (c < 0)
- return rtnl_log_parse_error(c);
+ return c;
+
+ pager_open(arg_no_pager, false);
if (arg_legend)
- printf("%s %16s %24s %16s %16s\n", "Local Intf", "Device ID", "Port ID", "TTL", "Capability");
+ printf("%-16s %-17s %-16s %-11s %-17s %-16s\n",
+ "LINK",
+ "CHASSIS ID",
+ "SYSTEM NAME",
+ "CAPS",
+ "PORT ID",
+ "PORT DESCRIPTION");
- for (i = j = 0; i < c; i++) {
- _cleanup_free_ char *chassis = NULL, *port = NULL, *cap = NULL, *lldp = NULL;
- _cleanup_strv_free_ char **l = NULL;
+ for (i = 0; i < c; i++) {
+ _cleanup_fclose_ FILE *f = NULL;
- r = sd_network_link_get_lldp(links[i].ifindex, &lldp);
- if (r < 0)
+ r = open_lldp_neighbors(links[i].ifindex, &f);
+ if (r == -ENOENT)
continue;
+ if (r < 0) {
+ log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex);
+ continue;
+ }
- l = strv_split_newlines(lldp);
- if (!l)
- return -ENOMEM;
-
- STRV_FOREACH(s, l) {
-
- p = *s;
- for (;;) {
- _cleanup_free_ char *a = NULL, *b = NULL, *word = NULL;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
- if (r < 0)
- return log_error_errno(r, "Failed to parse LLDP syntax \"%s\": %m", *s);
-
- if (r == 0)
- break;
-
- r = split_pair(word, "=", &a, &b);
- if (r < 0)
- continue;
-
- if (streq(a, "_Chassis")) {
- r = free_and_strdup(&chassis, b);
- if (r < 0)
- return r;
-
- } else if (streq(a, "_Port")) {
- r = free_and_strdup(&port, b);
- if (r < 0)
- return r;
-
- } else if (streq(a, "_TTL")) {
- long long unsigned x = 0;
- usec_t time;
+ for (;;) {
+ _cleanup_free_ char *cid = NULL, *pid = NULL, *sname = NULL, *pdesc = NULL;
+ const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL, *capabilities = NULL;
+ _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+ uint16_t cc;
- r = safe_atollu(b, &x);
- if (r < 0 || (usec_t) x != x)
- return log_warning_errno(r < 0 ? r : ERANGE,
- "Failed to parse TTL \"%s\": %m", b);
+ r = next_lldp_neighbor(f, &n);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to read neighbor data: %m");
+ break;
+ }
+ if (r == 0)
+ break;
- time = now(clock_boottime_or_monotonic());
- if (x < time)
- continue;
+ (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id);
+ (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
+ (void) sd_lldp_neighbor_get_system_name(n, &system_name);
+ (void) sd_lldp_neighbor_get_port_description(n, &port_description);
- ttl = (double) (x - time) / USEC_PER_SEC;
+ if (chassis_id) {
+ cid = ellipsize(chassis_id, 17, 100);
+ if (cid)
+ chassis_id = cid;
+ }
- } else if (streq(a, "_CAP")) {
- sscanf(b, "%x", &capability);
+ if (port_id) {
+ pid = ellipsize(port_id, 17, 100);
+ if (pid)
+ port_id = pid;
+ }
- cap = lldp_system_caps(capability);
- }
+ if (system_name) {
+ sname = ellipsize(system_name, 16, 100);
+ if (sname)
+ system_name = sname;
+ }
+ if (port_description) {
+ pdesc = ellipsize(port_description, 16, 100);
+ if (pdesc)
+ port_description = pdesc;
}
- if (ttl >= 0) {
- printf("%10s %24s %16s %16f %16s\n",
- links[i].name,
- strna(chassis), strna(port),
- ttl, cap);
- j++;
+ if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) {
+ capabilities = lldp_capabilities_to_string(cc);
+ all |= cc;
}
+
+ printf("%-16s %-17s %-16s %-11s %-17s %-16s\n",
+ links[i].name,
+ strna(chassis_id),
+ strna(system_name),
+ strna(capabilities),
+ strna(port_id),
+ strna(port_description));
+
+ m++;
}
}
if (arg_legend) {
- printf("\nCapability Codes:\n"
- "(O) - Other, (P) - Repeater, (B) - Bridge , (W) - WLAN Access Point, (R) = Router,\n"
- "(T) - Telephone, (D) - Data Over Cable Service Interface Specifications, (A) - Station,\n"
- "(C) - Customer VLAN, (S) - Service VLAN, (M) - Two-port MAC Relay (TPMR)\n\n");
-
- printf("Total entries displayed: %d\n", j);
+ lldp_capabilities_legend(all);
+ printf("\n%i neighbors listed.\n", m);
}
return 0;
@@ -1020,9 +1040,9 @@ static void help(void) {
" --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n\n"
"Commands:\n"
- " list List links\n"
+ " list [LINK...] List links\n"
" status [LINK...] Show link status\n"
- " lldp Show lldp information\n"
+ " lldp [LINK...] Show LLDP neighbors\n"
, program_invocation_short_name);
}
@@ -1084,15 +1104,23 @@ static int parse_argv(int argc, char *argv[]) {
static int networkctl_main(int argc, char *argv[]) {
const Verb verbs[] = {
- { "list", VERB_ANY, 1, VERB_DEFAULT, list_links },
- { "status", 1, VERB_ANY, 0, link_status },
- { "lldp", VERB_ANY, 1, VERB_DEFAULT, link_lldp_status },
+ { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
+ { "status", VERB_ANY, VERB_ANY, 0, link_status },
+ { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
+static void warn_networkd_missing(void) {
+
+ if (access("/run/systemd/netif/state", F_OK) >= 0)
+ return;
+
+ fprintf(stderr, "WARNING: systemd-networkd is not running, output will be incomplete.\n\n");
+}
+
int main(int argc, char* argv[]) {
int r;
@@ -1103,6 +1131,8 @@ int main(int argc, char* argv[]) {
if (r <= 0)
goto finish;
+ warn_networkd_missing();
+
r = networkctl_main(argc, argv);
finish:
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
new file mode 100644
index 0000000000..8b149124b3
--- /dev/null
+++ b/src/network/networkd-conf.c
@@ -0,0 +1,155 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <ctype.h>
+
+#include "conf-parser.h"
+#include "def.h"
+#include "dhcp-identifier.h"
+#include "networkd-conf.h"
+#include "string-table.h"
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+ return config_parse_many(PKGSYSCONFDIR "/networkd.conf",
+ CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
+ "DUID\0",
+ config_item_perf_lookup, networkd_gperf_lookup,
+ false, m);
+}
+
+static const char* const duid_type_table[_DUID_TYPE_MAX] = {
+ [DUID_TYPE_RAW] = "raw",
+ [DUID_TYPE_LLT] = "link-layer-time",
+ [DUID_TYPE_EN] = "vendor",
+ [DUID_TYPE_LL] = "link-layer",
+ [DUID_TYPE_UUID] = "uuid"
+};
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type");
+
+int config_parse_duid_rawdata(
+ 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 r;
+ long byte;
+ char *cbyte, *pnext;
+ const char *pduid = rvalue;
+ size_t count = 0, duid_index = 0;
+ Manager *m;
+ Network *n;
+ DUIDType *duid_type;
+ uint16_t *dhcp_duid_type;
+ size_t *dhcp_duid_len;
+ uint8_t *dhcp_duid;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(userdata);
+
+ if (ltype == DUID_CONFIG_SOURCE_GLOBAL) {
+ m = userdata;
+ duid_type = &m->duid_type;
+ dhcp_duid_type = &m->dhcp_duid_type;
+ dhcp_duid_len = &m->dhcp_duid_len;
+ dhcp_duid = m->dhcp_duid;
+ } else {
+ /* DUID_CONFIG_SOURCE_NETWORK */
+ n = userdata;
+ duid_type = &n->duid_type;
+ dhcp_duid_type = &n->dhcp_duid_type;
+ dhcp_duid_len = &n->dhcp_duid_len;
+ dhcp_duid = n->dhcp_duid;
+ }
+
+ if (*duid_type == _DUID_TYPE_INVALID)
+ *duid_type = DUID_TYPE_RAW;
+
+ switch (*duid_type) {
+ case DUID_TYPE_LLT:
+ /* RawData contains DUID-LLT link-layer address (offset 6) */
+ duid_index = 6;
+ break;
+ case DUID_TYPE_EN:
+ /* RawData contains DUID-EN identifier (offset 4) */
+ duid_index = 4;
+ break;
+ case DUID_TYPE_LL:
+ /* RawData contains DUID-LL link-layer address (offset 2) */
+ duid_index = 2;
+ break;
+ case DUID_TYPE_UUID:
+ /* RawData specifies UUID (offset 0) - fall thru */
+ case DUID_TYPE_RAW:
+ /* First two bytes of RawData is DUID Type - fall thru */
+ default:
+ break;
+ }
+
+ if (*duid_type != DUID_TYPE_RAW)
+ *dhcp_duid_type = (uint16_t)(*duid_type);
+
+ /* RawData contains DUID in format " NN:NN:NN... " */
+ while (true) {
+ r = extract_first_word(&pduid, &cbyte, ":", 0);
+ if (r < 0) {
+ log_error("Failed to read DUID.");
+ return -EINVAL;
+ }
+ if (r == 0)
+ break;
+ if (duid_index >= MAX_DUID_LEN) {
+ log_error("DUID length exceeds maximum length.");
+ return -EINVAL;
+ }
+
+ errno = 0;
+ byte = strtol(cbyte, &pnext, 16);
+ if ((errno == ERANGE && (byte == LONG_MAX || byte == LONG_MIN))
+ || (errno != 0 && byte == 0) || (cbyte == pnext)) {
+ log_error("Invalid DUID byte: %s.", cbyte);
+ return -EINVAL;
+ }
+
+ /* If DUID_TYPE_RAW, first two bytes hold DHCP DUID type code */
+ if ((*duid_type == DUID_TYPE_RAW) && (count < 2)) {
+ *dhcp_duid_type |= (byte << (8 * (1 - count)));
+ count++;
+ continue;
+ }
+
+ dhcp_duid[duid_index++] = byte;
+ }
+
+ *dhcp_duid_len = duid_index;
+
+ return 0;
+}
diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h
new file mode 100644
index 0000000000..efc370f839
--- /dev/null
+++ b/src/network/networkd-conf.h
@@ -0,0 +1,36 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "networkd.h"
+
+typedef enum DuidConfigSource {
+ DUID_CONFIG_SOURCE_GLOBAL = 0,
+ DUID_CONFIG_SOURCE_NETWORK,
+} DuidConfigSource;
+
+int manager_parse_config_file(Manager *m);
+
+const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length);
+
+int config_parse_duid_type(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_duid_rawdata(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 03c28bbcb6..0589ebf227 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -34,7 +34,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
assert(link);
assert(link->dhcp4_messages > 0);
- link->dhcp4_messages --;
+ link->dhcp4_messages--;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -96,7 +96,7 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0)
return log_link_warning_errno(link, r, "Could not set host route: %m");
- link->dhcp4_messages ++;
+ link->dhcp4_messages++;
route->family = AF_INET;
route->gw.in = gateway;
@@ -110,7 +110,7 @@ static int link_set_dhcp_routes(Link *link) {
return r;
}
- link->dhcp4_messages ++;
+ link->dhcp4_messages++;
}
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
@@ -137,7 +137,7 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0)
return log_link_warning_errno(link, r, "Could not set host route: %m");
- link->dhcp4_messages ++;
+ link->dhcp4_messages++;
}
return 0;
@@ -625,7 +625,21 @@ int dhcp4_configure(Link *link) {
switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID:
- /* Library defaults to this. */
+ /* If configured, apply user specified DUID and/or IAID */
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return r;
break;
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 5f7a005c36..d4b2fbfc57 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -230,6 +230,23 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
+ r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
+ if (r < 0)
+ goto error;
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp6_client_set_duid(client,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp6_client_set_duid(client,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ goto error;
+
r = sd_dhcp6_client_set_index(client, link->ifindex);
if (r < 0)
goto error;
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index 1538caa204..241f486211 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -37,7 +37,7 @@ int fdb_entry_new_static(Network *const network,
assert(network);
/* search entry in hashmap first. */
- if(section) {
+ if (section) {
fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section));
if (fdb_entry) {
*ret = fdb_entry;
@@ -141,10 +141,10 @@ int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) {
/* remove and FDB entry. */
void fdb_entry_free(FdbEntry *fdb_entry) {
- if(!fdb_entry)
+ if (!fdb_entry)
return;
- if(fdb_entry->network) {
+ if (fdb_entry->network) {
LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries,
fdb_entry);
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
new file mode 100644
index 0000000000..0625fb335b
--- /dev/null
+++ b/src/network/networkd-gperf.gperf
@@ -0,0 +1,18 @@
+%{
+#include <stddef.h>
+#include "conf-parser.h"
+#include "networkd-conf.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name networkd_gperf_hash
+%define lookup-function-name networkd_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+DUID.Type, config_parse_duid_type, 0, offsetof(Manager, duid_type)
+DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_GLOBAL, offsetof(Manager, dhcp_duid)
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index 949c75337c..e05fd3eea7 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -165,7 +165,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
return 0;
}
-static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
+static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
Link *link = userdata;
int r;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 692c0bf63d..88b3cbe90a 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -29,6 +29,7 @@
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-link.h"
+#include "networkd-lldp-tx.h"
#include "networkd-netdev.h"
#include "set.h"
#include "socket-util.h"
@@ -38,7 +39,9 @@
#include "util.h"
#include "virt.h"
-bool link_dhcp6_enabled(Link *link) {
+static bool link_dhcp6_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -48,7 +51,9 @@ bool link_dhcp6_enabled(Link *link) {
return link->network->dhcp & ADDRESS_FAMILY_IPV6;
}
-bool link_dhcp4_enabled(Link *link) {
+static bool link_dhcp4_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -58,7 +63,9 @@ bool link_dhcp4_enabled(Link *link) {
return link->network->dhcp & ADDRESS_FAMILY_IPV4;
}
-bool link_dhcp4_server_enabled(Link *link) {
+static bool link_dhcp4_server_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -68,7 +75,9 @@ bool link_dhcp4_server_enabled(Link *link) {
return link->network->dhcp_server;
}
-bool link_ipv4ll_enabled(Link *link) {
+static bool link_ipv4ll_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -78,7 +87,9 @@ bool link_ipv4ll_enabled(Link *link) {
return link->network->link_local & ADDRESS_FAMILY_IPV4;
}
-bool link_ipv6ll_enabled(Link *link) {
+static bool link_ipv6ll_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -88,20 +99,42 @@ bool link_ipv6ll_enabled(Link *link) {
return link->network->link_local & ADDRESS_FAMILY_IPV6;
}
-bool link_lldp_enabled(Link *link) {
+static bool link_lldp_rx_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
+ if (link->iftype != ARPHRD_ETHER)
+ return false;
+
if (!link->network)
return false;
if (link->network->bridge)
return false;
- return link->network->lldp;
+ return link->network->lldp_mode != LLDP_MODE_NO;
+}
+
+static bool link_lldp_tx_enabled(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (link->iftype != ARPHRD_ETHER)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ return link->network->lldp_emit;
}
static bool link_ipv4_forward_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -115,6 +148,7 @@ static bool link_ipv4_forward_enabled(Link *link) {
}
static bool link_ipv6_forward_enabled(Link *link) {
+ assert(link);
if (!socket_ipv6_is_supported())
return false;
@@ -131,7 +165,9 @@ static bool link_ipv6_forward_enabled(Link *link) {
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
-bool link_ipv6_accept_ra_enabled(Link *link) {
+static bool link_ipv6_accept_ra_enabled(Link *link) {
+ assert(link);
+
if (link->flags & IFF_LOOPBACK)
return false;
@@ -300,6 +336,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
uint16_t type;
const char *ifname;
int r, ifindex;
+ unsigned short iftype;
assert(manager);
assert(message);
@@ -317,6 +354,10 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
else if (ifindex <= 0)
return -EINVAL;
+ r = sd_rtnl_message_link_get_type(message, &iftype);
+ if (r < 0)
+ return r;
+
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
if (r < 0)
return r;
@@ -330,30 +371,24 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
link->state = LINK_STATE_PENDING;
link->rtnl_extended_attrs = true;
link->ifindex = ifindex;
+ link->iftype = iftype;
link->ifname = strdup(ifname);
if (!link->ifname)
return -ENOMEM;
r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
if (r < 0)
- log_link_debug(link, "MAC address not found for new device, continuing without");
+ log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
- r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
- link->ifindex);
- if (r < 0)
+ if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
return -ENOMEM;
- r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
- link->ifindex);
- if (r < 0)
+ if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
return -ENOMEM;
- r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
- link->ifindex);
- if (r < 0)
+ if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
return -ENOMEM;
-
r = hashmap_ensure_allocated(&manager->links, NULL);
if (r < 0)
return r;
@@ -399,10 +434,11 @@ static void link_free(Link *link) {
sd_dhcp_client_unref(link->dhcp_client);
sd_dhcp_lease_unref(link->dhcp_lease);
+ link_lldp_tx_stop(link);
+
free(link->lease_file);
sd_lldp_unref(link->lldp);
-
free(link->lldp_file);
sd_ipv4ll_unref(link->ipv4ll);
@@ -436,7 +472,7 @@ Link *link_unref(Link *link) {
assert(link->n_ref > 0);
- link->n_ref --;
+ link->n_ref--;
if (link->n_ref > 0)
return NULL;
@@ -452,7 +488,7 @@ Link *link_ref(Link *link) {
assert(link->n_ref > 0);
- link->n_ref ++;
+ link->n_ref++;
return link;
}
@@ -506,33 +542,28 @@ static int link_stop_clients(Link *link) {
if (link->dhcp_client) {
k = sd_dhcp_client_stop(link->dhcp_client);
if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
+ r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m");
}
if (link->ipv4ll) {
k = sd_ipv4ll_stop(link->ipv4ll);
if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
+ r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m");
}
if (link->dhcp6_client) {
k = sd_dhcp6_client_stop(link->dhcp6_client);
if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
+ r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
}
if (link->ndisc_router_discovery) {
k = sd_ndisc_stop(link->ndisc_router_discovery);
if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
- }
-
- if (link->lldp) {
- k = sd_lldp_stop(link->lldp);
- if (k < 0)
- r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
+ r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
}
+ link_lldp_tx_stop(link);
return r;
}
@@ -645,7 +676,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
LINK_STATE_LINGER));
- link->link_messages --;
+ link->link_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
@@ -681,7 +712,7 @@ static int link_enter_set_routes(Link *link) {
return r;
}
- link->link_messages ++;
+ link->link_messages++;
}
if (link->link_messages == 0) {
@@ -723,7 +754,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
LINK_STATE_FAILED, LINK_STATE_LINGER));
- link->link_messages --;
+ link->link_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
@@ -850,7 +881,7 @@ static int link_enter_set_addresses(Link *link) {
return r;
}
- link->link_messages ++;
+ link->link_messages++;
}
/* now that we can figure out a default address for the dhcp server,
@@ -999,7 +1030,7 @@ static int link_set_bridge_fdb(Link *const link) {
LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
r = fdb_entry_configure(link, fdb_entry);
- if(r < 0) {
+ if (r < 0) {
log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
break;
}
@@ -1211,7 +1242,7 @@ static int link_set_bridge(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
- if(link->network->cost != 0) {
+ if (link->network->cost != 0) {
r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
@@ -1230,23 +1261,93 @@ static int link_set_bridge(Link *link) {
return r;
}
-static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
+static int link_lldp_save(Link *link) {
+ _cleanup_free_ char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ sd_lldp_neighbor **l = NULL;
+ int n = 0, r, i;
+
+ assert(link);
+ assert(link->lldp_file);
+
+ if (!link->lldp) {
+ (void) unlink(link->lldp_file);
+ return 0;
+ }
+
+ r = sd_lldp_get_neighbors(link->lldp, &l);
+ if (r < 0)
+ goto finish;
+ if (r == 0) {
+ (void) unlink(link->lldp_file);
+ goto finish;
+ }
+
+ n = r;
+
+ r = fopen_temporary(link->lldp_file, &f, &temp_path);
+ if (r < 0)
+ goto finish;
+
+ fchmod(fileno(f), 0644);
+
+ for (i = 0; i < n; i++) {
+ const void *p;
+ le64_t u;
+ size_t sz;
+
+ r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
+ if (r < 0)
+ goto finish;
+
+ u = htole64(sz);
+ (void) fwrite(&u, 1, sizeof(u), f);
+ (void) fwrite(p, 1, sz, f);
+ }
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ goto finish;
+
+ if (rename(temp_path, link->lldp_file) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+finish:
+ if (r < 0) {
+ (void) unlink(link->lldp_file);
+ if (temp_path)
+ (void) unlink(temp_path);
+
+ log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
+ }
+
+ if (l) {
+ for (i = 0; i < n; i++)
+ sd_lldp_neighbor_unref(l[i]);
+ free(l);
+ }
+
+ return r;
+}
+
+static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
Link *link = userdata;
int r;
assert(link);
- assert(link->network);
- assert(link->manager);
- switch (event) {
- case SD_LLDP_EVENT_UPDATE_INFO:
- r = sd_lldp_save(link->lldp, link->lldp_file);
- if (r < 0)
- log_link_warning_errno(link, r, "Could not save LLDP: %m");
+ (void) link_lldp_save(link);
+
+ if (link_lldp_tx_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
+ /* If we received information about a new neighbor, restart the LLDP "fast" logic */
- break;
- default:
- break;
+ log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
+
+ r = link_lldp_tx_start(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
}
}
@@ -1311,14 +1412,10 @@ static int link_acquire_conf(Link *link) {
return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
}
- if (link_lldp_enabled(link)) {
- assert(link->lldp);
-
- log_link_debug(link, "Starting LLDP");
-
- r = sd_lldp_start(link->lldp);
+ if (link_lldp_tx_enabled(link)) {
+ r = link_lldp_tx_start(link);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not start LLDP: %m");
+ return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
}
return 0;
@@ -1559,7 +1656,7 @@ static int link_new_bound_by_list(Link *link) {
m = link->manager;
- HASHMAP_FOREACH (carrier, m->links, i) {
+ HASHMAP_FOREACH(carrier, m->links, i) {
if (!carrier->network)
continue;
@@ -1578,7 +1675,7 @@ static int link_new_bound_by_list(Link *link) {
if (list_updated)
link_dirty(link);
- HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
+ HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
r = link_put_carrier(carrier, link, &carrier->bound_to_links);
if (r < 0)
return r;
@@ -1738,7 +1835,7 @@ static int link_joined(Link *link) {
}
}
- if(link->network->bridge) {
+ if (link->network->bridge) {
r = link_set_bridge(link);
if (r < 0)
log_link_error_errno(link, r, "Could not set bridge message: %m");
@@ -1754,7 +1851,7 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *us
assert(link);
assert(link->network);
- link->enslaving --;
+ link->enslaving--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
@@ -1810,7 +1907,7 @@ static int link_enter_join_netdev(Link *link) {
return r;
}
- link->enslaving ++;
+ link->enslaving++;
}
if (link->network->bridge) {
@@ -1831,7 +1928,7 @@ static int link_enter_join_netdev(Link *link) {
return r;
}
- link->enslaving ++;
+ link->enslaving++;
}
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
@@ -1853,7 +1950,7 @@ static int link_enter_join_netdev(Link *link) {
return r;
}
- link->enslaving ++;
+ link->enslaving++;
}
return 0;
@@ -2030,6 +2127,27 @@ static int link_drop_foreign_config(Link *link) {
return 0;
}
+static int link_update_lldp(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (!link->lldp)
+ return 0;
+
+ if (link->flags & IFF_UP) {
+ r = sd_lldp_start(link->lldp);
+ if (r > 0)
+ log_link_debug(link, "Started LLDP.");
+ } else {
+ r = sd_lldp_stop(link->lldp);
+ if (r > 0)
+ log_link_debug(link, "Stopped LLDP.");
+ }
+
+ return r;
+}
+
static int link_configure(Link *link) {
int r;
@@ -2108,8 +2226,19 @@ static int link_configure(Link *link) {
return r;
}
- if (link_lldp_enabled(link)) {
- r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
+ if (link_lldp_rx_enabled(link)) {
+ r = sd_lldp_new(&link->lldp, link->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_lldp_match_capabilities(link->lldp,
+ link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
+ SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
+ SD_LLDP_SYSTEM_CAPABILITIES_ALL);
+ if (r < 0)
+ return r;
+
+ r = sd_lldp_set_filter_address(link->lldp, &link->mac);
if (r < 0)
return r;
@@ -2117,8 +2246,11 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
- r = sd_lldp_set_callback(link->lldp,
- lldp_handler, link);
+ r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
+ if (r < 0)
+ return r;
+
+ r = link_update_lldp(link);
if (r < 0)
return r;
}
@@ -2307,7 +2439,7 @@ network_file_fail:
continue;
}
- *prefixlen_str ++ = '\0';
+ *prefixlen_str++ = '\0';
r = sscanf(prefixlen_str, "%hhu", &prefixlen);
if (r != 1) {
@@ -2354,7 +2486,7 @@ network_file_fail:
continue;
}
- *prefixlen_str ++ = '\0';
+ *prefixlen_str++ = '\0';
r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime);
if (r != 5) {
@@ -2562,7 +2694,6 @@ int link_carrier_reset(Link *link) {
return 0;
}
-
int link_update(Link *link, sd_netlink_message *m) {
struct ether_addr mac;
const char *ifname;
@@ -2649,6 +2780,21 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
}
if (link->dhcp6_client) {
@@ -2658,6 +2804,24 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
+
+ r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
+ link->network->iaid);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
+
+ if (link->network->duid_type != _DUID_TYPE_INVALID)
+ r = sd_dhcp6_client_set_duid(link->dhcp6_client,
+ link->network->dhcp_duid_type,
+ link->network->dhcp_duid,
+ link->network->dhcp_duid_len);
+ else
+ r = sd_dhcp6_client_set_duid(link->dhcp6_client,
+ link->manager->dhcp_duid_type,
+ link->manager->dhcp_duid,
+ link->manager->dhcp_duid_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
}
}
}
@@ -2668,6 +2832,10 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0)
return r;
+ r = link_update_lldp(link);
+ if (r < 0)
+ return r;
+
carrier_gained = !had_carrier && link_has_carrier(link);
carrier_lost = had_carrier && !link_has_carrier(link);
@@ -2683,12 +2851,34 @@ int link_update(Link *link, sd_netlink_message *m) {
r = link_carrier_lost(link);
if (r < 0)
return r;
-
}
return 0;
}
+static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
+ bool space = false;
+ Iterator i;
+ Link *link;
+
+ assert(f);
+ assert(prefix);
+
+ if (hashmap_isempty(h))
+ return;
+
+ fputs(prefix, f);
+ HASHMAP_FOREACH(link, h, i) {
+ if (space)
+ fputc(' ', f);
+
+ fprintf(f, "%i", link->ifindex);
+ space = true;
+ }
+
+ fputc('\n', f);
+}
+
int link_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -2708,6 +2898,8 @@ int link_save(Link *link) {
return 0;
}
+ link_lldp_save(link);
+
admin_state = link_state_to_string(link->state);
assert(admin_state);
@@ -2887,27 +3079,8 @@ int link_save(Link *link) {
fputc('\n', f);
}
- if (!hashmap_isempty(link->bound_to_links)) {
- Link *carrier;
- bool space = false;
-
- fputs("CARRIER_BOUND_TO=", f);
- HASHMAP_FOREACH(carrier, link->bound_to_links, i)
- fputs_with_space(f, carrier->ifname, NULL, &space);
-
- fputc('\n', f);
- }
-
- if (!hashmap_isempty(link->bound_by_links)) {
- Link *carrier;
- bool space = false;
-
- fputs("CARRIER_BOUND_BY=", f);
- HASHMAP_FOREACH(carrier, link->bound_by_links, i)
- fputs_with_space(f, carrier->ifname, NULL, &space);
-
- fputc('\n', f);
- }
+ print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links);
+ print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links);
if (link->dhcp_lease) {
struct in_addr address;
@@ -2947,19 +3120,6 @@ int link_save(Link *link) {
}
}
- if (link->lldp) {
- assert(link->network);
-
- r = sd_lldp_save(link->lldp, link->lldp_file);
- if (r < 0)
- goto fail;
-
- fprintf(f,
- "LLDP_FILE=%s\n",
- link->lldp_file);
- } else
- unlink(link->lldp_file);
-
r = fflush_and_check(f);
if (r < 0)
goto fail;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 0e6a7b6f21..f2a64ca9b5 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -65,6 +65,7 @@ struct Link {
int ifindex;
char *ifname;
+ unsigned short iftype;
char *state_file;
struct ether_addr mac;
struct in6_addr ipv6ll_address;
@@ -111,9 +112,14 @@ struct Link {
sd_dhcp6_client *dhcp6_client;
bool rtnl_extended_attrs;
+ /* This is about LLDP reception */
sd_lldp *lldp;
char *lldp_file;
+ /* This is about LLDP transmission */
+ unsigned lldp_tx_fast; /* The LLDP txFast counter (See 802.1ab-2009, section 9.2.5.18) */
+ sd_event_source *lldp_tx_event_source;
+
Hashmap *bound_by_links;
Hashmap *bound_to_links;
};
@@ -154,14 +160,6 @@ int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link);
int ndisc_configure(Link *link);
-bool link_lldp_enabled(Link *link);
-bool link_ipv4ll_enabled(Link *link);
-bool link_ipv6ll_enabled(Link *link);
-bool link_dhcp4_server_enabled(Link *link);
-bool link_dhcp4_enabled(Link *link);
-bool link_dhcp6_enabled(Link *link);
-bool link_ipv6_accept_ra_enabled(Link *link);
-
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c
new file mode 100644
index 0000000000..5af2a31ea7
--- /dev/null
+++ b/src/network/networkd-lldp-tx.c
@@ -0,0 +1,346 @@
+/***
+ 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 <endian.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "hostname-util.h"
+#include "networkd-lldp-tx.h"
+#include "random-util.h"
+#include "socket-util.h"
+#include "string-util.h"
+#include "unaligned.h"
+
+/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */
+#define LLDP_TX_FAST_INIT 4U
+
+/* The LLDP spec calls this "msgTxHold", see 9.2.5.6 */
+#define LLDP_TX_HOLD 4U
+
+/* The jitter range to add, see 9.2.2. */
+#define LLDP_JITTER_USEC (400U * USEC_PER_MSEC)
+
+/* The LLDP spec calls this msgTxInterval, but we subtract half the jitter off it. */
+#define LLDP_TX_INTERVAL_USEC (30U * USEC_PER_SEC - LLDP_JITTER_USEC / 2)
+
+/* The LLDP spec calls this msgFastTx, but we subtract half the jitter off it. */
+#define LLDP_FAST_TX_USEC (1U * USEC_PER_SEC - LLDP_JITTER_USEC / 2)
+
+static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) {
+ assert(p);
+
+ if (id > 127)
+ return -EBADMSG;
+ if (sz > 511)
+ return -ENOBUFS;
+
+ (*p)[0] = (id << 1) | !!(sz & 256);
+ (*p)[1] = sz & 255;
+
+ *p = *p + 2;
+ return 0;
+}
+
+static int lldp_make_packet(
+ const struct ether_addr *hwaddr,
+ const char *machine_id,
+ const char *ifname,
+ uint16_t ttl,
+ const char *port_description,
+ const char *hostname,
+ const char *pretty_hostname,
+ uint16_t system_capabilities,
+ uint16_t enabled_capabilities,
+ void **ret, size_t *sz) {
+
+ size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0, pretty_hostname_length = 0;
+ _cleanup_free_ void *packet = NULL;
+ struct ether_header *h;
+ uint8_t *p;
+ size_t l;
+ int r;
+
+ assert(hwaddr);
+ assert(machine_id);
+ assert(ifname);
+ assert(ret);
+ assert(sz);
+
+ machine_id_length = strlen(machine_id);
+ ifname_length = strlen(ifname);
+
+ if (port_description)
+ port_description_length = strlen(port_description);
+
+ if (hostname)
+ hostname_length = strlen(hostname);
+
+ if (pretty_hostname)
+ pretty_hostname_length = strlen(pretty_hostname);
+
+ l = sizeof(struct ether_header) +
+ /* Chassis ID */
+ 2 + 1 + machine_id_length +
+ /* Port ID */
+ 2 + 1 + ifname_length +
+ /* TTL */
+ 2 + 2 +
+ /* System Capabilities */
+ 2 + 4 +
+ /* End */
+ 2;
+
+ /* Port Description */
+ if (port_description)
+ l += 2 + port_description_length;
+
+ /* System Name */
+ if (hostname)
+ l += 2 + hostname_length;
+
+ /* System Description */
+ if (pretty_hostname)
+ l += 2 + pretty_hostname_length;
+
+ packet = malloc(l);
+ if (!packet)
+ return -ENOMEM;
+
+ h = (struct ether_header*) packet;
+ h->ether_type = htobe16(ETHERTYPE_LLDP);
+ memcpy(h->ether_dhost, &(struct ether_addr) { SD_LLDP_MULTICAST_ADDR }, ETH_ALEN);
+ memcpy(h->ether_shost, hwaddr, ETH_ALEN);
+
+ p = (uint8_t*) packet + sizeof(struct ether_header);
+
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length);
+ if (r < 0)
+ return r;
+ *(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED;
+ p = mempcpy(p, machine_id, machine_id_length);
+
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length);
+ if (r < 0)
+ return r;
+ *(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME;
+ p = mempcpy(p, ifname, ifname_length);
+
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2);
+ if (r < 0)
+ return r;
+ unaligned_write_be16(p, ttl);
+ p += 2;
+
+ if (port_description) {
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length);
+ if (r < 0)
+ return r;
+ p = mempcpy(p, port_description, port_description_length);
+ }
+
+ if (hostname) {
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length);
+ if (r < 0)
+ return r;
+ p = mempcpy(p, hostname, hostname_length);
+ }
+
+ if (pretty_hostname) {
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length);
+ if (r < 0)
+ return r;
+ p = mempcpy(p, pretty_hostname, pretty_hostname_length);
+ }
+
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
+ if (r < 0)
+ return r;
+ unaligned_write_be16(p, system_capabilities);
+ p += 2;
+ unaligned_write_be16(p, enabled_capabilities);
+ p += 2;
+
+ r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0);
+ if (r < 0)
+ return r;
+
+ assert(p == (uint8_t*) packet + l);
+
+ *ret = packet;
+ *sz = l;
+
+ packet = NULL;
+ return 0;
+}
+
+static int lldp_send_packet(int ifindex, const void *packet, size_t packet_size) {
+
+ union sockaddr_union sa = {
+ .ll.sll_family = AF_PACKET,
+ .ll.sll_protocol = htobe16(ETHERTYPE_LLDP),
+ .ll.sll_ifindex = ifindex,
+ .ll.sll_halen = ETH_ALEN,
+ .ll.sll_addr = SD_LLDP_MULTICAST_ADDR,
+ };
+
+ _cleanup_close_ int fd = -1;
+ ssize_t l;
+
+ assert(ifindex > 0);
+ assert(packet || packet_size <= 0);
+
+ fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW);
+ if (fd < 0)
+ return -errno;
+
+ l = sendto(fd, packet, packet_size, MSG_NOSIGNAL, &sa.sa, sizeof(sa.ll));
+ if (l < 0)
+ return -errno;
+
+ if ((size_t) l != packet_size)
+ return -EIO;
+
+ return 0;
+}
+
+static int link_send_lldp(Link *link) {
+ char machine_id_string[SD_ID128_STRING_MAX];
+ _cleanup_free_ char *hostname = NULL, *pretty_hostname = NULL;
+ _cleanup_free_ void *packet = NULL;
+ size_t packet_size = 0;
+ sd_id128_t machine_id;
+ uint16_t caps;
+ usec_t ttl;
+ int r;
+
+ r = sd_id128_get_machine(&machine_id);
+ if (r < 0)
+ return r;
+
+ (void) gethostname_strict(&hostname);
+ (void) parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &pretty_hostname, NULL);
+
+ ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC);
+ if (ttl > (usec_t) UINT16_MAX)
+ ttl = (usec_t) UINT16_MAX;
+
+ caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ?
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER :
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION;
+
+ r = lldp_make_packet(&link->mac,
+ sd_id128_to_string(machine_id, machine_id_string),
+ link->ifname,
+ (uint16_t) ttl,
+ link->network ? link->network->description : NULL,
+ hostname,
+ pretty_hostname,
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
+ caps,
+ &packet, &packet_size);
+ if (r < 0)
+ return r;
+
+ return lldp_send_packet(link->ifindex, packet, packet_size);
+}
+
+static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) {
+ Link *link = userdata;
+ usec_t current, delay, next;
+ int r;
+
+ assert(s);
+ assert(userdata);
+
+ log_link_debug(link, "Sending LLDP packet...");
+
+ r = link_send_lldp(link);
+ if (r < 0)
+ log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m");
+
+ if (link->lldp_tx_fast > 0)
+ link->lldp_tx_fast--;
+
+ assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), &current) >= 0);
+
+ delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC;
+ next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC);
+
+ r = sd_event_source_set_time(s, next);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m");
+
+ r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m");
+
+ return 0;
+}
+
+int link_lldp_tx_start(Link *link) {
+ usec_t next;
+ int r;
+
+ assert(link);
+
+ /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */
+
+ link->lldp_tx_fast = LLDP_TX_FAST_INIT;
+
+ next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC),
+ (usec_t) random_u64() % LLDP_JITTER_USEC);
+
+ if (link->lldp_tx_event_source) {
+ usec_t old;
+
+ /* Lower the timeout, maybe */
+ r = sd_event_source_get_time(link->lldp_tx_event_source, &old);
+ if (r < 0)
+ return r;
+
+ if (old <= next)
+ return 0;
+
+ return sd_event_source_set_time(link->lldp_tx_event_source, next);
+ } else {
+ r = sd_event_add_time(
+ link->manager->event,
+ &link->lldp_tx_event_source,
+ clock_boottime_or_monotonic(),
+ next,
+ 0,
+ on_lldp_timer,
+ link);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_source_set_description(link->lldp_tx_event_source, "lldp-tx");
+ }
+
+ return 0;
+}
+
+void link_lldp_tx_stop(Link *link) {
+ assert(link);
+
+ link->lldp_tx_event_source = sd_event_source_unref(link->lldp_tx_event_source);
+}
diff --git a/src/bootchart/store.h b/src/network/networkd-lldp-tx.h
index 6e9acf2a6f..8c7f403005 100644
--- a/src/bootchart/store.h
+++ b/src/network/networkd-lldp-tx.h
@@ -3,10 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.com>
+ 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
@@ -22,15 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
-
-#include "bootchart.h"
+#include "networkd-link.h"
-double gettime_ns(void);
-void log_uptime(void);
-int log_sample(DIR *proc,
- int sample,
- struct ps_struct *ps_first,
- struct list_sample_data **ptr,
- int *pscount,
- int *cpus);
+int link_lldp_tx_start(Link *link);
+void link_lldp_tx_stop(Link *link);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index b8cb7f875d..d355aaa19c 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1037,6 +1037,8 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
+ m->duid_type = _DUID_TYPE_INVALID;
+
*ret = m;
m = NULL;
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index f2287be20a..4577292e44 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -19,6 +19,7 @@
#include <netinet/ether.h>
#include <netinet/icmp6.h>
+#include <netinet/in.h>
#include <linux/if.h>
#include "sd-ndisc.h"
@@ -32,7 +33,7 @@ static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *
assert(link);
assert(link->ndisc_messages > 0);
- link->ndisc_messages --;
+ link->ndisc_messages--;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -76,15 +77,15 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8);
else {
/* see RFC4291 section 2.5.1 */
- address->in_addr.in6.__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0];
- address->in_addr.in6.__in6_u.__u6_addr8[8] ^= 1 << 1;
- address->in_addr.in6.__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1];
- address->in_addr.in6.__in6_u.__u6_addr8[10] = link->mac.ether_addr_octet[2];
- address->in_addr.in6.__in6_u.__u6_addr8[11] = 0xff;
- address->in_addr.in6.__in6_u.__u6_addr8[12] = 0xfe;
- address->in_addr.in6.__in6_u.__u6_addr8[13] = link->mac.ether_addr_octet[3];
- address->in_addr.in6.__in6_u.__u6_addr8[14] = link->mac.ether_addr_octet[4];
- address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
+ address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0];
+ address->in_addr.in6.s6_addr[8] ^= 1 << 1;
+ address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1];
+ address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2];
+ address->in_addr.in6.s6_addr[11] = 0xff;
+ address->in_addr.in6.s6_addr[12] = 0xfe;
+ address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3];
+ address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4];
+ address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5];
}
address->prefixlen = prefixlen;
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
@@ -98,7 +99,7 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
return;
}
- link->ndisc_messages ++;
+ link->ndisc_messages++;
}
static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata) {
@@ -136,7 +137,7 @@ static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *pre
return;
}
- link->ndisc_messages ++;
+ link->ndisc_messages++;
}
static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
@@ -186,7 +187,7 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
return;
}
- link->ndisc_messages ++;
+ link->ndisc_messages++;
}
static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
index 106f15fabc..6b9cbcded6 100644
--- a/src/network/networkd-netdev-bond.c
+++ b/src/network/networkd-netdev-bond.c
@@ -375,7 +375,7 @@ int config_parse_arp_ip_target_address(const char *unit,
}
LIST_PREPEND(arp_ip_target, b->arp_ip_targets, buffer);
- b->n_arp_ip_targets ++;
+ b->n_arp_ip_targets++;
buffer = NULL;
}
diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h
index b2bf7e15f1..27f26f7870 100644
--- a/src/network/networkd-netdev-bridge.h
+++ b/src/network/networkd-netdev-bridge.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct Bridge Bridge;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-dummy.h b/src/network/networkd-netdev-dummy.h
index 29f75a149b..42da62ebe4 100644
--- a/src/network/networkd-netdev-dummy.h
+++ b/src/network/networkd-netdev-dummy.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct Dummy Dummy;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-ipvlan.h b/src/network/networkd-netdev-ipvlan.h
index 5b85ef2150..4bd0b67866 100644
--- a/src/network/networkd-netdev-ipvlan.h
+++ b/src/network/networkd-netdev-ipvlan.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct IPVlan IPVlan;
#include "missing.h"
diff --git a/src/network/networkd-netdev-macvlan.h b/src/network/networkd-netdev-macvlan.h
index 8b42684de6..622ef9ef53 100644
--- a/src/network/networkd-netdev-macvlan.h
+++ b/src/network/networkd-netdev-macvlan.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct MacVlan MacVlan;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 46ff2974f4..7aaa041ba3 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -54,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 || t->family != -1);
+ assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
@@ -87,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 || t->family != -1);
+ assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
@@ -124,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 || t->family != -1);
+ assert(IN_SET(t->family, AF_INET, AF_UNSPEC));
assert(link);
assert(m);
@@ -497,7 +497,7 @@ static void ipip_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
- t->family = -1;
+ t->family = AF_UNSPEC;
}
static void sit_init(NetDev *n) {
@@ -507,7 +507,7 @@ static void sit_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
- t->family = -1;
+ t->family = AF_UNSPEC;
}
static void vti_init(NetDev *n) {
@@ -538,7 +538,7 @@ static void gre_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
- t->family = -1;
+ t->family = AF_UNSPEC;
}
static void ip6gre_init(NetDev *n) {
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
index ea1d9a79e7..0d41f80a3c 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct Tunnel Tunnel;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
index ab9a1b0426..32917fe6d5 100644
--- a/src/network/networkd-netdev-tuntap.c
+++ b/src/network/networkd-netdev-tuntap.c
@@ -20,6 +20,7 @@
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>
+#include <netinet/if_ether.h>
#include "alloc-util.h"
#include "fd-util.h"
@@ -87,7 +88,7 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
assert(t);
- if(t->user_name) {
+ if (t->user_name) {
user = t->user_name;
@@ -126,7 +127,7 @@ static int netdev_create_tuntap(NetDev *netdev) {
int r;
r = netdev_fill_tuntap_message(netdev, &ifr);
- if(r < 0)
+ if (r < 0)
return r;
return netdev_tuntap_add(netdev, &ifr);
diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h
index b970b0ce3b..cbb7ee05a6 100644
--- a/src/network/networkd-netdev-tuntap.h
+++ b/src/network/networkd-netdev-tuntap.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct TunTap TunTap;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-veth.h b/src/network/networkd-netdev-veth.h
index f7fdf906ab..ae5785783c 100644
--- a/src/network/networkd-netdev-veth.h
+++ b/src/network/networkd-netdev-veth.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct Veth Veth;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-vlan.h b/src/network/networkd-netdev-vlan.h
index 8701c4b785..1de6a1cc36 100644
--- a/src/network/networkd-netdev-vlan.h
+++ b/src/network/networkd-netdev-vlan.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct VLan VLan;
#include "networkd-netdev.h"
diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c
index eb9a2c06b3..dabbd97c87 100644
--- a/src/network/networkd-netdev-vxlan.c
+++ b/src/network/networkd-netdev-vxlan.c
@@ -54,13 +54,13 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m");
- if(v->ttl) {
+ if (v->ttl) {
r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m");
}
- if(v->tos) {
+ if (v->tos) {
r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TOS, v->tos);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TOS attribute: %m");
@@ -86,7 +86,7 @@ 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_L3MISS attribute: %m");
- if(v->fdb_ageing) {
+ if (v->fdb_ageing) {
r = sd_netlink_message_append_u32(m, IFLA_VXLAN_AGEING, v->fdb_ageing / USEC_PER_SEC);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_AGEING attribute: %m");
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
index 459ce53f5e..a4bb44635a 100644
--- a/src/network/networkd-netdev-vxlan.h
+++ b/src/network/networkd-netdev-vxlan.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
typedef struct VxLan VxLan;
#include "in-addr-util.h"
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 3eacee824b..7ea825fcb4 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "list.h"
typedef struct NetDev NetDev;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 409df1709f..9793938080 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -2,6 +2,7 @@
#include <stddef.h>
#include "conf-parser.h"
#include "networkd.h"
+#include "networkd-conf.h"
#include "network-internal.h"
%}
struct ConfigPerfItem;
@@ -26,6 +27,9 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Link.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
+DUID.Type, config_parse_duid_type, 0, offsetof(Network, duid_type)
+DUID.RawData, config_parse_duid_rawdata, DUID_CONFIG_SOURCE_NETWORK, offsetof(Network, dhcp_duid)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
@@ -40,7 +44,8 @@ Network.DHCPServer, config_parse_bool,
Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local)
Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token)
-Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
+Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode)
+Network.EmitLLDP, config_parse_bool, 0, offsetof(Network, lldp_emit)
Network.Address, config_parse_address, 0, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.Domains, config_parse_domains, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 4315790093..5946ba18dc 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -119,6 +119,8 @@ static int network_load_one(Manager *manager, const char *filename) {
network->allow_port_to_be_root = true;
network->unicast_flood = true;
+ network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
+
network->llmnr = RESOLVE_SUPPORT_YES;
network->mdns = RESOLVE_SUPPORT_NO;
network->dnssec_mode = _DNSSEC_MODE_INVALID;
@@ -129,10 +131,12 @@ static int network_load_one(Manager *manager, const char *filename) {
network->ipv6_accept_ra = -1;
network->ipv6_dad_transmits = -1;
network->ipv6_hop_limit = -1;
+ network->duid_type = _DUID_TYPE_INVALID;
r = config_parse(NULL, filename, file,
"Match\0"
"Link\0"
+ "DUID\0"
"Network\0"
"Address\0"
"Route\0"
@@ -627,10 +631,7 @@ int config_parse_ipv4ll(
* config_parse_address_family_boolean(), except that it
* applies only to IPv4 */
- if (parse_boolean(rvalue))
- *link_local |= ADDRESS_FAMILY_IPV4;
- else
- *link_local &= ~ADDRESS_FAMILY_IPV4;
+ SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
return 0;
}
@@ -994,6 +995,10 @@ int config_parse_dnssec_negative_trust_anchors(
continue;
}
+ r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
+ if (r < 0)
+ return log_oom();
+
r = set_put(n->dnssec_negative_trust_anchors, w);
if (r < 0)
return log_oom();
@@ -1013,3 +1018,13 @@ static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
+
+static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
+ [LLDP_MODE_NO] = "no",
+ [LLDP_MODE_YES] = "yes",
+ [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 03c3f206c3..5400a8bc9d 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -24,6 +24,7 @@
typedef struct Network Network;
+#include "dhcp-identifier.h"
#include "networkd-address.h"
#include "networkd-fdb.h"
#include "networkd-netdev.h"
@@ -58,6 +59,14 @@ typedef enum DHCPUseDomains {
_DHCP_USE_DOMAINS_INVALID = -1,
} DHCPUseDomains;
+typedef enum LLDPMode {
+ LLDP_MODE_NO = 0,
+ LLDP_MODE_YES = 1,
+ LLDP_MODE_ROUTERS_ONLY = 2,
+ _LLDP_MODE_MAX,
+ _LLDP_MODE_INVALID = -1,
+} LLDPMode;
+
struct Network {
Manager *manager;
@@ -136,8 +145,16 @@ struct Network {
struct ether_addr *mac;
unsigned mtu;
+ uint32_t iaid;
+ /* Value of Type in [DUID] section */
+ DUIDType duid_type;
+ /* DUID type code - RFC 3315 */
+ uint16_t dhcp_duid_type;
+ size_t dhcp_duid_len;
+ uint8_t dhcp_duid[MAX_DUID_LEN];
- bool lldp;
+ LLDPMode lldp_mode; /* LLDP reception */
+ bool lldp_emit; /* LLDP transmission */
LIST_HEAD(Address, static_addresses);
LIST_HEAD(Route, static_routes);
@@ -181,6 +198,7 @@ int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigne
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);
+int config_parse_lldp_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);
/* 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);
@@ -197,3 +215,6 @@ IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
+
+const char* lldp_mode_to_string(LLDPMode m) _const_;
+LLDPMode lldp_mode_from_string(const char *s) _pure_;
diff --git a/src/network/networkd-wait-online.h b/src/network/networkd-wait-online.h
index 421c2bdf44..f91995c306 100644
--- a/src/network/networkd-wait-online.h
+++ b/src/network/networkd-wait-online.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "sd-event.h"
#include "sd-netlink.h"
#include "sd-network.h"
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 3a2615e6fd..c8f81a2ca6 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -21,6 +21,7 @@
#include "capability-util.h"
#include "networkd.h"
+#include "networkd-conf.h"
#include "signal-util.h"
#include "user-util.h"
@@ -89,6 +90,10 @@ int main(int argc, char *argv[]) {
goto out;
}
+ r = manager_parse_config_file(m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse configuration file: %m");
+
r = manager_load_config(m);
if (r < 0) {
log_error_errno(r, "Could not load configuration files: %m");
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 7ee922621a..72a2438ac8 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <arpa/inet.h>
#include "sd-bus.h"
@@ -31,6 +31,7 @@
typedef struct Manager Manager;
+#include "dhcp-identifier.h"
#include "networkd-address-pool.h"
#include "networkd-link.h"
#include "networkd-network.h"
@@ -61,6 +62,13 @@ struct Manager {
LIST_HEAD(AddressPool, address_pools);
usec_t network_dirs_ts_usec;
+
+ /* Value of Type in [DUID] section */
+ DUIDType duid_type;
+ /* DUID type code - RFC 3315 */
+ uint16_t dhcp_duid_type;
+ size_t dhcp_duid_len;
+ uint8_t dhcp_duid[MAX_DUID_LEN];
};
extern const char* const network_dirs[];
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index 1db5ba7116..f50f1ad6c2 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -55,8 +55,7 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) {
"cgroup.events",
"cgroup.clone_children",
"cgroup.controllers",
- "cgroup.subtree_control",
- "cgroup.populated")
+ "cgroup.subtree_control")
if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0)
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
"Failed to chown() cgroup file %s, ignoring: %m", fn);
@@ -73,7 +72,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if ((unified > 0) == unified_requested)
return 0;
@@ -94,7 +93,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) {
if (unified)
r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr");
else
- r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior");
+ r = mount("cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
if (r < 0) {
r = log_error_errno(errno, "Failed to mount unified hierarchy: %m");
goto finish;
@@ -135,7 +134,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if (unified == 0)
return 0;
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 70cca15278..8e2d2d543c 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -438,21 +438,22 @@ static int mount_bind(const char *dest, CustomMount *m) {
r = mkdir_parents_label(where, 0755);
if (r < 0)
return log_error_errno(r, "Failed to make parents of %s: %m", where);
+
+ /* Create the mount point. Any non-directory file can be
+ * mounted on any non-directory file (regular, fifo, socket,
+ * char, block).
+ */
+ if (S_ISDIR(source_st.st_mode))
+ r = mkdir_label(where, 0755);
+ else
+ r = touch(where);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create mount point %s: %m", where);
+
} else {
return log_error_errno(errno, "Failed to stat %s: %m", where);
}
- /* Create the mount point. Any non-directory file can be
- * mounted on any non-directory file (regular, fifo, socket,
- * char, block).
- */
- if (S_ISDIR(source_st.st_mode))
- r = mkdir_label(where, 0755);
- else
- r = touch(where);
- if (r < 0 && r != -EEXIST)
- return log_error_errno(r, "Failed to create mount point %s: %m", where);
-
if (mount(m->source, where, NULL, mount_flags, mount_opts) < 0)
return log_error_errno(errno, "mount(%s) failed: %m", where);
@@ -750,7 +751,7 @@ static int mount_unified_cgroups(const char *dest) {
return -EINVAL;
}
- if (mount("cgroup", p, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior") < 0)
+ if (mount("cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0)
return log_error_errno(errno, "Failed to mount unified cgroup hierarchy to %s: %m", p);
return 0;
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index fcb1efaa74..74a0ae865b 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -232,7 +232,7 @@ int setup_veth_extra(
if (r < 0)
return r;
- idx ++;
+ idx++;
}
return 0;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 5a68fec603..eb89916b7e 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -87,6 +87,7 @@
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stat-util.h"
@@ -561,7 +562,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_CAPABILITY:
case ARG_DROP_CAPABILITY: {
p = optarg;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *t = NULL;
r = extract_first_word(&p, &t, ",", 0);
@@ -976,6 +977,13 @@ static int verify_arguments(void) {
return -EINVAL;
}
+#ifndef HAVE_LIBIPTC
+ if (arg_expose_ports) {
+ log_error("--port= is not supported, compiled without libiptc support.");
+ return -EOPNOTSUPP;
+ }
+#endif
+
if (arg_start_mode == START_BOOT && arg_kill_signal <= 0)
arg_kill_signal = SIGRTMIN+3;
@@ -2560,7 +2568,7 @@ static int inner_child(
envp[n_env] = strv_find_prefix(environ, "TERM=");
if (envp[n_env])
- n_env ++;
+ n_env++;
if ((asprintf((char**)(envp + n_env++), "HOME=%s", home ? home: "/root") < 0) ||
(asprintf((char**)(envp + n_env++), "USER=%s", arg_user ? arg_user : "root") < 0) ||
@@ -3284,6 +3292,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_selinux_apifs_context) {
+ r = mac_selinux_apply(console, arg_selinux_apifs_context);
+ if (r < 0)
+ goto finish;
+ }
+
if (unlockpt(master) < 0) {
r = log_error_errno(errno, "Failed to unlock tty: %m");
goto finish;
@@ -3618,7 +3632,7 @@ int main(int argc, char *argv[]) {
/* We failed to wait for the container, or the
* container exited abnormally */
goto finish;
- else if (r > 0 || container_status == CONTAINER_TERMINATED){
+ else if (r > 0 || container_status == CONTAINER_TERMINATED) {
/* The container exited with a non-zero
* status, or with zero status and no reboot
* was requested. */
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 1582d702f8..8d57b26cbc 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -66,7 +66,7 @@ static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
if (af != AF_UNSPEC && family != af)
continue;
- c ++;
+ c++;
}
if (r < 0)
return r;
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index 69c0d9bdc1..0de6bd2241 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -90,7 +90,7 @@ static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
if (af != AF_UNSPEC && family != af)
continue;
- c ++;
+ c++;
}
if (r < 0)
return r;
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
index db9666b970..7b79d29d7e 100644
--- a/src/resolve/dns-type.h
+++ b/src/resolve/dns-type.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "macro.h"
/* DNS record types, taken from
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index a519074278..14ee01c49d 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <gcrypt.h>
#include <getopt.h>
#include <net/if.h>
@@ -44,12 +43,19 @@ static uint16_t arg_class = 0;
static bool arg_legend = true;
static uint64_t arg_flags = 0;
+typedef enum ServiceFamily {
+ SERVICE_FAMILY_TCP,
+ SERVICE_FAMILY_UDP,
+ SERVICE_FAMILY_SCTP,
+ _SERVICE_FAMILY_INVALID = -1,
+} ServiceFamily;
+static ServiceFamily arg_service_family = SERVICE_FAMILY_TCP;
+
typedef enum RawType {
RAW_NONE,
RAW_PAYLOAD,
RAW_PACKET,
} RawType;
-
static RawType arg_raw = RAW_NONE;
static enum {
@@ -57,10 +63,34 @@ static enum {
MODE_RESOLVE_RECORD,
MODE_RESOLVE_SERVICE,
MODE_RESOLVE_OPENPGP,
+ MODE_RESOLVE_TLSA,
MODE_STATISTICS,
MODE_RESET_STATISTICS,
} arg_mode = MODE_RESOLVE_HOST;
+static ServiceFamily service_family_from_string(const char *s) {
+ if (s == NULL || streq(s, "tcp"))
+ return SERVICE_FAMILY_TCP;
+ if (streq(s, "udp"))
+ return SERVICE_FAMILY_UDP;
+ if (streq(s, "sctp"))
+ return SERVICE_FAMILY_SCTP;
+ return _SERVICE_FAMILY_INVALID;
+}
+
+static const char* service_family_to_string(ServiceFamily service) {
+ switch(service) {
+ case SERVICE_FAMILY_TCP:
+ return "_tcp";
+ case SERVICE_FAMILY_UDP:
+ return "_udp";
+ case SERVICE_FAMILY_SCTP:
+ return "_sctp";
+ default:
+ assert_not_reached("invalid service");
+ }
+}
+
static void print_source(uint64_t flags, usec_t rtt) {
char rtt_str[FORMAT_TIMESTAMP_MAX];
@@ -832,7 +862,7 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
}
domain++;
- r = string_hashsum(address, domain - 1 - address, GCRY_MD_SHA224, &hashed);
+ r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
if (r < 0)
return log_error_errno(r, "Hashing failed: %m");
@@ -844,6 +874,38 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
arg_type ?: DNS_TYPE_OPENPGPKEY);
}
+static int resolve_tlsa(sd_bus *bus, const char *address) {
+ const char *port;
+ uint16_t port_num = 443;
+ _cleanup_free_ char *full = NULL;
+ int r;
+
+ assert(bus);
+ assert(address);
+
+ port = strrchr(address, ':');
+ if (port) {
+ r = safe_atou16(port + 1, &port_num);
+ if (r < 0 || port_num == 0)
+ return log_error_errno(r, "Invalid port \"%s\".", port + 1);
+
+ address = strndupa(address, port - address);
+ }
+
+ r = asprintf(&full, "_%u.%s.%s",
+ port_num,
+ service_family_to_string(arg_service_family),
+ address);
+ if (r < 0)
+ return log_oom();
+
+ log_debug("Looking up \"%s\".", full);
+
+ return resolve_record(bus, full,
+ arg_class ?: DNS_CLASS_IN,
+ arg_type ?: DNS_TYPE_TLSA);
+}
+
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;
@@ -1031,6 +1093,7 @@ static void help(void) {
" --service-address=BOOL Resolve address for services (default: yes)\n"
" --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
" --openpgp Query OpenPGP public key\n"
+ " --tlsa Query TLS public key\n"
" --cname=BOOL Follow CNAME redirects (default: yes)\n"
" --search=BOOL Use search domains for single-label names\n"
" (default: yes)\n"
@@ -1050,6 +1113,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SERVICE_ADDRESS,
ARG_SERVICE_TXT,
ARG_OPENPGP,
+ ARG_TLSA,
ARG_RAW,
ARG_SEARCH,
ARG_STATISTICS,
@@ -1069,6 +1133,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
{ "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
{ "openpgp", no_argument, NULL, ARG_OPENPGP },
+ { "tlsa", optional_argument, NULL, ARG_TLSA },
{ "raw", optional_argument, NULL, ARG_RAW },
{ "search", required_argument, NULL, ARG_SEARCH },
{ "statistics", no_argument, NULL, ARG_STATISTICS, },
@@ -1183,6 +1248,15 @@ static int parse_argv(int argc, char *argv[]) {
arg_mode = MODE_RESOLVE_OPENPGP;
break;
+ case ARG_TLSA:
+ arg_mode = MODE_RESOLVE_TLSA;
+ arg_service_family = service_family_from_string(optarg);
+ if (arg_service_family < 0) {
+ log_error("Unknown service family \"%s\".", optarg);
+ return -EINVAL;
+ }
+ break;
+
case ARG_RAW:
if (on_tty()) {
log_error("Refusing to write binary data to tty.");
@@ -1205,40 +1279,28 @@ static int parse_argv(int argc, char *argv[]) {
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;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
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;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
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;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
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;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
break;
case ARG_STATISTICS:
@@ -1261,7 +1323,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (arg_type != 0 && arg_mode != MODE_RESOLVE_RECORD) {
+ if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) {
log_error("--service and --type= may not be combined.");
return -EINVAL;
}
@@ -1378,6 +1440,24 @@ int main(int argc, char **argv) {
}
break;
+ case MODE_RESOLVE_TLSA:
+ if (argc < optind + 1) {
+ log_error("Domain name required.");
+ r = -EINVAL;
+ goto finish;
+
+ }
+
+ r = 0;
+ while (optind < argc) {
+ int k;
+
+ k = resolve_tlsa(bus, argv[optind++]);
+ if (k < 0)
+ r = k;
+ }
+ break;
+
case MODE_STATISTICS:
if (argc > optind) {
log_error("Too many arguments.");
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index a138be2421..16cae8c1e5 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -188,7 +188,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
if (!canonical)
canonical = dns_resource_record_ref(rr);
- added ++;
+ added++;
}
if (added <= 0) {
@@ -418,7 +418,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
if (r < 0)
goto finish;
- added ++;
+ added++;
}
if (added <= 0) {
@@ -587,7 +587,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
if (r < 0)
goto finish;
- added ++;
+ added++;
}
if (added <= 0) {
@@ -1094,9 +1094,9 @@ static void bus_method_resolve_service_complete(DnsQuery *q) {
}
if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
- q->block_all_complete ++;
+ q->block_all_complete++;
r = resolve_service_hostname(q, rr, ifindex);
- q->block_all_complete --;
+ q->block_all_complete--;
if (r < 0)
goto finish;
@@ -1137,7 +1137,6 @@ finish:
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;
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index bb93fbfda2..990dc03b60 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -59,7 +59,7 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con
assert(m);
assert(string);
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&string, &word, NULL, 0);
@@ -114,7 +114,7 @@ int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
assert(m);
assert(string);
- for(;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES);
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
index c08f7a7edd..0dadf8b1dd 100644
--- a/src/resolve/resolved-dns-answer.c
+++ b/src/resolve/resolved-dns-answer.c
@@ -538,7 +538,7 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
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 --;
+ (*a)->n_rrs--;
continue;
} else
@@ -624,7 +624,7 @@ int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
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 --;
+ (*a)->n_rrs--;
continue;
} else
@@ -757,7 +757,7 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
assert(a);
/* Tries to extend the DnsAnswer object. And if that's not
- * possibly, since we are not the sole owner, then allocate a
+ * possible, 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. */
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 4b7672fbbf..77c42d7aad 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -402,7 +402,7 @@ static int dns_cache_put_positive(
k = dns_cache_remove_by_rr(c, rr);
log_debug("%s: %s",
k > 0 ? "Removed zero TTL entry from cache" : "Not caching zero TTL cache entry",
- dns_resource_key_to_string(i->key, key_str, sizeof key_str));
+ dns_resource_key_to_string(rr->key, key_str, sizeof key_str));
return 0;
}
@@ -497,7 +497,7 @@ static int dns_cache_put_negative(
if (nsec_ttl <= 0 || soa->soa.minimum <= 0 || soa->ttl <= 0) {
log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s",
- dns_resource_key_to_string(i->key, key_str, sizeof key_str));
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
return 0;
}
@@ -640,7 +640,7 @@ int dns_cache_put(
cache_keys = dns_answer_size(answer);
if (key)
- cache_keys ++;
+ cache_keys++;
/* Make some space for our new entries */
dns_cache_make_space(c, cache_keys);
@@ -987,7 +987,7 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
if (r < 0)
return r;
- ancount ++;
+ ancount++;
}
}
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 2e41dae656..b7907bb511 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -38,8 +38,8 @@ static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
dns_packet_rewind(rewinder->packet, rewinder->saved_rindex);
}
-#define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while(0)
-#define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while(0)
+#define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0)
+#define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0)
int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
DnsPacket *p;
@@ -1469,7 +1469,7 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta
return r;
}
- bit ++;
+ bit++;
bitmask >>= 1;
}
}
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index a7496aa586..706f8c14ed 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -62,6 +62,7 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
while ((t = set_steal_first(c->transactions))) {
set_remove(t->notify_query_candidates, c);
+ set_remove(t->notify_query_candidates_done, c);
dns_transaction_gc(t);
}
}
@@ -139,6 +140,10 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->notify_query_candidates, c);
if (r < 0)
goto gc;
@@ -927,7 +932,7 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
assert(q);
- q->n_cname_redirects ++;
+ q->n_cname_redirects++;
if (q->n_cname_redirects > CNAME_MAX)
return -ELOOP;
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index d0a86ef206..6a29a93a26 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -1116,40 +1116,30 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
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)
+ t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
+ if (!t)
return NULL;
- r = asprintf(&ss, "%s\n"
+ r = asprintf(&s,
+ "%s %u %u %u %s\n"
" -- Cert. usage: %s\n"
" -- Selector: %s\n"
" -- Matching type: %s",
- s,
+ k,
+ rr->tlsa.cert_usage,
+ rr->tlsa.selector,
+ rr->tlsa.matching_type,
+ t,
cert_usage,
selector,
matching_type);
if (r < 0)
return NULL;
- free(s);
- s = ss;
break;
}
@@ -1228,13 +1218,16 @@ ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
case DNS_TYPE_MX:
case DNS_TYPE_LOC:
case DNS_TYPE_DS:
- case DNS_TYPE_SSHFP:
case DNS_TYPE_DNSKEY:
case DNS_TYPE_RRSIG:
case DNS_TYPE_NSEC:
case DNS_TYPE_NSEC3:
return -EINVAL;
+ case DNS_TYPE_SSHFP:
+ *out = rr->sshfp.fingerprint;
+ return rr->sshfp.fingerprint_size;
+
case DNS_TYPE_TLSA:
*out = rr->tlsa.data;
return rr->tlsa.data_size;
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 646e34598d..020a2abd77 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -82,7 +82,7 @@ enum {
struct DnsResourceKey {
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()! */
+ char *_name; /* don't access directly, use dns_resource_key_name()! */
};
/* Creates a temporary resource key. This is only useful to quickly
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 27342a0e04..49d488cec5 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -120,7 +120,7 @@ DnsServer* dns_server_ref(DnsServer *s) {
return NULL;
assert(s->n_ref > 0);
- s->n_ref ++;
+ s->n_ref++;
return s;
}
@@ -130,7 +130,7 @@ DnsServer* dns_server_unref(DnsServer *s) {
return NULL;
assert(s->n_ref > 0);
- s->n_ref --;
+ s->n_ref--;
if (s->n_ref > 0)
return NULL;
@@ -290,9 +290,9 @@ void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel le
if (s->possible_feature_level == level) {
if (protocol == IPPROTO_UDP)
- s->n_failed_udp ++;
+ s->n_failed_udp++;
else if (protocol == IPPROTO_TCP)
- s->n_failed_tcp ++;
+ s->n_failed_tcp++;
}
if (s->resend_timeout > usec)
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 3443f71976..a5129c201e 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -52,6 +52,7 @@ static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) {
while ((z = set_steal_first(t->dnssec_transactions))) {
set_remove(z->notify_transactions, t);
+ set_remove(z->notify_transactions_done, t);
dns_transaction_gc(z);
}
}
@@ -100,14 +101,26 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
set_remove(c->transactions, t);
set_free(t->notify_query_candidates);
+ while ((c = set_steal_first(t->notify_query_candidates_done)))
+ set_remove(c->transactions, t);
+ set_free(t->notify_query_candidates_done);
+
while ((i = set_steal_first(t->notify_zone_items)))
i->probe_transaction = NULL;
set_free(t->notify_zone_items);
+ while ((i = set_steal_first(t->notify_zone_items_done)))
+ i->probe_transaction = NULL;
+ set_free(t->notify_zone_items_done);
+
while ((z = set_steal_first(t->notify_transactions)))
set_remove(z->dnssec_transactions, t);
set_free(t->notify_transactions);
+ while ((z = set_steal_first(t->notify_transactions_done)))
+ set_remove(z->dnssec_transactions, t);
+ set_free(t->notify_transactions_done);
+
dns_transaction_flush_dnssec_transactions(t);
set_free(t->dnssec_transactions);
@@ -127,8 +140,11 @@ bool dns_transaction_gc(DnsTransaction *t) {
return true;
if (set_isempty(t->notify_query_candidates) &&
+ set_isempty(t->notify_query_candidates_done) &&
set_isempty(t->notify_zone_items) &&
- set_isempty(t->notify_transactions)) {
+ set_isempty(t->notify_zone_items_done) &&
+ set_isempty(t->notify_transactions) &&
+ set_isempty(t->notify_transactions_done)) {
dns_transaction_free(t);
return false;
}
@@ -209,7 +225,7 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
LIST_PREPEND(transactions_by_scope, s->transactions, t);
t->scope = s;
- s->manager->n_transactions_total ++;
+ s->manager->n_transactions_total++;
if (ret)
*ret = t;
@@ -266,6 +282,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->notify_zone_items))) {
/* First, make sure the zone item drops the reference
* to us */
@@ -284,7 +301,6 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
DnsQueryCandidate *c;
DnsZoneItem *z;
DnsTransaction *d;
- Iterator i;
const char *st;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
@@ -333,39 +349,17 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
* transaction isn't freed while we are still looking at it */
t->block_gc++;
- SET_FOREACH(c, t->notify_query_candidates, i)
+ SET_FOREACH_MOVE(c, t->notify_query_candidates_done, t->notify_query_candidates)
dns_query_candidate_notify(c);
- SET_FOREACH(z, t->notify_zone_items, i)
- dns_zone_item_notify(z);
+ SWAP_TWO(t->notify_query_candidates, t->notify_query_candidates_done);
- 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));
+ SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items)
+ dns_zone_item_notify(z);
+ SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done);
- 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]);
- }
- }
+ SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions)
+ dns_transaction_notify(d, t);
+ SWAP_TWO(t->notify_transactions, t->notify_transactions_done);
t->block_gc--;
dns_transaction_gc(t);
@@ -1375,7 +1369,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
other->state = DNS_TRANSACTION_PENDING;
other->next_attempt_after = ts;
- qdcount ++;
+ qdcount++;
if (dns_key_is_shared(other->key))
add_known_answers = true;
@@ -1626,6 +1620,10 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->dnssec_transactions, aux);
if (r < 0)
goto gc;
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index 491c62d772..eaece91533 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -118,17 +118,17 @@ struct DnsTransaction {
/* Query candidates this transaction is referenced by and that
* shall be notified about this specific transaction
* completing. */
- Set *notify_query_candidates;
+ Set *notify_query_candidates, *notify_query_candidates_done;
/* Zone items this transaction is referenced by and that shall
* be notified about completion. */
- Set *notify_zone_items;
+ Set *notify_zone_items, *notify_zone_items_done;
/* 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;
+ Set *notify_transactions, *notify_transactions_done;
/* The opposite direction: the transactions this transaction
* created in order to request DNSKEY or DS RRs. */
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index 03813da6a2..850eed8cb8 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -38,6 +38,7 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
i->probe_transaction = NULL;
set_remove(t->notify_zone_items, i);
+ set_remove(t->notify_zone_items_done, i);
dns_transaction_gc(t);
}
@@ -186,6 +187,10 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&t->notify_zone_items_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->notify_zone_items, i);
if (r < 0)
goto gc;
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index 6ccbdca20e..40d650949d 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -301,7 +301,7 @@ int manager_etc_hosts_read(Manager *m) {
FOREACH_LINE(line, f, return log_error_errno(errno, "Failed to read /etc/hosts: %m")) {
char *l;
- nr ++;
+ nr++;
l = strstrip(line);
if (isempty(l))
diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c
index ef12abfbb5..8b1d71a3eb 100644
--- a/src/resolve/resolved-llmnr.c
+++ b/src/resolve/resolved-llmnr.c
@@ -286,7 +286,7 @@ static int on_llmnr_stream_packet(DnsStream *s) {
scope = manager_find_scope(s->manager, s->read_packet);
if (!scope) {
- log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
+ log_warning("Got LLMNR TCP packet on unknown scope. Ignoring.");
return 0;
}
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index 065427b690..ff03acc772 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -158,7 +158,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
if (*count == MAXNS)
fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
- (*count) ++;
+ (*count)++;
fprintf(f, "nameserver %s\n", s->server_string);
}
@@ -184,7 +184,7 @@ static void write_resolv_conf_search(
}
(*length) += strlen(domain);
- (*count) ++;
+ (*count)++;
fputc(' ', f);
fputs(domain, f);
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index c7e2ab14d6..161ea03412 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -48,7 +48,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/resolve/test-dns-packet.c b/src/resolve/test-dns-packet.c
index 1abbd3fa2e..c232a69ce1 100644
--- a/src/resolve/test-dns-packet.c
+++ b/src/resolve/test-dns-packet.c
@@ -89,7 +89,6 @@ static void test_packet_from_file(const char* filename, bool canonical) {
int main(int argc, char **argv) {
int i, N;
_cleanup_globfree_ glob_t g = {};
- _cleanup_strv_free_ char **globs = NULL;
char **fnames;
log_parse_environment();
diff --git a/src/resolve/test-dnssec.c b/src/resolve/test-dnssec.c
index a093d86a91..c9b5ffa62b 100644
--- a/src/resolve/test-dnssec.c
+++ b/src/resolve/test-dnssec.c
@@ -327,10 +327,12 @@ static void test_dnssec_nsec3_hash(void) {
int main(int argc, char*argv[]) {
test_dnssec_canonicalize();
+#ifdef HAVE_GCRYPT
test_dnssec_verify_dns_key();
test_dnssec_verify_rrset();
test_dnssec_verify_rrset2();
test_dnssec_nsec3_hash();
+#endif
return 0;
}
diff --git a/src/run/run.c b/src/run/run.c
index e7f4c21f73..f92a7f4e2e 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -83,8 +83,8 @@ static void polkit_agent_open_if_enabled(void) {
static void help(void) {
printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
"Run the specified command in a transient scope or service or timer\n"
- "unit. If timer option is specified and unit is exist which is\n"
- "specified with --unit option then command can be omitted.\n\n"
+ "unit. If a timer option is specified and the unit specified with\n"
+ "the --unit option exists, the command can be omitted.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-ask-password Do not prompt for password\n"
@@ -878,7 +878,7 @@ static int start_transient_service(
(void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
if (!arg_quiet)
- log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
+ log_info("Running as unit: %s\nPress ^] three times within 1s to disconnect TTY.", service);
r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward);
if (r < 0)
@@ -896,7 +896,7 @@ static int start_transient_service(
fputc('\n', stdout);
} else if (!arg_quiet)
- log_info("Running as unit %s.", service);
+ log_info("Running as unit: %s", service);
return 0;
}
@@ -1038,7 +1038,7 @@ static int start_transient_scope(
return r;
if (!arg_quiet)
- log_info("Running scope as unit %s.", scope);
+ log_info("Running scope as unit: %s", scope);
execvpe(argv[0], argv, env);
@@ -1189,9 +1189,9 @@ static int start_transient_timer(
if (r < 0)
return r;
- log_info("Running timer as unit %s.", timer);
+ log_info("Running timer as unit: %s", timer);
if (argv[0])
- log_info("Will run service as unit %s.", service);
+ log_info("Will run service as unit: %s", service);
return 0;
}
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index 3cb9e781fd..6779691c28 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -119,7 +119,7 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
}
if (ptr == 0)
- return -EINVAL;
+ return -ENODATA;
/* read Firmware Basic Boot Performance Data Record */
fd = open("/dev/mem", O_CLOEXEC|O_RDONLY);
@@ -146,6 +146,10 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
if (brec.type != ACPI_FPDT_BOOT_REC)
return -EINVAL;
+ if (brec.exit_services_exit == 0)
+ /* Non-UEFI compatible boot. */
+ return -ENODATA;
+
if (brec.startup_start == 0 || brec.exit_services_exit < brec.startup_start)
return -EINVAL;
if (brec.exit_services_exit > NSEC_PER_HOUR)
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index c87eaf63d8..d9dd3c6a11 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -843,7 +843,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) {
if (r < 0)
return r;
- while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
+ while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
_cleanup_free_ char *escaped = NULL;
if (first)
@@ -1068,7 +1068,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
}
case SD_BUS_TYPE_UINT32: {
- uint64_t u;
+ uint32_t u;
uint32_t *p = userdata;
r = sd_bus_message_read_basic(m, type, &u);
@@ -1412,7 +1412,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
return bus_log_create_error(r);
field = strndupa(assignment, eq - assignment);
- eq ++;
+ eq++;
if (streq(field, "CPUQuota")) {
@@ -2030,7 +2030,7 @@ static const struct {
static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) {
_cleanup_free_ char *service_shell_quoted = NULL;
- const char *systemctl = "systemctl", *journalctl = "journalct";
+ const char *systemctl = "systemctl", *journalctl = "journalctl";
assert(service);
diff --git a/src/shared/condition.c b/src/shared/condition.c
index f93785865e..3a45ed265c 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -295,7 +295,7 @@ static int condition_test_needs_update(Condition *c) {
return false;
/* Any other failure means we should allow the condition to be true,
- * so that we rather invoke too many update tools then too
+ * so that we rather invoke too many update tools than too
* few. */
if (!path_is_absolute(c->parameter))
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index e7fe9ac21e..bd0a1f483b 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -294,7 +294,7 @@ int config_parse(const char *unit,
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
unsigned line = 0, section_line = 0;
- bool section_ignored = false;
+ bool section_ignored = false, allow_bom = true;
int r;
assert(filename);
@@ -314,11 +314,11 @@ int config_parse(const char *unit,
fd_warn_permissions(filename, fileno(f));
- while (!feof(f)) {
- char l[LINE_MAX], *p, *c = NULL, *e;
+ for (;;) {
+ char buf[LINE_MAX], *l, *p, *c = NULL, *e;
bool escaped = false;
- if (!fgets(l, sizeof(l), f)) {
+ if (!fgets(buf, sizeof buf, f)) {
if (feof(f))
break;
@@ -326,6 +326,11 @@ int config_parse(const char *unit,
return -errno;
}
+ l = buf;
+ if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
+ l += strlen(UTF8_BYTE_ORDER_MARK);
+ allow_bom = false;
+
truncate_nl(l);
if (continuation) {
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index a91c94c322..73fb132413 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -178,7 +178,7 @@ int config_parse_personality(const char *unit, const char *filename, unsigned li
assert(data); \
\
xs = new0(type, 1); \
- if(!xs) \
+ if (!xs) \
return -ENOMEM; \
\
*xs = invalid; \
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 0fc2a31f04..835557c6b2 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -180,7 +180,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
unsigned slashes = 0;
for (y = terminal - 1; y >= name && *y == '\\'; y--)
- slashes ++;
+ slashes++;
if (slashes % 2 == 0) {
/* The '.' was not escaped */
@@ -192,7 +192,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
}
}
- terminal --;
+ terminal--;
}
r = dns_label_unescape(&name, dest, sz);
@@ -1172,7 +1172,7 @@ int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
assert(a);
assert(ret);
- for (; n_labels > 0; n_labels --) {
+ for (; n_labels > 0; n_labels--) {
r = dns_name_parent(&a);
if (r < 0)
return r;
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index 2de3642cb3..af780f0b8b 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,9 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
-
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
diff --git a/src/shared/gcrypt-util.c b/src/shared/gcrypt-util.c
index b887243849..39b544b6f0 100644
--- a/src/shared/gcrypt-util.c
+++ b/src/shared/gcrypt-util.c
@@ -19,10 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#ifdef HAVE_GCRYPT
#include <gcrypt.h>
-#include "hexdecoct.h"
#include "gcrypt-util.h"
+#include "hexdecoct.h"
void initialize_libgcrypt(bool secmem) {
const char *p;
@@ -32,7 +33,7 @@ void initialize_libgcrypt(bool secmem) {
p = gcry_check_version("1.4.5");
assert(p);
- /* Turn off "secmem". Clients which whish to make use of this
+ /* Turn off "secmem". Clients which wish to make use of this
* feature should initialize the library manually */
if (!secmem)
gcry_control(GCRYCTL_DISABLE_SECMEM);
@@ -67,3 +68,4 @@ int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) {
*out = enc;
return 0;
}
+#endif
diff --git a/src/shared/gcrypt-util.h b/src/shared/gcrypt-util.h
index c7652c22d1..cf33b3c59c 100644
--- a/src/shared/gcrypt-util.h
+++ b/src/shared/gcrypt-util.h
@@ -19,7 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
void initialize_libgcrypt(bool secmem);
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out);
+#endif
+
+static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {
+#ifdef HAVE_GCRYPT
+ return string_hashsum(s, len, GCRY_MD_SHA224, out);
+#else
+ return -EOPNOTSUPP;
+#endif
+}
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
index 52ab29ed5f..55b41bbcd8 100644
--- a/src/shared/gpt.h
+++ b/src/shared/gpt.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <endian.h>
#include "sd-id128.h"
diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h
index acf519f4f7..8a570fc265 100644
--- a/src/shared/install-printf.h
+++ b/src/shared/install-printf.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "install.h"
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret);
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 5eb3bd35c7..e2d2931c51 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -997,7 +997,7 @@ static int show_journal(FILE *f,
continue;
}
- line ++;
+ line++;
maybe_print_begin_newline(f, &flags);
r = output_journal(f, j, mode, n_columns, flags, ellipsized);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index ed8a29c575..d2f1c4a40c 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fs.h>
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index e5674e4137..23890c63a0 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -24,6 +24,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
@@ -138,7 +139,7 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL);
if (errno == ENOENT)
- return 99;
+ _exit(99);
_exit(EXIT_FAILURE);
}
@@ -238,10 +239,8 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
}
r = mkfs_exists("btrfs");
- if (r == -ENOENT) {
- log_debug("mkfs.btrfs is missing, cannot create loopback file for /var/lib/machines.");
- return 0;
- }
+ if (r == 0)
+ return sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing");
if (r < 0)
return r;
diff --git a/src/shared/pager.c b/src/shared/pager.c
index 05b2b15e40..c16bc027be 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -52,11 +52,14 @@ noreturn static void pager_fallback(void) {
_exit(EXIT_SUCCESS);
}
-int pager_open(bool jump_to_end) {
+int pager_open(bool no_pager, bool jump_to_end) {
_cleanup_close_pair_ int fd[2] = { -1, -1 };
const char *pager;
pid_t parent_pid;
+ if (no_pager)
+ return 0;
+
if (pager_pid > 0)
return 1;
diff --git a/src/shared/pager.h b/src/shared/pager.h
index 9fb05796bb..893e1d2bb6 100644
--- a/src/shared/pager.h
+++ b/src/shared/pager.h
@@ -23,7 +23,7 @@
#include "macro.h"
-int pager_open(bool jump_to_end);
+int pager_open(bool no_pager, bool jump_to_end);
void pager_close(void);
bool pager_have(void) _pure_;
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 061d31f4de..02c03b98d8 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -461,10 +461,7 @@ int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) {
if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b)
return 0;
- if (b)
- f->flags |= PTY_FORWARD_IGNORE_VHANGUP;
- else
- f->flags &= ~PTY_FORWARD_IGNORE_VHANGUP;
+ SET_FLAG(f->flags, PTY_FORWARD_IGNORE_VHANGUP, b);
if (!ignore_vhangup(f)) {
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index a0aef66bc8..35aa60101f 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -37,7 +37,7 @@
#include "string-util.h"
#include "strv.h"
-#define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0)
+#define USE(x, y) do { (x) = (y); (y) = NULL; } while (0)
int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index 51f4621844..ad10039ff4 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
int parse_sleep_config(const char *verb, char ***modes, char ***states);
int can_sleep(const char *verb);
diff --git a/src/shared/uid-range.c b/src/shared/uid-range.c
index eb251492c3..b6ec474390 100644
--- a/src/shared/uid-range.c
+++ b/src/shared/uid-range.c
@@ -54,7 +54,7 @@ static void uid_range_coalesce(UidRange **p, unsigned *n) {
if (*n > j+1)
memmove(y, y+1, sizeof(UidRange) * (*n - j -1));
- (*n) --;
+ (*n)--;
j--;
}
}
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index 99d4b62139..1157a0c72e 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -427,7 +427,7 @@ static int resolve_remote(Connection *c) {
service = strrchr(arg_remote_host, ':');
if (service) {
node = strndupa(arg_remote_host, service - arg_remote_host);
- service ++;
+ service++;
} else {
node = arg_remote_host;
service = "80";
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 91eace90e2..ce8efce3d5 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -190,7 +190,7 @@ int main(int argc, char *argv[]) {
}
for (;;) {
- _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
int events_a, events_b, fd;
uint64_t timeout_a, timeout_b, t;
struct timespec _ts, *ts;
@@ -234,12 +234,14 @@ int main(int argc, char *argv[]) {
fd = sd_bus_get_fd(a);
if (fd < 0) {
+ r = fd;
log_error_errno(r, "Failed to get fd: %m");
goto finish;
}
events_a = sd_bus_get_events(a);
if (events_a < 0) {
+ r = events_a;
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
@@ -252,6 +254,7 @@ int main(int argc, char *argv[]) {
events_b = sd_bus_get_events(b);
if (events_b < 0) {
+ r = events_b;
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
@@ -294,8 +297,6 @@ int main(int argc, char *argv[]) {
}
}
- r = 0;
-
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index c75d12c136..3407d93c80 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -152,7 +152,7 @@ static bool arg_now = false;
static int daemon_reload(int argc, char *argv[], void* userdata);
static int halt_now(enum action a);
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
static bool original_stdout_is_tty;
@@ -200,14 +200,6 @@ static void release_busses(void) {
busses[w] = sd_bus_flush_close_unref(busses[w]);
}
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static void ask_password_agent_open_if_enabled(void) {
/* Open the password agent as a child process if necessary */
@@ -348,6 +340,11 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) {
if (arg_all)
return true;
+ if (!strv_isempty(arg_states))
+ return true;
+
+ /* By default show all units except the ones in inactive
+ * state and with no pending job */
if (u->job_id > 0)
return true;
@@ -678,7 +675,7 @@ static int list_units(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -890,7 +887,7 @@ static int list_sockets(int argc, char *argv[], void *userdata) {
int r = 0, n;
sd_bus *bus;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -1197,7 +1194,7 @@ static int list_timers(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r = 0;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -1365,7 +1362,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
char *path;
int r;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (install_client_side()) {
Hashmap *h;
@@ -1436,7 +1433,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
};
if (output_show_unit_file(&units[c], strv_skip(argv, 1)))
- c ++;
+ c++;
}
if (r < 0)
@@ -1484,7 +1481,7 @@ static int list_dependencies_print(const char *name, int level, unsigned int bra
printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
}
- if (arg_full){
+ if (arg_full) {
printf("%s\n", name);
return 0;
}
@@ -1638,11 +1635,27 @@ static int list_dependencies_one(
if (arg_plain)
printf(" ");
else {
- int state;
+ UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
const char *on;
- state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
- on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
+ (void) get_state_one_unit(bus, *c, &active_state);
+ switch (active_state) {
+ case UNIT_ACTIVE:
+ case UNIT_RELOADING:
+ case UNIT_ACTIVATING:
+ on = ansi_highlight_green();
+ break;
+
+ case UNIT_INACTIVE:
+ case UNIT_DEACTIVATING:
+ on = ansi_normal();
+ break;
+
+ default:
+ on = ansi_highlight_red();
+ break;
+ }
+
printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_normal());
}
@@ -1679,7 +1692,7 @@ static int list_dependencies(int argc, char *argv[], void *userdata) {
} else
u = SPECIAL_DEFAULT_TARGET;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -1883,13 +1896,13 @@ static void output_machines_list(struct machine_info *machine_infos, unsigned n)
printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
if (m->is_host)
- printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
+ printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
(int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
on_state, statelen, strna(m->state), off_state,
on_failed, failedlen, m->n_failed_units, off_failed,
jobslen, m->n_jobs);
else
- printf("%-*s %s%-*s%s %s%*u%s %*u\n",
+ printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
namelen, strna(m->name),
on_state, statelen, strna(m->state), off_state,
on_failed, failedlen, m->n_failed_units, off_failed,
@@ -1910,7 +1923,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
return -EPERM;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -2067,7 +2080,7 @@ static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipp
return;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
id_len = strlen("JOB");
unit_len = strlen("UNIT");
@@ -2137,7 +2150,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
int r;
bool skipped = false;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -2407,18 +2420,19 @@ static int unit_find_paths(
return r;
}
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
_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;
+ UnitActiveState state;
+ const char *path;
int r;
assert(name);
+ assert(active_state);
/* 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,
"org.freedesktop.systemd1",
@@ -2434,7 +2448,7 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
/* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
* considered inactive. */
- state = "inactive";
+ state = UNIT_INACTIVE;
} else {
r = sd_bus_message_read(reply, "o", &path);
@@ -2452,13 +2466,15 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
if (r < 0)
return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
- state = buf;
+ state = unit_active_state_from_string(buf);
+ if (state == _UNIT_ACTIVE_STATE_INVALID) {
+ log_error("Invalid unit state '%s' for: %s", buf, name);
+ return -EINVAL;
+ }
}
- if (!quiet)
- puts(state);
-
- return nulstr_contains(good_states, state);
+ *active_state = state;
+ return 0;
}
static int check_triggering_units(
@@ -2466,9 +2482,10 @@ static int check_triggering_units(
const char *name) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
+ _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
_cleanup_strv_free_ char **triggered_by = NULL;
bool print_warning_label = true;
+ UnitActiveState active_state;
char **i;
int r;
@@ -2487,11 +2504,11 @@ static int check_triggering_units(
"org.freedesktop.systemd1.Unit",
"LoadState",
&error,
- &state);
+ &load_state);
if (r < 0)
return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
- if (streq(state, "masked"))
+ if (streq(load_state, "masked"))
return 0;
r = sd_bus_get_property_strv(
@@ -2506,11 +2523,11 @@ static int check_triggering_units(
return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
STRV_FOREACH(i, triggered_by) {
- r = check_one_unit(bus, *i, "active\0reloading\0", true);
+ r = get_state_one_unit(bus, *i, &active_state);
if (r < 0)
- return log_error_errno(r, "Failed to check unit: %m");
+ return r;
- if (r == 0)
+ if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
continue;
if (print_warning_label) {
@@ -2604,7 +2621,10 @@ static int start_unit_one(
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);
+ log_error("See %s logs and 'systemctl%s status %s' for details.",
+ arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ name);
return r;
}
@@ -3171,11 +3191,12 @@ static int start_special(int argc, char *argv[], void *userdata) {
return start_unit(argc, argv, userdata);
}
-static int check_unit_generic(int code, const char *good_states, char **args) {
+static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
_cleanup_strv_free_ char **names = NULL;
+ UnitActiveState active_state;
sd_bus *bus;
char **name;
- int r;
+ int r, i;
bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
@@ -3187,13 +3208,16 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- int state;
+ r = get_state_one_unit(bus, *name, &active_state);
+ if (r < 0)
+ return r;
- state = check_one_unit(bus, *name, good_states, arg_quiet);
- if (state < 0)
- return state;
- if (state > 0)
- found = true;
+ if (!arg_quiet)
+ puts(unit_active_state_to_string(active_state));
+
+ for (i = 0; i < nb_states; ++i)
+ if (good_states[i] == active_state)
+ found = true;
}
/* use the given return code for the case that we won't find
@@ -3202,12 +3226,14 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
}
static int check_unit_active(int argc, char *argv[], void *userdata) {
+ const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
/* According to LSB: 3, "program is not running" */
- return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1));
+ return check_unit_generic(3, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int check_unit_failed(int argc, char *argv[], void *userdata) {
- return check_unit_generic(1, "failed\0", strv_skip(argv, 1));
+ const UnitActiveState states[] = { UNIT_FAILED };
+ return check_unit_generic(1, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int kill_unit(int argc, char *argv[], void *userdata) {
@@ -4559,7 +4585,7 @@ static int show_all(
if (r < 0)
return r;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
c = (unsigned) r;
@@ -4611,8 +4637,8 @@ static int show_system_status(sd_bus *bus) {
printf(" State: %s%s%s\n",
on, strna(mi.state), off);
- printf(" Jobs: %u queued\n", mi.n_jobs);
- printf(" Failed: %u units\n", mi.n_failed_units);
+ printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
+ printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
printf(" Since: %s; %s\n",
format_timestamp(since2, sizeof(since2), mi.timestamp),
@@ -4654,7 +4680,7 @@ static int show(int argc, char *argv[], void *userdata) {
return -EINVAL;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
if (show_status)
/* Increase max number of open files to 16K if we can, we
@@ -4672,7 +4698,7 @@ static int show(int argc, char *argv[], void *userdata) {
if (show_status && argc <= 1) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
show_system_status(bus);
new_line = true;
@@ -4813,7 +4839,7 @@ static int cat(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to expand names: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
STRV_FOREACH(name, names) {
_cleanup_free_ char *fragment_path = NULL;
@@ -5003,7 +5029,7 @@ static int show_environment(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -6170,15 +6196,30 @@ static int edit(int argc, char *argv[], void *userdata) {
r = daemon_reload(argc, argv, userdata);
end:
- STRV_FOREACH_PAIR(original, tmp, paths)
+ STRV_FOREACH_PAIR(original, tmp, paths) {
(void) unlink(*tmp);
+ /* Removing empty dropin dirs */
+ if (!arg_full) {
+ _cleanup_free_ char *dir;
+
+ dir = dirname_malloc(*original);
+ if (!dir)
+ return log_oom();
+
+ /* no need to check if the dir is empty, rmdir
+ * does nothing if it is not the case.
+ */
+ (void) rmdir(dir);
+ }
+ }
+
return r;
}
static void systemctl_help(void) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Query or send control commands to the systemd manager.\n\n"
@@ -6550,7 +6591,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
}
p = optarg;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *type = NULL;
r = extract_first_word(&p, &type, ",", 0);
@@ -6600,7 +6641,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return log_oom();
} else {
p = optarg;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *prop = NULL;
r = extract_first_word(&p, &prop, ",", 0);
@@ -6710,11 +6751,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_FORCE:
- arg_force ++;
+ arg_force++;
break;
case 'f':
- arg_force ++;
+ arg_force++;
break;
case ARG_NO_RELOAD:
@@ -6785,7 +6826,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
}
p = optarg;
- for(;;) {
+ for (;;) {
_cleanup_free_ char *s = NULL;
r = extract_first_word(&p, &s, ",", 0);
@@ -7180,7 +7221,7 @@ static int telinit_parse_argv(int argc, char *argv[]) {
arg_action = table[i].to;
- optind ++;
+ optind++;
return 1;
}
@@ -7271,6 +7312,7 @@ static int parse_argv(int argc, char *argv[]) {
return systemctl_parse_argv(argc, argv);
}
+#ifdef HAVE_SYSV_COMPAT
_pure_ static int action_to_runlevel(void) {
static const char table[_ACTION_MAX] = {
@@ -7288,6 +7330,7 @@ _pure_ static int action_to_runlevel(void) {
return table[arg_action];
}
+#endif
static int talk_initctl(void) {
#ifdef HAVE_SYSV_COMPAT
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 2d4e1f26e1..3bb886be75 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -74,7 +74,7 @@
#endif
#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \
- static inline void func##p(type **p) { \
+ static __inline__ void func##p(type **p) { \
if (*p) \
func(*p); \
} \
diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h
index 47b256d5b9..623cee0c50 100644
--- a/src/systemd/sd-bus-protocol.h
+++ b/src/systemd/sd-bus-protocol.h
@@ -59,7 +59,7 @@ enum {
SD_BUS_TYPE_STRUCT_END = ')',
SD_BUS_TYPE_DICT_ENTRY = 'e', /* not actually used in signatures */
SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{',
- SD_BUS_TYPE_DICT_ENTRY_END = '}',
+ SD_BUS_TYPE_DICT_ENTRY_END = '}'
};
/* Well-known errors. Note that this is only a sanitized subset of the
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 6ad6d51979..e8f84eb545 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -34,7 +34,7 @@ enum {
_SD_BUS_VTABLE_METHOD = 'M',
_SD_BUS_VTABLE_SIGNAL = 'S',
_SD_BUS_VTABLE_PROPERTY = 'P',
- _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W',
+ _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W'
};
enum {
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 2a2ef0eb98..295989cd69 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -89,13 +89,13 @@ enum {
SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32,
SD_BUS_CREDS_DESCRIPTION = 1ULL << 33,
SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
- _SD_BUS_CREDS_ALL = (1ULL << 34) -1,
+ _SD_BUS_CREDS_ALL = (1ULL << 34) -1
};
enum {
SD_BUS_NAME_REPLACE_EXISTING = 1ULL << 0,
SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- SD_BUS_NAME_QUEUE = 1ULL << 2,
+ SD_BUS_NAME_QUEUE = 1ULL << 2
};
/* Callbacks */
diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h
index 5bfca6ecec..c1d07561d7 100644
--- a/src/systemd/sd-device.h
+++ b/src/systemd/sd-device.h
@@ -22,6 +22,7 @@
***/
#include <inttypes.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "_sd-common.h"
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 2b865a80e1..374ff8774e 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -84,9 +84,9 @@ enum {
typedef struct sd_dhcp_client sd_dhcp_client;
-typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,
+typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event,
void *userdata);
-int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
+int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
void *userdata);
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
@@ -98,6 +98,8 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
const uint8_t *data, size_t data_len);
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+ uint16_t duid_type, uint8_t *duid, size_t duid_len);
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
const uint8_t **data, size_t *data_len);
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
@@ -113,7 +115,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
int sd_dhcp_client_new(sd_dhcp_client **ret);
-int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int priority);
+int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority);
int sd_dhcp_client_detach_event(sd_dhcp_client *client);
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index 8658197e80..fcef083ce6 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -37,7 +37,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);
sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server);
-int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int priority);
+int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int64_t priority);
int sd_dhcp_server_detach_event(sd_dhcp_server *client);
sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client);
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 9608060830..4604cb6382 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -76,17 +76,18 @@ enum {
typedef struct sd_dhcp6_client sd_dhcp6_client;
-typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event,
+typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event,
void *userdata);
int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
- sd_dhcp6_client_cb_t cb, void *userdata);
+ sd_dhcp6_client_callback_t cb, void *userdata);
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
- size_t duid_len);
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+ uint8_t *duid, size_t duid_len);
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid);
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
@@ -97,8 +98,7 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
int sd_dhcp6_client_start(sd_dhcp6_client *client);
int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
-int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
- int priority);
+int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority);
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index 1ea97e47f8..531ace1c34 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -55,7 +55,7 @@ enum {
SD_EVENT_RUNNING,
SD_EVENT_EXITING,
SD_EVENT_FINISHED,
- SD_EVENT_PREPARING,
+ SD_EVENT_PREPARING
};
enum {
@@ -69,7 +69,11 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
+#else
+typedef void* sd_event_child_handler_t;
+#endif
int sd_event_default(sd_event **e);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index a3bf5897b8..4dff0b9b81 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -100,11 +100,11 @@ int sd_id128_get_boot(sd_id128_t *ret);
((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \
0 })
-_sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
+_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
return memcmp(&a, &b, 16) == 0;
}
-_sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) {
+_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
return a.qwords[0] == 0 && a.qwords[1] == 0;
}
diff --git a/src/systemd/sd-ipv4acd.h b/src/systemd/sd-ipv4acd.h
index 3a2219c82c..9e3e14a30c 100644
--- a/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/sd-ipv4acd.h
@@ -37,12 +37,12 @@ enum {
};
typedef struct sd_ipv4acd sd_ipv4acd;
-typedef void (*sd_ipv4acd_cb_t)(sd_ipv4acd *ll, int event, void *userdata);
+typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *ll, int event, void *userdata);
int sd_ipv4acd_detach_event(sd_ipv4acd *ll);
-int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority);
+int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority);
int sd_ipv4acd_get_address(sd_ipv4acd *ll, struct in_addr *address);
-int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata);
+int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata);
int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr);
int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index);
int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address);
diff --git a/src/systemd/sd-ipv4ll.h b/src/systemd/sd-ipv4ll.h
index 67c566fe0d..6fa38a2243 100644
--- a/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/sd-ipv4ll.h
@@ -36,12 +36,12 @@ enum {
};
typedef struct sd_ipv4ll sd_ipv4ll;
-typedef void (*sd_ipv4ll_cb_t)(sd_ipv4ll *ll, int event, void *userdata);
+typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata);
int sd_ipv4ll_detach_event(sd_ipv4ll *ll);
-int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority);
+int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority);
int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
-int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata);
+int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata);
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index);
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index abb9eca576..d4c6f409cd 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -72,7 +72,7 @@ enum {
SD_JOURNAL_SYSTEM = 4,
SD_JOURNAL_CURRENT_USER = 8,
- SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM, /* deprecated name */
+ SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM /* deprecated name */
};
/* Wakeup event types */
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index ea952ef187..4f2a3b50c0 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -30,57 +30,150 @@
_SD_BEGIN_DECLARATIONS;
+typedef struct sd_lldp sd_lldp;
+typedef struct sd_lldp_neighbor sd_lldp_neighbor;
+
+#define SD_LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
+
+/* IEEE 802.3AB Clause 9: TLV Types */
enum {
- SD_LLDP_EVENT_UPDATE_INFO = 0,
+ SD_LLDP_TYPE_END = 0,
+ SD_LLDP_TYPE_CHASSIS_ID = 1,
+ SD_LLDP_TYPE_PORT_ID = 2,
+ SD_LLDP_TYPE_TTL = 3,
+ SD_LLDP_TYPE_PORT_DESCRIPTION = 4,
+ SD_LLDP_TYPE_SYSTEM_NAME = 5,
+ SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6,
+ SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
+ SD_LLDP_TYPE_MGMT_ADDRESS = 8,
+ SD_LLDP_TYPE_PRIVATE = 127,
};
+/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
enum {
- SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE,
- SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE,
- SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE,
+ SD_LLDP_CHASSIS_SUBTYPE_RESERVED = 0,
+ SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1,
+ SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2,
+ SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3,
+ SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4,
+ SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5,
+ SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6,
+ SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7,
};
-typedef struct sd_lldp sd_lldp;
-typedef struct sd_lldp_packet sd_lldp_packet;
+/* IEEE 802.3AB Clause 9.5.3: Port subtype */
+enum {
+ SD_LLDP_PORT_SUBTYPE_RESERVED = 0,
+ SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1,
+ SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2,
+ SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3,
+ SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4,
+ SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5,
+ SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
+ SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
+};
-typedef void (*sd_lldp_cb_t)(sd_lldp *lldp, int event, void *userdata);
+enum {
+ SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0,
+ SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
+ SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2,
+ SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3,
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4,
+ SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5,
+ SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6,
+ SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7,
+ SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8,
+ SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9,
+ SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10,
+};
-int sd_lldp_new(int ifindex, const char *ifname, const struct ether_addr *mac, sd_lldp **ret);
-sd_lldp* sd_lldp_unref(sd_lldp *lldp);
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
-int sd_lldp_start(sd_lldp *lldp);
-int sd_lldp_stop(sd_lldp *lldp);
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \
+ ((uint16_t) \
+ (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER| \
+ SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE| \
+ SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \
+ SD_LLDP_SYSTEM_CAPABILITIES_ROUTER| \
+ SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS| \
+ SD_LLDP_SYSTEM_CAPABILITIES_CVLAN| \
+ SD_LLDP_SYSTEM_CAPABILITIES_SVLAN| \
+ SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
-int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority);
-int sd_lldp_detach_event(sd_lldp *lldp);
-int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata);
-int sd_lldp_save(sd_lldp *lldp, const char *file);
+#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
+#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
+
+enum {
+ SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
+ SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
+ SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3,
+ SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4,
+ SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5,
+ SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6,
+ SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7,
+};
+
+typedef enum sd_lldp_event {
+ SD_LLDP_EVENT_ADDED = 'a',
+ SD_LLDP_EVENT_REMOVED = 'r',
+ SD_LLDP_EVENT_UPDATED = 'u',
+ SD_LLDP_EVENT_REFRESHED = 'f',
+} sd_lldp_event;
-int sd_lldp_packet_read_chassis_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length);
-int sd_lldp_packet_read_port_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length);
-int sd_lldp_packet_read_ttl(sd_lldp_packet *tlv, uint16_t *ttl);
-int sd_lldp_packet_read_system_name(sd_lldp_packet *tlv, char **data, uint16_t *length);
-int sd_lldp_packet_read_system_description(sd_lldp_packet *tlv, char **data, uint16_t *length);
-int sd_lldp_packet_read_system_capability(sd_lldp_packet *tlv, uint16_t *data);
-int sd_lldp_packet_read_port_description(sd_lldp_packet *tlv, char **data, uint16_t *length);
+typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
-/* IEEE 802.1 organizationally specific TLVs */
-int sd_lldp_packet_read_port_vlan_id(sd_lldp_packet *tlv, uint16_t *id);
-int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id);
-int sd_lldp_packet_read_vlan_name(sd_lldp_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length);
-int sd_lldp_packet_read_management_vid(sd_lldp_packet *tlv, uint16_t *id);
-int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id);
+int sd_lldp_new(sd_lldp **ret, int ifindex);
+sd_lldp* sd_lldp_unref(sd_lldp *lldp);
-sd_lldp_packet *sd_lldp_packet_ref(sd_lldp_packet *tlv);
-sd_lldp_packet *sd_lldp_packet_unref(sd_lldp_packet *tlv);
+int sd_lldp_start(sd_lldp *lldp);
+int sd_lldp_stop(sd_lldp *lldp);
-int sd_lldp_packet_get_destination_type(sd_lldp_packet *tlv, int *dest);
+int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
+int sd_lldp_detach_event(sd_lldp *lldp);
-int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs);
+int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
+
+/* Controls how much and what to store in the neighbors database */
+int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
+int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask);
+int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address);
+
+int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors);
+
+int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size);
+sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n);
+sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);
+
+/* Access to LLDP frame metadata */
+int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
+int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
+int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
+
+/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
+int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
+int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
+int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret);
+int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
+int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
+
+/* Low-level, iterative TLV access. This is for evertyhing else, it iteratively goes through all available TLVs
+ * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
+int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
+int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
+int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type);
+int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type);
+int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], uint8_t *subtype);
+int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[3], uint8_t subtype);
+int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_packet, sd_lldp_packet_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref);
_SD_END_DECLARATIONS;
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
index 8a72576ec8..3c44d63021 100644
--- a/src/systemd/sd-messages.h
+++ b/src/systemd/sd-messages.h
@@ -82,8 +82,6 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01)
-#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)
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
index 762947531d..29bcbe8e3e 100644
--- a/src/systemd/sd-ndisc.h
+++ b/src/systemd/sd-ndisc.h
@@ -52,7 +52,7 @@ int sd_ndisc_set_callback(sd_ndisc *nd,
int sd_ndisc_set_index(sd_ndisc *nd, int interface_index);
int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
-int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority);
+int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority);
int sd_ndisc_detach_event(sd_ndisc *nd);
sd_event *sd_ndisc_get_event(sd_ndisc *nd);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index b4798d2476..af7a797567 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -64,7 +64,7 @@ int sd_netlink_wait(sd_netlink *nl, uint64_t timeout);
int sd_netlink_add_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata);
int sd_netlink_remove_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata);
-int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int priority);
+int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
int sd_netlink_detach_event(sd_netlink *nl);
int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
@@ -131,7 +131,7 @@ int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type);
int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family);
int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex);
int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags);
-int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type);
+int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type);
int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index e20d12c44d..0f13e2bae7 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -99,11 +99,11 @@ int sd_network_link_get_network_file(int ifindex, char **filename);
/* Get DNS entries for a given link. These are string representations of
* IP addresses */
-int sd_network_link_get_dns(int ifindex, char ***addr);
+int sd_network_link_get_dns(int ifindex, char ***ret);
/* Get NTP entries for a given link. These are domain names or string
* representations of IP addresses */
-int sd_network_link_get_ntp(int ifindex, char ***addr);
+int sd_network_link_get_ntp(int ifindex, char ***ret);
/* Indicates whether or not LLMNR should be enabled for the link
* Possible levels of support: yes, no, resolve
@@ -133,19 +133,17 @@ int sd_network_link_get_dnssec(int ifindex, char **dnssec);
*/
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 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);
+/* Get the carrier interface indexes to which current link is bound to. */
+int sd_network_link_get_carrier_bound_to(int ifindex, int **ifindexes);
/* Get the CARRIERS that are bound to current link. */
-int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
+int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes);
/* Get the timezone that was learnt on a specific link. */
int sd_network_link_get_timezone(int ifindex, char **timezone);
diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h
index 903b917f70..1c792dab39 100644
--- a/src/systemd/sd-resolve.h
+++ b/src/systemd/sd-resolve.h
@@ -79,7 +79,7 @@ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec);
int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid);
-int sd_resolve_attach_event(sd_resolve *resolve, sd_event *e, int priority);
+int sd_resolve_attach_event(sd_resolve *resolve, sd_event *e, int64_t priority);
int sd_resolve_detach_event(sd_resolve *resolve);
sd_event *sd_resolve_get_event(sd_resolve *resolve);
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 863c628323..4377f1b910 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1820,7 +1820,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index b5925a47dc..59e1a3e921 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -864,7 +864,7 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
}
service = hashmap_get(all_services, name);
- if (!service){
+ if (!service) {
log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name);
continue;
}
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
new file mode 100644
index 0000000000..cc4821eaf5
--- /dev/null
+++ b/src/test/test-alloc-util.c
@@ -0,0 +1,55 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "macro.h"
+#include "util.h"
+
+static void test_alloca(void) {
+ static const uint8_t zero[997] = { };
+ char *t;
+
+ t = alloca_align(17, 512);
+ assert_se(!((uintptr_t)t & 0xff));
+ memzero(t, 17);
+
+ t = alloca0_align(997, 1024);
+ assert_se(!((uintptr_t)t & 0x1ff));
+ assert_se(!memcmp(t, zero, 997));
+}
+
+static void test_memdup_multiply(void) {
+ int org[] = {1, 2, 3};
+ int *dup;
+
+ dup = (int*)memdup_multiply(org, sizeof(int), 3);
+
+ assert_se(dup);
+ assert_se(dup[0] == 1);
+ assert_se(dup[1] == 2);
+ assert_se(dup[2] == 3);
+ free(dup);
+}
+
+int main(int argc, char *argv[]) {
+ test_alloca();
+ test_memdup_multiply();
+
+ return 0;
+}
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index d2add5880c..8e68d6510d 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -34,17 +34,18 @@ static int test_acpi_fpdt(void) {
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read ACPI FPDT: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA;
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read ACPI FPDT: %m");
+ return ok ? 0 : r;
}
log_info("ACPI FPDT: loader start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
static int test_efi_loader(void) {
@@ -57,33 +58,34 @@ static int test_efi_loader(void) {
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read EFI loader data: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read EFI loader data: %m");
+ return ok ? 0 : r;
}
log_info("EFI Loader: start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
-int main(int argc, char* argv[]) {
+static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
int r;
dual_timestamp fw, l, k;
- test_acpi_fpdt();
- test_efi_loader();
-
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
- log_error_errno(r, "Failed to read variables: %m");
- return 1;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read variables: %m");
+ return ok ? 0 : r;
}
log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
@@ -91,6 +93,21 @@ int main(int argc, char* argv[]) {
log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
+ return 1;
+}
+
+int main(int argc, char* argv[]) {
+ int p, q, r;
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ p = test_acpi_fpdt();
+ assert(p >= 0);
+ q = test_efi_loader();
+ assert(q >= 0);
+ r = test_boot_timestamps();
+ assert(r >= 0);
- return 0;
+ return (p > 0 || q > 0 || r >> 0) ? EXIT_SUCCESS : EXIT_TEST_SKIP;
}
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 8754cb3381..5a8c6cbfb6 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -137,6 +137,7 @@ int main(int argc, char* argv[]) {
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);
+ test_next("Sun 16:00:00", "CET", 1456041600123456, 1456066800000000);
assert_se(calendar_spec_from_string("test", &c) < 0);
assert_se(calendar_spec_from_string("", &c) < 0);
diff --git a/src/test/test-clock.c b/src/test/test-clock.c
new file mode 100644
index 0000000000..84f775e5bc
--- /dev/null
+++ b/src/test/test-clock.c
@@ -0,0 +1,96 @@
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2016 Canonical Ltd.
+
+ 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 <unistd.h>
+#include <fcntl.h>
+
+#include "clock-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "log.h"
+#include "macro.h"
+
+static void test_clock_is_localtime(void) {
+ char adjtime[] = "/tmp/test-adjtime.XXXXXX";
+ int fd = -1;
+ _cleanup_fclose_ FILE* f = NULL;
+
+ static const struct scenario {
+ const char* contents;
+ int expected_result;
+ } scenarios[] = {
+ /* adjtime configures UTC */
+ {"0.0 0 0\n0\nUTC\n", 0},
+ /* adjtime configures local time */
+ {"0.0 0 0\n0\nLOCAL\n", 1},
+ /* no final EOL */
+ {"0.0 0 0\n0\nUTC", 0},
+ {"0.0 0 0\n0\nLOCAL", 1},
+ /* empty value -> defaults to UTC */
+ {"0.0 0 0\n0\n", 0},
+ /* unknown value -> defaults to UTC */
+ {"0.0 0 0\n0\nFOO\n", 0},
+ /* no third line */
+ {"0.0 0 0", 0},
+ {"0.0 0 0\n", 0},
+ {"0.0 0 0\n0", 0},
+ };
+
+ /* without an adjtime file we default to UTC */
+ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0);
+
+ fd = mkostemp_safe(adjtime, O_WRONLY|O_CLOEXEC);
+ assert_se(fd >= 0);
+ log_info("adjtime test file: %s", adjtime);
+ f = fdopen(fd, "w");
+ assert_se(f);
+
+ for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) {
+ log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result);
+ log_info("%s", scenarios[i].contents);
+ rewind(f);
+ ftruncate(fd, 0);
+ assert_se(write_string_stream(f, scenarios[i].contents, false) == 0);
+ assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result);
+ }
+
+ unlink(adjtime);
+}
+
+/* Test with the real /etc/adjtime */
+static void test_clock_is_localtime_system(void) {
+ int r;
+ r = clock_is_localtime(NULL);
+
+ if (access("/etc/adjtime", F_OK) == 0) {
+ log_info("/etc/adjtime exists, clock_is_localtime() == %i", r);
+ /* if /etc/adjtime exists we expect some answer, no error or
+ * crash */
+ assert_se(r == 0 || r == 1);
+ } else
+ /* default is UTC if there is no /etc/adjtime */
+ assert_se(r == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_clock_is_localtime();
+ test_clock_is_localtime_system();
+
+ return 0;
+}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index b3a4c40339..be5d2611f8 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -215,6 +215,14 @@ static void test_config_parse_nsec(void) {
test_config_parse_nsec_one("garbage", 0);
}
+static void test_config_parse_iec_uint64(void) {
+ uint64_t offset = 0;
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
+ assert_se(offset == 4 * 1024 * 1024);
+
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
@@ -230,6 +238,7 @@ int main(int argc, char **argv) {
test_config_parse_mode();
test_config_parse_sec();
test_config_parse_nsec();
+ test_config_parse_iec_uint64();
return 0;
}
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index ad57cb0202..cb437754b4 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -24,6 +24,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "log.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
@@ -39,6 +40,8 @@ static void test_copy_file(void) {
size_t sz = 0;
int fd;
+ log_info("%s", __func__);
+
fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
assert_se(fd >= 0);
close(fd);
@@ -66,6 +69,8 @@ static void test_copy_file_fd(void) {
char text[] = "boohoo\nfoo\n\tbar\n";
char buf[64] = {0};
+ log_info("%s", __func__);
+
in_fd = mkostemp_safe(in_fn, O_RDWR);
assert_se(in_fd >= 0);
out_fd = mkostemp_safe(out_fn, O_RDWR);
@@ -91,6 +96,8 @@ static void test_copy_tree(void) {
"link2", "dir1/file");
char **p, **link;
+ log_info("%s", __func__);
+
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -173,11 +180,65 @@ static void test_copy_bytes(void) {
assert_se(r == -EBADF);
}
+static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint64_t max_bytes) {
+ char fn2[] = "/tmp/test-copy-file-XXXXXX";
+ char fn3[] = "/tmp/test-copy-file-XXXXXX";
+ _cleanup_close_ int fd = -1, fd2 = -1, fd3 = -1;
+ int r;
+ struct stat buf, buf2, buf3;
+
+ log_info("%s try_reflink=%s max_bytes=%" PRIu64, __func__, yes_no(try_reflink), max_bytes);
+
+ fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ assert_se(fd >= 0);
+
+ fd2 = mkostemp_safe(fn2, O_RDWR);
+ assert_se(fd2 >= 0);
+
+ fd3 = mkostemp_safe(fn3, O_WRONLY);
+ assert_se(fd3 >= 0);
+
+ r = copy_bytes(fd, fd2, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ assert_se(IN_SET(r, 0, 1));
+
+ assert_se(lseek(fd2, 0, SEEK_SET) == 0);
+
+ r = copy_bytes(fd2, fd3, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ /* We cannot distinguish between the input being exactly max_bytes
+ * or longer than max_bytes (without trying to read one more byte,
+ * or calling stat, or FION_READ, etc, and we don't want to do any
+ * of that). So we expect "truncation" since we know that file we
+ * are copying is exactly max_bytes bytes. */
+ assert_se(r == 1);
+
+ assert_se(fstat(fd, &buf) == 0);
+ assert_se(fstat(fd2, &buf2) == 0);
+ assert_se(fstat(fd3, &buf3) == 0);
+
+ assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes));
+ assert_se(buf3.st_size == buf2.st_size);
+
+ unlink(fn2);
+ unlink(fn3);
+}
+
int main(int argc, char *argv[]) {
test_copy_file();
test_copy_file_fd();
test_copy_tree();
test_copy_bytes();
+ test_copy_bytes_regular_file(argv[0], false, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], true, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], false, 1000); /* smaller than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 1000);
+ test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 32000);
return 0;
}
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
new file mode 100644
index 0000000000..8818d1ffb7
--- /dev/null
+++ b/src/test/test-cpu-set-util.c
@@ -0,0 +1,143 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "cpu-set-util.h"
+#include "macro.h"
+
+static void test_parse_cpu_set(void) {
+ cpu_set_t *c = NULL;
+ int ncpus;
+ int cpu;
+
+ /* Simple range (from CPUAffinity example) */
+ ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
+ c = mfree(c);
+
+ /* A more interesting range */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Quoted strings */
+ ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Use commas as separators */
+ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Commas with spaces (and trailing comma, space) */
+ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 8; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges */
+ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges with trailing comma, space */
+ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Negative range (returns empty cpu_set) */
+ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
+ c = mfree(c);
+
+ /* Overlapping ranges */
+ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ for (cpu = 0; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Mix ranges and individual CPUs */
+ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
+ assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 4; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Garbage */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Range with garbage */
+ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Empty string */
+ c = NULL;
+ ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus == 0); /* empty string returns 0 */
+ assert_se(!c);
+
+ /* Runnaway quoted string */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+}
+
+int main(int argc, char *argv[]) {
+ test_parse_cpu_set();
+
+ return 0;
+}
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index 4ce00f4b1f..a7cb426282 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -38,27 +38,27 @@ int main(int argc, char*argv[]) {
sd_notify(0,
"STATUS=Starting up");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Reloading\n"
"RELOADING=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Quitting\n"
"STOPPING=1");
- sleep(5);
+ sleep(1);
return EXIT_SUCCESS;
}
diff --git a/src/test/test-env-replace.c b/src/test/test-env-util.c
index 264acc6ea6..35bb62906e 100644
--- a/src/test/test-env-replace.c
+++ b/src/test/test-env-util.c
@@ -2,6 +2,7 @@
This file is part of systemd.
Copyright 2010 Lennart Poettering
+ 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
@@ -177,10 +178,37 @@ static void test_env_name_is_valid(void) {
assert_se(!env_name_is_valid(NULL));
assert_se(!env_name_is_valid(""));
+ assert_se(!env_name_is_valid("xxx\a"));
+ assert_se(!env_name_is_valid("xxx\007b"));
+ assert_se(!env_name_is_valid("\007\009"));
assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
}
+static void test_env_value_is_valid(void) {
+ assert_se(env_value_is_valid(""));
+ assert_se(env_value_is_valid("głąb kapuściany"));
+ assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+}
+
+static void test_env_assignment_is_valid(void) {
+ assert_se(env_assignment_is_valid("a="));
+ assert_se(env_assignment_is_valid("b=głąb kapuściany"));
+ assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
+ assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+
+ assert_se(!env_assignment_is_valid("="));
+ assert_se(!env_assignment_is_valid("a b="));
+ assert_se(!env_assignment_is_valid("a ="));
+ assert_se(!env_assignment_is_valid(" b="));
+ /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
+ assert_se(!env_assignment_is_valid("a.b="));
+ assert_se(!env_assignment_is_valid("a-b="));
+ assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
+ assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
+ assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
+}
+
int main(int argc, char *argv[]) {
test_strv_env_delete();
test_strv_env_unset();
@@ -189,6 +217,8 @@ int main(int argc, char *argv[]) {
test_replace_env_arg();
test_env_clean();
test_env_name_is_valid();
+ test_env_value_is_valid();
+ test_env_assignment_is_valid();
return 0;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
new file mode 100644
index 0000000000..6cbb8443fe
--- /dev/null
+++ b/src/test/test-escape.c
@@ -0,0 +1,114 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "escape.h"
+#include "macro.h"
+
+static void test_cescape(void) {
+ _cleanup_free_ char *escaped;
+
+ assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+ assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_cunescape(void) {
+ _cleanup_free_ char *unescaped;
+
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+ unescaped = mfree(unescaped);
+
+ /* incomplete sequences */
+ assert_se(cunescape("\\x0", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x0"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\x", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\", 0, &unescaped) < 0);
+ assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\11", 0, &unescaped) < 0);
+ assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\11"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\1", 0, &unescaped) < 0);
+ assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\1"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
+ assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "ßßΠA"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\073", 0, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, ";"));
+}
+
+static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_escape(s, bad));
+ assert_se(streq_ptr(r, expected));
+}
+
+static void test_shell_escape(void) {
+ test_shell_escape_one("", "", "");
+ test_shell_escape_one("\\", "", "\\\\");
+ test_shell_escape_one("foobar", "", "foobar");
+ test_shell_escape_one("foobar", "o", "f\\o\\obar");
+ test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
+}
+
+static void test_shell_maybe_quote_one(const char *s, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_maybe_quote(s));
+ assert_se(streq(r, expected));
+}
+
+static void test_shell_maybe_quote(void) {
+
+ test_shell_maybe_quote_one("", "");
+ test_shell_maybe_quote_one("\\", "\"\\\\\"");
+ test_shell_maybe_quote_one("\"", "\"\\\"\"");
+ test_shell_maybe_quote_one("foobar", "foobar");
+ test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
+ test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
+}
+
+int main(int argc, char *argv[]) {
+ test_cescape();
+ test_cunescape();
+ test_shell_escape();
+ test_shell_maybe_quote();
+
+ return 0;
+}
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index d021be4671..901cc44af6 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -91,7 +91,7 @@ static void test_exec_personality(Manager *m) {
#elif defined(__s390__)
test(m, "exec-personality-s390.service", 0, CLD_EXITED);
-#else
+#elif defined(__i386__)
test(m, "exec-personality-x86.service", 0, CLD_EXITED);
#endif
}
@@ -130,18 +130,33 @@ static void test_exec_systemcallerrornumber(Manager *m) {
#endif
}
+static void test_exec_systemcall_system_mode_with_user(Manager *m) {
+#ifdef HAVE_SECCOMP
+ if (getpwnam("nobody"))
+ test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
+ else if (getpwnam("nfsnobody"))
+ test(m, "exec-systemcallfilter-system-user-nfsnobody.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_systemcall_system_mode_with_user, could not find nobody/nfsnobody user: %m");
+#endif
+}
+
static void test_exec_user(Manager *m) {
if (getpwnam("nobody"))
test(m, "exec-user.service", 0, CLD_EXITED);
+ else if (getpwnam("nfsnobody"))
+ test(m, "exec-user-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m");
+ log_error_errno(errno, "Skipping test_exec_user, could not find nobody/nfsnobody user: %m");
}
static void test_exec_group(Manager *m) {
if (getgrnam("nobody"))
test(m, "exec-group.service", 0, CLD_EXITED);
+ else if (getgrnam("nfsnobody"))
+ test(m, "exec-group-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m");
+ log_error_errno(errno, "Skipping test_exec_group, could not find nobody/nfsnobody group: %m");
}
static void test_exec_environment(Manager *m) {
@@ -204,8 +219,10 @@ static void test_exec_runtimedirectory(Manager *m) {
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
if (getgrnam("nobody"))
test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ else if (getgrnam("nfsnobody"))
+ test(m, "exec-runtimedirectory-owner-nfsnobody.service", 0, CLD_EXITED);
else
- log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m");
+ log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody/nfsnobody group: %m");
}
static void test_exec_capabilityboundingset(Manager *m) {
@@ -234,9 +251,16 @@ static void test_exec_capabilityambientset(Manager *m) {
* 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);
- }
+ if (getpwnam("nobody")) {
+ test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
+ } else if (getpwnam("nfsnobody")) {
+ test(m, "exec-capabilityambientset-nfsnobody.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityambientset-merge-nfsnobody.service", 0, CLD_EXITED);
+ } else
+ log_error_errno(errno, "Skipping test_exec_capabilityambientset, could not find nobody/nfsnobody user: %m");
+ } else
+ log_error_errno(errno, "Skipping test_exec_capabilityambientset, the kernel does not support ambient capabilities: %m");
}
static void test_exec_privatenetwork(Manager *m) {
@@ -267,8 +291,31 @@ static void test_exec_spec_interpolation(Manager *m) {
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
}
+static int run_tests(ManagerRunningAs running_as, test_function_t *tests) {
+ test_function_t *test = NULL;
+ Manager *m = NULL;
+ int r;
+
+ assert_se(tests);
+
+ r = manager_new(running_as, true, &m);
+ if (MANAGER_SKIP_TEST(r)) {
+ printf("Skipping test: manager_new: %s\n", strerror(-r));
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+ for (test = tests; test && *test; test++)
+ (*test)(m);
+
+ manager_free(m);
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
- test_function_t tests[] = {
+ test_function_t user_tests[] = {
test_exec_workingdirectory,
test_exec_personality,
test_exec_ignoresigpipe,
@@ -291,8 +338,10 @@ int main(int argc, char *argv[]) {
test_exec_spec_interpolation,
NULL,
};
- test_function_t *test = NULL;
- Manager *m = NULL;
+ test_function_t system_tests[] = {
+ test_exec_systemcall_system_mode_with_user,
+ NULL,
+ };
int r;
log_parse_environment();
@@ -317,18 +366,9 @@ int main(int argc, char *argv[]) {
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
- r = manager_new(MANAGER_USER, true, &m);
- if (MANAGER_SKIP_TEST(r)) {
- printf("Skipping test: manager_new: %s\n", strerror(-r));
- return EXIT_TEST_SKIP;
- }
- assert_se(r >= 0);
- assert_se(manager_startup(m, NULL, NULL) >= 0);
-
- for (test = tests; test && *test; test++)
- (*test)(m);
+ r = run_tests(MANAGER_USER, user_tests);
+ if (r != 0)
+ return r;
- manager_free(m);
-
- return 0;
+ return run_tests(MANAGER_SYSTEM, system_tests);
}
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
new file mode 100644
index 0000000000..421d3bdeb3
--- /dev/null
+++ b/src/test/test-fd-util.c
@@ -0,0 +1,103 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+
+static void test_close_many(void) {
+ int fds[3];
+ char name0[] = "/tmp/test-close-many.XXXXXX";
+ char name1[] = "/tmp/test-close-many.XXXXXX";
+ char name2[] = "/tmp/test-close-many.XXXXXX";
+
+ fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
+ fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
+ fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
+
+ close_many(fds, 2);
+
+ assert_se(fcntl(fds[0], F_GETFD) == -1);
+ assert_se(fcntl(fds[1], F_GETFD) == -1);
+ assert_se(fcntl(fds[2], F_GETFD) >= 0);
+
+ safe_close(fds[2]);
+
+ unlink(name0);
+ unlink(name1);
+ unlink(name2);
+}
+
+static void test_close_nointr(void) {
+ char name[] = "/tmp/test-test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+ assert_se(close_nointr(fd) < 0);
+
+ unlink(name);
+}
+
+static void test_same_fd(void) {
+ _cleanup_close_pair_ int p[2] = { -1, -1 };
+ _cleanup_close_ int a = -1, b = -1, c = -1;
+
+ assert_se(pipe2(p, O_CLOEXEC) >= 0);
+ assert_se((a = dup(p[0])) >= 0);
+ assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
+ assert_se((c = dup(a)) >= 0);
+
+ assert_se(same_fd(p[0], p[0]) > 0);
+ assert_se(same_fd(p[1], p[1]) > 0);
+ assert_se(same_fd(a, a) > 0);
+ assert_se(same_fd(b, b) > 0);
+
+ assert_se(same_fd(a, p[0]) > 0);
+ assert_se(same_fd(p[0], a) > 0);
+ assert_se(same_fd(c, p[0]) > 0);
+ assert_se(same_fd(p[0], c) > 0);
+ assert_se(same_fd(a, c) > 0);
+ assert_se(same_fd(c, a) > 0);
+
+ assert_se(same_fd(p[0], p[1]) == 0);
+ assert_se(same_fd(p[1], p[0]) == 0);
+ assert_se(same_fd(p[0], b) == 0);
+ assert_se(same_fd(b, p[0]) == 0);
+ assert_se(same_fd(p[1], a) == 0);
+ assert_se(same_fd(a, p[1]) == 0);
+ assert_se(same_fd(p[1], b) == 0);
+ assert_se(same_fd(b, p[1]) == 0);
+
+ assert_se(same_fd(a, b) == 0);
+ assert_se(same_fd(b, a) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_close_many();
+ test_close_nointr();
+ test_same_fd();
+
+ return 0;
+}
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 5586a2d6c1..ec9f173da2 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -27,6 +27,7 @@
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
@@ -425,6 +426,134 @@ static void test_load_env_file_pairs(void) {
unlink(fn);
}
+static void test_search_and_fopen(void) {
+ const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(basename(name), "r", "/", dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+
+static void test_search_and_fopen_nulstr(void) {
+ const char dirs[] = "/tmp/foo/bar\0/tmp\0";
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+static void test_writing_tmpfile(void) {
+ char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_free_ char *contents = NULL;
+ size_t size;
+ int fd, r;
+ struct iovec iov[3];
+
+ IOVEC_SET_STRING(iov[0], "abc\n");
+ IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
+ IOVEC_SET_STRING(iov[2], "");
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ printf("tmpfile: %s", name);
+
+ r = writev(fd, iov, 3);
+ assert_se(r >= 0);
+
+ r = read_full_file(name, &contents, &size);
+ assert_se(r == 0);
+ printf("contents: %s", contents);
+ assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+
+ unlink(name);
+}
+
+static void test_tempfn(void) {
+ char *ret = NULL, *p;
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -439,6 +568,10 @@ int main(int argc, char *argv[]) {
test_write_string_file_no_create();
test_write_string_file_verify();
test_load_env_file_pairs();
+ test_search_and_fopen();
+ test_search_and_fopen_nulstr();
+ test_writing_tmpfile();
+ test_tempfn();
return 0;
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
new file mode 100644
index 0000000000..6db2c2b6f1
--- /dev/null
+++ b/src/test/test-fs-util.c
@@ -0,0 +1,91 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+static void test_unlink_noerrno(void) {
+ char name[] = "/tmp/test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+
+ {
+ PROTECT_ERRNO;
+ errno = -42;
+ assert_se(unlink_noerrno(name) >= 0);
+ assert_se(errno == -42);
+ assert_se(unlink_noerrno(name) < 0);
+ assert_se(errno == -42);
+ }
+}
+
+static void test_readlink_and_make_absolute(void) {
+ char tempdir[] = "/tmp/test-readlink_and_make_absolute";
+ char name[] = "/tmp/test-readlink_and_make_absolute/original";
+ char name2[] = "test-readlink_and_make_absolute/original";
+ char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
+ char *r = NULL;
+
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
+ assert_se(touch(name) >= 0);
+
+ assert_se(symlink(name, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(chdir(tempdir) >= 0);
+ assert_se(symlink(name2, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+}
+
+static void test_get_files_in_directory(void) {
+ _cleanup_strv_free_ char **l = NULL, **t = NULL;
+
+ assert_se(get_files_in_directory("/tmp", &l) >= 0);
+ assert_se(get_files_in_directory(".", &t) >= 0);
+ assert_se(get_files_in_directory(".", NULL) >= 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_unlink_noerrno();
+ test_readlink_and_make_absolute();
+ test_get_files_in_directory();
+
+ return 0;
+}
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index ea3d1a6909..63a4b8c243 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -131,8 +131,45 @@ static void test_fstab_yes_no_option(void) {
assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false);
}
+static void test_fstab_node_to_udev_node(void) {
+ char *n;
+
+ n = fstab_node_to_udev_node("LABEL=applé/jack");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
+ free(n);
+
+ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PONIES=awesome");
+ puts(n);
+ assert_se(streq(n, "PONIES=awesome"));
+ free(n);
+
+ n = fstab_node_to_udev_node("/dev/xda1");
+ puts(n);
+ assert_se(streq(n, "/dev/xda1"));
+ free(n);
+}
+
int main(void) {
test_fstab_filter_options();
test_fstab_find_pri();
test_fstab_yes_no_option();
+ test_fstab_node_to_udev_node();
+
+ return 0;
}
diff --git a/src/bootchart/svg.h b/src/test/test-glob-util.c
index 6e06b5ad97..227d4290f0 100644
--- a/src/bootchart/svg.h
+++ b/src/test/test-glob-util.c
@@ -1,12 +1,7 @@
-#pragma once
-
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Corporation
-
- Authors:
- Auke Kok <auke-jan.h.kok@intel.com>
+ Copyright 2010 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
@@ -22,14 +17,34 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int svg_do(FILE *of,
- const char *build,
- struct list_sample_data *head,
- struct ps_struct *ps_first,
- int n_samples,
- int pscount,
- int n_cpus,
- double graph_start,
- double log_start,
- double interval,
- int overrun);
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "glob-util.h"
+#include "macro.h"
+
+static void test_glob_exists(void) {
+ char name[] = "/tmp/test-glob_exists.XXXXXX";
+ int fd = -1;
+ int r;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 1);
+
+ r = unlink(name);
+ assert_se(r == 0);
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 0);
+}
+
+int main(void) {
+ test_glob_exists();
+
+ return 0;
+}
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 6bf33306a9..1bd5c02f87 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -323,26 +323,29 @@ static void test_hashmap_remove_value(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
char *r;
- r = hashmap_remove_value(NULL, "key 1", (void*) "val 1");
+ char val1[] = "val 1";
+ char val2[] = "val 2";
+
+ r = hashmap_remove_value(NULL, "key 1", val1);
assert_se(r == NULL);
m = hashmap_new(&string_hash_ops);
assert_se(m);
- r = hashmap_remove_value(m, "key 1", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 1", val1);
assert_se(r == NULL);
- hashmap_put(m, "key 1", (void*) "val 1");
- hashmap_put(m, "key 2", (void*) "val 2");
+ hashmap_put(m, "key 1", val1);
+ hashmap_put(m, "key 2", val2);
- r = hashmap_remove_value(m, "key 1", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 1", val1);
assert_se(streq(r, "val 1"));
r = hashmap_get(m, "key 2");
assert_se(streq(r, "val 2"));
assert_se(!hashmap_get(m, "key 1"));
- r = hashmap_remove_value(m, "key 2", (void*) "val 1");
+ r = hashmap_remove_value(m, "key 2", val1);
assert_se(r == NULL);
r = hashmap_get(m, "key 2");
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
new file mode 100644
index 0000000000..276f25d091
--- /dev/null
+++ b/src/test/test-hexdecoct.c
@@ -0,0 +1,387 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "hexdecoct.h"
+#include "macro.h"
+#include "string-util.h"
+
+static void test_hexchar(void) {
+ assert_se(hexchar(0xa) == 'a');
+ assert_se(hexchar(0x0) == '0');
+}
+
+static void test_unhexchar(void) {
+ assert_se(unhexchar('a') == 0xA);
+ assert_se(unhexchar('A') == 0xA);
+ assert_se(unhexchar('0') == 0x0);
+}
+
+static void test_base32hexchar(void) {
+ assert_se(base32hexchar(0) == '0');
+ assert_se(base32hexchar(9) == '9');
+ assert_se(base32hexchar(10) == 'A');
+ assert_se(base32hexchar(31) == 'V');
+}
+
+static void test_unbase32hexchar(void) {
+ assert_se(unbase32hexchar('0') == 0);
+ assert_se(unbase32hexchar('9') == 9);
+ assert_se(unbase32hexchar('A') == 10);
+ assert_se(unbase32hexchar('V') == 31);
+ assert_se(unbase32hexchar('=') == -EINVAL);
+}
+
+static void test_base64char(void) {
+ assert_se(base64char(0) == 'A');
+ assert_se(base64char(26) == 'a');
+ assert_se(base64char(63) == '/');
+}
+
+static void test_unbase64char(void) {
+ assert_se(unbase64char('A') == 0);
+ assert_se(unbase64char('Z') == 25);
+ assert_se(unbase64char('a') == 26);
+ assert_se(unbase64char('z') == 51);
+ assert_se(unbase64char('0') == 52);
+ assert_se(unbase64char('9') == 61);
+ assert_se(unbase64char('+') == 62);
+ assert_se(unbase64char('/') == 63);
+ assert_se(unbase64char('=') == -EINVAL);
+}
+
+static void test_octchar(void) {
+ assert_se(octchar(00) == '0');
+ assert_se(octchar(07) == '7');
+}
+
+static void test_unoctchar(void) {
+ assert_se(unoctchar('0') == 00);
+ assert_se(unoctchar('7') == 07);
+}
+
+static void test_decchar(void) {
+ assert_se(decchar(0) == '0');
+ assert_se(decchar(9) == '9');
+}
+
+static void test_undecchar(void) {
+ assert_se(undecchar('0') == 0);
+ assert_se(undecchar('9') == 9);
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base32hexmem(void) {
+ char *b32;
+
+ b32 = base32hexmem("", strlen(""), true);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CO======"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG===="));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU==="));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG="));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8======"));
+ free(b32);
+
+ b32 = base32hexmem("", strlen(""), false);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CO"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG"));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU"));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG"));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8"));
+ free(b32);
+}
+
+static void test_unbase32hexmem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base64mem(void) {
+ char *b64;
+
+ assert_se(base64mem("", strlen(""), &b64) == 0);
+ assert_se(streq(b64, ""));
+ free(b64);
+
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
+ assert_se(streq(b64, "Zg=="));
+ free(b64);
+
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
+ assert_se(streq(b64, "Zm8="));
+ free(b64);
+
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
+ assert_se(streq(b64, "Zm9v"));
+ free(b64);
+
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYg=="));
+ free(b64);
+
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmE="));
+ free(b64);
+
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmFy"));
+ free(b64);
+}
+
+static void test_unbase64mem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+}
+
+static void test_hexdump(void) {
+ uint8_t data[146];
+ unsigned i;
+
+ hexdump(stdout, NULL, 0);
+ hexdump(stdout, "", 0);
+ hexdump(stdout, "", 1);
+ hexdump(stdout, "x", 1);
+ hexdump(stdout, "x", 2);
+ hexdump(stdout, "foobar", 7);
+ hexdump(stdout, "f\nobar", 7);
+ hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
+
+ for (i = 0; i < ELEMENTSOF(data); i++)
+ data[i] = i*2;
+
+ hexdump(stdout, data, sizeof(data));
+}
+
+int main(int argc, char *argv[]) {
+ test_hexchar();
+ test_unhexchar();
+ test_base32hexchar();
+ test_unbase32hexchar();
+ test_base64char();
+ test_unbase64char();
+ test_octchar();
+ test_unoctchar();
+ test_decchar();
+ test_undecchar();
+ test_unhexmem();
+ test_base32hexmem();
+ test_unbase32hexmem();
+ test_base64mem();
+ test_unbase64mem();
+ test_hexdump();
+
+ return 0;
+}
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
new file mode 100644
index 0000000000..10bd3833bc
--- /dev/null
+++ b/src/test/test-io-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "macro.h"
+
+static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
+ char check[n];
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+ assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
+
+ assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
+ assert_se(ftruncate(fd, n) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(read(fd, check, n) == (ssize_t) n);
+
+ assert_se(memcmp(buffer, check, n) == 0);
+}
+
+static void test_sparse_write(void) {
+ const char test_a[] = "test";
+ const char test_b[] = "\0\0\0\0test\0\0\0\0";
+ const char test_c[] = "\0\0test\0\0\0\0";
+ const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
+ const char test_e[] = "test\0\0\0\0test";
+ _cleanup_close_ int fd = -1;
+ char fn[] = "/tmp/sparseXXXXXX";
+
+ fd = mkostemp(fn, O_CLOEXEC);
+ assert_se(fd >= 0);
+ unlink(fn);
+
+ test_sparse_write_one(fd, test_a, sizeof(test_a));
+ test_sparse_write_one(fd, test_b, sizeof(test_b));
+ test_sparse_write_one(fd, test_c, sizeof(test_c));
+ test_sparse_write_one(fd, test_d, sizeof(test_d));
+ test_sparse_write_one(fd, test_e, sizeof(test_e));
+}
+
+int main(void) {
+ test_sparse_write();
+
+ return 0;
+}
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 2464d32458..c5bcaf47bb 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -23,9 +23,14 @@
int main(int argc, char *argv[]) {
uid_t uid;
-
- assert_se(argc == 2);
- assert_se(parse_uid(argv[1], &uid) >= 0);
+ int r;
+ const char* name = argv[1] ?: "nfsnobody";
+
+ r = get_user_creds(&name, &uid, NULL, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to resolve \"%s\": %m", name);
+ return EXIT_FAILURE;
+ }
return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index a7eb60e8cf..e28de9b37b 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -24,170 +24,140 @@
#include "libudev.h"
+#include "fd-util.h"
+#include "log.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
static void print_device(struct udev_device *device) {
const char *str;
dev_t devnum;
int count;
struct udev_list_entry *list_entry;
- printf("*** device: %p ***\n", device);
+ log_info("*** device: %p ***", device);
str = udev_device_get_action(device);
if (str != NULL)
- printf("action: '%s'\n", str);
+ log_info("action: '%s'", str);
str = udev_device_get_syspath(device);
- printf("syspath: '%s'\n", str);
+ log_info("syspath: '%s'", str);
str = udev_device_get_sysname(device);
- printf("sysname: '%s'\n", str);
+ log_info("sysname: '%s'", str);
str = udev_device_get_sysnum(device);
if (str != NULL)
- printf("sysnum: '%s'\n", str);
+ log_info("sysnum: '%s'", str);
str = udev_device_get_devpath(device);
- printf("devpath: '%s'\n", str);
+ log_info("devpath: '%s'", str);
str = udev_device_get_subsystem(device);
if (str != NULL)
- printf("subsystem: '%s'\n", str);
+ log_info("subsystem: '%s'", str);
str = udev_device_get_devtype(device);
if (str != NULL)
- printf("devtype: '%s'\n", str);
+ log_info("devtype: '%s'", str);
str = udev_device_get_driver(device);
if (str != NULL)
- printf("driver: '%s'\n", str);
+ log_info("driver: '%s'", str);
str = udev_device_get_devnode(device);
if (str != NULL)
- printf("devname: '%s'\n", str);
+ log_info("devname: '%s'", str);
devnum = udev_device_get_devnum(device);
if (major(devnum) > 0)
- printf("devnum: %u:%u\n", major(devnum), minor(devnum));
+ log_info("devnum: %u:%u", major(devnum), minor(devnum));
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
- printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
+ log_info("link: '%s'", udev_list_entry_get_name(list_entry));
count++;
}
if (count > 0)
- printf("found %i links\n", count);
+ log_info("found %i links", count);
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
- printf("property: '%s=%s'\n",
+ log_info("property: '%s=%s'",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
count++;
}
if (count > 0)
- printf("found %i properties\n", count);
+ log_info("found %i properties", count);
str = udev_device_get_property_value(device, "MAJOR");
if (str != NULL)
- printf("MAJOR: '%s'\n", str);
+ log_info("MAJOR: '%s'", str);
str = udev_device_get_sysattr_value(device, "dev");
if (str != NULL)
- printf("attr{dev}: '%s'\n", str);
-
- printf("\n");
+ log_info("attr{dev}: '%s'", str);
}
-static int test_device(struct udev *udev, const char *syspath) {
+static void test_device(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
- if (device == NULL) {
- printf("no device found\n");
- return -1;
- }
- print_device(device);
-
- return 0;
+ if (device == NULL)
+ log_warning_errno(errno, "udev_device_new_from_syspath: %m");
+ else
+ print_device(device);
}
-static int test_device_parents(struct udev *udev, const char *syspath) {
+static void test_device_parents(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
struct udev_device *device_parent;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL)
- return -1;
+ return;
- printf("looking at parents\n");
+ log_info("looking at parents");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
- printf("looking at parents again\n");
+ log_info("looking at parents again");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
-
- return 0;
}
-static int test_device_devnum(struct udev *udev) {
+static void test_device_devnum(struct udev *udev) {
dev_t devnum = makedev(1, 3);
- struct udev_device *device;
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ log_info("looking up device: %u:%u", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_devnum: %m");
+ else
+ print_device(device);
}
-static int test_device_subsys_name(struct udev *udev) {
- struct udev_device *device;
-
- printf("looking up device: 'block':'sda'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'subsystem':'pci'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'drivers':'scsi:sd'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
+static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: 'module':'printk'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
+ log_info("looking up device: '%s:%s'", subsys, dev);
+ device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
+ else
+ print_device(device);
}
static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
@@ -200,63 +170,45 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
if (device != NULL) {
- printf("device: '%s' (%s)\n",
- udev_device_get_syspath(device),
- udev_device_get_subsystem(device));
+ log_info("device: '%s' (%s)",
+ udev_device_get_syspath(device),
+ udev_device_get_subsystem(device));
udev_device_unref(device);
count++;
}
}
- printf("found %i devices\n\n", count);
+ log_info("found %i devices", count);
return count;
}
-static int test_monitor(struct udev *udev) {
- struct udev_monitor *udev_monitor = NULL;
- int fd_ep;
- int fd_udev = -1;
- struct epoll_event ep_udev, ep_stdin;
+static void test_monitor(struct udev *udev) {
+ _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor;
+ _cleanup_close_ int fd_ep;
+ int fd_udev;
+ struct epoll_event ep_udev = {
+ .events = EPOLLIN,
+ }, ep_stdin = {
+ .events = EPOLLIN,
+ .data.fd = STDIN_FILENO,
+ };
fd_ep = epoll_create1(EPOLL_CLOEXEC);
- if (fd_ep < 0) {
- printf("error creating epoll fd: %m\n");
- goto out;
- }
+ assert_se(fd_ep >= 0);
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (udev_monitor == NULL) {
- printf("no socket\n");
- goto out;
- }
+ assert_se(udev_monitor != NULL);
+
fd_udev = udev_monitor_get_fd(udev_monitor);
+ ep_udev.data.fd = fd_udev;
- if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
- printf("filter failed\n");
- goto out;
- }
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0);
- if (udev_monitor_enable_receiving(udev_monitor) < 0) {
- printf("bind failed\n");
- goto out;
- }
+ assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0);
- memzero(&ep_udev, sizeof(struct epoll_event));
- ep_udev.events = EPOLLIN;
- ep_udev.data.fd = fd_udev;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
-
- memzero(&ep_stdin, sizeof(struct epoll_event));
- ep_stdin.events = EPOLLIN;
- ep_stdin.data.fd = STDIN_FILENO;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0);
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0);
for (;;) {
int fdcount;
@@ -265,7 +217,7 @@ static int test_monitor(struct udev *udev) {
int i;
printf("waiting for events from udev, press ENTER to exit\n");
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
+ fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
printf("epoll fd count: %i\n", fdcount);
for (i = 0; i < fdcount; i++) {
@@ -279,36 +231,29 @@ static int test_monitor(struct udev *udev) {
udev_device_unref(device);
} else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
printf("exiting loop\n");
- goto out;
+ return;
}
}
}
-out:
- if (fd_ep >= 0)
- close(fd_ep);
- udev_monitor_unref(udev_monitor);
- return 0;
}
-static int test_queue(struct udev *udev) {
+static void test_queue(struct udev *udev) {
struct udev_queue *udev_queue;
+ bool empty;
udev_queue = udev_queue_new(udev);
- if (udev_queue == NULL)
- return -1;
-
- if (udev_queue_get_queue_is_empty(udev_queue))
- printf("queue is empty\n");
+ assert_se(udev_queue);
+ empty = udev_queue_get_queue_is_empty(udev_queue);
+ log_info("queue is %s", empty ? "empty" : "not empty");
udev_queue_unref(udev_queue);
- return 0;
}
static int test_enumerate(struct udev *udev, const char *subsystem) {
struct udev_enumerate *udev_enumerate;
int r;
- printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
+ log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -317,7 +262,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'net' + duplicated scan + null + zero\n");
+ log_info("enumerate 'net' + duplicated scan + null + zero");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -337,7 +282,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'block'\n");
+ log_info("enumerate 'block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -351,7 +296,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'not block'\n");
+ log_info("enumerate 'not block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -360,7 +305,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'pci, mem, vc'\n");
+ log_info("enumerate 'pci, mem, vc'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -371,7 +316,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'subsystem'\n");
+ log_info("enumerate 'subsystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -379,7 +324,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'property IF_FS_*=filesystem'\n");
+ log_info("enumerate 'property IF_FS_*=filesystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -397,32 +342,32 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
hwdb = udev_hwdb_new(udev);
udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
- printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
- printf("\n");
+ log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
hwdb = udev_hwdb_unref(hwdb);
assert_se(hwdb == NULL);
}
int main(int argc, char *argv[]) {
- struct udev *udev = NULL;
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ bool arg_monitor = false;
static const struct option options[] = {
- { "syspath", required_argument, NULL, 'p' },
+ { "syspath", required_argument, NULL, 'p' },
{ "subsystem", required_argument, NULL, 's' },
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'V' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "monitor", no_argument, NULL, 'm' },
{}
};
const char *syspath = "/devices/virtual/mem/null";
const char *subsystem = NULL;
- char path[1024];
int c;
udev = udev_new();
- printf("context: %p\n", udev);
+ log_info("context: %p", udev);
if (udev == NULL) {
- printf("no context\n");
+ log_info("no context");
return 1;
}
@@ -444,14 +389,18 @@ int main(int argc, char *argv[]) {
case 'h':
printf("--debug --syspath= --subsystem= --help\n");
- goto out;
+ return EXIT_SUCCESS;
case 'V':
printf("%s\n", VERSION);
- goto out;
+ return EXIT_SUCCESS;
+
+ case 'm':
+ arg_monitor = true;
+ break;
case '?':
- goto out;
+ return EXIT_FAILURE;
default:
assert_not_reached("Unhandled option code.");
@@ -459,14 +408,16 @@ int main(int argc, char *argv[]) {
/* add sys path if needed */
- if (!startswith(syspath, "/sys")) {
- xsprintf(path, "/sys/%s", syspath);
- syspath = path;
- }
+ if (!startswith(syspath, "/sys"))
+ syspath = strjoina("/sys/", syspath);
test_device(udev, syspath);
test_device_devnum(udev);
- test_device_subsys_name(udev);
+ test_device_subsys_name(udev, "block", "sda");
+ test_device_subsys_name(udev, "subsystem", "pci");
+ test_device_subsys_name(udev, "drivers", "scsi:sd");
+ test_device_subsys_name(udev, "module", "printk");
+
test_device_parents(udev, syspath);
test_enumerate(udev, subsystem);
@@ -475,8 +426,8 @@ int main(int argc, char *argv[]) {
test_hwdb(udev, "usb:v0D50p0011*");
- test_monitor(udev);
-out:
- udev_unref(udev);
- return 0;
+ if (arg_monitor)
+ test_monitor(udev);
+
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index 2748395ade..7b67337331 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -31,7 +31,7 @@ int main(int argc, char* argv[]) {
r = loopback_setup();
if (r < 0)
- fprintf(stderr, "loopback: %s\n", strerror(-r));
+ log_error("loopback: %m");
- return 0;
+ return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c
index 79ff6ae74d..bc6dd0926c 100644
--- a/src/test/test-netlink-manual.c
+++ b/src/test/test-netlink-manual.c
@@ -68,10 +68,10 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
/* skip test if module cannot be loaded */
r = load_module("ipip");
- if(r < 0)
+ if (r < 0)
return EXIT_TEST_SKIP;
- if(getuid() != 0)
+ if (getuid() != 0)
return EXIT_TEST_SKIP;
/* IPIP tunnel */
@@ -99,7 +99,7 @@ static int test_tunnel_configure(sd_netlink *rtnl) {
assert_se((m = sd_netlink_message_unref(m)) == NULL);
r = load_module("sit");
- if(r < 0)
+ if (r < 0)
return EXIT_TEST_SKIP;
/* sit */
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 53a585290a..d376dd56c5 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -433,6 +433,50 @@ static void test_path_is_mount_point(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
+static void test_file_in_same_dir(void) {
+ char *t;
+
+ t = file_in_same_dir("/", "a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("/", "/a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("", "a");
+ assert_se(streq(t, "a"));
+ free(t);
+
+ t = file_in_same_dir("a/", "a");
+ assert_se(streq(t, "a/a"));
+ free(t);
+
+ t = file_in_same_dir("bar/foo", "bar");
+ assert_se(streq(t, "bar/bar"));
+ free(t);
+}
+
+static void test_filename_is_valid(void) {
+ char foo[FILENAME_MAX+2];
+ int i;
+
+ assert_se(!filename_is_valid(""));
+ assert_se(!filename_is_valid("/bar/foo"));
+ assert_se(!filename_is_valid("/"));
+ assert_se(!filename_is_valid("."));
+ assert_se(!filename_is_valid(".."));
+
+ for (i=0; i<FILENAME_MAX+1; i++)
+ foo[i] = 'a';
+ foo[FILENAME_MAX+1] = '\0';
+
+ assert_se(!filename_is_valid(foo));
+
+ assert_se(filename_is_valid("foo_bar-333"));
+ assert_se(filename_is_valid("o.o"));
+}
+
int main(int argc, char **argv) {
test_path();
test_find_binary(argv[0]);
@@ -444,6 +488,8 @@ int main(int argc, char **argv) {
test_path_startswith();
test_prefix_root();
test_path_is_mount_point();
+ test_file_in_same_dir();
+ test_filename_is_valid();
return 0;
}
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 7a3b145414..1e704a03dc 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -93,7 +93,7 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
ts = now(CLOCK_MONOTONIC);
/* We process events until the service related to the path has been successfully started */
- while(service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
+ while (service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
usec_t n;
int r;
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
new file mode 100644
index 0000000000..a7a8f621a2
--- /dev/null
+++ b/src/test/test-proc-cmdline.c
@@ -0,0 +1,52 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 "log.h"
+#include "macro.h"
+#include "proc-cmdline.h"
+#include "special.h"
+#include "string-util.h"
+
+static int parse_item(const char *key, const char *value) {
+ assert_se(key);
+
+ log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
+ return 0;
+}
+
+static void test_parse_proc_cmdline(void) {
+ assert_se(parse_proc_cmdline(parse_item) >= 0);
+}
+
+static void test_runlevel_to_target(void) {
+ assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+ assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
+}
+
+int main(void) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_proc_cmdline();
+ test_runlevel_to_target();
+
+ return 0;
+}
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 48be5a3a87..4616314200 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -18,12 +18,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sys/personality.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "architecture.h"
#include "log.h"
#include "macro.h"
#include "process-util.h"
@@ -128,6 +130,29 @@ static void test_pid_is_alive(void) {
assert_se(!pid_is_alive(-1));
}
+static void test_personality(void) {
+
+ assert_se(personality_to_string(PER_LINUX));
+ assert_se(!personality_to_string(PERSONALITY_INVALID));
+
+ assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
+
+ assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
+ assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
+
+#ifdef __x86_64__
+ assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
+ assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
+
+ assert_se(personality_from_string("x86-64") == PER_LINUX);
+ assert_se(personality_from_string("x86") == PER_LINUX32);
+ assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
+ assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
+
+ assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
+#endif
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -135,6 +160,7 @@ int main(int argc, char *argv[]) {
test_get_process_comm();
test_pid_is_unwaited();
test_pid_is_alive();
+ test_personality();
return 0;
}
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
new file mode 100644
index 0000000000..7545ad3764
--- /dev/null
+++ b/src/test/test-selinux.c
@@ -0,0 +1,122 @@
+/***
+ 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 <sys/stat.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "log.h"
+#include "selinux-util.h"
+#include "string-util.h"
+#include "time-util.h"
+#include "util.h"
+
+static void test_testing(void) {
+ bool b;
+
+ log_info("============ %s ==========", __func__);
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+
+ mac_selinux_retest();
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+}
+
+static void test_loading(void) {
+ usec_t n1, n2;
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ r = mac_selinux_init();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info_errno(r, "mac_selinux_init → %d (%m) %.2fs", r, (n2 - n1)/1e6);
+}
+
+static void test_cleanup(void) {
+ usec_t n1, n2;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ mac_selinux_finish();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info("mac_selinux_finish → %.2fs", (n2 - n1)/1e6);
+}
+
+static void test_misc(const char* fname) {
+ _cleanup_(mac_selinux_freep) char *label = NULL, *label2 = NULL, *label3 = NULL;
+ int r;
+ _cleanup_close_ int fd = -1;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_get_our_label(&label);
+ log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"",
+ r, strnull(label));
+
+ r = mac_selinux_get_create_label_from_exe(fname, &label2);
+ log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"",
+ r, strnull(label2));
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+
+ r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3);
+ log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"",
+ r, strnull(label3));
+}
+
+static void test_create_file_prepare(const char* fname) {
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_create_file_prepare(fname, S_IRWXU);
+ log_info_errno(r, "mac_selinux_create_file_prepare → %d (%m)", r);
+
+ mac_selinux_create_file_clear();
+}
+
+int main(int argc, char **argv) {
+ const char *path = SYSTEMD_BINARY_PATH;
+ if (argc >= 2)
+ path = argv[1];
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ test_testing();
+ test_loading();
+ test_misc(path);
+ test_create_file_prepare(path);
+ test_cleanup();
+
+ return 0;
+}
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index 3083501ce9..671eb869cb 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -17,6 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <signal.h>
+#include <unistd.h>
+
+#include "macro.h"
#include "signal-util.h"
static void test_block_signals(void) {
@@ -44,6 +48,20 @@ static void test_block_signals(void) {
assert_se(sigismember(&ss, SIGVTALRM) == 0);
}
+static void test_ignore_signals(void) {
+ assert_se(ignore_signals(SIGINT, -1) >= 0);
+ assert_se(kill(getpid(), SIGINT) >= 0);
+ assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+ assert_se(kill(getpid(), SIGUSR1) >= 0);
+ assert_se(kill(getpid(), SIGUSR2) >= 0);
+ assert_se(kill(getpid(), SIGTERM) >= 0);
+ assert_se(kill(getpid(), SIGPIPE) >= 0);
+ assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_block_signals();
+ test_ignore_signals();
+
+ return 0;
}
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
index caae911f30..b74b7ad2dd 100644
--- a/src/test/test-siphash24.c
+++ b/src/test/test-siphash24.c
@@ -22,9 +22,9 @@
#define ITERATIONS 10000000ULL
-static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
+static void do_test(const uint8_t *in, size_t len, const uint8_t *key) {
struct siphash state = {};
- uint64_t out = 0;
+ uint64_t out;
unsigned i, j;
out = siphash24(in, len, key);
@@ -60,7 +60,46 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
assert_se(out == 0xa129ca6149be45e5);
}
}
- return 0;
+}
+
+static void test_short_hashes(void) {
+ const uint8_t one[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
+ const uint8_t key[16] = { 0x22, 0x24, 0x41, 0x22, 0x55, 0x77, 0x88, 0x07,
+ 0x23, 0x09, 0x23, 0x14, 0x0c, 0x33, 0x0e, 0x0f};
+ uint8_t two[sizeof one] = {};
+
+ struct siphash state1 = {}, state2 = {};
+ unsigned i, j;
+
+ siphash24_init(&state1, key);
+ siphash24_init(&state2, key);
+
+ /* hashing 1, 2, 3, 4, 5, ..., 16 bytes, with the byte after the buffer different */
+ for (i = 1; i <= sizeof one; i++) {
+ siphash24_compress(one, i, &state1);
+
+ two[i-1] = one[i-1];
+ siphash24_compress(two, i, &state2);
+
+ assert_se(memcmp(&state1, &state2, sizeof state1) == 0);
+ }
+
+ /* hashing n and 1, n and 2, n and 3, ..., n-1 and 1, n-2 and 2, ... */
+ for (i = sizeof one; i > 0; i--) {
+ zero(two);
+
+ for (j = 1; j <= sizeof one; j++) {
+ siphash24_compress(one, i, &state1);
+ siphash24_compress(one, j, &state1);
+
+ siphash24_compress(one, i, &state2);
+ two[j-1] = one[j-1];
+ siphash24_compress(two, j, &state2);
+
+ assert_se(memcmp(&state1, &state2, sizeof state1) == 0);
+ }
+ }
}
/* see https://131002.net/siphash/siphash.pdf, Appendix A */
@@ -80,4 +119,6 @@ int main(int argc, char *argv[]) {
do_test(in_buf + 2, sizeof(in), key);
memcpy(in_buf + 4, in, sizeof(in));
do_test(in_buf + 4, sizeof(in), key);
+
+ test_short_hashes();
}
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
new file mode 100644
index 0000000000..8f99a13772
--- /dev/null
+++ b/src/test/test-sizeof.c
@@ -0,0 +1,53 @@
+/***
+ 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 "log.h"
+#include "time-util.h"
+
+/* Print information about various types. Useful when diagnosing
+ * gcc diagnostics on an unfamiliar architecture. */
+
+#pragma GCC diagnostic ignored "-Wtype-limits"
+
+#define info(t) \
+ log_info("%s → %zu bits%s", STRINGIFY(t), \
+ sizeof(t)*CHAR_BIT, \
+ strstr(STRINGIFY(t), "signed") ? "" : \
+ ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+
+int main(void) {
+ info(char);
+ info(signed char);
+ info(unsigned char);
+ info(short unsigned);
+ info(unsigned);
+ info(long unsigned);
+ info(long long unsigned);
+
+ info(float);
+ info(double);
+ info(long double);
+
+ info(size_t);
+ info(ssize_t);
+ info(time_t);
+ info(usec_t);
+
+ return 0;
+}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
new file mode 100644
index 0000000000..a10227f823
--- /dev/null
+++ b/src/test/test-stat-util.c
@@ -0,0 +1,68 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+#include "stat-util.h"
+
+static void test_files_same(void) {
+ _cleanup_close_ int fd = -1;
+ char name[] = "/tmp/test-files_same.XXXXXX";
+ char name_alias[] = "/tmp/test-files_same.alias";
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_alias) >= 0);
+
+ assert_se(files_same(name, name));
+ assert_se(files_same(name, name_alias));
+
+ unlink(name);
+ unlink(name_alias);
+}
+
+static void test_is_symlink(void) {
+ char name[] = "/tmp/test-is_symlink.XXXXXX";
+ char name_link[] = "/tmp/test-is_symlink.link";
+ _cleanup_close_ int fd = -1;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_link) >= 0);
+
+ assert_se(is_symlink(name) == 0);
+ assert_se(is_symlink(name_link) == 1);
+ assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
+
+
+ unlink(name);
+ unlink(name_link);
+}
+
+int main(int argc, char *argv[]) {
+ test_files_same();
+ test_is_symlink();
+
+ return 0;
+}
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 9b48e95998..d0f84d70bc 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -17,7 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "macro.h"
#include "string-util.h"
+#include "strv.h"
static void test_string_erase(void) {
char *x;
@@ -97,9 +100,271 @@ static void test_ascii_strcasecmp_nn(void) {
assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
}
+static void test_streq_ptr(void) {
+ assert_se(streq_ptr(NULL, NULL));
+ assert_se(!streq_ptr("abc", "cdef"));
+}
+
+static void test_strstrip(void) {
+ char *r;
+ char input[] = " hello, waldo. ";
+
+ r = strstrip(input);
+ assert_se(streq(r, "hello, waldo."));
+}
+
+static void test_strextend(void) {
+ _cleanup_free_ char *str = strdup("0123");
+ strextend(&str, "456", "78", "9", NULL);
+ assert_se(streq(str, "0123456789"));
+}
+
+static void test_strrep(void) {
+ _cleanup_free_ char *one, *three, *zero;
+ one = strrep("waldo", 1);
+ three = strrep("waldo", 3);
+ zero = strrep("waldo", 0);
+
+ assert_se(streq(one, "waldo"));
+ assert_se(streq(three, "waldowaldowaldo"));
+ assert_se(streq(zero, ""));
+}
+
+
+static void test_strappend(void) {
+ _cleanup_free_ char *t1, *t2, *t3, *t4;
+
+ t1 = strappend(NULL, NULL);
+ assert_se(streq(t1, ""));
+
+ t2 = strappend(NULL, "suf");
+ assert_se(streq(t2, "suf"));
+
+ t3 = strappend("pre", NULL);
+ assert_se(streq(t3, "pre"));
+
+ t4 = strappend("pre", "suf");
+ assert_se(streq(t4, "presuf"));
+}
+
+static void test_string_has_cc(void) {
+ assert_se(string_has_cc("abc\1", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t\a"));
+
+ assert_se(!string_has_cc("abc\t\t", "\t"));
+ assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
+ assert_se(!string_has_cc("a\ab\tc", "\t\a"));
+}
+
+static void test_ascii_strlower(void) {
+ char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
+ assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
+}
+
+static void test_strshorten(void) {
+ char s[] = "foobar";
+
+ assert_se(strlen(strshorten(s, 6)) == 6);
+ assert_se(strlen(strshorten(s, 12)) == 6);
+ assert_se(strlen(strshorten(s, 2)) == 2);
+ assert_se(strlen(strshorten(s, 0)) == 0);
+}
+
+static void test_strjoina(void) {
+ char *actual;
+
+ actual = strjoina("", "foo", "bar");
+ assert_se(streq(actual, "foobar"));
+
+ actual = strjoina("foo", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo", "", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo");
+ assert_se(streq(actual, "foo"));
+
+ actual = strjoina(NULL);
+ assert_se(streq(actual, ""));
+
+ actual = strjoina(NULL, "foo");
+ assert_se(streq(actual, ""));
+
+ actual = strjoina("foo", NULL, "bar");
+ assert_se(streq(actual, "foo"));
+}
+
+static void test_strcmp_ptr(void) {
+ assert_se(strcmp_ptr(NULL, NULL) == 0);
+ assert_se(strcmp_ptr("", NULL) > 0);
+ assert_se(strcmp_ptr("foo", NULL) > 0);
+ assert_se(strcmp_ptr(NULL, "") < 0);
+ assert_se(strcmp_ptr(NULL, "bar") < 0);
+ assert_se(strcmp_ptr("foo", "bar") > 0);
+ assert_se(strcmp_ptr("bar", "baz") < 0);
+ assert_se(strcmp_ptr("foo", "foo") == 0);
+ assert_se(strcmp_ptr("", "") == 0);
+}
+
+static void test_foreach_word(void) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+ const char test[] = "test abc d\te f ";
+ const char * const expected[] = {
+ "test",
+ "abc",
+ "d",
+ "e",
+ "f",
+ "",
+ NULL
+ };
+
+ FOREACH_WORD(word, l, test, state)
+ assert_se(strneq(expected[i++], word, l));
+}
+
+static void check(const char *test, char** expected, bool trailing) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+
+ printf("<<<%s>>>\n", test);
+ FOREACH_WORD_QUOTED(word, l, test, state) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = strndup(word, l));
+ assert_se(strneq(expected[i++], word, l));
+ printf("<%s>\n", t);
+ }
+ printf("<<<%s>>>\n", state);
+ assert_se(expected[i] == NULL);
+ assert_se(isempty(state) == !trailing);
+}
+
+static void test_foreach_word_quoted(void) {
+ check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
+ STRV_MAKE("test",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "",
+ "",
+ "hhh",
+ "",
+ "",
+ "a b c"),
+ false);
+
+ check("test \"xxx",
+ STRV_MAKE("test"),
+ true);
+
+ check("test\\",
+ STRV_MAKE_EMPTY,
+ true);
+}
+
+static void test_endswith(void) {
+ assert_se(endswith("foobar", "bar"));
+ assert_se(endswith("foobar", ""));
+ assert_se(endswith("foobar", "foobar"));
+ assert_se(endswith("", ""));
+
+ assert_se(!endswith("foobar", "foo"));
+ assert_se(!endswith("foobar", "foobarfoofoo"));
+}
+
+static void test_endswith_no_case(void) {
+ assert_se(endswith_no_case("fooBAR", "bar"));
+ assert_se(endswith_no_case("foobar", ""));
+ assert_se(endswith_no_case("foobar", "FOOBAR"));
+ assert_se(endswith_no_case("", ""));
+
+ assert_se(!endswith_no_case("foobar", "FOO"));
+ assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
+}
+
+static void test_delete_chars(void) {
+ char *r;
+ char input[] = " hello, waldo. abc";
+
+ r = delete_chars(input, WHITESPACE);
+ assert_se(streq(r, "hello,waldo.abc"));
+}
+
+static void test_in_charset(void) {
+ assert_se(in_charset("dddaaabbbcccc", "abcd"));
+ assert_se(!in_charset("dddaaabbbcccc", "abc f"));
+}
+
+static void test_split_pair(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+
+ assert_se(split_pair("", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
+ assert_se(streq(a, "foo"));
+ assert_se(streq(b, "bar"));
+ free(a);
+ free(b);
+ assert_se(split_pair("==", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, ""));
+ free(a);
+ free(b);
+
+ assert_se(split_pair("===", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, "="));
+}
+
+static void test_first_word(void) {
+ assert_se(first_word("Hello", ""));
+ assert_se(first_word("Hello", "Hello"));
+ assert_se(first_word("Hello world", "Hello"));
+ assert_se(first_word("Hello\tworld", "Hello"));
+ assert_se(first_word("Hello\nworld", "Hello"));
+ assert_se(first_word("Hello\rworld", "Hello"));
+ assert_se(first_word("Hello ", "Hello"));
+
+ assert_se(!first_word("Hello", "Hellooo"));
+ assert_se(!first_word("Hello", "xxxxx"));
+ assert_se(!first_word("Hellooo", "Hello"));
+}
+
int main(int argc, char *argv[]) {
test_string_erase();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
+ test_streq_ptr();
+ test_strstrip();
+ test_strextend();
+ test_strrep();
+ test_strappend();
+ test_string_has_cc();
+ test_ascii_strlower();
+ test_strshorten();
+ test_strjoina();
+ test_strcmp_ptr();
+ test_foreach_word();
+ test_foreach_word_quoted();
+ test_endswith();
+ test_endswith_no_case();
+ test_delete_chars();
+ test_in_charset();
+ test_split_pair();
+ test_first_word();
+
return 0;
}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index ef451c6abf..fea1f848cd 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -660,6 +660,25 @@ static void test_strv_make_nulstr(void) {
test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
}
+static void test_foreach_string(void) {
+ const char * const t[] = {
+ "foo",
+ "bar",
+ "waldo",
+ NULL
+ };
+ const char *x;
+ unsigned i = 0;
+
+ FOREACH_STRING(x, "foo", "bar", "waldo")
+ assert_se(streq_ptr(t[i++], x));
+
+ assert_se(i == 3);
+
+ FOREACH_STRING(x, "zzz")
+ assert_se(streq(x, "zzz"));
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
test_strv_foreach();
@@ -724,5 +743,7 @@ int main(int argc, char *argv[]) {
test_strv_extend_n();
test_strv_make_nulstr();
+ test_foreach_string();
+
return 0;
}
diff --git a/src/test/test-time.c b/src/test/test-time.c
index 9062c3f3c1..ee7d55c5ab 100644
--- a/src/test/test-time.c
+++ b/src/test/test-time.c
@@ -220,7 +220,7 @@ int main(int argc, char *argv[]) {
/* Ensure TIME_T_MAX works correctly */
x = (uintmax_t) TIME_T_MAX;
- x ++;
+ x++;
assert((time_t) x < 0);
return 0;
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 9cc64f7c68..d01789fe08 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
log_debug("version %s", VERSION);
- mac_selinux_init("/dev");
+ mac_selinux_init();
action = argv[1];
if (action == NULL) {
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index b0c343590d..cc6c61ba63 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -606,7 +606,7 @@ static void test_install_printf(void) {
} else assert_se(t == NULL); \
strcpy(i.name, d1); \
strcpy(i.path, d2); \
- } while(false)
+ } while (false)
expect(i, "%n", "name.service");
expect(i, "%N", "name");
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 42c6a8d5e2..8d1ec19f17 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -37,6 +37,30 @@ static void test_gid_to_name_one(gid_t gid, const char *name) {
assert_se(streq_ptr(t, name));
}
+static void test_parse_uid(void) {
+ int r;
+ uid_t uid;
+
+ r = parse_uid("100", &uid);
+ assert_se(r == 0);
+ assert_se(uid == 100);
+
+ r = parse_uid("65535", &uid);
+ assert_se(r == -ENXIO);
+
+ r = parse_uid("asdsdas", &uid);
+ assert_se(r == -EINVAL);
+}
+
+static void test_uid_ptr(void) {
+
+ assert_se(UID_TO_PTR(0) != NULL);
+ assert_se(UID_TO_PTR(1000) != NULL);
+
+ assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
+ assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
+}
+
int main(int argc, char*argv[]) {
test_uid_to_name_one(0, "root");
@@ -48,5 +72,8 @@ int main(int argc, char*argv[]) {
test_gid_to_name_one(0xFFFF, "65535");
test_gid_to_name_one(0xFFFFFFFF, "4294967295");
+ test_parse_uid();
+ test_uid_ptr();
+
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9a8a265790..05cb1eae76 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -19,47 +19,16 @@
***/
#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/xattr.h>
#include <unistd.h>
-#include "alloc-util.h"
-#include "conf-parser.h"
-#include "cpu-set-util.h"
#include "def.h"
-#include "escape.h"
-#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
-#include "fstab-util.h"
-#include "glob-util.h"
-#include "hexdecoct.h"
-#include "io-util.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
#include "rm-rf.h"
-#include "signal-util.h"
-#include "special.h"
-#include "stat-util.h"
#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
#include "util.h"
-#include "virt.h"
-#include "web-util.h"
-#include "xattr-util.h"
-
-static void test_streq_ptr(void) {
- assert_se(streq_ptr(NULL, NULL));
- assert_se(!streq_ptr("abc", "cdef"));
-}
static void test_align_power2(void) {
unsigned long i, p2;
@@ -151,19 +120,6 @@ static void test_container_of(void) {
v1) == &myval);
}
-static void test_alloca(void) {
- static const uint8_t zero[997] = { };
- char *t;
-
- t = alloca_align(17, 512);
- assert_se(!((uintptr_t)t & 0xff));
- memzero(t, 17);
-
- t = alloca0_align(997, 1024);
- assert_se(!((uintptr_t)t & 0x1ff));
- assert_se(!memcmp(t, zero, 997));
-}
-
static void test_div_round_up(void) {
int div;
@@ -197,544 +153,6 @@ static void test_div_round_up(void) {
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
}
-static void test_first_word(void) {
- assert_se(first_word("Hello", ""));
- assert_se(first_word("Hello", "Hello"));
- assert_se(first_word("Hello world", "Hello"));
- assert_se(first_word("Hello\tworld", "Hello"));
- assert_se(first_word("Hello\nworld", "Hello"));
- assert_se(first_word("Hello\rworld", "Hello"));
- assert_se(first_word("Hello ", "Hello"));
-
- assert_se(!first_word("Hello", "Hellooo"));
- assert_se(!first_word("Hello", "xxxxx"));
- assert_se(!first_word("Hellooo", "Hello"));
-}
-
-static void test_close_many(void) {
- int fds[3];
- char name0[] = "/tmp/test-close-many.XXXXXX";
- char name1[] = "/tmp/test-close-many.XXXXXX";
- char name2[] = "/tmp/test-close-many.XXXXXX";
-
- fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
- fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
- fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
-
- close_many(fds, 2);
-
- assert_se(fcntl(fds[0], F_GETFD) == -1);
- assert_se(fcntl(fds[1], F_GETFD) == -1);
- assert_se(fcntl(fds[2], F_GETFD) >= 0);
-
- safe_close(fds[2]);
-
- unlink(name0);
- unlink(name1);
- unlink(name2);
-}
-
-static void test_parse_uid(void) {
- int r;
- uid_t uid;
-
- r = parse_uid("100", &uid);
- assert_se(r == 0);
- assert_se(uid == 100);
-
- r = parse_uid("65535", &uid);
- assert_se(r == -ENXIO);
-
- r = parse_uid("asdsdas", &uid);
- assert_se(r == -EINVAL);
-}
-
-static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
-
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
-
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
-
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
-
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
-}
-
-static void test_strstrip(void) {
- char *r;
- char input[] = " hello, waldo. ";
-
- r = strstrip(input);
- assert_se(streq(r, "hello, waldo."));
-}
-
-static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
-
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
-}
-
-static void test_in_charset(void) {
- assert_se(in_charset("dddaaabbbcccc", "abcd"));
- assert_se(!in_charset("dddaaabbbcccc", "abc f"));
-}
-
-static void test_hexchar(void) {
- assert_se(hexchar(0xa) == 'a');
- assert_se(hexchar(0x0) == '0');
-}
-
-static void test_unhexchar(void) {
- assert_se(unhexchar('a') == 0xA);
- assert_se(unhexchar('A') == 0xA);
- assert_se(unhexchar('0') == 0x0);
-}
-
-static void test_base32hexchar(void) {
- assert_se(base32hexchar(0) == '0');
- assert_se(base32hexchar(9) == '9');
- assert_se(base32hexchar(10) == 'A');
- assert_se(base32hexchar(31) == 'V');
-}
-
-static void test_unbase32hexchar(void) {
- assert_se(unbase32hexchar('0') == 0);
- assert_se(unbase32hexchar('9') == 9);
- assert_se(unbase32hexchar('A') == 10);
- assert_se(unbase32hexchar('V') == 31);
- assert_se(unbase32hexchar('=') == -EINVAL);
-}
-
-static void test_base64char(void) {
- assert_se(base64char(0) == 'A');
- assert_se(base64char(26) == 'a');
- assert_se(base64char(63) == '/');
-}
-
-static void test_unbase64char(void) {
- assert_se(unbase64char('A') == 0);
- assert_se(unbase64char('Z') == 25);
- assert_se(unbase64char('a') == 26);
- assert_se(unbase64char('z') == 51);
- assert_se(unbase64char('0') == 52);
- assert_se(unbase64char('9') == 61);
- assert_se(unbase64char('+') == 62);
- assert_se(unbase64char('/') == 63);
- assert_se(unbase64char('=') == -EINVAL);
-}
-
-static void test_octchar(void) {
- assert_se(octchar(00) == '0');
- assert_se(octchar(07) == '7');
-}
-
-static void test_unoctchar(void) {
- assert_se(unoctchar('0') == 00);
- assert_se(unoctchar('7') == 07);
-}
-
-static void test_decchar(void) {
- assert_se(decchar(0) == '0');
- assert_se(decchar(9) == '9');
-}
-
-static void test_undecchar(void) {
- assert_se(undecchar('0') == 0);
- assert_se(undecchar('9') == 9);
-}
-
-static void test_unhexmem(void) {
- const char *hex = "efa214921";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
- _cleanup_free_ void *mem = NULL;
- size_t len;
-
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
-
- assert_se((hex2 = hexmem(mem, len)));
-
- free(mem);
-
- assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
-
- free(hex2);
-
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base32hexmem(void) {
- char *b32;
-
- b32 = base32hexmem("", strlen(""), true);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), true);
- assert_se(b32);
- assert_se(streq(b32, "CO======"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNG===="));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU==="));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG="));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8======"));
- free(b32);
-
- b32 = base32hexmem("", strlen(""), false);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), false);
- assert_se(b32);
- assert_se(streq(b32, "CO"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNG"));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU"));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG"));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8"));
- free(b32);
-}
-
-static void test_unbase32hexmem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base64mem(void) {
- char *b64;
-
- assert_se(base64mem("", strlen(""), &b64) == 0);
- assert_se(streq(b64, ""));
- free(b64);
-
- assert_se(base64mem("f", strlen("f"), &b64) == 4);
- assert_se(streq(b64, "Zg=="));
- free(b64);
-
- assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
- assert_se(streq(b64, "Zm8="));
- free(b64);
-
- assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
- assert_se(streq(b64, "Zm9v"));
- free(b64);
-
- assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYg=="));
- free(b64);
-
- assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmE="));
- free(b64);
-
- assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmFy"));
- free(b64);
-}
-
-static void test_unbase64mem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
-}
-
-static void test_cescape(void) {
- _cleanup_free_ char *escaped;
-
- assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
- assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
-}
-
-static void test_cunescape(void) {
- _cleanup_free_ char *unescaped;
-
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
- unescaped = mfree(unescaped);
-
- /* incomplete sequences */
- assert_se(cunescape("\\x0", 0, &unescaped) < 0);
- assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x0"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\x", 0, &unescaped) < 0);
- assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\", 0, &unescaped) < 0);
- assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\11", 0, &unescaped) < 0);
- assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\11"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\1", 0, &unescaped) < 0);
- assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\1"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
- assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "ßßΠA"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\073", 0, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, ";"));
-}
-
-static void test_foreach_word(void) {
- const char *word, *state;
- size_t l;
- int i = 0;
- const char test[] = "test abc d\te f ";
- const char * const expected[] = {
- "test",
- "abc",
- "d",
- "e",
- "f",
- "",
- NULL
- };
-
- FOREACH_WORD(word, l, test, state)
- assert_se(strneq(expected[i++], word, l));
-}
-
-static void check(const char *test, char** expected, bool trailing) {
- const char *word, *state;
- size_t l;
- int i = 0;
-
- printf("<<<%s>>>\n", test);
- FOREACH_WORD_QUOTED(word, l, test, state) {
- _cleanup_free_ char *t = NULL;
-
- assert_se(t = strndup(word, l));
- assert_se(strneq(expected[i++], word, l));
- printf("<%s>\n", t);
- }
- printf("<<<%s>>>\n", state);
- assert_se(expected[i] == NULL);
- assert_se(isempty(state) == !trailing);
-}
-
-static void test_foreach_word_quoted(void) {
- check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
- STRV_MAKE("test",
- "a",
- "b",
- "c",
- "d",
- "e",
- "",
- "",
- "hhh",
- "",
- "",
- "a b c"),
- false);
-
- check("test \"xxx",
- STRV_MAKE("test"),
- true);
-
- check("test\\",
- STRV_MAKE_EMPTY,
- true);
-}
-
-static void test_memdup_multiply(void) {
- int org[] = {1, 2, 3};
- int *dup;
-
- dup = (int*)memdup_multiply(org, sizeof(int), 3);
-
- assert_se(dup);
- assert_se(dup[0] == 1);
- assert_se(dup[1] == 2);
- assert_se(dup[2] == 3);
- free(dup);
-}
-
static void test_u64log2(void) {
assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3);
@@ -754,210 +172,6 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
-static void test_parse_cpu_set(void) {
- cpu_set_t *c = NULL;
- int ncpus;
- int cpu;
-
- /* Simple range (from CPUAffinity example) */
- ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
- c = mfree(c);
-
- /* A more interesting range */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Quoted strings */
- ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Use commas as separators */
- ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Commas with spaces (and trailing comma, space) */
- ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 8; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges */
- ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges with trailing comma, space */
- ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Negative range (returns empty cpu_set) */
- ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
- c = mfree(c);
-
- /* Overlapping ranges */
- ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
- for (cpu = 0; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Mix ranges and individual CPUs */
- ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
- assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 4; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Garbage */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Range with garbage */
- ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Empty string */
- c = NULL;
- ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus == 0); /* empty string returns 0 */
- assert_se(!c);
-
- /* Runnaway quoted string */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-}
-
-static void test_config_parse_iec_uint64(void) {
- uint64_t offset = 0;
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
- assert_se(offset == 4 * 1024 * 1024);
-
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
-}
-
-static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
-}
-
-static void test_strrep(void) {
- _cleanup_free_ char *one, *three, *zero;
- one = strrep("waldo", 1);
- three = strrep("waldo", 3);
- zero = strrep("waldo", 0);
-
- assert_se(streq(one, "waldo"));
- assert_se(streq(three, "waldowaldowaldo"));
- assert_se(streq(zero, ""));
-}
-
-static void test_split_pair(void) {
- _cleanup_free_ char *a = NULL, *b = NULL;
-
- assert_se(split_pair("", "", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
- assert_se(split_pair("", "=", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
- assert_se(streq(a, "foo"));
- assert_se(streq(b, "bar"));
- free(a);
- free(b);
- assert_se(split_pair("==", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, ""));
- free(a);
- free(b);
-
- assert_se(split_pair("===", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, "="));
-}
-
-static void test_fstab_node_to_udev_node(void) {
- char *n;
-
- n = fstab_node_to_udev_node("LABEL=applé/jack");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
- free(n);
-
- n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PONIES=awesome");
- puts(n);
- assert_se(streq(n, "PONIES=awesome"));
- free(n);
-
- n = fstab_node_to_udev_node("/dev/xda1");
- puts(n);
- assert_se(streq(n, "/dev/xda1"));
- free(n);
-}
-
-static void test_get_files_in_directory(void) {
- _cleanup_strv_free_ char **l = NULL, **t = NULL;
-
- assert_se(get_files_in_directory("/tmp", &l) >= 0);
- assert_se(get_files_in_directory(".", &t) >= 0);
- assert_se(get_files_in_directory(".", NULL) >= 0);
-}
-
static void test_in_set(void) {
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
@@ -968,50 +182,6 @@ static void test_in_set(void) {
assert_se(!IN_SET(0, 1, 2, 3, 4));
}
-static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
- _cleanup_free_ char *contents = NULL;
- size_t size;
- int fd, r;
- struct iovec iov[3];
-
- IOVEC_SET_STRING(iov[0], "abc\n");
- IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
- IOVEC_SET_STRING(iov[2], "");
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- printf("tmpfile: %s", name);
-
- r = writev(fd, iov, 3);
- assert_se(r >= 0);
-
- r = read_full_file(name, &contents, &size);
- assert_se(r == 0);
- printf("contents: %s", contents);
- assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
-}
-
-static void test_hexdump(void) {
- uint8_t data[146];
- unsigned i;
-
- hexdump(stdout, NULL, 0);
- hexdump(stdout, "", 0);
- hexdump(stdout, "", 1);
- hexdump(stdout, "x", 1);
- hexdump(stdout, "x", 2);
- hexdump(stdout, "foobar", 7);
- hexdump(stdout, "f\nobar", 7);
- hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
-
- for (i = 0; i < ELEMENTSOF(data); i++)
- data[i] = i*2;
-
- hexdump(stdout, data, sizeof(data));
-}
-
static void test_log2i(void) {
assert_se(log2i(1) == 0);
assert_se(log2i(2) == 1);
@@ -1023,341 +193,6 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
-static void test_foreach_string(void) {
- const char * const t[] = {
- "foo",
- "bar",
- "waldo",
- NULL
- };
- const char *x;
- unsigned i = 0;
-
- FOREACH_STRING(x, "foo", "bar", "waldo")
- assert_se(streq_ptr(t[i++], x));
-
- assert_se(i == 3);
-
- FOREACH_STRING(x, "zzz")
- assert_se(streq(x, "zzz"));
-}
-
-static void test_filename_is_valid(void) {
- char foo[FILENAME_MAX+2];
- int i;
-
- assert_se(!filename_is_valid(""));
- assert_se(!filename_is_valid("/bar/foo"));
- assert_se(!filename_is_valid("/"));
- assert_se(!filename_is_valid("."));
- assert_se(!filename_is_valid(".."));
-
- for (i=0; i<FILENAME_MAX+1; i++)
- foo[i] = 'a';
- foo[FILENAME_MAX+1] = '\0';
-
- assert_se(!filename_is_valid(foo));
-
- assert_se(filename_is_valid("foo_bar-333"));
- assert_se(filename_is_valid("o.o"));
-}
-
-static void test_string_has_cc(void) {
- assert_se(string_has_cc("abc\1", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t\a"));
-
- assert_se(!string_has_cc("abc\t\t", "\t"));
- assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
- assert_se(!string_has_cc("a\ab\tc", "\t\a"));
-}
-
-static void test_ascii_strlower(void) {
- char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
- assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
-}
-
-static void test_files_same(void) {
- _cleanup_close_ int fd = -1;
- char name[] = "/tmp/test-files_same.XXXXXX";
- char name_alias[] = "/tmp/test-files_same.alias";
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_alias) >= 0);
-
- assert_se(files_same(name, name));
- assert_se(files_same(name, name_alias));
-
- unlink(name);
- unlink(name_alias);
-}
-
-static void test_is_valid_documentation_url(void) {
- assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
- assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
- assert_se(documentation_url_is_valid("file:/foo/foo"));
- assert_se(documentation_url_is_valid("man:systemd.special(7)"));
- assert_se(documentation_url_is_valid("info:bar"));
-
- assert_se(!documentation_url_is_valid("foo:"));
- assert_se(!documentation_url_is_valid("info:"));
- assert_se(!documentation_url_is_valid(""));
-}
-
-static void test_file_in_same_dir(void) {
- char *t;
-
- t = file_in_same_dir("/", "a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("/", "/a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("", "a");
- assert_se(streq(t, "a"));
- free(t);
-
- t = file_in_same_dir("a/", "a");
- assert_se(streq(t, "a/a"));
- free(t);
-
- t = file_in_same_dir("bar/foo", "bar");
- assert_se(streq(t, "bar/bar"));
- free(t);
-}
-
-static void test_endswith(void) {
- assert_se(endswith("foobar", "bar"));
- assert_se(endswith("foobar", ""));
- assert_se(endswith("foobar", "foobar"));
- assert_se(endswith("", ""));
-
- assert_se(!endswith("foobar", "foo"));
- assert_se(!endswith("foobar", "foobarfoofoo"));
-}
-
-static void test_endswith_no_case(void) {
- assert_se(endswith_no_case("fooBAR", "bar"));
- assert_se(endswith_no_case("foobar", ""));
- assert_se(endswith_no_case("foobar", "FOOBAR"));
- assert_se(endswith_no_case("", ""));
-
- assert_se(!endswith_no_case("foobar", "FOO"));
- assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
-}
-
-static void test_close_nointr(void) {
- char name[] = "/tmp/test-test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
- assert_se(close_nointr(fd) < 0);
-
- unlink(name);
-}
-
-
-static void test_unlink_noerrno(void) {
- char name[] = "/tmp/test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
-
- {
- PROTECT_ERRNO;
- errno = -42;
- assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == -42);
- assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == -42);
- }
-}
-
-static void test_readlink_and_make_absolute(void) {
- char tempdir[] = "/tmp/test-readlink_and_make_absolute";
- char name[] = "/tmp/test-readlink_and_make_absolute/original";
- char name2[] = "test-readlink_and_make_absolute/original";
- char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
- char *r = NULL;
-
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
- assert_se(touch(name) >= 0);
-
- assert_se(symlink(name, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(chdir(tempdir) >= 0);
- assert_se(symlink(name2, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
-}
-
-static void test_ignore_signals(void) {
- assert_se(ignore_signals(SIGINT, -1) >= 0);
- assert_se(kill(getpid(), SIGINT) >= 0);
- assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
- assert_se(kill(getpid(), SIGUSR1) >= 0);
- assert_se(kill(getpid(), SIGUSR2) >= 0);
- assert_se(kill(getpid(), SIGTERM) >= 0);
- assert_se(kill(getpid(), SIGPIPE) >= 0);
- assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
-}
-
-static void test_strshorten(void) {
- char s[] = "foobar";
-
- assert_se(strlen(strshorten(s, 6)) == 6);
- assert_se(strlen(strshorten(s, 12)) == 6);
- assert_se(strlen(strshorten(s, 2)) == 2);
- assert_se(strlen(strshorten(s, 0)) == 0);
-}
-
-static void test_strjoina(void) {
- char *actual;
-
- actual = strjoina("", "foo", "bar");
- assert_se(streq(actual, "foobar"));
-
- actual = strjoina("foo", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo", "", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo");
- assert_se(streq(actual, "foo"));
-
- actual = strjoina(NULL);
- assert_se(streq(actual, ""));
-
- actual = strjoina(NULL, "foo");
- assert_se(streq(actual, ""));
-
- actual = strjoina("foo", NULL, "bar");
- assert_se(streq(actual, "foo"));
-}
-
-static void test_is_symlink(void) {
- char name[] = "/tmp/test-is_symlink.XXXXXX";
- char name_link[] = "/tmp/test-is_symlink.link";
- _cleanup_close_ int fd = -1;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_link) >= 0);
-
- assert_se(is_symlink(name) == 0);
- assert_se(is_symlink(name_link) == 1);
- assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
-
- unlink(name);
- unlink(name_link);
-}
-
-static void test_search_and_fopen(void) {
- const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(basename(name), "r", "/", dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-
-static void test_search_and_fopen_nulstr(void) {
- const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-static void test_glob_exists(void) {
- char name[] = "/tmp/test-glob_exists.XXXXXX";
- int fd = -1;
- int r;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 1);
-
- r = unlink(name);
- assert_se(r == 0);
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 0);
-}
-
static void test_execute_directory(void) {
char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
@@ -1402,17 +237,6 @@ static void test_execute_directory(void) {
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
}
-static int parse_item(const char *key, const char *value) {
- assert_se(key);
-
- log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
- return 0;
-}
-
-static void test_parse_proc_cmdline(void) {
- assert_se(parse_proc_cmdline(parse_item) >= 0);
-}
-
static void test_raw_clone(void) {
pid_t parent, pid, pid2;
@@ -1438,285 +262,20 @@ static void test_raw_clone(void) {
}
}
-static void test_same_fd(void) {
- _cleanup_close_pair_ int p[2] = { -1, -1 };
- _cleanup_close_ int a = -1, b = -1, c = -1;
-
- assert_se(pipe2(p, O_CLOEXEC) >= 0);
- assert_se((a = dup(p[0])) >= 0);
- assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
- assert_se((c = dup(a)) >= 0);
-
- assert_se(same_fd(p[0], p[0]) > 0);
- assert_se(same_fd(p[1], p[1]) > 0);
- assert_se(same_fd(a, a) > 0);
- assert_se(same_fd(b, b) > 0);
-
- assert_se(same_fd(a, p[0]) > 0);
- assert_se(same_fd(p[0], a) > 0);
- assert_se(same_fd(c, p[0]) > 0);
- assert_se(same_fd(p[0], c) > 0);
- assert_se(same_fd(a, c) > 0);
- assert_se(same_fd(c, a) > 0);
-
- assert_se(same_fd(p[0], p[1]) == 0);
- assert_se(same_fd(p[1], p[0]) == 0);
- assert_se(same_fd(p[0], b) == 0);
- assert_se(same_fd(b, p[0]) == 0);
- assert_se(same_fd(p[1], a) == 0);
- assert_se(same_fd(a, p[1]) == 0);
- assert_se(same_fd(p[1], b) == 0);
- assert_se(same_fd(b, p[1]) == 0);
-
- assert_se(same_fd(a, b) == 0);
- assert_se(same_fd(b, a) == 0);
-}
-
-static void test_uid_ptr(void) {
-
- assert_se(UID_TO_PTR(0) != NULL);
- assert_se(UID_TO_PTR(1000) != NULL);
-
- assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
- assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
-}
-
-static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
- char check[n];
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(ftruncate(fd, 0) >= 0);
- assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
-
- assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
- assert_se(ftruncate(fd, n) >= 0);
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(read(fd, check, n) == (ssize_t) n);
-
- assert_se(memcmp(buffer, check, n) == 0);
-}
-
-static void test_sparse_write(void) {
- const char test_a[] = "test";
- const char test_b[] = "\0\0\0\0test\0\0\0\0";
- const char test_c[] = "\0\0test\0\0\0\0";
- const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
- const char test_e[] = "test\0\0\0\0test";
- _cleanup_close_ int fd = -1;
- char fn[] = "/tmp/sparseXXXXXX";
-
- fd = mkostemp(fn, O_CLOEXEC);
- assert_se(fd >= 0);
- unlink(fn);
-
- test_sparse_write_one(fd, test_a, sizeof(test_a));
- test_sparse_write_one(fd, test_b, sizeof(test_b));
- test_sparse_write_one(fd, test_c, sizeof(test_c));
- test_sparse_write_one(fd, test_d, sizeof(test_d));
- test_sparse_write_one(fd, test_e, sizeof(test_e));
-}
-
-static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_escape(s, bad));
- assert_se(streq_ptr(r, expected));
-}
-
-static void test_shell_escape(void) {
- test_shell_escape_one("", "", "");
- test_shell_escape_one("\\", "", "\\\\");
- test_shell_escape_one("foobar", "", "foobar");
- test_shell_escape_one("foobar", "o", "f\\o\\obar");
- test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
-}
-
-static void test_shell_maybe_quote_one(const char *s, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_maybe_quote(s));
- assert_se(streq(r, expected));
-}
-
-static void test_shell_maybe_quote(void) {
-
- test_shell_maybe_quote_one("", "");
- test_shell_maybe_quote_one("\\", "\"\\\\\"");
- test_shell_maybe_quote_one("\"", "\"\\\"\"");
- test_shell_maybe_quote_one("foobar", "foobar");
- test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
-}
-
-static void test_tempfn(void) {
- char *ret = NULL, *p;
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-}
-
-static void test_strcmp_ptr(void) {
- assert_se(strcmp_ptr(NULL, NULL) == 0);
- assert_se(strcmp_ptr("", NULL) > 0);
- assert_se(strcmp_ptr("foo", NULL) > 0);
- assert_se(strcmp_ptr(NULL, "") < 0);
- assert_se(strcmp_ptr(NULL, "bar") < 0);
- assert_se(strcmp_ptr("foo", "bar") > 0);
- assert_se(strcmp_ptr("bar", "baz") < 0);
- assert_se(strcmp_ptr("foo", "foo") == 0);
- assert_se(strcmp_ptr("", "") == 0);
-}
-
-static void test_fgetxattrat_fake(void) {
- char t[] = "/var/tmp/xattrtestXXXXXX";
- _cleanup_close_ int fd = -1;
- const char *x;
- char v[3] = {};
- int r;
-
- assert_se(mkdtemp(t));
- x = strjoina(t, "/test");
- assert_se(touch(x) >= 0);
-
- r = setxattr(x, "user.foo", "bar", 3, 0);
- if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
- goto cleanup;
- assert_se(r >= 0);
-
- fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
-
- assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
- assert_se(memcmp(v, "bar", 3) == 0);
-
- safe_close(fd);
- fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
- assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
-
-cleanup:
- assert_se(unlink(x) >= 0);
- assert_se(rmdir(t) >= 0);
-}
-
-static void test_runlevel_to_target(void) {
- assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
- assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
- assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
-}
-
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_streq_ptr();
test_align_power2();
test_max();
test_container_of();
- test_alloca();
test_div_round_up();
- test_first_word();
- test_close_many();
- test_parse_uid();
- test_strappend();
- test_strstrip();
- test_delete_chars();
- test_in_charset();
- test_hexchar();
- test_unhexchar();
- test_base32hexchar();
- test_unbase32hexchar();
- test_base64char();
- test_unbase64char();
- test_octchar();
- test_unoctchar();
- test_decchar();
- test_undecchar();
- test_unhexmem();
- test_base32hexmem();
- test_unbase32hexmem();
- test_base64mem();
- test_unbase64mem();
- test_cescape();
- test_cunescape();
- test_foreach_word();
- test_foreach_word_quoted();
- test_memdup_multiply();
test_u64log2();
test_protect_errno();
- test_parse_cpu_set();
- test_config_parse_iec_uint64();
- test_strextend();
- test_strrep();
- test_split_pair();
- test_fstab_node_to_udev_node();
- test_get_files_in_directory();
test_in_set();
- test_writing_tmpfile();
- test_hexdump();
test_log2i();
- test_foreach_string();
- test_filename_is_valid();
- test_string_has_cc();
- test_ascii_strlower();
- test_files_same();
- test_is_valid_documentation_url();
- test_file_in_same_dir();
- test_endswith();
- test_endswith_no_case();
- test_close_nointr();
- test_unlink_noerrno();
- test_readlink_and_make_absolute();
- test_ignore_signals();
- test_strshorten();
- test_strjoina();
- test_is_symlink();
- test_search_and_fopen();
- test_search_and_fopen_nulstr();
- test_glob_exists();
test_execute_directory();
- test_parse_proc_cmdline();
test_raw_clone();
- test_same_fd();
- test_uid_ptr();
- test_sparse_write();
- test_shell_escape();
- test_shell_maybe_quote();
- test_tempfn();
- test_strcmp_ptr();
- test_fgetxattrat_fake();
- test_runlevel_to_target();
return 0;
}
diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c
new file mode 100644
index 0000000000..79a3a13af6
--- /dev/null
+++ b/src/test/test-web-util.c
@@ -0,0 +1,39 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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"
+#include "web-util.h"
+
+static void test_is_valid_documentation_url(void) {
+ assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
+ assert_se(documentation_url_is_valid("file:/foo/foo"));
+ assert_se(documentation_url_is_valid("man:systemd.special(7)"));
+ assert_se(documentation_url_is_valid("info:bar"));
+
+ assert_se(!documentation_url_is_valid("foo:"));
+ assert_se(!documentation_url_is_valid("info:"));
+ assert_se(!documentation_url_is_valid(""));
+}
+
+int main(int argc, char *argv[]) {
+ test_is_valid_documentation_url();
+
+ return 0;
+}
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
new file mode 100644
index 0000000000..267f29426c
--- /dev/null
+++ b/src/test/test-xattr-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 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 <fcntl.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "xattr-util.h"
+
+static void test_fgetxattrat_fake(void) {
+ char t[] = "/var/tmp/xattrtestXXXXXX";
+ _cleanup_close_ int fd = -1;
+ const char *x;
+ char v[3] = {};
+ int r;
+
+ assert_se(mkdtemp(t));
+ x = strjoina(t, "/test");
+ assert_se(touch(x) >= 0);
+
+ r = setxattr(x, "user.foo", "bar", 3, 0);
+ if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
+ goto cleanup;
+ assert_se(r >= 0);
+
+ fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+
+ assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
+ assert_se(memcmp(v, "bar", 3) == 0);
+
+ safe_close(fd);
+ fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+ assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
+
+cleanup:
+ assert_se(unlink(x) >= 0);
+ assert_se(rmdir(t) >= 0);
+}
+
+int main(void) {
+ test_fgetxattrat_fake();
+
+ return 0;
+}
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 097963b41b..a2270aff46 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -40,14 +40,6 @@ static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static char *arg_host = NULL;
static bool arg_adjust_system_clock = false;
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
static void polkit_agent_open_if_enabled(void) {
/* Open the polkit agent as a child process if necessary */
@@ -313,7 +305,7 @@ static int list_timezones(sd_bus *bus, char **args, unsigned n) {
if (r < 0)
return log_error_errno(r, "Failed to read list of time zones: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
strv_print(zones);
return 0;
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 2a10135fba..ffec609c69 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -78,7 +78,7 @@ static int context_read_data(Context *c) {
c->zone = t;
t = NULL;
- c->local_rtc = clock_is_localtime() > 0;
+ c->local_rtc = clock_is_localtime(NULL) > 0;
return 0;
}
@@ -125,30 +125,44 @@ static int context_write_data_local_rtc(Context *c) {
if (!w)
return -ENOMEM;
} else {
- char *p, *e;
+ char *p;
+ const char *e = "\n"; /* default if there is less than 3 lines */
+ const char *prepend = "";
size_t a, b;
- p = strchr(s, '\n');
- if (!p)
- return -EIO;
-
- p = strchr(p+1, '\n');
- if (!p)
- return -EIO;
-
- p++;
- e = strchr(p, '\n');
- if (!e)
- return -EIO;
+ p = strchrnul(s, '\n');
+ if (*p == '\0')
+ /* only one line, no \n terminator */
+ prepend = "\n0\n";
+ else if (p[1] == '\0') {
+ /* only one line, with \n terminator */
+ ++p;
+ prepend = "0\n";
+ } else {
+ p = strchr(p+1, '\n');
+ if (!p) {
+ /* only two lines, no \n terminator */
+ prepend = "\n";
+ p = s + strlen(s);
+ } else {
+ char *end;
+ /* third line might have a \n terminator or not */
+ p++;
+ end = strchr(p, '\n');
+ /* if we actually have a fourth line, use that as suffix "e", otherwise the default \n */
+ if (end)
+ e = end;
+ }
+ }
a = p - s;
b = strlen(e);
- w = new(char, a + (c->local_rtc ? 5 : 3) + b + 1);
+ w = new(char, a + (c->local_rtc ? 5 : 3) + strlen(prepend) + b + 1);
if (!w)
return -ENOMEM;
- *(char*) mempcpy(stpcpy(mempcpy(w, s, a), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
+ *(char*) mempcpy(stpcpy(stpcpy(mempcpy(w, s, a), prepend), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
if (streq(w, NULL_ADJTIME_UTC)) {
if (unlink("/etc/adjtime") < 0)
@@ -159,7 +173,7 @@ static int context_write_data_local_rtc(Context *c) {
}
}
- mac_selinux_init("/etc");
+ mac_selinux_init();
return write_string_file_atomic_label("/etc/adjtime", w);
}
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 23e19159e0..b67d672a6a 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -122,7 +122,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (clock_is_localtime() > 0) {
+ if (clock_is_localtime(NULL) > 0) {
log_info("The system is configured to read the RTC time in the local time zone. "
"This mode can not be fully supported. All system time to RTC updates are disabled.");
m->rtc_local_time = true;
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 7b105a6bd4..efd264b34d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -613,7 +613,7 @@ static int path_set_perms(Item *i, const char *path) {
* with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
* O_PATH. */
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path);
@@ -804,7 +804,7 @@ static int path_set_acls(Item *item, const char *path) {
assert(item);
assert(path);
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
@@ -917,10 +917,7 @@ static int parse_attribute_from_arg(Item *item) {
v = attributes[i].value;
- if (mode == MODE_ADD || mode == MODE_SET)
- value |= v;
- else
- value &= ~v;
+ SET_FLAG(value, v, (mode == MODE_ADD || mode == MODE_SET));
mask |= v;
}
@@ -2288,7 +2285,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- mac_selinux_init(NULL);
+ mac_selinux_init();
items = ordered_hashmap_new(&string_hash_ops);
globs = ordered_hashmap_new(&string_hash_ops);
diff --git a/src/udev/mtd_probe/mtd_probe.h b/src/udev/mtd_probe/mtd_probe.h
index caea5c2693..68e4954537 100644
--- a/src/udev/mtd_probe/mtd_probe.h
+++ b/src/udev/mtd_probe/mtd_probe.h
@@ -1,3 +1,5 @@
+#pragma once
+
/*
* Copyright (C) 2010 - Maxim Levitsky
*
@@ -17,8 +19,6 @@
* Boston, MA 02110-1301 USA
*/
-#pragma once
-
#include <mtd/mtd-user.h>
#include "macro.h"
diff --git a/src/udev/mtd_probe/probe_smartmedia.c b/src/udev/mtd_probe/probe_smartmedia.c
index 6a6c5522a7..2a7ba17637 100644
--- a/src/udev/mtd_probe/probe_smartmedia.c
+++ b/src/udev/mtd_probe/probe_smartmedia.c
@@ -73,7 +73,7 @@ void probe_smart_media(int mtd_fd, mtd_info_t* info)
for (offset = 0 ; offset < block_size * spare_count ;
offset += sector_size) {
lseek(mtd_fd, SEEK_SET, offset);
- if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE){
+ if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE) {
cis_found = 1;
break;
}
diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h
index 2e6e1d7150..7716516e76 100644
--- a/src/udev/net/ethtool-util.h
+++ b/src/udev/net/ethtool-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <macro.h>
/* we can't use DUPLEX_ prefix, as it
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 15145fc5eb..c66504102f 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -18,7 +18,6 @@
***/
#include <netinet/ether.h>
-#include <linux/netdevice.h>
#include "sd-netlink.h"
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index f525fe2116..9df5529d05 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include "libudev.h"
#include "condition.h"
diff --git a/src/udev/scsi_id/scsi.h b/src/udev/scsi_id/scsi.h
index 3bf1a94200..a27a84a40a 100644
--- a/src/udev/scsi_id/scsi.h
+++ b/src/udev/scsi_id/scsi.h
@@ -1,3 +1,5 @@
+#pragma once
+
/*
* scsi.h
*
@@ -10,8 +12,6 @@
* Free Software Foundation version 2 of the License.
*/
-#pragma once
-
#include <scsi/scsi.h>
struct scsi_ioctl_command {
diff --git a/src/udev/scsi_id/scsi_id.h b/src/udev/scsi_id/scsi_id.h
index 141b116a88..5c2e1c28ee 100644
--- a/src/udev/scsi_id/scsi_id.h
+++ b/src/udev/scsi_id/scsi_id.h
@@ -1,3 +1,5 @@
+#pragma once
+
/*
* Copyright (C) IBM Corp. 2003
*
@@ -15,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
-
#define MAX_PATH_LEN 512
/*
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 3a3d8a1770..51a55cdbc4 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -177,7 +177,7 @@ static bool test_pointers(struct udev_device *dev,
has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs);
/* unset has_mt_coordinates if devices claims to have all abs axis */
- if(has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs))
+ if (has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs))
has_mt_coordinates = false;
is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props);
has_touch = test_bit(BTN_TOUCH, bitmask_key);
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index b6ed45d8ba..6e9adc6e96 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -712,7 +712,7 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
* devices do not expose their buses and do not provide a unique
* and predictable name that way.
*/
- if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport)
+ if (streq_ptr(udev_device_get_subsystem(dev), "block") && !supported_transport)
path = mfree(path);
if (path != NULL) {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index c06ace09cf..475856db6f 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -33,9 +33,11 @@
#include "conf-files.h"
#include "escape.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "glob-util.h"
#include "path-util.h"
#include "stat-util.h"
+#include "stdio-util.h"
#include "strbuf.h"
#include "string-util.h"
#include "strv.h"
@@ -686,41 +688,31 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi
return 0;
}
-static int attr_subst_subdir(char *attr, size_t len) {
- bool found = false;
+static void attr_subst_subdir(char *attr, size_t len) {
+ const char *pos, *tail, *path;
+ _cleanup_closedir_ DIR *dir = NULL;
+ struct dirent *dent;
- if (strstr(attr, "/*/")) {
- char *pos;
- char dirname[UTIL_PATH_SIZE];
- const char *tail;
- DIR *dir;
+ pos = strstr(attr, "/*/");
+ if (!pos)
+ return;
- strscpy(dirname, sizeof(dirname), attr);
- pos = strstr(dirname, "/*/");
- if (pos == NULL)
- return -1;
- pos[0] = '\0';
- tail = &pos[2];
- dir = opendir(dirname);
- if (dir != NULL) {
- struct dirent *dent;
+ tail = pos + 2;
+ path = strndupa(attr, pos - attr + 1); /* include slash at end */
+ dir = opendir(path);
+ if (dir == NULL)
+ return;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- struct stat stats;
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir))
+ if (dent->d_name[0] != '.') {
+ char n[strlen(dent->d_name) + strlen(tail) + 1];
- if (dent->d_name[0] == '.')
- continue;
- strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL);
- if (stat(attr, &stats) == 0) {
- found = true;
- break;
- }
+ strscpyl(n, sizeof n, dent->d_name, tail, NULL);
+ if (faccessat(dirfd(dir), n, F_OK, 0) == 0) {
+ strscpyl(attr, len, path, n, NULL);
+ break;
}
- closedir(dir);
}
- }
-
- return found;
}
static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) {
@@ -831,12 +823,13 @@ static const char *get_key_attribute(struct udev *udev, char *str) {
return NULL;
}
-static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
- enum operation_type op,
- const char *value, const void *data) {
- struct token *token = &rule_tmp->token[rule_tmp->token_cur];
+static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
+ enum operation_type op,
+ const char *value, const void *data) {
+ struct token *token = rule_tmp->token + rule_tmp->token_cur;
const char *attr = NULL;
+ assert(rule_tmp->token_cur < ELEMENTSOF(rule_tmp->token));
memzero(token, sizeof(struct token));
switch (type) {
@@ -919,8 +912,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
case TK_M_MAX:
case TK_END:
case TK_UNSET:
- log_error("wrong type %u", type);
- return -1;
+ assert_not_reached("wrong type");
}
if (value != NULL && type < TK_M_MAX) {
@@ -969,11 +961,6 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
token->key.type = type;
token->key.op = op;
rule_tmp->token_cur++;
- if (rule_tmp->token_cur >= ELEMENTSOF(rule_tmp->token)) {
- log_error("temporary rule array too small");
- return -1;
- }
- return 0;
}
static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp) {
@@ -1010,8 +997,13 @@ static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp) {
return 0;
}
-static int add_rule(struct udev_rules *rules, char *line,
- const char *filename, unsigned int filename_off, unsigned int lineno) {
+#define LOG_RULE_ERROR(fmt, ...) log_error("Invalid rule %s:%u: " fmt, filename, lineno, ##__VA_ARGS__)
+#define LOG_RULE_WARNING(fmt, ...) log_warning("%s:%u: " fmt, filename, lineno, ##__VA_ARGS__)
+#define LOG_RULE_DEBUG(fmt, ...) log_debug("%s:%u: " fmt, filename, lineno, ##__VA_ARGS__)
+#define LOG_AND_RETURN(fmt, ...) { LOG_RULE_ERROR(fmt, __VA_ARGS__); return; }
+
+static void add_rule(struct udev_rules *rules, char *line,
+ const char *filename, unsigned int filename_off, unsigned int lineno) {
char *linepos;
const char *attr;
struct rule_tmp rule_tmp = {
@@ -1052,427 +1044,322 @@ static int add_rule(struct udev_rules *rules, char *line,
break;
}
+ if (rule_tmp.token_cur >= ELEMENTSOF(rule_tmp.token))
+ LOG_AND_RETURN("temporary rule array too small, aborting event processing with %u items", rule_tmp.token_cur);
+
if (streq(key, "ACTION")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid ACTION operation");
- goto invalid;
- }
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL);
- continue;
- }
- if (streq(key, "DEVPATH")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid DEVPATH operation");
- goto invalid;
- }
+ } else if (streq(key, "DEVPATH")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL);
- continue;
- }
- if (streq(key, "KERNEL")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid KERNEL operation");
- goto invalid;
- }
+ } else if (streq(key, "KERNEL")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL);
- continue;
- }
- if (streq(key, "SUBSYSTEM")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid SUBSYSTEM operation");
- goto invalid;
- }
+ } else if (streq(key, "SUBSYSTEM")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
/* bus, class, subsystem events should all be the same */
- if (streq(value, "subsystem") ||
- streq(value, "bus") ||
- streq(value, "class")) {
- if (streq(value, "bus") || streq(value, "class"))
- log_error("'%s' must be specified as 'subsystem' "
- "please fix it in %s:%u", value, filename, lineno);
+ if (STR_IN_SET(value, "subsystem", "bus", "class")) {
+ if (!streq(value, "subsystem"))
+ LOG_RULE_WARNING("'%s' must be specified as 'subsystem'; please fix", value);
+
rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
} else
rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
- continue;
- }
- if (streq(key, "DRIVER")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid DRIVER operation");
- goto invalid;
- }
+ } else if (streq(key, "DRIVER")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL);
- continue;
- }
- if (startswith(key, "ATTR{")) {
+ } else if (startswith(key, "ATTR{")) {
attr = get_key_attribute(rules->udev, key + strlen("ATTR"));
- if (attr == NULL) {
- log_error("error parsing ATTR attribute");
- goto invalid;
- }
- if (op == OP_REMOVE) {
- log_error("invalid ATTR operation");
- goto invalid;
- }
+ if (attr == NULL)
+ LOG_AND_RETURN("error parsing %s attribute", "ATTR");
+
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "ATTR");
+
if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
else
rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
- continue;
- }
- if (startswith(key, "SYSCTL{")) {
+ } else if (startswith(key, "SYSCTL{")) {
attr = get_key_attribute(rules->udev, key + strlen("SYSCTL"));
- if (attr == NULL) {
- log_error("error parsing SYSCTL attribute");
- goto invalid;
- }
- if (op == OP_REMOVE) {
- log_error("invalid SYSCTL operation");
- goto invalid;
- }
+ if (attr == NULL)
+ LOG_AND_RETURN("error parsing %s attribute", "ATTR");
+
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "ATTR");
+
if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
else
rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
- continue;
- }
- if (startswith(key, "SECLABEL{")) {
+ } else if (startswith(key, "SECLABEL{")) {
attr = get_key_attribute(rules->udev, key + strlen("SECLABEL"));
- if (!attr) {
- log_error("error parsing SECLABEL attribute");
- goto invalid;
- }
- if (op == OP_REMOVE) {
- log_error("invalid SECLABEL operation");
- goto invalid;
- }
+ if (attr == NULL)
+ LOG_AND_RETURN("error parsing %s attribute", "SECLABEL");
+
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "SECLABEL");
rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr);
- continue;
- }
- if (streq(key, "KERNELS")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid KERNELS operation");
- goto invalid;
- }
+ } else if (streq(key, "KERNELS")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL);
- continue;
- }
- if (streq(key, "SUBSYSTEMS")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid SUBSYSTEMS operation");
- goto invalid;
- }
+ } else if (streq(key, "SUBSYSTEMS")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL);
- continue;
- }
- if (streq(key, "DRIVERS")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid DRIVERS operation");
- goto invalid;
- }
+ } else if (streq(key, "DRIVERS")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL);
- continue;
- }
- if (startswith(key, "ATTRS{")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid ATTRS operation");
- goto invalid;
- }
+ } else if (startswith(key, "ATTRS{")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", "ATTRS");
+
attr = get_key_attribute(rules->udev, key + strlen("ATTRS"));
- if (attr == NULL) {
- log_error("error parsing ATTRS attribute");
- goto invalid;
- }
+ if (attr == NULL)
+ LOG_AND_RETURN("error parsing %s attribute", "ATTRS");
+
if (startswith(attr, "device/"))
- log_error("the 'device' link may not be available in a future kernel, "
- "please fix it in %s:%u", filename, lineno);
- else if (strstr(attr, "../") != NULL)
- log_error("do not reference parent sysfs directories directly, "
- "it may break with a future kernel, please fix it in %s:%u", filename, lineno);
+ LOG_RULE_WARNING("'device' link may not be available in future kernels; please fix");
+ if (strstr(attr, "../") != NULL)
+ LOG_RULE_WARNING("direct reference to parent sysfs directory, may break in future kernels; please fix");
rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr);
- continue;
- }
- if (streq(key, "TAGS")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid TAGS operation");
- goto invalid;
- }
+ } else if (streq(key, "TAGS")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL);
- continue;
- }
- if (startswith(key, "ENV{")) {
+ } else if (startswith(key, "ENV{")) {
attr = get_key_attribute(rules->udev, key + strlen("ENV"));
- if (attr == NULL) {
- log_error("error parsing ENV attribute");
- goto invalid;
- }
- if (op == OP_REMOVE) {
- log_error("invalid ENV operation");
- goto invalid;
- }
- if (op < OP_MATCH_MAX) {
- if (rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr) != 0)
- goto invalid;
- } else {
- static const char *blacklist[] = {
- "ACTION",
- "SUBSYSTEM",
- "DEVTYPE",
- "MAJOR",
- "MINOR",
- "DRIVER",
- "IFINDEX",
- "DEVNAME",
- "DEVLINKS",
- "DEVPATH",
- "TAGS",
- };
- unsigned int i;
-
- for (i = 0; i < ELEMENTSOF(blacklist); i++) {
- if (!streq(attr, blacklist[i]))
- continue;
- log_error("invalid ENV attribute, '%s' can not be set %s:%u", attr, filename, lineno);
- goto invalid;
- }
- if (rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr) != 0)
- goto invalid;
- }
- continue;
- }
+ if (attr == NULL)
+ LOG_AND_RETURN("error parsing %s attribute", "ENV");
+
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "ENV");
- if (streq(key, "TAG")) {
+ if (op < OP_MATCH_MAX)
+ rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr);
+ else {
+ if (STR_IN_SET(attr,
+ "ACTION",
+ "SUBSYSTEM",
+ "DEVTYPE",
+ "MAJOR",
+ "MINOR",
+ "DRIVER",
+ "IFINDEX",
+ "DEVNAME",
+ "DEVLINKS",
+ "DEVPATH",
+ "TAGS"))
+ LOG_AND_RETURN("invalid ENV attribute, '%s' cannot be set", attr);
+
+ rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
+ }
+
+ } else if (streq(key, "TAG")) {
if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
else
rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
- continue;
- }
- if (streq(key, "PROGRAM")) {
- if (op == OP_REMOVE) {
- log_error("invalid PROGRAM operation");
- goto invalid;
- }
+ } else if (streq(key, "PROGRAM")) {
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL);
- continue;
- }
- if (streq(key, "RESULT")) {
- if (op > OP_MATCH_MAX) {
- log_error("invalid RESULT operation");
- goto invalid;
- }
+ } else if (streq(key, "RESULT")) {
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL);
- continue;
- }
- if (startswith(key, "IMPORT")) {
+ } else if (startswith(key, "IMPORT")) {
attr = get_key_attribute(rules->udev, key + strlen("IMPORT"));
if (attr == NULL) {
- log_error("IMPORT{} type missing, ignoring IMPORT %s:%u", filename, lineno);
+ LOG_RULE_WARNING("ignoring IMPORT{} with missing type");
continue;
}
- if (op == OP_REMOVE) {
- log_error("invalid IMPORT operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "IMPORT");
+
if (streq(attr, "program")) {
/* find known built-in command */
if (value[0] != '/') {
- enum udev_builtin_cmd cmd;
+ const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- cmd = udev_builtin_lookup(value);
if (cmd < UDEV_BUILTIN_MAX) {
- log_debug("IMPORT found builtin '%s', replacing %s:%u",
- value, filename, lineno);
+ LOG_RULE_DEBUG("IMPORT found builtin '%s', replacing", value);
rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
continue;
}
}
rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
} else if (streq(attr, "builtin")) {
- enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
+ const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
- if (cmd < UDEV_BUILTIN_MAX)
- rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ if (cmd >= UDEV_BUILTIN_MAX)
+ LOG_RULE_WARNING("IMPORT{builtin} '%s' unknown", value);
else
- log_error("IMPORT{builtin}: '%s' unknown %s:%u", value, filename, lineno);
- } else if (streq(attr, "file")) {
+ rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
+ } else if (streq(attr, "file"))
rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
- } else if (streq(attr, "db")) {
+ else if (streq(attr, "db"))
rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
- } else if (streq(attr, "cmdline")) {
+ else if (streq(attr, "cmdline"))
rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
- } else if (streq(attr, "parent")) {
+ else if (streq(attr, "parent"))
rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
- } else
- log_error("IMPORT{} unknown type, ignoring IMPORT %s:%u", filename, lineno);
- continue;
- }
+ else
+ LOG_RULE_ERROR("ignoring unknown %s{} type '%s'", "IMPORT", attr);
- if (startswith(key, "TEST")) {
+ } else if (startswith(key, "TEST")) {
mode_t mode = 0;
- if (op > OP_MATCH_MAX) {
- log_error("invalid TEST operation");
- goto invalid;
- }
+ if (op > OP_MATCH_MAX)
+ LOG_AND_RETURN("invalid %s operation", "TEST");
+
attr = get_key_attribute(rules->udev, key + strlen("TEST"));
if (attr != NULL) {
mode = strtol(attr, NULL, 8);
rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
- } else {
+ } else
rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
- }
- continue;
- }
- if (startswith(key, "RUN")) {
+ } else if (startswith(key, "RUN")) {
attr = get_key_attribute(rules->udev, key + strlen("RUN"));
if (attr == NULL)
attr = "program";
- if (op == OP_REMOVE) {
- log_error("invalid RUN operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", "RUN");
if (streq(attr, "builtin")) {
- enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
+ const enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
if (cmd < UDEV_BUILTIN_MAX)
rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
else
- log_error("RUN{builtin}: '%s' unknown %s:%u", value, filename, lineno);
+ LOG_RULE_ERROR("RUN{builtin}: '%s' unknown", value);
} else if (streq(attr, "program")) {
- enum udev_builtin_cmd cmd = UDEV_BUILTIN_MAX;
+ const enum udev_builtin_cmd cmd = UDEV_BUILTIN_MAX;
rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
- } else {
- log_error("RUN{} unknown type, ignoring RUN %s:%u", filename, lineno);
- }
+ } else
+ LOG_RULE_ERROR("ignoring unknown %s{} type '%s'", "RUN", attr);
- continue;
- }
+ } else if (streq(key, "LABEL")) {
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
- if (streq(key, "LABEL")) {
- if (op == OP_REMOVE) {
- log_error("invalid LABEL operation");
- goto invalid;
- }
rule_tmp.rule.rule.label_off = rules_add_string(rules, value);
- continue;
- }
- if (streq(key, "GOTO")) {
- if (op == OP_REMOVE) {
- log_error("invalid GOTO operation");
- goto invalid;
- }
+ } else if (streq(key, "GOTO")) {
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
+
rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL);
- continue;
- }
- if (startswith(key, "NAME")) {
- if (op == OP_REMOVE) {
- log_error("invalid NAME operation");
- goto invalid;
- }
- if (op < OP_MATCH_MAX) {
+ } else if (startswith(key, "NAME")) {
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
+
+ if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
- } else {
+ else {
if (streq(value, "%k")) {
- log_error("NAME=\"%%k\" is ignored, because it breaks kernel supplied names, "
- "please remove it from %s:%u\n", filename, lineno);
+ LOG_RULE_WARNING("NAME=\"%%k\" is ignored, because it breaks kernel supplied names; please remove");
continue;
}
- if (value[0] == '\0') {
- log_debug("NAME=\"\" is ignored, because udev will not delete any device nodes, "
- "please remove it from %s:%u\n", filename, lineno);
+ if (isempty(value)) {
+ LOG_RULE_DEBUG("NAME=\"\" is ignored, because udev will not delete any device nodes; please remove");
continue;
}
rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
}
rule_tmp.rule.rule.can_set_name = true;
- continue;
- }
- if (streq(key, "SYMLINK")) {
- if (op == OP_REMOVE) {
- log_error("invalid SYMLINK operation");
- goto invalid;
- }
+ } else if (streq(key, "SYMLINK")) {
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
+
if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
else
rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
rule_tmp.rule.rule.can_set_name = true;
- continue;
- }
- if (streq(key, "OWNER")) {
+ } else if (streq(key, "OWNER")) {
uid_t uid;
char *endptr;
- if (op == OP_REMOVE) {
- log_error("invalid OWNER operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
uid = strtoul(value, &endptr, 10);
- if (endptr[0] == '\0') {
+ if (endptr[0] == '\0')
rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
- } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) {
+ else if (rules->resolve_names > 0 && strchr("$%", value[0]) == NULL) {
uid = add_uid(rules, value);
rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
} else if (rules->resolve_names >= 0)
rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
rule_tmp.rule.rule.can_set_name = true;
- continue;
- }
- if (streq(key, "GROUP")) {
+ } else if (streq(key, "GROUP")) {
gid_t gid;
char *endptr;
- if (op == OP_REMOVE) {
- log_error("invalid GROUP operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
gid = strtoul(value, &endptr, 10);
- if (endptr[0] == '\0') {
+ if (endptr[0] == '\0')
rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
- } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) {
+ else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) {
gid = add_gid(rules, value);
rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
} else if (rules->resolve_names >= 0)
rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
rule_tmp.rule.rule.can_set_name = true;
- continue;
- }
- if (streq(key, "MODE")) {
+ } else if (streq(key, "MODE")) {
mode_t mode;
char *endptr;
- if (op == OP_REMOVE) {
- log_error("invalid MODE operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
mode = strtol(value, &endptr, 8);
if (endptr[0] == '\0')
@@ -1480,27 +1367,23 @@ static int add_rule(struct udev_rules *rules, char *line,
else
rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
rule_tmp.rule.rule.can_set_name = true;
- continue;
- }
- if (streq(key, "OPTIONS")) {
+ } else if (streq(key, "OPTIONS")) {
const char *pos;
- if (op == OP_REMOVE) {
- log_error("invalid OPTIONS operation");
- goto invalid;
- }
+ if (op == OP_REMOVE)
+ LOG_AND_RETURN("invalid %s operation", key);
pos = strstr(value, "link_priority=");
if (pos != NULL) {
- int prio = atoi(&pos[strlen("link_priority=")]);
+ int prio = atoi(pos + strlen("link_priority="));
rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio);
}
pos = strstr(value, "string_escape=");
if (pos != NULL) {
- pos = &pos[strlen("string_escape=")];
+ pos += strlen("string_escape=");
if (startswith(pos, "none"))
rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
else if (startswith(pos, "replace"))
@@ -1527,30 +1410,19 @@ static int add_rule(struct udev_rules *rules, char *line,
pos = strstr(value, "static_node=");
if (pos != NULL) {
- rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, &pos[strlen("static_node=")], NULL);
+ pos += strlen("static_node=");
+ rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, pos, NULL);
rule_tmp.rule.rule.has_static_node = true;
}
- continue;
- }
-
- log_error("unknown key '%s' in %s:%u", key, filename, lineno);
- goto invalid;
+ } else
+ LOG_AND_RETURN("unknown key '%s'", key);
}
- /* add rule token */
+ /* add rule token and sort tokens */
rule_tmp.rule.rule.token_count = 1 + rule_tmp.token_cur;
- if (add_token(rules, &rule_tmp.rule) != 0)
- goto invalid;
-
- /* add tokens to list, sorted by type */
- if (sort_token(rules, &rule_tmp) != 0)
- goto invalid;
-
- return 0;
-invalid:
- log_error("invalid rule '%s:%u'", filename, lineno);
- return -1;
+ if (add_token(rules, &rule_tmp.rule) != 0 || sort_token(rules, &rule_tmp) != 0)
+ LOG_RULE_ERROR("failed to add rule token");
}
static int parse_file(struct udev_rules *rules, const char *filename) {
@@ -1849,18 +1721,18 @@ enum escape_type {
ESCAPE_REPLACE,
};
-int udev_rules_apply_to_event(struct udev_rules *rules,
- struct udev_event *event,
- usec_t timeout_usec,
- usec_t timeout_warn_usec,
- struct udev_list *properties_list) {
+void udev_rules_apply_to_event(struct udev_rules *rules,
+ struct udev_event *event,
+ usec_t timeout_usec,
+ usec_t timeout_warn_usec,
+ struct udev_list *properties_list) {
struct token *cur;
struct token *rule;
enum escape_type esc = ESCAPE_UNSET;
bool can_set_name;
if (rules->tokens == NULL)
- return -1;
+ return;
can_set_name = ((!streq(udev_device_get_action(event->dev), "remove")) &&
(major(udev_device_get_devnum(event->dev)) > 0 ||
@@ -2168,7 +2040,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
break;
}
case TK_M_IMPORT_CMDLINE: {
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
bool imported = false;
f = fopen("/proc/cmdline", "re");
@@ -2181,12 +2053,12 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
pos = strstr(cmdline, key);
if (pos != NULL) {
+ imported = true;
pos += strlen(key);
- if (pos[0] == '\0' || isspace(pos[0])) {
+ if (pos[0] == '\0' || isspace(pos[0]))
/* we import simple flags as 'FLAG=1' */
udev_device_add_property(event->dev, key, "1");
- imported = true;
- } else if (pos[0] == '=') {
+ else if (pos[0] == '=') {
const char *value;
pos++;
@@ -2195,11 +2067,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
pos++;
pos[0] = '\0';
udev_device_add_property(event->dev, key, value);
- imported = true;
}
}
}
- fclose(f);
}
if (!imported && cur->key.op != OP_NOMATCH)
goto nomatch;
@@ -2428,13 +2298,17 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
log_debug("%i character(s) replaced", count);
}
if (major(udev_device_get_devnum(event->dev)) &&
- (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) {
- log_error("NAME=\"%s\" ignored, kernel device nodes "
- "can not be renamed; please fix it in %s:%u\n", name,
- rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
+ !streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/"))) {
+ log_error("NAME=\"%s\" ignored, kernel device nodes cannot be renamed; please fix it in %s:%u\n",
+ name,
+ rules_str(rules, rule->rule.filename_off),
+ rule->rule.filename_line);
break;
}
- free_and_strdup(&event->name, name_str);
+ if (free_and_strdup(&event->name, name_str) < 0) {
+ log_oom();
+ return;
+ }
log_debug("NAME '%s' %s:%u",
event->name,
rules_str(rules, rule->rule.filename_off),
@@ -2491,7 +2365,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
const char *key_name = rules_str(rules, cur->key.attr_off);
char attr[UTIL_PATH_SIZE];
char value[UTIL_NAME_SIZE];
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0)
strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
@@ -2502,13 +2376,10 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
f = fopen(attr, "we");
- if (f != NULL) {
- if (fprintf(f, "%s", value) <= 0)
- log_error_errno(errno, "error writing ATTR{%s}: %m", attr);
- fclose(f);
- } else {
+ if (f == NULL)
log_error_errno(errno, "error opening ATTR{%s} for writing: %m", attr);
- }
+ else if (fprintf(f, "%s", value) <= 0)
+ log_error_errno(errno, "error writing ATTR{%s}: %m", attr);
break;
}
case TK_A_SYSCTL: {
@@ -2546,7 +2417,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
cur = &rules->tokens[cur->key.rule_goto];
continue;
case TK_END:
- return 0;
+ return;
case TK_M_PARENTS_MIN:
case TK_M_PARENTS_MAX:
@@ -2574,7 +2445,7 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) {
char **t;
FILE *f = NULL;
_cleanup_free_ char *path = NULL;
- int r = 0;
+ int r;
if (rules->tokens == NULL)
return 0;
@@ -2645,8 +2516,6 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) {
if (r < 0 && errno != EEXIST)
return log_error_errno(errno, "failed to create symlink %s -> %s: %m",
tag_symlink, device_node);
- else
- r = 0;
}
}
@@ -2698,12 +2567,11 @@ finish:
fflush(f);
fchmod(fileno(f), 0644);
if (ferror(f) || rename(path, "/run/udev/static_node-tags") < 0) {
- r = -errno;
- unlink("/run/udev/static_node-tags");
- unlink(path);
+ unlink_noerrno("/run/udev/static_node-tags");
+ unlink_noerrno(path);
+ return -errno;
}
- fclose(f);
}
- return r;
+ return 0;
}
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 1f9c8120c0..8433e8d9f2 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -1,3 +1,5 @@
+#pragma once
+
/*
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2003-2010 Kay Sievers <kay@vrfy.org>
@@ -16,9 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
-
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "libudev.h"
@@ -71,9 +72,9 @@ struct udev_rules;
struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names);
struct udev_rules *udev_rules_unref(struct udev_rules *rules);
bool udev_rules_check_timestamp(struct udev_rules *rules);
-int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event,
- usec_t timeout_usec, usec_t timeout_warn_usec,
- struct udev_list *properties_list);
+void udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event,
+ usec_t timeout_usec, usec_t timeout_warn_usec,
+ struct udev_list *properties_list);
int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index f9cb5e63a2..b5f7f0d512 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -100,7 +100,7 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
udev_list_init(udev, &subsystem_match_list, true);
udev_list_init(udev, &tag_match_list, true);
- while((c = getopt_long(argc, argv, "pekus:t:h", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "pekus:t:h", options, NULL)) >= 0)
switch (c) {
case 'p':
case 'e':
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index ff427cf292..702dbe5282 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -61,7 +61,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
log_debug("version %s", VERSION);
- while((c = getopt_long(argc, argv, "a:N:h", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "a:N:h", options, NULL)) >= 0)
switch (c) {
case 'a':
action = optarg;
diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h
index 37e4fe8369..dc712b0d93 100644
--- a/src/udev/udevadm-util.h
+++ b/src/udev/udevadm-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/*
* Copyright (C) 2014 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
*
@@ -15,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
-
#include "udev.h"
struct udev_device *find_device(struct udev *udev,
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 7bd2c1ea42..a6a873e5de 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- mac_selinux_init("/dev");
+ mac_selinux_init();
while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
switch (c) {
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index bb92f16352..243df7386f 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1695,7 +1695,7 @@ int main(int argc, char *argv[]) {
umask(022);
- r = mac_selinux_init("/dev");
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "could not initialize labelling: %m");
goto exit;
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c
index 931e583785..da306a4444 100644
--- a/src/update-done/update-done.c
+++ b/src/update-done/update-done.c
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c
index 8bf44e2100..9b29b5ba1d 100644
--- a/src/user-sessions/user-sessions.c
+++ b/src/user-sessions/user-sessions.c
@@ -40,7 +40,7 @@ int main(int argc, char*argv[]) {
umask(0022);
- mac_selinux_init(NULL);
+ mac_selinux_init();
if (streq(argv[1], "start")) {
int r = 0;