> …
**Linux kernel version used** (`uname -a`)
- > …
+<!-- Make sure to enclose the pasted kernel version in `backticks`, so that
+ GitHub doesn't convert the `#` character typically included in it into a
+ reference to old GitHub issues. -->
+ > `…`
**CPU architecture issue was seen on**
> …
**Steps to reproduce the problem**
> …
+
+**Additional program output to the terminal or log subsystem illustrating the issue**
+
+<!-- Please paste relevant program terminal or journal output here, ideally
+ when generated in debug mode (try setting the SYSTEMD_LOG_LEVEL=debug
+ environment variable). For very long copy/pasted data consider using a
+ service like https://gist.github.com/. Where copy/paste is not possible
+ (for example early boot or late shutdown), a photo of the screen might do
+ too, but text is always much preferred. -->
+```text
+…
+```
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
+
+**The systemd version you checked that didn't have the feature you are asking for**
+<!-- If this is not the most recently released upstream version, then please check first if it has that feature already. -->
AR="gcc-ar-$COMPILER_VERSION"
# Latest gcc stack deb packages provided by
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+ add-apt-repository -y ppa:ubuntu-toolchain-r/test
PACKAGES+=(gcc-$COMPILER_VERSION)
else
fatal "Unknown compiler: $COMPILER"
# support all the features we need (like --optimization=). Since the build-dep
# command above installs the distro versions, let's install the pip ones just
# locally and add the local bin directory to the $PATH.
-pip3 install --user -U meson ninja
+pip3 install --user -U meson==0.56.2 ninja
export PATH="$HOME/.local/bin:$PATH"
$CC --version
+meson --version
+ninja --version
for args in "${ARGS[@]}"; do
SECONDS=0
fatal "meson failed with $args"
fi
- ninja --version
- if ! ninja -C build; then
- fatal "ninja failed with $args"
+ if ! meson compile -C build; then
+ fatal "'meson compile' failed with $args"
fi
git clean -dxf
- { COMPILER: "gcc", COMPILER_VERSION: "10" }
- { COMPILER: "clang", COMPILER_VERSION: "10" }
- { COMPILER: "clang", COMPILER_VERSION: "11" }
+ - { COMPILER: "clang", COMPILER_VERSION: "12" }
env: ${{ matrix.env }}
steps:
- name: Repository checkout
uses: actions/checkout@v1
- name: Build check (${{ env.COMPILER }}-${{ env.COMPILER_VERSION }})
- run: sudo -E .github/workflows/ubuntu-build-check.sh
+ run: sudo -E .github/workflows/build_test.sh
- 'tools/oss-fuzz.sh'
push:
branches:
- - master
+ - main
jobs:
Fuzzing:
runs-on: ubuntu-latest
run: tools/get-coverity.sh
# Reuse the setup phase of the unit test script to avoid code duplication
- name: Install build dependencies
- run: sudo -E .github/workflows/ubuntu-unit-tests.sh SETUP
+ run: sudo -E .github/workflows/unit_tests.sh SETUP
# Preconfigure with meson to prevent Coverity from capturing meson metadata
- name: Preconfigure the build directory
run: meson cov-build -Dman=false
on:
push:
branches:
- - master
+ - main
pull_request:
branches:
- - master
+ - main
jobs:
ci:
- name: Install
run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect
+ # glibc 2.33-3 shipped on 2021-02-06 breaks running Arch containers on
+ # systems with older kernels (like Ubuntu Focal). Until the issue is
+ # resolved, let's pin the Arch repositories to glibc 2.32-5 to mitigate
+ # the annoying CI fails.
+ #
+ # See: https://bugs.archlinux.org/task/69563
+ - name: Pin repositories to 2021-02-05
+ run: sed -i '/^\[Distribution\]/aMirror=https://archive.archlinux.org/repos/2021/02/05/' .mkosi/mkosi.arch
+
- name: Symlink
run: ln -s .mkosi/mkosi.${{ matrix.distro }} mkosi.default
on:
pull_request:
branches:
- - master
+ - main
jobs:
build:
- name: Repository checkout
uses: actions/checkout@v1
- name: Install build dependencies
- run: sudo -E .github/workflows/ubuntu-unit-tests.sh SETUP
+ run: sudo -E .github/workflows/unit_tests.sh SETUP
- name: Build & test (${{ matrix.run_phase }})
- run: sudo -E .github/workflows/ubuntu-unit-tests.sh RUN_${{ matrix.run_phase }}
+ run: sudo -E .github/workflows/unit_tests.sh RUN_${{ matrix.run_phase }}
--- /dev/null
+---
+# vi:ts=2 sw=2 et:
+#
+# Docs: https://packit.dev/docs/
+
+specfile_path: .packit_rpm/systemd.spec
+synced_files:
+ - .packit.yaml
+ - src: .packit_rpm/systemd.spec
+ dest: systemd.spec
+upstream_package_name: systemd
+downstream_package_name: systemd
+# `git describe` returns in systemd's case 'v245-xxx' which breaks RPM version
+# detection (that expects 245-xxxx'). Let's tweak the version string accordingly
+upstream_tag_template: "v{version}"
+
+actions:
+ post-upstream-clone:
+ # Use the Fedora Rawhide specfile
+ - "git clone https://src.fedoraproject.org/rpms/systemd .packit_rpm --depth=1"
+ # Drop backported patches from the specfile, but keep the downstream-only ones
+ # - Patch0000-0499: backported patches from upstream
+ # - Patch0500-9999: downstream-only patches
+ - "sed -ri '/^Patch0[0-4][0-9]{2}+\\:.+\\.patch/d' .packit_rpm/systemd.spec"
+ # Build the RPMs with -Werror to catch possible compiler warnings. Since
+ # --werror in meson doesn't seem to work with -Db_lto=true [0], let's use
+ # -Dc_args= and -Dcpp_args= instead.
+ #
+ # Exceptions:
+ # - use -Wno-deprecated-declarations to get around mallinfo() use in
+ # basic/selinux-util.c
+ # - don't use -Werror on x86 architectures, otherwise all function checks
+ # will fail (with error: cast from pointer to integer of different size)
+ #
+ # [0] https://github.com/mesonbuild/meson/issues/7360
+ - 'sed -i "/^CONFIGURE_OPTS=(/a%ifnarch i386 i686\n-Dc_args=\"-Werror -Wno-deprecated-declarations\" -Dcpp_args=\"-Werror -Wno-deprecated-declarations\"\n%endif" .packit_rpm/systemd.spec'
+
+jobs:
+- job: copr_build
+ trigger: pull_request
+ metadata:
+ targets:
+ - fedora-rawhide-aarch64
+ - fedora-rawhide-i386
+ - fedora-rawhide-x86_64
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
all:
ninja -C build
CHANGES WITH 248:
+ * A concept of system extension images is introduced. Such images may
+ be used to extend the /usr/ and /opt/ directory hierarchies at
+ runtime with additional files (even if the file system is read-only).
+ When a system extension image is activated, its /usr/ and /opt/
+ hierarchies and os-release information are combined via overlayfs
+ with the file system hierarchy of the host OS.
+
+ A new systemd-sysext tool can be used to merge, unmerge, list, and
+ refresh system extension hierarchies. See
+ https://www.freedesktop.org/software/systemd/man/systemd-sysext.html.
+
+ The systemd-sysext.service automatically merges installed system
+ extensions during boot (before basic.target, but not in very early
+ boot, since various file systems have to be mounted first).
+
+ The SYSEXT_LEVEL= field in os-release(5) may be used to specify the
+ supported system extension level.
+
+ * A new configuration file /etc/veritytab may be used to configure
+ integrity protection for block devices. Each line is in the format
+ "volume-name data-device hash-device roothash options".
+
+ * A new kernel command-line option systemd.verity.root-options= may be
+ used to configure dm-verity behaviour for the root device.
+
+ * The key file specified in /etc/crypttab (the third field) may now
+ refer to a UNIX socket path. The key is acquired by connecting to
+ that socket and reading from it. This allows the implementation of a
+ service to provide key information dynamically, at the moment when it
+ is needed.
+
+ * Support has been added for extracting the PKCS#11 token URI and
+ encrypted key from the LUKS2 JSON embedded metadata header. This
+ allows the information how to open the encrypted device to be
+ embedded directly in the device and obviates the need for
+ configuration in an external file.
+
+ * LUKS devices may now be unlocked using TPM2 hardware.
+
+ * systemd-repart may lock partitions using TPM2 hardware. This may be
+ useful for example to create an encrypted /var partition bound to the
+ machine on first boot.
+
+ * A new systemd-cryptenroll tool has been added to enroll FIDO2+PKCS#11
+ security tokens to LUKS volumes, list and destroy them. See
+ https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html.
+
+ * The manager may be configured at compile time to use fexecve instead
+ of execve when spawning children. Using fexecve closes a window
+ between checking the security context of an executable and spawning
+ it, but unfortunately the kernel displays stale information in the
+ comm field, which impacts ps output and such.
+
+ * The configuration option -Dcompat-gateway-hostname has been dropped.
+ "_gateway" is now the only supported name.
+
+ * The ConditionSecurity=tpm2 unit file setting may be used to check
+ if the system has at least one TPM2 (tpmrm class) device.
+
+ * The tables of system calls in seccomps filters are now automatically
+ generated from kernel lists exported on
+ https://fedora.juszkiewicz.com.pl/syscalls.html.
+
+ The following architectures should now have complete lists:
+ alpha, arc, arm64, arm, i386, ia64, m68k, mips64n32, mips64, mipso32,
+ powerpc, powerpc64, s390, s390x, tilegx, sparc, x86_64, x32.
+
* The MountAPIVFS= service file setting now additionally mounts a tmpfs
- on /run/ if it is not already a mount point. A writable /run/ has always
- been a requirement for a functioning system, but this was not
+ on /run/ if it is not already a mount point. A writable /run/ has
+ always been a requirement for a functioning system, but this was not
guaranteed when using a read-only image.
- Users can always specify BindPaths= or InaccessiblePaths= as overrides,
- and they will take precedence. If the host's root mount point is used,
- there is no change in behaviour.
+
+ Users can always specify BindPaths= or InaccessiblePaths= as
+ overrides, and they will take precedence. If the host's root mount
+ point is used, there is no change in behaviour.
+
+ * New bind mounts and file system image mounts may be injected into the
+ mount namespace of a service (without restarting it). This is exposed
+ respectively as 'systemctl bind <unit> <path>…' and
+ 'systemctl mount-image <unit> <image>…'.
+
+ * The StandardOuput= and StandardError= settings can now specify files
+ to be truncated for output (as "truncate:<path>").
+
+ * The ExecPaths= and NoExecPaths= settings may be used to specify
+ noexec for parts of the file system.
+
+ * sd-bus has a new function sd_bus_open_use_machine() to open a
+ connection to the session bus of a specific user in a local container
+ or on the local host. It also gained a convenience function
+ sd_bus_reply() to call sd_bus_send() with an existing reply message.
+
+ * sd-event allows rate limits to be set on event sources. See the new
+ man page sd_event_source_set_ratelimit(3) for details.
+
+ * systemd.link files gained a [Link] Promiscuous= switch, which allows
+ the device to be raised in promiscuous mode.
+
+ New [Link] TransmitQueues= and ReceiveQueues= settings allow the
+ number of TX and RX queues to be configured.
+
+ New [Link] TransmitQueueLength= setting allows the size of the TX
+ queue to be configured.
+
+ New [Link] GenericSegmentOffloadMaxBytes= and
+ GenericSegmentOffloadMaxSegments= allow capping the packet size and
+ the number of segments accepted in Generic Segment Offload.
+
+ * systemd.network files gained a [Network] RouteTable= configuration
+ switch to select the routing policy table.
+
+ systemd.network files gained a [RoutingPolicyRule] Type=
+ configuration switch (one of "blackhole, "unreachable", "prohibit").
+
+ systemd.network files gained a [IPv6AcceptRA] RouteDenyList= and
+ RouteAllowList= settings to ignore/accept route advertisements from
+ routers matching specified prefixes. The DenyList= setting has been
+ renamed to PrefixDenyList= and a new PrefixAllowList= option has been
+ added.
+
+ systemd.network files gained a [DHCPv6] UseAddress= setting to
+ optionally ignore the address provided in the lease.
+
+ systemd.network files gained a [DHCPv6PrefixDelegation]
+ ManageTemporaryAddress= switch.
+
+ * systemd.netdev files gained a [VLAN] Protocol=, IngressQOSMaps=,
+ EgressQOSMaps=, and [MACVLAN] BroadcastMulticastQueueLength=
+ configuration options for VLAN packet handling.
+
+ * udev rules may now set log_level= option. This allows debug logs to
+ be enabled for select events, e.g. just for a specific subsystem or
+ even a single device.
+
+ * udev now exports the VOLUME_ID, LOGICAL_VOLUME_ID, VOLUME_SET_ID, and
+ DATA_PREPARED_ID attributes for block devices (when available).
+
+ * udev now exports decoded DMI information about memory under the
+ /sys/class/dmi/id/ pseudo device.
+
+ * /dev is not mounted noexec any more. This didn't provide any
+ significant security benefits and would conflicts with the executable
+ mappings used with /dev/sgx device nodes.
+
+ * Permissions for /dev/vsock are now set to 0o666, and /dev/vhost-vsock
+ and /dev/vhost-net are owned by the kvm group.
+
+ * The hardware database has been extended with a list of fingerprint
+ readers that correctly support autosuspend using data from libfprint.
+
+ * systemd-resolved can now answer DNSSEC questions through the stub
+ resolver interface in a way that allows local clients to do DNSSEC
+ validation themselves. For a question with DO+CD set, it'll proxy the
+ DNS query and respond with a mostly unmodified packet received from
+ the upstream server.
+
+ * systemd-nspawn gained a new --ambient-capability= setting
+ (AmbientCapability= in .nspawn files) to configure ambient
+ capabilities passed to the container payload.
+
+ * systemd-nspawn gained the ability to configure the firewall using the
+ nft subsystem (in addition to the existing iptables support).
+
+ * systemd-oomd now gained a new DefaultMemoryPressureDurationSec=
+ setting to configure the time a unit's cgroup needs to exceed memory
+ pressure limits before action will be taken.
+
+ systemd-oomd is now considered fully supported (the usual
+ backwards-compatiblity promises apply). Swap is not required for
+ operation, but it is still recommended.
+
+ * systemd-timesyncd gained a new ConnectionRetrySec= setting which
+ configures the retry delay when trying to contact servers.
+
+ * systemd-stdio-bridge gained --system/--user options to connect to the
+ system bus (previous default) or the user session bus.
+
+ * When the hostname is set to "localhost", systemd-hostnamed will
+ accept this. Previously such a setting would be mostly silently
+ ignored. The goal is to honour configuration as specified by the
+ user.
+
+ * systemd-hostnamed now exports the fallback hostname and the source of
+ the configured hostname ("static", "transient", or "fallback") as
+ D-Bus properties.
+
+ * systemd-hostnamed now exports the HardwareVendor and HardwareModel
+ D-Bus properties. hostnamectl shows this in the status output.
+
+ * systemd-localed may now call locale-gen to generate missing locales
+ on-demand (UTF-8-only). This improves integration with Debian-based
+ distributions (Debian/Ubuntu/PureOS/Tanglu/...) and Arch Linux.
+
+ * systemctl --check-inhibitors may now be used to obey inhibitors even
+ when invoked non-interactively.
+
+ * systemctl import-environment will now emit a warning when called
+ without any arguments (i.e. to import the full environment block of
+ the called program). This command will usually be invoked from a
+ shell, which means that it'll inherit a bunch of variables which are
+ specific to that shell, and usually to the TTY the shell is connected
+ to, and don't have any meaning in the global context of the system or
+ user service manager. Instead, only specific variables should be
+ imported into the manager environment block.
+
+ Similarly, programs which update the manager environment block by
+ directly calling the D-Bus API of the manager, should also push
+ specific variables, and not the full inherited environment.
+
+ * coredumpctl gained a --debugger-arguments= switch to pass arguments
+ to the debugger.
+
+ * networkctl now shows the link activation policy in status.
+
+ * Various tools gained --pager/--no-pager/--json switches to
+ enable/disable the pager and provide JSON output.
+
+ * Various tools now accept SYSTEMD_COLORS=16|256 to configure what
+ colours are used in output.
+
+ * less 568 or newer is now required. Link markup is now always used,
+ and older versions will not display it properly. SYSTEMD_URLIFY=0 may
+ be used to disable it.
+
+ * Builds with support for separate / and /usr hierarchies (split-usr
+ builds, non-merged-usr builds) are now officially deprecated. A
+ warning is emitted during build. Support is slated to be removed in
+ about a year (when the Debian Bookworm release development starts).
+
+ * The main development branch has been renamed to 'main'.
+
+ * mmcblk[0-9]boot[0-9] devices will no longer be probed automatically
+ for partitions, as in the vast majority of cases they contain none
+ and are used internally by the bootloader (eg: uboot).
CHANGES WITH 247:
* Support for dynamically creating users for the lifetime of a service
has been added. If DynamicUser=yes is specified, user and group IDs
- will be allocated from the range 61184..65519 for the lifetime of the
+ will be allocated from the range 61184…65519 for the lifetime of the
service. They can be resolved using the new nss-systemd.so NSS
module. The module must be enabled in /etc/nsswitch.conf. Services
started in this way have PrivateTmp= and RemoveIPC= enabled, so that
* The LimitNICE= setting now optionally takes normal UNIX nice values
in addition to the raw integer limit value. If the specified
- parameter is prefixed with "+" or "-" and is in the range -20..19 the
+ parameter is prefixed with "+" or "-" and is in the range -20…19 the
value is understood as UNIX nice value. If not prefixed like this it
is understood as raw RLIMIT_NICE limit.
individual indexes.
* The various memory-related resource limit settings (such as
- LimitAS=) now understand the usual K, M, G, ... suffixes to
+ LimitAS=) now understand the usual K, M, G, … suffixes to
the base of 1024 (IEC). Similar, the time-related resource
- limit settings understand the usual min, h, day, ...
- suffixes now.
+ limit settings understand the usual min, h, day, … suffixes
+ now.
* There's a new system.conf setting DefaultTasksMax= to
control the default TasksMax= setting for services and
* /usr/lib/os-release gained a new optional field VARIANT= for
distributions that support multiple variants (such as a
- desktop edition, a server edition, ...)
+ desktop edition, a server edition, …)
Contributions from: Aaro Koskinen, Adam Goode, Alban Crequy,
Alberto Fanjul Alonso, Alexander Sverdlin, Alex Puchades, Alin
into account when storing rfkill state on disk, as the name
might be dynamically assigned and not stable. Instead, the
ID_PATH udev variable combined with the rfkill type (wlan,
- bluetooth, ...) is used.
+ bluetooth, …) is used.
* A new service systemd-machine-id-commit.service has been
added. When used on systems where /etc is read-only during
* Calendar time specifications in .timer units now also
understand the strings "semi-annually", "quarterly" and
"minutely" as shortcuts (in addition to the preexisting
- "annually", "hourly", ...).
+ "annually", "hourly", …).
* systemd-tmpfiles will now correctly create files in /dev
at boot which are marked for creation only at boot. It is
match against MAC address, device path, driver name and type,
and will apply attributes like the naming policy, link speed,
MTU, duplex settings, Wake-on-LAN settings, MAC address, MAC
- address assignment policy (randomized, ...).
+ address assignment policy (randomized, …).
* The configuration of network interface naming rules for
"permanent interface names" has changed: a new NamePolicy=
recent boots with their times and boot IDs.
* The various tools like systemctl, loginctl, timedatectl,
- busctl, systemd-run, ... have gained a new switch "-M" to
+ busctl, systemd-run, … have gained a new switch "-M" to
connect to a specific, local OS container (as direct
connection, without requiring SSH). This works on any
container that is registered with machined, such as those
* If a privileged process logs a journal message with the
OBJECT_PID= field set, then journald will automatically
augment this with additional OBJECT_UID=, OBJECT_GID=,
- OBJECT_COMM=, OBJECT_EXE=, ... fields. This is useful if
+ OBJECT_COMM=, OBJECT_EXE=, … fields. This is useful if
system services want to log events about specific client
processes. journactl/systemctl has been updated to make use
of this information if all log messages regarding a specific
inhibitors during their runtime. A simple way to achieve
that is to invoke the DE wrapped in an invocation of:
- systemd-inhibit --what=handle-power-key:handle-sleep-key:handle-lid-switch ...
+ systemd-inhibit --what=handle-power-key:handle-sleep-key:handle-lid-switch …
* Access to unit operations is now checked via SELinux taking
the unit file label and client process label into account.
should be used to create dead device nodes as workarounds for broken
subsystems.
- * udev: RUN+="socket:..." and udev_monitor_new_from_socket() is
+ * udev: RUN+="socket:…" and udev_monitor_new_from_socket() is
no longer supported. udev_monitor_new_from_netlink() needs to be
used to subscribe to events.
CONFIG_SIGNALFD
CONFIG_TIMERFD
CONFIG_EPOLL
- CONFIG_NET
+ CONFIG_UNIX (it requires CONFIG_NET, but every other flag in it is not necessary)
CONFIG_SYSFS
CONFIG_PROC_FS
CONFIG_FHANDLE (libudev, mount and bind mount handling)
Note that the build prefix for systemd must be /usr. (Moreover,
packages systemd relies on — such as D-Bus — really should use the same
prefix, otherwise you are on your own.) -Dsplit-usr=false (which is the
- default and does not need to be specified) is the recommended setting,
- and -Dsplit-usr=true should be used on systems which have /usr on a
- separate partition.
+ default and does not need to be specified) is the recommended setting.
+ -Dsplit-usr=true can be used to give a semblance of support for systems
+ with programs installed split between / and /usr. Moving everything
+ under /usr is strongly encouraged.
Additional packages are necessary to run some tests:
- busybox (used by test/TEST-13-NSPAWN-SMOKE)
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
-[![Semaphore CI 2.0 Build Status](https://the-real-systemd.semaphoreci.com/badges/systemd/branches/master.svg?style=shields)](https://the-real-systemd.semaphoreci.com/projects/systemd)<br/>
+[![Semaphore CI 2.0 Build Status](https://the-real-systemd.semaphoreci.com/badges/systemd/branches/main.svg?style=shields)](https://the-real-systemd.semaphoreci.com/projects/systemd)<br/>
[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#systemd)<br/>
[![CIFuzz](https://github.com/systemd/systemd/workflows/CIFuzz/badge.svg)](https://github.com/systemd/systemd/actions)<br/>
[![CentOS CI - CentOS 7](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20CentOS%207&job=upstream-centos7)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos7/)<br/>
[![CentOS CI - Arch](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch&job=upstream-vagrant-archlinux)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux/)<br/>
[![CentOS CI - Arch (sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch%20(sanitizers)&job=upstream-vagrant-archlinux-sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux-sanitizers/)<br/>
-[![Fossies codespell report](https://fossies.org/linux/test/systemd-master.tar.gz/codespell.svg)](https://fossies.org/linux/test/systemd-master.tar.gz/codespell.html)</br>
+[![Fossies codespell report](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.svg)](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.html)</br>
[![Packaging status](https://repology.org/badge/tiny-repos/systemd.svg)](https://repology.org/project/systemd/versions)
## Details
Features:
+* Hook up journald's FSS logic with TPM2: seal the verification disk by
+ time-based policy, so that the verification key can remain on host and ve
+ validated via TPM.
+
+* sd-event: port to new kernel API epoll_wait2() (new in 5.11), to get more
+ accurate wait timeouts
+
* sd-boot: define a drop-in dir in the ESP that may contain X.509
certificates. If the firmware is detected to be in setup mode, automatically
enroll them as PK/KEK/db, turn off setup mode and proceed. Optionally,
#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
cflags=CFLAGS="$CFLAGS"
symbols of `libsystemd.so` and `libudev.so` with the list of man pages. Symbols
lacking documentation are highlighted.
-7. Use `meson compile -C build hwdb-update` to automatically download and import the
+7. Use `meson compile -C build update-hwdb` to automatically download and import the
PCI, USB and OUI databases into hwdb.
-8. Use `meson compile -C build man/update-man-rules` to update the meson rules for
+8. Use `meson compile -C build update-man-rules` to update the meson rules for
building man pages automatically from the docbook XML files included in
`man/`.
hibernation is available even if the swap devices do not provide enough room
for it.
-systemd-udevd:
-
-* `$NET_NAMING_SCHEME=` – if set, takes a network naming scheme (i.e. one of
- "v238", "v239", "v240"…, or the special value "latest") as parameter. If
- specified udev's net_id builtin will follow the specified naming scheme when
- determining stable network interface names. This may be used to revert to
- naming schemes of older udev versions, in order to provide more stable naming
- across updates. This environment variable takes precedence over the kernel
- command line option `net.naming-scheme=`, except if the value is prefixed
- with `:` in which case the kernel command line option takes precedence, if it
- is specified as well.
-
* `$SYSTEMD_REBOOT_TO_FIRMWARE_SETUP` — if set overrides systemd-logind's
built-in EFI logic of requesting a reboot into the firmware. Takes a
boolean. If set to false the functionality is turned off entirely. If set to
hence synthesize drop-in snippets and symlinks for all boot entries at boot
or whenever they change if it wants to integrate with systemd-logind's APIs.
+systemd-udevd:
+
+* `$NET_NAMING_SCHEME=` – if set, takes a network naming scheme (i.e. one of
+ "v238", "v239", "v240"…, or the special value "latest") as parameter. If
+ specified udev's net_id builtin will follow the specified naming scheme when
+ determining stable network interface names. This may be used to revert to
+ naming schemes of older udev versions, in order to provide more stable naming
+ across updates. This environment variable takes precedence over the kernel
+ command line option `net.naming-scheme=`, except if the value is prefixed
+ with `:` in which case the kernel command line option takes precedence, if it
+ is specified as well.
+
installed systemd tests:
* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if
specify API file systems such as `/proc/` or `/sys/` here, or hierarchies
that have them as submounts. In particular, do not specify the root directory
`/` here.
+
+systemd-tmpfiles:
+
+* `SYSTEMD_TMPFILES_FORCE_SUBVOL` - if unset, v/q/Q lines will create subvolumes only if the
+ OS itself is installed into a subvolume. If set to 1 (or another true value), these lines will always create
+ subvolumes (if the backing filesystem supports them). If set to 0, these lines will always create directories.
-How we use GVariant for serializing D-Bus messages
---------------------------------------------------
+---
+title: GVariant D-Bus Message Serialization
+category: Interfaces
+layout: default
+---
+
+# GVariant D-Bus Message Serialization
We stay close to the original dbus1 framing as possible, but make
certain changes to adapt for GVariant. dbus1 has the following
an UEFI-capable VM:
```
-# systemd-nspawn -bi image.raw
+# mkosi boot
```
or:
```
-# qemu-system-x86_64 -enable-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -hda image.raw
+# mkosi qemu
```
Every time you rerun the `mkosi` command a fresh image is built, incorporating
-all current changes you made to the project tree.
+all current changes you made to the project tree. To save time when rebuilding,
+you can use mkosi's incremental mode (`-i`). This instructs mkosi to build a set
+of cache images that make future builds a lot faster. Note that the `-i` flag
+both instructs mkosi to build cached images if they don't exist yet and to use
+cached images if they already exist so make sure to always specify `-i` if you
+want mkosi to use the cached images.
+
+If you're going to build mkosi images that use the same distribution and release
+that you're currently using, you can speed up the initial mkosi run by having it
+reuse the host's package cache. To do this, create a mkosi override file in
+mkosi.default.d/ (e.g 20-local.conf) and add the following contents:
-Alternatively, you may install the systemd version from your git check-out
-directly on top of your host system's directory tree. This mostly works fine,
-but of course you should know what you are doing as you might make your system
-unbootable in case of a bug in your changes. Also, you might step into your
-package manager's territory with this. Be careful!
+```
+[Packages]
+Cache=<full-path-to-package-manager-cache> # (e.g. /var/cache/dnf)
+```
-And never forget: most distributions provide very simple and convenient ways to
-install all development packages necessary to build systemd. For example, on
-Fedora the following command line should be sufficient to install all of
-systemd's build dependencies:
+If you want to do a local build without mkosi, most distributions also provide
+very simple and convenient ways to install all development packages necessary
+to build systemd. For example, on Fedora the following command line should be
+sufficient to install all of systemd's build dependencies:
```
# dnf builddep systemd
$ meson compile -C build # build it locally, see if everything compiles fine
$ meson test -C build # run some simple regression tests
$ ln -s .mkosi/mkosi.fedora mkosi.default # Configure mkosi to build a fedora image
-$ (umask 077; echo 123 > mkosi.rootpw) # set root password used by mkosi
$ sudo mkosi # build a test image
-$ sudo systemd-nspawn -bi image.raw # boot up the test image
+$ sudo mkosi boot # boot up the test image
$ git add -p # interactively put together your patch
$ git commit # commit it
$ git push REMOTE HEAD:refs/heads/BRANCH
- [Setting up a new project - OSS-Fuzz](https://google.github.io/oss-fuzz/getting-started/new-project-guide/)
- [Tutorials - OSS-Fuzz](https://google.github.io/oss-fuzz/reference/useful-links/#tutorials)
+
+## mkosi + clangd
+
+[clangd](https://clangd.llvm.org/) is a language server that provides code completion, diagnostics and more
+right in your editor of choice (with the right plugin installed). When using mkosi, we can run clangd in the
+mkosi build container to avoid needing to build systemd on the host machine just to make clangd work. To
+achieve this, create a script with the following contents in systemd's project directory on the host:
+
+```sh
+#!/usr/bin/env sh
+tee mkosi-clangd.build > /dev/null << EOF
+#!/usr/bin/env sh
+exec clangd \\
+ --compile-commands-dir=/root/build \\
+ --path-mappings=\\
+"\\
+$(pwd)=/root/src,\\
+$(pwd)/mkosi.builddir=/root/build,\\
+$(pwd)/mkosi.includedir=/usr/include,\\
+$(pwd)/mkosi.installdir=/root/dest\\
+" \\
+ --header-insertion=never
+EOF
+chmod +x mkosi-clangd.build
+exec sudo mkosi --source-file-transfer=mount --incremental --skip-final-phase --build-script mkosi-clangd.build build
+```
+
+Next, mark the script as executable and point your editor plugin to use this script to start clangd. For
+vscode's clangd extension, this is done via setting the `clangd.path` option to the path of the
+mkosi-clangd.sh script.
+
+To be able to navigate to include files of systemd's dependencies, we need to make the /usr/include folder of
+the build image available on the host. mkosi supports this by setting the `IncludeDirectory` option in
+mkosi's config. The easiest way to set the option is to create a file 20-local.conf in mkosi.default.d/ and
+add the following contents:
+
+```
+[Packages]
+IncludeDirectory=mkosi.includedir
+```
+
+This will make the contents of /usr/include available in mkosi.includedir in the systemd project directory.
+We already configured clangd to map any paths in /usr/include in the build image to mkosi.includedir/ on the
+host in the mkosi-clangd.sh script.
+
+We also need to make sure clangd is installed in the build image. To have mkosi install clangd in the build
+image, edit the 20-local.conf file we created earlier and add the following contents under the `[Packages]`
+section:
+
+```
+BuildPackages=<clangd-package>
+```
+
+Note that the exact package containing clangd will differ depending on the distribution used. Some
+distributions have a separate clangd package, others put the clangd binary in a clang-tools-extra package and
+some bundle clangd in the clang package.
+
+Because mkosi needs to run as root, we also need to make sure we can enter the root password when the editor
+plugin tries to run the mkosi-clangd.sh script. To be able to enter the root password in non-interactive
+scripts, we use an askpass provider. This is a program that sudo will launch if it detects it's being
+executed from a non-interactive shell so that the root password can still be entered. There are multiple
+implementations such as gnome askpass and KDE askpass. Install one of the askpass packages your distro
+provides and set the `SUDO_ASKPASS` environment variable to the path of the askpass binary you want to use.
+If configured correctly, a window will appear when your editor plugin tries to run the mkosi-clangd.sh script
+allowing you to enter the root password.
+
+Due to a bug in btrfs, it's currently impossible to mount two mkosi btrfs images at the same time. Because of
+this, trying to do a regular build while the clangd image is running will fail. To circumvent this, use ext4
+instead of btrfs for the images by adding the following contents to 20-local.conf:
+
+```
+[Output]
+Format=gpt_ext4
+```
+
+Finally, to ensure clangd starts up quickly in the editor, run an incremental build with mkosi to make sure
+the cached images are initialized (`mkosi -i`).
+
+Now, your editor will start clangd in the mkosi build image and all of clangd's features will work as
+expected.
| `/run` | File hierarchy change | yes | yes | numerous | yes | OpenSUSE, Debian, ArchLinux | no |
| [Generators](https://www.freedesktop.org/software/systemd/man/systemd.generator.html) | Subprocess | yes | yes | - | no | - | no |
| [System Updates](https://www.freedesktop.org/software/systemd/man/systemd.offline-updates.html) | System Mode | yes | yes | - | no | - | no |
-| [Presets](https://freedesktop.org/wiki/Software/systemd/Preset) | File format | yes | yes | - | no | - | no |
+| [Presets](https://www.freedesktop.org/software/systemd/man/systemd.preset.html) | File format | yes | yes | - | no | - | no |
| Udev rules | File format | yes | yes | numerous | no | no | partially |
2. Update the contributors list in NEWS (`meson compile -C build git-contrib`)
3. Update the time and place in NEWS
4. [RC1] Update version and library numbers in `meson.build`
-5. Check dbus docs with `meson compile -C build man/update-dbus-docs`
+5. Check dbus docs with `meson compile -C build update-dbus-docs`
6. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"`
7. Do `meson compile -C build`
8. Make sure that the version string and package string match: `build/systemctl --version`
✓ IPAddressDeny=
✓ ManagedOOMSwap=
✓ ManagedOOMMemoryPressure=
-✓ ManagedOOMMemoryPressureLimitPercent=
+✓ ManagedOOMMemoryPressureLimit=
+✓ ManagedOOMPreference=
```
## Process Killing Settings
ID_OUI_FROM_DATABASE=Skidata AG
OUI:00047D*
- ID_OUI_FROM_DATABASE=Pelco
+ ID_OUI_FROM_DATABASE=Motorola Solutions Inc.
OUI:00047E*
ID_OUI_FROM_DATABASE=Siqura B.V.
ID_OUI_FROM_DATABASE=Birka BPA Informationssystem AB
OUI:00080C*
- ID_OUI_FROM_DATABASE=VDA Elettronica spa
+ ID_OUI_FROM_DATABASE=VDA Group S.p.a.
OUI:00080D*
ID_OUI_FROM_DATABASE=Toshiba
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:00141D*
- ID_OUI_FROM_DATABASE=LTI-Motion GmbH
+ ID_OUI_FROM_DATABASE=KEBA Industrial Automation Germany GmbH
OUI:00141E*
ID_OUI_FROM_DATABASE=P.A. Semi, Inc.
ID_OUI_FROM_DATABASE=Fon Technology S.L.
OUI:001885*
- ID_OUI_FROM_DATABASE=Avigilon Corporation
+ ID_OUI_FROM_DATABASE=Motorola Solutions Inc.
OUI:001886*
ID_OUI_FROM_DATABASE=EL-TECH, INC.
ID_OUI_FROM_DATABASE=NV Michel Van de Wiele
OUI:001A86*
- ID_OUI_FROM_DATABASE=AdvancedIO Systems Inc
+ ID_OUI_FROM_DATABASE=New Wave Design & Verification
OUI:001A87*
ID_OUI_FROM_DATABASE=Canhold International Limited
ID_OUI_FROM_DATABASE=DBS Lodging Technologies, LLC
OUI:001F92*
- ID_OUI_FROM_DATABASE=Avigilon Corporation
+ ID_OUI_FROM_DATABASE=Motorola Solutions Inc.
OUI:001F93*
ID_OUI_FROM_DATABASE=Xiotech Corporation
ID_OUI_FROM_DATABASE=Chroma
OUI:0023BB*
- ID_OUI_FROM_DATABASE=Schmitt Industries
+ ID_OUI_FROM_DATABASE=Accretech SBS, Inc.
OUI:0023BC*
ID_OUI_FROM_DATABASE=EQ-SYS GmbH
OUI:002D76*
ID_OUI_FROM_DATABASE=TITECH GmbH
+OUI:002DB3*
+ ID_OUI_FROM_DATABASE=AMPAK Technology,Inc.
+
OUI:002EC7*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:006762*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:00682B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:0068EB*
ID_OUI_FROM_DATABASE=HP Inc.
ID_OUI_FROM_DATABASE=DACOLL LIMITED
OUI:00808C*
- ID_OUI_FROM_DATABASE=NetAlly
+ ID_OUI_FROM_DATABASE=NETSCOUT SYSTEMS INC
OUI:00808D*
ID_OUI_FROM_DATABASE=WESTCOAST TECHNOLOGY B.V.
ID_OUI_FROM_DATABASE=THE PANDA PROJECT
OUI:00A00E*
- ID_OUI_FROM_DATABASE=NetAlly
+ ID_OUI_FROM_DATABASE=NETSCOUT SYSTEMS INC
OUI:00A00F*
ID_OUI_FROM_DATABASE=Broadband Technologies
ID_OUI_FROM_DATABASE=Axxcelera Broadband Wireless
OUI:00C06A*
- ID_OUI_FROM_DATABASE=ZAHNER-ELEKTRIK GMBH & CO. KG
+ ID_OUI_FROM_DATABASE=Zahner-Elektrik Ingeborg Zahner-Schiller GmbH & Co. KG.
OUI:00C06B*
ID_OUI_FROM_DATABASE=OSI PLUS CORPORATION
OUI:00CBBD*
ID_OUI_FROM_DATABASE=Cambridge Broadband Networks Group
+OUI:00CC34*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:00CC3F*
ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
ID_OUI_FROM_DATABASE=DATAX NV
OUI:00E0DF*
- ID_OUI_FROM_DATABASE=KEYMILE GmbH
+ ID_OUI_FROM_DATABASE=DZS GmbH
OUI:00E0E0*
ID_OUI_FROM_DATABASE=SI ELECTRONICS, LTD.
OUI:00E406*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:00E421*
+ ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc.
+
OUI:00E5E4*
ID_OUI_FROM_DATABASE=Sichuan Tianyi Comheart Telecom Co., Ltd.
OUI:040EC2*
ID_OUI_FROM_DATABASE=ViewSonic Mobile China Limited
+OUI:0411190*
+ ID_OUI_FROM_DATABASE=FORT Robotics Inc.
+
+OUI:0411191*
+ ID_OUI_FROM_DATABASE=Acentury
+
+OUI:0411192*
+ ID_OUI_FROM_DATABASE=Alethea Communications Technologies Pvt. Ltd.
+
+OUI:0411193*
+ ID_OUI_FROM_DATABASE=SUZHOU RIBAO TECHNOLOGY CO.,LTD.
+
+OUI:0411194*
+ ID_OUI_FROM_DATABASE=Bolicom Innovation Technology (BeiJing) Co.,LTD.
+
+OUI:0411195*
+ ID_OUI_FROM_DATABASE=CEITA COMMUNICATION TECHNOLOGY CO.,LTD
+
+OUI:0411196*
+ ID_OUI_FROM_DATABASE=ZPD technology Co., Ltd
+
+OUI:0411197*
+ ID_OUI_FROM_DATABASE=Herrick Tech Labs
+
+OUI:0411198*
+ ID_OUI_FROM_DATABASE=Shenzhen YIZHENG Technology Co.,Ltd
+
+OUI:0411199*
+ ID_OUI_FROM_DATABASE=AC Power Distribution / ACT Entmt.
+
+OUI:041119A*
+ ID_OUI_FROM_DATABASE=CyOne Security AG
+
+OUI:041119B*
+ ID_OUI_FROM_DATABASE=Hubei Baobao Intelligent Technology Co.,LTD
+
+OUI:041119C*
+ ID_OUI_FROM_DATABASE=Haerbin Donglin Technology Co., Ltd.
+
+OUI:041119D*
+ ID_OUI_FROM_DATABASE=Nuance Hearing Ltd.
+
+OUI:041119E*
+ ID_OUI_FROM_DATABASE=JULIDA LIMITED
+
OUI:041552*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:0425C5*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0425E0*
+ ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+
OUI:042605*
ID_OUI_FROM_DATABASE=GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH
OUI:042665*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:042728*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
OUI:042758*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:045604*
ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd.
+OUI:0456E5*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:04572F*
ID_OUI_FROM_DATABASE=Sertel Electronics UK Ltd
OUI:047A0B*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd.
+OUI:047BCB*
+ ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
+
OUI:047D50*
ID_OUI_FROM_DATABASE=Shenzhen Kang Ying Technology Co.Ltd.
OUI:048D38*
ID_OUI_FROM_DATABASE=Netcore Technology Inc.
+OUI:049081*
+ ID_OUI_FROM_DATABASE=Pensando Systems, Inc.
+
OUI:049162*
ID_OUI_FROM_DATABASE=Microchip Technology Inc.
ID_OUI_FROM_DATABASE=Smobile Co., Ltd.
OUI:049F81*
- ID_OUI_FROM_DATABASE=NetAlly
+ ID_OUI_FROM_DATABASE=NETSCOUT SYSTEMS INC
OUI:049FCA*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:04B648*
ID_OUI_FROM_DATABASE=ZENNER
+OUI:04BA1C*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:04BA36*
ID_OUI_FROM_DATABASE=Li Seng Technology Ltd
OUI:04C241*
ID_OUI_FROM_DATABASE=Nokia
+OUI:04C29B*
+ ID_OUI_FROM_DATABASE=Aura Home, Inc.
+
OUI:04C3E60*
ID_OUI_FROM_DATABASE=DREAMKAS LLC
OUI:04D16EE*
ID_OUI_FROM_DATABASE=Evolute Systems Private Limited
+OUI:04D320*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:04D395*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
OUI:04D590*
ID_OUI_FROM_DATABASE=Fortinet, Inc.
+OUI:04D60E*
+ ID_OUI_FROM_DATABASE=FUNAI ELECTRIC CO., LTD.
+
OUI:04D6AA*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+OUI:04D6F4*
+ ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd.
+
OUI:04D783*
ID_OUI_FROM_DATABASE=Y&H E&C Co.,LTD.
OUI:080FFA*
ID_OUI_FROM_DATABASE=KSP INC.
+OUI:081086*
+ ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
+
OUI:08115E*
ID_OUI_FROM_DATABASE=Bitel Co., Ltd.
OUI:082CB6*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:082CED*
+ ID_OUI_FROM_DATABASE=Technity Solutions Inc.
+
+OUI:082E36*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:082E5F*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:082FE9*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:08306B*
ID_OUI_FROM_DATABASE=Palo Alto Networks
OUI:083A2F*
ID_OUI_FROM_DATABASE=Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd
+OUI:083A38*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:083A5C*
ID_OUI_FROM_DATABASE=Junilab, Inc.
OUI:084656*
ID_OUI_FROM_DATABASE=VEO-LABS
+OUI:08474C*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:0847D0*
ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd.
OUI:088039*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:0881B2*
+ ID_OUI_FROM_DATABASE=Logitech (China) Technology Co., Ltd
+
OUI:0881BC*
ID_OUI_FROM_DATABASE=HongKong Ipro Technology Co., Limited
OUI:08A12B*
ID_OUI_FROM_DATABASE=ShenZhen EZL Technology Co., Ltd
+OUI:08A189*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
+
OUI:08A5C8*
ID_OUI_FROM_DATABASE=Sunnovo International Limited
OUI:08A6BC*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+OUI:08A7C0*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:08A8A1*
ID_OUI_FROM_DATABASE=Cyclotronics Power Concepts, Inc
OUI:08AA55*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:08AA89*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:08ACA5*
ID_OUI_FROM_DATABASE=Benu Video, Inc.
OUI:08BA5F*
ID_OUI_FROM_DATABASE=Qingdao Hisense Electronics Co.,Ltd.
+OUI:08BB3C*
+ ID_OUI_FROM_DATABASE=Flextronics Tech.(Ind) Pvt Ltd
+
OUI:08BBCC*
ID_OUI_FROM_DATABASE=AK-NORD EDV VERTRIEBSGES. mbH
OUI:08F4AB*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:08F606*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:08F69C*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:0C5101*
ID_OUI_FROM_DATABASE=Apple, Inc.
-OUI:0C51D0*
- ID_OUI_FROM_DATABASE=Altice Labs S.A.
-
OUI:0C51F7*
ID_OUI_FROM_DATABASE=CHAUVIN ARNOUX
OUI:0C5A9E*
ID_OUI_FROM_DATABASE=Wi-SUN Alliance
+OUI:0C5CB50*
+ ID_OUI_FROM_DATABASE=Yamasei
+
+OUI:0C5CB51*
+ ID_OUI_FROM_DATABASE=avxav Electronic Trading LLC
+
+OUI:0C5CB52*
+ ID_OUI_FROM_DATABASE=HongKong Blossom Limited
+
+OUI:0C5CB53*
+ ID_OUI_FROM_DATABASE=iH&S Technology Limited
+
+OUI:0C5CB54*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:0C5CB55*
+ ID_OUI_FROM_DATABASE=The Raymond Corporation
+
+OUI:0C5CB56*
+ ID_OUI_FROM_DATABASE=S2C limited
+
+OUI:0C5CB57*
+ ID_OUI_FROM_DATABASE=Energybox Limited
+
+OUI:0C5CB58*
+ ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd.
+
+OUI:0C5CB59*
+ ID_OUI_FROM_DATABASE=Colordeve International
+
+OUI:0C5CB5A*
+ ID_OUI_FROM_DATABASE=Zhengzhou coal machinery hydraulic electric control Co.,Ltd
+
+OUI:0C5CB5B*
+ ID_OUI_FROM_DATABASE=ADI
+
+OUI:0C5CB5C*
+ ID_OUI_FROM_DATABASE=Hunan Newman Car NetworKing Technology Co.,Ltd
+
+OUI:0C5CB5D*
+ ID_OUI_FROM_DATABASE=BSU Inc
+
+OUI:0C5CB5E*
+ ID_OUI_FROM_DATABASE=Munters Europe AB
+
OUI:0C5CD8*
ID_OUI_FROM_DATABASE=DOLI Elektronik GmbH
OUI:0C839A*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:0C83CC*
+ ID_OUI_FROM_DATABASE=Alpha Networks Inc.
+
OUI:0C8411*
ID_OUI_FROM_DATABASE=A.O. Smith Water Products
OUI:0C8C24*
ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+OUI:0C8C69*
+ ID_OUI_FROM_DATABASE=Shenzhen elink smart Co., ltd
+
OUI:0C8C8F*
ID_OUI_FROM_DATABASE=Kamo Technology Limited
OUI:0CCEF6*
ID_OUI_FROM_DATABASE=Guizhou Fortuneship Technology Co., Ltd
+OUI:0CCF89*
+ ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+
OUI:0CCFD1*
ID_OUI_FROM_DATABASE=SPRINGWAVE Co., Ltd
OUI:0CE0E4*
ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+OUI:0CE441*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:0CE4A0*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:100F18*
ID_OUI_FROM_DATABASE=Fu Gang Electronic(KunShan)CO.,LTD
+OUI:101081*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:1010B6*
ID_OUI_FROM_DATABASE=McCain Inc
OUI:1027BE*
ID_OUI_FROM_DATABASE=TVIP
+OUI:1027F5*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:102831*
ID_OUI_FROM_DATABASE=Morion Inc.
OUI:102AB3*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:102B41*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:102C6B*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
OUI:102D31*
ID_OUI_FROM_DATABASE=Shenzhen Americas Trading Company LLC
+OUI:102D41*
+ ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd.
+
OUI:102D96*
ID_OUI_FROM_DATABASE=Looxcie Inc.
OUI:103711*
ID_OUI_FROM_DATABASE=Simlink AS
+OUI:10381F*
+ ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd.
+
OUI:103917*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:10394E*
+ ID_OUI_FROM_DATABASE=Hisense broadband multimedia technology Co.,Ltd
+
OUI:1039E9*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:103D0A*
ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+OUI:103D1C*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:103D3E*
ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
OUI:105072*
ID_OUI_FROM_DATABASE=Sercomm Corporation.
+OUI:105107*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:105172*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:1093E9*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:109497*
+ ID_OUI_FROM_DATABASE=Logitech Hong Kong
+
OUI:1094BB*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:10A4BE*
ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+OUI:10A4DA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:10A5D0*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:10C753*
ID_OUI_FROM_DATABASE=Qingdao Intelligent&Precise Electronics Co.,Ltd.
+OUI:10C9CA*
+ ID_OUI_FROM_DATABASE=Ace Technology Corp.
+
OUI:10CA81*
ID_OUI_FROM_DATABASE=PRECIA
OUI:10D542*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:10D561*
+ ID_OUI_FROM_DATABASE=Tuya Smart Inc.
+
OUI:10D7B0*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:1407E0*
ID_OUI_FROM_DATABASE=Abrantix AG
+OUI:1409B4*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:1409DC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:143AEA*
ID_OUI_FROM_DATABASE=Dynapower Company LLC
+OUI:143B42*
+ ID_OUI_FROM_DATABASE=Realfit(Shenzhen) Intelligent Technology Co., Ltd
+
OUI:143CC3*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:144FD7E*
ID_OUI_FROM_DATABASE=Edan Instruments, Inc.
+OUI:145051*
+ ID_OUI_FROM_DATABASE=SHARP Corporation
+
OUI:145120*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:14517E*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:145290*
ID_OUI_FROM_DATABASE=KNS Group LLC (YADRO Company)
OUI:145A83*
ID_OUI_FROM_DATABASE=Logi-D inc
+OUI:145AFC*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:145BD1*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:147BAC*
ID_OUI_FROM_DATABASE=Nokia
+OUI:147D05*
+ ID_OUI_FROM_DATABASE=SERCOMM PHILIPPINES INC
+
OUI:147DB3*
ID_OUI_FROM_DATABASE=JOA TELECOM.CO.,LTD
OUI:148430*
ID_OUI_FROM_DATABASE=MITAC COMPUTING TECHNOLOGY CORPORATION
+OUI:14857F*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:148692*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:14893E*
ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED
+OUI:1489CB*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:1489FD*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:14CAA0*
ID_OUI_FROM_DATABASE=Hu&Co
+OUI:14CB19*
+ ID_OUI_FROM_DATABASE=HP Inc.
+
OUI:14CC20*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:14DB85*
ID_OUI_FROM_DATABASE=S NET MEDIA
+OUI:14DD9C*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:14DDA9*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
OUI:182A44*
ID_OUI_FROM_DATABASE=HIROSE ELECTRONIC SYSTEM
+OUI:182A57*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:182A7B*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:1831BF*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:183219*
+ ID_OUI_FROM_DATABASE=EM Microelectronic
+
OUI:1832A2*
ID_OUI_FROM_DATABASE=LAON TECHNOLOGY CO., LTD.
OUI:18422F*
ID_OUI_FROM_DATABASE=Alcatel Lucent
+OUI:1842D4*
+ ID_OUI_FROM_DATABASE=Wuhan Hosan Telecommunication Technology Co.,Ltd
+
OUI:184462*
ID_OUI_FROM_DATABASE=Riava Networks, Inc.
OUI:18473D*
ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+OUI:184859*
+ ID_OUI_FROM_DATABASE=Castlenet Technology Inc.
+
OUI:1848CA*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:184C08*
ID_OUI_FROM_DATABASE=Rockwell Automation
+OUI:184CAE*
+ ID_OUI_FROM_DATABASE=CONTINENTAL
+
OUI:184E16*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:18BB26*
ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+OUI:18BB41*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:18BC5A*
ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
OUI:18BF1C*
ID_OUI_FROM_DATABASE=Jiangsu Huitong Group Co.,Ltd.
+OUI:18BFB3*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division
+
OUI:18C04D*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:18C19D*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+OUI:18C241*
+ ID_OUI_FROM_DATABASE=SonicWall
+
OUI:18C2BF*
ID_OUI_FROM_DATABASE=BUFFALO.INC
OUI:1C45C2*
ID_OUI_FROM_DATABASE=Huizhou City Sunsin lntelligent Technology Co.,Ltd
+OUI:1C472F*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:1C4840*
ID_OUI_FROM_DATABASE=IMS Messsysteme GmbH
OUI:1C6E76*
ID_OUI_FROM_DATABASE=Quarion Technology Inc
+OUI:1C6EE6*
+ ID_OUI_FROM_DATABASE=NHNETWORKS
+
OUI:1C6F65*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:1C8779E*
ID_OUI_FROM_DATABASE=ASSYSTEM France
+OUI:1C87E3*
+ ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+
OUI:1C88790*
ID_OUI_FROM_DATABASE=Newps co.,ltd
OUI:1C9179*
ID_OUI_FROM_DATABASE=Integrated System Technologies Ltd
+OUI:1C9180*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:1C919D*
ID_OUI_FROM_DATABASE=Dongguan Liesheng Electronic Co., Ltd.
+OUI:1C937C*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:1C9492*
ID_OUI_FROM_DATABASE=RUAG Schweiz AG
OUI:1C994C*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:1C9957*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:1C9C26*
ID_OUI_FROM_DATABASE=Zoovel Technologies
OUI:1CA0D3E*
ID_OUI_FROM_DATABASE=Exicom Tele-Systems Ltd.
+OUI:1CA0EF0*
+ ID_OUI_FROM_DATABASE=Tangshan Liulin Automation Equipment Co., Ltd.
+
+OUI:1CA0EF1*
+ ID_OUI_FROM_DATABASE=Wisnu and Supak Co.,Ltd.
+
+OUI:1CA0EF2*
+ ID_OUI_FROM_DATABASE=Schneider-Electric(China)Co.Ltd,Shenzhen Branch
+
+OUI:1CA0EF3*
+ ID_OUI_FROM_DATABASE=Sequent AG
+
+OUI:1CA0EF4*
+ ID_OUI_FROM_DATABASE=Leviathan Solutions Ltd.
+
+OUI:1CA0EF5*
+ ID_OUI_FROM_DATABASE=Nanjing Bilin Intelligent Identification Technology Co.,Ltd
+
+OUI:1CA0EF6*
+ ID_OUI_FROM_DATABASE=HANJEN.CHIN CO., LTD.
+
+OUI:1CA0EF7*
+ ID_OUI_FROM_DATABASE=tec5AG
+
+OUI:1CA0EF8*
+ ID_OUI_FROM_DATABASE=Zillnk
+
+OUI:1CA0EF9*
+ ID_OUI_FROM_DATABASE=Atlas Aerospace
+
+OUI:1CA0EFA*
+ ID_OUI_FROM_DATABASE=Henrich Electronics Corporation
+
+OUI:1CA0EFB*
+ ID_OUI_FROM_DATABASE=BMK professional electronics GmbH
+
+OUI:1CA0EFC*
+ ID_OUI_FROM_DATABASE=LLC Gagar.In
+
+OUI:1CA0EFD*
+ ID_OUI_FROM_DATABASE=Shenzhen Liandian Communication Technology Co.LTD
+
+OUI:1CA0EFE*
+ ID_OUI_FROM_DATABASE=RDA Microelectronics Technologies (Shanghai) Co. , Ltd
+
OUI:1CA2B1*
ID_OUI_FROM_DATABASE=ruwido austria gmbh
OUI:1CA532*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+OUI:1CA681*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:1CA770*
ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
OUI:1CCDE5*
ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd
+OUI:1CD107*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:1CD1BA*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:1CD1E0*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:1CD40C*
ID_OUI_FROM_DATABASE=Kriwan Industrie-Elektronik GmbH
OUI:1CE62B*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:1CE6AD*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:1CE6C7*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:202598*
ID_OUI_FROM_DATABASE=Teleview
+OUI:2025D2*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:202681*
ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
OUI:203AEF*
ID_OUI_FROM_DATABASE=Sivantos GmbH
+OUI:203B69*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:203CAE*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:205D47*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:205E64*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:205EF7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:20658E*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:2066CF*
+ ID_OUI_FROM_DATABASE=FREEBOX SAS
+
OUI:20677C*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
OUI:206A8A*
ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation
+OUI:206A94*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+
OUI:206AFF*
ID_OUI_FROM_DATABASE=Atlas Elektronik UK Limited
OUI:2087AC*
ID_OUI_FROM_DATABASE=AES motomation
+OUI:2087EC*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:20896F*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:20A787*
ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited
+OUI:20A7F9*
+ ID_OUI_FROM_DATABASE=SHENZHEN OLANBOA TECHNOLOGY CO., LTD
+
OUI:20A8B9*
ID_OUI_FROM_DATABASE=SIEMENS AG
OUI:20B5C6*
ID_OUI_FROM_DATABASE=Mimosa Networks
+OUI:20B730*
+ ID_OUI_FROM_DATABASE=TeconGroup, Inc
+
OUI:20B780*
ID_OUI_FROM_DATABASE=Toshiba Visual Solutions Corporation Co.,Ltd
OUI:20C6EB*
ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+OUI:20C74F*
+ ID_OUI_FROM_DATABASE=SensorPush
+
OUI:20C8B3*
ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD.
OUI:20CD6E*
ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+OUI:20CE2A1*
+ ID_OUI_FROM_DATABASE=Shanghai Digicube Info&Tech Co.,Ltd.
+
+OUI:20CE2A7*
+ ID_OUI_FROM_DATABASE=Beijing Huadianzhongxin Tech.Co.,Ltd
+
OUI:20CEC4*
ID_OUI_FROM_DATABASE=Peraso Technologies
OUI:24181D*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+OUI:2418C6*
+ ID_OUI_FROM_DATABASE=HUNAN FN-LINK TECHNOLOGY LIMITED
+
OUI:241A8C*
ID_OUI_FROM_DATABASE=Squarehead Technology AS
OUI:244427*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:24456B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:244597*
ID_OUI_FROM_DATABASE=GEMUE Gebr. Mueller Apparatebau
OUI:245CCB*
ID_OUI_FROM_DATABASE=AXIe Consortium, Inc.
+OUI:245DFC0*
+ ID_OUI_FROM_DATABASE=CompanyDeep
+
+OUI:245DFC1*
+ ID_OUI_FROM_DATABASE=ARTICONA - Bechtle Logistik & Service GmbH
+
+OUI:245DFC2*
+ ID_OUI_FROM_DATABASE=Blue Iris Labs
+
+OUI:245DFC3*
+ ID_OUI_FROM_DATABASE=Shenzhen Hailuck Electronic Technology CO.,LTD
+
+OUI:245DFC4*
+ ID_OUI_FROM_DATABASE=Suzhou Jiangzhi electronic technology co., Ltd
+
+OUI:245DFC5*
+ ID_OUI_FROM_DATABASE=ContactProximity Inc
+
+OUI:245DFC6*
+ ID_OUI_FROM_DATABASE=Guangzhou Lango Electronics Technology Co.,Ltd.
+
+OUI:245DFC7*
+ ID_OUI_FROM_DATABASE=LTY LLC
+
+OUI:245DFC8*
+ ID_OUI_FROM_DATABASE=Cosmicnode
+
+OUI:245DFC9*
+ ID_OUI_FROM_DATABASE=TORGOVYY DOM TEHNOLOGIY LLC
+
+OUI:245DFCA*
+ ID_OUI_FROM_DATABASE=Tata Sky Limited
+
+OUI:245DFCB*
+ ID_OUI_FROM_DATABASE=ONLY
+
+OUI:245DFCC*
+ ID_OUI_FROM_DATABASE=Senix Corporation
+
+OUI:245DFCD*
+ ID_OUI_FROM_DATABASE=Hunan Honestone lntelligence Technology Co.,Ltd
+
+OUI:245DFCE*
+ ID_OUI_FROM_DATABASE=Dodge
+
OUI:245EBE*
ID_OUI_FROM_DATABASE=QNAP Systems, Inc.
OUI:2497ED*
ID_OUI_FROM_DATABASE=Techvision Intelligent Technology Limited
+OUI:249AD8*
+ ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD.
+
OUI:249EAB*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:24A534*
ID_OUI_FROM_DATABASE=SynTrust Tech International Ltd.
+OUI:24A65E*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:24A7DC*
ID_OUI_FROM_DATABASE=BSkyB Ltd
OUI:24E6BA*
ID_OUI_FROM_DATABASE=JSC Zavod im. Kozitsky
+OUI:24E853*
+ ID_OUI_FROM_DATABASE=LG Innotek
+
OUI:24E927*
ID_OUI_FROM_DATABASE=TomTom International BV
OUI:2829D9*
ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd
+OUI:282B96*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:282C020*
ID_OUI_FROM_DATABASE=SAKATA DENKI Co., Ltd.
OUI:2841C6*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:2841EC*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:284430*
ID_OUI_FROM_DATABASE=GenesisTechnical Systems (UK) Ltd
OUI:2852F9*
ID_OUI_FROM_DATABASE=Zhongxin Intelligent Times (Shenzhen) Co., Ltd.
+OUI:28534E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:285471*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:285AEB*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:285B0C*
+ ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co., Ltd.
+
OUI:285F2F*
ID_OUI_FROM_DATABASE=RNware Co.,Ltd.
OUI:28AF0A*
ID_OUI_FROM_DATABASE=Sirius XM Radio Inc
+OUI:28AFFD*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:28B0CC*
ID_OUI_FROM_DATABASE=Xenya d.o.o.
OUI:28C68E*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:28C709*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:28C718*
ID_OUI_FROM_DATABASE=Altierre
OUI:28C87A*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:28C87C*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:28C914*
ID_OUI_FROM_DATABASE=Taimag Corporation
OUI:28D0CB*
ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd
+OUI:28D0EA*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:28D127*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd
OUI:28D244*
ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology Co., Ltd.
+OUI:28D3EA*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:28D436*
ID_OUI_FROM_DATABASE=Jiangsu dewosi electric co., LTD
ID_OUI_FROM_DATABASE=Shenzhen Super D Technology Co., Ltd
OUI:28EF01*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:28F033*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:28F366*
ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD
+OUI:28F49B*
+ ID_OUI_FROM_DATABASE=LEETEK
+
OUI:28F532*
ID_OUI_FROM_DATABASE=ADD-Engineering BV
OUI:2C0033*
ID_OUI_FROM_DATABASE=EControls, LLC
+OUI:2C00AB*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:2C00F7*
ID_OUI_FROM_DATABASE=XOS
OUI:2C081C*
ID_OUI_FROM_DATABASE=OVH
+OUI:2C0823*
+ ID_OUI_FROM_DATABASE=Sercomm France Sarl
+
OUI:2C088C*
ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
OUI:2C16BDE*
ID_OUI_FROM_DATABASE=Molex Incorporated
+OUI:2C17E0*
+ ID_OUI_FROM_DATABASE=SYSTEMES ET TECHNOLOGIES IDENTIFICATION (STid)
+
OUI:2C1875*
ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
OUI:2C431A*
ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+OUI:2C43BE*
+ ID_OUI_FROM_DATABASE=Sunnovo International Limited
+
OUI:2C4401*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:2C5089*
ID_OUI_FROM_DATABASE=Shenzhen Kaixuan Visual Technology Co.,Limited
+OUI:2C52AF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:2C534A*
ID_OUI_FROM_DATABASE=Shenzhen Winyao Electronic Limited
OUI:2C7155*
ID_OUI_FROM_DATABASE=HiveMotion
+OUI:2C71FF*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:2C72C3*
ID_OUI_FROM_DATABASE=Soundmatters
OUI:2C8BF2*
ID_OUI_FROM_DATABASE=Hitachi Metals America Ltd
+OUI:2C8DB1*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:2C9127*
ID_OUI_FROM_DATABASE=Eintechno Corporation
OUI:2CBE97*
ID_OUI_FROM_DATABASE=Ingenieurbuero Bickele und Buehler GmbH
+OUI:2CBEEB*
+ ID_OUI_FROM_DATABASE=Nothing Technology Limited
+
OUI:2CC260*
ID_OUI_FROM_DATABASE=Oracle Corporation
OUI:2CC5D3*
ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:2CC81B*
+ ID_OUI_FROM_DATABASE=Routerboard.com
+
OUI:2CCA0C*
ID_OUI_FROM_DATABASE=WITHUS PLANET
OUI:2CCD69*
ID_OUI_FROM_DATABASE=Aqavi.com
+OUI:2CCE1E*
+ ID_OUI_FROM_DATABASE=Cloudtronics Pty Ltd
+
OUI:2CCF58*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:2CFDAB*
ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+OUI:2CFDB3*
+ ID_OUI_FROM_DATABASE=TCL Technoly Electronics(Huizhou).,Ltd
+
OUI:2CFF65*
ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd.
OUI:3037A6*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:3037B3*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:303855*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:3078C2*
ID_OUI_FROM_DATABASE=Innowireless / QUCELL Networks
+OUI:3078D3*
+ ID_OUI_FROM_DATABASE=Virgilant Technologies Ltd.
+
OUI:307BAC*
ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
OUI:307C30*
ID_OUI_FROM_DATABASE=RIM
+OUI:307C4A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:307C5E*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:30809B*
ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+OUI:308398*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:308454*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
OUI:3085A9*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:3085EB*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:30862D*
ID_OUI_FROM_DATABASE=Arista Network, Inc.
OUI:308D99*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:308E7A*
+ ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
+
OUI:309048*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:309435*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:309587*
+ ID_OUI_FROM_DATABASE=HUNAN FN-LINK TECHNOLOGY LIMITED
+
OUI:3095E3*
ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED
OUI:30A452*
ID_OUI_FROM_DATABASE=Arrival Elements BV
+OUI:30A612*
+ ID_OUI_FROM_DATABASE=ShenZhen Hugsun Technology Co.,Ltd.
+
OUI:30A889*
ID_OUI_FROM_DATABASE=DECIMATOR DESIGN
OUI:30B164*
ID_OUI_FROM_DATABASE=Power Electronics International Inc.
+OUI:30B1B5*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:30B216*
ID_OUI_FROM_DATABASE=Hitachi ABB Power Grids – Grid Automation
OUI:30E37A*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:30E396*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:30E3D6*
ID_OUI_FROM_DATABASE=Spotify USA Inc.
OUI:30F7D7*
ID_OUI_FROM_DATABASE=Thread Technology Co., Ltd
+OUI:30F94B*
+ ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
+
OUI:30F9ED*
ID_OUI_FROM_DATABASE=Sony Corporation
OUI:34495B*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:344AC3*
+ ID_OUI_FROM_DATABASE=HuNan ZiKun Information Technology CO., Ltd
+
OUI:344B3D*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:34684A*
ID_OUI_FROM_DATABASE=Teraworks Co., Ltd.
+OUI:346893*
+ ID_OUI_FROM_DATABASE=Tecnovideo Srl
+
OUI:346895*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:347146*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:34732D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:34735A*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:347563*
ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
OUI:34862A*
ID_OUI_FROM_DATABASE=Heinz Lackmann GmbH & Co KG
+OUI:34865D*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:34873D*
ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd.
OUI:34AB37*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:34AB95*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:34ADE4*
ID_OUI_FROM_DATABASE=Shanghai Chint Power Systems Co., Ltd.
OUI:34E911*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:34E9FE*
+ ID_OUI_FROM_DATABASE=Metis Co., Ltd.
+
OUI:34EA34*
ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd
OUI:38019F*
ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+OUI:3802DE*
+ ID_OUI_FROM_DATABASE=Sercomm Corporation.
+
OUI:380546*
ID_OUI_FROM_DATABASE=Foctek Photonics, Inc.
OUI:381DD9*
ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+OUI:382028*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:382056*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:38521A*
ID_OUI_FROM_DATABASE=Nokia
+OUI:385247*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:38539C*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:388602*
ID_OUI_FROM_DATABASE=Flexoptix GmbH
+OUI:3887D5*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:38881E*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:389F83*
ID_OUI_FROM_DATABASE=OTN Systems N.V.
+OUI:38A067*
+ ID_OUI_FROM_DATABASE=Nokia Solutions and Networks GmbH & Co. KG
+
OUI:38A28C*
ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
OUI:38AFD0*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Nevro
OUI:38AFD7*
ID_OUI_FROM_DATABASE=FUJITSU LIMITED
OUI:38B1DB*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:38B3F7*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:38B4D3*
ID_OUI_FROM_DATABASE=BSH Hausgeraete GmbH
ID_OUI_FROM_DATABASE=MATRIXSTREAM TECHNOLOGIES, INC.
OUI:38B8EB7*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Sirin Mobile Technologies
OUI:38B8EB8*
ID_OUI_FROM_DATABASE=CeeNex Inc
OUI:38F33F*
ID_OUI_FROM_DATABASE=TATSUNO CORPORATION
+OUI:38F3AB*
+ ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd
+
+OUI:38F3FB*
+ ID_OUI_FROM_DATABASE=Asperiq
+
OUI:38F554*
ID_OUI_FROM_DATABASE=HISENSE ELECTRIC CO.,LTD
OUI:3C05AB*
ID_OUI_FROM_DATABASE=Product Creation Studio
+OUI:3C0630*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:3C06A7*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:3C13CC*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:3C1512*
+ ID_OUI_FROM_DATABASE=Shenzhen Huanhu Technology Co.,Ltd
+
OUI:3C15C2*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:3C7A8A*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:3C7AAA*
+ ID_OUI_FROM_DATABASE=China Dragon Technology Limited
+
+OUI:3C7AC4*
+ ID_OUI_FROM_DATABASE=Chemtronics
+
OUI:3C7C3F*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
OUI:3CA82A*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:3CA8ED*
+ ID_OUI_FROM_DATABASE=smart light technology
+
OUI:3CA9F4*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:3CC2E1*
ID_OUI_FROM_DATABASE=XINHUA CONTROL ENGINEERING CO.,LTD
+OUI:3CC786*
+ ID_OUI_FROM_DATABASE=DONGGUAN HUARONG COMMUNICATION TECHNOLOGIES CO.,LTD.
+
OUI:3CC99E*
ID_OUI_FROM_DATABASE=Huiyang Technology Co., Ltd
OUI:3CE1A1*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
+OUI:3CE36B*
+ ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
+
OUI:3CE3E7*
ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
OUI:3CFDFE*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:3CFFD8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:4000E0*
ID_OUI_FROM_DATABASE=Derek(Shaoguan)Limited
OUI:402343*
ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+OUI:4024B2*
+ ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd.
+
OUI:4025C2*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:4040A7*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
+OUI:404101*
+ ID_OUI_FROM_DATABASE=Rockwell Automation
+
OUI:404229*
ID_OUI_FROM_DATABASE=Layer3TV, Inc
+OUI:4044FD*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:4045DA*
ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd.
OUI:40BD9E*
ID_OUI_FROM_DATABASE=Physio-Control, Inc
+OUI:40BEEE*
+ ID_OUI_FROM_DATABASE=Shenzhen Yunding Information Technology Co.,Ltd
+
OUI:40BF17*
ID_OUI_FROM_DATABASE=Digistar Telecom. SA
OUI:40E3D6*
ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+OUI:40E64B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:40E730*
ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc.
OUI:446FD81*
ID_OUI_FROM_DATABASE=Shenzhen Furuilian Electronic Co.,Ltd.
+OUI:446FD82*
+ ID_OUI_FROM_DATABASE=BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş.
+
+OUI:446FD83*
+ ID_OUI_FROM_DATABASE=Shenzhen Mestechs Technology CO., LTD
+
OUI:446FD84*
ID_OUI_FROM_DATABASE=lb Lautsprecher gmbH
OUI:446FD85*
ID_OUI_FROM_DATABASE=ZHEJIANG SHIP ELECTRONICS & TECHNOLOGY CO., LTD.
+OUI:446FD86*
+ ID_OUI_FROM_DATABASE=Anhui GuDao Tech
+
OUI:446FD87*
ID_OUI_FROM_DATABASE=ITC
OUI:446FD88*
ID_OUI_FROM_DATABASE=Global Telecom Engineering, Inc
+OUI:446FD89*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:446FD8A*
+ ID_OUI_FROM_DATABASE=ZHEJIANG HIKAILINK TECHNOLOGY Co., Ltd
+
OUI:446FD8B*
ID_OUI_FROM_DATABASE=Beijing gpthink technology co.,LTD.
+OUI:446FD8C*
+ ID_OUI_FROM_DATABASE=Changzhou Haitu Electronic Technology Co.,Ltd
+
OUI:446FD8D*
ID_OUI_FROM_DATABASE=SCAIME
+OUI:446FD8E*
+ ID_OUI_FROM_DATABASE=CTE
+
+OUI:446FF8*
+ ID_OUI_FROM_DATABASE=Dyson Limited
+
OUI:44700B*
ID_OUI_FROM_DATABASE=IFFU
OUI:449B78*
ID_OUI_FROM_DATABASE=The Now Factory
+OUI:449BC1*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:449CB5*
ID_OUI_FROM_DATABASE=Alcomp, Inc
OUI:44BB3B*
ID_OUI_FROM_DATABASE=Google, Inc.
+OUI:44BDDE*
+ ID_OUI_FROM_DATABASE=BHTC GmbH
+
OUI:44BFE3*
ID_OUI_FROM_DATABASE=Shenzhen Longtech Electronics Co.,Ltd
OUI:480033*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+OUI:48007D*
+ ID_OUI_FROM_DATABASE=DTS ELEKTRONIK SAN. TIC. LTD. STI.
+
OUI:4801C5*
ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd
OUI:481249*
ID_OUI_FROM_DATABASE=Luxcom Technologies Inc.
+OUI:481258*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:48137E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:481D70*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:481F2D*
+ ID_OUI_FROM_DATABASE=Shenzhen Jie Shi Lian Industrial Co.,LTD
+
OUI:48210B*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
OUI:48282F*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:482952*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:4829E4*
+ ID_OUI_FROM_DATABASE=ZAO NPK Rotek
+
OUI:482AE3*
ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
OUI:48365F*
ID_OUI_FROM_DATABASE=Wintecronics Ltd.
+OUI:483871*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:483974*
ID_OUI_FROM_DATABASE=Proware Technologies Co., Ltd.
OUI:4851C5*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:4851CF*
+ ID_OUI_FROM_DATABASE=Intelbras
+
OUI:485261*
ID_OUI_FROM_DATABASE=SOREEL
OUI:486834*
ID_OUI_FROM_DATABASE=Silicon Motion, Inc.
+OUI:48684A*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:486B2C*
ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD.
OUI:487746*
ID_OUI_FROM_DATABASE=Calix Inc.
+OUI:48785E*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:48794D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:487D2E*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:487E48*
+ ID_OUI_FROM_DATABASE=Earda Technologies co Ltd
+
OUI:488244*
ID_OUI_FROM_DATABASE=Life Fitness / Div. of Brunswick
OUI:48881E*
ID_OUI_FROM_DATABASE=EthoSwitch LLC
+OUI:488899*
+ ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd.
+
OUI:4888CA*
ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
OUI:48B253*
ID_OUI_FROM_DATABASE=Marketaxess Corporation
+OUI:48B25D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:48B5A7*
ID_OUI_FROM_DATABASE=Glory Horse Industries Ltd.
OUI:4C57CA*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:4C5D3C*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:4C5DCD*
ID_OUI_FROM_DATABASE=Oy Finnish Electric Vehicle Technologies Ltd
OUI:4C60DE*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:4C617E*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:4C6255*
ID_OUI_FROM_DATABASE=SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V.
OUI:4C774F*
ID_OUI_FROM_DATABASE=Embedded Wireless Labs
+OUI:4C7766*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+
OUI:4C776D*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:4C7897*
ID_OUI_FROM_DATABASE=Arrowhead Alarm Products Ltd
+OUI:4C796E*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:4C79BA*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:4CB8B5*
ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+OUI:4CB910*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:4CB911*
ID_OUI_FROM_DATABASE=Raisecom Technology CO.,LTD
OUI:4CF19E*
ID_OUI_FROM_DATABASE=Groupe Atlantic
+OUI:4CF202*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:4CF2BF*
ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
OUI:5041B9*
ID_OUI_FROM_DATABASE=I-O DATA DEVICE,INC.
+OUI:504348*
+ ID_OUI_FROM_DATABASE=ThingsMatrix Inc.
+
OUI:5043B9*
ID_OUI_FROM_DATABASE=OktoInform RUS
OUI:509551*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:509707*
+ ID_OUI_FROM_DATABASE=Xiamen Paperang Technology Co.,Ltd.
+
OUI:509744*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
OUI:509772*
ID_OUI_FROM_DATABASE=Westinghouse Digital
+OUI:509839*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:509871*
ID_OUI_FROM_DATABASE=Inventum Technologies Private Limited
OUI:5098F3*
ID_OUI_FROM_DATABASE=Rheem Australia Pty Ltd
+OUI:509A46*
+ ID_OUI_FROM_DATABASE=Safetrust Inc
+
OUI:509A4C*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:50ADD5*
ID_OUI_FROM_DATABASE=Dynalec Corporation
+OUI:50AE86*
+ ID_OUI_FROM_DATABASE=Linkintec Co., Ltd
+
OUI:50AF4D*
ID_OUI_FROM_DATABASE=zte corporation
OUI:50C271*
ID_OUI_FROM_DATABASE=SECURETECH INC
+OUI:50C2ED*
+ ID_OUI_FROM_DATABASE=GN Audio A/S
+
OUI:50C3A2*
ID_OUI_FROM_DATABASE=nFore Technology Co.,Ltd.
OUI:50E14A*
ID_OUI_FROM_DATABASE=Private
+OUI:50E24E*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:50E549*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:50F43C*
ID_OUI_FROM_DATABASE=Leeo Inc
+OUI:50F4EB*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:50F520*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:540E2D*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:540E58*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:541031*
ID_OUI_FROM_DATABASE=SMARTO
OUI:541473*
ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited
+OUI:5414F3*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:5414FD*
ID_OUI_FROM_DATABASE=Orbbec 3D Technology International
OUI:5448E6*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd
+OUI:5449DF*
+ ID_OUI_FROM_DATABASE=Peloton Interactive, Inc
+
OUI:544A00*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:54724F*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:54725E*
+ ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD
+
OUI:547398*
ID_OUI_FROM_DATABASE=Toyo Electronics Corporation
OUI:54E4BD*
ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+OUI:54E61B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:54E63F*
ID_OUI_FROM_DATABASE=ShenZhen LingKeWeiEr Technology Co., Ltd.
OUI:54F6C5*
ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD
+OUI:54F6E2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:54F876*
ID_OUI_FROM_DATABASE=ABB AG
OUI:58108C*
ID_OUI_FROM_DATABASE=Intelbras
+OUI:5810B7*
+ ID_OUI_FROM_DATABASE=Infinix mobility limited
+
OUI:581243*
ID_OUI_FROM_DATABASE=AcSiP Technology Corp.
OUI:583526*
ID_OUI_FROM_DATABASE=DEEPLET TECHNOLOGY CORP
+OUI:58356B*
+ ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+
OUI:5835D9*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:584498*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:58454C*
+ ID_OUI_FROM_DATABASE=Ericsson AB
+
OUI:58468F*
ID_OUI_FROM_DATABASE=Koncar Electronics and Informatics
OUI:5855CA*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:5856C2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:5856E8*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:586B14*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:586C25*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:586D8F*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
OUI:5894A2*
ID_OUI_FROM_DATABASE=KETEK GmbH
+OUI:5894AE*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:5894B2*
ID_OUI_FROM_DATABASE=BrainCo
OUI:58AEA8*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:58AEF1*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:58B035*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:58D349*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:58D391*
+ ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd.
+
OUI:58D50A*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:58FB84*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:58FB96*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:58FC20*
+ ID_OUI_FROM_DATABASE=Altice Labs S.A.
+
OUI:58FC73*
ID_OUI_FROM_DATABASE=Arria Live Media, Inc.
ID_OUI_FROM_DATABASE=Private
OUI:58FD20*
- ID_OUI_FROM_DATABASE=Bravida Sakerhet AB
+ ID_OUI_FROM_DATABASE=Systemhouse Solutions AB
OUI:58FDB1*
ID_OUI_FROM_DATABASE=LG Electronics
OUI:5C16C7*
ID_OUI_FROM_DATABASE=Big Switch Networks
+OUI:5C1720*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:5C1737*
ID_OUI_FROM_DATABASE=I-View Now, LLC.
OUI:5C6199*
ID_OUI_FROM_DATABASE=CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.
+OUI:5C625A*
+ ID_OUI_FROM_DATABASE=CANON INC.
+
OUI:5C63BF*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:5C647A*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:5C648E*
+ ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+
OUI:5C666C*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
OUI:5CAF06*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+OUI:5CB00A*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:5CB066*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:6014B3*
ID_OUI_FROM_DATABASE=CyberTAN Technology Inc.
+OUI:6015920*
+ ID_OUI_FROM_DATABASE=S Labs sp. z o.o.
+
+OUI:6015921*
+ ID_OUI_FROM_DATABASE=RTDS Technologies Inc.
+
+OUI:6015922*
+ ID_OUI_FROM_DATABASE=EDA Technology Co.,LTD
+
+OUI:6015923*
+ ID_OUI_FROM_DATABASE=OSI TECHNOLOGY CO.,LTD.
+
+OUI:6015924*
+ ID_OUI_FROM_DATABASE=Zaptec
+
+OUI:6015926*
+ ID_OUI_FROM_DATABASE=BEIJING KUANGSHI TECHNOLOGY CO., LTD
+
+OUI:6015927*
+ ID_OUI_FROM_DATABASE=Faster CZ spol. s r.o.
+
+OUI:6015928*
+ ID_OUI_FROM_DATABASE=Yangzhou Wanfang Electronic Technology,CO .,Ltd.
+
+OUI:6015929*
+ ID_OUI_FROM_DATABASE=JIANGSU SUNFY TECHNOLOGIES HOLDING CO.,LTD.
+
+OUI:601592A*
+ ID_OUI_FROM_DATABASE=insensiv GmbH
+
+OUI:601592B*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:601592C*
+ ID_OUI_FROM_DATABASE=PSS Co., Ltd
+
+OUI:601592D*
+ ID_OUI_FROM_DATABASE=REMOWIRELESS COMMUNICATION INTERNATIONAL CO.,LIMITED
+
+OUI:601592E*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
OUI:6015C7*
ID_OUI_FROM_DATABASE=IdaTech
OUI:601888*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:601895*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:60190C*
ID_OUI_FROM_DATABASE=RRAMAC
OUI:605718*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:60577D*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:605BB4*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+OUI:605E4F*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:605F8D*
ID_OUI_FROM_DATABASE=eero inc.
OUI:60A44C*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:60A4B7*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:60A4D0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:60A730*
ID_OUI_FROM_DATABASE=Shenzhen Yipinfang Internet Technology Co.,Ltd
+OUI:60A751*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:60A8FE*
ID_OUI_FROM_DATABASE=Nokia Solutions and Networks GmbH & Co. KG
OUI:60C5AD*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:60C5E6*
+ ID_OUI_FROM_DATABASE=Skullcandy
+
OUI:60C658*
ID_OUI_FROM_DATABASE=PHYTRONIX Co.,Ltd.
OUI:6405E9*
ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd.
+OUI:6407F6*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:64094C*
ID_OUI_FROM_DATABASE=Beijing Superbee Wireless Technology Co.,Ltd
OUI:640BD7*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:640D22*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
OUI:640DCE*
ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
OUI:6416F0*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:641759*
+ ID_OUI_FROM_DATABASE=Intellivision Holdings, LLC
+
OUI:641A22*
ID_OUI_FROM_DATABASE=Heliospectra AB
OUI:642737*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:642753*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:6429ED*
ID_OUI_FROM_DATABASE=AO PKK Milandr
OUI:64628A*
ID_OUI_FROM_DATABASE=evon GmbH
+OUI:64644A*
+ ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd
+
OUI:64649B*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:646E97*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:646EE0*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:646EEA*
ID_OUI_FROM_DATABASE=Iskratel d.o.o.
OUI:6479A7*
ID_OUI_FROM_DATABASE=Phison Electronics Corp.
+OUI:6479F0*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:647BCE*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:64956C*
ID_OUI_FROM_DATABASE=LG Electronics
+OUI:649714*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:649829*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
OUI:64E003*
ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+OUI:64E0AB*
+ ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD
+
OUI:64E161*
ID_OUI_FROM_DATABASE=DEP Corp.
OUI:682C7B*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:682D83*
+ ID_OUI_FROM_DATABASE=SHENZHEN DINGHE COMMUNICATION COMPANY
+
OUI:682DDC*
ID_OUI_FROM_DATABASE=Wuhan Changjiang Electro-Communication Equipment CO.,LTD
OUI:689E19*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:689E6A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:689FF0*
ID_OUI_FROM_DATABASE=zte corporation
OUI:6C1A75*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:6C1B3F*
+ ID_OUI_FROM_DATABASE=MiraeSignal Co., Ltd
+
OUI:6C1C71*
ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
OUI:6C25B9*
ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD.
+OUI:6C2636*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:6C2779*
ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
OUI:6C33A9*
ID_OUI_FROM_DATABASE=Magicjack LP
+OUI:6C3491*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:6C3838*
ID_OUI_FROM_DATABASE=Marking System Technology Co., Ltd.
OUI:6C4598*
ID_OUI_FROM_DATABASE=Antex Electronic Corp.
+OUI:6C4760*
+ ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd
+
OUI:6C49C1*
ID_OUI_FROM_DATABASE=o2ones Co., Ltd.
OUI:6C55E8*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+OUI:6C5640*
+ ID_OUI_FROM_DATABASE=BLU Products Inc
+
OUI:6C5697*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:6CD2BA*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:6CD630*
+ ID_OUI_FROM_DATABASE=Rootous System Co.,Ltd
+
OUI:6CD68A*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
OUI:6CFDB9*
ID_OUI_FROM_DATABASE=Proware Technologies Co Ltd.
+OUI:6CFE54*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:6CFFBE*
ID_OUI_FROM_DATABASE=MPB Communications Inc.
OUI:70B3D5003*
ID_OUI_FROM_DATABASE=ANYROAM
+OUI:70B3D5004*
+ ID_OUI_FROM_DATABASE=LEIDOS
+
OUI:70B3D5005*
ID_OUI_FROM_DATABASE=CT Company
OUI:70B3D502B*
ID_OUI_FROM_DATABASE=Scorpion Precision Industry (HK)CO. Ltd.
+OUI:70B3D502C*
+ ID_OUI_FROM_DATABASE=Iylus Inc.
+
OUI:70B3D502D*
ID_OUI_FROM_DATABASE=NEXTtec srl
OUI:70B3D5035*
ID_OUI_FROM_DATABASE=HKW-Elektronik GmbH
+OUI:70B3D5036*
+ ID_OUI_FROM_DATABASE=PARAGON ID
+
OUI:70B3D5037*
ID_OUI_FROM_DATABASE=EIFFAGE ENERGIE ELECTRONIQUE
OUI:70B3D50E3*
ID_OUI_FROM_DATABASE=SinTau SrL
+OUI:70B3D50E4*
+ ID_OUI_FROM_DATABASE=Walter Müller AG
+
OUI:70B3D50E5*
ID_OUI_FROM_DATABASE=Delta Solutions LLC
OUI:70B3D50FC*
ID_OUI_FROM_DATABASE=vitalcare
+OUI:70B3D50FD*
+ ID_OUI_FROM_DATABASE=JSC Ural Factories
+
OUI:70B3D50FE*
ID_OUI_FROM_DATABASE=Vocality International Ltd
OUI:70B3D5127*
ID_OUI_FROM_DATABASE=VITEC
+OUI:70B3D5128*
+ ID_OUI_FROM_DATABASE=Akse srl
+
OUI:70B3D5129*
ID_OUI_FROM_DATABASE=OOO Microlink-Svyaz
OUI:70B3D515F*
ID_OUI_FROM_DATABASE=SAVRONİK ELEKTRONİK
+OUI:70B3D5160*
+ ID_OUI_FROM_DATABASE=European Synchrotron Radiation Facility
+
OUI:70B3D5161*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D516C*
ID_OUI_FROM_DATABASE=OCEAN
+OUI:70B3D516D*
+ ID_OUI_FROM_DATABASE=BluB0X Security, Inc.
+
OUI:70B3D516E*
ID_OUI_FROM_DATABASE=Jemac Sweden AB
OUI:70B3D5195*
ID_OUI_FROM_DATABASE=Ci4Rail
+OUI:70B3D5196*
+ ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+
OUI:70B3D5197*
ID_OUI_FROM_DATABASE=Lattech Systems Pty Ltd
OUI:70B3D519C*
ID_OUI_FROM_DATABASE=Kubu, Inc.
+OUI:70B3D519D*
+ ID_OUI_FROM_DATABASE=Automata GmbH & Co. KG
+
OUI:70B3D519E*
ID_OUI_FROM_DATABASE=J-Factor Embedded Technologies
OUI:70B3D51AD*
ID_OUI_FROM_DATABASE=Techworld Industries Ltd
+OUI:70B3D51AE*
+ ID_OUI_FROM_DATABASE=EcoG
+
OUI:70B3D51AF*
ID_OUI_FROM_DATABASE=Teenage Engineering AB
+OUI:70B3D51B0*
+ ID_OUI_FROM_DATABASE=NAL Research Corporation
+
OUI:70B3D51B1*
ID_OUI_FROM_DATABASE=Shanghai Danyan Information Technology Co., Ltd.
OUI:70B3D5211*
ID_OUI_FROM_DATABASE=Fracarro srl
+OUI:70B3D5212*
+ ID_OUI_FROM_DATABASE=Semiconsoft, inc
+
OUI:70B3D5213*
ID_OUI_FROM_DATABASE=ETON Deutschland Electro Acoustic GmbH
OUI:70B3D5264*
ID_OUI_FROM_DATABASE=ifak technology + service GmbH
+OUI:70B3D5265*
+ ID_OUI_FROM_DATABASE=Rapiot
+
OUI:70B3D5266*
ID_OUI_FROM_DATABASE=Spectra Displays Ltd
OUI:70B3D52C4*
ID_OUI_FROM_DATABASE=Hodwa Co., Ltd
+OUI:70B3D52C5*
+ ID_OUI_FROM_DATABASE=MECT SRL
+
OUI:70B3D52C7*
ID_OUI_FROM_DATABASE=Worldsensing
OUI:70B3D52E3*
ID_OUI_FROM_DATABASE=Meiknologic GmbH
+OUI:70B3D52E4*
+ ID_OUI_FROM_DATABASE=Schneider Electric Motion USA
+
OUI:70B3D52E5*
ID_OUI_FROM_DATABASE=Fläkt Woods AB
OUI:70B3D5311*
ID_OUI_FROM_DATABASE=Günther Spelsberg GmbH + Co. KG
+OUI:70B3D5312*
+ ID_OUI_FROM_DATABASE=SMITEC S.p.A.
+
OUI:70B3D5313*
ID_OUI_FROM_DATABASE=DIEHL Controls
+OUI:70B3D5314*
+ ID_OUI_FROM_DATABASE=Grau Elektronik GmbH
+
OUI:70B3D5316*
ID_OUI_FROM_DATABASE=Austco Marketing & Service (USA) ltd.
OUI:70B3D5372*
ID_OUI_FROM_DATABASE=MATELEX
+OUI:70B3D5373*
+ ID_OUI_FROM_DATABASE=Hangzhou Weimu Technology Co.,Ltd.
+
OUI:70B3D5374*
ID_OUI_FROM_DATABASE=OOO NPP Mars-Energo
OUI:70B3D538F*
ID_OUI_FROM_DATABASE=Sorynorydotcom Inc
+OUI:70B3D5390*
+ ID_OUI_FROM_DATABASE=TEX COMPUTER SRL
+
OUI:70B3D5391*
ID_OUI_FROM_DATABASE=Changshu Ruite Electric Co.,Ltd.
OUI:70B3D53B2*
ID_OUI_FROM_DATABASE=Sicon srl
+OUI:70B3D53B3*
+ ID_OUI_FROM_DATABASE=Movicom Electric LLC
+
OUI:70B3D53B4*
ID_OUI_FROM_DATABASE=YOUSUNG
OUI:70B3D53DB*
ID_OUI_FROM_DATABASE=KST technology
+OUI:70B3D53DC*
+ ID_OUI_FROM_DATABASE=XIA LLC
+
OUI:70B3D53DD*
ID_OUI_FROM_DATABASE=Kniggendorf + Kögler Security GmbH
OUI:70B3D544B*
ID_OUI_FROM_DATABASE=Open System Solutions Limited
+OUI:70B3D544C*
+ ID_OUI_FROM_DATABASE=ejoin, s.r.o.
+
OUI:70B3D544D*
ID_OUI_FROM_DATABASE=Vessel Technology Ltd
OUI:70B3D544F*
ID_OUI_FROM_DATABASE=Velvac Incorporated
+OUI:70B3D5452*
+ ID_OUI_FROM_DATABASE=ITALIANA PONTI RADIO SRL
+
OUI:70B3D5453*
ID_OUI_FROM_DATABASE=Foerster-Technik GmbH
OUI:70B3D546C*
ID_OUI_FROM_DATABASE=SHANGHAI CHENZHU INSTRUMENT CO., LTD.
+OUI:70B3D546D*
+ ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
+
OUI:70B3D546E*
ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd.
ID_OUI_FROM_DATABASE=KeyProd
OUI:70B3D5474*
- ID_OUI_FROM_DATABASE=DAYOUPLUS
+ ID_OUI_FROM_DATABASE=CTROGERS LLC
OUI:70B3D5475*
ID_OUI_FROM_DATABASE=EWATTCH
OUI:70B3D54D8*
ID_OUI_FROM_DATABASE=Versilis Inc.
+OUI:70B3D54D9*
+ ID_OUI_FROM_DATABASE=Coda Octopus Products Limited
+
OUI:70B3D54DA*
ID_OUI_FROM_DATABASE=Private
OUI:70B3D54FA*
ID_OUI_FROM_DATABASE=Thruvision Limited
+OUI:70B3D54FB*
+ ID_OUI_FROM_DATABASE=MAS Elettronica sas di Mascetti Sandro e C.
+
OUI:70B3D54FC*
ID_OUI_FROM_DATABASE=Mettler Toledo
OUI:70B3D550A*
ID_OUI_FROM_DATABASE=AMEDTEC Medizintechnik Aue GmbH
+OUI:70B3D550B*
+ ID_OUI_FROM_DATABASE=Nordson Corporation
+
OUI:70B3D550C*
ID_OUI_FROM_DATABASE=Hangzhou landesker digital technology co. LTD
OUI:70B3D551F*
ID_OUI_FROM_DATABASE=VALEO CDA
+OUI:70B3D5520*
+ ID_OUI_FROM_DATABASE=promedias AG
+
OUI:70B3D5521*
ID_OUI_FROM_DATABASE=Selex ES Inc.
OUI:70B3D5580*
ID_OUI_FROM_DATABASE=Private
+OUI:70B3D5581*
+ ID_OUI_FROM_DATABASE=Thermokon Sensortechnik GmbH
+
OUI:70B3D5582*
ID_OUI_FROM_DATABASE=VAGLER International Sdn Bhd
OUI:70B3D5585*
ID_OUI_FROM_DATABASE=Nefteavtomatika
+OUI:70B3D5586*
+ ID_OUI_FROM_DATABASE=Aliter Technologies
+
OUI:70B3D5587*
ID_OUI_FROM_DATABASE=INCAA Computers
OUI:70B3D559E*
ID_OUI_FROM_DATABASE=i2-electronics
+OUI:70B3D559F*
+ ID_OUI_FROM_DATABASE=Megger Germany GmbH
+
OUI:70B3D55A0*
ID_OUI_FROM_DATABASE=Ascon Tecnologic S.r.l.
OUI:70B3D55B6*
ID_OUI_FROM_DATABASE=Ethical Lighting and Sensor Solutions Limited
+OUI:70B3D55B7*
+ ID_OUI_FROM_DATABASE=on-systems limited
+
OUI:70B3D55B8*
ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH
+OUI:70B3D55B9*
+ ID_OUI_FROM_DATABASE=EIZO RUGGED SOLUTIONS
+
OUI:70B3D55BA*
ID_OUI_FROM_DATABASE=INFRASAFE/ ADVANTOR SYSTEMS
OUI:70B3D55C1*
ID_OUI_FROM_DATABASE=Shanghai JaWay Information Technology Co., Ltd.
+OUI:70B3D55C2*
+ ID_OUI_FROM_DATABASE=Sono-Tek Corporation
+
+OUI:70B3D55C3*
+ ID_OUI_FROM_DATABASE=DIC Corporation
+
OUI:70B3D55C4*
ID_OUI_FROM_DATABASE=TATTILE SRL
OUI:70B3D5603*
ID_OUI_FROM_DATABASE=EGISTECH CO.,LTD.
+OUI:70B3D5604*
+ ID_OUI_FROM_DATABASE=Foxtrot Research Corp
+
OUI:70B3D5605*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
OUI:70B3D563C*
ID_OUI_FROM_DATABASE=Pivothead
+OUI:70B3D563D*
+ ID_OUI_FROM_DATABASE=Topic Embedded Products B.V.
+
OUI:70B3D563E*
ID_OUI_FROM_DATABASE=RIKEN OPTECH CORPORATION
OUI:70B3D566D*
ID_OUI_FROM_DATABASE=Sanmina Israel
+OUI:70B3D566E*
+ ID_OUI_FROM_DATABASE=SIAME
+
OUI:70B3D566F*
ID_OUI_FROM_DATABASE=Simplified MFG
OUI:70B3D5680*
ID_OUI_FROM_DATABASE=BASF Corporation
+OUI:70B3D5681*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
OUI:70B3D5682*
ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited
OUI:70B3D568F*
ID_OUI_FROM_DATABASE=PEEK TRAFFIC
+OUI:70B3D5690*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
OUI:70B3D5691*
ID_OUI_FROM_DATABASE=PEEK TRAFFIC
ID_OUI_FROM_DATABASE=Altaneos
OUI:70B3D569B*
- ID_OUI_FROM_DATABASE=TAIYO SEIKI CO.,LTD.
+ ID_OUI_FROM_DATABASE=Horizon Co., Ltd
OUI:70B3D569C*
ID_OUI_FROM_DATABASE=Keepen
OUI:70B3D56B3*
ID_OUI_FROM_DATABASE=DuraComm Corporation
+OUI:70B3D56B4*
+ ID_OUI_FROM_DATABASE=Nudron IoT Solutions LLP
+
OUI:70B3D56B5*
ID_OUI_FROM_DATABASE=ART SPA
OUI:70B3D56BF*
ID_OUI_FROM_DATABASE=Otto Bihler Maschinenfabrik GmbH & Co. KG
+OUI:70B3D56C0*
+ ID_OUI_FROM_DATABASE=LLC NTZ Mekhanotronika
+
OUI:70B3D56C1*
ID_OUI_FROM_DATABASE=Labtronik s.r.l.
OUI:70B3D56D3*
ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+OUI:70B3D56D4*
+ ID_OUI_FROM_DATABASE=Telerob Gesellschaft für Fernhantierungs
+
+OUI:70B3D56D5*
+ ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+
OUI:70B3D56D6*
ID_OUI_FROM_DATABASE=KMtronic ltd
OUI:70B3D570C*
ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+OUI:70B3D570D*
+ ID_OUI_FROM_DATABASE=OMNISENSING PHOTONICS LLC
+
OUI:70B3D570E*
ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd
OUI:70B3D5712*
ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC
+OUI:70B3D5713*
+ ID_OUI_FROM_DATABASE=Coloet S.r.l.
+
OUI:70B3D5714*
ID_OUI_FROM_DATABASE=Alturna Networks
OUI:70B3D5719*
ID_OUI_FROM_DATABASE=2M Technology
+OUI:70B3D571A*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
OUI:70B3D571B*
ID_OUI_FROM_DATABASE=elsys
ID_OUI_FROM_DATABASE=Motec Pty Ltd
OUI:70B3D5720*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Jeio Tech
OUI:70B3D5721*
ID_OUI_FROM_DATABASE=Zoe Medical
OUI:70B3D5724*
ID_OUI_FROM_DATABASE=Quan International Co., Ltd.
+OUI:70B3D5725*
+ ID_OUI_FROM_DATABASE=Swiss Timing LTD
+
OUI:70B3D5726*
ID_OUI_FROM_DATABASE=ATGS
OUI:70B3D572A*
ID_OUI_FROM_DATABASE=MRC Systems GmbH
+OUI:70B3D572B*
+ ID_OUI_FROM_DATABASE=Medipense Inc.
+
OUI:70B3D572C*
ID_OUI_FROM_DATABASE=NuRi&G Engineering co,.Ltd.
OUI:70B3D5745*
ID_OUI_FROM_DATABASE=TMSI LLC
+OUI:70B3D5746*
+ ID_OUI_FROM_DATABASE=Smart Systems LLC
+
OUI:70B3D5747*
ID_OUI_FROM_DATABASE=Eva Automation
OUI:70B3D5797*
ID_OUI_FROM_DATABASE=Mitsubishi Electric India Pvt. Ltd.
+OUI:70B3D5798*
+ ID_OUI_FROM_DATABASE=TIAMA
+
OUI:70B3D5799*
ID_OUI_FROM_DATABASE=Vitec System Engineering Inc.
OUI:70B3D57CB*
ID_OUI_FROM_DATABASE=KeyW Corporation
+OUI:70B3D57CC*
+ ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD.
+
OUI:70B3D57CD*
ID_OUI_FROM_DATABASE=Molekuler Goruntuleme A.S.
OUI:70B3D57F5*
ID_OUI_FROM_DATABASE=Incusense
+OUI:70B3D57F6*
+ ID_OUI_FROM_DATABASE=IDZ Ltd
+
OUI:70B3D57F7*
ID_OUI_FROM_DATABASE=JASCO Applied Sciences Canada Ltd
OUI:70B3D57F9*
ID_OUI_FROM_DATABASE=Communication Systems Solutions
+OUI:70B3D57FA*
+ ID_OUI_FROM_DATABASE=meoENERGY
+
OUI:70B3D57FB*
ID_OUI_FROM_DATABASE=db Broadcast Products Ltd
OUI:70B3D5811*
ID_OUI_FROM_DATABASE=CJSC «INTERSET»
+OUI:70B3D5812*
+ ID_OUI_FROM_DATABASE=TESCAN Brno, s.r.o.
+
OUI:70B3D5813*
ID_OUI_FROM_DATABASE=Wavemed srl
OUI:70B3D5828*
ID_OUI_FROM_DATABASE=Xacti Corporation
+OUI:70B3D5829*
+ ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
+
OUI:70B3D582A*
ID_OUI_FROM_DATABASE=C W F Hamilton & Co Ltd
OUI:70B3D58C8*
ID_OUI_FROM_DATABASE=KRONOTECH SRL
+OUI:70B3D58C9*
+ ID_OUI_FROM_DATABASE=Arwin Technology Limited
+
OUI:70B3D58CA*
ID_OUI_FROM_DATABASE=Allied Data Systems
OUI:70B3D58E4*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D58E5*
+ ID_OUI_FROM_DATABASE=Shanghai Armour Technology Co., Ltd.
+
OUI:70B3D58E6*
ID_OUI_FROM_DATABASE=Mothonic AB
OUI:70B3D58E8*
ID_OUI_FROM_DATABASE=PREO INDUSTRIES FAR EAST LTD
+OUI:70B3D58E9*
+ ID_OUI_FROM_DATABASE=COONTROL Tecnologia em Combustão LTDA EPP
+
OUI:70B3D58EA*
ID_OUI_FROM_DATABASE=JLCooper Electronics
OUI:70B3D58FC*
ID_OUI_FROM_DATABASE=Mianjie Technology
+OUI:70B3D58FD*
+ ID_OUI_FROM_DATABASE=sonatest
+
OUI:70B3D58FE*
ID_OUI_FROM_DATABASE=Selmatec AS
OUI:70B3D5911*
ID_OUI_FROM_DATABASE=Equatel
+OUI:70B3D5912*
+ ID_OUI_FROM_DATABASE=VERTEL DIGITAL PRIVATE LIMITED
+
OUI:70B3D5913*
ID_OUI_FROM_DATABASE=Shenzhen Riitek Technology Co.,Ltd
OUI:70B3D5914*
ID_OUI_FROM_DATABASE=Contec Americas Inc.
+OUI:70B3D5915*
+ ID_OUI_FROM_DATABASE=DHK Storage, LLC
+
OUI:70B3D5916*
ID_OUI_FROM_DATABASE=Techno Mathematical Co.,Ltd
OUI:70B3D5927*
ID_OUI_FROM_DATABASE=LG Electronics
+OUI:70B3D5928*
+ ID_OUI_FROM_DATABASE=Done Design Inc
+
OUI:70B3D5929*
ID_OUI_FROM_DATABASE=OutSys
OUI:70B3D596B*
ID_OUI_FROM_DATABASE=FOCAL-JMLab
+OUI:70B3D596C*
+ ID_OUI_FROM_DATABASE=Weble Sàrl
+
OUI:70B3D596D*
ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH
OUI:70B3D59BB*
ID_OUI_FROM_DATABASE=Jinga-hi, Inc.
+OUI:70B3D59BC*
+ ID_OUI_FROM_DATABASE=Radian Research, Inc.
+
OUI:70B3D59BD*
ID_OUI_FROM_DATABASE=Signal Processing Devices Sweden AB
ID_OUI_FROM_DATABASE=Benchmark Electronics BV
OUI:70B3D59EE*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Lockheed Martin - THAAD
OUI:70B3D59EF*
ID_OUI_FROM_DATABASE=Cottonwood Creek Technologies, Inc.
OUI:70B3D59FE*
ID_OUI_FROM_DATABASE=SURUGA SEIKI CO., LTD.
+OUI:70B3D59FF*
+ ID_OUI_FROM_DATABASE=Network Integrity Systems
+
OUI:70B3D5A00*
ID_OUI_FROM_DATABASE=ATX NETWORKS LTD
OUI:70B3D5A01*
ID_OUI_FROM_DATABASE=FeldTech GmbH
+OUI:70B3D5A02*
+ ID_OUI_FROM_DATABASE=GreenFlux
+
OUI:70B3D5A03*
ID_OUI_FROM_DATABASE=Proemion GmbH
OUI:70B3D5A1D*
ID_OUI_FROM_DATABASE=Fluid Components International
+OUI:70B3D5A1E*
+ ID_OUI_FROM_DATABASE=Monnit Corporation
+
OUI:70B3D5A1F*
ID_OUI_FROM_DATABASE=GlobalTest LLC
ID_OUI_FROM_DATABASE=Argon ST
OUI:70B3D5A9F*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Master Meter Inc.
OUI:70B3D5AA0*
ID_OUI_FROM_DATABASE=Simple Works, Inc.
OUI:70B3D5ACF*
ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC
+OUI:70B3D5AD0*
+ ID_OUI_FROM_DATABASE=REO AG
+
OUI:70B3D5AD1*
ID_OUI_FROM_DATABASE=Sensile Technologies SA
OUI:70B3D5B00*
ID_OUI_FROM_DATABASE=HORIBA ABX SAS
+OUI:70B3D5B01*
+ ID_OUI_FROM_DATABASE=G.S.D GROUP INC.
+
OUI:70B3D5B02*
ID_OUI_FROM_DATABASE=Nordic Automation Systems AS
OUI:70B3D5B11*
ID_OUI_FROM_DATABASE=CAB S.R.L.
+OUI:70B3D5B12*
+ ID_OUI_FROM_DATABASE=VTEQ
+
OUI:70B3D5B13*
ID_OUI_FROM_DATABASE=Omwave
OUI:70B3D5B4B*
ID_OUI_FROM_DATABASE=Network Customizing Technologies Inc
+OUI:70B3D5B4C*
+ ID_OUI_FROM_DATABASE=AmericanPharma Technologies
+
OUI:70B3D5B4D*
ID_OUI_FROM_DATABASE=Avidbots Corporation
OUI:70B3D5B6F*
ID_OUI_FROM_DATABASE=Integra Metering SAS
+OUI:70B3D5B70*
+ ID_OUI_FROM_DATABASE=Torion Plasma Corporation
+
OUI:70B3D5B71*
ID_OUI_FROM_DATABASE=Optiver Pty Ltd
OUI:70B3D5B78*
ID_OUI_FROM_DATABASE=HOERMANN GmbH
+OUI:70B3D5B79*
+ ID_OUI_FROM_DATABASE=Dadacon GmbH
+
OUI:70B3D5B7A*
ID_OUI_FROM_DATABASE=MAHLE
OUI:70B3D5BC7*
ID_OUI_FROM_DATABASE=Autonomic Controls, Inc.
+OUI:70B3D5BC8*
+ ID_OUI_FROM_DATABASE=Loma Systems s.r.o.
+
OUI:70B3D5BC9*
ID_OUI_FROM_DATABASE=Yite technology
OUI:70B3D5BD6*
ID_OUI_FROM_DATABASE=Consarc Corporation
+OUI:70B3D5BD7*
+ ID_OUI_FROM_DATABASE=TT Group SRL
+
OUI:70B3D5BD8*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D5C6A*
ID_OUI_FROM_DATABASE=Private
+OUI:70B3D5C6B*
+ ID_OUI_FROM_DATABASE=Herholdt Controls srl
+
OUI:70B3D5C6C*
ID_OUI_FROM_DATABASE=McQ Inc
OUI:70B3D5C9F*
ID_OUI_FROM_DATABASE=Triax A/S
+OUI:70B3D5CA0*
+ ID_OUI_FROM_DATABASE=Xirgo Technologies LLC
+
OUI:70B3D5CA1*
ID_OUI_FROM_DATABASE=Waldo System
OUI:70B3D5CA5*
ID_OUI_FROM_DATABASE=PTS Technologies Pte Ltd
+OUI:70B3D5CA6*
+ ID_OUI_FROM_DATABASE=AXING AG
+
OUI:70B3D5CA7*
ID_OUI_FROM_DATABASE=i-View Communication Inc.
OUI:70B3D5CAC*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5CAD*
+ ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+
OUI:70B3D5CAE*
ID_OUI_FROM_DATABASE=THEMA
OUI:70B3D5CB4*
ID_OUI_FROM_DATABASE=Planewave Instruments
+OUI:70B3D5CB5*
+ ID_OUI_FROM_DATABASE=Atlas Lighting Products
+
OUI:70B3D5CB6*
ID_OUI_FROM_DATABASE=Kuebrich Ingeniergesellschaft mbh & Co. KG
OUI:70B3D5CBF*
ID_OUI_FROM_DATABASE=Cubic ITS, Inc. dba GRIDSMART Technologies
+OUI:70B3D5CC0*
+ ID_OUI_FROM_DATABASE=Avionica
+
OUI:70B3D5CC1*
ID_OUI_FROM_DATABASE=BEEcube Inc.
OUI:70B3D5CDF*
ID_OUI_FROM_DATABASE=3D Printing Specialists
+OUI:70B3D5CE0*
+ ID_OUI_FROM_DATABASE=M.S. CONTROL
+
OUI:70B3D5CE1*
ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG
OUI:70B3D5CE7*
ID_OUI_FROM_DATABASE=June Automation Singapore Pte. Ltd.
+OUI:70B3D5CE8*
+ ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG
+
OUI:70B3D5CE9*
ID_OUI_FROM_DATABASE=KINEMETRICS
OUI:70B3D5CEA*
ID_OUI_FROM_DATABASE=Computerwise, Inc.
+OUI:70B3D5CEB*
+ ID_OUI_FROM_DATABASE=Xirgo Technologies LLC
+
OUI:70B3D5CEC*
ID_OUI_FROM_DATABASE=Deltronic Security AB
OUI:70B3D5CF8*
ID_OUI_FROM_DATABASE=Idneo Technologies S.A.U.
+OUI:70B3D5CF9*
+ ID_OUI_FROM_DATABASE=Breas Medical AB
+
+OUI:70B3D5CFA*
+ ID_OUI_FROM_DATABASE=SCHEIBER
+
OUI:70B3D5CFB*
ID_OUI_FROM_DATABASE=Screen Innovations
OUI:70B3D5D03*
ID_OUI_FROM_DATABASE=Digitella Inc.
+OUI:70B3D5D04*
+ ID_OUI_FROM_DATABASE=Plenty Unlimited Inc
+
OUI:70B3D5D05*
ID_OUI_FROM_DATABASE=Colmek
OUI:70B3D5D1C*
ID_OUI_FROM_DATABASE=Specialised Imaging Limited
+OUI:70B3D5D1D*
+ ID_OUI_FROM_DATABASE=Stuyts Engineering Haarlem BV
+
OUI:70B3D5D1E*
ID_OUI_FROM_DATABASE=Houston Radar LLC
OUI:70B3D5D20*
ID_OUI_FROM_DATABASE=Rheonics GmbH
+OUI:70B3D5D21*
+ ID_OUI_FROM_DATABASE=biosilver .co.,ltd
+
OUI:70B3D5D22*
ID_OUI_FROM_DATABASE=DEK Technologies
OUI:70B3D5D2B*
ID_OUI_FROM_DATABASE=StreamPlay Oy Ltd
+OUI:70B3D5D2C*
+ ID_OUI_FROM_DATABASE=microWerk GmbH
+
OUI:70B3D5D2D*
ID_OUI_FROM_DATABASE=Evolute Systems Private Limited
OUI:70B3D5D44*
ID_OUI_FROM_DATABASE=ic-automation GmbH
+OUI:70B3D5D45*
+ ID_OUI_FROM_DATABASE=Vemco Sp. z o. o.
+
OUI:70B3D5D46*
ID_OUI_FROM_DATABASE=Contineo s.r.o.
OUI:70B3D5D51*
ID_OUI_FROM_DATABASE=Azcom Technology S.r.l.
+OUI:70B3D5D52*
+ ID_OUI_FROM_DATABASE=Sensoronic Co.,Ltd
+
OUI:70B3D5D53*
ID_OUI_FROM_DATABASE=BeiLi eTek (Zhangjiagang) Co., Ltd.
OUI:70B3D5D6C*
ID_OUI_FROM_DATABASE=GP Systems GmbH
+OUI:70B3D5D6D*
+ ID_OUI_FROM_DATABASE=ACD Elekronik GmbH
+
OUI:70B3D5D6E*
ID_OUI_FROM_DATABASE=ard sa
OUI:70B3D5D82*
ID_OUI_FROM_DATABASE=SUN ELECTRONICS CO.,LTD.
+OUI:70B3D5D83*
+ ID_OUI_FROM_DATABASE=AKASAKATEC INC.
+
OUI:70B3D5D84*
ID_OUI_FROM_DATABASE=Sentry360
OUI:70B3D5D9F*
ID_OUI_FROM_DATABASE=Digital Solutions JSC
+OUI:70B3D5DA0*
+ ID_OUI_FROM_DATABASE=Jiangsu Etern Compamy Limited
+
OUI:70B3D5DA1*
ID_OUI_FROM_DATABASE=Qprel srl
OUI:70B3D5DD9*
ID_OUI_FROM_DATABASE=MaNima Technologies BV
+OUI:70B3D5DDA*
+ ID_OUI_FROM_DATABASE=Hubbell Power Systems
+
OUI:70B3D5DDB*
ID_OUI_FROM_DATABASE=Intra Corporation
OUI:70B3D5DEA*
ID_OUI_FROM_DATABASE=Advanced Ventilation Applications, Inc.
+OUI:70B3D5DEB*
+ ID_OUI_FROM_DATABASE=DORLET SAU
+
OUI:70B3D5DEC*
ID_OUI_FROM_DATABASE=Condev-Automation GmbH
OUI:70B3D5DEE*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5DEF*
+ ID_OUI_FROM_DATABASE=ISG Nordic AB
+
OUI:70B3D5DF0*
ID_OUI_FROM_DATABASE=astozi consulting Tomasz Zieba
OUI:70B3D5E18*
ID_OUI_FROM_DATABASE=Plasmapp Co.,Ltd.
+OUI:70B3D5E19*
+ ID_OUI_FROM_DATABASE=BAB TECHNOLOGIE GmbH
+
OUI:70B3D5E1A*
ID_OUI_FROM_DATABASE=BIZERBA LUCEO
OUI:70B3D5E40*
ID_OUI_FROM_DATABASE=Siemens Mobility GmbH - MO TI SPA
+OUI:70B3D5E42*
+ ID_OUI_FROM_DATABASE=Neusoft Reach Automotive Technology (Shenyang) Co.,Ltd
+
OUI:70B3D5E43*
ID_OUI_FROM_DATABASE=SL Audio A/S
OUI:70B3D5E5E*
ID_OUI_FROM_DATABASE=Critical Link LLC
+OUI:70B3D5E60*
+ ID_OUI_FROM_DATABASE=Davitor AB
+
OUI:70B3D5E61*
ID_OUI_FROM_DATABASE=Adeli
OUI:70B3D5EDF*
ID_OUI_FROM_DATABASE=GridNavigator
+OUI:70B3D5EE0*
+ ID_OUI_FROM_DATABASE=Stecomp
+
OUI:70B3D5EE1*
ID_OUI_FROM_DATABASE=allora Factory BVBA
OUI:70B3D5EEF*
ID_OUI_FROM_DATABASE=TATTILE SRL
+OUI:70B3D5EF0*
+ ID_OUI_FROM_DATABASE=PNETWORKS
+
OUI:70B3D5EF1*
ID_OUI_FROM_DATABASE=Nanotok LLC
OUI:70B3D5F1A*
ID_OUI_FROM_DATABASE=Sator Controls s.r.o.
+OUI:70B3D5F1B*
+ ID_OUI_FROM_DATABASE=RoyalShield Technologies India Private Limited
+
OUI:70B3D5F1C*
ID_OUI_FROM_DATABASE=Bavaria Digital Technik GmbH
OUI:70B3D5F25*
ID_OUI_FROM_DATABASE=JSC “Scientific Industrial Enterprise Rubin
+OUI:70B3D5F26*
+ ID_OUI_FROM_DATABASE=XJ ELECTRIC CO., LTD.
+
OUI:70B3D5F27*
ID_OUI_FROM_DATABASE=NIRIT- Xinwei Telecom Technology Co., Ltd.
OUI:70B3D5F30*
ID_OUI_FROM_DATABASE=ADE Technology Inc.
+OUI:70B3D5F31*
+ ID_OUI_FROM_DATABASE=The-Box Development
+
OUI:70B3D5F32*
ID_OUI_FROM_DATABASE=Elektronik Art
ID_OUI_FROM_DATABASE=KST technology
OUI:70B3D5F7C*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Medicomp, Inc
OUI:70B3D5F7D*
ID_OUI_FROM_DATABASE=2M Technology
OUI:70B3D5FB3*
ID_OUI_FROM_DATABASE=3PS Inc
+OUI:70B3D5FB4*
+ ID_OUI_FROM_DATABASE=Array Technologies Inc.
+
OUI:70B3D5FB5*
ID_OUI_FROM_DATABASE=Orange Tree Technologies Ltd
OUI:70B3D5FDF*
ID_OUI_FROM_DATABASE=NARA CONTROLS INC.
+OUI:70B3D5FE0*
+ ID_OUI_FROM_DATABASE=Blueprint Lab
+
+OUI:70B3D5FE1*
+ ID_OUI_FROM_DATABASE=Shenzhen Zhiting Technology Co.,Ltd
+
OUI:70B3D5FE2*
ID_OUI_FROM_DATABASE=Galileo Tıp Teknolojileri San. ve Tic. A.S.
OUI:70DF2F*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:70DFF7*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:70E027*
ID_OUI_FROM_DATABASE=HONGYU COMMUNICATION TECHNOLOGY LIMITED
OUI:70F087*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:70F088*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
OUI:70F096*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:7405A5*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:7409AC*
+ ID_OUI_FROM_DATABASE=Quext, LLC
+
OUI:740ABC*
ID_OUI_FROM_DATABASE=LightwaveRF Technology Ltd
OUI:741489*
ID_OUI_FROM_DATABASE=SRT Wireless
+OUI:741575*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:7415E2*
ID_OUI_FROM_DATABASE=Tri-Sen Systems Corporation
OUI:74ACB9*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+OUI:74AD98*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:74ADB7*
ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
OUI:74D21D*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:74D285*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:74D435*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:780F77*
ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd
+OUI:781053*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
OUI:781100*
ID_OUI_FROM_DATABASE=Quantumsolution
OUI:781881*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+OUI:7818A8*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:78192E*
ID_OUI_FROM_DATABASE=NASCENT Technology
OUI:786256*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:7864C0*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:7864E6*
ID_OUI_FROM_DATABASE=Green Motive Technology Limited
+OUI:78653B*
+ ID_OUI_FROM_DATABASE=Shaoxing Ourten Electronics Co., Ltd.
+
OUI:786559*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:78725D*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:787A6F*
+ ID_OUI_FROM_DATABASE=Juice Technology AG
+
OUI:787B8A*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:78A683*
ID_OUI_FROM_DATABASE=Precidata
+OUI:78A6A0*
+ ID_OUI_FROM_DATABASE=Hangzhou Ezviz Software Co.,Ltd.
+
OUI:78A6BD*
ID_OUI_FROM_DATABASE=DAEYEON Control&Instrument Co,.Ltd
OUI:78B46A*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:78B554*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:78B5D2*
ID_OUI_FROM_DATABASE=Ever Treasure Industrial Limited
OUI:78CF2F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:78CFF9*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:78D004*
ID_OUI_FROM_DATABASE=Neousys Technology Inc.
OUI:78D99F*
ID_OUI_FROM_DATABASE=NuCom HK Ltd.
+OUI:78D9E9*
+ ID_OUI_FROM_DATABASE=MOMENTUM IOT
+
OUI:78DA07*
ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
OUI:78E2BD*
ID_OUI_FROM_DATABASE=Vodafone Automotive S.p.A.
+OUI:78E36D*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:78E3B5*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:78F09B*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:78F235*
+ ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd.
+
OUI:78F29E*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
OUI:78FFCA*
ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+OUI:7C004D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:7C010A*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:7C092B*
ID_OUI_FROM_DATABASE=Bekey A/S
+OUI:7C0A3F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:7C0A50*
ID_OUI_FROM_DATABASE=J-MEX Inc.
OUI:7C1AFC*
ID_OUI_FROM_DATABASE=Dalian Co-Edifice Video Technology Co., Ltd
+OUI:7C1B93*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:7C1C4E*
ID_OUI_FROM_DATABASE=LG Innotek
OUI:7C3CB6*
ID_OUI_FROM_DATABASE=Shenzhen Homecare Technology Co.,Ltd.
+OUI:7C3D2B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:7C3E9D*
ID_OUI_FROM_DATABASE=PATECH
OUI:7C534A*
ID_OUI_FROM_DATABASE=Metamako
+OUI:7C55A7*
+ ID_OUI_FROM_DATABASE=Kastle Systems
+
OUI:7C55E7*
ID_OUI_FROM_DATABASE=YSI, Inc.
OUI:7C9EBD*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:7C9F07*
+ ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD
+
OUI:7CA15D*
ID_OUI_FROM_DATABASE=GN ReSound A/S
OUI:7CB77B*
ID_OUI_FROM_DATABASE=Paradigm Electronics Inc
+OUI:7CB94C*
+ ID_OUI_FROM_DATABASE=Bouffalo Lab (Nanjing) Co., Ltd.
+
OUI:7CB960*
ID_OUI_FROM_DATABASE=Shanghai X-Cheng telecom LTD
OUI:7CD9A0*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:7CD9F4*
+ ID_OUI_FROM_DATABASE=UAB Teltonika Telematics
+
OUI:7CD9FE*
ID_OUI_FROM_DATABASE=New Cosmos Electric Co., Ltd.
OUI:7CF429*
ID_OUI_FROM_DATABASE=NUUO Inc.
+OUI:7CF666*
+ ID_OUI_FROM_DATABASE=Tuya Smart Inc.
+
OUI:7CF854*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:7CF880*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:7CF90E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:8005DF*
ID_OUI_FROM_DATABASE=Montage Technology Group Limited
+OUI:80071B*
+ ID_OUI_FROM_DATABASE=VSOLUTION TELECOMMUNICATION TECHNOLOGY CO.,LTD.
+
OUI:8007A2*
ID_OUI_FROM_DATABASE=Esson Technology Inc.
OUI:8022A7*
ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
+OUI:802511*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:802689*
ID_OUI_FROM_DATABASE=D-Link International
OUI:803253*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:803428*
+ ID_OUI_FROM_DATABASE=Microchip Technology Inc.
+
OUI:803457*
ID_OUI_FROM_DATABASE=OT Systems Limited
OUI:80427C*
ID_OUI_FROM_DATABASE=Adolf Tedsen GmbH & Co. KG
+OUI:8044FD*
+ ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd.
+
+OUI:8045DD*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:804731*
ID_OUI_FROM_DATABASE=Packet Design, Inc.
+OUI:804786*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:8048A5*
ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
OUI:807215*
ID_OUI_FROM_DATABASE=BSkyB Ltd
+OUI:807264*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:80739F*
ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
OUI:808A8B*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:808AF7*
+ ID_OUI_FROM_DATABASE=Nanoleaf
+
OUI:808B5C*
ID_OUI_FROM_DATABASE=Shenzhen Runhuicheng Technology Co., Ltd
OUI:80F25E*
ID_OUI_FROM_DATABASE=Kyynel
+OUI:80F3EF*
+ ID_OUI_FROM_DATABASE=Facebook Technologies, LLC
+
OUI:80F503*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:8404D2*
ID_OUI_FROM_DATABASE=Kirale Technologies SL
+OUI:8406FA*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:840B2D*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD.
OUI:841E26*
ID_OUI_FROM_DATABASE=KERNEL-I Co.,LTD
+OUI:841EA3*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:842096*
ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
OUI:84225E*
ID_OUI_FROM_DATABASE=SHENZHEN TECHNEWCHIP TECHNOLOGY CO.,LTD.
+OUI:842388*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:84248D*
ID_OUI_FROM_DATABASE=Zebra Technologies Inc
OUI:84262B*
ID_OUI_FROM_DATABASE=Nokia
+OUI:84267A*
+ ID_OUI_FROM_DATABASE=GUANGDONG TAIDE ZHILIAN TECHNOLOGY CO.,LTD
+
OUI:842690*
ID_OUI_FROM_DATABASE=BEIJING THOUGHT SCIENCE CO.,LTD.
OUI:843A4B*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:843A5B*
+ ID_OUI_FROM_DATABASE=Inventec(Chongqing) Corporation
+
+OUI:843B10*
+ ID_OUI_FROM_DATABASE=Lv switch Inc.
+
OUI:843DC6*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:847A88*
ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:847AB6*
+ ID_OUI_FROM_DATABASE=AltoBeam (China) Inc.
+
OUI:847BEB*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:848BCDE*
ID_OUI_FROM_DATABASE=Emotiv Inc
+OUI:848C8D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:848D84*
ID_OUI_FROM_DATABASE=Rajant Corporation
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:849000*
- ID_OUI_FROM_DATABASE=Arnold & Richter Cine Technik
+ ID_OUI_FROM_DATABASE=Arnold&Richter Cine Technik GmbH & Co. Betriebs KG
OUI:84930C*
ID_OUI_FROM_DATABASE=InCoax Networks Europe AB
OUI:84AB1A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:84AB26*
+ ID_OUI_FROM_DATABASE=Tiinlab Corporation
+
OUI:84ACA4*
ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd
ID_OUI_FROM_DATABASE=Gnodal Ltd
OUI:84C78F*
- ID_OUI_FROM_DATABASE=STORDIS GmbH
+ ID_OUI_FROM_DATABASE=APS Networks GmbH
OUI:84C7A9*
ID_OUI_FROM_DATABASE=C3PO S.A.
OUI:84D4C8*
ID_OUI_FROM_DATABASE=Widex A/S
+OUI:84D608*
+ ID_OUI_FROM_DATABASE=Wingtech Mobile Communications Co., Ltd.
+
OUI:84D6C5*
ID_OUI_FROM_DATABASE=SolarEdge Technologies
OUI:84E892*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+OUI:84E986*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:84EA97*
ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
OUI:84FCFE*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:84FD27*
+ ID_OUI_FROM_DATABASE=Silicon Laboratories
+
OUI:84FDD1*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:88299C*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:882A5E*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:882B94*
ID_OUI_FROM_DATABASE=MADOKA SYSTEM Co.,Ltd.
OUI:8844F6*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:884604*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:88462A*
ID_OUI_FROM_DATABASE=Telechips Inc.
OUI:888E68*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:889009*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:88908D*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:88C3B3*
ID_OUI_FROM_DATABASE=SOVICO
+OUI:88C3E5*
+ ID_OUI_FROM_DATABASE=Betop Techonologies
+
OUI:88C626*
ID_OUI_FROM_DATABASE=Logitech, Inc
OUI:88E034*
ID_OUI_FROM_DATABASE=Shinwa industries(China) ltd.
+OUI:88E056*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:88E0A0*
ID_OUI_FROM_DATABASE=Shenzhen VisionSTOR Technologies Co., Ltd
OUI:8C192DE*
ID_OUI_FROM_DATABASE=Elcon AB
+OUI:8C19B5*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:8C1ABF*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:8C2937*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:8C2A8E*
+ ID_OUI_FROM_DATABASE=DongGuan Ramaxel Memory Technology
+
OUI:8C2DAA*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:8C2FA6*
ID_OUI_FROM_DATABASE=Solid Optics B.V.
+OUI:8C31E2*
+ ID_OUI_FROM_DATABASE=DAYOUPLUS
+
OUI:8C3330*
ID_OUI_FROM_DATABASE=EmFirst Co., Ltd.
OUI:8C3401*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:8C3446*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:8C34FD*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:8C3579*
ID_OUI_FROM_DATABASE=QDIQO Sp. z o.o.
+OUI:8C367A*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
OUI:8C395C*
ID_OUI_FROM_DATABASE=Bit4id Srl
OUI:8C426D*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:8C4361*
+ ID_OUI_FROM_DATABASE=Hailo Digital Hub GmbH & Co. KG
+
OUI:8C4435*
ID_OUI_FROM_DATABASE=Shanghai BroadMobi Communication Technology Co., Ltd.
OUI:8C736E*
ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+OUI:8C73A0*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:8C76C1*
ID_OUI_FROM_DATABASE=Goden Tech Limited
OUI:8C83E1*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:8C83FC*
+ ID_OUI_FROM_DATABASE=Axioma Metering UAB
+
OUI:8C8401*
ID_OUI_FROM_DATABASE=Private
OUI:8CAAB5*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:8CAACE*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:8CAB8E*
ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd.
OUI:8CD67F*
ID_OUI_FROM_DATABASE=EM Microelectronic
+OUI:8CD9D6*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:8CDB25*
ID_OUI_FROM_DATABASE=ESG Solutions
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:8CE748*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
OUI:8CE78C*
ID_OUI_FROM_DATABASE=DK Networks
OUI:902181*
ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd
+OUI:9023B4*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:9023EC*
ID_OUI_FROM_DATABASE=Availink, Inc.
OUI:90A7C1*
ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc.
+OUI:90A822*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:90A935*
ID_OUI_FROM_DATABASE=JWEntertainment
OUI:90B4DD*
ID_OUI_FROM_DATABASE=Private
+OUI:90B67A*
+ ID_OUI_FROM_DATABASE=Shenzhen Skyworth Digital Technology CO., Ltd
+
OUI:90B686*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:90C115*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
+OUI:90C119*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:90C1C6*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:90F891*
ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+OUI:90F9B7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:90FB5B*
ID_OUI_FROM_DATABASE=Avaya Inc
ID_OUI_FROM_DATABASE=Dongguan CXWE Technology Co.,Ltd.
OUI:9405BB3*
- ID_OUI_FROM_DATABASE=Neurik AG
+ ID_OUI_FROM_DATABASE=Neutrik AG
OUI:9405BB4*
ID_OUI_FROM_DATABASE=Shenzhen Baolijie Technology Co., Ltd.
OUI:9439E5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:943A91*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:943AF0*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:943BB1*
ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+OUI:943CC6*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:943DC9*
ID_OUI_FROM_DATABASE=Asahi Net, Inc.
OUI:94A40C*
ID_OUI_FROM_DATABASE=Diehl Metering GmbH
+OUI:94A4F9*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:94A67E*
ID_OUI_FROM_DATABASE=NETGEAR
OUI:94E226*
ID_OUI_FROM_DATABASE=D. ORtiz Consulting, LLC
+OUI:94E23C*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:94E2FD*
ID_OUI_FROM_DATABASE=Boge Kompressoren OTTO Boge GmbH & Co. KG
OUI:94E9EE*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:94EA32*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:94EAEA*
ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO
OUI:981888*
ID_OUI_FROM_DATABASE=Cisco Meraki
+OUI:981A35*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:981BB5*
ID_OUI_FROM_DATABASE=ASSA ABLOY Korea Co., Ltd iRevo
OUI:98262A*
ID_OUI_FROM_DATABASE=Applied Research Associates, Inc
+OUI:9827820*
+ ID_OUI_FROM_DATABASE=SHENZHEN HEROFUN BIO-TECH CO., LTD
+
+OUI:9827821*
+ ID_OUI_FROM_DATABASE=INFODAS GmbH
+
+OUI:9827822*
+ ID_OUI_FROM_DATABASE=Anhui Shengren Electronic Technology Co., Ltd
+
+OUI:9827823*
+ ID_OUI_FROM_DATABASE=Danfoss Power Solutions
+
+OUI:9827824*
+ ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc.
+
+OUI:9827825*
+ ID_OUI_FROM_DATABASE=Guangzhou Wuzhou Technology Co, Ltd.
+
+OUI:9827826*
+ ID_OUI_FROM_DATABASE=WESTERN SECURITY SOLUTIONS
+
+OUI:9827827*
+ ID_OUI_FROM_DATABASE=KORTEK CORPORATION
+
+OUI:9827828*
+ ID_OUI_FROM_DATABASE=CATS Power design
+
+OUI:9827829*
+ ID_OUI_FROM_DATABASE=Wuxi GuoYiHaiJu Technology Co.,Ltd.
+
+OUI:982782A*
+ ID_OUI_FROM_DATABASE=Nanjing BianYu Future Home Technology Co.Ltd
+
+OUI:982782B*
+ ID_OUI_FROM_DATABASE=RayTron, INC.
+
+OUI:982782C*
+ ID_OUI_FROM_DATABASE=KRISTECH Krzysztof Kajstura
+
+OUI:982782D*
+ ID_OUI_FROM_DATABASE=Thorlabs GmbH
+
+OUI:982782E*
+ ID_OUI_FROM_DATABASE=SureFlap Ltd
+
OUI:9828A6*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
OUI:983713*
ID_OUI_FROM_DATABASE=PT.Navicom Indonesia
+OUI:98387D*
+ ID_OUI_FROM_DATABASE=ITRONIC TECHNOLOGY CO . , LTD .
+
OUI:98398E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:983F60*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:983F66*
+ ID_OUI_FROM_DATABASE=Wuhan Funshion Online Technologies Co.,Ltd
+
OUI:983F9F*
ID_OUI_FROM_DATABASE=China SSJ (Suzhou) Network Technology Inc.
OUI:984246*
ID_OUI_FROM_DATABASE=SOL INDUSTRY PTE., LTD
+OUI:984265*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:9843DA*
ID_OUI_FROM_DATABASE=INTERTECH
OUI:984827*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:984874*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:984914*
ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
OUI:9874DA*
ID_OUI_FROM_DATABASE=Infinix mobility limited
+OUI:98751A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:9876B6*
ID_OUI_FROM_DATABASE=Adafruit
OUI:98AAFCE*
ID_OUI_FROM_DATABASE=Comarch S.A.
+OUI:98AD1D*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:98AE71*
ID_OUI_FROM_DATABASE=VVDN Technologies Pvt Ltd
OUI:98C0EB*
ID_OUI_FROM_DATABASE=Global Regency Ltd
+OUI:98C3D2*
+ ID_OUI_FROM_DATABASE=Ningbo Sanxing Medical Electric Co.,Ltd
+
OUI:98C5DB*
ID_OUI_FROM_DATABASE=Ericsson AB
OUI:98CC4D*
ID_OUI_FROM_DATABASE=Shenzhen mantunsci co., LTD
+OUI:98CDAC*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:98CDB4*
ID_OUI_FROM_DATABASE=Virident Systems, Inc.
OUI:9C1C12*
ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+OUI:9C1C37*
+ ID_OUI_FROM_DATABASE=AltoBeam (China) Inc.
+
OUI:9C1D36*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:9C4EBF*
ID_OUI_FROM_DATABASE=BoxCast
+OUI:9C4F5F*
+ ID_OUI_FROM_DATABASE=TAP Sound System
+
OUI:9C4FCF*
ID_OUI_FROM_DATABASE=TCT mobile ltd
OUI:9C7514*
ID_OUI_FROM_DATABASE=Wildix srl
+OUI:9C760E*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:9C7613*
+ ID_OUI_FROM_DATABASE=Ring LLC
+
OUI:9C77AA*
ID_OUI_FROM_DATABASE=NADASNV
OUI:9C7F57*
ID_OUI_FROM_DATABASE=UNIC Memory Technology Co Ltd
+OUI:9C7F81*
+ ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+
OUI:9C807D*
ID_OUI_FROM_DATABASE=SYSCABLE Korea Inc.
OUI:9C8275*
ID_OUI_FROM_DATABASE=Yichip Microelectronics (Hangzhou) Co.,Ltd
+OUI:9C8281*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:9C83BF*
ID_OUI_FROM_DATABASE=PRO-VISION, Inc.
OUI:9C93E4*
ID_OUI_FROM_DATABASE=Private
+OUI:9C9567*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:9C95F8*
ID_OUI_FROM_DATABASE=SmartDoor Systems, LLC
OUI:9CDB07*
ID_OUI_FROM_DATABASE=Thum+Mahr GmbH
+OUI:9CDBCB*
+ ID_OUI_FROM_DATABASE=Wuhan Funshion Online Technologies Co.,Ltd
+
OUI:9CDC71*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
OUI:A0341B*
ID_OUI_FROM_DATABASE=Adero Inc
+OUI:A03679*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A0369F*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:A0481C*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:A04A5E*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
OUI:A04C5B*
ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
OUI:A07099*
ID_OUI_FROM_DATABASE=Beijing Huacan Electronics Co., Ltd
+OUI:A070B7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A071A9*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:A0D795*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A0D7A0*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:A0D807*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:A40450*
ID_OUI_FROM_DATABASE=nFore Technology Inc.
+OUI:A4056E*
+ ID_OUI_FROM_DATABASE=Tiinlab Corporation
+
OUI:A4059E*
ID_OUI_FROM_DATABASE=STA Infinity LLP
OUI:A41908*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:A41B34*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
OUI:A41BC0*
ID_OUI_FROM_DATABASE=Fastec Imaging Corporation
OUI:A43523*
ID_OUI_FROM_DATABASE=Guangdong Donyan Network Technologies Co.,Ltd.
+OUI:A4352D*
+ ID_OUI_FROM_DATABASE=TRIZ Networks corp.
+
OUI:A43831*
ID_OUI_FROM_DATABASE=RF elements s.r.o.
OUI:A438FC*
ID_OUI_FROM_DATABASE=Plastic Logic
+OUI:A439B6*
+ ID_OUI_FROM_DATABASE=SHENZHEN PEIZHE MICROELECTRONICS CO .LTD
+
OUI:A43A69*
ID_OUI_FROM_DATABASE=Vers Inc
OUI:A44C11*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:A44C62*
+ ID_OUI_FROM_DATABASE=Hangzhou Microimage Software Co., Ltd
+
OUI:A44CC8*
ID_OUI_FROM_DATABASE=Dell Inc.
ID_OUI_FROM_DATABASE=Foshan Yisihang Electrical Technology Co., Ltd.
OUI:A453EE6*
- ID_OUI_FROM_DATABASE=Aura Home, Inc.
+ ID_OUI_FROM_DATABASE=Shenzhen Xunqi Interconnet Technology Co., Ltd
OUI:A453EE7*
ID_OUI_FROM_DATABASE=Beijing Lanke Science and Technology Co.,LTd.
OUI:A456CC*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+OUI:A45802*
+ ID_OUI_FROM_DATABASE=SHIN-IL TECH
+
OUI:A4580F0*
ID_OUI_FROM_DATABASE=INNOPRO
OUI:A47ACF*
ID_OUI_FROM_DATABASE=VIBICOM COMMUNICATIONS INC.
+OUI:A47B1A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:A47B2C*
ID_OUI_FROM_DATABASE=Nokia
OUI:A47D9F*
ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
+OUI:A47E36*
+ ID_OUI_FROM_DATABASE=EM Microelectronic
+
OUI:A47E39*
ID_OUI_FROM_DATABASE=zte corporation
OUI:A49B4F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:A49BCD*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:A49BF5*
ID_OUI_FROM_DATABASE=Hybridserver Tec GmbH
OUI:A4A24A*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:A4A46B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A4A4D3*
ID_OUI_FROM_DATABASE=Bluebank Communication Technology Co.Ltd
OUI:A4CD23*
ID_OUI_FROM_DATABASE=Shenzhenshi Xinzhongxin Co., Ltd
+OUI:A4CEDA*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:A4CF12*
ID_OUI_FROM_DATABASE=Espressif Inc.
OUI:A4D578*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:A4D795*
+ ID_OUI_FROM_DATABASE=Wingtech Mobile Communications Co.,Ltd
+
OUI:A4D856*
ID_OUI_FROM_DATABASE=Gimbal, Inc
OUI:A4DA3F*
ID_OUI_FROM_DATABASE=Bionics Corp.
+OUI:A4DAD4*
+ ID_OUI_FROM_DATABASE=Yamato Denki Co.,Ltd.
+
OUI:A4DB2E*
ID_OUI_FROM_DATABASE=Kingspan Environmental Ltd
OUI:A842A7*
ID_OUI_FROM_DATABASE=Jiangsu Huitong Group Co.,Ltd.
+OUI:A84397*
+ ID_OUI_FROM_DATABASE=Innogrit Corporation
+
OUI:A84481*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:A84E3F*
ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+OUI:A85081*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A8515B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:A862A2*
ID_OUI_FROM_DATABASE=JIWUMEDIA CO., LTD.
+OUI:A8637D*
+ ID_OUI_FROM_DATABASE=D-Link International
+
OUI:A863DF*
ID_OUI_FROM_DATABASE=DISPLAIRE CORPORATION
OUI:A8776F*
ID_OUI_FROM_DATABASE=Zonoff
+OUI:A877E5*
+ ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+
OUI:A87B39*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:A8922C*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+OUI:A8934A*
+ ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+
OUI:A89352*
ID_OUI_FROM_DATABASE=SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD
OUI:A8E77D*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:A8E81E*
+ ID_OUI_FROM_DATABASE=ATW TECHNOLOGY, INC.
+
OUI:A8E824*
ID_OUI_FROM_DATABASE=INIM ELECTRONICS S.R.L.
OUI:A8F038*
ID_OUI_FROM_DATABASE=SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD
+OUI:A8F266*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:A8F274*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:AC122F*
ID_OUI_FROM_DATABASE=Fantasia Trading LLC
+OUI:AC139C*
+ ID_OUI_FROM_DATABASE=Adtran Inc
+
OUI:AC1461*
ID_OUI_FROM_DATABASE=ATAW Co., Ltd.
OUI:AC1F09*
ID_OUI_FROM_DATABASE=shenzhen RAKwireless technology Co.,Ltd
+OUI:AC1F0F*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:AC1F6B*
ID_OUI_FROM_DATABASE=Super Micro Computer, Inc.
OUI:AC220B*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:AC2316*
+ ID_OUI_FROM_DATABASE=Mist Systems, Inc.
+
OUI:AC2334*
ID_OUI_FROM_DATABASE=Infinix mobility limited
OUI:AC5AEE*
ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+OUI:AC5AFC*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:AC5D10*
ID_OUI_FROM_DATABASE=Pace Americas
OUI:AC7409*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:AC74C4*
+ ID_OUI_FROM_DATABASE=Maytronics Ltd.
+
OUI:AC751D*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:AC9572*
ID_OUI_FROM_DATABASE=Jovision Technology Co., Ltd.
+OUI:AC9929*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:AC9A22*
ID_OUI_FROM_DATABASE=NXP Semiconductors
OUI:ACD564*
ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+OUI:ACD618*
+ ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd
+
OUI:ACD657*
ID_OUI_FROM_DATABASE=Shaanxi GuoLian Digital TV Technology Co.,Ltd.
OUI:B01F81F*
ID_OUI_FROM_DATABASE=Private
+OUI:B0227A*
+ ID_OUI_FROM_DATABASE=HP Inc.
+
+OUI:B02491*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:B024F3*
ID_OUI_FROM_DATABASE=Progeny Systems
OUI:B03956*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:B03ACE*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:B03D96*
ID_OUI_FROM_DATABASE=Vision Valley FZ LLC
+OUI:B03DC2*
+ ID_OUI_FROM_DATABASE=Wasp artificial intelligence(Shenzhen) Co.,ltd
+
OUI:B03E51*
ID_OUI_FROM_DATABASE=BSkyB Ltd
OUI:B04E26*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:B04F13*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:B04FC3*
ID_OUI_FROM_DATABASE=Shenzhen NVC Cloud Technology Co., Ltd.
OUI:B05CE5*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:B05DD4*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:B06088*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:B0C8AD*
ID_OUI_FROM_DATABASE=People Power Company
+OUI:B0C952*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:B0C95B*
ID_OUI_FROM_DATABASE=Beijing Symtech CO.,LTD
OUI:B40FB3*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:B4107B*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:B41489*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B414E6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B41513*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:B46077*
ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
+OUI:B4608C*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:B460ED*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd
OUI:B48655*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:B48901*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B48910*
ID_OUI_FROM_DATABASE=Coster T.E. S.P.A.
+OUI:B48A5F*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:B48B19*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:B49EE6*
ID_OUI_FROM_DATABASE=SHENZHEN TECHNOLOGY CO LTD
+OUI:B4A25C*
+ ID_OUI_FROM_DATABASE=Cambium Networks Limited
+
OUI:B4A2EB0*
ID_OUI_FROM_DATABASE=QKM Technology(Dongguan)Co.,Ltd
OUI:B4E1EB*
ID_OUI_FROM_DATABASE=Private
+OUI:B4E3F9*
+ ID_OUI_FROM_DATABASE=Silicon Laboratories
+
OUI:B4E62A*
ID_OUI_FROM_DATABASE=LG Innotek
OUI:B4F949*
ID_OUI_FROM_DATABASE=optilink networks pvt ltd
+OUI:B4FA48*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B4FBE3*
ID_OUI_FROM_DATABASE=AltoBeam (China) Inc.
OUI:B81413*
ID_OUI_FROM_DATABASE=Keen High Holding(HK) Ltd.
+OUI:B814DB*
+ ID_OUI_FROM_DATABASE=OHSUNG
+
OUI:B81619*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:B82A72*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:B82AA9*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B82ADC*
ID_OUI_FROM_DATABASE=EFR Europäische Funk-Rundsteuerung GmbH
OUI:B843E4*
ID_OUI_FROM_DATABASE=Vlatacom
+OUI:B844AE*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
OUI:B844D9*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:B88198*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:B881FA*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B88303*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
OUI:B8A175*
ID_OUI_FROM_DATABASE=Roku, Inc.
+OUI:B8A377*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B8A386*
ID_OUI_FROM_DATABASE=D-Link International
OUI:B8D309*
ID_OUI_FROM_DATABASE=Cox Communications, Inc
+OUI:B8D43E*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:B8D49D*
ID_OUI_FROM_DATABASE=M Seven System Ltd.
OUI:B8D526*
ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+OUI:B8D6F6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B8D7AF*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:BCEE7B*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:BCF171*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:BCF1F2*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:BCF9F2*
ID_OUI_FROM_DATABASE=TEKO
+OUI:BCFAB8*
+ ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronic Technology Company Limited
+
OUI:BCFE8C*
ID_OUI_FROM_DATABASE=Altronic, LLC
OUI:BCFF21*
ID_OUI_FROM_DATABASE=Smart Code(shenzhen)Technology Co.,Ltd
+OUI:BCFF4D*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:BCFFAC*
ID_OUI_FROM_DATABASE=TOPCON CORPORATION
OUI:C005C2*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:C006C3*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:C0074A*
ID_OUI_FROM_DATABASE=Brita GmbH
OUI:C044E3*
ID_OUI_FROM_DATABASE=Shenzhen Sinkna Electronics Co., LTD
+OUI:C04754*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:C048E6*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:C04A09*
ID_OUI_FROM_DATABASE=Zhejiang Everbright Communication Equip. Co,. Ltd
+OUI:C04B13*
+ ID_OUI_FROM_DATABASE=WonderSound Technology Co., Ltd
+
OUI:C04DF7*
ID_OUI_FROM_DATABASE=SERELEC
OUI:C09134*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:C09296*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:C09435*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:C0AC54*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:C0AEFD*
+ ID_OUI_FROM_DATABASE=Shenzhen HC-WLAN Technology Co.,Ltd
+
OUI:C0B101*
ID_OUI_FROM_DATABASE=zte corporation
OUI:C0D3C0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C0D46B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C0D682*
ID_OUI_FROM_DATABASE=Arista Networks
OUI:C0DC6A*
ID_OUI_FROM_DATABASE=Qingdao Eastsoft Communication Technology Co.,LTD
+OUI:C0DCD7*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C0DCDA*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:C0E018*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:C0E1BE*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C0E3A0*
ID_OUI_FROM_DATABASE=Renesas Electronics (Penang) Sdn. Bhd.
OUI:C45A86*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:C45BBE*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:C45BF7*
ID_OUI_FROM_DATABASE=ants
OUI:C4700B*
ID_OUI_FROM_DATABASE=GUANGZHOU CHIP TECHNOLOGIES CO.,LTD
+OUI:C470AB*
+ ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD
+
OUI:C47130*
ID_OUI_FROM_DATABASE=Fon Technology S.L.
OUI:C4913A*
ID_OUI_FROM_DATABASE=Shenzhen Sanland Electronic Co., ltd.
+OUI:C491CF*
+ ID_OUI_FROM_DATABASE=Luxul
+
OUI:C4924C*
ID_OUI_FROM_DATABASE=KEISOKUKI CENTER CO.,LTD.
OUI:C4BBEA*
ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc
+OUI:C4BCD7*
+ ID_OUI_FROM_DATABASE=New Ryatek
+
OUI:C4BD6A*
ID_OUI_FROM_DATABASE=SKF GmbH
OUI:C4CD82*
ID_OUI_FROM_DATABASE=Hangzhou Lowan Information Technology Co., Ltd.
+OUI:C4D0E3*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:C4D197*
ID_OUI_FROM_DATABASE=Ventia Utility Services
OUI:C4F0EC*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:C4F174*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:C4F1D1*
ID_OUI_FROM_DATABASE=BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD.
OUI:C81073*
ID_OUI_FROM_DATABASE=CENTURY OPTICOMM CO.,LTD
+OUI:C8138B*
+ ID_OUI_FROM_DATABASE=Shenzhen Skyworth Digital Technology CO., Ltd
+
OUI:C81451*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:C8334B*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C833E5*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C8348E*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:C84C75*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:C84D34*
+ ID_OUI_FROM_DATABASE=LIONS Taiwan Technology Inc.
+
OUI:C84F0E*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
OUI:C8778B*
ID_OUI_FROM_DATABASE=Mercury Systems – Trusted Mission Solutions, Inc.
+OUI:C87B23*
+ ID_OUI_FROM_DATABASE=Bose Corporation
+
OUI:C87B5B*
ID_OUI_FROM_DATABASE=zte corporation
OUI:C89383*
ID_OUI_FROM_DATABASE=Embedded Automation, Inc.
+OUI:C89402*
+ ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+
OUI:C894BB*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:C8979F*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:C89BAD*
+ ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
+
OUI:C89C13*
ID_OUI_FROM_DATABASE=Inspiremobile
OUI:C8BAE9*
ID_OUI_FROM_DATABASE=QDIS
+OUI:C8BB81*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C8BBD3*
ID_OUI_FROM_DATABASE=Embrane
OUI:C8BE19*
ID_OUI_FROM_DATABASE=D-Link International
+OUI:C8BFFE*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C8C126*
ID_OUI_FROM_DATABASE=ZPM Industria e Comercio Ltda
OUI:C8D7B0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C8D884*
+ ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
+
OUI:C8D9D2*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:CC2237E*
ID_OUI_FROM_DATABASE=MANUFACTURAS Y TRANSFORMADOS AB, S.L.
+OUI:CC242E*
+ ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd.
+
OUI:CC25EF*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:CC3080*
ID_OUI_FROM_DATABASE=VAIO Corporation
+OUI:CC3296*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:CC32E5*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:CC3331*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:CC33BB*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:CC66B2*
ID_OUI_FROM_DATABASE=Nokia
+OUI:CC68B6*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:CC69B0*
ID_OUI_FROM_DATABASE=Global Traffic Technologies, LLC
OUI:CC6A10*
ID_OUI_FROM_DATABASE=The Chamberlain Group, Inc
+OUI:CC6B1E*
+ ID_OUI_FROM_DATABASE=CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.
+
OUI:CC6B98*
ID_OUI_FROM_DATABASE=Minetec Wireless Technologies
OUI:CC7F76*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:CC812A*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:CC81DA*
ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd.
OUI:CC856C*
ID_OUI_FROM_DATABASE=SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD
+OUI:CC86EC*
+ ID_OUI_FROM_DATABASE=Silicon Laboratories
+
OUI:CC874A*
ID_OUI_FROM_DATABASE=Nokia
OUI:CC8826*
ID_OUI_FROM_DATABASE=LG Innotek
+OUI:CC88C7*
+ ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+
+OUI:CC895E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:CC89FD*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:CC9916*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+OUI:CC9C3E*
+ ID_OUI_FROM_DATABASE=Cisco Meraki
+
OUI:CC9E00*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:CCD9E9*
ID_OUI_FROM_DATABASE=SCR Engineers Ltd.
+OUI:CCDB04*
+ ID_OUI_FROM_DATABASE=DataRemote Inc.
+
OUI:CCDB93*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:CCEA1C*
ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd
+OUI:CCED21*
+ ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd.
+
OUI:CCEDDC*
ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
OUI:D07C2D*
ID_OUI_FROM_DATABASE=Leie IOT technology Co., Ltd
+OUI:D07D33*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:D07DE5*
ID_OUI_FROM_DATABASE=Forward Pay Systems, Inc.
OUI:D096FB*
ID_OUI_FROM_DATABASE=DASAN Network Solutions
+OUI:D097FE*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:D099D5*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
OUI:D0CF5E*
ID_OUI_FROM_DATABASE=Energy Micro AS
+OUI:D0CFD8*
+ ID_OUI_FROM_DATABASE=Huizhou Boshijie Technology Co.,Ltd
+
OUI:D0D003*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD
OUI:D0DFC7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:D0E042*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:D0E140*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:D446E1*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:D4475A*
+ ID_OUI_FROM_DATABASE=ScreenBeam, Inc.
+
OUI:D4482D*
ID_OUI_FROM_DATABASE=Shenzhen Deejoy Lighting Technology Co.,Ltd.
OUI:D4772B*
ID_OUI_FROM_DATABASE=Nanjing Ztlink Network Technology Co.,Ltd
+OUI:D47798*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:D477B2*
ID_OUI_FROM_DATABASE=Netix Global B.V.
OUI:D858D7*
ID_OUI_FROM_DATABASE=CZ.NIC, z.s.p.o.
+OUI:D85982*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D85B2A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:D85DFB*
ID_OUI_FROM_DATABASE=Private
+OUI:D85ED3*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
OUI:D85F77*
ID_OUI_FROM_DATABASE=Telink Semiconductor (Shanghai) Co., Ltd.
OUI:D89A34*
ID_OUI_FROM_DATABASE=Beijing SHENQI Technology Co., Ltd.
+OUI:D89AC1*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:D89B3B*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:D8A315*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:D8A35C*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:D8A491*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:D8BB2C*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:D8BBC1*
+ ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD.
+
OUI:D8BC59*
ID_OUI_FROM_DATABASE=Shenzhen DAPU Microelectronics Co., Ltd
OUI:D8CC98*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:D8CD2C*
+ ID_OUI_FROM_DATABASE=WUXI NEIHUA NETWORK TECHNOLOGY CO., LTD
+
OUI:D8CE3A*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
ID_OUI_FROM_DATABASE=TCT mobile ltd
OUI:D8E72B*
- ID_OUI_FROM_DATABASE=NetAlly
+ ID_OUI_FROM_DATABASE=NETSCOUT SYSTEMS INC
OUI:D8E743*
ID_OUI_FROM_DATABASE=Wush, Inc
OUI:D8E952*
ID_OUI_FROM_DATABASE=KEOPSYS
+OUI:D8EB46*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:D8EB97*
ID_OUI_FROM_DATABASE=TRENDnet, Inc.
+OUI:D8EC5E*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
+
+OUI:D8ECE5*
+ ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+
OUI:D8ED1C*
ID_OUI_FROM_DATABASE=Magna Technology SL
OUI:DC0EA1*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+OUI:DC15C8*
+ ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
+
OUI:DC15DB*
ID_OUI_FROM_DATABASE=Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd.
OUI:DC2C26*
ID_OUI_FROM_DATABASE=Iton Technology Limited
+OUI:DC2D3C*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:DC2DCB*
ID_OUI_FROM_DATABASE=Beijing Unis HengYue Technology Co., Ltd.
OUI:DC86D8*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:DC87CB*
+ ID_OUI_FROM_DATABASE=Beijing Perfectek Technologies Co., Ltd.
+
OUI:DC8983*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:DCB082*
ID_OUI_FROM_DATABASE=Nokia
+OUI:DCB131*
+ ID_OUI_FROM_DATABASE=SHENZHEN HUARUIAN TECHNOLOGY CO.,LTD
+
OUI:DCB3B4*
ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd.
ID_OUI_FROM_DATABASE=Tiertime Corporation
OUI:DCE533A*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Amazinglayer Network Co., Ltd.
OUI:DCE533B*
ID_OUI_FROM_DATABASE=Tintel Hongkong Co.Ltd
OUI:E00C7F*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:E00CE5*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E00DB9*
ID_OUI_FROM_DATABASE=Cree, Inc.
OUI:E091F5*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:E0925C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:E092A7*
ID_OUI_FROM_DATABASE=Feitian Technologies Co., Ltd
OUI:E0D9E3*
ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd.
+OUI:E0DA90*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E0DADC*
ID_OUI_FROM_DATABASE=JVC KENWOOD Corporation
OUI:E0DB88*
ID_OUI_FROM_DATABASE=Open Standard Digital-IF Interface for SATCOM Systems
+OUI:E0DBD1*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:E0DCA0*
ID_OUI_FROM_DATABASE=Siemens Industrial Automation Products Ltd Chengdu
OUI:E0E2E6*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:E0E37C*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E0E5CF*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:E0E631*
ID_OUI_FROM_DATABASE=SNB TECHNOLOGIES LIMITED
+OUI:E0E656*
+ ID_OUI_FROM_DATABASE=Nethesis srl
+
OUI:E0E751*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:E0E7BB*
ID_OUI_FROM_DATABASE=Nureva, Inc.
+OUI:E0E8BB*
+ ID_OUI_FROM_DATABASE=Unicom Vsens Telecommunications Co., Ltd.
+
OUI:E0E8E6*
ID_OUI_FROM_DATABASE=Shenzhen C-Data Technology Co., Ltd.
ID_OUI_FROM_DATABASE=TomTom Software Ltd
OUI:E405F8*
- ID_OUI_FROM_DATABASE=Delta Innovation Technology Co., Ltd.
+ ID_OUI_FROM_DATABASE=Bytedance
OUI:E40EEE*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:E42771*
ID_OUI_FROM_DATABASE=Smartlabs
+OUI:E428A4*
+ ID_OUI_FROM_DATABASE=Prama India Private Limited
+
OUI:E42AD3*
ID_OUI_FROM_DATABASE=Magneti Marelli S.p.A. Powertrain
OUI:E44122*
ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd
+OUI:E44164*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:E441E6*
ID_OUI_FROM_DATABASE=Ottec Technology GmbH
OUI:E44E18*
ID_OUI_FROM_DATABASE=Gardasoft VisionLimited
+OUI:E44E2D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:E44E76*
ID_OUI_FROM_DATABASE=CHAMPIONTECH ENTERPRISE (SHENZHEN) INC
OUI:E454E8*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:E455A8*
+ ID_OUI_FROM_DATABASE=Cisco Meraki
+
OUI:E455EA*
ID_OUI_FROM_DATABASE=Dedicated Computing
OUI:E47723*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:E47727*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E4776B*
ID_OUI_FROM_DATABASE=AARTESYS AG
OUI:E4C806*
ID_OUI_FROM_DATABASE=Ceiec Electric Technology Inc.
+OUI:E4C90B*
+ ID_OUI_FROM_DATABASE=Radwin
+
OUI:E4CA12*
ID_OUI_FROM_DATABASE=zte corporation
OUI:E4F4C6*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:E4F75B*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:E4F7A1*
ID_OUI_FROM_DATABASE=Datafox GmbH
OUI:E4FC82*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:E4FD45*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:E4FDA1*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:E81CBA*
ID_OUI_FROM_DATABASE=Fortinet, Inc.
+OUI:E81CD8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:E81DA8*
ID_OUI_FROM_DATABASE=Ruckus Wireless
OUI:E84C56*
ID_OUI_FROM_DATABASE=INTERCEPT SERVICES LIMITED
+OUI:E84D74*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E84DD0*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:E84ECE*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:E84F25*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+
OUI:E84F4B*
ID_OUI_FROM_DATABASE=Shenzhen Delos Electronic Co., Ltd
OUI:E86A64*
ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd
+OUI:E86CC70*
+ ID_OUI_FROM_DATABASE=Trapeze Switzerland GmbH
+
+OUI:E86CC71*
+ ID_OUI_FROM_DATABASE=ASSA ABLOY(GuangZhou) Smart Technology Co., Ltd
+
+OUI:E86CC72*
+ ID_OUI_FROM_DATABASE=Xirgo Technologies LLC
+
+OUI:E86CC73*
+ ID_OUI_FROM_DATABASE=Shenzhen Yibaifen Industrial Co.,Ltd.
+
+OUI:E86CC74*
+ ID_OUI_FROM_DATABASE=Koal Software Co., Ltd
+
+OUI:E86CC75*
+ ID_OUI_FROM_DATABASE=Shenzhen Rongda Computer Co.,Ltd
+
+OUI:E86CC76*
+ ID_OUI_FROM_DATABASE=KLAB
+
+OUI:E86CC77*
+ ID_OUI_FROM_DATABASE=Huaqin Technology Co.,Ltd
+
+OUI:E86CC78*
+ ID_OUI_FROM_DATABASE=Lighthouse EIP
+
+OUI:E86CC79*
+ ID_OUI_FROM_DATABASE=Hangzhou Lanxum Security Technology Co., Ltd
+
+OUI:E86CC7A*
+ ID_OUI_FROM_DATABASE=CoxSpace
+
+OUI:E86CC7B*
+ ID_OUI_FROM_DATABASE=MORNSUN Guangzhou Science & Technology Co., Ltd.
+
+OUI:E86CC7C*
+ ID_OUI_FROM_DATABASE=Limited Liability Company M.S.Korp
+
+OUI:E86CC7D*
+ ID_OUI_FROM_DATABASE=z-max mediasolution
+
+OUI:E86CC7E*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
OUI:E86CDA*
ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center
ID_OUI_FROM_DATABASE=Toshiba
OUI:E89E0C*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=MAX8USA DISTRIBUTORS INC.
OUI:E89EB4*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:E89F39*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:E89F80*
ID_OUI_FROM_DATABASE=Belkin International Inc.
OUI:E8A4C1*
ID_OUI_FROM_DATABASE=Deep Sea Electronics Ltd
+OUI:E8A660*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E8A788*
ID_OUI_FROM_DATABASE=XIAMEN LEELEN TECHNOLOGY CO., LTD
OUI:E8E98E*
ID_OUI_FROM_DATABASE=SOLAR controls s.r.o.
+OUI:E8EA4D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E8EA6A*
ID_OUI_FROM_DATABASE=StarTech.com
OUI:E8F408*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:E8F654*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E8F724*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
OUI:E8FCAF*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:E8FD35*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E8FD72*
ID_OUI_FROM_DATABASE=SHANGHAI LINGUO TECHNOLOGY CO., LTD.
OUI:EC01EE*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:EC0273*
+ ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+
OUI:EC0441*
ID_OUI_FROM_DATABASE=ShenZhen TIGO Semiconductor Co., Ltd.
OUI:EC086B*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:EC0BAE*
+ ID_OUI_FROM_DATABASE=Hangzhou BroadLink Technology Co.,Ltd
+
OUI:EC0D9A*
ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc.
OUI:EC14F6*
ID_OUI_FROM_DATABASE=BioControl AS
+OUI:EC153D*
+ ID_OUI_FROM_DATABASE=Beijing Yaxunhongda Technology Co., Ltd.
+
OUI:EC172F*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:EC2E4E*
ID_OUI_FROM_DATABASE=HITACHI-LG DATA STORAGE INC
+OUI:EC2E98*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
OUI:EC3091*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:EC6264*
ID_OUI_FROM_DATABASE=Global411 Internet Services, LLC
+OUI:EC63D7*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:EC63E5*
ID_OUI_FROM_DATABASE=ePBoard Design LLC
OUI:ECB313*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+OUI:ECB4E8*
+ ID_OUI_FROM_DATABASE=Wistron Mexico SA de CV
+
OUI:ECB541*
ID_OUI_FROM_DATABASE=SHINANO E and E Co.Ltd.
OUI:ECB907*
ID_OUI_FROM_DATABASE=CloudGenix Inc
+OUI:ECB970*
+ ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD
+
OUI:ECBAFE*
ID_OUI_FROM_DATABASE=GIROPTIC
OUI:ECC57F*
ID_OUI_FROM_DATABASE=Suzhou Pairlink Network Technology
+OUI:ECC5D2*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:ECC882*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:F0007F*
ID_OUI_FROM_DATABASE=Janz - Contadores de Energia, SA
+OUI:F0016E*
+ ID_OUI_FROM_DATABASE=Tianyi Telecom Terminals Company Limited
+
OUI:F0022B*
ID_OUI_FROM_DATABASE=Chrontel
OUI:F0219D*
ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd.
+OUI:F021E0*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:F0224E*
ID_OUI_FROM_DATABASE=Esan electronic co.
ID_OUI_FROM_DATABASE=Shenzhen Lachesis Mhealth Co., Ltd.
OUI:F023B9D*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Shenyang Ali Technology Company Limited
OUI:F023B9E*
ID_OUI_FROM_DATABASE=Domotz Ltd
OUI:F02E51*
ID_OUI_FROM_DATABASE=Casa Systems
+OUI:F02F4B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F02F74*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
OUI:F0463B*
ID_OUI_FROM_DATABASE=Comcast Cable Corporation
+OUI:F04A02*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:F04A2B*
ID_OUI_FROM_DATABASE=PYRAMID Computer GmbH
OUI:F0620D*
ID_OUI_FROM_DATABASE=Shenzhen Egreat Tech Corp.,Ltd
+OUI:F0625A*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:F06281*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
OUI:F07765*
ID_OUI_FROM_DATABASE=Sourcefire, Inc
+OUI:F077C3*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:F077D0*
ID_OUI_FROM_DATABASE=Xcellen
OUI:F09CE9*
ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+OUI:F09E4A*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:F09E63*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:F0A35A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F0A3B2*
+ ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+
OUI:F0A764*
ID_OUI_FROM_DATABASE=GST Co., Ltd.
OUI:F0B107*
ID_OUI_FROM_DATABASE=Ericsson AB
+OUI:F0B11D*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:F0B2E5*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:F0CBA1*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F0D08C*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
OUI:F0D14F*
ID_OUI_FROM_DATABASE=LINEAR LLC
OUI:F0FEE7*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:F40223*
+ ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd.
+
+OUI:F40228*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+
OUI:F40270*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:F44156*
ID_OUI_FROM_DATABASE=Arrikto Inc.
+OUI:F4419E*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:F44227*
ID_OUI_FROM_DATABASE=S & S Research Inc.
OUI:F44450*
ID_OUI_FROM_DATABASE=BND Co., Ltd.
+OUI:F44588*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F445ED*
ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd.
OUI:F44E05*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F44EE3*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:F44EFD*
ID_OUI_FROM_DATABASE=Actions Semiconductor Co.,Ltd.(Cayman Islands)
OUI:F46ABC*
ID_OUI_FROM_DATABASE=Adonit Corp. Ltd.
+OUI:F46AD7*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
+OUI:F46B8C*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd.
+
OUI:F46BEF*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:F4A739*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:F4A80D*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
+
OUI:F4A997*
ID_OUI_FROM_DATABASE=CANON INC.
OUI:F4B164*
ID_OUI_FROM_DATABASE=Lightning Telecommunications Technology Co. Ltd
+OUI:F4B1C2*
+ ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
+
OUI:F4B301*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:F4BD9E*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F4BEEC*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F4BF80*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:F4C795*
- ID_OUI_FROM_DATABASE=WEY Elektronik AG
+ ID_OUI_FROM_DATABASE=WEY Technology AG
+
+OUI:F4C7AA*
+ ID_OUI_FROM_DATABASE=Marvell Semiconductors
OUI:F4C7C8*
ID_OUI_FROM_DATABASE=Kelvin Inc.
OUI:F4F951*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F4FBB8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F4FC32*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:F81897*
ID_OUI_FROM_DATABASE=2Wire Inc
+OUI:F81A2B*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:F81A67*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:F83DFF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:F83E95*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F83F51*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:F845AD*
ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+OUI:F845C4*
+ ID_OUI_FROM_DATABASE=Shenzhen Netforward Micro-Electronic Co., Ltd.
+
OUI:F8461C*
ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc.
OUI:F84ABF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:F84CDA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F84D33*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:F877B8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F8790A*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:F87A41*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:F884F2*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F885F9*
+ ID_OUI_FROM_DATABASE=Calix Inc.
+
OUI:F887F1*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:F8893C*
ID_OUI_FROM_DATABASE=Inventec Appliances Corp.
+OUI:F889D2*
+ ID_OUI_FROM_DATABASE=CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.
+
OUI:F88A3C0*
ID_OUI_FROM_DATABASE=ART SPA
OUI:F895EA*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F89753*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:F897CF*
ID_OUI_FROM_DATABASE=DAESHIN-INFORMATION TECHNOLOGY CO., LTD.
OUI:F8A9DE*
ID_OUI_FROM_DATABASE=PUISSANCE PLUS
+OUI:F8AA3F*
+ ID_OUI_FROM_DATABASE=DWnet Technologies(Suzhou) Corporation
+
OUI:F8AA8A*
ID_OUI_FROM_DATABASE=Axview Technology (Shenzhen) Co.,Ltd
OUI:F8AB05*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:F8ABE5*
+ ID_OUI_FROM_DATABASE=shenzhen worldelite electronics co., LTD
+
OUI:F8AC65*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:FC1349*
ID_OUI_FROM_DATABASE=Global Apps Corp.
+OUI:FC13F0*
+ ID_OUI_FROM_DATABASE=Bouffalo Lab (Nanjing) Co., Ltd.
+
OUI:FC1499*
ID_OUI_FROM_DATABASE=Aimore Acoustics Incorporation
OUI:FC335F*
ID_OUI_FROM_DATABASE=Polyera
+OUI:FC3497*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
OUI:FC3598*
ID_OUI_FROM_DATABASE=Favite Inc.
OUI:FC3FDB*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:FC4009*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:FC4203*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:FC4D8C*
ID_OUI_FROM_DATABASE=SHENZHEN PANTE ELECTRONICS TECHNOLOGY CO., LTD
+OUI:FC4DA6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:FC4DD4*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
+OUI:FC4EA4*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:FC5090*
ID_OUI_FROM_DATABASE=SIMEX Sp. z o.o.
OUI:FC55DC*
ID_OUI_FROM_DATABASE=Baltic Latvian Universal Electronics LLC
+OUI:FC584A*
+ ID_OUI_FROM_DATABASE=xiamenshi c-chip technology co., ltd
+
OUI:FC589A*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:FC9BC6*
ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd
+OUI:FC9C98*
+ ID_OUI_FROM_DATABASE=Arlo Technology
+
OUI:FC9DD8*
ID_OUI_FROM_DATABASE=Beijing TongTongYiLian Science and Technology Ltd.
OUI:FCA9B0*
ID_OUI_FROM_DATABASE=MIARTECH (SHANGHAI),INC.
+OUI:FCA9DC*
+ ID_OUI_FROM_DATABASE=Renesas Electronics (Penang) Sdn. Bhd.
+
OUI:FCAA14*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:FCE66A*
ID_OUI_FROM_DATABASE=Industrial Software Co
+OUI:FCE806*
+ ID_OUI_FROM_DATABASE=Edifier International
+
OUI:FCE892*
ID_OUI_FROM_DATABASE=Hangzhou Lancable Technology Co.,Ltd
acpi:TGV*:
ID_VENDOR_FROM_DATABASE=Grass Valley Germany GmbH
+acpi:TGW*:
+ ID_VENDOR_FROM_DATABASE=TECHNOGYM S.p.A.
+
acpi:THN*:
ID_VENDOR_FROM_DATABASE=Thundercom Holdings Sdn. Bhd.
---- 20-acpi-vendor.hwdb.base 2020-11-26 13:49:35.243482590 +0100
-+++ 20-acpi-vendor.hwdb 2020-11-26 13:49:35.260482675 +0100
+--- 20-acpi-vendor.hwdb.base 2021-02-12 15:42:10.664053745 +0100
++++ 20-acpi-vendor.hwdb 2021-02-12 15:42:10.706054210 +0100
@@ -3,6 +3,8 @@
# Data imported from:
# https://uefi.org/uefi-pnp-export
acpi:TEZ*:
ID_VENDOR_FROM_DATABASE=Tech Source Inc.
-@@ -6760,9 +6828,6 @@
+@@ -6763,9 +6831,6 @@
acpi:TNC*:
ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd
acpi:TNM*:
ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA
-@@ -7069,14 +7134,14 @@
+@@ -7072,14 +7137,14 @@
acpi:UNC*:
ID_VENDOR_FROM_DATABASE=Unisys Corporation
acpi:UNI*:
ID_VENDOR_FROM_DATABASE=Uniform Industry Corp.
-@@ -7111,6 +7176,9 @@
+@@ -7114,6 +7179,9 @@
acpi:USA*:
ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG
acpi:USD*:
ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation
-@@ -7357,9 +7425,6 @@
+@@ -7360,9 +7428,6 @@
acpi:WAL*:
ID_VENDOR_FROM_DATABASE=Wave Access
acpi:WAV*:
ID_VENDOR_FROM_DATABASE=Wavephore
-@@ -7484,7 +7549,7 @@
+@@ -7487,7 +7552,7 @@
ID_VENDOR_FROM_DATABASE=WyreStorm Technologies LLC
acpi:WYS*:
acpi:WYT*:
ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd.
-@@ -7498,9 +7563,6 @@
+@@ -7501,9 +7566,6 @@
acpi:XDM*:
ID_VENDOR_FROM_DATABASE=XDM Ltd.
acpi:XES*:
ID_VENDOR_FROM_DATABASE=Extreme Engineering Solutions, Inc.
-@@ -7531,9 +7593,6 @@
+@@ -7534,9 +7596,6 @@
acpi:XNT*:
ID_VENDOR_FROM_DATABASE=XN Technologies, Inc.
acpi:XQU*:
ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD
-@@ -7600,6 +7659,9 @@
+@@ -7603,6 +7662,9 @@
acpi:ZBX*:
ID_VENDOR_FROM_DATABASE=Zebax Technologies
ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA)
pci:v00001000d000000B2*
- ID_MODEL_FROM_DATABASE=PEX880xx PCIe Gen 4 Switch SES management endpoint
+ ID_MODEL_FROM_DATABASE=PCIe Switch management endpoint
+
+pci:v00001000d000000B2sv00001D49sd00000003*
+ ID_MODEL_FROM_DATABASE=PCIe Switch management endpoint (ThinkSystem 1611-8P PCIe Gen4 NVMe Switch Adapter)
pci:v00001000d000000BE*
ID_MODEL_FROM_DATABASE=SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC)
pci:v00001000d00006001*
ID_MODEL_FROM_DATABASE=DX1 Multiformat Broadcast HD/SD Encoder/Decoder
+pci:v00001000d0000C012*
+ ID_MODEL_FROM_DATABASE=PEX880xx PCIe Gen 4 Switch
+
+pci:v00001000d0000C012sv00001D49sd00000003*
+ ID_MODEL_FROM_DATABASE=PEX880xx PCIe Gen 4 Switch (ThinkSystem 1611-8P PCIe Gen4 NVMe Switch Adapter)
+
pci:v00001001*
ID_VENDOR_FROM_DATABASE=Kolter Electronic
pci:v00001002d0000154C*
ID_MODEL_FROM_DATABASE=Kryptos [Radeon RX 350]
+pci:v00001002d0000154Csv00001462sd00007C28*
+ ID_MODEL_FROM_DATABASE=Kryptos [Radeon RX 350] (MS-7C28 Motherboard)
+
pci:v00001002d0000154E*
ID_MODEL_FROM_DATABASE=Garfield
pci:v00001002d000015D8sv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Picasso (ThinkPad E595)
+pci:v00001002d000015D8sv0000EA50sd0000CC10*
+ ID_MODEL_FROM_DATABASE=Picasso (RXi2-BP)
+
pci:v00001002d000015DD*
ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series]
pci:v00001002d000015DDsv0000103Csd000083C6*
ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon Vega 8 Mobile)
+pci:v00001002d000015DDsv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (PRIME Motherboard)
+
pci:v00001002d000015DDsv00001458sd0000D000*
ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon RX Vega 11)
+pci:v00001002d000015DDsv0000EA50sd0000CC10*
+ ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (RXi2-BP)
+
pci:v00001002d000015DE*
ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller
pci:v00001002d000015DEsv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller (Pavilion Laptop 15-cw1xxx)
+pci:v00001002d000015DEsv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller (PRIME B450M-A Motherboard)
+
pci:v00001002d000015DEsv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller (ThinkPad E595)
+pci:v00001002d000015DEsv0000EA50sd0000CC10*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller (RXi2-BP)
+
pci:v00001002d000015DF*
ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor
pci:v00001002d000015DFsv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor (Pavilion Laptop 15-cw1xxx)
+pci:v00001002d000015DFsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor (mCOM10-L1900)
+
pci:v00001002d000015FF*
ID_MODEL_FROM_DATABASE=Fenghuang [Zhongshan Subor Z+]
pci:v00001002d00001636*
ID_MODEL_FROM_DATABASE=Renoir
+pci:v00001002d00001638*
+ ID_MODEL_FROM_DATABASE=Cezanne
+
+pci:v00001002d0000163F*
+ ID_MODEL_FROM_DATABASE=VanGogh
+
+pci:v00001002d0000164C*
+ ID_MODEL_FROM_DATABASE=Lucienne
+
pci:v00001002d00001714*
ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series]
pci:v00001002d00004383sv00001458sd0000A102*
ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (GA-880GMA-USB3)
+pci:v00001002d00004383sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004383sv000017F2sd00005000*
ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (KI690-AM2 Motherboard)
pci:v00001002d00004385sv00001462sd00007368*
ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (K9AG Neo2)
+pci:v00001002d00004385sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004385sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (H8DGU)
pci:v00001002d00004390sv00001458sd0000B002*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (GA-MA770-DS3rev2.0 Motherboard)
+pci:v00001002d00004390sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004390sv00001849sd00004390*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (Motherboard (one of many))
pci:v00001002d00004396sv00001458sd00005004*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (GA-880GMA-USB3)
+pci:v00001002d00004396sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004396sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (H8DGU)
pci:v00001002d00004397sv00001458sd00005004*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (GA-880GMA-USB3)
+pci:v00001002d00004397sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004397sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (H8DGU)
pci:v00001002d00004398sv0000105Bsd00000E13*
ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (N15235/A74MX mainboard / AMD SB700)
+pci:v00001002d00004398sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004398sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (H8DGU)
pci:v00001002d00004399sv00001458sd00005004*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (GA-880GMA-USB3)
+pci:v00001002d00004399sv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00004399sv0000174Bsd00001001*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (PURE Fusion Mini)
pci:v00001002d0000439Csv0000105Bsd00000E13*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (N15235/A74MX mainboard / AMD SB700)
+pci:v00001002d0000439Csv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d0000439D*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller
pci:v00001002d0000439Dsv0000105Bsd00000E13*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (N15235/A74MX mainboard / AMD SB700)
+pci:v00001002d0000439Dsv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d0000439Dsv0000174Bsd00001001*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (PURE Fusion Mini)
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE / TD / 128M)
pci:v00001002d00005964sv00001458sd00004018*
- ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE)
+ ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (R92S128T (Radeon 9200 SE 128MB))
pci:v00001002d00005964sv00001458sd00004032*
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE 128MB)
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary)
pci:v00001002d00005D44sv00001458sd00004019*
- ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE (Secondary))
+ ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (R92S128T (Radeon 9200 SE 128MB Secondary))
pci:v00001002d00005D44sv00001458sd00004032*
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE 128MB)
pci:v00001002d00006608sv000013CCsd00003D28*
ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100] (MXRT-2600)
+pci:v00001002d00006609*
+ ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100 / Barco MXRT 2600]
+
pci:v00001002d00006610*
ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350]
ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Instinct]
pci:v00001002d000066A1*
- ID_MODEL_FROM_DATABASE=Vega 20
+ ID_MODEL_FROM_DATABASE=Vega 20 WKS GL-XE [Radeon Pro VII]
pci:v00001002d000066A2*
ID_MODEL_FROM_DATABASE=Vega 20
pci:v00001002d000066A3*
- ID_MODEL_FROM_DATABASE=Vega 20
+ ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Pro Vega II/Radeon Pro Vega II Duo]
pci:v00001002d000066A7*
ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Pro Vega 20]
pci:v00001002d000067B1sv0000174Bsd0000E324*
ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290/390] (Sapphire Nitro R9 390)
+pci:v00001002d000067B8*
+ ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X Engineering Sample]
+
pci:v00001002d000067B9*
ID_MODEL_FROM_DATABASE=Vesuvius [Radeon R9 295X2]
pci:v00001002d000067DFsv00001462sd0000341E*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570 Armor 4G OC)
+pci:v00001002d000067DFsv00001462sd0000809E*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480 4GB)
+
pci:v00001002d000067DFsv00001462sd00008A92*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580)
pci:v00001002d000067DFsv00001682sd00009480*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480)
+pci:v00001002d000067DFsv00001682sd00009587*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 590 FATBOY 8GB)
+
pci:v00001002d000067DFsv00001682sd00009588*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580 XTR)
pci:v00001002d00006868*
ID_MODEL_FROM_DATABASE=Vega 10 [Radeon PRO WX 8100/8200]
+pci:v00001002d00006869*
+ ID_MODEL_FROM_DATABASE=Vega 10 XGA [Radeon Pro Vega 48]
+
+pci:v00001002d0000686A*
+ ID_MODEL_FROM_DATABASE=Vega 10 LEA
+
+pci:v00001002d0000686B*
+ ID_MODEL_FROM_DATABASE=Vega 10 XTXA [Radeon Pro Vega 64X]
+
pci:v00001002d0000686C*
ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25 MxGPU]
+pci:v00001002d0000686D*
+ ID_MODEL_FROM_DATABASE=Vega 10 GLXTA
+
+pci:v00001002d0000686E*
+ ID_MODEL_FROM_DATABASE=Vega 10 GLXLA
+
pci:v00001002d0000687F*
ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64]
pci:v00001002d0000687Fsv00001458sd0000230C*
ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (Radeon RX VEGA 56 GAMING OC 8G)
+pci:v00001002d0000687Fsv00001DA2sd0000E376*
+ ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (Radeon RX VEGA 56 Pulse 8GB OC HBM2)
+
pci:v00001002d00006880*
ID_MODEL_FROM_DATABASE=Lexington [Radeon HD 6550M]
pci:v00001002d000068DA*
ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570]
+pci:v00001002d000068DAsv00001462sd00008071*
+ ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (VR5550-MD1G (Radeon HD 5550))
+
pci:v00001002d000068DAsv0000148Csd00003000*
ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390)
pci:v00001002d0000731Fsv00001458sd00002313*
ID_MODEL_FROM_DATABASE=Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT] (Radeon RX 5700 XT Gaming OC)
+pci:v00001002d0000731Fsv00001682sd00005701*
+ ID_MODEL_FROM_DATABASE=Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT] (RX 5700 XT RAW II)
+
pci:v00001002d0000731Fsv00001DA2sd0000E411*
ID_MODEL_FROM_DATABASE=Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT] (Radeon RX 5600 XT)
pci:v00001002d00007360*
ID_MODEL_FROM_DATABASE=Navi 12 [Radeon Pro 5600M]
+pci:v00001002d00007388*
+ ID_MODEL_FROM_DATABASE=Arcturus GL-XL
+
+pci:v00001002d0000738C*
+ ID_MODEL_FROM_DATABASE=Arcturus GL-XL [AMD Instinct MI100]
+
+pci:v00001002d0000738E*
+ ID_MODEL_FROM_DATABASE=Arcturus GL-XL
+
pci:v00001002d000073BF*
ID_MODEL_FROM_DATABASE=Navi 21 [Radeon RX 6800/6800 XT / 6900 XT]
+pci:v00001002d000073BFsv00001EAEsd00006701*
+ ID_MODEL_FROM_DATABASE=Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] (XFX Speedster MERC 319 AMD Radeon RX 6800 XT Black)
+
pci:v00001002d000073C3*
ID_MODEL_FROM_DATABASE=Navi 22
pci:v00001002d000073DF*
ID_MODEL_FROM_DATABASE=Navi 22
+pci:v00001002d000073E0*
+ ID_MODEL_FROM_DATABASE=Navi 23
+
pci:v00001002d000073FF*
ID_MODEL_FROM_DATABASE=Navi 23
pci:v00001002d0000960F*
ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300]
+pci:v00001002d0000960Fsv00001462sd00007596*
+ ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300] (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00009610*
ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200]
pci:v00001002d00009616*
ID_MODEL_FROM_DATABASE=RS780L [Radeon 3000]
+pci:v00001002d00009616sv00001462sd00007501*
+ ID_MODEL_FROM_DATABASE=RS780L [Radeon 3000] (760GM-E51(MS-7596) Motherboard)
+
pci:v00001002d00009640*
ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6550D]
pci:v00001002d00009830*
ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400 / R3 Series]
+pci:v00001002d00009830sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400 / R3 Series] (AM1I-A Motherboard)
+
pci:v00001002d00009831*
ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400E]
pci:v00001002d00009840*
ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio
+pci:v00001002d00009840sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio (AM1I-A Motherboard)
+
pci:v00001002d00009840sv00001849sd00009840*
ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio (QC5000-ITX/PH)
pci:v00001022d00001452*
ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge
+pci:v00001022d00001452sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge (mCOM10-L1900)
+
pci:v00001022d00001453*
ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) PCIe GPP Bridge
pci:v00001022d0000149Csv00001462sd00007C37*
ID_MODEL_FROM_DATABASE=Matisse USB 3.0 Host Controller (X570-A PRO motherboard)
+pci:v00001022d0000149D*
+ ID_MODEL_FROM_DATABASE=Vangogh CVIP
+
pci:v00001022d00001510*
ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex
pci:v00001022d00001536*
ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex
+pci:v00001022d00001536sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex (AM1I-A Motherboard)
+
pci:v00001022d00001536sv00001849sd00001536*
ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex (QC5000-ITX/PH)
pci:v00001022d000015D0sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven/Raven2 Root Complex (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d000015D0sv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2 Root Complex (PRIME B450M-A Motherboard)
+
pci:v00001022d000015D1*
ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU
pci:v00001022d000015D1sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d000015D1sv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU (PRIME B450M-A Motherboard)
+
+pci:v00001022d000015D1sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU (mCOM10-L1900)
+
pci:v00001022d000015D2*
ID_MODEL_FROM_DATABASE=Raven/Raven2 PCIe Dummy Host Bridge
pci:v00001022d000015DB*
ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A
+pci:v00001022d000015DBsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A (mCOM10-L1900)
+
pci:v00001022d000015DC*
ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B
+pci:v00001022d000015DCsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B (mCOM10-L1900)
+
pci:v00001022d000015DE*
ID_MODEL_FROM_DATABASE=Raven/Raven2/FireFlight HD Audio Controller
pci:v00001022d000015DF*
ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) Platform Security Processor
+pci:v00001022d000015DFsv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) Platform Security Processor (PRIME Motherboard)
+
pci:v00001022d000015DFsv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) Platform Security Processor (ThinkPad E595)
+pci:v00001022d000015DFsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) Platform Security Processor (mCOM10-L1900)
+
pci:v00001022d000015E0*
ID_MODEL_FROM_DATABASE=Raven USB 3.1
pci:v00001022d000015E0sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven USB 3.1 (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d000015E0sv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven USB 3.1 (PRIME Motherboard)
+
pci:v00001022d000015E0sv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Raven USB 3.1 (ThinkPad E595)
+pci:v00001022d000015E0sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven USB 3.1 (mCOM10-L1900)
+
pci:v00001022d000015E1*
ID_MODEL_FROM_DATABASE=Raven USB 3.1
pci:v00001022d000015E1sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Raven USB 3.1 (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d000015E1sv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=Raven USB 3.1 (PRIME Motherboard)
+
pci:v00001022d000015E1sv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Raven USB 3.1 (ThinkPad E595)
+pci:v00001022d000015E1sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=Raven USB 3.1 (mCOM10-L1900)
+
pci:v00001022d000015E2*
ID_MODEL_FROM_DATABASE=Raven/Raven2/FireFlight/Renoir Audio Processor
pci:v00001022d000015E3sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) HD Audio Controller (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d000015E3sv00001043sd000086C7*
+ ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) HD Audio Controller (PRIME B450M-A Motherboard)
+
pci:v00001022d000015E3sv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) HD Audio Controller (ThinkPad E595)
pci:v00001022d00001644*
ID_MODEL_FROM_DATABASE=Renoir I2S
+pci:v00001022d00001648*
+ ID_MODEL_FROM_DATABASE=VanGogh Root Complex
+
+pci:v00001022d00001649*
+ ID_MODEL_FROM_DATABASE=VanGogh PSP/CCP
+
pci:v00001022d00001700*
ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 0
pci:v00001022d00007801sv0000103Csd0000194E*
ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (ProBook 455 G1 Notebook)
+pci:v00001022d00007801sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (AM1I-A Motherboard)
+
pci:v00001022d00007801sv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (Z50-75)
pci:v00001022d00007807sv0000103Csd00001985*
ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (Pavilion 17-e163sg Notebook PC)
+pci:v00001022d00007807sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (AM1I-A Motherboard)
+
pci:v00001022d00007807sv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (Z50-75)
pci:v00001022d00007808sv0000103Csd00001985*
ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (Pavilion 17-e163sg Notebook PC)
+pci:v00001022d00007808sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (AM1I-A Motherboard)
+
pci:v00001022d00007808sv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (Z50-75)
pci:v00001022d0000780Bsv0000103Csd00001985*
ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Pavilion 17-e163sg Notebook PC)
+pci:v00001022d0000780Bsv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH SMBus Controller (AM1I-A Motherboard)
+
pci:v00001022d0000780Bsv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Z50-75)
pci:v00001022d0000780Dsv00001043sd00008444*
ID_MODEL_FROM_DATABASE=FCH Azalia Controller (F2A85-M Series)
+pci:v00001022d0000780Dsv00001043sd00008576*
+ ID_MODEL_FROM_DATABASE=FCH Azalia Controller (AM1I-A Motherboard)
+
pci:v00001022d0000780Dsv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH Azalia Controller (Z50-75)
pci:v00001022d0000780Esv0000103Csd00001985*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Pavilion 17-e163sg Notebook PC)
+pci:v00001022d0000780Esv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH LPC Bridge (AM1I-A Motherboard)
+
pci:v00001022d0000780Esv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Z50-75)
pci:v00001022d00007814sv0000103Csd00001985*
ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (Pavilion 17-e163sg Notebook PC)
+pci:v00001022d00007814sv00001043sd00008623*
+ ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (AM1I-A Motherboard)
+
pci:v00001022d00007814sv000017AAsd00003988*
ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (Z50-75)
pci:v00001022d00007901sv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d00007901sv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (PRIME Motherboard)
+
pci:v00001022d00007901sv00001462sd00007C37*
ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (X570-A PRO motherboard)
+pci:v00001022d00007901sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (mCOM10-L1900)
+
pci:v00001022d00007902*
ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode]
pci:v00001022d0000790Bsv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d0000790Bsv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=FCH SMBus Controller (PRIME Motherboard)
+
pci:v00001022d0000790Bsv00001462sd00007C37*
ID_MODEL_FROM_DATABASE=FCH SMBus Controller (X570-A PRO motherboard)
pci:v00001022d0000790Bsv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=FCH SMBus Controller (ThinkPad E595)
+pci:v00001022d0000790Bsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=FCH SMBus Controller (mCOM10-L1900)
+
pci:v00001022d0000790E*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge
pci:v00001022d0000790Esv0000103Csd00008615*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Pavilion Laptop 15-cw1xxx)
+pci:v00001022d0000790Esv00001043sd0000876B*
+ ID_MODEL_FROM_DATABASE=FCH LPC Bridge (PRIME B450M-A Motherboard)
+
pci:v00001022d0000790Esv00001462sd00007C37*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge (X570-A PRO motherboard)
pci:v00001022d0000790Esv000017AAsd00005124*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge (ThinkPad E595)
+pci:v00001022d0000790Esv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=FCH LPC Bridge (mCOM10-L1900)
+
pci:v00001022d0000790F*
ID_MODEL_FROM_DATABASE=FCH PCI Bridge
pci:v00001033d00000035sv0000807Dsd00000035*
ID_MODEL_FROM_DATABASE=OHCI USB Controller (PCI-USB2 (OHCI subsystem))
+pci:v00001033d00000035sv00008086sd00004D44*
+ ID_MODEL_FROM_DATABASE=OHCI USB Controller (D850EMV2 motherboard)
+
pci:v00001033d0000003B*
ID_MODEL_FROM_DATABASE=PCI to C-bus Bridge
pci:v00001033d000000E0sv0000807Dsd00001043*
ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (PCI-USB2 (EHCI subsystem))
+pci:v00001033d000000E0sv00008086sd00004D44*
+ ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (D850EMV2 motherboard)
+
pci:v00001033d000000E7*
ID_MODEL_FROM_DATABASE=uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller
pci:v00001077d00002031sv0000103Csd00008002*
ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (3830C 16G Fibre Channel Host Bus Adapter)
+pci:v00001077d00002031sv00001077sd00000241*
+ ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (QLE2670 16Gb Single Port Fibre Channel Adapter)
+
pci:v00001077d00002071*
ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter
pci:v00001077d00002081sv00001077sd000002E3*
ID_MODEL_FROM_DATABASE=ISP2814-based 64/32G Fibre Channel to PCIe Controller (QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter)
+pci:v00001077d00002089*
+ ID_MODEL_FROM_DATABASE=ISP2854-based 64/32G Fibre Channel to PCIe Controller with StorCryption
+
+pci:v00001077d00002089sv00001077sd000002E8*
+ ID_MODEL_FROM_DATABASE=ISP2854-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2884 Quad Port 64GFC PCIe Gen4 x16 Adapter with StorCryption)
+
+pci:v00001077d00002089sv00001077sd000002EA*
+ ID_MODEL_FROM_DATABASE=ISP2854-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2784 Quad Port 32GFC PCIe Gen4 x16 Adapter with StorCryption)
+
pci:v00001077d00002100*
ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter
pci:v00001077d00002261sv00001590sd0000022D*
ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (5830C 32Gb Dual Port Fibre Channel Adapter)
+pci:v00001077d00002261sv0000193Dsd0000100D*
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (NIC-FC680i-Mb-2x16G)
+
pci:v00001077d00002281*
ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller
pci:v00001077d00002281sv00001590sd000002D4*
ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (SN1610Q – 2P Enhanced 32GFC Dual Port Fibre Channel Host Bus Adapter)
+pci:v00001077d00002289*
+ ID_MODEL_FROM_DATABASE=ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption
+
+pci:v00001077d00002289sv00001077sd000002E9*
+ ID_MODEL_FROM_DATABASE=ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2882 Dual Port 64GFC PCIe Gen4 x8 Adapter with StorCryption)
+
+pci:v00001077d00002289sv00001077sd000002EB*
+ ID_MODEL_FROM_DATABASE=ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2782 Dual Port 32GFC PCIe Gen4 x8 Adapter with StorCryption)
+
+pci:v00001077d00002289sv00001077sd000002EF*
+ ID_MODEL_FROM_DATABASE=ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2880 Single Port 64GFC PCIe Gen4 x8 Adapter with StorCryption)
+
+pci:v00001077d00002289sv00001077sd000002F1*
+ ID_MODEL_FROM_DATABASE=ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption (QLE2780 Single Port 32GFC PCIe Gen4 x8 Adapter with StorCryption)
+
pci:v00001077d00002300*
ID_MODEL_FROM_DATABASE=QLA2300 64-bit Fibre Channel Adapter
pci:v00001077d00008070sv00001590sd000002BD*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10Gb 2P 524SFP+ NIC)
+pci:v00001077d00008070sv0000193Dsd00001030*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (NIC-ETH681i-Mb-2x25G)
+
+pci:v00001077d00008070sv0000193Dsd00001032*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (NIC-ETH682i-Mb-2x25G)
+
pci:v00001077d00008080*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE)
pci:v000010B5d00009050sv000010B5sd00009050*
ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCI-I04 PCI Passive PC/CAN Interface)
+pci:v000010B5d00009050sv000012FEsd00000001*
+ ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (CAN-PCI/331 CAN bus controller)
+
pci:v000010B5d00009050sv00001369sd00008901*
ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX11+ PCI)
pci:v000010DEd00000A23*
ID_MODEL_FROM_DATABASE=GT216 [GeForce 210]
+pci:v000010DEd00000A24*
+ ID_MODEL_FROM_DATABASE=GT216 [GeForce 405]
+
pci:v000010DEd00000A26*
ID_MODEL_FROM_DATABASE=GT216 [GeForce 405]
pci:v000010DEd00001AED*
ID_MODEL_FROM_DATABASE=TU116 USB Type-C UCSI Controller
+pci:v000010DEd00001AEF*
+ ID_MODEL_FROM_DATABASE=GA102 High Definition Audio Controller
+
pci:v000010DEd00001B00*
ID_MODEL_FROM_DATABASE=GP102 [TITAN X]
pci:v000010DEd00001B38*
ID_MODEL_FROM_DATABASE=GP102GL [Tesla P40]
+pci:v000010DEd00001B39*
+ ID_MODEL_FROM_DATABASE=GP102GL [Tesla P10]
+
pci:v000010DEd00001B70*
ID_MODEL_FROM_DATABASE=GP102GL
ID_MODEL_FROM_DATABASE=GP106GL [Quadro P2200]
pci:v000010DEd00001C35*
- ID_MODEL_FROM_DATABASE=GP106
+ ID_MODEL_FROM_DATABASE=GP106M [Quadro P2000 Mobile]
pci:v000010DEd00001C36*
- ID_MODEL_FROM_DATABASE=GP106
+ ID_MODEL_FROM_DATABASE=GP106 [P106M]
pci:v000010DEd00001C60*
ID_MODEL_FROM_DATABASE=GP106BM [GeForce GTX 1060 Mobile 6GB]
pci:v000010DEd00001F9C*
ID_MODEL_FROM_DATABASE=TU117M [GeForce MX450]
+pci:v000010DEd00001F9D*
+ ID_MODEL_FROM_DATABASE=TU117M [GeForce GTX 1650 Mobile / Max-Q]
+
pci:v000010DEd00001FAE*
ID_MODEL_FROM_DATABASE=TU117GL
pci:v000010DEd00001FB9*
ID_MODEL_FROM_DATABASE=TU117GLM [Quadro T1000 Mobile]
+pci:v000010DEd00001FBB*
+ ID_MODEL_FROM_DATABASE=TU117GLM [Quadro T500 Mobile]
+
pci:v000010DEd00001FBF*
ID_MODEL_FROM_DATABASE=TU117GL
pci:v000010DEd000020B1*
ID_MODEL_FROM_DATABASE=GA100 [A100 PCIe 40GB]
+pci:v000010DEd000020B2*
+ ID_MODEL_FROM_DATABASE=GA100 [A100 SXM4 80GB]
+
pci:v000010DEd000020BE*
ID_MODEL_FROM_DATABASE=GA100 [GRID A100A]
pci:v000010DEd000021BF*
ID_MODEL_FROM_DATABASE=TU116GL
+pci:v000010DEd000021C2*
+ ID_MODEL_FROM_DATABASE=TU116
+
pci:v000010DEd000021C4*
ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1660 SUPER]
pci:v000010DEd00002204*
ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3090]
+pci:v000010DEd00002205*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080 Ti]
+
pci:v000010DEd00002206*
ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080]
+pci:v000010DEd00002206sv000010DEsd00001467*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080]
+
pci:v000010DEd00002206sv000010DEsd0000146D*
ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080] (GA102 [GeForce RTX 3080 20GB])
pci:v000010DEd00002230*
ID_MODEL_FROM_DATABASE=GA102GL [RTX A6000]
+pci:v000010DEd00002235*
+ ID_MODEL_FROM_DATABASE=GA102GL [RTX A40]
+
+pci:v000010DEd00002236*
+ ID_MODEL_FROM_DATABASE=GA102GL
+
pci:v000010DEd0000223F*
ID_MODEL_FROM_DATABASE=GA102GL
+pci:v000010DEd0000228B*
+ ID_MODEL_FROM_DATABASE=GA104 High Definition Audio Controller
+
+pci:v000010DEd00002321*
+ ID_MODEL_FROM_DATABASE=GA103
+
pci:v000010DEd00002482*
ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Ti]
ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3060 Ti]
pci:v000010DEd0000249C*
- ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile / Max-Q 8GB/16GB]
+ ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3080 Mobile / Max-Q 8GB/16GB]
pci:v000010DEd0000249D*
ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile / Max-Q]
+pci:v000010DEd0000249F*
+ ID_MODEL_FROM_DATABASE=GA104M
+
pci:v000010DEd000024AC*
ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 30x0 Engineering Sample]
pci:v000010DEd000024AF*
ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Engineering Sample]
+pci:v000010DEd000024B6*
+ ID_MODEL_FROM_DATABASE=GA104
+
+pci:v000010DEd000024B8*
+ ID_MODEL_FROM_DATABASE=GA104
+
pci:v000010DEd000024BF*
ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Engineering Sample]
pci:v000010DEd000024DC*
- ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile 16GB]
+ ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3080 Mobile / Max-Q 8GB/16GB]
pci:v000010DEd000024DD*
ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile / Max-Q]
+pci:v000010DEd00002501*
+ ID_MODEL_FROM_DATABASE=GA106 [GeForce RTX 3060]
+
+pci:v000010DEd00002503*
+ ID_MODEL_FROM_DATABASE=GA106 [GeForce RTX 3060]
+
+pci:v000010DEd00002505*
+ ID_MODEL_FROM_DATABASE=GA106
+
+pci:v000010DEd00002520*
+ ID_MODEL_FROM_DATABASE=GA106M [GeForce RTX 3060 Mobile / Max-Q]
+
pci:v000010DEd0000252F*
ID_MODEL_FROM_DATABASE=GA106 [GeForce RTX 3060 Engineering Sample]
+pci:v000010DEd00002560*
+ ID_MODEL_FROM_DATABASE=GA106M [GeForce RTX 3060 Mobile / Max-Q]
+
+pci:v000010DEd00002583*
+ ID_MODEL_FROM_DATABASE=GA107 [GeForce RTX 3050]
+
+pci:v000010DEd000025A2*
+ ID_MODEL_FROM_DATABASE=GA107
+
+pci:v000010DEd000025A4*
+ ID_MODEL_FROM_DATABASE=GA107
+
pci:v000010DEd000025AF*
ID_MODEL_FROM_DATABASE=GA107 [GeForce RTX 3050 Engineering Sample]
pci:v000010DFd0000E300sv00001590sd0000022E*
ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (Synergy 5330C 2-Port 32Gb Fibre Channel Mezz Card)
+pci:v000010DFd0000E300sv0000193Dsd00001060*
+ ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (NIC-FC730i-Mb-2P)
+
pci:v000010DFd0000F011*
ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter
pci:v000010DFd0000F400sv00001590sd000002D6*
ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (StoreFabric SN1610E 2-Port 32Gb Fibre Channel Adapter)
+pci:v000010DFd0000F500*
+ ID_MODEL_FROM_DATABASE=LPe37000/LPe38000 Series 32Gb/64Gb Fibre Channel Adapter
+
pci:v000010DFd0000F700*
ID_MODEL_FROM_DATABASE=LP7000 Fibre Channel Host Adapter
pci:v000010ECd00000139*
ID_MODEL_FROM_DATABASE=RTL-8139/8139C/8139C+ Ethernet Controller
+pci:v000010ECd00003000*
+ ID_MODEL_FROM_DATABASE=Killer E3000 2.5GbE Controller
+
pci:v000010ECd00005208*
ID_MODEL_FROM_DATABASE=RTS5208 PCI Express Card Reader
pci:v000010ECd0000525Asv00001028sd000006E4*
ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (XPS 15 9550)
+pci:v000010ECd0000525Asv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (Latitude 11 5175 2-in-1)
+
pci:v000010ECd0000525Asv000017AAsd0000224F*
ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (ThinkPad X1 Carbon 5th Gen)
pci:v000010ECd00008139sv0000A0A0sd00000007*
ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325C)
+pci:v000010ECd00008161*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
+
+pci:v000010ECd00008161sv000010ECsd00008168*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (TP-Link TG-3468 v4.0 Gigabit PCI Express Network Adapter)
+
pci:v000010ECd00008167*
ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet
pci:v000010ECd00008168sv00001043sd00008505*
ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P8 series motherboard)
+pci:v000010ECd00008168sv00001043sd00008554*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (H81M-C Motherboard)
+
+pci:v000010ECd00008168sv00001043sd0000859E*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (AM1I-A Motherboard)
+
+pci:v000010ECd00008168sv00001043sd00008677*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (PRIME B450M-A Motherboard)
+
pci:v000010ECd00008168sv0000105Bsd00000D7C*
ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (D270S/D250S Motherboard)
pci:v000010ECd00008168sv00001775sd000011CC*
ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (CC11/CL11)
+pci:v000010ECd00008168sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (ThinkCentre E73)
+
pci:v000010ECd00008168sv000017AAsd00003814*
ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Z50-75)
pci:v000010ECd00008168sv00008086sd0000D615*
ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Desktop Board D510MO/D525MW)
+pci:v000010ECd00008168sv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (mCOM10-L1900)
+
pci:v000010ECd00008169*
ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller
pci:v000010ECd00008169sv0000A0A0sd00000449*
ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (AK86-L motherboard)
+pci:v000010ECd0000816A*
+ ID_MODEL_FROM_DATABASE=RTL8111xP UART #1
+
+pci:v000010ECd0000816Asv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=RTL8111xP UART #1 (mCOM10-L1900)
+
+pci:v000010ECd0000816B*
+ ID_MODEL_FROM_DATABASE=RTL8111xP UART #2
+
+pci:v000010ECd0000816Bsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=RTL8111xP UART #2 (mCOM10-L1900)
+
+pci:v000010ECd0000816C*
+ ID_MODEL_FROM_DATABASE=RTL8111xP IPMI interface
+
+pci:v000010ECd0000816Csv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=RTL8111xP IPMI interface (mCOM10-L1900)
+
+pci:v000010ECd0000816D*
+ ID_MODEL_FROM_DATABASE=RTL811x EHCI host controller
+
+pci:v000010ECd0000816Dsv0000EA50sd0000CE19*
+ ID_MODEL_FROM_DATABASE=RTL811x EHCI host controller (mCOM10-L1900)
+
pci:v000010ECd00008171*
ID_MODEL_FROM_DATABASE=RTL8191SEvA Wireless LAN Controller
pci:v000010EEd00007038sv000017AAsd0000402F*
ID_MODEL_FROM_DATABASE=FPGA Card XC7VX690T (FPGA XC7VX690T-3FFG1157E)
+pci:v000010EEd00008019*
+ ID_MODEL_FROM_DATABASE=Memory controller
+
pci:v000010EEd00008380*
ID_MODEL_FROM_DATABASE=Ellips ProfiXpress Profibus Master
pci:v00001172d00000530*
ID_MODEL_FROM_DATABASE=Stratix IV
+pci:v00001172d0000646C*
+ ID_MODEL_FROM_DATABASE=KT-500/KT-521 board
+
pci:v00001173*
ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc
pci:v00001179d00000103*
ID_MODEL_FROM_DATABASE=EX-IDE Type-B
+pci:v00001179d0000010E*
+ ID_MODEL_FROM_DATABASE=PXP04 NVMe SSD
+
pci:v00001179d0000010F*
ID_MODEL_FROM_DATABASE=NVMe Controller
pci:v00001179d00000113*
ID_MODEL_FROM_DATABASE=BG3 NVMe SSD Controller
+pci:v00001179d00000113sv00001179sd00000001*
+ ID_MODEL_FROM_DATABASE=BG3 NVMe SSD Controller (Toshiba KBG30ZMS128G 128GB NVMe SSD)
+
pci:v00001179d00000115*
ID_MODEL_FROM_DATABASE=XG4 NVMe SSD Controller
+pci:v00001179d0000011A*
+ ID_MODEL_FROM_DATABASE=XG6 NVMe SSD Controller
+
pci:v00001179d00000404*
ID_MODEL_FROM_DATABASE=DVD Decoder card
pci:v0000125Bd00009100sv0000A000sd00007000*
ID_MODEL_FROM_DATABASE=AX99100 PCIe to Multi I/O Controller (Local Bus)
+pci:v0000125Bd00009100sv0000EA50sd00001C10*
+ ID_MODEL_FROM_DATABASE=AX99100 PCIe to Multi I/O Controller (RXi2-BP)
+
pci:v0000125C*
ID_VENDOR_FROM_DATABASE=Aurora Technologies, Inc.
pci:v0000126Fd00002262*
ID_MODEL_FROM_DATABASE=SM2262/SM2262EN SSD Controller
+pci:v0000126Fd00002263*
+ ID_MODEL_FROM_DATABASE=SM2263EN/SM2263XT SSD Controller
+
pci:v00001270*
ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd.
ID_MODEL_FROM_DATABASE=DM562P V90 Modem
pci:v00001282d00009009*
- ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit
+ ID_MODEL_FROM_DATABASE=DM9009 Ethernet Controller
pci:v00001282d00009100*
ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet
pci:v00001282d00009102*
- ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet
+ ID_MODEL_FROM_DATABASE=DM9102 Fast Ethernet Controller
pci:v00001282d00009102sv00000291sd00008212*
- ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit)
+ ID_MODEL_FROM_DATABASE=DM9102 Fast Ethernet Controller (DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit)
pci:v00001282d00009132*
ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit
pci:v00001283d00008892*
ID_MODEL_FROM_DATABASE=IT8892E PCIe to PCI Bridge
+pci:v00001283d00008892sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=IT8892E PCIe to PCI Bridge (DH61CR motherboard)
+
pci:v00001283d00008893*
ID_MODEL_FROM_DATABASE=IT8893E PCIe to PCI Bridge
pci:v000012D8d00002608*
ID_MODEL_FROM_DATABASE=PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch
+pci:v000012D8d00002608sv0000EA50sd0000CC10*
+ ID_MODEL_FROM_DATABASE=PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch (RXi2-BP)
+
pci:v000012D8d0000400A*
ID_MODEL_FROM_DATABASE=PI7C9X442SL PCI Express Bridge Port
pci:v000012D8d00008154*
ID_MODEL_FROM_DATABASE=PI7C8154A/PI7C8154B/PI7C8154BI PCI-to-PCI Bridge
+pci:v000012D8d00008619*
+ ID_MODEL_FROM_DATABASE=PI7C9X2G1616PR PCIe2 16-Port/16-Lane Packet Switch
+
pci:v000012D8d0000E110*
ID_MODEL_FROM_DATABASE=PI7C9X110 PCI Express to PCI bridge
pci:v000012EBd00000001*
ID_MODEL_FROM_DATABASE=Vortex 1
+pci:v000012EBd00000001sv00000000sd00000300*
+ ID_MODEL_FROM_DATABASE=Vortex 1 (Terasound A3D PCI)
+
pci:v000012EBd00000001sv0000104Dsd00008036*
ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor)
ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D)
pci:v000012EBd00000001sv0000122Dsd00001002*
- ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor)
+ ID_MODEL_FROM_DATABASE=Vortex 1 (SC 338-A3D)
pci:v000012EBd00000001sv000012EBsd00000001*
ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor)
ID_VENDOR_FROM_DATABASE=Sonix Inc
pci:v00001353*
- ID_VENDOR_FROM_DATABASE=Vierling Communication SAS
+ ID_VENDOR_FROM_DATABASE=dbeeSet Technology
pci:v00001353d00000002*
ID_MODEL_FROM_DATABASE=Proserver
pci:v00001353d00000005*
ID_MODEL_FROM_DATABASE=PCI-FUT-S0
+pci:v00001353d00000006*
+ ID_MODEL_FROM_DATABASE=OTDU-1U (FPGA Zynq-7000)
+
+pci:v00001353d00000007*
+ ID_MODEL_FROM_DATABASE=OTDU-EX
+
pci:v00001354*
ID_VENDOR_FROM_DATABASE=Dwave System Inc
pci:v0000144Dd0000A802*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM951/PM951
+pci:v0000144Dd0000A802sv0000144Dsd0000A801*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM951/PM951 (PM963 2.5" NVMe PCIe SSD)
+
pci:v0000144Dd0000A804*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM961/PM961
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM961/PM961/SM963
+
+pci:v0000144Dd0000A804sv0000144Dsd0000A801*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM961/PM961/SM963 (SM963 2.5" NVMe PCIe SSD)
pci:v0000144Dd0000A808*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM981/PM981/PM983
pci:v0000144Dd0000A808sv00001D49sd0000403B*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM981/PM981/PM983 (Thinksystem U.2 PM983 NVMe SSD)
+pci:v0000144Dd0000A80A*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller PM9A1/980PRO
+
pci:v0000144Dd0000A820*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X
pci:v000014E4d0000168Esv0000193Dsd00001006*
ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (530F-L)
+pci:v000014E4d0000168Esv0000193Dsd0000100F*
+ ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (NIC-ETH522i-Mb-2x10G)
+
pci:v000014E4d00001690*
ID_MODEL_FROM_DATABASE=NetXtreme BCM57760 Gigabit Ethernet PCIe
pci:v000014E4d000016A1sv00001043sd0000866E*
ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10 Gigabit Ethernet (PEB-10G/57840-2T 10GBase-T Network Adapter)
+pci:v000014E4d000016A1sv0000193Dsd0000100B*
+ ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10 Gigabit Ethernet (NIC-ETH521i-Mb-4x10G)
+
pci:v000014E4d000016A2*
ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet
pci:v000014E4d00001807*
ID_MODEL_FROM_DATABASE=BCM5750X NetXtreme-E RDMA Virtual Function
+pci:v000014E4d00002711*
+ ID_MODEL_FROM_DATABASE=BCM2711 PCIe Bridge
+
pci:v000014E4d00003352*
ID_MODEL_FROM_DATABASE=BCM3352
pci:v000015B3d00001015sv0000193Dsd0000100A*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (620F-B)
+pci:v000015B3d00001015sv0000193Dsd00001031*
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (NIC-ETH640i-Mb-2x25G)
+
pci:v000015B3d00001016*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function]
pci:v000015B3d00001017sv000015B3sd00000068*
ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (ConnectX®-5 EN network interface card for OCP2.0, Type 1, with host management, 25GbE dual-port SFP28, PCIe3.0 x8, no bracket Halogen free ; MCX542B-ACAN)
+pci:v000015B3d00001017sv0000193Dsd00001051*
+ ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (NIC-IB1040i-Mb-2P)
+
pci:v000015B3d00001018*
ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5 Virtual Function]
ID_MODEL_FROM_DATABASE=WD Black NVMe SSD
pci:v000015B7d00005002*
- ID_MODEL_FROM_DATABASE=WD Black 2018 / PC SN720 NVMe SSD
+ ID_MODEL_FROM_DATABASE=WD Black 2018/SN750 / PC SN720 NVMe SSD
pci:v000015B7d00005003*
- ID_MODEL_FROM_DATABASE=WD Black 2018 / PC SN520 NVMe SSD
+ ID_MODEL_FROM_DATABASE=WD Blue SN500 / PC SN520 NVMe SSD
pci:v000015B7d00005004*
ID_MODEL_FROM_DATABASE=PC SN520 NVMe SSD
ID_MODEL_FROM_DATABASE=PC SN520 NVMe SSD
pci:v000015B7d00005006*
- ID_MODEL_FROM_DATABASE=WD Black 2019/PC SN750 NVMe SSD
+ ID_MODEL_FROM_DATABASE=WD Black SN750 / PC SN730 NVMe SSD
pci:v000015B7d00005009*
ID_MODEL_FROM_DATABASE=WD Blue SN550 NVMe SSD
pci:v000015B7d00005009sv000015B7sd00005009*
ID_MODEL_FROM_DATABASE=WD Blue SN550 NVMe SSD
+pci:v000015B7d0000500B*
+ ID_MODEL_FROM_DATABASE=PC SN530 NVMe SSD
+
+pci:v000015B7d0000500Bsv00001414sd0000500B*
+ ID_MODEL_FROM_DATABASE=PC SN530 NVMe SSD (Xbox Series X)
+
pci:v000015B7d0000500D*
ID_MODEL_FROM_DATABASE=WD Ultrastar DC SN340 NVMe SSD
+pci:v000015B7d00005011*
+ ID_MODEL_FROM_DATABASE=WD Black SN850
+
pci:v000015B8*
ID_VENDOR_FROM_DATABASE=ADDI-DATA GmbH
pci:v00001760d00000800*
ID_MODEL_FROM_DATABASE=PCD8006 - PCIe digital Inputs/Outputs
+pci:v00001760d00000840*
+ ID_MODEL_FROM_DATABASE=PCA-8428 General-purpose multifunctional PCIe card with 8 analog inputs and 2 analog outputs
+
+pci:v00001760d00000841*
+ ID_MODEL_FROM_DATABASE=PCA-8429 General-purpose multifunctional PCIe card with 8 analog inputs
+
+pci:v00001760d00000842*
+ ID_MODEL_FROM_DATABASE=PCA-8438 General-purpose multifunctional PCIe card with 16 analog inputs and 2 analog outputs
+
+pci:v00001760d00000843*
+ ID_MODEL_FROM_DATABASE=PCA-8439 General-purpose multifunctional PCIe card with 16 analog inputs
+
pci:v00001760d0000FF00*
ID_MODEL_FROM_DATABASE=CTU CAN FD PCIe Card
pci:v000017CBd00001000*
ID_MODEL_FROM_DATABASE=QCS405 PCIe Root Complex
+pci:v000017CBd00001101*
+ ID_MODEL_FROM_DATABASE=QCA6390 Wireless Network Adapter [AX500-DBS (2x2)]
+
pci:v000017CC*
ID_VENDOR_FROM_DATABASE=NetChip Technology, Inc
pci:v000019E5d00001822sv000019E5sd0000D146*
ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 SP585 (4*25GE))
+pci:v000019E5d00003714*
+ ID_MODEL_FROM_DATABASE=ES3000 V5 NVMe PCIe SSD
+
+pci:v000019E5d00003714sv000019E5sd00005312*
+ ID_MODEL_FROM_DATABASE=ES3000 V5 NVMe PCIe SSD (NVMe SSD ES3500P V5 2000GB 2.5" U.2)
+
pci:v000019E5d0000371E*
ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Bridge
+pci:v000019E5d00003754*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD
+
+pci:v000019E5d00003754sv000019E5sd00006122*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3600P V6 1600GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006123*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3600P V6 3200GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006124*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3600P V6 6400GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006141*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3800P V6 800GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006142*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3800P V6 1600GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006212*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3500P V6 1920GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006213*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3500P V6 3840GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006214*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3500P V6 7680GB 2.5" U.2)
+
+pci:v000019E5d00003754sv000019E5sd00006215*
+ ID_MODEL_FROM_DATABASE=ES3000 V6 NVMe PCIe SSD (NVMe SSD ES3500P V6 15360GB 2.5" U.2)
+
pci:v000019E5d0000375E*
ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Function
pci:v00001A4Ad00001010*
ID_MODEL_FROM_DATABASE=AMC EVR - Stockholm Timing Board
+pci:v00001A4Ad00001020*
+ ID_MODEL_FROM_DATABASE=PGPCard - Gen3 Cameralink Interface
+
pci:v00001A4Ad00001030*
ID_MODEL_FROM_DATABASE=PGPCard - Gen3 GIGe Interface
pci:v00001B36d0000000D*
ID_MODEL_FROM_DATABASE=QEMU XHCI Host Controller
+pci:v00001B36d00000010*
+ ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller
+
pci:v00001B36d00000100*
ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card
pci:v00001B4Bd0000917A*
ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller
+pci:v00001B4Bd00009182*
+ ID_MODEL_FROM_DATABASE=88SE9182 PCIe 2.0 x2 2-port SATA 6 Gb/s Controller
+
pci:v00001B4Bd00009183*
ID_MODEL_FROM_DATABASE=88SS9183 PCIe SSD Controller
pci:v00001B4Bd000091A4*
ID_MODEL_FROM_DATABASE=88SE912x IDE Controller
+pci:v00001B4Bd00009215*
+ ID_MODEL_FROM_DATABASE=88SE9215 PCIe 2.0 x1 4-port SATA 6 Gb/s Controller
+
pci:v00001B4Bd00009220*
ID_MODEL_FROM_DATABASE=88SE9220 PCIe 2.0 x2 2-port SATA 6 Gb/s RAID Controller
pci:v00001B4Bd00009230*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller
pci:v00001B4Bd00009230sv00001028sd00001FD6*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Adapter)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (BOSS-S1 Adapter)
pci:v00001B4Bd00009230sv00001028sd00001FDF*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Modular)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (BOSS-S1 Modular)
pci:v00001B4Bd00009230sv00001028sd00001FE2*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Adapter)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (BOSS-S1 Adapter)
pci:v00001B4Bd00009230sv00001028sd00002010*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S2 Adapter)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (BOSS-S2 Adapter)
pci:v00001B4Bd00009230sv00001D49sd00000300*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem M.2 with Mirroring Enablement Kit)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem M.2 with Mirroring Enablement Kit)
pci:v00001B4Bd00009230sv00001D49sd00000301*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem SR630 x16 PCIE with 4 SATA ports Riser)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem SR630 x16 PCIE with 4 SATA ports Riser)
pci:v00001B4Bd00009230sv00001D49sd00000302*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit)
pci:v00001B4Bd00009230sv00001D49sd00000303*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit)
pci:v00001B4Bd00009230sv00001D49sd00000304*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem M.2 SATA 2-Bay RAID Enablement Kit)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem M.2 SATA 2-Bay RAID Enablement Kit)
pci:v00001B4Bd00009230sv00001D49sd00000305*
- ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem 7mm SATA 2-Bay Rear RAID Enablement Kit)
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller (ThinkSystem 7mm SATA 2-Bay Rear RAID Enablement Kit)
pci:v00001B4Bd00009235*
ID_MODEL_FROM_DATABASE=88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller
pci:v00001B96d00002500*
ID_MODEL_FROM_DATABASE=Ultrastar DC SN840 NVMe SSD
+pci:v00001B96d00002600*
+ ID_MODEL_FROM_DATABASE=Ultrastar DC ZN540 ZNS NVMe SSD
+
pci:v00001B96d00003714*
ID_MODEL_FROM_DATABASE=PC SN730 NVMe SSD
pci:v00001C5Cd00001504*
ID_MODEL_FROM_DATABASE=SC300 512GB M.2 2280 SATA Solid State Drive
+pci:v00001C5Cd00001527*
+ ID_MODEL_FROM_DATABASE=PC401 NVMe Solid State Drive 256GB
+
pci:v00001C5Cd0000243B*
ID_MODEL_FROM_DATABASE=PE6110 NVMe Solid State Drive
ID_VENDOR_FROM_DATABASE=Beijing Memblaze Technology Co. Ltd.
pci:v00001C5Fd0000000D*
- ID_MODEL_FROM_DATABASE=PBlaze5 520/526 AIC
+ ID_MODEL_FROM_DATABASE=PBlaze5 520/526
pci:v00001C5Fd0000003D*
- ID_MODEL_FROM_DATABASE=PBlaze5 920/926 AIC
+ ID_MODEL_FROM_DATABASE=PBlaze5 920/926
+
+pci:v00001C5Fd0000003E*
+ ID_MODEL_FROM_DATABASE=PBlaze6 6920
-pci:v00001C5Fd0000010D*
- ID_MODEL_FROM_DATABASE=PBlaze5 520/526 U.2
+pci:v00001C5Fd0000003Esv00001C5Fsd00000A31*
+ ID_MODEL_FROM_DATABASE=PBlaze6 6920 (NVMe SSD PBlaze6 6920 3840GB 2.5" U.2)
-pci:v00001C5Fd0000013D*
- ID_MODEL_FROM_DATABASE=PBlaze5 920/926 U.2
+pci:v00001C5Fd0000003Esv00001C5Fsd00000A41*
+ ID_MODEL_FROM_DATABASE=PBlaze6 6920 (NVMe SSD PBlaze6 6920 7680GB 2.5" U.2)
+
+pci:v00001C5Fd0000003Esv00001C5Fsd00004A31*
+ ID_MODEL_FROM_DATABASE=PBlaze6 6920 (NVMe SSD PBlaze6 6920 3200GB 2.5" U.2)
+
+pci:v00001C5Fd0000003Esv00001C5Fsd00004A41*
+ ID_MODEL_FROM_DATABASE=PBlaze6 6920 (NVMe SSD PBlaze6 6920 6400GB 2.5" U.2)
pci:v00001C5Fd00000540*
ID_MODEL_FROM_DATABASE=PBlaze4 NVMe SSD
pci:v00001D0F*
ID_VENDOR_FROM_DATABASE=Amazon.com, Inc.
+pci:v00001D0Fd00008061*
+ ID_MODEL_FROM_DATABASE=NVMe EBS Controller
+
pci:v00001D0Fd0000CD01*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller
pci:v00001D6Cd00001016*
ID_MODEL_FROM_DATABASE=AR-ARK-BBDEV-FX1 [Arkville 64B DPDK Baseband Device]
+pci:v00001D6Cd00001017*
+ ID_MODEL_FROM_DATABASE=AR-ARK-FX1 [Arkville 64B Multi-Homed Primary Endpoint]
+
+pci:v00001D6Cd00001018*
+ ID_MODEL_FROM_DATABASE=AR-ARK-FX1 [Arkville 64B Multi-Homed Secondary Endpoint]
+
+pci:v00001D6Cd00001019*
+ ID_MODEL_FROM_DATABASE=AR-ARK-FX1 [Arkville 64B Multi-Homed Tertiary Endpoint]
+
pci:v00001D6Cd00004200*
ID_MODEL_FROM_DATABASE=A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument]
ID_VENDOR_FROM_DATABASE=Enyx
pci:v00001D93*
- ID_VENDOR_FROM_DATABASE=YADRO (KNS Group)
+ ID_VENDOR_FROM_DATABASE=YADRO
pci:v00001D94*
ID_VENDOR_FROM_DATABASE=Chengdu Haiguang IC Design Co., Ltd.
ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001000sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001000sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001000sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001000sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001000sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001001*
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001001sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001001sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001001sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001001sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001001sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001002*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001002sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001002sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001002sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001002sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001002sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001003*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001003sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001003sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001003sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001003sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001003sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001004*
ID_MODEL_FROM_DATABASE=DSC Management Controller
ID_MODEL_FROM_DATABASE=DSC Management Controller (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001004sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Management Controller (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Management Controller (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001004sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Management Controller (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001004sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001004sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Management Controller (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Management Controller (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001004sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001007*
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (Naples 25Gb 2-port SFP28 x8 4GB)
pci:v00001DD8d00001007sv00001DD8sd00004007*
- ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSP DSC-25 10/25G 2p OCP Card)
+ ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSP DSC-25 Ent 10/25G OCP3 Card)
pci:v00001DD8d00001007sv00001DD8sd00004008*
- ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+ ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSP DSC-25 10/25G 2p SFP28 Card)
pci:v00001DD8d00001007sv00001DD8sd0000400A*
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DD8d00001007sv00001DD8sd0000400D*
- ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSP DSC-100 100G 2p QSFP28 Card)
+ ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSP DSC-100 Ent 100Gb Card)
+
+pci:v00001DD8d00001007sv00001DD8sd0000400E*
+ ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card)
pci:v00001DE0*
ID_VENDOR_FROM_DATABASE=Groq
pci:v00001DE0d00000000*
- ID_MODEL_FROM_DATABASE=Q100 Tensor Streaming Processor
+ ID_MODEL_FROM_DATABASE=TSP100 Tensor Streaming Processor
pci:v00001DE1*
ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd.
pci:v00001DEFd0000E00C*
ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 7
+pci:v00001DEFd0000E100*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Complex A
+
+pci:v00001DEFd0000E101*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a0
+
+pci:v00001DEFd0000E102*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a1
+
+pci:v00001DEFd0000E103*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a2
+
+pci:v00001DEFd0000E104*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a3
+
+pci:v00001DEFd0000E105*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a4
+
+pci:v00001DEFd0000E106*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a5
+
+pci:v00001DEFd0000E107*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a6
+
+pci:v00001DEFd0000E108*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port a7
+
+pci:v00001DEFd0000E110*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Complex B
+
+pci:v00001DEFd0000E111*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b0
+
+pci:v00001DEFd0000E112*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b1
+
+pci:v00001DEFd0000E113*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b2
+
+pci:v00001DEFd0000E114*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b3
+
+pci:v00001DEFd0000E115*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b4
+
+pci:v00001DEFd0000E116*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b5
+
+pci:v00001DEFd0000E117*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b6
+
+pci:v00001DEFd0000E118*
+ ID_MODEL_FROM_DATABASE=Altra PCI Express Root Port b7
+
pci:v00001DF3*
ID_VENDOR_FROM_DATABASE=Ethernity Networks
pci:v00001E36d00008011*
ID_MODEL_FROM_DATABASE=I10 [CloudBlazer]
+pci:v00001E36d00008012*
+ ID_MODEL_FROM_DATABASE=I10L [CloudBlazer]
+
pci:v00001E38*
ID_VENDOR_FROM_DATABASE=Blaize, Inc
ID_VENDOR_FROM_DATABASE=GSI Technology
pci:v00001E4Cd00000010*
- ID_MODEL_FROM_DATABASE=APU [Leda-G]
+ ID_MODEL_FROM_DATABASE=APU [Leda]
pci:v00001E4Cd00000010sv00001E4Csd00000120*
- ID_MODEL_FROM_DATABASE=APU [Leda-G] (SE120)
+ ID_MODEL_FROM_DATABASE=APU [Leda] (SE120)
pci:v00001E57*
ID_VENDOR_FROM_DATABASE=Beijing Panyi Technology Co., Ltd
pci:v00001E57d00000100sv00000000sd00000100*
ID_MODEL_FROM_DATABASE=The device has already been deleted. (PY8800 64GB Accelerator)
+pci:v00001E60*
+ ID_VENDOR_FROM_DATABASE=Hailo Technologies Ltd.
+
+pci:v00001E60d00002864*
+ ID_MODEL_FROM_DATABASE=Hailo-8 AI Processor
+
pci:v00001E6B*
ID_VENDOR_FROM_DATABASE=Axiado Corp.
pci:v00001E95*
ID_VENDOR_FROM_DATABASE=Solid State Storage Technology Corporation
+pci:v00001EA0*
+ ID_VENDOR_FROM_DATABASE=Tencent Technology (Shenzhen) Company Limited
+
+pci:v00001EA0d00002A16*
+ ID_MODEL_FROM_DATABASE=Cloud Intelligent Inference Controller
+
pci:v00001EAB*
ID_VENDOR_FROM_DATABASE=Hefei DATANG Storage Technology Co.,LTD.
+pci:v00001EABd0000300A*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 300A
+
+pci:v00001EABd0000300B*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 300B
+
pci:v00001EAE*
ID_VENDOR_FROM_DATABASE=XFX Limited
pci:v00001EB1d00001001*
ID_MODEL_FROM_DATABASE=Video Accelerator
+pci:v00001ED8*
+ ID_VENDOR_FROM_DATABASE=Digiteq Automotive
+
+pci:v00001ED8d00000101*
+ ID_MODEL_FROM_DATABASE=FG4 PCIe Frame Grabber
+
+pci:v00001ED9*
+ ID_VENDOR_FROM_DATABASE=Myrtle.ai
+
+pci:v00001EE9*
+ ID_VENDOR_FROM_DATABASE=SUSE LLC
+
pci:v00001FC0*
ID_VENDOR_FROM_DATABASE=Ascom (Finland) Oy
pci:v00002646*
ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc.
+pci:v00002646d00000010*
+ ID_MODEL_FROM_DATABASE=HyperX Predator PCIe AHCI SSD
+
pci:v00002646d00002263*
ID_MODEL_FROM_DATABASE=A2000 NVMe SSD
+pci:v00002646d00005008*
+ ID_MODEL_FROM_DATABASE=U-SNS8154P3 NVMe SSD
+
+pci:v00002646d0000500D*
+ ID_MODEL_FROM_DATABASE=OM3PDP3 NVMe SSD
+
pci:v0000270B*
ID_VENDOR_FROM_DATABASE=Xantel Corporation
pci:v00008086d00000100sv00001043sd0000844D*
ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (P8P67/P8H67 Series Motherboard)
+pci:v00008086d00000100sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (DH61CR motherboard)
+
pci:v00008086d00000101*
ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port
pci:v00008086d00000176*
ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller
+pci:v00008086d00000201*
+ ID_MODEL_FROM_DATABASE=Arctic Sound
+
pci:v00008086d00000284*
ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP LPC Premium Controller/eSPI Controller
pci:v00008086d000002A6*
ID_MODEL_FROM_DATABASE=Comet Lake North Peak
+pci:v00008086d000002B0*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #9
+
+pci:v00008086d000002B1*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #10
+
+pci:v00008086d000002B3*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #12
+
+pci:v00008086d000002B4*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #13
+
+pci:v00008086d000002B8*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #1
+
+pci:v00008086d000002BC*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCI Express Root Port #5
+
+pci:v00008086d000002C5*
+ ID_MODEL_FROM_DATABASE=Comet Lake Serial IO I2C Host Controller
+
pci:v00008086d000002C8*
ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP cAVS
pci:v00008086d000002E9*
ID_MODEL_FROM_DATABASE=Comet Lake Serial IO I2C Host Controller
+pci:v00008086d000002EA*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP LPSS: I2C Controller #2
+
pci:v00008086d000002ED*
ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP USB 3.1 xHCI Host Controller
pci:v00008086d00000412sv0000103Csd00001998*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (EliteDesk 800 G1)
+pci:v00008086d00000412sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (ThinkCentre E73)
+
pci:v00008086d00000412sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (ThinkCentre M83)
ID_MODEL_FROM_DATABASE=Thunderbolt 4 USB Controller [Goshen Ridge 2020]
pci:v00008086d00000B60*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller]
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller]
pci:v00008086d00000B60sv00001028sd00002060*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED MU U.2 1.6TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED MU U.2 1.6TB (P5600))
pci:v00008086d00000B60sv00001028sd00002061*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED MU U.2 3.2TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED MU U.2 3.2TB (P5600))
pci:v00008086d00000B60sv00001028sd00002062*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED MU U.2 6.4TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED MU U.2 6.4TB (P5600))
pci:v00008086d00000B60sv00001028sd00002064*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED RI U.2 1.92TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED RI U.2 1.92TB (P5500))
pci:v00008086d00000B60sv00001028sd00002065*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED RI U.2 3.84TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED RI U.2 3.84TB (P5500))
pci:v00008086d00000B60sv00001028sd00002066*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe SED RI U.2 7.68TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe SED RI U.2 7.68TB (P5500))
pci:v00008086d00000B60sv00001028sd0000209E*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe MU U.2 1.6TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe MU U.2 1.6TB (P5600))
pci:v00008086d00000B60sv00001028sd0000209F*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe MU U.2 3.2TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe MU U.2 3.2TB (P5600))
pci:v00008086d00000B60sv00001028sd00002100*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe MU U.2 6.4TB (P5600))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe MU U.2 6.4TB (P5600))
pci:v00008086d00000B60sv00001028sd00002102*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe RI U.2 1.92TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe RI U.2 1.92TB (P5500))
pci:v00008086d00000B60sv00001028sd00002103*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe RI U.2 3.84TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe RI U.2 3.84TB (P5500))
pci:v00008086d00000B60sv00001028sd00002104*
- ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (NVMe RI U.2 7.68TB (P5500))
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe RI U.2 7.68TB (P5500))
+
+pci:v00008086d00000B60sv00008086sd00008008*
+ ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Sentinel Rock Controller] (NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P5510))
pci:v00008086d00000BE0*
ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller
pci:v00008086d00000C00sv0000103Csd00001998*
ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (EliteDesk 800 G1)
+pci:v00008086d00000C00sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (ThinkCentre E73)
+
pci:v00008086d00000C00sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (ThinkCentre M83)
pci:v00008086d00001132sv00008086sd00004557*
ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EGEW Mainboard)
+pci:v00008086d00001136*
+ ID_MODEL_FROM_DATABASE=Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
+
+pci:v00008086d00001137*
+ ID_MODEL_FROM_DATABASE=Thunderbolt 4 NHI [Maple Ridge 4C 2020]
+
+pci:v00008086d00001138*
+ ID_MODEL_FROM_DATABASE=Thunderbolt 4 USB Controller [Maple Ridge 4C 2020]
+
pci:v00008086d00001161*
ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Advanced Programmable Interrupt Controller
pci:v00008086d00001503sv000010CFsd0000161C*
ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection (LIFEBOOK E752)
+pci:v00008086d00001503sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection (DH61CR motherboard)
+
pci:v00008086d00001507*
ID_MODEL_FROM_DATABASE=Ethernet Express Module X520-P2
pci:v00008086d0000156Fsv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM (EliteBook 840 G3)
+pci:v00008086d0000156Fsv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM (ThinkPad T570)
+
pci:v00008086d00001570*
ID_MODEL_FROM_DATABASE=Ethernet Connection I219-V
pci:v00008086d00001572sv000017AAsd00004002*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710-2 AnyFabric for 10GbE SFP+)
+pci:v00008086d00001572sv0000193Dsd00001020*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (NIC-ETH561F-sL-4x10G)
+
+pci:v00008086d00001572sv0000193Dsd00001021*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (NIC-ETH561F-sL-2x10G)
+
pci:v00008086d00001572sv000019E5sd0000D11C*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 2-port X710 10Gb SFP+ Adapter SP330)
pci:v00008086d0000157B*
ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection
+pci:v00008086d0000157Bsv0000EA50sd0000CC10*
+ ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (RXi2-BP)
+
pci:v00008086d0000157C*
ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection
pci:v00008086d00001581sv00001590sd000000F8*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 2-port 563i Adapter)
+pci:v00008086d00001581sv0000193Dsd0000100E*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (NIC-ETH561i-Mb-4x10G)
+
pci:v00008086d00001581sv00008086sd00000000*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet Converged Network Adapter XL710-Q2)
pci:v00008086d00001592sv00001137sd000002BF*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (E810CQDA2 2x100 GbE QSFP28 PCIe NIC)
+pci:v00008086d00001592sv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q1)
+
pci:v00008086d00001592sv00008086sd00000002*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q2)
pci:v00008086d00001592sv00008086sd0000000C*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet 100G 2P E810-C OCP)
+pci:v00008086d00001592sv00008086sd0000000D*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-L-Q2 for OCP 3.0)
+
pci:v00008086d00001593*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP
pci:v00008086d000015FFsv00001137sd000002C2*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (X710T4LG 4x10 GbE RJ45 PCIe NIC)
+pci:v00008086d000015FFsv00001137sd000002D9*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L OCP 3.0)
+
+pci:v00008086d000015FFsv00001137sd000002DA*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T4L OCP 3.0)
+
pci:v00008086d000015FFsv00008086sd00000000*
ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-TL)
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00001901*
- ID_MODEL_FROM_DATABASE=6th-9th Gen Core Processor PCIe Controller (x16)
+ ID_MODEL_FROM_DATABASE=6th-10th Gen Core Processor PCIe Controller (x16)
pci:v00008086d00001902*
ID_MODEL_FROM_DATABASE=HD Graphics 510
pci:v00008086d00001903sv00001028sd000006E4*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (XPS 15 9550)
+pci:v00008086d00001903sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (Latitude 11 5175 2-in-1)
+
pci:v00008086d00001903sv0000103Csd0000825B*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (OMEN-17-w001nv)
pci:v00008086d00001904sv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (EliteBook 840 G3)
+pci:v00008086d00001904sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (ThinkPad T570)
+
pci:v00008086d00001904sv000017AAsd0000382A*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (B51-80 Laptop)
pci:v00008086d0000190Csv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (Latitude 7275 tablet)
+pci:v00008086d0000190Csv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (Latitude 11 5175 2-in-1)
+
pci:v00008086d0000190F*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00001916sv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] (EliteBook 840 G3)
+pci:v00008086d00001916sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] (ThinkPad T570)
+
pci:v00008086d00001918*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00001919sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit (Latitude 7275 tablet)
+pci:v00008086d00001919sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit (Latitude 11 5175 2-in-1)
+
pci:v00008086d0000191B*
ID_MODEL_FROM_DATABASE=HD Graphics 530
pci:v00008086d0000191Esv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=HD Graphics 515 (Latitude 7275 tablet)
+pci:v00008086d0000191Esv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=HD Graphics 515 (Latitude 11 5175 2-in-1)
+
pci:v00008086d0000191F*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00001C02sv00001043sd0000844D*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (P8 series motherboard)
+pci:v00008086d00001C02sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (DH61CR motherboard)
+
pci:v00008086d00001C02sv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (Server Board S1200BT Family)
pci:v00008086d00001C20sv00008086sd00002008*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (DQ67SW board)
+pci:v00008086d00001C20sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (DH61CR motherboard)
+
pci:v00008086d00001C20sv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Apple MacBookPro8,2 [Core i7, 15", 2011])
pci:v00008086d00001C22sv000017AAsd000021CF*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (ThinkPad T520)
+pci:v00008086d00001C22sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (DH61CR motherboard)
+
pci:v00008086d00001C22sv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2)
pci:v00008086d00001C26sv000017AAsd000021CF*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (ThinkPad T520)
+pci:v00008086d00001C26sv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (DH61CR motherboard)
+
pci:v00008086d00001C26sv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2)
pci:v00008086d00001C2Dsv000017AAsd000021CF*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (ThinkPad T520)
+pci:v00008086d00001C2Dsv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (DH61CR motherboard)
+
pci:v00008086d00001C2Dsv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2)
pci:v00008086d00001C3Asv000017AAsd000021CF*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (ThinkPad T520)
+pci:v00008086d00001C3Asv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (DH61CR motherboard)
+
pci:v00008086d00001C3Asv00008086sd00007270*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011])
pci:v00008086d00001C5C*
ID_MODEL_FROM_DATABASE=H61 Express Chipset LPC Controller
+pci:v00008086d00001C5Csv00008086sd0000200D*
+ ID_MODEL_FROM_DATABASE=H61 Express Chipset LPC Controller (DH61CR motherboard)
+
pci:v00008086d00001C5D*
ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller
pci:v00008086d00002442sv00008086sd00004557*
ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D815EGEW Mainboard)
+pci:v00008086d00002442sv00008086sd00004D44*
+ ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D850EMV2 motherboard)
+
pci:v00008086d00002442sv00008086sd00005744*
ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (S845WD1-E mainboard)
pci:v00008086d00002445sv00008086sd00004656*
ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Desktop Board D815EFV)
+pci:v00008086d00002445sv00008086sd00004D44*
+ ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (D850EMV2 motherboard)
+
pci:v00008086d00002446*
ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller
pci:v00008086d0000244Bsv00008086sd00004557*
ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EGEW Mainboard)
+pci:v00008086d0000244Bsv00008086sd00004D44*
+ ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D850EMV2 motherboard)
+
pci:v00008086d0000244Bsv00008086sd00005744*
ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (S845WD1-E mainboard)
pci:v00008086d00002590sv0000103Csd0000099C*
ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (NX6110/NC6120)
+pci:v00008086d00002590sv00001043sd000082D9*
+ ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Asus Eee PC 900)
+
pci:v00008086d00002590sv0000104Dsd000081B7*
ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Vaio VGN-S3XP)
pci:v00008086d00002A00sv0000103Csd000030C1*
ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 6910p)
+pci:v00008086d00002A00sv0000103Csd000030C5*
+ ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 8510p)
+
pci:v00008086d00002A00sv0000103Csd000030CC*
ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Pavilion dv6700)
pci:v00008086d00002A42*
ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller
+pci:v00008086d00002A42sv00001028sd000002AA*
+ ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (Dell Inspiron 1545)
+
pci:v00008086d00002A42sv000017AAsd00002112*
ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (ThinkPad T400)
ID_MODEL_FROM_DATABASE=Dual Band Wireless-AC 3165 Plus Bluetooth (Dual Band Wireless-AC 3165)
pci:v00008086d00003184*
- ID_MODEL_FROM_DATABASE=UHD Graphics 605
+ ID_MODEL_FROM_DATABASE=GeminiLake [UHD Graphics 605]
pci:v00008086d00003185*
- ID_MODEL_FROM_DATABASE=UHD Graphics 605
+ ID_MODEL_FROM_DATABASE=GeminiLake [UHD Graphics 600]
pci:v00008086d0000318C*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Dynamic Platform and Thermal Framework Processor Participant
pci:v00008086d000031A2*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Integrated Sensor Solution
+pci:v00008086d000031A8*
+ ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor USB 3.0 xHCI Controller
+
+pci:v00008086d000031A8sv00001849sd000031A8*
+ ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor USB 3.0 xHCI Controller
+
pci:v00008086d000031AC*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO I2C Host Controller
pci:v00008086d000031DC*
ID_MODEL_FROM_DATABASE=AC 1550i Wireless
+pci:v00008086d000031E3*
+ ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor SATA Controller
+
+pci:v00008086d000031E8*
+ ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor LPC Controller
+
pci:v00008086d000031EE*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller
pci:v00008086d000034B0*
ID_MODEL_FROM_DATABASE=Ice Lake-LP PCI Express Root Port #9
+pci:v00008086d000034B7*
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP PCI Express Root Port #16
+
pci:v00008086d000034BC*
ID_MODEL_FROM_DATABASE=Ice Lake-LP PCI Express Root Port #5
ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2c Controller #5
pci:v00008086d000034C8*
- ID_MODEL_FROM_DATABASE=Smart Sound Technology Audio Controller
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP Smart Sound Technology Audio Controller
pci:v00008086d000034D3*
ID_MODEL_FROM_DATABASE=Ice Lake-LP SATA Controller [AHCI mode]
pci:v00008086d000034E0*
- ID_MODEL_FROM_DATABASE=Management Engine Interface
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP Management Engine
pci:v00008086d000034E8*
ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2C Controller #0
pci:v00008086d000034ED*
ID_MODEL_FROM_DATABASE=Ice Lake-LP USB 3.1 xHCI Host Controller
+pci:v00008086d000034EF*
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP DRAM Controller
+
pci:v00008086d000034F0*
ID_MODEL_FROM_DATABASE=Killer Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)
pci:v00008086d000034F8*
ID_MODEL_FROM_DATABASE=Ice Lake-LP SD Controller
+pci:v00008086d000034FC*
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP Integrated Sensor Solution
+
pci:v00008086d00003500*
ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port
pci:v00008086d00003E89*
ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x4)
+pci:v00008086d00003E90*
+ ID_MODEL_FROM_DATABASE=CoffeeLake-S GT1 [UHD Graphics 610]
+
pci:v00008086d00003E91*
- ID_MODEL_FROM_DATABASE=8th Gen Core Processor Gaussian Mixture Model
+ ID_MODEL_FROM_DATABASE=CoffeeLake-S GT2 [UHD Graphics 630]
pci:v00008086d00003E92*
- ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Desktop)
+ ID_MODEL_FROM_DATABASE=CometLake-S GT2 [UHD Graphics 630]
pci:v00008086d00003E92sv00001028sd00000869*
- ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Desktop) (Vostro 3470)
+ ID_MODEL_FROM_DATABASE=CometLake-S GT2 [UHD Graphics 630] (Vostro 3470)
pci:v00008086d00003E93*
- ID_MODEL_FROM_DATABASE=UHD Graphics 610
+ ID_MODEL_FROM_DATABASE=CoffeeLake-S GT1 [UHD Graphics 610]
pci:v00008086d00003E96*
- ID_MODEL_FROM_DATABASE=HD Graphics P630
+ ID_MODEL_FROM_DATABASE=CoffeeLake-S GT2 [UHD Graphics P630]
pci:v00008086d00003E98*
- ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Desktop 9 Series)
+ ID_MODEL_FROM_DATABASE=CoffeeLake-S GT2 [UHD Graphics 630]
pci:v00008086d00003E9B*
- ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Mobile)
+ ID_MODEL_FROM_DATABASE=CoffeeLake-H GT2 [UHD Graphics 630]
pci:v00008086d00003EA0*
- ID_MODEL_FROM_DATABASE=UHD Graphics 620 (Whiskey Lake)
+ ID_MODEL_FROM_DATABASE=WhiskeyLake-U GT2 [UHD Graphics 620]
pci:v00008086d00003EA0sv00001028sd0000089E*
- ID_MODEL_FROM_DATABASE=UHD Graphics 620 (Whiskey Lake) (Inspiron 5482)
+ ID_MODEL_FROM_DATABASE=WhiskeyLake-U GT2 [UHD Graphics 620] (Inspiron 5482)
pci:v00008086d00003EA5*
- ID_MODEL_FROM_DATABASE=Iris Plus Graphics 655
+ ID_MODEL_FROM_DATABASE=CoffeeLake-U GT3e [Iris Plus Graphics 655]
pci:v00008086d00003EC2*
ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00004036*
ID_MODEL_FROM_DATABASE=5400 Chipset FBD Registers
+pci:v00008086d00004041*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane]
+
pci:v00008086d00004100*
ID_MODEL_FROM_DATABASE=Moorestown Graphics and Video
pci:v00008086d00004117*
ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #4
+pci:v00008086d00004140*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane]
+
+pci:v00008086d00004140sv00001028sd00002134*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (SED 400GB 2.5" U.2 (P5800X))
+
+pci:v00008086d00004140sv00001028sd00002135*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (SED 800GB 2.5" U.2 (P5800X))
+
+pci:v00008086d00004140sv00001028sd00002136*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (SED 1.6GB 2.5" U.2 (P5800X))
+
+pci:v00008086d00004140sv00001028sd00002137*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (400GB 2.5" U.2 (P5800X))
+
+pci:v00008086d00004140sv00001028sd00002138*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (800GB 2.5" U.2 (P5800X))
+
+pci:v00008086d00004140sv00001028sd00002139*
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (1.6TB 2.5" U.2 (P5800X))
+
pci:v00008086d00004220*
ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection
pci:v00008086d0000467F*
ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller
+pci:v00008086d00004680*
+ ID_MODEL_FROM_DATABASE=AlderLake-S GT1
+
+pci:v00008086d000046A0*
+ ID_MODEL_FROM_DATABASE=AlderLake-P GT2
+
+pci:v00008086d00004905*
+ ID_MODEL_FROM_DATABASE=DG1 [Iris Xe MAX Graphics]
+
+pci:v00008086d00004906*
+ ID_MODEL_FROM_DATABASE=DG1 [Iris Xe Pod]
+
+pci:v00008086d00004907*
+ ID_MODEL_FROM_DATABASE=SG1 [Server GPU SG-18M]
+
+pci:v00008086d00004908*
+ ID_MODEL_FROM_DATABASE=DG1 [Iris Xe Graphics]
+
pci:v00008086d00004C3D*
ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller
+pci:v00008086d00004F80*
+ ID_MODEL_FROM_DATABASE=DG2
+
+pci:v00008086d00004F81*
+ ID_MODEL_FROM_DATABASE=DG2
+
+pci:v00008086d00004F82*
+ ID_MODEL_FROM_DATABASE=DG2
+
pci:v00008086d00005001*
ID_MODEL_FROM_DATABASE=LE80578
pci:v00008086d00008500sv00001993sd00000DEF*
ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#0)
+pci:v00008086d00008603*
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP Dynamic Tuning Processor Participant
+
pci:v00008086d000087C0*
ID_MODEL_FROM_DATABASE=UHD Graphics 617
pci:v00008086d00008A0D*
ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 NHI #1
+pci:v00008086d00008A12*
+ ID_MODEL_FROM_DATABASE=Ice Lake-LP Processor Host Bridge/DRAM Registers
+
pci:v00008086d00008A13*
ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 USB Controller
pci:v00008086d00008A17*
ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 NHI #0
+pci:v00008086d00008A19*
+ ID_MODEL_FROM_DATABASE=Image Signal Processor
+
pci:v00008086d00008A1D*
ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #0
pci:v00008086d00008C02sv0000103Csd00001998*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (EliteDesk 800 G1)
+pci:v00008086d00008C02sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkCentre E73)
+
pci:v00008086d00008C02sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkCentre M83)
pci:v00008086d00008C10sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (ThinkPad T440p)
+pci:v00008086d00008C10sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (ThinkCentre E73)
+
pci:v00008086d00008C11*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1
pci:v00008086d00008C1A*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6
+pci:v00008086d00008C1Asv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6 (ThinkCentre E73)
+
pci:v00008086d00008C1B*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6
pci:v00008086d00008C22sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkPad T440p)
+pci:v00008086d00008C22sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkCentre E73)
+
pci:v00008086d00008C22sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkCentre M83)
pci:v00008086d00008C26sv000017AAsd00002210*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T540p)
+pci:v00008086d00008C26sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkCentre E73)
+
pci:v00008086d00008C26sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkCentre M83)
pci:v00008086d00008C2Dsv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkPad T440p)
+pci:v00008086d00008C2Dsv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkCentre E73)
+
pci:v00008086d00008C2Dsv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkCentre M83)
pci:v00008086d00008C31sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkPad T440p)
+pci:v00008086d00008C31sv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkCentre E73)
+
pci:v00008086d00008C31sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkCentre M83)
pci:v00008086d00008C3Asv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkPad T440p)
+pci:v00008086d00008C3Asv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkCentre E73)
+
pci:v00008086d00008C3Asv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkCentre M83)
pci:v00008086d00008C5C*
ID_MODEL_FROM_DATABASE=H81 Express LPC Controller
+pci:v00008086d00008C5Csv000017AAsd00003098*
+ ID_MODEL_FROM_DATABASE=H81 Express LPC Controller (ThinkCentre E73)
+
pci:v00008086d00008C5D*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d000096A1*
ID_MODEL_FROM_DATABASE=Integrated RAID
+pci:v00008086d00009A03*
+ ID_MODEL_FROM_DATABASE=TigerLake-LP Dynamic Tuning Processor Participant
+
pci:v00008086d00009A09*
ID_MODEL_FROM_DATABASE=11th Gen Core Processor PCIe Controller
pci:v00008086d00009A0B*
ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller
+pci:v00008086d00009A0D*
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Telemetry Aggregator
+
pci:v00008086d00009A13*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt USB Controller
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 USB Controller
pci:v00008086d00009A14*
ID_MODEL_FROM_DATABASE=11th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00009A17*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt USB Controller
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 USB Controller
pci:v00008086d00009A1B*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt NHI #0
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 NHI #0
pci:v00008086d00009A1D*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt NHI #1
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 NHI #1
pci:v00008086d00009A1F*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt NHI #0
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 NHI #0
pci:v00008086d00009A21*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt NHI #1
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 NHI #1
pci:v00008086d00009A23*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt PCI Express Root Port #0
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #0
pci:v00008086d00009A25*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt PCI Express Root Port #1
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #1
pci:v00008086d00009A27*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt PCI Express Root Port #2
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #2
pci:v00008086d00009A29*
- ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt PCI Express Root Port #3
+ ID_MODEL_FROM_DATABASE=Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #3
pci:v00008086d00009A2B*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt PCI Express Root Port #0
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 PCI Express Root Port #0
pci:v00008086d00009A2D*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt PCI Express Root Port #1
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 PCI Express Root Port #1
pci:v00008086d00009A2F*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt PCI Express Root Port #2
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 PCI Express Root Port #2
pci:v00008086d00009A31*
- ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt PCI Express Root Port #3
+ ID_MODEL_FROM_DATABASE=Tiger Lake-H Thunderbolt 4 PCI Express Root Port #3
pci:v00008086d00009A33*
ID_MODEL_FROM_DATABASE=Tiger Lake Trace Hub
pci:v00008086d00009A49*
- ID_MODEL_FROM_DATABASE=Iris Xe Graphics
+ ID_MODEL_FROM_DATABASE=TigerLake GT2 [Iris Xe Graphics]
pci:v00008086d00009B41*
- ID_MODEL_FROM_DATABASE=UHD Graphics
+ ID_MODEL_FROM_DATABASE=CometLake-U GT2 [UHD Graphics]
pci:v00008086d00009B44*
ID_MODEL_FROM_DATABASE=10th Gen Core Processor Host Bridge/DRAM Registers
+pci:v00008086d00009B53*
+ ID_MODEL_FROM_DATABASE=Comet Lake-S 6c Host Bridge/DRAM Controller
+
pci:v00008086d00009B54*
ID_MODEL_FROM_DATABASE=10th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00009B61*
ID_MODEL_FROM_DATABASE=Comet Lake-U v1 4c Host Bridge/DRAM Controller
+pci:v00008086d00009B63*
+ ID_MODEL_FROM_DATABASE=10th Gen Core Processor Host Bridge/DRAM Registers
+
pci:v00008086d00009B64*
ID_MODEL_FROM_DATABASE=10th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00009BC4*
- ID_MODEL_FROM_DATABASE=UHD Graphics
+ ID_MODEL_FROM_DATABASE=CometLake-H GT2 [UHD Graphics]
+
+pci:v00008086d00009BC5*
+ ID_MODEL_FROM_DATABASE=CometLake-S GT2 [UHD Graphics 630]
pci:v00008086d00009BC8*
- ID_MODEL_FROM_DATABASE=UHD Graphics 630
+ ID_MODEL_FROM_DATABASE=CometLake-S GT2 [UHD Graphics 630]
pci:v00008086d00009C00*
ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode]
pci:v00008086d00009D03sv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude E7470)
+pci:v00008086d00009D03sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D03sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude 3570)
pci:v00008086d00009D18*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9
+pci:v00008086d00009D18sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 (ThinkPad T570)
+
pci:v00008086d00009D18sv000017AAsd0000382A*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 (B51-80 Laptop)
pci:v00008086d00009D21sv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude E7470)
+pci:v00008086d00009D21sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D21sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude 3570)
pci:v00008086d00009D21sv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (EliteBook 840 G3)
+pci:v00008086d00009D21sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (ThinkPad T570)
+
pci:v00008086d00009D21sv000017AAsd0000224F*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (ThinkPad X1 Carbon 5th Gen)
pci:v00008086d00009D23sv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude E7470)
+pci:v00008086d00009D23sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D23sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude 3570)
pci:v00008086d00009D2Fsv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude E7470)
+pci:v00008086d00009D2Fsv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D2Fsv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude 3570)
pci:v00008086d00009D31sv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude E7470)
+pci:v00008086d00009D31sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D31sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude 3570)
pci:v00008086d00009D32sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=CSI-2 Host Controller (Latitude 7275 tablet)
+pci:v00008086d00009D32sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=CSI-2 Host Controller (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D35*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Integrated Sensor Hub
pci:v00008086d00009D35sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Integrated Sensor Hub (Latitude 7275 tablet)
+pci:v00008086d00009D35sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Integrated Sensor Hub (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D3A*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1
pci:v00008086d00009D3Asv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude E7470)
+pci:v00008086d00009D3Asv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D3Asv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude 3570)
pci:v00008086d00009D3Dsv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Active Management Technology - SOL (EliteBook 840 G3)
+pci:v00008086d00009D3Dsv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Active Management Technology - SOL (ThinkPad T570)
+
pci:v00008086d00009D43*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller
pci:v00008086d00009D46sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=LPC/eSPI Controller (Latitude 7275 tablet)
+pci:v00008086d00009D46sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=LPC/eSPI Controller (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D48*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller
pci:v00008086d00009D48sv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (EliteBook 840 G3)
+pci:v00008086d00009D48sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (ThinkPad T570)
+
pci:v00008086d00009D4E*
ID_MODEL_FROM_DATABASE=Sunrise Point LPC Controller/eSPI Controller
pci:v00008086d00009D60sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (Latitude 7275 tablet)
+pci:v00008086d00009D60sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D60sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (Latitude 3570)
pci:v00008086d00009D61sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #1 (Latitude 7275 tablet)
+pci:v00008086d00009D61sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #1 (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D62*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2
pci:v00008086d00009D62sv00001028sd000006D6*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2 (Latitude 7275 tablet)
+pci:v00008086d00009D62sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2 (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D63*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #3
pci:v00008086d00009D70sv00001028sd000006DC*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude E7470)
+pci:v00008086d00009D70sv00001028sd000006E6*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude 11 5175 2-in-1)
+
pci:v00008086d00009D70sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude 3570)
pci:v00008086d00009D70sv0000103Csd00008079*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (EliteBook 840 G3)
+pci:v00008086d00009D70sv000017AAsd00002247*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (ThinkPad T570)
+
pci:v00008086d00009D70sv000017AAsd0000382A*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (B51-80 Laptop)
pci:v00008086d0000A0B0*
ID_MODEL_FROM_DATABASE=Tiger Lake-LP PCI Express Root Port #9
+pci:v00008086d0000A0BD*
+ ID_MODEL_FROM_DATABASE=Tigerlake PCH-LP PCI Express Root Port #6
+
pci:v00008086d0000A0BF*
ID_MODEL_FROM_DATABASE=Tiger Lake-LP PCI Express Root Port #8
pci:v00008086d0000A382*
ID_MODEL_FROM_DATABASE=400 Series Chipset Family SATA AHCI Controller
+pci:v00008086d0000A3A1*
+ ID_MODEL_FROM_DATABASE=Memory controller
+
pci:v00008086d0000A3A3*
ID_MODEL_FROM_DATABASE=Comet Lake PCH-V SMBus Host Controller
+pci:v00008086d0000A3AF*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-V USB Controller
+
pci:v00008086d0000A3B1*
ID_MODEL_FROM_DATABASE=Comet Lake PCH-V Thermal Subsystem
pci:v00008088d00000101sv00008088sd00000201*
ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T)
+pci:v00008088d00000101sv00008088sd00004201*
+ ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T (WOL))
+
+pci:v00008088d00000101sv00008088sd00008201*
+ ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T (NCSI))
+
+pci:v00008088d00000101sv00008088sd0000C201*
+ ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T (WOL, NCSI))
+
pci:v00008088d00000102*
ID_MODEL_FROM_DATABASE=WX1860A2S Gigabit Ethernet Controller
pci:v00008088d00000103sv00008088sd00000440*
ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400-OCP)
+pci:v00008088d00000103sv00008088sd00004103*
+ ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400T (WOL))
+
+pci:v00008088d00000103sv00008088sd00008103*
+ ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400T (NCSI))
+
+pci:v00008088d00000103sv00008088sd0000C103*
+ ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400T (WOL, NCSI))
+
pci:v00008088d00000104*
ID_MODEL_FROM_DATABASE=WX1860A4S Gigabit Ethernet Controller
pci:v00008088d00000105sv00008088sd00000202*
ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT)
+pci:v00008088d00000105sv00008088sd00004202*
+ ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT (WOL))
+
+pci:v00008088d00000105sv00008088sd00008202*
+ ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT (NCSI))
+
+pci:v00008088d00000105sv00008088sd0000C202*
+ ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT (WOL, NCSI))
+
pci:v00008088d00000106*
ID_MODEL_FROM_DATABASE=WX1860AL2S Gigabit Ethernet Controller
pci:v00008088d00000107sv00008088sd00000402*
ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400HT)
+pci:v00008088d00000107sv00008088sd00004402*
+ ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400HT (WOL))
+
+pci:v00008088d00000107sv00008088sd00008402*
+ ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400HT (NCSI))
+
+pci:v00008088d00000107sv00008088sd0000C402*
+ ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller (Quad-Port Ethernet Network Adaptor SF400HT (WOL, NCSI))
+
pci:v00008088d00000108*
ID_MODEL_FROM_DATABASE=WX1860AL4S Gigabit Ethernet Controller
pci:v00008088d00000108sv00008088sd00000420*
ID_MODEL_FROM_DATABASE=WX1860AL4S Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400HT-S)
+pci:v00008088d00000109*
+ ID_MODEL_FROM_DATABASE=WX1860-LC Gigabit Ethernet Controller
+
+pci:v00008088d0000010A*
+ ID_MODEL_FROM_DATABASE=WX1860A1 Gigabit Ethernet Controller
+
+pci:v00008088d0000010B*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller
+
+pci:v00008088d0000010Bsv00008088sd00000102*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller (Single-Port Ethernet Network Adaptor SF100HT)
+
+pci:v00008088d0000010Bsv00008088sd00004102*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller (Single-Port Ethernet Network Adaptor SF100HT (WOL))
+
+pci:v00008088d0000010Bsv00008088sd00008102*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller (Single-Port Ethernet Network Adaptor SF100HT (NCSI))
+
+pci:v00008088d0000010Bsv00008088sd0000C102*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller (Single-Port Ethernet Network Adaptor SF100HT (WOL, NCSI))
+
+pci:v00008088d00000111*
+ ID_MODEL_FROM_DATABASE=WX1860A2 Ethernet Controller Virtual Function
+
+pci:v00008088d00000113*
+ ID_MODEL_FROM_DATABASE=WX1860A4 Ethernet Controller Virtual Function
+
+pci:v00008088d00000115*
+ ID_MODEL_FROM_DATABASE=WX1860AL2 Ethernet Controller Virtual Function
+
+pci:v00008088d00000117*
+ ID_MODEL_FROM_DATABASE=WX1860AL4 Ethernet Controller Virtual Function
+
+pci:v00008088d00000119*
+ ID_MODEL_FROM_DATABASE=WX1860-LC Gigabit Ethernet Controller Virtual Function
+
+pci:v00008088d0000011A*
+ ID_MODEL_FROM_DATABASE=WX1860A1 Gigabit Ethernet Controller Virtual Function
+
+pci:v00008088d0000011B*
+ ID_MODEL_FROM_DATABASE=WX1860AL1 Gigabit Ethernet Controller Virtual Function
+
+pci:v00008088d00001000*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller RP1000 Virtual Function for 10GbE SFP+
+
pci:v00008088d00001001*
ID_MODEL_FROM_DATABASE=Ethernet Controller RP1000 for 10GbE SFP+
pci:v00008088d00001001sv00008088sd00000000*
ID_MODEL_FROM_DATABASE=Ethernet Controller RP1000 for 10GbE SFP+ (Ethernet Network Adaptor RP1000 for 10GbE SFP+)
+pci:v00008088d00002000*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller RP2000 Virtual Function for 10GbE SFP+
+
pci:v00008088d00002001*
ID_MODEL_FROM_DATABASE=Ethernet Controller RP2000 for 10GbE SFP+
ID_MODEL_FROM_DATABASE=W89C940
pci:v0000E159*
- ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc.
+ ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc. / ICP DAS
pci:v0000E159d00000001*
ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface
pci:v0000EA01d00000800*
ID_MODEL_FROM_DATABASE=PCI-800 Digital I/O Card
+pci:v0000EA50*
+ ID_VENDOR_FROM_DATABASE=Emerson Automation Solutions
+
pci:v0000EA60*
ID_VENDOR_FROM_DATABASE=RME
usb:v0421p0157*
ID_MODEL_FROM_DATABASE=5800 XpressMusic (Imaging mode)
+usb:v0421p0189*
+ ID_MODEL_FROM_DATABASE=N810 Internet Tablet WiMAX
+
usb:v0421p0199*
ID_MODEL_FROM_DATABASE=6700 Classic (msc)
ID_MODEL_FROM_DATABASE=N900 (Storage Mode)
usb:v0421p01C8*
- ID_MODEL_FROM_DATABASE=N900 (PC-Suite Mode)
+ ID_MODEL_FROM_DATABASE=N900/N950 (PC-Suite Mode)
usb:v0421p0228*
ID_MODEL_FROM_DATABASE=5530 XpressMusic
ID_MODEL_FROM_DATABASE=C7-00 (Nokia Suite mode)
usb:v0421p03D1*
- ID_MODEL_FROM_DATABASE=N950
+ ID_MODEL_FROM_DATABASE=N950 (Storage Mode)
+
+usb:v0421p03D2*
+ ID_MODEL_FROM_DATABASE=N950 (PC Suite mode)
usb:v0421p0400*
ID_MODEL_FROM_DATABASE=7600 Phone Parent
ID_MODEL_FROM_DATABASE=6230i MultiMedia Card
usb:v0421p0431*
- ID_MODEL_FROM_DATABASE=770 Internet Tablet
+ ID_MODEL_FROM_DATABASE=770/N800 Internet Tablet
usb:v0421p0432*
ID_MODEL_FROM_DATABASE=N90 Phone Parent
ID_MODEL_FROM_DATABASE=E65 (Storage mode)
usb:v0421p0518*
- ID_MODEL_FROM_DATABASE=N9 Phone
+ ID_MODEL_FROM_DATABASE=N9 (Storage mode)
+
+usb:v0421p0519*
+ ID_MODEL_FROM_DATABASE=N9 (RNDIS/Ethernet mode)
+
+usb:v0421p051A*
+ ID_MODEL_FROM_DATABASE=N9 (PC Suite mode)
usb:v0421p054D*
ID_MODEL_FROM_DATABASE=C2-01
usb:v05FCp0010*
ID_MODEL_FROM_DATABASE=Soundcraft Si MADI combo card
+usb:v05FCp0021*
+ ID_MODEL_FROM_DATABASE=Soundcraft Signature 12 MTK
+
usb:v05FCp7849*
ID_MODEL_FROM_DATABASE=Harman/Kardon SoundSticks
usb:v32B3pD1A7*
ID_MODEL_FROM_DATABASE=TXT Multihub
+usb:v3310*
+ ID_VENDOR_FROM_DATABASE=MUDITA Sp. z o.o.
+
+usb:v3310p0100*
+ ID_MODEL_FROM_DATABASE=Pure
+
+usb:v3310p0101*
+ ID_MODEL_FROM_DATABASE=Pure tethering
+
usb:v3333*
ID_VENDOR_FROM_DATABASE=InLine
--- /dev/null
+# This file is part of systemd.
+#
+# Rules to autosuspend known fingerprint readers (pulled from libfprint).
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# This file has been generated using fprint-list-udev-hwdb with all drivers enabled
+
+# Supported by libfprint driver upektc_img
+usb:v147Ep2016*
+usb:v147Ep2020*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver vfs5011
+usb:v138Ap0010*
+usb:v138Ap0011*
+usb:v138Ap0015*
+usb:v138Ap0017*
+usb:v138Ap0018*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes3500
+usb:v08FFp5731*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes4000
+usb:v5501p08FF*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes1610
+usb:v08FFp1600*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes1660
+usb:v08FFp1660*
+usb:v08FFp1680*
+usb:v08FFp1681*
+usb:v08FFp1682*
+usb:v08FFp1683*
+usb:v08FFp1684*
+usb:v08FFp1685*
+usb:v08FFp1686*
+usb:v08FFp1687*
+usb:v08FFp1688*
+usb:v08FFp1689*
+usb:v08FFp168A*
+usb:v08FFp168B*
+usb:v08FFp168C*
+usb:v08FFp168D*
+usb:v08FFp168E*
+usb:v08FFp168F*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes2660
+usb:v08FFp2660*
+usb:v08FFp2680*
+usb:v08FFp2681*
+usb:v08FFp2682*
+usb:v08FFp2683*
+usb:v08FFp2684*
+usb:v08FFp2685*
+usb:v08FFp2686*
+usb:v08FFp2687*
+usb:v08FFp2688*
+usb:v08FFp2689*
+usb:v08FFp268A*
+usb:v08FFp268B*
+usb:v08FFp268C*
+usb:v08FFp268D*
+usb:v08FFp268E*
+usb:v08FFp268F*
+usb:v08FFp2691*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes2501
+usb:v08FFp2500*
+usb:v08FFp2580*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver aes2550
+usb:v08FFp2550*
+usb:v08FFp2810*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver vfs101
+usb:v138Ap0001*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver vfs301
+usb:v138Ap0005*
+usb:v138Ap0008*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver vfs0050
+usb:v138Ap0050*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver etes603
+usb:v1C7Ap0603*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver vcom5s
+usb:v061Ap0110*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver synaptics
+usb:v06CBp00BD*
+usb:v06CBp00E9*
+usb:v06CBp00DF*
+usb:v06CBp00F9*
+usb:v06CBp00FC*
+usb:v06CBp00C2*
+usb:v06CBp00C9*
+usb:v06CBp00E7*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver elan
+usb:v04F3p0903*
+usb:v04F3p0907*
+usb:v04F3p0C01*
+usb:v04F3p0C02*
+usb:v04F3p0C03*
+usb:v04F3p0C04*
+usb:v04F3p0C05*
+usb:v04F3p0C06*
+usb:v04F3p0C07*
+usb:v04F3p0C08*
+usb:v04F3p0C09*
+usb:v04F3p0C0A*
+usb:v04F3p0C0B*
+usb:v04F3p0C0C*
+usb:v04F3p0C0D*
+usb:v04F3p0C0E*
+usb:v04F3p0C0F*
+usb:v04F3p0C10*
+usb:v04F3p0C11*
+usb:v04F3p0C12*
+usb:v04F3p0C13*
+usb:v04F3p0C14*
+usb:v04F3p0C15*
+usb:v04F3p0C16*
+usb:v04F3p0C17*
+usb:v04F3p0C18*
+usb:v04F3p0C19*
+usb:v04F3p0C1A*
+usb:v04F3p0C1B*
+usb:v04F3p0C1C*
+usb:v04F3p0C1D*
+usb:v04F3p0C1E*
+usb:v04F3p0C1F*
+usb:v04F3p0C20*
+usb:v04F3p0C21*
+usb:v04F3p0C22*
+usb:v04F3p0C23*
+usb:v04F3p0C24*
+usb:v04F3p0C25*
+usb:v04F3p0C26*
+usb:v04F3p0C27*
+usb:v04F3p0C28*
+usb:v04F3p0C29*
+usb:v04F3p0C2A*
+usb:v04F3p0C2B*
+usb:v04F3p0C2C*
+usb:v04F3p0C2D*
+usb:v04F3p0C2E*
+usb:v04F3p0C2F*
+usb:v04F3p0C30*
+usb:v04F3p0C31*
+usb:v04F3p0C32*
+usb:v04F3p0C33*
+usb:v04F3p0C42*
+usb:v04F3p0C4D*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver uru4000
+usb:v045Ep00BC*
+usb:v045Ep00BD*
+usb:v045Ep00CA*
+usb:v05BAp0007*
+usb:v05BAp0008*
+usb:v05BAp000A*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver upektc
+usb:v0483p2015*
+usb:v147Ep3001*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver upeksonly
+usb:v147Ep1000*
+usb:v147Ep1001*
+ ID_AUTOSUSPEND=1
+
+# Supported by libfprint driver goodixmoc
+usb:v27C6p5840*
+usb:v27C6p6496*
+usb:v27C6p60A2*
+usb:v27C6p63AC*
+usb:v27C6p639C*
+ ID_AUTOSUSPEND=1
+
+# Known unsupported devices
+usb:v04F3p036B*
+usb:v04F3p0C00*
+usb:v04F3p0C4B*
+usb:v04F3p0C4C*
+usb:v04F3p0C4F*
+usb:v04F3p0C57*
+usb:v04F3p2706*
+usb:v06CBp0081*
+usb:v06CBp0088*
+usb:v06CBp008A*
+usb:v06CBp009A*
+usb:v06CBp009B*
+usb:v06CBp00A2*
+usb:v06CBp00B7*
+usb:v06CBp00BB*
+usb:v06CBp00BE*
+usb:v06CBp00CB*
+usb:v06CBp00D8*
+usb:v06CBp00DA*
+usb:v0A5Cp5801*
+usb:v0A5Cp5805*
+usb:v0A5Cp5834*
+usb:v0A5Cp5843*
+usb:v10A5p0007*
+usb:v1188p9545*
+usb:v138Ap0007*
+usb:v138Ap003A*
+usb:v138Ap003C*
+usb:v138Ap003D*
+usb:v138Ap003F*
+usb:v138Ap0090*
+usb:v138Ap0091*
+usb:v138Ap0092*
+usb:v138Ap0094*
+usb:v138Ap0097*
+usb:v138Ap009D*
+usb:v138Ap00AB*
+usb:v147Ep1002*
+usb:v1491p0088*
+usb:v16D1p1027*
+usb:v1C7Ap0300*
+usb:v1C7Ap0570*
+usb:v1C7Ap0575*
+usb:v27C6p5042*
+usb:v27C6p5110*
+usb:v27C6p5117*
+usb:v27C6p5201*
+usb:v27C6p521D*
+usb:v27C6p5301*
+usb:v27C6p530C*
+usb:v27C6p532D*
+usb:v27C6p533C*
+usb:v27C6p5381*
+usb:v27C6p5385*
+usb:v27C6p538C*
+usb:v27C6p538D*
+usb:v27C6p5395*
+usb:v27C6p5584*
+usb:v27C6p55A2*
+usb:v27C6p55A4*
+usb:v27C6p55B4*
+usb:v27C6p5740*
+usb:v2808p9338*
+usb:v298Dp2033*
+usb:v3538p0930*
+ ID_AUTOSUSPEND=1
# Sort by brand, model
+#########################################
+# ACECAD
+#########################################
+
+# Acecad Flair / Pentagram Quadpen
+evdev:input:b0003v0460p0004*
+ EVDEV_ABS_00=::40
+ EVDEV_ABS_01=::40
+
#########################################
# AIPTEK
#########################################
EVDEV_ABS_00=1008:5793:66
EVDEV_ABS_01=687:5176:107
+# Dell Latitude E5510
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnDellInc.:pnLatitudeE5510:*
+ EVDEV_ABS_00=73:1828:26
+ EVDEV_ABS_01=101:1319:27
+ EVDEV_ABS_35=73:1828:26
+ EVDEV_ABS_36=101:1319:27
+
# Dell Latitude E6220
evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220:*
EVDEV_ABS_00=76:1815:22
EVDEV_ABS_00=0:10000:400
EVDEV_ABS_01=0:6250:400
-#WALTOP International Corp. Graphics Tablet
+# WALTOP International Corp. Graphics Tablet
evdev:input:b0003v172Fp0047*
EVDEV_ABS_00=0:20000:80
EVDEV_ABS_01=0:12500:80
+
+# WALTOP International Corp. Batteryless Tablet
+evdev:input:b0003v172Fp0505*
+ EVDEV_ABS_00=::160
+ EVDEV_ABS_01=::160
# HP EliteBook Folio G1
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPEliteBookFolioG1:*
KEYBOARD_KEY_64=calendar
- KEYBOARD_KEY_81=micmute
+ KEYBOARD_KEY_81=f20
# HP ProBook 650
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:*
evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI:*
KEYBOARD_KEY_287=f20 # Microphone mute button, should be micmute
-# Huawei MACH-WX9
+# Huawei MACH-WX9 and EUL-WX9
evdev:atkbd:dmi:bvn*:bvr*:svnHUAWEI*:pnMACH-WX9:*
+evdev:atkbd:dmi:bvn*:bvr*:svnHUAWEI*:pnEUL-WX9:*
KEYBOARD_KEY_f7=unknown
KEYBOARD_KEY_f8=fn
evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*:pnMACH-WX9:*
+evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*:pnEUL-WX9:*
KEYBOARD_KEY_281=unknown # Brightness Down, also emitted by acpi-video, ignore
KEYBOARD_KEY_282=unknown # Brightness Up, also emitted by acpi-video, ignore
KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up
KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34][AB]*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X3A*:*
KEYBOARD_KEY_ce=! # Fn+F8 keyboard backlight up
KEYBOARD_KEY_8d=! # Fn+F7 keyboard backlight down
KEYBOARD_KEY_96=! # Fn+F1 performance mode (?)
sensor:modalias:acpi:ACCE0001*:dmi:*svnEndless*:*pnELT-NL3:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 0, 0, -1; -1, 0, 0
+#########################################
+# Estar
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*:svnEstar:pneSTARBEAUTYHDIntelQuadcore:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
#########################################
# Eve Technology
#########################################
sensor:modalias:acpi:BOSC0200*:dmi:*:svnJumper:pnEZpad:*:rvr.A006:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1
+# EZpad 7
+sensor:modalias:acpi:KIOX0009*:dmi:*:bvrJumper12x.WJ2012.bsBKRCP*:svnJumper:pnEZpad:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
# EZpad Go
sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnjumper:pnEZpad:*:ct31:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
#########################################
# Medion
#########################################
+# Medion Akoya E2228T MD61900
+sensor:modalias:acpi:KIOX020A*:dmi:*:svnMEDION:pnE2228TMD61900:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
+ ACCEL_LOCATION=base
# Medion Akoya E1239T MD60568
sensor:modalias:acpi:KIOX0009*:dmi:*:svnMEDION:pnE1239TMD60568:*
sensor:modalias:acpi:SMO8500*:dmi:*:svnProwise:pnPT301:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+#########################################
+# Reeder
+#########################################
+
+# A8iW-Rev.A
+sensor:modalias:acpi:SMO8500*:dmi:*:rvnReeder:rnA8iW-Rev.A:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
#########################################
# Schneider
#########################################
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:*
+sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnYourbookC11B:*
+sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnYOURBOOKC11B:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
ACCEL_LOCATION=display
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:*
sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:*
+sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnYourbookC11B:*
+sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnYOURBOOKC11B:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
ACCEL_LOCATION=base
Hsinchu 30077\r
TW\r
\r
-C8-C6-4A (hex) Flextronics Tech.(Ind) Pvt Ltd\r
-C8C64A (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
- SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC\r
- Chennai 602107\r
- IN\r
-\r
30-EA-26 (hex) Sycada BV\r
30EA26 (base 16) Sycada BV\r
Burgemeester Stramanweg 105B\r
Hangzhou Zhejiang 310052\r
CN\r
\r
-8C-E7-48 (hex) Private\r
-8CE748 (base 16) Private\r
-\r
10-82-86 (hex) Luxshare Precision Industry Co.,Ltd\r
108286 (base 16) Luxshare Precision Industry Co.,Ltd\r
2nd floor, A building, Sanyo New Industrial Area, West of Maoyi, Shajing Baoan District\r
Seoul 153-801\r
KR\r
\r
-E8-9E-0C (hex) Private\r
-E89E0C (base 16) Private\r
-\r
48-E6-C0 (hex) SIMCom Wireless Solutions Co.,Ltd.\r
48E6C0 (base 16) SIMCom Wireless Solutions Co.,Ltd.\r
Building B,SIM Technology Building,No.633,Jinzhong Road\r
San Jose CA 94568\r
US\r
\r
-2C-B8-ED (hex) SonicWall\r
-2CB8ED (base 16) SonicWall\r
- 5455 Great America Parkway\r
- Santa Clara CA 95054\r
- US\r
-\r
68-D4-82 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT\r
68D482 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT\r
SONGGANG\r
Tokyo 196-8666\r
JP\r
\r
-00-04-7D (hex) Pelco\r
-00047D (base 16) Pelco\r
- 3500 Pelco Way\r
- Clovis CA 93612\r
- US\r
-\r
00-07-BF (hex) Armillaire Technologies, Inc.\r
0007BF (base 16) Armillaire Technologies, Inc.\r
10411 Motor City Drive\r
Huntingdon TN 38344\r
US\r
\r
-0C-51-D0 (hex) Altice Labs S.A.\r
-0C51D0 (base 16) Altice Labs S.A.\r
- NIF 504705610, Rua Eng. José Ferreira Pinto Basto\r
- Aveiro 3810-106\r
- PT\r
-\r
A4-5E-5A (hex) ACTIVIO Inc.\r
A45E5A (base 16) ACTIVIO Inc.\r
Takeuchi Lorie Bldg. Room 503, 1-34-12, Takadanobaba\r
Vancouver WA 98682\r
US\r
\r
+4C-F2-02 (hex) Xiaomi Communications Co Ltd\r
+4CF202 (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+A8-77-E5 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD\r
+A877E5 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD\r
+ Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China\r
+ SHENZHEN GUANGDONG 518057\r
+ CN\r
+\r
+10-A4-DA (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+10A4DA (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+38-20-28 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+382028 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+E4-77-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E47727 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+10-51-07 (hex) Intel Corporate\r
+105107 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+AC-74-C4 (hex) Maytronics Ltd.\r
+AC74C4 (base 16) Maytronics Ltd.\r
+ Kibbutz Yizrael\r
+ Kibbutz Yizrael 1935000\r
+ IL\r
+\r
+84-D6-08 (hex) Wingtech Mobile Communications Co., Ltd.\r
+84D608 (base 16) Wingtech Mobile Communications Co., Ltd.\r
+ No.777,Yazhong Road,Nanhu District,\r
+ Jiaxing Zhejiang 314006\r
+ CN\r
+\r
+34-68-93 (hex) Tecnovideo Srl\r
+346893 (base 16) Tecnovideo Srl\r
+ Via A. De Gasperi, 3\r
+ Villaverla Vicenza 36030\r
+ IT\r
+\r
+3C-7A-AA (hex) China Dragon Technology Limited\r
+3C7AAA (base 16) China Dragon Technology Limited\r
+ B4 Bldg.Haoshan 1st Industry Park,\r
+ Shenzhen Guangdong 518104\r
+ CN\r
+\r
+6C-47-60 (hex) Sunitec Enterprise Co.,Ltd\r
+6C4760 (base 16) Sunitec Enterprise Co.,Ltd\r
+ 3F.,No.98-1,Mincyuan Rd.Sindian City\r
+ Taipei County 231 231141\r
+ CN\r
+\r
+18-32-19 (hex) EM Microelectronic\r
+183219 (base 16) EM Microelectronic\r
+ Rue des Sors 3\r
+ Marin-Epagnier Neuchatel 2074\r
+ CH\r
+\r
+28-D3-EA (hex) Huawei Device Co., Ltd.\r
+28D3EA (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+A8-F2-66 (hex) Huawei Device Co., Ltd.\r
+A8F266 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-26-7A (hex) GUANGDONG TAIDE ZHILIAN TECHNOLOGY CO.,LTD\r
+84267A (base 16) GUANGDONG TAIDE ZHILIAN TECHNOLOGY CO.,LTD\r
+ Taide Technology Park,Jinfenghuang Industrial District, Fenggang Town,\r
+ Dongguan GUANGDONG 523000 \r
+ CN\r
+\r
+D8-EC-5E (hex) Belkin International Inc.\r
+D8EC5E (base 16) Belkin International Inc.\r
+ 12045 East Waterfront Drive\r
+ Playa Vista 90094\r
+ US\r
+\r
+84-FD-27 (hex) Silicon Laboratories\r
+84FD27 (base 16) Silicon Laboratories\r
+ 400 West Cesar Chavez Street\r
+ Austin 78701\r
+ US\r
+\r
+CC-9C-3E (hex) Cisco Meraki\r
+CC9C3E (base 16) Cisco Meraki\r
+ 500 Terry A. Francois Blvd\r
+ San Francisco 94158\r
+ US\r
+\r
+48-29-E4 (hex) ZAO NPK Rotek\r
+4829E4 (base 16) ZAO NPK Rotek\r
+ Prospekt Mira\r
+ Moscow 129223\r
+ RU\r
+\r
+FC-A9-DC (hex) Renesas Electronics (Penang) Sdn. Bhd.\r
+FCA9DC (base 16) Renesas Electronics (Penang) Sdn. Bhd.\r
+ Phase 3, Bayan Lepas FIZ\r
+ Bayan Lepas Penang 11900\r
+ MY\r
+\r
+FC-58-4A (hex) xiamenshi c-chip technology co., ltd\r
+FC584A (base 16) xiamenshi c-chip technology co., ltd\r
+ Baoyuan Road\r
+ Shenzhen City Guangdong Province 518101\r
+ CN\r
+\r
+78-65-3B (hex) Shaoxing Ourten Electronics Co., Ltd.\r
+78653B (base 16) Shaoxing Ourten Electronics Co., Ltd.\r
+ 3rd Floor # 7, No. 1732 Yanhua industrial park West Renmin Road,Shangyu\r
+ Shaoxing Zhejiang 312000\r
+ CN\r
+\r
+E0-E6-56 (hex) Nethesis srl\r
+E0E656 (base 16) Nethesis srl\r
+ strada degli olmi 12\r
+ Pesaro Pesaro e Urbino 61122\r
+ IT\r
+\r
+90-23-B4 (hex) New H3C Technologies Co., Ltd\r
+9023B4 (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+88-2A-5E (hex) New H3C Technologies Co., Ltd\r
+882A5E (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+84-1E-A3 (hex) Sagemcom Broadband SAS\r
+841EA3 (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+F4-02-23 (hex) PAX Computer Technology(Shenzhen) Ltd.\r
+F40223 (base 16) PAX Computer Technology(Shenzhen) Ltd.\r
+ 4/F, No.3 Building, Software Park, Second Central Science-Tech Road, High-Tech\r
+ Shenzhen GuangDong 518057\r
+ CN\r
+\r
+88-46-04 (hex) Xiaomi Communications Co Ltd\r
+884604 (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+64-6E-E0 (hex) Intel Corporate\r
+646EE0 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+04-56-E5 (hex) Intel Corporate\r
+0456E5 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+08-10-86 (hex) NEC Platforms, Ltd.\r
+081086 (base 16) NEC Platforms, Ltd.\r
+ 2-3 Kandatsukasamachi\r
+ Chiyodaku Tokyo 101-8532\r
+ JP\r
+\r
+64-79-F0 (hex) Intel Corporate\r
+6479F0 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+1C-D1-E0 (hex) Cisco Systems, Inc\r
+1CD1E0 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+24-45-6B (hex) Huawei Device Co., Ltd.\r
+24456B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+48-38-71 (hex) Huawei Device Co., Ltd.\r
+483871 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+44-BD-DE (hex) BHTC GmbH\r
+44BDDE (base 16) BHTC GmbH\r
+ Hansastrasse 40\r
+ Lippstadt 59557\r
+ DE\r
+\r
+8C-2A-8E (hex) DongGuan Ramaxel Memory Technology\r
+8C2A8E (base 16) DongGuan Ramaxel Memory Technology\r
+ No.32, Industrial East Road,Innovation Park, High-tech Industrial Development Zone, Songshan Lake, Dongguan City, Guangdong Province,China\r
+ DongGuan Guangdong 523808\r
+ CN\r
+\r
+40-44-FD (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+4044FD (base 16) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+ No.178 Yulong Avenue, Yufengshan, Yubei District, Chongqing.\r
+ Chongqing China 401120\r
+ CN\r
+\r
+E8-FD-35 (hex) Huawei Device Co., Ltd.\r
+E8FD35 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+EC-C5-D2 (hex) Huawei Device Co., Ltd.\r
+ECC5D2 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+B4-60-8C (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+B4608C (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+B8-14-DB (hex) OHSUNG\r
+B814DB (base 16) OHSUNG\r
+ 335-4,SANHODAERO,GUMI,GYEONG BUK,KOREA\r
+ GUMI GYEONG BUK 730-030\r
+ KR\r
+\r
+80-07-1B (hex) VSOLUTION TELECOMMUNICATION TECHNOLOGY CO.,LTD.\r
+80071B (base 16) VSOLUTION TELECOMMUNICATION TECHNOLOGY CO.,LTD.\r
+ Room 601,Originality Building B2, NO.162 Science Avenue,Science Town\r
+ Guangzhou Guangdong 510663\r
+ CN\r
+\r
+FC-13-F0 (hex) Bouffalo Lab (Nanjing) Co., Ltd.\r
+FC13F0 (base 16) Bouffalo Lab (Nanjing) Co., Ltd.\r
+ 5F, Gongxiang Space, No.100 Tuanjie Road, Nanjing, China\r
+ Nanjing Jiangsu 211800\r
+ CN\r
+\r
+1C-6E-E6 (hex) NHNETWORKS\r
+1C6EE6 (base 16) NHNETWORKS\r
+ 54,Chemdanyeonsin-ro 30beon-gil,Buk-gu\r
+ Gwangju 61080\r
+ KR\r
+\r
+08-F6-06 (hex) zte corporation\r
+08F606 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+E8-9E-0C (hex) MAX8USA DISTRIBUTORS INC.\r
+E89E0C (base 16) MAX8USA DISTRIBUTORS INC.\r
+ 4757 NW 72ND AVENUE\r
+ MIAMI FL 33166\r
+ US\r
+\r
+FC-9C-98 (hex) Arlo Technology\r
+FC9C98 (base 16) Arlo Technology\r
+ 3030 Orchard Parkway\r
+ San Jose CA 95134\r
+ US\r
+\r
+A0-70-B7 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A070B7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+78-B5-54 (hex) Huawei Device Co., Ltd.\r
+78B554 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+68-9E-6A (hex) Huawei Device Co., Ltd.\r
+689E6A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+28-2B-96 (hex) Huawei Device Co., Ltd.\r
+282B96 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+CC-68-B6 (hex) TP-Link Corporation Limited\r
+CC68B6 (base 16) TP-Link Corporation Limited\r
+ Room 901,9/F.New East Ocean Centre, 9 Science Museum Road\r
+ Tsim Sha Tsui Kowloon 999077\r
+ HK\r
+\r
+14-DD-9C (hex) vivo Mobile Communication Co., Ltd.\r
+14DD9C (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+64-64-4A (hex) Beijing Xiaomi Mobile Software Co., Ltd\r
+64644A (base 16) Beijing Xiaomi Mobile Software Co., Ltd\r
+ The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District\r
+ Beijing Beijing 100085\r
+ CN\r
+\r
+A4-39-B6 (hex) SHENZHEN PEIZHE MICROELECTRONICS CO .LTD\r
+A439B6 (base 16) SHENZHEN PEIZHE MICROELECTRONICS CO .LTD\r
+ 1110 Nanshan Street, Nanshan District, Shenzhen, China Petroleum Building 2012\r
+ Shenzhen 518000\r
+ CN\r
+\r
+F4-FB-B8 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F4FBB8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+CC-33-31 (hex) Texas Instruments\r
+CC3331 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+2C-B8-ED (hex) SonicWall\r
+2CB8ED (base 16) SonicWall\r
+ 1033 McCarthy Blvd\r
+ Milpitas CA 95035\r
+ US\r
+\r
+C8-9B-AD (hex) Honor Device Co., Ltd.\r
+C89BAD (base 16) Honor Device Co., Ltd.\r
+ Suite 3401, Unit A, Building 6, Shum Yip Sky Park, No. 8089, Hongli West Road, Xiangmihu Street, Futian District,Shenzhen, Guangdong 518040, People's Republic of China\r
+ Shenzhen 518040\r
+ CN\r
+\r
+C4-5B-BE (hex) Espressif Inc.\r
+C45BBE (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+88-90-09 (hex) Juniper Networks\r
+889009 (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+90-B6-7A (hex) Shenzhen Skyworth Digital Technology CO., Ltd\r
+90B67A (base 16) Shenzhen Skyworth Digital Technology CO., Ltd\r
+ 4F,Block A, Skyworth?Building,\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+7C-D9-F4 (hex) UAB Teltonika Telematics\r
+7CD9F4 (base 16) UAB Teltonika Telematics\r
+ Saltoniskiu str. 9B-1\r
+ Vilnius LT-08105\r
+ LT\r
+\r
+C8-C6-4A (hex) Flextronics Tech.(Ind) Pvt Ltd\r
+C8C64A (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
+ 365, Benjamin Road\r
+ Sricity Vardahiah Palem(M),Chilamathur Village, Chittoor Distict 517646\r
+ IN\r
+\r
+FC-4E-A4 (hex) Apple, Inc.\r
+FC4EA4 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F4-BE-EC (hex) Apple, Inc.\r
+F4BEEC (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+BC-FF-4D (hex) Espressif Inc.\r
+BCFF4D (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+54-E6-1B (hex) Apple, Inc.\r
+54E61B (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+D8-9A-C1 (hex) Nokia\r
+D89AC1 (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+F0-B1-1D (hex) Nokia\r
+F0B11D (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+00-04-7D (hex) Motorola Solutions Inc.\r
+00047D (base 16) Motorola Solutions Inc.\r
+ 500 W Monroe Street, Ste 4400 \r
+ Chicago IL 60661-3781\r
+ US\r
+\r
+A4-D7-95 (hex) Wingtech Mobile Communications Co.,Ltd\r
+A4D795 (base 16) Wingtech Mobile Communications Co.,Ltd\r
+ No.777,Yazhong Road,Nanhu District\r
+ Jiaxing Zhejiang 314001\r
+ CN\r
+\r
+84-AB-26 (hex) Tiinlab Corporation\r
+84AB26 (base 16) Tiinlab Corporation\r
+ 35F,Tower A,Tanglang City,3333 Liuxian Avenue,Nanshan District\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+F8-97-53 (hex) Huawei Device Co., Ltd.\r
+F89753 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+58-94-AE (hex) Huawei Device Co., Ltd.\r
+5894AE (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+B0-3A-CE (hex) Huawei Device Co., Ltd.\r
+B03ACE (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+34-AB-95 (hex) Espressif Inc.\r
+34AB95 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+C4-91-CF (hex) Luxul \r
+C491CF (base 16) Luxul \r
+ 12884 Frontrunner Blvd, Suite 201\r
+ Draper UT 84020\r
+ US\r
+\r
+58-35-6B (hex) TECNO MOBILE LIMITED\r
+58356B (base 16) TECNO MOBILE LIMITED\r
+ ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG\r
+ Hong Kong Hong Kong 999077\r
+ HK\r
+\r
+F8-4C-DA (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F84CDA (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+A8-93-4A (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+A8934A (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+ Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District\r
+ Chongqing Chongqing 401332\r
+ CN\r
+\r
+A4-05-6E (hex) Tiinlab Corporation\r
+A4056E (base 16) Tiinlab Corporation\r
+ 35F,Tower A,Tanglang City,3333 Liuxian Avenue,Nanshan District\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+8C-19-B5 (hex) Arcadyan Corporation\r
+8C19B5 (base 16) Arcadyan Corporation\r
+ No.8, Sec.2, Guangfu Rd.\r
+ Hsinchu City Hsinchu 30071\r
+ TW\r
+\r
+C8-7B-23 (hex) Bose Corporation\r
+C87B23 (base 16) Bose Corporation\r
+ The Mountain\r
+ Framingham MA 01701-9168\r
+ US\r
+\r
+78-D9-E9 (hex) MOMENTUM IOT\r
+78D9E9 (base 16) MOMENTUM IOT\r
+ 100 W. BROADWAY, STE. 500\r
+ LONG BEACH CA 90802\r
+ US\r
+\r
+2C-08-23 (hex) Sercomm France Sarl\r
+2C0823 (base 16) Sercomm France Sarl\r
+ 2/4 Rue Maurice Hartmann 92370 Issy Les Moulineaux France\r
+ Moulineaux 92370\r
+ FR\r
+\r
+30-8E-7A (hex) Shenzhen iComm Semiconductor CO.,LTD\r
+308E7A (base 16) Shenzhen iComm Semiconductor CO.,LTD\r
+ Room 504A,Block B,Digital Building,Gargen City,No.1079,Nanhai Road,Nanshan District,Shenzhen.\r
+ Shenzhen 518067\r
+ CN\r
+\r
+9C-1C-37 (hex) AltoBeam (China) Inc.\r
+9C1C37 (base 16) AltoBeam (China) Inc.\r
+ B808, Tsinghua Tongfang Hi-Tech Plaza, Haidian\r
+ Beijing Beijing 100083\r
+ CN\r
+\r
+8C-E7-48 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+8CE748 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+ No.469,Jianghui Road\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+98-42-65 (hex) Sagemcom Broadband SAS\r
+984265 (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+B8-A3-77 (hex) Cisco Systems, Inc\r
+B8A377 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+E4-4E-2D (hex) Cisco Systems, Inc\r
+E44E2D (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+00-CC-34 (hex) Juniper Networks\r
+00CC34 (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+1C-D1-07 (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+1CD107 (base 16) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+ No.178 Yulong Avenue, Yufengshan, Yubei District, Chongqing.\r
+ Chongqing China 401120\r
+ CN\r
+\r
+10-3D-1C (hex) Intel Corporate\r
+103D1C (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+38-87-D5 (hex) Intel Corporate\r
+3887D5 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
9C-FF-C2 (hex) AVI Systems GmbH\r
9CFFC2 (base 16) AVI Systems GmbH\r
Dr. Franz Wilhelmstraße 2A\r
Beijing Beijing 100012\r
CN\r
\r
-84-C7-8F (hex) STORDIS GmbH\r
-84C78F (base 16) STORDIS GmbH\r
- Rosenwiesstr. 17\r
- Stuttgart 70567\r
- DE\r
-\r
50-41-B9 (hex) I-O DATA DEVICE,INC.\r
5041B9 (base 16) I-O DATA DEVICE,INC.\r
3-10,Sakurada-machi\r
Shenzhen Guangdong 518109\r
CN\r
\r
-00-1F-92 (hex) Avigilon Corporation\r
-001F92 (base 16) Avigilon Corporation\r
- Box 378, 101 - 1001 West Broadway\r
- Vancouver BC V6H 4E4\r
- CA\r
-\r
00-0C-03 (hex) HDMI Licensing, LLC\r
000C03 (base 16) HDMI Licensing, LLC\r
1060 East Arques Ave.\r
Calgary AB T2R 0L4\r
CA\r
\r
-00-80-8C (hex) NetAlly\r
-00808C (base 16) NetAlly\r
- 310 Littleton Road\r
- Westford MA 01886 \r
- US\r
-\r
-04-9F-81 (hex) NetAlly\r
-049F81 (base 16) NetAlly\r
- 310 Littleton Road\r
- Westford MA 01886 \r
- US\r
-\r
00-10-87 (hex) XSTREAMIS PLC\r
001087 (base 16) XSTREAMIS PLC\r
OXFORD SCIENCE PARK\r
San Luis Obispo CA 93401\r
US\r
\r
-00-23-BB (hex) Schmitt Industries\r
-0023BB (base 16) Schmitt Industries\r
- 2765 NW Nicolai St\r
- Portland Oregon 97210\r
- US\r
-\r
00-23-8D (hex) Techno Design Co., Ltd.\r
00238D (base 16) Techno Design Co., Ltd.\r
312-2\r
St. Ingbert Saarland 66386\r
DE\r
\r
-00-1A-86 (hex) AdvancedIO Systems Inc\r
-001A86 (base 16) AdvancedIO Systems Inc\r
- 595 Howe Street, Suite 502\r
- Vancouver BC V6C 2T5\r
- CA\r
-\r
00-1A-C7 (hex) UNIPOINT\r
001AC7 (base 16) UNIPOINT\r
7F Gwangsung Bld 831-47 YeokSam-Dong\r
San Jose CA 94568\r
US\r
\r
-D8-D5-B9 (hex) Rainforest Automation, Inc.\r
-D8D5B9 (base 16) Rainforest Automation, Inc.\r
- 827 Cambie St.\r
- Vancouver British Columbia V6B 2P4\r
- CA\r
-\r
00-1B-B0 (hex) Bharat Electronics Limited\r
001BB0 (base 16) Bharat Electronics Limited\r
JALAHALLI POST\r
Grand Rapids MI 49505\r
US\r
\r
+88-C3-E5 (hex) Betop Techonologies \r
+88C3E5 (base 16) Betop Techonologies \r
+ 6F., No. 669, Bannan Road, Zhonghe District\r
+ New Taipei City 235\r
+ TW\r
+\r
+E4-28-A4 (hex) Prama India Private Limited\r
+E428A4 (base 16) Prama India Private Limited\r
+ Off 103, 765 Fly Edge, TPS III Jn of S V Rd, Nr Kora Kendra\r
+ Borivali West, Mumbai Maharashtra 400092\r
+ IN\r
+\r
+94-3A-91 (hex) Amazon Technologies Inc.\r
+943A91 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102 \r
+ Reno NV 89507\r
+ US\r
+\r
+00-0F-A0 (hex) CANON KOREA BUSINESS SOLUTIONS INC.\r
+000FA0 (base 16) CANON KOREA BUSINESS SOLUTIONS INC.\r
+ Canon BS Tower, 607 Teheran-ro\r
+ Seoul Gangnam-gu 06173\r
+ KR\r
+\r
+40-8C-1F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+408C1F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+2C-3F-0B (hex) Cisco Meraki\r
+2C3F0B (base 16) Cisco Meraki\r
+ 500 Terry A. Francois Blvd\r
+ San Francisco 94158\r
+ US\r
+\r
+80-C5-01 (hex) OctoGate IT Security Systems GmbH\r
+80C501 (base 16) OctoGate IT Security Systems GmbH\r
+ Friedrich List Strasse 42\r
+ Paderborn NRW 33100\r
+ DE\r
+\r
+04-F0-3E (hex) Huawei Device Co., Ltd.\r
+04F03E (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+78-E2-2C (hex) Huawei Device Co., Ltd.\r
+78E22C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+C0-D0-26 (hex) Huawei Device Co., Ltd.\r
+C0D026 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
14-D1-9E (hex) Apple, Inc.\r
14D19E (base 16) Apple, Inc.\r
1 Infinite Loop\r
Cupertino CA 95014\r
US\r
\r
-00-0F-A0 (hex) CANON KOREA BUSINESS SOLUTIONS INC.\r
-000FA0 (base 16) CANON KOREA BUSINESS SOLUTIONS INC.\r
- Canon BS Tower, 607 Teheran-ro\r
- Seoul Gangnam-gu 06173\r
+00-2D-B3 (hex) AMPAK Technology,Inc.\r
+002DB3 (base 16) AMPAK Technology,Inc.\r
+ 3F, No.15-1 Zhonghua Road, Hsinchu Industrail Park, Hukou,\r
+ Hsinchu Hsinchu,Taiwan R.O.C. 30352\r
+ TW\r
+\r
+3C-C7-86 (hex) DONGGUAN HUARONG COMMUNICATION TECHNOLOGIES CO.,LTD.\r
+3CC786 (base 16) DONGGUAN HUARONG COMMUNICATION TECHNOLOGIES CO.,LTD.\r
+ No.130 Dongxing East Road, Dongkeng Town\r
+ DONGGUAN 523450\r
+ CN\r
+\r
+28-C8-7C (hex) zte corporation\r
+28C87C (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+14-50-51 (hex) SHARP Corporation\r
+145051 (base 16) SHARP Corporation\r
+ 1 Takumi-cho, Sakai-ku\r
+ Sakai City Osaka 590-8522\r
+ JP\r
+\r
+C4-D0-E3 (hex) Intel Corporate\r
+C4D0E3 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+E4-FD-45 (hex) Intel Corporate\r
+E4FD45 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+18-4C-AE (hex) CONTINENTAL\r
+184CAE (base 16) CONTINENTAL\r
+ 1 AVENUE PAUL OURLIAC\r
+ TOULOUSE 31100\r
+ FR\r
+\r
+98-38-7D (hex) ITRONIC TECHNOLOGY CO . , LTD .\r
+98387D (base 16) ITRONIC TECHNOLOGY CO . , LTD .\r
+ 2F C Building Fu Xin Lin lndustrial Park Hangcheng\r
+ lndustrial Zone Xixiang Street Baoan District Shenzhen 518100\r
+ CN\r
+\r
+C8-D8-84 (hex) Universal Electronics, Inc.\r
+C8D884 (base 16) Universal Electronics, Inc.\r
+ 201 E. Sandpointe Ave\r
+ Santa Ana CA 92707\r
+ US\r
+\r
+B4-A2-5C (hex) Cambium Networks Limited\r
+B4A25C (base 16) Cambium Networks Limited\r
+ Unit B2, Linhay Business Park,\r
+ Ashburton Devon TQ13 7UP\r
+ GB\r
+\r
+2C-71-FF (hex) Amazon Technologies Inc.\r
+2C71FF (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102 \r
+ Reno NV 89507\r
+ US\r
+\r
+AC-D6-18 (hex) OnePlus Technology (Shenzhen) Co., Ltd\r
+ACD618 (base 16) OnePlus Technology (Shenzhen) Co., Ltd\r
+ 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING,\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+6C-56-40 (hex) BLU Products Inc\r
+6C5640 (base 16) BLU Products Inc\r
+ 10814 NW 33rd Street\r
+ Miami FL 33172\r
+ US\r
+\r
+48-78-5E (hex) Amazon Technologies Inc.\r
+48785E (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102 \r
+ Reno NV 89507\r
+ US\r
+\r
+20-C7-4F (hex) SensorPush\r
+20C74F (base 16) SensorPush\r
+ PO Box 211\r
+ Garrison NY 10524\r
+ US\r
+\r
+48-29-52 (hex) Sagemcom Broadband SAS\r
+482952 (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+A4-7E-36 (hex) EM Microelectronic\r
+A47E36 (base 16) EM Microelectronic\r
+ Rue des Sors 3\r
+ Marin-Epagnier Neuchatel 2074\r
+ CH\r
+\r
+B0-5D-D4 (hex) ARRIS Group, Inc.\r
+B05DD4 (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+24-E8-53 (hex) LG Innotek\r
+24E853 (base 16) LG Innotek\r
+ 26, Hanamsandan 5beon-ro\r
+ Gwangju Gwangsan-gu 506-731\r
KR\r
\r
-40-8C-1F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
-408C1F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+30-7C-4A (hex) Huawei Device Co., Ltd.\r
+307C4A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+2C-CE-1E (hex) Cloudtronics Pty Ltd\r
+2CCE1E (base 16) Cloudtronics Pty Ltd\r
+ Unit 1 6 Powells Road Brookvale\r
+ Sydney NSW 2100\r
+ AU\r
+\r
+F0-21-E0 (hex) eero inc.\r
+F021E0 (base 16) eero inc.\r
+ 660 3rd Street\r
+ San Francisco 94107\r
+ US\r
+\r
+9C-DB-CB (hex) Wuhan Funshion Online Technologies Co.,Ltd\r
+9CDBCB (base 16) Wuhan Funshion Online Technologies Co.,Ltd\r
+ 5th Floor,Financial Port Building A9,No.77 Optical Valley Avenue, East Lake High-Tech Development Zone, Wuhan\r
+ Wuhan CN/Hubei 430000\r
+ CN\r
+\r
+64-17-59 (hex) Intellivision Holdings, LLC\r
+641759 (base 16) Intellivision Holdings, LLC\r
+ 1844 E Carnegie\r
+ Santa Ana CA 92705\r
+ US\r
+\r
+50-43-48 (hex) ThingsMatrix Inc.\r
+504348 (base 16) ThingsMatrix Inc.\r
+ 9442 North Capital of Texas Hwy Plaza One Suite 500 Austin\r
+ Austin TX 78759\r
+ US\r
+\r
+D8-59-82 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+D85982 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+48-B2-5D (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+48B25D (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+2C-FD-B3 (hex) TCL Technoly Electronics(Huizhou).,Ltd\r
+2CFDB3 (base 16) TCL Technoly Electronics(Huizhou).,Ltd\r
+ Section 37, Zhongkai Hi-Tech Development Zone\r
+ Huizhou Guangdong 516006\r
+ CN\r
+\r
+A4-1B-34 (hex) China Mobile Group Device Co.,Ltd.\r
+A41B34 (base 16) China Mobile Group Device Co.,Ltd.\r
+ 32 Xuanwumen West Street,Xicheng District\r
+ Beijing 100053\r
+ CN\r
+\r
+80-45-DD (hex) Intel Corporate\r
+8045DD (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+C0-D4-6B (hex) Huawei Device Co., Ltd.\r
+C0D46B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+9C-95-67 (hex) Huawei Device Co., Ltd.\r
+9C9567 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+58-AE-F1 (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+58AEF1 (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+A4-7B-1A (hex) Huawei Device Co., Ltd.\r
+A47B1A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+14-7D-05 (hex) SERCOMM PHILIPPINES INC\r
+147D05 (base 16) SERCOMM PHILIPPINES INC\r
+ Lot 1 & 5, Phase 1, Filinvest Technology Park 1, Brgy. Punta, Calamba City\r
+ Calamba Lot 1\r
+ PH\r
+\r
+78-7A-6F (hex) Juice Technology AG\r
+787A6F (base 16) Juice Technology AG\r
+ Gewerbestrasse 7\r
+ Cham Select State CH-6330\r
+ CH\r
+\r
+E8-6C-C7 (hex) IEEE Registration Authority\r
+E86CC7 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+40-24-B2 (hex) Sichuan AI-Link Technology Co., Ltd.\r
+4024B2 (base 16) Sichuan AI-Link Technology Co., Ltd.\r
+ Anzhou, Industrial Park\r
+ Mianyang Sichuan 622650\r
+ CN\r
+\r
+64-0D-22 (hex) LG Electronics (Mobile Communications)\r
+640D22 (base 16) LG Electronics (Mobile Communications)\r
+ 60-39, Gasan-dong, Geumcheon-gu\r
+ Seoul 153-801\r
+ KR\r
+\r
+20-A7-F9 (hex) SHENZHEN OLANBOA TECHNOLOGY CO., LTD\r
+20A7F9 (base 16) SHENZHEN OLANBOA TECHNOLOGY CO., LTD\r
+ 4/F, Building B, Block A, Longquan Science Park, Tongfuyu Phase II, Tongsheng Community, Dalang Street, Longhua District, Shenzhen\r
+ shenzhen Guangdong 518000\r
+ CN\r
+\r
+C0-06-C3 (hex) TP-Link Corporation Limited\r
+C006C3 (base 16) TP-Link Corporation Limited\r
+ Room 901,9/F.New East Ocean Centre, 9 Science Museum Road\r
+ Tsim Sha Tsui Kowloon 999077\r
+ HK\r
+\r
+3C-15-12 (hex) Shenzhen Huanhu Technology Co.,Ltd\r
+3C1512 (base 16) Shenzhen Huanhu Technology Co.,Ltd\r
+ 7 / F, building C4, Hengfeng Industrial City, 739 Zhoushi Road, Hezhou community, Hangcheng street, Bao'an District, Shenzhen\r
+ Shenzhen 518000\r
+ CN\r
+\r
+8C-31-E2 (hex) DAYOUPLUS\r
+8C31E2 (base 16) DAYOUPLUS\r
+ 3F 509, Dunchon-daero, Jungwon-gu, Seongnam-si, Gyeonggi-do, Republic of Korea\r
+ Seongnam-si Gyeonggi-do 13217\r
+ KR\r
+\r
+10-39-4E (hex) Hisense broadband multimedia technology Co.,Ltd\r
+10394E (base 16) Hisense broadband multimedia technology Co.,Ltd\r
+ Song ling Road 399\r
+ Qingdao 266000\r
+ CN\r
+\r
+D8-D5-B9 (hex) Rainforest Automation, Inc.\r
+D8D5B9 (base 16) Rainforest Automation, Inc.\r
+ 200 – 311 Pender St. W\r
+ Vancouver British Columbia V6B 1T3\r
+ CA\r
+\r
+04-BA-1C (hex) Huawei Device Co., Ltd.\r
+04BA1C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+7C-3D-2B (hex) Huawei Device Co., Ltd.\r
+7C3D2B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+18-C2-41 (hex) SonicWall\r
+18C241 (base 16) SonicWall\r
+ 1033 McCarthy Blvd\r
+ Milpitas CA 95035\r
+ US\r
+\r
+58-45-4C (hex) Ericsson AB\r
+58454C (base 16) Ericsson AB\r
+ Torshamnsgatan 36\r
+ Stockholm SE-164 80\r
+ SE\r
+\r
+FC-4D-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+FC4DA6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+B4-14-E6 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B414E6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+AC-99-29 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+AC9929 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+18-48-59 (hex) Castlenet Technology Inc.\r
+184859 (base 16) Castlenet Technology Inc.\r
+ 5th Fl., No.159-1, Sec.3, Beishen Rd., Shenkeng Dist., \r
+ New Taipei City 222004\r
+ TW\r
+\r
+14-51-7E (hex) New H3C Technologies Co., Ltd\r
+14517E (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+08-3A-38 (hex) New H3C Technologies Co., Ltd\r
+083A38 (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+70-F0-88 (hex) Nintendo Co.,Ltd\r
+70F088 (base 16) Nintendo Co.,Ltd\r
+ 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU\r
+ KYOTO KYOTO 601-8501\r
+ JP\r
+\r
+84-23-88 (hex) Ruckus Wireless\r
+842388 (base 16) Ruckus Wireless\r
+ 350 West Java Drive\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+F4-C7-AA (hex) Marvell Semiconductors\r
+F4C7AA (base 16) Marvell Semiconductors\r
+ 15485 Sand Canyon Ave\r
+ IRVINE CA 92618\r
+ US\r
+\r
+F8-AB-E5 (hex) shenzhen worldelite electronics co., LTD\r
+F8ABE5 (base 16) shenzhen worldelite electronics co., LTD\r
+ Office 5 F, Xiang Yu Industrial Park, Longsheng Road, Longgang Dist\r
+ Shenzhen Guangdong 51800\r
+ CN\r
+\r
+E0-DB-D1 (hex) Technicolor CH USA Inc.\r
+E0DBD1 (base 16) Technicolor CH USA Inc.\r
+ 5030 Sugarloaf Parkway Bldg 6 \r
+ Lawrenceville GA 30044\r
+ US\r
+\r
+CC-ED-21 (hex) Nokia Shanghai Bell Co., Ltd.\r
+CCED21 (base 16) Nokia Shanghai Bell Co., Ltd.\r
+ No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai\r
+ Shanghai 201206\r
+ CN\r
+\r
+10-D5-61 (hex) Tuya Smart Inc.\r
+10D561 (base 16) Tuya Smart Inc.\r
+ 160 Greentree Drive, Suite 101\r
+ Dover DE 19904\r
+ US\r
+\r
+00-1A-86 (hex) New Wave Design & Verification\r
+001A86 (base 16) New Wave Design & Verification\r
+ 4950 W 78th St.\r
+ Minneapolis MN 55435\r
+ US\r
+\r
+50-9A-46 (hex) Safetrust Inc\r
+509A46 (base 16) Safetrust Inc\r
+ 8112 Mill Creek Rd\r
+ Fremont CA 94539\r
+ US\r
+\r
+D0-CF-D8 (hex) Huizhou Boshijie Technology Co.,Ltd\r
+D0CFD8 (base 16) Huizhou Boshijie Technology Co.,Ltd\r
+ No.1 Xisan road, Huifeng west road, Zhongkai high-tech zone\r
+ Huizhou Guangdong 516006\r
+ CN\r
+\r
+84-C7-8F (hex) APS Networks GmbH\r
+84C78F (base 16) APS Networks GmbH\r
+ Rosenwiesstr. 17\r
+ Stuttgart 70567\r
+ DE\r
+\r
+F0-A3-B2 (hex) Hui Zhou Gaoshengda Technology Co.,LTD\r
+F0A3B2 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD\r
+ No.75,Zhongkai High-Tech Development District,Huizhou\r
+ Hui Zhou Guangdong 516006\r
+ CN\r
+\r
+08-BB-3C (hex) Flextronics Tech.(Ind) Pvt Ltd\r
+08BB3C (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
+ 365, Benjamin Road\r
+ Sricity Vardahiah Palem(M),Chilamathur Village, Chittoor Distict 517646\r
+ IN\r
+\r
+2C-BE-EB (hex) Nothing Technology Limited\r
+2CBEEB (base 16) Nothing Technology Limited\r
+ 11 Staple Inn\r
+ London London WC1V 7QH\r
+ GB\r
+\r
+F0-4A-02 (hex) Cisco Systems, Inc\r
+F04A02 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+74-09-AC (hex) Quext, LLC\r
+7409AC (base 16) Quext, LLC\r
+ 5214 68th St., Suite 201\r
+ Lubbock TX 79424\r
+ US\r
+\r
+F0-01-6E (hex) Tianyi Telecom Terminals Company Limited\r
+F0016E (base 16) Tianyi Telecom Terminals Company Limited\r
+ 6/F Changshang Building, No.29 North Xinhua Street, Xicheng District\r
+ Beijing 100031\r
+ CN\r
+\r
+EC-0B-AE (hex) Hangzhou BroadLink Technology Co.,Ltd\r
+EC0BAE (base 16) Hangzhou BroadLink Technology Co.,Ltd\r
+ Room 101,1/F,Unit C,Building 1,No.57 Jiang'er Road,Changhe Street,Binjiang District,Hangzhou,Zhejiang,P.R.China\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+80-25-11 (hex) ITEL MOBILE LIMITED\r
+802511 (base 16) ITEL MOBILE LIMITED\r
+ RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K\r
+ Hong Kong KOWLOON 999077\r
+ HK\r
+\r
+E8-A6-60 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E8A660 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+CC-24-2E (hex) Shenzhen SuperElectron Technology Co.,Ltd.\r
+CC242E (base 16) Shenzhen SuperElectron Technology Co.,Ltd.\r
+ 1213-1214, haosheng business center, dongbin road, nanshan street, nanshan district, shenzhen city\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+08-2F-E9 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+082FE9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+98-48-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+984874 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+1C-A6-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+1CA681 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+B8-81-FA (hex) Apple, Inc.\r
+B881FA (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+9C-76-0E (hex) Apple, Inc.\r
+9C760E (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+94-EA-32 (hex) Apple, Inc.\r
+94EA32 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+C8-BF-FE (hex) Huawei Device Co., Ltd.\r
+C8BFFE (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+08-2E-36 (hex) Huawei Device Co., Ltd.\r
+082E36 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+50-F4-EB (hex) Apple, Inc.\r
+50F4EB (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+28-C7-09 (hex) Apple, Inc.\r
+28C709 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+38-02-DE (hex) Sercomm Corporation.\r
+3802DE (base 16) Sercomm Corporation.\r
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen\r
+ Miao-Lih Hsuan 115\r
+ TW\r
+\r
+5C-62-5A (hex) CANON INC.\r
+5C625A (base 16) CANON INC.\r
+ 30-2 Shimomaruko 3-chome,\r
+ Ohta-ku Tokyo 146-8501\r
+ JP\r
+\r
+7C-0A-3F (hex) Samsung Electronics Co.,Ltd\r
+7C0A3F (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+08-AA-89 (hex) zte corporation\r
+08AA89 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+A4-35-2D (hex) TRIZ Networks corp.\r
+A4352D (base 16) TRIZ Networks corp.\r
+ 815 Daewangpangyo-ro\r
+ Sujeong-gu, Seongnam-si Gyeonggi-do 13449\r
+ KR\r
+\r
+04-D6-0E (hex) FUNAI ELECTRIC CO., LTD.\r
+04D60E (base 16) FUNAI ELECTRIC CO., LTD.\r
+ 7-7-1, Nakagaito\r
+ Daito Osaka 574-0013\r
+ JP\r
+\r
+04-9F-81 (hex) NETSCOUT SYSTEMS INC\r
+049F81 (base 16) NETSCOUT SYSTEMS INC\r
+ 310 Littleton Road\r
+ Westford MA 01886 \r
+ US\r
+\r
+00-80-8C (hex) NETSCOUT SYSTEMS INC\r
+00808C (base 16) NETSCOUT SYSTEMS INC\r
+ 310 Littleton Road\r
+ Westford MA 01886 \r
+ US\r
+\r
+00-1F-92 (hex) Motorola Solutions Inc.\r
+001F92 (base 16) Motorola Solutions Inc.\r
+ 500 W Monroe Street, Ste 4400\r
+ Chicago IL 60661-3781\r
+ US\r
+\r
+00-23-BB (hex) Accretech SBS, Inc.\r
+0023BB (base 16) Accretech SBS, Inc.\r
+ 2451 NW 28th Ave.\r
+ Portland OR 97210\r
+ US\r
+\r
+B0-C9-52 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+B0C952 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
NO.18 HAIBIN ROAD,\r
DONG GUAN GUANG DONG 523860\r
CN\r
\r
-04-F0-3E (hex) Huawei Device Co., Ltd.\r
-04F03E (base 16) Huawei Device Co., Ltd.\r
+F4-41-9E (hex) Huawei Device Co., Ltd.\r
+F4419E (base 16) Huawei Device Co., Ltd.\r
No.2 of Xincheng Road, Songshan Lake Zone\r
Dongguan Guangdong 523808\r
CN\r
\r
-78-E2-2C (hex) Huawei Device Co., Ltd.\r
-78E22C (base 16) Huawei Device Co., Ltd.\r
+90-F9-B7 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+90F9B7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+F4-45-88 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F44588 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+C8-BB-81 (hex) Huawei Device Co., Ltd.\r
+C8BB81 (base 16) Huawei Device Co., Ltd.\r
No.2 of Xincheng Road, Songshan Lake Zone\r
Dongguan Guangdong 523808\r
CN\r
\r
-C0-D0-26 (hex) Huawei Device Co., Ltd.\r
-C0D026 (base 16) Huawei Device Co., Ltd.\r
+1C-47-2F (hex) Huawei Device Co., Ltd.\r
+1C472F (base 16) Huawei Device Co., Ltd.\r
No.2 of Xincheng Road, Songshan Lake Zone\r
Dongguan Guangdong 523808\r
CN\r
\r
-2C-3F-0B (hex) Cisco Meraki\r
-2C3F0B (base 16) Cisco Meraki\r
- 500 Terry A. Francois Blvd\r
- San Francisco 94158\r
+20-5E-64 (hex) Huawei Device Co., Ltd.\r
+205E64 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+60-57-7D (hex) eero inc.\r
+60577D (base 16) eero inc.\r
+ 660 3rd Street\r
+ San Francisco CA 94107\r
US\r
\r
-80-C5-01 (hex) OctoGate IT Security Systems GmbH\r
-80C501 (base 16) OctoGate IT Security Systems GmbH\r
- Friedrich List Strasse 42\r
- Paderborn NRW 33100\r
- DE\r
+C8-13-8B (hex) Shenzhen Skyworth Digital Technology CO., Ltd\r
+C8138B (base 16) Shenzhen Skyworth Digital Technology CO., Ltd\r
+ 4F,Block A, Skyworth?Building,\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+78-F2-35 (hex) Sichuan AI-Link Technology Co., Ltd.\r
+78F235 (base 16) Sichuan AI-Link Technology Co., Ltd.\r
+ Anzhou, Industrial Park\r
+ Mianyang Sichuan 622650\r
+ CN\r
+\r
+F4-4E-E3 (hex) Intel Corporate\r
+F44EE3 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+D0-E0-42 (hex) Cisco Systems, Inc\r
+D0E042 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
\r
84-80-94 (hex) Meter, Inc.\r
848094 (base 16) Meter, Inc.\r
San Jose CA 94568\r
US\r
\r
-28-EF-01 (hex) Private\r
-28EF01 (base 16) Private\r
-\r
C0-53-36 (hex) Beijing National Railway Research & Design Institute of Signal & Communication Group Co..Ltd.\r
C05336 (base 16) Beijing National Railway Research & Design Institute of Signal & Communication Group Co..Ltd.\r
7 floor, No.1 Automobile Museum South Road, Fengtai Science and Technology Park,\r
Beijing 100190\r
CN\r
\r
-58-FD-20 (hex) Bravida Sakerhet AB\r
-58FD20 (base 16) Bravida Sakerhet AB\r
- Mikrofonvagen 28\r
- STOCKHOLM 126 81\r
- SE\r
-\r
AC-A0-16 (hex) Cisco Systems, Inc\r
ACA016 (base 16) Cisco Systems, Inc\r
80 West Tasman Drive\r
Anyang-Si Gyeonggi-Do 431-061\r
KR\r
\r
-D8-E7-2B (hex) NetAlly\r
-D8E72B (base 16) NetAlly\r
- 310 Littleton Road\r
- Westford MA 01886 \r
- US\r
-\r
78-5C-72 (hex) Hioso Technology Co., Ltd.\r
785C72 (base 16) Hioso Technology Co., Ltd.\r
6th Floor, 12th Building, Wangtang Industrial Zone,\r
Paris 75001\r
FR\r
\r
-00-18-85 (hex) Avigilon Corporation\r
-001885 (base 16) Avigilon Corporation\r
- Box 378, 101 - 1001 West Broadway\r
- Vancouver BC V6H 4E4\r
- CA\r
-\r
00-18-88 (hex) GOTIVE a.s.\r
001888 (base 16) GOTIVE a.s.\r
Zámocká 34\r
Kyunggi-Do 435-040\r
KR\r
\r
-00-08-0C (hex) VDA Elettronica spa\r
-00080C (base 16) VDA Elettronica spa\r
- Viale Lino Zanussi, 3\r
- 33170 Pordenone \r
- IT\r
-\r
00-08-04 (hex) ICA Inc.\r
000804 (base 16) ICA Inc.\r
542-1 Noguki\r
Chatsworth CA 91311\r
US\r
\r
-E4-05-F8 (hex) Delta Innovation Technology Co., Ltd.\r
-E405F8 (base 16) Delta Innovation Technology Co., Ltd.\r
- China Digital Kingdom Building, Chaoyang District\r
- Beijing Beijing 100102\r
- CN\r
-\r
00-00-09 (hex) XEROX CORPORATION\r
000009 (base 16) XEROX CORPORATION\r
M/S 105-50C\r
Piscataway NJ 08554\r
US\r
\r
-34-56-FE (hex) Cisco Meraki\r
-3456FE (base 16) Cisco Meraki\r
+C8-94-02 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+C89402 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+ Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District\r
+ Chongqing Chongqing 401332\r
+ CN\r
+\r
+7C-B9-4C (hex) Bouffalo Lab (Nanjing) Co., Ltd.\r
+7CB94C (base 16) Bouffalo Lab (Nanjing) Co., Ltd.\r
+ 5F, Gongxiang Space, No.100 Tuanjie Road, Nanjing, China\r
+ Nanjing Jiangsu 211800\r
+ CN\r
+\r
+DC-15-C8 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH\r
+DC15C8 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH\r
+ Alt-Moabit 95\r
+ Berlin Berlin 10559\r
+ DE\r
+\r
+6C-D6-30 (hex) Rootous System Co.,Ltd\r
+6CD630 (base 16) Rootous System Co.,Ltd\r
+ KT B/D 4Floor, 100, Ahopgeori-gil\r
+ Yeonseo-myeon Sejong-si 30049\r
+ KR\r
+\r
+B8-07-56 (hex) Cisco Meraki\r
+B80756 (base 16) Cisco Meraki\r
500 Terry A. Francois Blvd\r
San Francisco 94158\r
US\r
\r
-B8-07-56 (hex) Cisco Meraki\r
-B80756 (base 16) Cisco Meraki\r
+C8-33-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C833E5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+34-56-FE (hex) Cisco Meraki\r
+3456FE (base 16) Cisco Meraki\r
500 Terry A. Francois Blvd\r
San Francisco 94158\r
US\r
\r
+B8-44-AE (hex) TCT mobile ltd\r
+B844AE (base 16) TCT mobile ltd\r
+ No.86 hechang 7th road, zhongkai, Hi-Tech District\r
+ Hui Zhou Guang Dong 516006\r
+ CN\r
+\r
+E4-F7-5B (hex) ARRIS Group, Inc.\r
+E4F75B (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+F8-79-0A (hex) ARRIS Group, Inc.\r
+F8790A (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+0C-CF-89 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD\r
+0CCF89 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD\r
+ NO.268? Fuqian Rd, Jutang community, Guanlan Town, Longhua New district\r
+ shenzhen guangdong 518000\r
+ CN\r
+\r
+0C-8C-69 (hex) Shenzhen elink smart Co., ltd\r
+0C8C69 (base 16) Shenzhen elink smart Co., ltd\r
+ Floor 2,Building A , Hongtian Xinfengze Industrial Park Huang Pu Community , Xin Qiao District ,Baoan Area\r
+ shenzhen Guangdong Province 518101\r
+ CN\r
+\r
+D8-BB-C1 (hex) Micro-Star INTL CO., LTD.\r
+D8BBC1 (base 16) Micro-Star INTL CO., LTD.\r
+ No.69, Lide St.,\r
+ New Taipei City Taiwan 235\r
+ TW\r
+\r
+AC-5A-FC (hex) Intel Corporate\r
+AC5AFC (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+1C-93-7C (hex) ARRIS Group, Inc.\r
+1C937C (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+58-FC-20 (hex) Altice Labs S.A.\r
+58FC20 (base 16) Altice Labs S.A.\r
+ NIF 504705610, Rua Eng. José Ferreira Pinto Basto\r
+ Aveiro 3810-106\r
+ PT\r
+\r
+58-FD-20 (hex) Systemhouse Solutions AB\r
+58FD20 (base 16) Systemhouse Solutions AB\r
+ Mikrofonvagen 28\r
+ STOCKHOLM 126 81\r
+ SE\r
+\r
+04-D6-F4 (hex) GD Midea Air-Conditioning Equipment Co.,Ltd.\r
+04D6F4 (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd.\r
+ Midea Global Innovation Center,Beijiao Town,Shunde\r
+ Foshan Guangdong 528311\r
+ CN\r
+\r
+04-90-81 (hex) Pensando Systems, Inc.\r
+049081 (base 16) Pensando Systems, Inc.\r
+ 570 Alder Drive\r
+ Milpitas CA 95035\r
+ US\r
+\r
+4C-79-6E (hex) Intel Corporate\r
+4C796E (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+98-AD-1D (hex) Huawei Device Co., Ltd.\r
+98AD1D (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+F8-AA-3F (hex) DWnet Technologies(Suzhou) Corporation\r
+F8AA3F (base 16) DWnet Technologies(Suzhou) Corporation\r
+ No.8,Tangzhuang Road, Suzhou Industrial Park, Jiangsu, China\r
+ Suzhou 21500\r
+ CN\r
+\r
+00-68-2B (hex) Huawei Device Co., Ltd.\r
+00682B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+F0-9E-4A (hex) Intel Corporate\r
+F09E4A (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+F0-77-C3 (hex) Intel Corporate\r
+F077C3 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+24-9A-D8 (hex) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD.\r
+249AD8 (base 16) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD.\r
+ 309, 3th Floor, No.16, Yun Ding North Road, Huli District\r
+ xiamen Fujian 361015\r
+ CN\r
+\r
+D8-5E-D3 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD.\r
+D85ED3 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD.\r
+ Pin-Jen City, Taoyuan, Taiwan, R.O.C.\r
+ Pin-Jen Taoyuan 324\r
+ TW\r
+\r
+00-E4-21 (hex) Sony Interactive Entertainment Inc.\r
+00E421 (base 16) Sony Interactive Entertainment Inc.\r
+ 1-7-1 Konan\r
+ Minato-ku Tokyo 108-0075\r
+ JP\r
+\r
+CC-DB-04 (hex) DataRemote Inc.\r
+CCDB04 (base 16) DataRemote Inc.\r
+ 18001 Old Cutler Rd. Suite 600\r
+ Palmetto Bay FL 33157\r
+ US\r
+\r
+E8-9F-39 (hex) Nokia\r
+E89F39 (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+34-73-5A (hex) Dell Inc.\r
+34735A (base 16) Dell Inc.\r
+ One Dell Way\r
+ Round Rock TX 78682\r
+ US\r
+\r
+8C-AA-CE (hex) Xiaomi Communications Co Ltd\r
+8CAACE (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+98-1A-35 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+981A35 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+80-34-28 (hex) Microchip Technology Inc.\r
+803428 (base 16) Microchip Technology Inc.\r
+ 2355 W. Chandler Blvd.\r
+ Chandler AZ 85224\r
+ US\r
+\r
+28-EF-01 (hex) Amazon Technologies Inc.\r
+28EF01 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+B0-22-7A (hex) HP Inc.\r
+B0227A (base 16) HP Inc.\r
+ 10300 Energy Dr\r
+ Spring TX 77389\r
+ US\r
+\r
+60-A7-51 (hex) Huawei Device Co., Ltd.\r
+60A751 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+10-2B-41 (hex) Samsung Electronics Co.,Ltd\r
+102B41 (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+34-4A-C3 (hex) HuNan ZiKun Information Technology CO., Ltd\r
+344AC3 (base 16) HuNan ZiKun Information Technology CO., Ltd\r
+ 101-8, 1st Floor, Juxing Venture Base, No. 8 Lujing Road, GaoXin Development District\r
+ Changsha City Hunan Province 410000\r
+ CN\r
+\r
+68-2D-83 (hex) SHENZHEN DINGHE COMMUNICATION COMPANY\r
+682D83 (base 16) SHENZHEN DINGHE COMMUNICATION COMPANY\r
+ ROOM 1802, BAOYUNDA WULIU INFORMATION BUILDING\r
+ SHENZHEN GUANGDONG 518101\r
+ CN\r
+\r
+A8-43-97 (hex) Innogrit Corporation\r
+A84397 (base 16) Innogrit Corporation\r
+ 1735 Technology Dr, Suite 620\r
+ San Jose CA 95110\r
+ US\r
+\r
+D8-CD-2C (hex) WUXI NEIHUA NETWORK TECHNOLOGY CO., LTD\r
+D8CD2C (base 16) WUXI NEIHUA NETWORK TECHNOLOGY CO., LTD\r
+ 16 Lexing Road, Xinwu District\r
+ Wuxi Jiangsu 214000\r
+ CN\r
+\r
+58-D3-91 (hex) Quectel Wireless Solutions Co., Ltd.\r
+58D391 (base 16) Quectel Wireless Solutions Co., Ltd.\r
+ 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District\r
+ Shanghai 200233\r
+ CN\r
+\r
+08-47-4C (hex) Nokia\r
+08474C (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+90-C1-19 (hex) Nokia\r
+90C119 (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+7C-F8-80 (hex) Cisco Systems, Inc\r
+7CF880 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+E4-05-F8 (hex) Bytedance\r
+E405F8 (base 16) Bytedance\r
+ E World Center,11 Zhongguancun Street Haidian Dist\r
+ Beijing City Beijing 100102\r
+ CN\r
+\r
+F8-45-C4 (hex) Shenzhen Netforward Micro-Electronic Co., Ltd.\r
+F845C4 (base 16) Shenzhen Netforward Micro-Electronic Co., Ltd.\r
+ Room 611-2?6st Floor,Building 1, The Sunmax Technology Park, No 8 Keyuan Road, Nanshan District\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+78-10-53 (hex) China Mobile Group Device Co.,Ltd.\r
+781053 (base 16) China Mobile Group Device Co.,Ltd.\r
+ 32 Xuanwumen West Street,Xicheng District\r
+ Beijing 100053\r
+ CN\r
+\r
+9C-4F-5F (hex) TAP Sound System\r
+9C4F5F (base 16) TAP Sound System\r
+ 15 rue Castel\r
+ Fontenay-sous-Bois 94120\r
+ FR\r
+\r
+00-08-0C (hex) VDA Group S.p.a.\r
+00080C (base 16) VDA Group S.p.a.\r
+ Viale Lino Zanussi 3\r
+ Pordenone Pordenone 33170\r
+ IT\r
+\r
+D0-97-FE (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+D097FE (base 16) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+ No.178 Yulong Avenue, Yufengshan, Yubei District, Chongqing.\r
+ Chongqing China 401120\r
+ CN\r
+\r
+84-3A-5B (hex) Inventec(Chongqing) Corporation\r
+843A5B (base 16) Inventec(Chongqing) Corporation\r
+ No.66 West District 2nd Rd, Shapingba District\r
+ Chongqing Chongqing 401331\r
+ CN\r
+\r
+54-49-DF (hex) Peloton Interactive, Inc\r
+5449DF (base 16) Peloton Interactive, Inc\r
+ 158 W 27th St, 4th Fl\r
+ New York NY 10001\r
+ US\r
+\r
+18-2A-57 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+182A57 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+F8-3E-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F83E95 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+48-12-58 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+481258 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+D8-EB-46 (hex) Google, Inc.\r
+D8EB46 (base 16) Google, Inc.\r
+ 1600 Amphitheatre Parkway\r
+ Mountain View CA 94043\r
+ US\r
+\r
+2C-17-E0 (hex) SYSTEMES ET TECHNOLOGIES IDENTIFICATION (STid)\r
+2C17E0 (base 16) SYSTEMES ET TECHNOLOGIES IDENTIFICATION (STid)\r
+ 20 Parc d’activités des Pradeaux\r
+ GREASQUE Select State F-13850\r
+ FR\r
+\r
+CC-32-96 (hex) Huawei Device Co., Ltd.\r
+CC3296 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+98-CD-AC (hex) Espressif Inc.\r
+98CDAC (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+80-8A-F7 (hex) Nanoleaf\r
+808AF7 (base 16) Nanoleaf\r
+ 100 Front Street East, 4th Floor\r
+ Toronto Ontario M5A 1E1\r
+ CA\r
+\r
+B0-3D-C2 (hex) Wasp artificial intelligence(Shenzhen) Co.,ltd\r
+B03DC2 (base 16) Wasp artificial intelligence(Shenzhen) Co.,ltd\r
+ A402,Block ABCD,Building 3,Phase 1,Tianan Yungu Industrial Park,Gangtou Comunity,Bantian Street,Longhua District,Shenzhen\r
+ Shenzhen Select State 518000\r
+ CN\r
+\r
+C8-4D-34 (hex) LIONS Taiwan Technology Inc.\r
+C84D34 (base 16) LIONS Taiwan Technology Inc.\r
+ 3F-2, 120, Sec. 2, Gongdao 5th Rd.\r
+ Hsinchu Taiwan 30072\r
+ TW\r
+\r
+44-6F-F8 (hex) Dyson Limited\r
+446FF8 (base 16) Dyson Limited\r
+ Tetbury Hill\r
+ Malmesbury Wiltshire SN16 0RP\r
+ GB\r
+\r
+6C-1B-3F (hex) MiraeSignal Co., Ltd\r
+6C1B3F (base 16) MiraeSignal Co., Ltd\r
+ #701,C-dong Bundang Techno Park Pangyoro 744\r
+ Bundang-gu Sungnam-si Kyungkido 13510\r
+ KR\r
+\r
+28-AF-FD (hex) Cisco Systems, Inc\r
+28AFFD (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+9C-76-13 (hex) Ring LLC\r
+9C7613 (base 16) Ring LLC\r
+ 1523 26th St\r
+ Santa Monica CA 90404\r
+ US\r
+\r
+44-9B-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+449BC1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+20-25-D2 (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+2025D2 (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+28-F4-9B (hex) LEETEK\r
+28F49B (base 16) LEETEK\r
+ Ojeong-ro, 47\r
+ Bucheon-si Gyeonggi-do 14445\r
+ KR\r
+\r
+18-42-D4 (hex) Wuhan Hosan Telecommunication Technology Co.,Ltd\r
+1842D4 (base 16) Wuhan Hosan Telecommunication Technology Co.,Ltd\r
+ Fourth Floor,Building N,Quannengtong Shuangchuang Yuan,Gold-silver Lake Street,East West Lake District,\r
+ Wuhan Hubei 430043\r
+ CN\r
+\r
+A8-63-7D (hex) D-Link International\r
+A8637D (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+2C-43-BE (hex) Sunnovo International Limited\r
+2C43BE (base 16) Sunnovo International Limited\r
+ 1717 Haitai Building\r
+ Beijing Beijing 100083\r
+ CN\r
+\r
+58-10-B7 (hex) Infinix mobility limited\r
+5810B7 (base 16) Infinix mobility limited\r
+ RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG\r
+ HongKong HongKong 999077\r
+ HK\r
+\r
+B0-24-91 (hex) Huawei Device Co., Ltd.\r
+B02491 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+98-75-1A (hex) Huawei Device Co., Ltd.\r
+98751A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+1C-91-80 (hex) Apple, Inc.\r
+1C9180 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+4C-B9-10 (hex) Apple, Inc.\r
+4CB910 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+B4-89-01 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B48901 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+E0-92-5C (hex) Apple, Inc.\r
+E0925C (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+EC-15-3D (hex) Beijing Yaxunhongda Technology Co., Ltd.\r
+EC153D (base 16) Beijing Yaxunhongda Technology Co., Ltd.\r
+ East area,4th floor,No.5,Shangdi 5th Street Haidian District,Beijing \r
+ Beijing Beijing 100000\r
+ CN\r
+\r
+D8-A3-5C (hex) Samsung Electronics Co.,Ltd\r
+D8A35C (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+C0-92-96 (hex) zte corporation\r
+C09296 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+50-E2-4E (hex) zte corporation\r
+50E24E (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+4C-77-66 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.\r
+4C7766 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.\r
+ 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+78-E3-6D (hex) Espressif Inc.\r
+78E36D (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+14-5A-FC (hex) Liteon Technology Corporation\r
+145AFC (base 16) Liteon Technology Corporation\r
+ 4F, 90, Chien 1 Road\r
+ New Taipei City Taiwan 23585\r
+ TW\r
+\r
+1C-A0-EF (hex) IEEE Registration Authority\r
+1CA0EF (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+00-18-85 (hex) Motorola Solutions Inc.\r
+001885 (base 16) Motorola Solutions Inc.\r
+ 500 W Monroe Street, Ste 4400\r
+ Chicago IL 60661-3781\r
+ US\r
+\r
+D8-E7-2B (hex) NETSCOUT SYSTEMS INC\r
+D8E72B (base 16) NETSCOUT SYSTEMS INC\r
+ 310 Littleton Road\r
+ Westford MA 01886 \r
+ US\r
+\r
+18-BF-B3 (hex) Samsung Electronics Co., Ltd., Memory Division\r
+18BFB3 (base 16) Samsung Electronics Co., Ltd., Memory Division\r
+ 1, Samsungjeonja-ro\r
+ Hwaseong-si Gyeonggi-do 18448\r
+ KR\r
+\r
+2C-8D-B1 (hex) Intel Corporate\r
+2C8DB1 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+58-6C-25 (hex) Intel Corporate\r
+586C25 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+08-2C-ED (hex) Technity Solutions Inc.\r
+082CED (base 16) Technity Solutions Inc.\r
+ 100 West Beaver Creek Rd, Unit 13\r
+ Richmond Hill Ontario L4B 1H4\r
+ CA\r
+\r
+34-86-5D (hex) Espressif Inc.\r
+34865D (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+B4-E3-F9 (hex) Silicon Laboratories\r
+B4E3F9 (base 16) Silicon Laboratories\r
+ 400 West Cesar Chavez Street\r
+ Austin TX 78701\r
+ US\r
+\r
+A4-9B-CD (hex) Cisco Systems, Inc\r
+A49BCD (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+04-27-28 (hex) Microsoft Corporation\r
+042728 (base 16) Microsoft Corporation\r
+ One Microsoft Way\r
+ REDMOND WA 98052\r
+ US\r
+\r
+20-66-CF (hex) FREEBOX SAS\r
+2066CF (base 16) FREEBOX SAS\r
+ 16 rue de la Ville l'Eveque\r
+ PARIS IdF 75008\r
+ FR\r
+\r
+2C-C8-1B (hex) Routerboard.com\r
+2CC81B (base 16) Routerboard.com\r
+ Mikrotikls SIA\r
+ Riga Riga LV1009\r
+ LV\r
+\r
+54-0E-58 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+540E58 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+5C-64-8E (hex) Zyxel Communications Corporation\r
+5C648E (base 16) Zyxel Communications Corporation\r
+ No. 6 Innovation Road II, Science Park\r
+ Hsichu Taiwan 300\r
+ TW\r
+\r
+30-E3-96 (hex) Huawei Device Co., Ltd.\r
+30E396 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+D0-7D-33 (hex) Huawei Device Co., Ltd.\r
+D07D33 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+C0-E1-BE (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C0E1BE (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+88-E0-56 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+88E056 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
F8-D0-27 (hex) Seiko Epson Corporation\r
F8D027 (base 16) Seiko Epson Corporation\r
2070 Kotobuki Koaka\r
Qingdao Shandong 266103\r
CN\r
\r
-F8-D4-78 (hex) Flextronics Tech.(Ind) Pvt Ltd\r
-F8D478 (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
- SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC\r
- Chennai 602107\r
- IN\r
-\r
48-C3-B0 (hex) Pharos Co.Ltd\r
48C3B0 (base 16) Pharos Co.Ltd\r
503 Ogong-ro 144 Deokjin-gu\r
Lörrach DE-79539\r
DE\r
\r
-44-B4-62 (hex) Flextronics Tech.(Ind) Pvt Ltd\r
-44B462 (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
- SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC\r
- Chennai 602107\r
- IN\r
-\r
94-B4-0F (hex) Aruba, a Hewlett Packard Enterprise Company\r
94B40F (base 16) Aruba, a Hewlett Packard Enterprise Company\r
3333 Scott Blvd\r
San Jose CA 94568\r
US\r
\r
-F4-C7-95 (hex) WEY Elektronik AG\r
-F4C795 (base 16) WEY Elektronik AG\r
- Dorfstrasse 57\r
- Unterengstringen Zurich 8103\r
- CH\r
-\r
78-11-85 (hex) NBS Payment Solutions Inc.\r
781185 (base 16) NBS Payment Solutions Inc.\r
703 Evans Ave\r
Pin-Jhen City, 324\r
TW\r
\r
-84-90-00 (hex) Arnold & Richter Cine Technik\r
-849000 (base 16) Arnold & Richter Cine Technik\r
- Tuerkenstrasse 89\r
- Munich Bavaria 80799\r
- DE\r
-\r
08-18-4C (hex) A. S. Thomas, Inc.\r
08184C (base 16) A. S. Thomas, Inc.\r
355 Providence Hwy\r
213 76 MALMOE \r
SE\r
\r
-00-E0-DF (hex) KEYMILE GmbH\r
-00E0DF (base 16) KEYMILE GmbH\r
- Wohlenbergstraße 3\r
- 30179 Hannover \r
- DE\r
-\r
00-E0-F2 (hex) ARLOTTO COMNET, INC.\r
00E0F2 (base 16) ARLOTTO COMNET, INC.\r
7F-4,55,TUNG-KUANG ROAD\r
BEDFORD TX 76021\r
US\r
\r
-00-C0-6A (hex) ZAHNER-ELEKTRIK GMBH & CO. KG\r
-00C06A (base 16) ZAHNER-ELEKTRIK GMBH & CO. KG\r
- P.O. BOX 1846\r
- \r
- DE\r
-\r
00-C0-E3 (hex) OSITECH COMMUNICATIONS, INC.\r
00C0E3 (base 16) OSITECH COMMUNICATIONS, INC.\r
679 SOUTHGATE DRIVE\r
Cupertino CA 95014\r
US\r
\r
+FC-40-09 (hex) zte corporation\r
+FC4009 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+24-A6-5E (hex) zte corporation\r
+24A65E (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+50-98-39 (hex) Xiaomi Communications Co Ltd\r
+509839 (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+48-00-7D (hex) DTS ELEKTRONIK SAN. TIC. LTD. STI.\r
+48007D (base 16) DTS ELEKTRONIK SAN. TIC. LTD. STI.\r
+ MAHMUTBEY MAH. 2650.SOK. NO:21\r
+ ISTANBUL 34218\r
+ TR\r
+\r
+30-B1-B5 (hex) Arcadyan Corporation\r
+30B1B5 (base 16) Arcadyan Corporation\r
+ No.8, Sec.2, Guangfu Rd.\r
+ Hsinchu City Hsinchu 30071\r
+ TW\r
+\r
+64-07-F6 (hex) Samsung Electronics Co.,Ltd\r
+6407F6 (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
E0-CB-BC (hex) Cisco Meraki\r
E0CBBC (base 16) Cisco Meraki\r
500 Terry A. Francois Blvd\r
San Francisco 94158\r
US\r
\r
+D8-EC-E5 (hex) Zyxel Communications Corporation\r
+D8ECE5 (base 16) Zyxel Communications Corporation\r
+ No. 6 Innovation Road II, Science Park\r
+ Hsichu Taiwan 300\r
+ TW\r
+\r
+C4-70-AB (hex) Ruijie Networks Co.,LTD\r
+C470AB (base 16) Ruijie Networks Co.,LTD\r
+ No. 2, 7th floor, xingwangruijie, haixi hi-tech industrial park, high-tech zone, fuzhou city\r
+ Fuzhou Fujian 350002\r
+ CN\r
+\r
+CC-6B-1E (hex) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+CC6B1E (base 16) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+ B22 Building,NO.51 Tongle Road, Shajing Town, Jiangnan District, Nanning, Guangxi Province, China\r
+ Nanning Guangxi 530007\r
+ CN\r
+\r
+F0-D0-8C (hex) TCT mobile ltd\r
+F0D08C (base 16) TCT mobile ltd\r
+ No.86 hechang 7th road, zhongkai, Hi-Tech District\r
+ Hui Zhou Guang Dong 516006\r
+ CN\r
+\r
+84-90-00 (hex) Arnold&Richter Cine Technik GmbH & Co. Betriebs KG\r
+849000 (base 16) Arnold&Richter Cine Technik GmbH & Co. Betriebs KG\r
+ Herbert-Bayer-Str. 10\r
+ Munchen Bavaria 80807\r
+ DE\r
+\r
+30-F9-4B (hex) Universal Electronics, Inc.\r
+30F94B (base 16) Universal Electronics, Inc.\r
+ 201 E. Sandpointe Ave\r
+ Santa Ana CA 92707\r
+ US\r
+\r
+B4-8A-5F (hex) Juniper Networks\r
+B48A5F (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+70-DF-F7 (hex) ARRIS Group, Inc.\r
+70DFF7 (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+00-E0-DF (hex) DZS GmbH\r
+00E0DF (base 16) DZS GmbH\r
+ Wohlenbergstrasse. 3\r
+ Hannover 30179\r
+ DE\r
+\r
+E0-E8-BB (hex) Unicom Vsens Telecommunications Co., Ltd.\r
+E0E8BB (base 16) Unicom Vsens Telecommunications Co., Ltd.\r
+ Room612,613,615,6Floors,Block3,Hengji center,N0.18 Jianguomen inner Street,Dondcheng Distict, Beijing,P.R.China\r
+ Beijing 100005\r
+ CN\r
+\r
+E4-C9-0B (hex) Radwin\r
+E4C90B (base 16) Radwin\r
+ Habarzel 27\r
+ Tel Aviv -- select -- 6971039\r
+ IL\r
+\r
+98-27-82 (hex) IEEE Registration Authority\r
+982782 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+38-A0-67 (hex) Nokia Solutions and Networks GmbH & Co. KG\r
+38A067 (base 16) Nokia Solutions and Networks GmbH & Co. KG\r
+ Werinherstrasse 91\r
+ München Bavaria D-81541\r
+ DE\r
+\r
+CC-81-2A (hex) vivo Mobile Communication Co., Ltd.\r
+CC812A (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+7C-1B-93 (hex) Huawei Device Co., Ltd.\r
+7C1B93 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+DC-2D-3C (hex) Huawei Device Co., Ltd.\r
+DC2D3C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+04-11-19 (hex) IEEE Registration Authority\r
+041119 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+E4-55-A8 (hex) Cisco Meraki\r
+E455A8 (base 16) Cisco Meraki\r
+ 500 Terry A. Francois Blvd\r
+ San Francisco 94158\r
+ US\r
+\r
+08-81-B2 (hex) Logitech (China) Technology Co., Ltd\r
+0881B2 (base 16) Logitech (China) Technology Co., Ltd\r
+ 1111 Changshou Road\r
+ Shanghai 200001\r
+ CN\r
+\r
+C4-F1-74 (hex) eero inc.\r
+C4F174 (base 16) eero inc.\r
+ 660 3rd Street\r
+ San Francisco CA 94107\r
+ US\r
+\r
+28-D0-EA (hex) Intel Corporate\r
+28D0EA (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+E0-0C-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E00CE5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+28-41-EC (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+2841EC (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+7C-00-4D (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+7C004D (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+04-D3-20 (hex) ITEL MOBILE LIMITED\r
+04D320 (base 16) ITEL MOBILE LIMITED\r
+ RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K\r
+ Hong Kong KOWLOON 999077\r
+ HK\r
+\r
+1C-99-57 (hex) Intel Corporate\r
+1C9957 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+F4-6B-8C (hex) Hon Hai Precision Ind. Co., Ltd.\r
+F46B8C (base 16) Hon Hai Precision Ind. Co., Ltd.\r
+ GuangDongShenZhen\r
+ ShenZhen GuangDong 518109\r
+ CN\r
+\r
+FC-34-97 (hex) ASUSTek COMPUTER INC.\r
+FC3497 (base 16) ASUSTek COMPUTER INC.\r
+ 15,Li-Te Rd., Peitou, Taipei 112, Taiwan\r
+ Taipei Taiwan 112\r
+ TW\r
+\r
+84-7A-B6 (hex) AltoBeam (China) Inc.\r
+847AB6 (base 16) AltoBeam (China) Inc.\r
+ B808, Tsinghua Tongfang Hi-Tech Plaza, Haidian\r
+ Beijing Beijing 100083\r
+ CN\r
+\r
+78-A6-A0 (hex) Hangzhou Ezviz Software Co.,Ltd.\r
+78A6A0 (base 16) Hangzhou Ezviz Software Co.,Ltd.\r
+ Room 302, Unit B, Building 2, 399 Danfeng Road,Binjiang District\r
+ Hangzhou Zhejiang 310051\r
+ CN\r
+\r
+48-51-CF (hex) Intelbras\r
+4851CF (base 16) Intelbras\r
+ BR 101, km 210, S/N°\r
+ São José Santa Catarina 88104800\r
+ BR\r
+\r
+4C-5D-3C (hex) Cisco Systems, Inc\r
+4C5D3C (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+34-73-2D (hex) Cisco Systems, Inc\r
+34732D (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+04-7B-CB (hex) Universal Global Scientific Industrial Co., Ltd.\r
+047BCB (base 16) Universal Global Scientific Industrial Co., Ltd.\r
+ 141, Lane 351, Taiping Road, Sec.1,Tsao Tuen\r
+ Nan-Tou Taiwan 54261\r
+ TW\r
+\r
+8C-34-46 (hex) Huawei Device Co., Ltd.\r
+8C3446 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+80-47-86 (hex) Samsung Electronics Co.,Ltd\r
+804786 (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+D4-47-5A (hex) ScreenBeam, Inc.\r
+D4475A (base 16) ScreenBeam, Inc.\r
+ 3301 Olcott St\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+E4-41-64 (hex) Nokia\r
+E44164 (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+34-E9-FE (hex) Metis Co., Ltd.\r
+34E9FE (base 16) Metis Co., Ltd.\r
+ 25, Saenari-ro, Bundang-gu\r
+ Seongnam-si Gyeonggi-do 13509\r
+ KR\r
+\r
+AC-13-9C (hex) Adtran Inc\r
+AC139C (base 16) Adtran Inc\r
+ 901 Explorer Blvd.\r
+ Huntsville AL 35806-2807\r
+ US\r
+\r
+A4-CE-DA (hex) Arcadyan Corporation\r
+A4CEDA (base 16) Arcadyan Corporation\r
+ No.8, Sec.2, Guangfu Rd.\r
+ Hsinchu City Hsinchu 30071\r
+ TW\r
+\r
+00-C0-6A (hex) Zahner-Elektrik Ingeborg Zahner-Schiller GmbH & Co. KG.\r
+00C06A (base 16) Zahner-Elektrik Ingeborg Zahner-Schiller GmbH & Co. KG.\r
+ P.O. BOX 1846\r
+ \r
+ DE\r
+\r
+8C-43-61 (hex) Hailo Digital Hub GmbH & Co. KG\r
+8C4361 (base 16) Hailo Digital Hub GmbH & Co. KG\r
+ Lahnstrasse 3a\r
+ Giessen Hessen 35398\r
+ DE\r
+\r
+54-72-5E (hex) UNIONMAN TECHNOLOGY CO.,LTD\r
+54725E (base 16) UNIONMAN TECHNOLOGY CO.,LTD\r
+ No.5,Huitai Road,Huinan High-Tech Park,Huiao Highway\r
+ Huizhou Guangdong 516025\r
+ CN\r
+\r
+98-C3-D2 (hex) Ningbo Sanxing Medical Electric Co.,Ltd\r
+98C3D2 (base 16) Ningbo Sanxing Medical Electric Co.,Ltd\r
+ No.26 FengWan Road,Cicheng Town,Jiangbei District,Ningbo,China \r
+ Ningbo 315029\r
+ CN\r
+\r
+24-5D-FC (hex) IEEE Registration Authority\r
+245DFC (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+9C-82-81 (hex) vivo Mobile Communication Co., Ltd.\r
+9C8281 (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+48-7E-48 (hex) Earda Technologies co Ltd\r
+487E48 (base 16) Earda Technologies co Ltd\r
+ Block A,Lianfeng Creative Park, #2 Jisheng Rd., Nansha District\r
+ Guangzhou Guangdong 511455\r
+ CN\r
+\r
+E0-E3-7C (hex) Huawei Device Co., Ltd.\r
+E0E37C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+24-18-C6 (hex) HUNAN FN-LINK TECHNOLOGY LIMITED\r
+2418C6 (base 16) HUNAN FN-LINK TECHNOLOGY LIMITED\r
+ No.8, Litong Road, Liuyan Economic & Tec\r
+ Changsha HUNAN 410329\r
+ CN\r
+\r
+30-78-D3 (hex) Virgilant Technologies Ltd.\r
+3078D3 (base 16) Virgilant Technologies Ltd.\r
+ 2F., No.3, Aly. 19, Lane 8, Tianmu E. Rd.,Shilin Dist., \r
+ Taipei City Taiwan 11153\r
+ TW\r
+\r
+60-18-95 (hex) Dell Inc.\r
+601895 (base 16) Dell Inc.\r
+ One Dell Way\r
+ Round Rock TX 78682\r
+ US\r
+\r
+E8-EA-4D (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E8EA4D (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+3C-FF-D8 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+3CFFD8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+4C-61-7E (hex) Huawei Device Co., Ltd.\r
+4C617E (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+B4-10-7B (hex) Texas Instruments\r
+B4107B (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+64-97-14 (hex) eero inc.\r
+649714 (base 16) eero inc.\r
+ 660 3rd Street\r
+ San Francisco CA 94107\r
+ US\r
+\r
+CC-86-EC (hex) Silicon Laboratories\r
+CC86EC (base 16) Silicon Laboratories\r
+ 400 West Cesar Chavez Street\r
+ Austin 78701\r
+ US\r
+\r
+40-41-01 (hex) Rockwell Automation\r
+404101 (base 16) Rockwell Automation\r
+ 1 Allen-Bradley Dr.\r
+ Mayfield Heights OH 44124-6118\r
+ US\r
+\r
+7C-55-A7 (hex) Kastle Systems\r
+7C55A7 (base 16) Kastle Systems\r
+ 6402 Arlington Blvd\r
+ Falls Church VA 22042\r
+ US\r
+\r
+40-BE-EE (hex) Shenzhen Yunding Information Technology Co.,Ltd\r
+40BEEE (base 16) Shenzhen Yunding Information Technology Co.,Ltd\r
+ 32G, Tower E, CR Land Building, Tong Gu Road 5#, Nanshan District,,Guangdong,CN\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+A4-4C-62 (hex) Hangzhou Microimage Software Co., Ltd\r
+A44C62 (base 16) Hangzhou Microimage Software Co., Ltd\r
+ Room 313, Unit B, Building 2, 399 Danfeng Road, Binjiang District\r
+ Hangzhou Zhejiang 310051\r
+ CN\r
+\r
+FC-E8-06 (hex) Edifier International\r
+FCE806 (base 16) Edifier International\r
+ Suit 2207, 22nd floor, Tower II, Lippo centre, 89 Queensway\r
+ Hong Kong 070\r
+ CN\r
+\r
+F4-C7-95 (hex) WEY Technology AG\r
+F4C795 (base 16) WEY Technology AG\r
+ Dorfstrasse 57\r
+ Unterengstringen Zurich 8103\r
+ CH\r
+\r
+44-B4-62 (hex) Flextronics Tech.(Ind) Pvt Ltd\r
+44B462 (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
+ 365, Benjamin Road\r
+ Sricity Vardahiah Palem(M),Chilamathur Village, Chittoor Distict 517646\r
+ IN\r
+\r
+F8-D4-78 (hex) Flextronics Tech.(Ind) Pvt Ltd\r
+F8D478 (base 16) Flextronics Tech.(Ind) Pvt Ltd\r
+ 365, Benjamin Road\r
+ Sricity Vardahiah Palem(M),Chilamathur Village, Chittoor Distict 517646\r
+ IN\r
+\r
+50-C2-ED (hex) GN Audio A/S\r
+50C2ED (base 16) GN Audio A/S\r
+ Lautrupbjerg 7\r
+ Ballerup DK-2750\r
+ DK\r
+\r
+90-A8-22 (hex) Amazon Technologies Inc.\r
+90A822 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102 \r
+ Reno NV 89507\r
+ US\r
+\r
+74-AD-98 (hex) Cisco Systems, Inc\r
+74AD98 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+84-8C-8D (hex) Apple, Inc.\r
+848C8D (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+0C-5C-B5 (hex) IEEE Registration Authority\r
+0C5CB5 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+E8-4F-25 (hex) Murata Manufacturing Co., Ltd.\r
+E84F25 (base 16) Murata Manufacturing Co., Ltd.\r
+ 1-10-1, Higashikotari\r
+ Nagaokakyo-shi Kyoto 617-8555\r
+ JP\r
+\r
+04-25-E0 (hex) Taicang T&W Electronics\r
+0425E0 (base 16) Taicang T&W Electronics\r
+ 89# Jiang Nan RD\r
+ Suzhou Jiangsu 215412\r
+ CN\r
+\r
+30-85-EB (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+3085EB (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+84-06-FA (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+8406FA (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+B8-D4-3E (hex) vivo Mobile Communication Co., Ltd.\r
+B8D43E (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+C0-DC-D7 (hex) Huawei Device Co., Ltd.\r
+C0DCD7 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+30-37-B3 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+3037B3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+14-CB-19 (hex) HP Inc.\r
+14CB19 (base 16) HP Inc.\r
+ 10300 Energy Dr\r
+ Spring TX 77389\r
+ US\r
+\r
+0C-E4-41 (hex) Apple, Inc.\r
+0CE441 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+B8-2A-A9 (hex) Apple, Inc.\r
+B82AA9 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+78-64-C0 (hex) Apple, Inc.\r
+7864C0 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+74-15-75 (hex) Xiaomi Communications Co Ltd\r
+741575 (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+38-52-47 (hex) Huawei Device Co., Ltd.\r
+385247 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E8-1C-D8 (hex) Apple, Inc.\r
+E81CD8 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+3C-06-30 (hex) Apple, Inc.\r
+3C0630 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F4-02-28 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND)\r
+F40228 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND)\r
+ 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE\r
+ Bangpakong Chachoengsao 24180\r
+ TH\r
+\r
+0C-83-CC (hex) Alpha Networks Inc.\r
+0C83CC (base 16) Alpha Networks Inc.\r
+ No.8 Li-shing 7th Rd., Science-based Industrial Park, Hsinchu, Taiwan, R.O.C\r
+ Hsinchu Taiwan 300\r
+ TW\r
+\r
+EC-B9-70 (hex) Ruijie Networks Co.,LTD\r
+ECB970 (base 16) Ruijie Networks Co.,LTD\r
+ No. 2, 7th floor, xingwangruijie, haixi hi-tech industrial park, high-tech zone, fuzhou city\r
+ Fuzhou Fujian 350002\r
+ CN\r
+\r
+30-83-98 (hex) Espressif Inc.\r
+308398 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+F8-89-D2 (hex) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+F889D2 (base 16) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+ B22 Building,NO.51 Tongle Road, Shajing Town, Jiangnan District, Nanning, Guangxi Province, China\r
+ Nanning Guangxi 530007\r
+ CN\r
+\r
+10-27-F5 (hex) TP-Link Corporation Limited\r
+1027F5 (base 16) TP-Link Corporation Limited\r
+ Room 901,9/F.New East Ocean Centre, 9 Science Museum Road\r
+ Tsim Sha Tsui Kowloon 999077\r
+ HK\r
+\r
+B0-4F-13 (hex) Dell Inc.\r
+B04F13 (base 16) Dell Inc.\r
+ One Dell Way\r
+ Round Rock TX 78682\r
+ US\r
+\r
+C0-4B-13 (hex) WonderSound Technology Co., Ltd\r
+C04B13 (base 16) WonderSound Technology Co., Ltd\r
+ 10A, Center of Shenmao, News Road 59, Meiling community, Lianhua Street, Futian district\r
+ Shenzhen 518034\r
+ CN\r
+\r
+9C-7F-81 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD\r
+9C7F81 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD\r
+ Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+C4-BC-D7 (hex) New Ryatek\r
+C4BCD7 (base 16) New Ryatek\r
+ Room 103, 1st floor, building 19, yard 1, Baosheng South Road, Haidian District, Beijing\r
+ Beijing Beijing 100192\r
+ CN\r
+\r
+C0-AE-FD (hex) Shenzhen HC-WLAN Technology Co.,Ltd\r
+C0AEFD (base 16) Shenzhen HC-WLAN Technology Co.,Ltd\r
+ Room 201E, Block D, Donghai Wang Industrial Zone, No. 369, Bulong Road, Bantian Street, Longgang District\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+20-6A-94 (hex) Hitron Technologies. Inc\r
+206A94 (base 16) Hitron Technologies. Inc\r
+ No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C\r
+ Hsin-chu Taiwan 300\r
+ TW\r
+\r
+30-95-87 (hex) HUNAN FN-LINK TECHNOLOGY LIMITED\r
+309587 (base 16) HUNAN FN-LINK TECHNOLOGY LIMITED\r
+ No.8, Litong Road, Liuyan Economic & Tec\r
+ Changsha HUNAN 410329\r
+ CN\r
+\r
+DC-87-CB (hex) Beijing Perfectek Technologies Co., Ltd.\r
+DC87CB (base 16) Beijing Perfectek Technologies Co., Ltd.\r
+ A-17, No. 101, 6F, Building 24, No. 68, Beiqing Road, Haidian District\r
+ Beijing Beijing 100094\r
+ CN\r
+\r
+10-2D-41 (hex) Sichuan AI-Link Technology Co., Ltd.\r
+102D41 (base 16) Sichuan AI-Link Technology Co., Ltd.\r
+ Anzhou, Industrial Park\r
+ Mianyang Sichuan 622650\r
+ CN\r
+\r
+64-27-53 (hex) Huawei Device Co., Ltd.\r
+642753 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+7C-F6-66 (hex) Tuya Smart Inc.\r
+7CF666 (base 16) Tuya Smart Inc.\r
+ 160 Greentree Drive, Suite 101\r
+ Dover DE 19904\r
+ US\r
+\r
+28-53-4E (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+28534E (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+5C-B0-0A (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+5CB00A (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+20-CE-2A (hex) IEEE Registration Authority\r
+20CE2A (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
7C-8A-E1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. \r
7C8AE1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. \r
NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE \r
Wuhan Hubei 430074\r
CN\r
\r
-38-AF-D0 (hex) Private\r
-38AFD0 (base 16) Private\r
-\r
80-D3-36 (hex) CERN\r
80D336 (base 16) CERN\r
CH-1211 \r
Kulim Kedah 09000\r
MY\r
\r
-00-A0-0E (hex) NetAlly\r
-00A00E (base 16) NetAlly\r
- 310 Littleton Road\r
- Westford MA 01886 \r
- US\r
-\r
00-C0-17 (hex) NetAlly\r
00C017 (base 16) NetAlly\r
2075 Research Parkway\r
Bucheon-shi Kyunggi-do 421-809\r
KR\r
\r
-00-14-1D (hex) LTI-Motion GmbH\r
-00141D (base 16) LTI-Motion GmbH\r
- Gewerbestrasse 5-9\r
- Lahnau Hessen 35633\r
- DE\r
-\r
00-14-12 (hex) S-TEC electronics AG\r
001412 (base 16) S-TEC electronics AG\r
Industriestrasse 49\r
Dover DE 19904\r
US\r
\r
-14-98-77 (hex) Apple, Inc.\r
-149877 (base 16) Apple, Inc.\r
- 1 Infinite Loop\r
- Cupertino CA 95014\r
+08-A7-C0 (hex) Technicolor CH USA Inc.\r
+08A7C0 (base 16) Technicolor CH USA Inc.\r
+ 5030 Sugarloaf Parkway Bldg 6 \r
+ Lawrenceville GA 30044\r
US\r
\r
-88-66-5A (hex) Apple, Inc.\r
-88665A (base 16) Apple, Inc.\r
- 1 Infinite Loop\r
- Cupertino CA 95014\r
- US\r
+28-5B-0C (hex) Sichuan Jiuzhou Electronic Technology Co., Ltd.\r
+285B0C (base 16) Sichuan Jiuzhou Electronic Technology Co., Ltd.\r
+ No. 259, Jiuzhou Road\r
+ Mianyang City Sichuan Province 621000\r
+ CN\r
\r
-B0-E5-F9 (hex) Apple, Inc.\r
-B0E5F9 (base 16) Apple, Inc.\r
- 1 Infinite Loop\r
- Cupertino CA 95014\r
- US\r
+14-89-CB (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+1489CB (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+6C-26-36 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+6C2636 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+48-68-4A (hex) Intel Corporate\r
+48684A (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+BC-F1-71 (hex) Intel Corporate\r
+BCF171 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
\r
84-71-6A (hex) Huawei Device Co., Ltd.\r
84716A (base 16) Huawei Device Co., Ltd.\r
Dongguan Guangdong 523808\r
CN\r
\r
+58-56-C2 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+5856C2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+A0-36-79 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A03679 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+B8-D6-F6 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B8D6F6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+2C-52-AF (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+2C52AF (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+14-98-77 (hex) Apple, Inc.\r
+149877 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+88-66-5A (hex) Apple, Inc.\r
+88665A (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+B0-E5-F9 (hex) Apple, Inc.\r
+B0E5F9 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
AC-17-C8 (hex) Cisco Meraki\r
AC17C8 (base 16) Cisco Meraki\r
500 Terry A. Francois Blvd\r
500 Terry A. Francois Blvd\r
San Francisco 94158\r
US\r
+\r
+58-FB-96 (hex) Ruckus Wireless\r
+58FB96 (base 16) Ruckus Wireless\r
+ 350 West Java Drive\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+F0-62-5A (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+F0625A (base 16) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+ No.178 Yulong Avenue, Yufengshan, Yubei District, Chongqing.\r
+ Chongqing China 401120\r
+ CN\r
+\r
+64-E0-AB (hex) UNIONMAN TECHNOLOGY CO.,LTD\r
+64E0AB (base 16) UNIONMAN TECHNOLOGY CO.,LTD\r
+ No.5,Huitai Road,Huinan High-Tech Park,Huiao Highway\r
+ Huizhou Guangdong 516025\r
+ CN\r
+\r
+AC-23-16 (hex) Mist Systems, Inc.\r
+AC2316 (base 16) Mist Systems, Inc.\r
+ 1601 South De Anza Blvd, Suite 248\r
+ Cupertino CA 95014\r
+ US\r
+\r
+2C-00-AB (hex) ARRIS Group, Inc.\r
+2C00AB (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+3C-E3-6B (hex) Zhejiang Dahua Technology Co., Ltd.\r
+3CE36B (base 16) Zhejiang Dahua Technology Co., Ltd.\r
+ No.1199,Waterfront Road \r
+ Hangzhou Zhejiang 310053\r
+ CN\r
+\r
+20-3B-69 (hex) vivo Mobile Communication Co., Ltd.\r
+203B69 (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+5C-17-20 (hex) Huawei Device Co., Ltd.\r
+5C1720 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+98-3F-66 (hex) Wuhan Funshion Online Technologies Co.,Ltd\r
+983F66 (base 16) Wuhan Funshion Online Technologies Co.,Ltd\r
+ 5th Floor,Financial Port Building A9,No.77 Optical Valley Avenue, East Lake High-Tech Development Zone, Wuhan\r
+ Wuhan CN/Hubei 430000\r
+ CN\r
+\r
+60-5E-4F (hex) Huawei Device Co., Ltd.\r
+605E4F (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+1C-E6-AD (hex) Huawei Device Co., Ltd.\r
+1CE6AD (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+50-97-07 (hex) Xiamen Paperang Technology Co.,Ltd.\r
+509707 (base 16) Xiamen Paperang Technology Co.,Ltd.\r
+ Unit 1702-1703, 17/F, No.55, North Chengyi Road,Xiamen Software Park Phase 3\r
+ Xiamen Fujian 361021\r
+ CN\r
+\r
+EC-63-D7 (hex) Intel Corporate\r
+EC63D7 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+14-85-7F (hex) Intel Corporate\r
+14857F (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+7C-9F-07 (hex) CIG SHANGHAI CO LTD\r
+7C9F07 (base 16) CIG SHANGHAI CO LTD\r
+ 5th Floor, Building 8 No 2388 Chenhang Road\r
+ SHANGHAI 201114\r
+ CN\r
+\r
+1C-87-E3 (hex) TECNO MOBILE LIMITED\r
+1C87E3 (base 16) TECNO MOBILE LIMITED\r
+ ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG\r
+ Hong Kong Hong Kong 999077\r
+ HK\r
+\r
+94-E2-3C (hex) Intel Corporate\r
+94E23C (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+20-B7-30 (hex) TeconGroup, Inc\r
+20B730 (base 16) TeconGroup, Inc\r
+ 3rd Khoroshevskaya str., 20, floor 1, room 112\r
+ Moscow 123423\r
+ RU\r
+\r
+48-88-99 (hex) Shenzhen SuperElectron Technology Co.,Ltd.\r
+488899 (base 16) Shenzhen SuperElectron Technology Co.,Ltd.\r
+ 1213-1214, haosheng business center, dongbin road, nanshan street, nanshan district, shenzhen city\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+DC-B1-31 (hex) SHENZHEN HUARUIAN TECHNOLOGY CO.,LTD\r
+DCB131 (base 16) SHENZHEN HUARUIAN TECHNOLOGY CO.,LTD\r
+ Floo2nd and 3rd floor, building A, Huixin Industrial Park, No.31 Yonghe Road, Heping community, Fuhai street, Bao'an District, Shenzhen, China\r
+ Shenzhen Guangdong 518101\r
+ CN\r
+\r
+84-3B-10 (hex) Lv switch Inc.\r
+843B10 (base 16) Lv switch Inc.\r
+ F1 building,New light source base Luocun town,Nanhai district\r
+ Foshan Guangdong 528000\r
+ CN\r
+\r
+94-A4-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+94A4F9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+6C-34-91 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+6C3491 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+E8-4D-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E84D74 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+CC-89-5E (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+CC895E (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+80-44-FD (hex) China Mobile (Hangzhou) Information Technology Co., Ltd.\r
+8044FD (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd.\r
+ No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District, Hangzhou, Zhejiang\r
+ Hangzhou Zhejiang 310000\r
+ CN\r
+\r
+F4-6A-D7 (hex) Microsoft Corporation\r
+F46AD7 (base 16) Microsoft Corporation\r
+ One Microsoft Way\r
+ REDMOND WA 98052\r
+ US\r
+\r
+48-1F-2D (hex) Shenzhen Jie Shi Lian Industrial Co.,LTD\r
+481F2D (base 16) Shenzhen Jie Shi Lian Industrial Co.,LTD\r
+ 6F,C Building,Jinao Industrial Park,Juling Rd,Guanlan Town,Longhua\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+8C-73-A0 (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+8C73A0 (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+14-09-B4 (hex) zte corporation\r
+1409B4 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+10-10-81 (hex) zte corporation\r
+101081 (base 16) zte corporation\r
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+78-CF-F9 (hex) Huawei Device Co., Ltd.\r
+78CFF9 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+A8-E8-1E (hex) ATW TECHNOLOGY, INC.\r
+A8E81E (base 16) ATW TECHNOLOGY, INC.\r
+ 1F, No.236 Ba’ai Street, Shulin District\r
+ New Taipei City 23845\r
+ TW\r
+\r
+F8-85-F9 (hex) Calix Inc.\r
+F885F9 (base 16) Calix Inc.\r
+ 2777 Orchard Pkwy\r
+ San Jose CA 95131\r
+ US\r
+\r
+CC-88-C7 (hex) Aruba, a Hewlett Packard Enterprise Company\r
+CC88C7 (base 16) Aruba, a Hewlett Packard Enterprise Company\r
+ 3333 Scott Blvd\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+F8-1A-2B (hex) Google, Inc.\r
+F81A2B (base 16) Google, Inc.\r
+ 1600 Amphitheatre Parkway\r
+ Mountain View CA 94043\r
+ US\r
+\r
+F4-A8-0D (hex) Wistron InfoComm(Kunshan)Co.,Ltd.\r
+F4A80D (base 16) Wistron InfoComm(Kunshan)Co.,Ltd.\r
+ 168# First Avenue,Kunshan Integrated Free Trade Zone,Kunshan,Jiangsu,China\r
+ Kunshan Jiangsu 215300\r
+ CN\r
+\r
+08-A1-89 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+08A189 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+ No.555 Qianmo Road\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+80-F3-EF (hex) Facebook Technologies, LLC\r
+80F3EF (base 16) Facebook Technologies, LLC\r
+ 1601 Willow Rd\r
+ Menlo Park CA 94025\r
+ US\r
+\r
+3C-A8-ED (hex) smart light technology\r
+3CA8ED (base 16) smart light technology\r
+ 172 LSro\r
+ Gunpo Gyeonggido 15807\r
+ KR\r
+\r
+04-C2-9B (hex) Aura Home, Inc.\r
+04C29B (base 16) Aura Home, Inc.\r
+ 50 Eldridge Street, Suite 5D\r
+ New York NY 10002\r
+ US\r
+\r
+14-3B-42 (hex) Realfit(Shenzhen) Intelligent Technology Co., Ltd\r
+143B42 (base 16) Realfit(Shenzhen) Intelligent Technology Co., Ltd\r
+ Room 201, building a, No.1 Qianwan 1st Road, Shenzhen Hong Kong cooperation zone, Qianhai\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+EC-2E-98 (hex) AzureWave Technology Inc.\r
+EC2E98 (base 16) AzureWave Technology Inc.\r
+ 8F., No. 94, Baozhong Rd.\r
+ New Taipei City Taiwan 231\r
+ TW\r
+\r
+38-F3-AB (hex) LCFC(HeFei) Electronics Technology co., ltd\r
+38F3AB (base 16) LCFC(HeFei) Electronics Technology co., ltd\r
+ YunGu Road 3188-1\r
+ Hefei Anhui 230000\r
+ CN\r
+\r
+50-AE-86 (hex) Linkintec Co., Ltd\r
+50AE86 (base 16) Linkintec Co., Ltd\r
+ 3rd floor, building A3, phase I, Zhihui Industrial Park, intersection of Chongqing Road and Yan'an Road, Baohe Economic Development Zone\r
+ Hefei City Anhui 230041\r
+ CN\r
+\r
+38-B3-F7 (hex) Huawei Device Co., Ltd.\r
+38B3F7 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-E9-86 (hex) Huawei Device Co., Ltd.\r
+84E986 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+AC-1F-0F (hex) Texas Instruments\r
+AC1F0F (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+74-D2-85 (hex) Texas Instruments\r
+74D285 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+60-15-92 (hex) IEEE Registration Authority\r
+601592 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+10-C9-CA (hex) Ace Technology Corp.\r
+10C9CA (base 16) Ace Technology Corp.\r
+ 237, Namdongseo-ro, Namdong-gu\r
+ Incheon 21634\r
+ KR\r
+\r
+BC-FA-B8 (hex) Guangzhou Shiyuan Electronic Technology Company Limited\r
+BCFAB8 (base 16) Guangzhou Shiyuan Electronic Technology Company Limited\r
+ No.6, 4th Yunpu Road, Yunpu industry District\r
+ Guangzhou Guangdong 510530\r
+ CN\r
+\r
+D4-77-98 (hex) Cisco Systems, Inc\r
+D47798 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+A0-4A-5E (hex) Microsoft Corporation\r
+A04A5E (base 16) Microsoft Corporation\r
+ One Microsoft Way\r
+ REDMOND WA 98052\r
+ US\r
+\r
+EC-02-73 (hex) Aruba, a Hewlett Packard Enterprise Company\r
+EC0273 (base 16) Aruba, a Hewlett Packard Enterprise Company\r
+ 3333 Scott Blvd\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+F4-B1-C2 (hex) Zhejiang Dahua Technology Co., Ltd.\r
+F4B1C2 (base 16) Zhejiang Dahua Technology Co., Ltd.\r
+ No.1199,Waterfront Road \r
+ Hangzhou Zhejiang 310053\r
+ CN\r
+\r
+A4-DA-D4 (hex) Yamato Denki Co.,Ltd.\r
+A4DAD4 (base 16) Yamato Denki Co.,Ltd.\r
+ 3-2-14,Koyama\r
+ Shinagawa-ku,Tokyo 142-0062\r
+ JP\r
+\r
+10-94-97 (hex) Logitech Hong Kong\r
+109497 (base 16) Logitech Hong Kong\r
+ Room 1002-1003, 10/F, Tower 1, Cheung Sha Wan Plaza, 833 Cheung Sha Wan Road, Kowloon, Hong Kong\r
+ Hong Kong NA\r
+ HK\r
+\r
+00-14-1D (hex) KEBA Industrial Automation Germany GmbH\r
+00141D (base 16) KEBA Industrial Automation Germany GmbH\r
+ Gewerbestrasse 5-9\r
+ Lahnau Hessen 35633\r
+ DE\r
+\r
+E0-DA-90 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E0DA90 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+A4-A4-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A4A46B (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+C0-47-54 (hex) vivo Mobile Communication Co., Ltd.\r
+C04754 (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+A0-D7-A0 (hex) Huawei Device Co., Ltd.\r
+A0D7A0 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+40-E6-4B (hex) Apple, Inc.\r
+40E64B (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+B4-FA-48 (hex) Apple, Inc.\r
+B4FA48 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+94-3C-C6 (hex) Espressif Inc.\r
+943CC6 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+8C-83-FC (hex) Axioma Metering UAB\r
+8C83FC (base 16) Axioma Metering UAB\r
+ Veterinaru str. 52\r
+ Biruliskes Kaunas district LT-54469\r
+ LT\r
+\r
+F0-2F-4B (hex) Apple, Inc.\r
+F02F4B (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+60-A4-B7 (hex) TP-Link Corporation Limited\r
+60A4B7 (base 16) TP-Link Corporation Limited\r
+ Room 901,9/F.New East Ocean Centre, 9 Science Museum Road\r
+ Tsim Sha Tsui Kowloon 999077\r
+ HK\r
+\r
+8C-D9-D6 (hex) Xiaomi Communications Co Ltd\r
+8CD9D6 (base 16) Xiaomi Communications Co Ltd\r
+ The Rainbow City of China Resources\r
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085\r
+ CN\r
+\r
+60-C5-E6 (hex) Skullcandy\r
+60C5E6 (base 16) Skullcandy\r
+ 6301 N. Landmark Dr.\r
+ Park City 84098\r
+ US\r
+\r
+38-F3-FB (hex) Asperiq\r
+38F3FB (base 16) Asperiq\r
+ Finngatan 8\r
+ Lund SE-22362\r
+ SE\r
+\r
+A4-58-02 (hex) SHIN-IL TECH\r
+A45802 (base 16) SHIN-IL TECH\r
+ 711 HO,DAEMYEONG BELLI ON,10, Gyeongin-ro 53ga-gil, Guro-gu\r
+ Seoul KS013\r
+ KR\r
+\r
+38-AF-D0 (hex) Nevro\r
+38AFD0 (base 16) Nevro\r
+ 1800 Bridge Pkwy\r
+ Redwood City CA 94065\r
+ US\r
+\r
+00-A0-0E (hex) NETSCOUT SYSTEMS INC\r
+00A00E (base 16) NETSCOUT SYSTEMS INC\r
+ 310 Littleton Road\r
+ Westford MA 01886 \r
+ US\r
+\r
+30-A6-12 (hex) ShenZhen Hugsun Technology Co.,Ltd.\r
+30A612 (base 16) ShenZhen Hugsun Technology Co.,Ltd.\r
+ 413~415 Room, 4/F, No.6 Bldg., TongFuYu Industrial Park, Dalang Street, 518109, Longhua New District,\r
+ ShengZhen GuangDong 518109\r
+ CN\r
+\r
+EC-B4-E8 (hex) Wistron Mexico SA de CV\r
+ECB4E8 (base 16) Wistron Mexico SA de CV\r
+ Baudelio Perez Mucharras #420 Col Paseos de Zaragoza \r
+ ciudad Juarez Chihuahua 32550\r
+ MX\r
+\r
+10-38-1F (hex) Sichuan AI-Link Technology Co., Ltd.\r
+10381F (base 16) Sichuan AI-Link Technology Co., Ltd.\r
+ Anzhou, Industrial Park\r
+ Mianyang Sichuan 622650\r
+ CN\r
+\r
+3C-7A-C4 (hex) Chemtronics\r
+3C7AC4 (base 16) Chemtronics\r
+ junho.hong@chemtronics.co.kr\r
+ Bundang-gu Gyeonggi-do 13493\r
+ KR\r
+\r
+54-14-F3 (hex) Intel Corporate\r
+5414F3 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+18-BB-41 (hex) Huawei Device Co., Ltd.\r
+18BB41 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+78-18-A8 (hex) Huawei Device Co., Ltd.\r
+7818A8 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+80-72-64 (hex) Huawei Device Co., Ltd.\r
+807264 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E8-F6-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E8F654 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+20-87-EC (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+2087EC (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+54-F6-E2 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+54F6E2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+A8-50-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A85081 (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
+ Dongguan 523808\r
+ CN\r
+\r
+6C-FE-54 (hex) Intel Corporate\r
+6CFE54 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+8C-36-7A (hex) Palo Alto Networks\r
+8C367A (base 16) Palo Alto Networks\r
+ 3000 Tannery Way\r
+ Santa Clara CA 95054\r
+ US\r
Shenzhen 518000\r
CN\r
\r
-8C-19-2D (hex) DataRemote Inc.\r
-200000-2FFFFF (base 16) DataRemote Inc.\r
- 19301 SW 106th Ave Suite 6\r
- Miami FL 33157\r
- US\r
-\r
D0-D9-4F (hex) Perfant Technology Co., Ltd\r
000000-0FFFFF (base 16) Perfant Technology Co., Ltd\r
Guo Ren Tong Xin B317,Ke Ji Zhong San Lu,Nanshan,Shenzhen,Guangdong,China\r
NINGBO ZHEJIANG PROVINCE 315191\r
CN\r
\r
+44-6F-D8 (hex) Changzhou Haitu Electronic Technology Co.,Ltd\r
+C00000-CFFFFF (base 16) Changzhou Haitu Electronic Technology Co.,Ltd\r
+ Building 47, Hang Seng Science park, Tianning District\r
+ Changzhou Jiangsu 213000\r
+ CN\r
+\r
+98-27-82 (hex) KORTEK CORPORATION\r
+700000-7FFFFF (base 16) KORTEK CORPORATION\r
+ 26, Venture-ro24beon-gil, Yeonsu-gu\r
+ Incheon 22011\r
+ KR\r
+\r
+98-27-82 (hex) Dspread Technology (Beijing) Inc.\r
+400000-4FFFFF (base 16) Dspread Technology (Beijing) Inc.\r
+ Jingxin Building, 2045 Suite , Chaoyang District\r
+ Beijing 100027\r
+ CN\r
+\r
+8C-19-2D (hex) DataRemote Inc.\r
+200000-2FFFFF (base 16) DataRemote Inc.\r
+ 18001 Old Cutler Rd. Suite 600\r
+ Palmetto Bay FL 33157\r
+ US\r
+\r
+04-11-19 (hex) Herrick Tech Labs\r
+700000-7FFFFF (base 16) Herrick Tech Labs\r
+ 20201 Century Blvd.\r
+ Germantown MD 20874\r
+ US\r
+\r
+E8-6C-C7 (hex) Limited Liability Company M.S.Korp\r
+C00000-CFFFFF (base 16) Limited Liability Company M.S.Korp\r
+ Mironovskaya st., 33, bldg.26, floor 4, office 5\r
+ Moscow Russian Federation 105318\r
+ RU\r
+\r
+E8-6C-C7 (hex) Trapeze Switzerland GmbH\r
+000000-0FFFFF (base 16) Trapeze Switzerland GmbH\r
+ Industrieplatz 3.\r
+ Neuhausen am Rheinfall Schaffhausen 8212\r
+ CH\r
+\r
+E8-6C-C7 (hex) Lighthouse EIP\r
+800000-8FFFFF (base 16) Lighthouse EIP\r
+ 21370 Heywood Avenue\r
+ Lakeville MN 55044\r
+ US\r
+\r
+E8-6C-C7 (hex) Koal Software Co., Ltd\r
+400000-4FFFFF (base 16) Koal Software Co., Ltd\r
+ Floor 6, Building 4, Lane 299, Jiangchang West Road, Jing 'an District\r
+ Shanghai Shanghai 200436\r
+ CN\r
+\r
+E8-6C-C7 (hex) Xirgo Technologies LLC\r
+200000-2FFFFF (base 16) Xirgo Technologies LLC\r
+ 188 Camino Ruiz\r
+ Camarillo CA 93012\r
+ US\r
+\r
+24-5D-FC (hex) Cosmicnode\r
+800000-8FFFFF (base 16) Cosmicnode\r
+ Zandstrand\r
+ Eindhoven North Brabant 5658BJ\r
+ NL\r
+\r
+24-5D-FC (hex) Suzhou Jiangzhi electronic technology co., Ltd\r
+400000-4FFFFF (base 16) Suzhou Jiangzhi electronic technology co., Ltd\r
+ Room 303, Building 2, No.88 Baifu Road, Kunshan Development Zone\r
+ Kunshan Jiangsu 215300\r
+ CN\r
+\r
+60-15-92 (hex) S Labs sp. z o.o.\r
+000000-0FFFFF (base 16) S Labs sp. z o.o.\r
+ Dworska 1a/1u\r
+ Kraków Lesser Poland 30-314\r
+ PL\r
+\r
+60-15-92 (hex) Annapurna labs\r
+B00000-BFFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+0C-5C-B5 (hex) The Raymond Corporation\r
+500000-5FFFFF (base 16) The Raymond Corporation\r
+ 22 South Canal St\r
+ Greene NY 13778\r
+ US\r
+\r
+60-15-92 (hex) Zaptec\r
+400000-4FFFFF (base 16) Zaptec\r
+ Richard Johnsensgate 4\r
+ Stavanger Rogaland N-4021\r
+ NO\r
+\r
+1C-A0-EF (hex) Shenzhen Liandian Communication Technology Co.LTD\r
+D00000-DFFFFF (base 16) Shenzhen Liandian Communication Technology Co.LTD\r
+ 1307, building A4, workshop 2, LiLang International Jewelry Industrial Park, 31 Bulan Road, xialilang community, Nanwan street, Longgang District\r
+ Shenzhen Guangdong 518112\r
+ CN\r
+\r
+0C-5C-B5 (hex) ADI\r
+B00000-BFFFFF (base 16) ADI\r
+ 2 Crest Hollow Lane\r
+ Manorville NY 11949\r
+ US\r
+\r
+1C-A0-EF (hex) Wisnu and Supak Co.,Ltd.\r
+100000-1FFFFF (base 16) Wisnu and Supak Co.,Ltd.\r
+ 102/111-112 Mooban Sinpattanatanee,, Tessabansongkroh Road., Ladyao, Jatujak,\r
+ Jatujak Bangkok Metropolis 10900\r
+ TH\r
+\r
4C-4B-F9 (hex) Shenzhen dingsheng technology co., LTD\r
400000-4FFFFF (base 16) Shenzhen dingsheng technology co., LTD\r
Floor 3, building 5, kaijeda industrial zone, no.97, huaxing road, langkou community, dalang street, longhua district\r
San Jose CA 95113\r
US\r
\r
-F0-23-B9 (hex) Private\r
-D00000-DFFFFF (base 16) Private\r
-\r
B0-FD-0B (hex) IDspire Corporation Ltd.\r
100000-1FFFFF (base 16) IDspire Corporation Ltd.\r
9F, No. 266, Sec. 1, Wenhua Rd., Banqiao Dist.\r
SAN DIEGO CA 92123\r
US\r
\r
-38-B8-EB (hex) Private\r
-700000-7FFFFF (base 16) Private\r
-\r
4C-BC-98 (hex) Dongguan SmartAction Technology Co.,Ltd\r
B00000-BFFFFF (base 16) Dongguan SmartAction Technology Co.,Ltd\r
Room1109,Building D,First Place,Nancheng District, Dongguan\r
Motilla del Palancar Cuenca 16200\r
ES\r
\r
-A4-53-EE (hex) Aura Home, Inc.\r
-600000-6FFFFF (base 16) Aura Home, Inc.\r
- 50 Eldridge Street, Suite 5D\r
- New York NY 10002\r
- US\r
-\r
A4-53-EE (hex) SSK CORPORATION\r
D00000-DFFFFF (base 16) SSK CORPORATION\r
3F, M-10, Centre of Hi-Tech Industrial Park, Nanshan\r
Beaverton OR 97008\r
US\r
\r
+44-6F-D8 (hex) ZHEJIANG HIKAILINK TECHNOLOGY Co., Ltd\r
+A00000-AFFFFF (base 16) ZHEJIANG HIKAILINK TECHNOLOGY Co., Ltd\r
+ Room 116, 1 / F, building 2, No. 87, Hexi, Changfeng street, Wuzhen Town, Tongxiang City\r
+ Jiaxing City Zhejiang China\r
+ CN\r
+\r
+44-6F-D8 (hex) Shenzhen Mestechs Technology CO., LTD\r
+300000-3FFFFF (base 16) Shenzhen Mestechs Technology CO., LTD\r
+ The 3rd Floor, E4A Bldg?TCL International E city, NO.1001 zhongshanyuan Rd, Nanshan District\r
+ shenzhen GuangDong 518052\r
+ CN\r
+\r
+98-27-82 (hex) Guangzhou Wuzhou Technology Co, Ltd.\r
+500000-5FFFFF (base 16) Guangzhou Wuzhou Technology Co, Ltd.\r
+ 4th Floor, Building C2, Hi-Tech Enterprise Accelerator, Kaiyuan Avenue #11, Huangpu District\r
+ Guangzhou Guangdong 510530\r
+ CN\r
+\r
+98-27-82 (hex) Nanjing BianYu Future Home Technology Co.Ltd\r
+A00000-AFFFFF (base 16) Nanjing BianYu Future Home Technology Co.Ltd\r
+ Longyu Middle Street\r
+ Beijing Beijing 100085\r
+ CN\r
+\r
+98-27-82 (hex) Wuxi GuoYiHaiJu Technology Co.,Ltd.\r
+900000-9FFFFF (base 16) Wuxi GuoYiHaiJu Technology Co.,Ltd.\r
+ Innovation Industrial Park E2-2F\r
+ hefei 230000\r
+ CN\r
+\r
+98-27-82 (hex) CATS Power design\r
+800000-8FFFFF (base 16) CATS Power design\r
+ 144 route des Vernes\r
+ PRINGY 74370\r
+ FR\r
+\r
+04-11-19 (hex) Alethea Communications Technologies Pvt. Ltd.\r
+200000-2FFFFF (base 16) Alethea Communications Technologies Pvt. Ltd.\r
+ 2346, 17th Cross, HSR Layout\r
+ Bangalore Karnataka 560102\r
+ IN\r
+\r
+04-11-19 (hex) Acentury\r
+100000-1FFFFF (base 16) Acentury\r
+ 120 West Beaver Creek Road, Unit 13\r
+ Richmond Hill ON L4B 1L2\r
+ CA\r
+\r
+E8-6C-C7 (hex) Huaqin Technology Co.,Ltd\r
+700000-7FFFFF (base 16) Huaqin Technology Co.,Ltd\r
+ No. 10 Keyuan Road, Songshan Lake\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+38-B8-EB (hex) Sirin Mobile Technologies\r
+700000-7FFFFF (base 16) Sirin Mobile Technologies\r
+ Muhlentalstrasse 2\r
+ Schaffhausen 8200\r
+ CH\r
+\r
+24-5D-FC (hex) CompanyDeep\r
+000000-0FFFFF (base 16) CompanyDeep\r
+ 122, Ross Street\r
+ Cambridge Cambridgeshire CB13BU\r
+ GB\r
+\r
+24-5D-FC (hex) TORGOVYY DOM TEHNOLOGIY LLC\r
+900000-9FFFFF (base 16) TORGOVYY DOM TEHNOLOGIY LLC\r
+ Gospytalnaya 10, ap. 109, village Selyatino, city Naro-Fominsk,\r
+ Moscow Moscow Region 143345\r
+ RU\r
+\r
+E8-6C-C7 (hex) CoxSpace\r
+A00000-AFFFFF (base 16) CoxSpace\r
+ 858ho, Business Support Hub, 815, Daewangpangyo-ro Sujeong-gu\r
+ Seongnam Kyeonggi-do 13449\r
+ KR\r
+\r
+24-5D-FC (hex) ContactProximity Inc\r
+500000-5FFFFF (base 16) ContactProximity Inc\r
+ 241 Arlington Street #966\r
+ Acton MA 01720\r
+ US\r
+\r
+F0-23-B9 (hex) Shenyang Ali Technology Company Limited\r
+D00000-DFFFFF (base 16) Shenyang Ali Technology Company Limited\r
+ No.17-5, Wensu Street\r
+ Dongling District Shenyang Liaoning Province 110168\r
+ CN\r
+\r
+24-5D-FC (hex) Guangzhou Lango Electronics Technology Co.,Ltd.\r
+600000-6FFFFF (base 16) Guangzhou Lango Electronics Technology Co.,Ltd.\r
+ Room 238, Room 406, No. 1, Yichuang Street, Huangpu District\r
+ Guangzhou Guangdong 510336\r
+ CN\r
+\r
+0C-5C-B5 (hex) Hunan Newman Car NetworKing Technology Co.,Ltd\r
+C00000-CFFFFF (base 16) Hunan Newman Car NetworKing Technology Co.,Ltd\r
+ 128 Lixiang East Road,ChangshaEconomic and Technological Development Zone\r
+ Changsha Hunan 410100\r
+ CN\r
+\r
+0C-5C-B5 (hex) S2C limited\r
+600000-6FFFFF (base 16) S2C limited\r
+ E1 No.2555 Xiupu Rd. Pudong New Area\r
+ Shanghai Shanghai 201135\r
+ CN\r
+\r
+1C-A0-EF (hex) LLC Gagar.In\r
+C00000-CFFFFF (base 16) LLC Gagar.In\r
+ Rybnikov Pereulok 1\r
+ Moscow 107045\r
+ RU\r
+\r
+1C-A0-EF (hex) Zillnk\r
+800000-8FFFFF (base 16) Zillnk\r
+ No. 505, 5 / F, Unit 2, building 1, No. 777, North Section of Yizhou Avenue, Chengdu High Tech Zone, China (Sichuan) Pilot Free Trade Zone\r
+ Chengdu 610000\r
+ CN\r
+\r
+1C-A0-EF (hex) Tangshan Liulin Automation Equipment Co., Ltd.\r
+000000-0FFFFF (base 16) Tangshan Liulin Automation Equipment Co., Ltd.\r
+ Building 110-3, No.410 Huoju Road, High-tech Zone\r
+ Tangshan City Hebei Province 063000\r
+ CN\r
+\r
+1C-A0-EF (hex) Leviathan Solutions Ltd.\r
+400000-4FFFFF (base 16) Leviathan Solutions Ltd.\r
+ Abel Jeno utca 23\r
+ Budapest 1113\r
+ HU\r
+\r
+20-CE-2A (hex) Shanghai Digicube Info&Tech Co.,Ltd.\r
+100000-1FFFFF (base 16) Shanghai Digicube Info&Tech Co.,Ltd.\r
+ Room B, 9th floor, building 1, Hongqiao headquarters, 100 Zixiu Road, \r
+ Shanghai Minhang District 201103\r
+ CN\r
+\r
20-85-93 (hex) UNILUMIN GROUP CO.,LTD\r
300000-3FFFFF (base 16) UNILUMIN GROUP CO.,LTD\r
No.112 Yongfu Rd.,BaoanDistrict,\r
Longmont CO 80501\r
US\r
\r
-DC-E5-33 (hex) Private\r
-A00000-AFFFFF (base 16) Private\r
-\r
24-15-10 (hex) SHANDONG KEHUI POWER AUTOMATION CO. LTD.\r
600000-6FFFFF (base 16) SHANDONG KEHUI POWER AUTOMATION CO. LTD.\r
No. 16,Sanying Road\r
JUVIGNY Select State 74100\r
FR\r
\r
+98-27-82 (hex) SHENZHEN HEROFUN BIO-TECH CO., LTD\r
+000000-0FFFFF (base 16) SHENZHEN HEROFUN BIO-TECH CO., LTD\r
+ 7001B, 7th Floor, LaoBing Building, East Block 2, No. 3012 XingYe Road, BaoAn District\r
+ Shenzhen 518100\r
+ CN\r
+\r
+44-6F-D8 (hex) Annapurna labs\r
+900000-9FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+44-6F-D8 (hex) Anhui GuDao Tech\r
+600000-6FFFFF (base 16) Anhui GuDao Tech\r
+ Dangtu Qingshanhe\r
+ MaAnShan AnHui 243000\r
+ CN\r
+\r
+98-27-82 (hex) RayTron, INC.\r
+B00000-BFFFFF (base 16) RayTron, INC.\r
+ 11F.ESLEAD Bldg.HONMACHI 1-4-8 HONMACHI CHUO-KU\r
+ Osaka Osaka 541-0053\r
+ JP\r
+\r
+98-27-82 (hex) Thorlabs GmbH\r
+D00000-DFFFFF (base 16) Thorlabs GmbH\r
+ Münchner Weg 1\r
+ Bergkirchen 85232\r
+ DE\r
+\r
+98-27-82 (hex) WESTERN SECURITY SOLUTIONS\r
+600000-6FFFFF (base 16) WESTERN SECURITY SOLUTIONS\r
+ WSS TOWER HARINAGAR\r
+ GURUGRAM HARYANA 122001\r
+ IN\r
+\r
+98-27-82 (hex) Danfoss Power Solutions\r
+300000-3FFFFF (base 16) Danfoss Power Solutions\r
+ 3500 Annapolis Lane N\r
+ Minneapolis MN 55447\r
+ US\r
+\r
+04-11-19 (hex) AC Power Distribution / ACT Entmt.\r
+900000-9FFFFF (base 16) AC Power Distribution / ACT Entmt.\r
+ 2313 N. Valley St.\r
+ Burbank CA 91505\r
+ US\r
+\r
+04-11-19 (hex) Nuance Hearing Ltd.\r
+D00000-DFFFFF (base 16) Nuance Hearing Ltd.\r
+ Raoul Wallenberg 24, Building A1, Floor 3\r
+ Tel Aviv 6971920\r
+ IL\r
+\r
+04-11-19 (hex) SUZHOU RIBAO TECHNOLOGY CO.,LTD.\r
+300000-3FFFFF (base 16) SUZHOU RIBAO TECHNOLOGY CO.,LTD.\r
+ SUZHOU RIBAO TECHNOLOGY CO.,LTD.\r
+ SUZHOU JIANGSU 215133\r
+ CN\r
+\r
+04-11-19 (hex) CyOne Security AG\r
+A00000-AFFFFF (base 16) CyOne Security AG\r
+ Hinterbergstrasse 18\r
+ Steinhausen Zug 6312\r
+ CH\r
+\r
+E8-6C-C7 (hex) Annapurna labs\r
+E00000-EFFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+E8-6C-C7 (hex) Shenzhen Yibaifen Industrial Co.,Ltd.\r
+300000-3FFFFF (base 16) Shenzhen Yibaifen Industrial Co.,Ltd.\r
+ 501/501, Building 2, Hongxiang Industrial Park, 21 Huancheng South Road, Ma'antang Community, Bantian Street, Longgang District, Shenzhen\r
+ Shenzhen 518000\r
+ CN\r
+\r
+E8-6C-C7 (hex) z-max mediasolution\r
+D00000-DFFFFF (base 16) z-max mediasolution\r
+ Surugadai Bldg.8F kanda surugadai 1-7-10\r
+ Chiyodaku Tokyo 101-0062\r
+ JP\r
+\r
+DC-E5-33 (hex) Amazinglayer Network Co., Ltd.\r
+A00000-AFFFFF (base 16) Amazinglayer Network Co., Ltd.\r
+ Room118, Building B, JinTaiHuaYun Building, WuGenLin HuTong 11\r
+ Beijing Beijing 100035\r
+ CN\r
+\r
+24-5D-FC (hex) ARTICONA - Bechtle Logistik & Service GmbH\r
+100000-1FFFFF (base 16) ARTICONA - Bechtle Logistik & Service GmbH\r
+ Bechtle Platz 1\r
+ Neckarsulm Baden-Württemberg 74172\r
+ DE\r
+\r
+24-5D-FC (hex) Blue Iris Labs\r
+200000-2FFFFF (base 16) Blue Iris Labs\r
+ 18 Acacia Rd\r
+ Fairfax CA 94930\r
+ US\r
+\r
+24-5D-FC (hex) LTY LLC\r
+700000-7FFFFF (base 16) LTY LLC\r
+ 1321 UPLAND DR\r
+ HOUSTON TX 77043\r
+ US\r
+\r
+60-15-92 (hex) PSS Co., Ltd\r
+C00000-CFFFFF (base 16) PSS Co., Ltd\r
+ 4F., No. 10, Ln. 327, Sec. 2, Zhongshan Rd., Zhonghe Dist.\r
+ New Taipei City ??? 235\r
+ TW\r
+\r
+0C-5C-B5 (hex) Annapurna labs\r
+400000-4FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+60-15-92 (hex) RTDS Technologies Inc.\r
+100000-1FFFFF (base 16) RTDS Technologies Inc.\r
+ 100-150 Innovation Drive\r
+ Winnipeg Manitoba R3T 2E1\r
+ CA\r
+\r
+60-15-92 (hex) Annapurna labs\r
+E00000-EFFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+60-15-92 (hex) JIANGSU SUNFY TECHNOLOGIES HOLDING CO.,LTD.\r
+900000-9FFFFF (base 16) JIANGSU SUNFY TECHNOLOGIES HOLDING CO.,LTD.\r
+ Building 6, No. 1088, Jiangcheng Road, Sutong Technology Industrial Park\r
+ Nantong Jiangsu 226017\r
+ CN\r
+\r
+60-15-92 (hex) OSI TECHNOLOGY CO.,LTD.\r
+300000-3FFFFF (base 16) OSI TECHNOLOGY CO.,LTD.\r
+ No.74, Fenyang Rd., Sanmin Dist.\r
+ Kaohsiung City Taiwan 807\r
+ TW\r
+\r
+0C-5C-B5 (hex) Shenzhen C & D Electronics Co., Ltd.\r
+800000-8FFFFF (base 16) Shenzhen C & D Electronics Co., Ltd.\r
+ 9th FIoor, Building 9, No.1 Qingxiang road, BaoNeng Science and TechnoIogy Industrial Park, Longhua New District\r
+ ShenZhen GuangDong 518000\r
+ CN\r
+\r
+0C-5C-B5 (hex) iH&S Technology Limited\r
+300000-3FFFFF (base 16) iH&S Technology Limited\r
+ iH&S Technology Limited\r
+ 7/F, Unify Commercial & Ind. Bldg., 31 Tai Yip Street, Kwun Tong Hong Kong 999077\r
+ HK\r
+\r
+0C-5C-B5 (hex) Colordeve International\r
+900000-9FFFFF (base 16) Colordeve International\r
+ 601, block B, Logistics Park, Yihong Road, Yantian village, Fenggang Town, DG, GD, China\r
+ Dongguan City 523702\r
+ CN\r
+\r
+0C-5C-B5 (hex) Energybox Limited\r
+700000-7FFFFF (base 16) Energybox Limited\r
+ 8/F., Green 18, HK Science Park\r
+ Sha Tin Hong Kong 0000\r
+ HK\r
+\r
+1C-A0-EF (hex) HANJEN.CHIN CO., LTD.\r
+600000-6FFFFF (base 16) HANJEN.CHIN CO., LTD.\r
+ Fl.2 No. 101 Jian 1st Rd., Zhonghe Dist., \r
+ NEW TAIPEI CITY TAIWAN 235\r
+ TW\r
+\r
+20-CE-2A (hex) Beijing Huadianzhongxin Tech.Co.,Ltd\r
+700000-7FFFFF (base 16) Beijing Huadianzhongxin Tech.Co.,Ltd\r
+ Room 318,the 3rd Floorl,Xingtianhaiyuan Building,Xianghuangqi East Rd,Nongda South Rd, Haidian District,Beijing,P.R.C\r
+ Bei Jing 100193\r
+ CN\r
+\r
4C-4B-F9 (hex) Shandong Linkotech Electronic Co., Ltd.\r
600000-6FFFFF (base 16) Shandong Linkotech Electronic Co., Ltd.\r
22nd Floor, Building 2, Aosheng Building, No.1166 Xinyi Street, High-tech Zone\r
San Jose California 95128\r
US\r
\r
-00-55-DA (hex) Nanoleaf\r
-500000-5FFFFF (base 16) Nanoleaf\r
- 162 John Street\r
- Toronto Ontario M5V2E5\r
- CA\r
-\r
00-55-DA (hex) Speechlab\r
A00000-AFFFFF (base 16) Speechlab\r
Gaasterlandstraat 3\r
Asbury Park NJ 07712\r
US\r
\r
-74-F8-DB (hex) Avantree Corporation\r
-900000-9FFFFF (base 16) Avantree Corporation\r
- 41871 Via San Miguel\r
- Fremont CA 94539\r
- US\r
-\r
88-5D-90 (hex) Creative Sensor Inc.\r
800000-8FFFFF (base 16) Creative Sensor Inc.\r
9F., No.501, Sec. 6, Nanjing E. Rd., Neihu Dist., Taipei City 114, Taiwan (R.O.C.)\r
Mail box 15123 Haifa 3508409\r
IL\r
\r
-40-11-75 (hex) disguise Technologies Limited\r
-C00000-CFFFFF (base 16) disguise Technologies Limited\r
- Units C&D 127 Great Suffolk Street\r
- London SE1 1PP\r
- GB\r
-\r
10-DC-B6 (hex) Shenzhen Sunwoda intelligent hardware Co.,Ltd\r
E00000-EFFFFF (base 16) Shenzhen Sunwoda intelligent hardware Co.,Ltd\r
No.6-6,Yan Shan Rd.,Baoan District,Shenzhen City,China\r
Beijing 100070\r
CN\r
\r
+40-11-75 (hex) disguise Technologies Limited\r
+C00000-CFFFFF (base 16) disguise Technologies Limited\r
+ 88-89 Blackfriars Rd\r
+ London South Bank SE1 8HA,\r
+ GB\r
+\r
44-6F-D8 (hex) Global Telecom Engineering, Inc\r
800000-8FFFFF (base 16) Global Telecom Engineering, Inc\r
17901 Von Karman Ave, Suite 600\r
Irvine CA 92614\r
US\r
\r
+74-F8-DB (hex) Avantree Corporation\r
+900000-9FFFFF (base 16) Avantree Corporation\r
+ 175 Bernal road Ste 106\r
+ SAN JOSE CA 95119-1343\r
+ US\r
+\r
+04-11-19 (hex) Shenzhen YIZHENG Technology Co.,Ltd\r
+800000-8FFFFF (base 16) Shenzhen YIZHENG Technology Co.,Ltd\r
+ 2305, block A7, Chuangzhi Yuncheng, Liuxian Avenue, Xili Town, Nanshan District\r
+ ShenZhen GuangDong 518000\r
+ CN\r
+\r
+04-11-19 (hex) Hubei Baobao Intelligent Technology Co.,LTD\r
+B00000-BFFFFF (base 16) Hubei Baobao Intelligent Technology Co.,LTD\r
+ Hubei Baobao Intelligent Technology Co.,LTD\r
+ Wuhan Hubei 430000\r
+ CN\r
+\r
+04-11-19 (hex) JULIDA LIMITED\r
+E00000-EFFFFF (base 16) JULIDA LIMITED\r
+ 1F., NO. 137, DATONG ST., BEITOU DIST.\r
+ TAIPEI CITY Taiwan 112\r
+ TW\r
+\r
+04-11-19 (hex) FORT Robotics Inc.\r
+000000-0FFFFF (base 16) FORT Robotics Inc.\r
+ 170 S. Independence Mall, Suite 275W\r
+ Philadelphia PA 19106\r
+ US\r
+\r
+E8-6C-C7 (hex) Shenzhen Rongda Computer Co.,Ltd\r
+500000-5FFFFF (base 16) Shenzhen Rongda Computer Co.,Ltd\r
+ 905, Block B, DuoCaiKeChuan Park, No.5 Guanle Road\r
+ Longhua District Shenzhen, Guangdong 518110\r
+ CN\r
+\r
+E8-6C-C7 (hex) Hangzhou Lanxum Security Technology Co., Ltd\r
+900000-9FFFFF (base 16) Hangzhou Lanxum Security Technology Co., Ltd\r
+ Room 402, Block A, 4th Floor, Building 3, No. 351 changhe Road, Changhe Street, Binjiang District\r
+ Hangzhou Zhejiang 310000\r
+ CN\r
+\r
+E8-6C-C7 (hex) KLAB\r
+600000-6FFFFF (base 16) KLAB\r
+ 94-23,Techno 2-ro\r
+ Yuseong-gu Daejeon 34014\r
+ KR\r
+\r
+24-5D-FC (hex) Senix Corporation\r
+C00000-CFFFFF (base 16) Senix Corporation\r
+ 10516 Route 116, Suite 300\r
+ Hinesburg VT 05461\r
+ US\r
+\r
+24-5D-FC (hex) Hunan Honestone lntelligence Technology Co.,Ltd\r
+D00000-DFFFFF (base 16) Hunan Honestone lntelligence Technology Co.,Ltd\r
+ 705, Building 1, Fortune Plaza, Wankuntu, Xiangzhang Road, Yuhua District, Changsha City,\r
+ Changsha 410007\r
+ CN\r
+\r
+24-5D-FC (hex) Dodge\r
+E00000-EFFFFF (base 16) Dodge\r
+ 6040 Ponders Court\r
+ Greenville SC 29615\r
+ US\r
+\r
+60-15-92 (hex) insensiv GmbH\r
+A00000-AFFFFF (base 16) insensiv GmbH\r
+ Auf dem Esch 28\r
+ Bielefeld Nordrhein-Westfalen 33619\r
+ DE\r
+\r
+00-55-DA (hex) Nanoleaf\r
+500000-5FFFFF (base 16) Nanoleaf\r
+ 100 Front Street East, 4th Floor\r
+ Toronto Ontario M5A 1E1\r
+ CA\r
+\r
+60-15-92 (hex) EDA Technology Co.,LTD\r
+200000-2FFFFF (base 16) EDA Technology Co.,LTD\r
+ Room 301, Building 24, Shengchuang Enterprise Park,No.1661 Jialuo Road, Jiading District\r
+ Shanghai Shanghai 201822\r
+ CN\r
+\r
+60-15-92 (hex) REMOWIRELESS COMMUNICATION INTERNATIONAL CO.,LIMITED\r
+D00000-DFFFFF (base 16) REMOWIRELESS COMMUNICATION INTERNATIONAL CO.,LIMITED\r
+ REMOWIRELESS RM1111,HONGYI BUILDING NO.2158 WANYUAN ROAD\r
+ SHANGHAI SHANGHAI 201103\r
+ CN\r
+\r
+0C-5C-B5 (hex) avxav Electronic Trading LLC\r
+100000-1FFFFF (base 16) avxav Electronic Trading LLC\r
+ Office 534 Building # 6WA Dubai Airport Free Zone\r
+ Dubai United Arab Emirates 33964\r
+ AE\r
+\r
+1C-A0-EF (hex) Sequent AG\r
+300000-3FFFFF (base 16) Sequent AG\r
+ Eptingerstrasse 3\r
+ Basel 4052\r
+ CH\r
+\r
+0C-5C-B5 (hex) Yamasei\r
+000000-0FFFFF (base 16) Yamasei\r
+ 2F., No. 37, Ln. 11, Sec. 6, Minquan E. Rd., Neihu Dist.\r
+ Taipei Taiwan (R.O.C.) 114\r
+ TW\r
+\r
+0C-5C-B5 (hex) HongKong Blossom Limited\r
+200000-2FFFFF (base 16) HongKong Blossom Limited\r
+ B1715,Jiansheng Building,No. 1 Pingji Road, NanWan Street Longgang\r
+ Shenzhen 518112\r
+ CN\r
+\r
+0C-5C-B5 (hex) Munters Europe AB\r
+E00000-EFFFFF (base 16) Munters Europe AB\r
+ Borgarfjordsgatan 16\r
+ Kista 16440\r
+ SE\r
+\r
+1C-A0-EF (hex) tec5AG\r
+700000-7FFFFF (base 16) tec5AG\r
+ Weisskirchener Strasse 2-6\r
+ Steinbach Hessen 61449\r
+ DE\r
+\r
20-85-93 (hex) Great Lite International\r
700000-7FFFFF (base 16) Great Lite International\r
11F., No.207-2, Sec. 3, Beixin Rd., Xindian Dist.,\r
Shenzhen 518100\r
CN\r
\r
-94-05-BB (hex) Neurik AG\r
-300000-3FFFFF (base 16) Neurik AG\r
- Im alten Riet 143\r
- Schaan SCHAAN 9494\r
- LI\r
-\r
DC-44-27 (hex) Tesla,Inc.\r
100000-1FFFFF (base 16) Tesla,Inc.\r
3500 Deer Creek Road\r
Nanjing Jiangsu 210012\r
CN\r
\r
+44-6F-D8 (hex) BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş.\r
+200000-2FFFFF (base 16) BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş.\r
+ Kimya Sanayicileri Org. San. Bolgesi Organik Cad. No:31\r
+ Istanbul Tuzla 34956\r
+ TR\r
+\r
44-6F-D8 (hex) ITC\r
700000-7FFFFF (base 16) ITC\r
3030 Corporate Grove Drive\r
Hudsonville MI 49426\r
US\r
+\r
+44-6F-D8 (hex) CTE\r
+E00000-EFFFFF (base 16) CTE\r
+ No. 1-7, Gongjian Rd., Cidu District, Keelung City 20647, Taiwan R.O.C\r
+ Keelung Taiwan 106\r
+ TW\r
+\r
+98-27-82 (hex) INFODAS GmbH\r
+100000-1FFFFF (base 16) INFODAS GmbH\r
+ Rhonestr. 2\r
+ Cologne 50765\r
+ DE\r
+\r
+98-27-82 (hex) Anhui Shengren Electronic Technology Co., Ltd\r
+200000-2FFFFF (base 16) Anhui Shengren Electronic Technology Co., Ltd\r
+ 520 Jiahe Road, Yuhui District\r
+ Bengbu Anhui 233000\r
+ CN\r
+\r
+98-27-82 (hex) SureFlap Ltd\r
+E00000-EFFFFF (base 16) SureFlap Ltd\r
+ 7 The Irwin Centre, Scotland Road, Dry Drayton\r
+ Cambridge Cambridgeshire CB23 8AR\r
+ GB\r
+\r
+98-27-82 (hex) KRISTECH Krzysztof Kajstura\r
+C00000-CFFFFF (base 16) KRISTECH Krzysztof Kajstura\r
+ Porzeczkowa 12\r
+ Ustro? Please select region, state or province 43-450\r
+ PL\r
+\r
+04-11-19 (hex) ZPD technology Co., Ltd\r
+600000-6FFFFF (base 16) ZPD technology Co., Ltd\r
+ 2# Floor, 1# Gate?12# Building?5# Jiangtai Road, Chaoyang District,Beijing\r
+ Beijing Beijing 100015\r
+ CN\r
+\r
+04-11-19 (hex) CEITA COMMUNICATION TECHNOLOGY CO.,LTD\r
+500000-5FFFFF (base 16) CEITA COMMUNICATION TECHNOLOGY CO.,LTD\r
+ 611, Renbao Building, 32 Baolong Road, Changlong Community, Buji Street, Longgang District\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+24-5D-FC (hex) Shenzhen Hailuck Electronic Technology CO.,LTD\r
+300000-3FFFFF (base 16) Shenzhen Hailuck Electronic Technology CO.,LTD\r
+ 2/F, building 19, Baotian industrial zone, the Third Baotian Road, Bao'an district\r
+ Shenzhen GuangDong 518101\r
+ CN\r
+\r
+04-11-19 (hex) Bolicom Innovation Technology (BeiJing) Co.,LTD.\r
+400000-4FFFFF (base 16) Bolicom Innovation Technology (BeiJing) Co.,LTD.\r
+ Rm2327, Building23, No.18 Anningzhuang East Road, Haidian District\r
+ Bei Jing 100000\r
+ CN\r
+\r
+04-11-19 (hex) Haerbin Donglin Technology Co., Ltd.\r
+C00000-CFFFFF (base 16) Haerbin Donglin Technology Co., Ltd.\r
+ Room 2, Floor 1, Unit 6, Building 2,Yuanshi Street 35, Nangang District\r
+ Haerbin Heilongjiang 150000\r
+ CN\r
+\r
+E8-6C-C7 (hex) MORNSUN Guangzhou Science & Technology Co., Ltd.\r
+B00000-BFFFFF (base 16) MORNSUN Guangzhou Science & Technology Co., Ltd.\r
+ No.5,Kehui St. 1,kehui Development Center,Science Ave.,Guangzhou Science City, Huangpu District\r
+ GuangZhou GuangDong 510000\r
+ CN\r
+\r
+E8-6C-C7 (hex) ASSA ABLOY(GuangZhou) Smart Technology Co., Ltd\r
+100000-1FFFFF (base 16) ASSA ABLOY(GuangZhou) Smart Technology Co., Ltd\r
+ Plant Building 5, 106 Xieshi Highway, Shibi 1st Village\r
+ Guangzhou GuangDong 511495\r
+ CN\r
+\r
+24-5D-FC (hex) ONLY\r
+B00000-BFFFFF (base 16) ONLY\r
+ 1F., No. 16, Ln. 76, Zhongyang N. Rd., Sanchong Dist\r
+ New Taipei City Taiwan (R.O.C.) 24146\r
+ TW\r
+\r
+24-5D-FC (hex) Tata Sky Limited\r
+A00000-AFFFFF (base 16) Tata Sky Limited\r
+ Unit 301 to 305, 3rd Floor, Windsor, Off C.S.T. Road, Kalina, Santacruz (East), Mumbai – 400 098 \r
+ Mumbai Maharashtra 400098\r
+ IN\r
+\r
+94-05-BB (hex) Neutrik AG\r
+300000-3FFFFF (base 16) Neutrik AG\r
+ Im alten Riet 143\r
+ Schaan SCHAAN 9494\r
+ LI\r
+\r
+60-15-92 (hex) Yangzhou Wanfang Electronic Technology,CO .,Ltd.\r
+800000-8FFFFF (base 16) Yangzhou Wanfang Electronic Technology,CO .,Ltd.\r
+ No.96 Anlin Road,Guangling District\r
+ Yangzhou City Jiangsu Province 225000\r
+ CN\r
+\r
+A4-53-EE (hex) Shenzhen Xunqi Interconnet Technology Co., Ltd\r
+600000-6FFFFF (base 16) Shenzhen Xunqi Interconnet Technology Co., Ltd\r
+ 26G, block B, Haiwang building, Chuangye Road, Nanshan District,\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+60-15-92 (hex) Faster CZ spol. s r.o.\r
+700000-7FFFFF (base 16) Faster CZ spol. s r.o.\r
+ Jarní 44g\r
+ Brno 61400\r
+ CZ\r
+\r
+60-15-92 (hex) BEIJING KUANGSHI TECHNOLOGY CO., LTD\r
+600000-6FFFFF (base 16) BEIJING KUANGSHI TECHNOLOGY CO., LTD\r
+ Room 1018,10th Floor, No.1 Zhongguancun Street, Haidian District, \r
+ Beijing Beijing 100086\r
+ CN\r
+\r
+0C-5C-B5 (hex) BSU Inc\r
+D00000-DFFFFF (base 16) BSU Inc\r
+ 1611 Headway Circle, Building 1, Suite 200\r
+ Austin TX 78754\r
+ US\r
+\r
+0C-5C-B5 (hex) Zhengzhou coal machinery hydraulic electric control Co.,Ltd\r
+A00000-AFFFFF (base 16) Zhengzhou coal machinery hydraulic electric control Co.,Ltd\r
+ 167 Jingkai 9th Street, Zhengzhou Economic Development Zone\r
+ Zhengzhou 45000\r
+ CN\r
+\r
+1C-A0-EF (hex) Nanjing Bilin Intelligent Identification Technology Co.,Ltd\r
+500000-5FFFFF (base 16) Nanjing Bilin Intelligent Identification Technology Co.,Ltd\r
+ No.9 Bancang Street\r
+ Nanjing Jiangsu 210000\r
+ CN\r
+\r
+1C-A0-EF (hex) Schneider-Electric(China)Co.Ltd,Shenzhen Branch\r
+200000-2FFFFF (base 16) Schneider-Electric(China)Co.Ltd,Shenzhen Branch\r
+ Unit A to C 7/F and 8/F,CES Building ,No.3099,Keyuan South road, Nanshan Dist, Shenzhen, GD, China\r
+ SHENZHEN 518000\r
+ CN\r
+\r
+1C-A0-EF (hex) BMK professional electronics GmbH\r
+B00000-BFFFFF (base 16) BMK professional electronics GmbH\r
+ Werner-von-Siemens-Straße 6\r
+ Augsburg 86159\r
+ DE\r
+\r
+1C-A0-EF (hex) Atlas Aerospace\r
+900000-9FFFFF (base 16) Atlas Aerospace\r
+ Ulbrokas 19a\r
+ Riga Riga LV-1021\r
+ LV\r
+\r
+1C-A0-EF (hex) Henrich Electronics Corporation\r
+A00000-AFFFFF (base 16) Henrich Electronics Corporation\r
+ 225 Deming Place\r
+ Westmont 60559\r
+ US\r
+\r
+1C-A0-EF (hex) RDA Microelectronics Technologies (Shanghai) Co. , Ltd\r
+E00000-EFFFFF (base 16) RDA Microelectronics Technologies (Shanghai) Co. , Ltd\r
+ Room 336, No.3, Lane 2288, Zuchongzhi Road, Pudong Area\r
+ Shanghai Shanghai 200120\r
+ CN\r
Barcelona Barcelona 08028\r
ES\r
\r
-70-B3-D5 (hex) Private\r
-A9F000-A9FFFF (base 16) Private\r
-\r
70-B3-D5 (hex) Arevita\r
5E1000-5E1FFF (base 16) Arevita\r
Baltu ave 145\r
New Taipei City, Taiwan 22101\r
TW\r
\r
-70-B3-D5 (hex) Private\r
-9EE000-9EEFFF (base 16) Private\r
-\r
70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd\r
70E000-70EFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd\r
NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China\r
Poellau bei Hartberg Steiermark 8225\r
AT\r
\r
-70-B3-D5 (hex) TORGOVYY DOM TEHNOLOGIY LLC\r
-7C0000-7C0FFF (base 16) TORGOVYY DOM TEHNOLOGIY LLC\r
- The village of Rumyantsevo, Build.1\r
- Moscow Moscow 142784\r
- RU\r
-\r
70-B3-D5 (hex) Raft Technologies\r
8D0000-8D0FFF (base 16) Raft Technologies\r
Habarzel 25\r
Mississauga Ontario L4V 1W1\r
CA\r
\r
-70-B3-D5 (hex) TAIYO SEIKI CO.,LTD.\r
-69B000-69BFFF (base 16) TAIYO SEIKI CO.,LTD.\r
- 1600 Aza-Shironoshita Asahi\r
- Shin Asahi-cho Takashima, Shiga 520-1501\r
- JP\r
-\r
70-B3-D5 (hex) PLUTO Solution co.,ltd.\r
842000-842FFF (base 16) PLUTO Solution co.,ltd.\r
B-1018, Kumkang Penterium IT Tower, 282, Hagui-ro, Dongan-gu\r
Plzen 301 28\r
CZ\r
\r
-70-B3-D5 (hex) S Labs sp. z o.o.\r
-C53000-C53FFF (base 16) S Labs sp. z o.o.\r
- Jasnogórska, 44\r
- Kraków Lesser Poland 31-358\r
- PL\r
-\r
70-B3-D5 (hex) Dameca a/s\r
EEA000-EEAFFF (base 16) Dameca a/s\r
Islevdalvej 211\r
Saint-Petersburg Russia 197183\r
RU\r
\r
-70-B3-D5 (hex) Leviathan Solutions Ltd.\r
-A69000-A69FFF (base 16) Leviathan Solutions Ltd.\r
- Kazal utca 64-66\r
- Budapest 1031\r
- HU\r
-\r
70-B3-D5 (hex) BEDEROV GmbH\r
371000-371FFF (base 16) BEDEROV GmbH\r
Rankestr. 8\r
TAIPEI 11560\r
TW\r
\r
-70-B3-D5 (hex) nexgenwave\r
-5BD000-5BDFFF (base 16) nexgenwave\r
- 1209 sicox tower, 484 Dunchon-daero, jungwon-gu\r
- Sungnam-si gyeonggi-do 13229\r
- KR\r
-\r
70-B3-D5 (hex) EBZ SysTec GmbH\r
1FA000-1FAFFF (base 16) EBZ SysTec GmbH\r
Bleicherstraße 7\r
Ravensburg DE 88212\r
DE\r
\r
+70-B3-D5 (hex) nexgenwave\r
+5BD000-5BDFFF (base 16) nexgenwave\r
+ 1209 sicox tower, 484 Dunchon-daero, jungwon-gu\r
+ Sungnam-si gyeonggi-do 13229\r
+ KR\r
+\r
70-B3-D5 (hex) TRIOPTICS\r
A11000-A11FFF (base 16) TRIOPTICS\r
Strandbaddamm 6\r
Wedel Schleswig-Holstein 22880\r
DE\r
\r
+70-B3-D5 (hex) Lockheed Martin - THAAD\r
+9EE000-9EEFFF (base 16) Lockheed Martin - THAAD\r
+ 4800 Bradford Drive\r
+ Huntsville AL 35805\r
+ US\r
+\r
+70-B3-D5 (hex) TT Group SRL\r
+BD7000-BD7FFF (base 16) TT Group SRL\r
+ Via Pazzano 112\r
+ Roma RM 00118\r
+ IT\r
+\r
+70-B3-D5 (hex) SIAME\r
+66E000-66EFFF (base 16) SIAME\r
+ RUE DES MATHEMATIQUES\r
+ GROMBALIA 8030\r
+ TN\r
+\r
+70-B3-D5 (hex) Stecomp\r
+EE0000-EE0FFF (base 16) Stecomp\r
+ Bollaarsdijk 11\r
+ Brielle 3231LA\r
+ NL\r
+\r
+70-B3-D5 (hex) Plenty Unlimited Inc\r
+D04000-D04FFF (base 16) Plenty Unlimited Inc\r
+ 590 Eccles Ave\r
+ South San Francisco CA 94080\r
+ US\r
+\r
+70-B3-D5 (hex) Aliter Technologies\r
+586000-586FFF (base 16) Aliter Technologies\r
+ Turcianska 16\r
+ Bratislava 82109\r
+ SK\r
+\r
+70-B3-D5 (hex) TORGOVYY DOM TEHNOLOGIY LLC\r
+7C0000-7C0FFF (base 16) TORGOVYY DOM TEHNOLOGIY LLC\r
+ Gospytalnaya 10, ap. 109, village Selyatino, city Naro-Fominsk,\r
+ Moscow Moscow Region 143345\r
+ RU\r
+\r
+70-B3-D5 (hex) Automata GmbH & Co. KG\r
+19D000-19DFFF (base 16) Automata GmbH & Co. KG\r
+ Gewerbering 5\r
+ Ried Bavaria 86510\r
+ DE\r
+\r
+70-B3-D5 (hex) XJ ELECTRIC CO., LTD.\r
+F26000-F26FFF (base 16) XJ ELECTRIC CO., LTD.\r
+ #1298 XUJI AVENUE\r
+ XUCHANG HENAN 461000\r
+ CN\r
+\r
+70-B3-D5 (hex) Topic Embedded Products B.V.\r
+63D000-63DFFF (base 16) Topic Embedded Products B.V.\r
+ Materiaalweg 4\r
+ Best Noord-Brabant 5681 RJ\r
+ NL\r
+\r
+70-B3-D5 (hex) EcoG\r
+1AE000-1AEFFF (base 16) EcoG\r
+ Gaenslerweg 24\r
+ Furth Bavaria 82041\r
+ DE\r
+\r
+70-B3-D5 (hex) Jiangsu Etern Compamy Limited\r
+DA0000-DA0FFF (base 16) Jiangsu Etern Compamy Limited\r
+ No. 1788 fenhu Guo Dao Road, Foho New&High-tech Industrial Development Zone, Wujiang\r
+ Suzhou Jiangsu 215211\r
+ CN\r
+\r
+70-B3-D5 (hex) JSC Ural Factories\r
+0FD000-0FDFFF (base 16) JSC Ural Factories\r
+ Gorky street 92\r
+ Izhevsk Udmurtia 426000\r
+ RU\r
+\r
+70-B3-D5 (hex) Semiconsoft, inc\r
+212000-212FFF (base 16) Semiconsoft, inc\r
+ 83 PINE HILL RD\r
+ SOUTHBOROUGH MA 01772\r
+ US\r
+\r
+70-B3-D5 (hex) M.S. CONTROL\r
+CE0000-CE0FFF (base 16) M.S. CONTROL\r
+ 139-141 Fitzgerald Street\r
+ WEST PERTH WA 6005\r
+ AU\r
+\r
+70-B3-D5 (hex) Hubbell Power Systems\r
+DDA000-DDAFFF (base 16) Hubbell Power Systems\r
+ 353 Powerville Road\r
+ Boonton Township NJ 07005\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+6D5000-6D5FFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Master Meter Inc.\r
+A9F000-A9FFFF (base 16) Master Meter Inc.\r
+ 101 Regency Pkwy\r
+ Mansfield TX 76063\r
+ US\r
+\r
+70-B3-D5 (hex) TIAMA\r
+798000-798FFF (base 16) TIAMA\r
+ ZA des Plattes - 1 Chemin des Plattes\r
+ VOURLES 69390 \r
+ FR\r
+\r
+70-B3-D5 (hex) Rapiot\r
+265000-265FFF (base 16) Rapiot\r
+ Eteläesplanadi 2\r
+ Helsinki 00130\r
+ FI\r
+\r
+70-B3-D5 (hex) OMNISENSING PHOTONICS LLC\r
+70D000-70DFFF (base 16) OMNISENSING PHOTONICS LLC\r
+ 8015 Four Quarter Road\r
+ Ellicott City MD 21043\r
+ US\r
+\r
+70-B3-D5 (hex) Torion Plasma Corporation\r
+B70000-B70FFF (base 16) Torion Plasma Corporation\r
+ 99 Hooper Rd, Unit #6\r
+ Barrie Ontario L4N9S3\r
+ CA\r
+\r
+70-B3-D5 (hex) Horizon Co., Ltd\r
+69B000-69BFFF (base 16) Horizon Co., Ltd\r
+ 1600 Aza-Shironoshita Asahi\r
+ Shin Asahi-cho Takashima, Shiga 520-1501\r
+ JP\r
+\r
+70-B3-D5 (hex) S Labs sp. z o.o.\r
+C53000-C53FFF (base 16) S Labs sp. z o.o.\r
+ Dworska 1a/1u\r
+ Kraków Lesser Poland 30-314\r
+ PL\r
+\r
+70-B3-D5 (hex) Smart Systems LLC\r
+746000-746FFF (base 16) Smart Systems LLC\r
+ Flat 1, building 7, Izmalkova street\r
+ Mykolaiv 54028\r
+ UA\r
+\r
+70-B3-D5 (hex) Megger Germany GmbH\r
+59F000-59FFFF (base 16) Megger Germany GmbH\r
+ Röderaue 41\r
+ Radeburg 01471\r
+ DE\r
+\r
+70-B3-D5 (hex) BluB0X Security, Inc.\r
+16D000-16DFFF (base 16) BluB0X Security, Inc.\r
+ 9 Bartlet Street Suite 334\r
+ Andover MA 01810\r
+ US\r
+\r
+70-B3-D5 (hex) Leviathan Solutions Ltd.\r
+A69000-A69FFF (base 16) Leviathan Solutions Ltd.\r
+ Abel Jeno utca 23\r
+ Budapest 1113\r
+ HU\r
+\r
+70-B3-D5 (hex) ACD Elekronik GmbH\r
+D6D000-D6DFFF (base 16) ACD Elekronik GmbH\r
+ Engelberg 2\r
+ Achstetten 88480\r
+ DE\r
+\r
+70-B3-D5 (hex) biosilver .co.,ltd\r
+D21000-D21FFF (base 16) biosilver .co.,ltd\r
+ 2-14-4, shinyokohama\r
+ yokohama kanagawa 2220033\r
+ JP\r
+\r
+70-B3-D5 (hex) Vemco Sp. z o. o.\r
+D45000-D45FFF (base 16) Vemco Sp. z o. o.\r
+ ul. Biala 1\r
+ Gdansk 80-435\r
+ PL\r
+\r
+70-B3-D5 (hex) Network Integrity Systems\r
+9FF000-9FFFFF (base 16) Network Integrity Systems\r
+ 1937 Tate Blvd. SE\r
+ Hickory NC 28602\r
+ US\r
+\r
70-B3-D5 (hex) EVCO SPA\r
A80000-A80FFF (base 16) EVCO SPA\r
VIA FELTRE N. 81\r
Arcugnano 36057\r
IT\r
\r
-70-B3-D5 (hex) Private\r
-720000-720FFF (base 16) Private\r
-\r
70-B3-D5 (hex) OnYield Inc Ltd\r
B74000-B74FFF (base 16) OnYield Inc Ltd\r
814 Houston Centre, 63 Mody Road\r
Shenzhen Guangdong 518054\r
CN\r
\r
-70-B3-D5 (hex) MiraeSignal Co., Ltd\r
-38C000-38CFFF (base 16) MiraeSignal Co., Ltd\r
- #203 E-dong Bundang Techno Park Yatapdong\r
- Sungnam Kyungkido 463760\r
- KR\r
-\r
70-B3-D5 (hex) Stara S/A Indústria de Implementos Agrícolas\r
13E000-13EFFF (base 16) Stara S/A Indústria de Implementos Agrícolas\r
Avenida Stara 519\r
Endicott NY 13760\r
US\r
\r
-70-B3-D5 (hex) DAYOUPLUS\r
-474000-474FFF (base 16) DAYOUPLUS\r
- 3F 509, Dunchon-daero, Jungwon-gu, Seongnam-si, Gyeonggi-do, Republic of Korea\r
- Seongnam-si Gyeonggi-do 13217\r
- KR\r
-\r
70-B3-D5 (hex) Guangzhou Xianhe Technology Engineering Co., Ltd\r
C13000-C13FFF (base 16) Guangzhou Xianhe Technology Engineering Co., Ltd\r
No. 30-6, Jiantai Road, Dongyong Town, Nansha District\r
Warsaw 02-486\r
PL\r
\r
+70-B3-D5 (hex) WIZAPPLY CO.,LTD\r
+8D2000-8D2FFF (base 16) WIZAPPLY CO.,LTD\r
+ 1-3-13-5107, Benten\r
+ Osaka-shi, Minato-ku Osaka-fu 552-0007\r
+ JP\r
+\r
+70-B3-D5 (hex) AmericanPharma Technologies\r
+B4C000-B4CFFF (base 16) AmericanPharma Technologies\r
+ 222 N 13th Street Suite 200\r
+ Boise ID 83702\r
+ US\r
+\r
70-B3-D5 (hex) ALFI\r
B0D000-B0DFFF (base 16) ALFI\r
Via Castelletto 20\r
Borgo Ticino NO 28040\r
IT\r
\r
-70-B3-D5 (hex) WIZAPPLY CO.,LTD\r
-8D2000-8D2FFF (base 16) WIZAPPLY CO.,LTD\r
- 1-3-13-5107, Benten\r
- Osaka-shi, Minato-ku Osaka-fu 552-0007\r
+70-B3-D5 (hex) Medipense Inc.\r
+72B000-72BFFF (base 16) Medipense Inc.\r
+ 9145 rue Boivin\r
+ Montreal Quebec H8R 2E5\r
+ CA\r
+\r
+70-B3-D5 (hex) MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD.\r
+7CC000-7CCFFF (base 16) MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD.\r
+ 3-1, Asahi, Nishibiwajima-Cho\r
+ Kiyosu Aichi 452-8561\r
JP\r
\r
+70-B3-D5 (hex) The-Box Development\r
+F31000-F31FFF (base 16) The-Box Development\r
+ D.D. Eisenhowerstraat 74\r
+ Groningen Groningen 9728 RX\r
+ NL\r
+\r
+70-B3-D5 (hex) MAS Elettronica sas di Mascetti Sandro e C.\r
+4FB000-4FBFFF (base 16) MAS Elettronica sas di Mascetti Sandro e C.\r
+ Via Risorgimento 16/C\r
+ Selvazzano Dentro Padova 35030\r
+ IT\r
+\r
+70-B3-D5 (hex) DHK Storage, LLC\r
+915000-915FFF (base 16) DHK Storage, LLC\r
+ 13873 Park Center Rd, Ste 510N\r
+ Herndon VA 20171\r
+ US\r
+\r
+70-B3-D5 (hex) Shenzhen Zhiting Technology Co.,Ltd\r
+FE1000-FE1FFF (base 16) Shenzhen Zhiting Technology Co.,Ltd\r
+ Room 516, Building 4, Qidi Xiexin science and Technology Park, Longcheng Street\r
+ Shenzhen Guangdong 518109\r
+ CN\r
+\r
+70-B3-D5 (hex) MiraeSignal Co., Ltd\r
+38C000-38CFFF (base 16) MiraeSignal Co., Ltd\r
+ #701,C-dong Bundang Techno Park Pangyoro 744\r
+ Bundang-gu Sungnam-si Kyungkido 13510\r
+ KR\r
+\r
+70-B3-D5 (hex) on-systems limited\r
+5B7000-5B7FFF (base 16) on-systems limited\r
+ 615A Jubilee Road\r
+ Letchworth Garden City Hertfordshire SG6 1NE\r
+ GB\r
+\r
+70-B3-D5 (hex) Blueprint Lab\r
+FE0000-FE0FFF (base 16) Blueprint Lab\r
+ 3-5 Queen St\r
+ Glebe NSW 2037\r
+ AU\r
+\r
+70-B3-D5 (hex) LEIDOS\r
+004000-004FFF (base 16) LEIDOS\r
+ 1121 W Reeves\r
+ Ridgecrest CA 93555\r
+ US\r
+\r
+70-B3-D5 (hex) Avionica \r
+CC0000-CC0FFF (base 16) Avionica \r
+ 9941 West Jessamine St\r
+ Miami FL 33157 \r
+ US\r
+\r
+70-B3-D5 (hex) Swiss Timing LTD\r
+725000-725FFF (base 16) Swiss Timing LTD\r
+ Rue de l'Envers 1\r
+ Corgemont 2606\r
+ CH\r
+\r
+70-B3-D5 (hex) RoyalShield Technologies India Private Limited\r
+F1B000-F1BFFF (base 16) RoyalShield Technologies India Private Limited\r
+ B-116, DDA Sheds, Okhla Industrial Area, Okhla Phase -I\r
+ New Delhi New Delhi 110020\r
+ IN\r
+\r
+70-B3-D5 (hex) Nudron IoT Solutions LLP\r
+6B4000-6B4FFF (base 16) Nudron IoT Solutions LLP\r
+ 10, Gitaneel Arcade, Hill Road, Bandra-W\r
+ Mumbai Maharashtra 400050\r
+ IN\r
+\r
+70-B3-D5 (hex) DORLET SAU\r
+DEB000-DEBFFF (base 16) DORLET SAU\r
+ Albert Eistein 34\r
+ Alava SPAIN 01510\r
+ ES\r
+\r
+70-B3-D5 (hex) Dadacon GmbH\r
+B79000-B79FFF (base 16) Dadacon GmbH\r
+ Hammarskjoeldring 75F\r
+ Frankfurt am Main Hessen 60439\r
+ DE\r
+\r
+70-B3-D5 (hex) XIA LLC\r
+3DC000-3DCFFF (base 16) XIA LLC\r
+ 31057 Genstar Road\r
+ HAYWARD CA 94544\r
+ US\r
+\r
+70-B3-D5 (hex) BAB TECHNOLOGIE GmbH\r
+E19000-E19FFF (base 16) BAB TECHNOLOGIE GmbH\r
+ Hoerder Burgstr.18\r
+ Dortmund NRW 44263\r
+ DE\r
+\r
+70-B3-D5 (hex) Schneider Electric Motion USA\r
+2E4000-2E4FFF (base 16) Schneider Electric Motion USA\r
+ 370 N. Main St.\r
+ Marlborough CT 06447\r
+ US\r
+\r
+70-B3-D5 (hex) Nordson Corporation\r
+50B000-50BFFF (base 16) Nordson Corporation\r
+ 11475 Lakefield Dr\r
+ Duluth GA 30097\r
+ US\r
+\r
+70-B3-D5 (hex) Done Design Inc\r
+928000-928FFF (base 16) Done Design Inc\r
+ 930 Delray Drive\r
+ Forest Hill MD 21050\r
+ US\r
+\r
+70-B3-D5 (hex) Jeio Tech \r
+720000-720FFF (base 16) Jeio Tech \r
+ 19 Alexander Road, Suite 7\r
+ Billerica MA 01821\r
+ US\r
+\r
+70-B3-D5 (hex) TESCAN Brno, s.r.o.\r
+812000-812FFF (base 16) TESCAN Brno, s.r.o.\r
+ Libusina tr.1\r
+ Brno 62300\r
+ CZ\r
+\r
70-B3-D5 (hex) System West dba ICS Electronics\r
E06000-E06FFF (base 16) System West dba ICS Electronics\r
7034 Commerce Circle Suite A\r
Seven Hills NSW 1730\r
AU\r
\r
+70-B3-D5 (hex) AKASAKATEC INC.\r
+D83000-D83FFF (base 16) AKASAKATEC INC.\r
+ 3F Marina Plaza 4-2\r
+ Shiraho kanazawa-ku Yokohamashi 2360007\r
+ JP\r
+\r
+70-B3-D5 (hex) VTEQ\r
+B12000-B12FFF (base 16) VTEQ\r
+ Conca de Barbera\r
+ Castellar del Vallés Barcelona / Spain 08122\r
+ ES\r
+\r
+70-B3-D5 (hex) promedias AG\r
+520000-520FFF (base 16) promedias AG\r
+ Grabenackerstrasse 27\r
+ Oberhasli ZH CH-8156\r
+ CH\r
+\r
00-1B-C5 (hex) OctoGate IT Security Systems GmbH\r
030000-030FFF (base 16) OctoGate IT Security Systems GmbH\r
Klingender Strasse 5\r
Paderborn NRW 33100\r
DE\r
\r
+70-B3-D5 (hex) Array Technologies Inc.\r
+FB4000-FB4FFF (base 16) Array Technologies Inc.\r
+ 21 Sequin Drive\r
+ Glastonbury 06033\r
+ US\r
+\r
+70-B3-D5 (hex) REO AG\r
+AD0000-AD0FFF (base 16) REO AG\r
+ Brühlerstr. 100\r
+ Solingen 42657\r
+ DE\r
+\r
+70-B3-D5 (hex) ejoin, s.r.o.\r
+44C000-44CFFF (base 16) ejoin, s.r.o.\r
+ Sturova 1\r
+ Dubnica nad Vahom 01841\r
+ SK\r
+\r
+70-B3-D5 (hex) TEX COMPUTER SRL \r
+390000-390FFF (base 16) TEX COMPUTER SRL \r
+ VIA MERCADANTE 35\r
+ CATTOLICA RIMINI 47841\r
+ IT\r
+\r
+70-B3-D5 (hex) Grau Elektronik GmbH\r
+314000-314FFF (base 16) Grau Elektronik GmbH\r
+ Badhausweg 14\r
+ Karlsbad Ittersbach Baden-Württemberg 76307\r
+ DE\r
+\r
+70-B3-D5 (hex) microWerk GmbH\r
+D2C000-D2CFFF (base 16) microWerk GmbH\r
+ Kaffeegasse, 7\r
+ Halsenbach 56283\r
+ DE\r
+\r
+70-B3-D5 (hex) Guan Show Technologe Co., Ltd.\r
+46D000-46DFFF (base 16) Guan Show Technologe Co., Ltd.\r
+ No.127, Jianguo 1st Rd., Lingya Dist.\r
+ Kaohsiung City 802\r
+ TW\r
+\r
+70-B3-D5 (hex) Foxtrot Research Corp\r
+604000-604FFF (base 16) Foxtrot Research Corp\r
+ 6201 Johns Road, Suite 3\r
+ Tampa FL 33634\r
+ US\r
+\r
+70-B3-D5 (hex) Monnit Corporation\r
+A1E000-A1EFFF (base 16) Monnit Corporation\r
+ 450 South Simmons STE 670\r
+ Kaysville UT 84037\r
+ US\r
+\r
+70-B3-D5 (hex) DEUTA-WERKE GmbH\r
+681000-681FFF (base 16) DEUTA-WERKE GmbH\r
+ Paffrather Str. 140\r
+ Bergisch Gladbach North Rhine-Westphalia 51465\r
+ DE\r
+\r
+70-B3-D5 (hex) Movicom Electric LLC\r
+3B3000-3B3FFF (base 16) Movicom Electric LLC\r
+ Nauchny proezd, 20\r
+ Moscow Moscow 117246\r
+ RU\r
+\r
+70-B3-D5 (hex) SMITEC S.p.A.\r
+312000-312FFF (base 16) SMITEC S.p.A.\r
+ Via Carlo Ceresa, 10\r
+ San Giovanni Bianco Bergamo 24015\r
+ IT\r
+\r
+70-B3-D5 (hex) Sicon srl\r
+690000-690FFF (base 16) Sicon srl\r
+ Via Sila 1/3\r
+ Isola Vicentina Vicenza 36033\r
+ IT\r
+\r
+70-B3-D5 (hex) SCHEIBER\r
+CFA000-CFAFFF (base 16) SCHEIBER\r
+ 2 BELLEVUE\r
+ SAINT PIERRE DU CHEMIN 85120\r
+ FR\r
+\r
+70-B3-D5 (hex) Telerob Gesellschaft für Fernhantierungs\r
+6D4000-6D4FFF (base 16) Telerob Gesellschaft für Fernhantierungs\r
+ Vogelsangstr. 8\r
+ Ostfildern 73760\r
+ DE\r
+\r
70-B3-D5 (hex) YUYAMA MFG Co.,Ltd\r
BBB000-BBBFFF (base 16) YUYAMA MFG Co.,Ltd\r
3-3-1\r
Petah Tikva Israel 49000\r
IL\r
\r
-70-B3-D5 (hex) Private\r
-F7C000-F7CFFF (base 16) Private\r
-\r
70-B3-D5 (hex) boekel\r
AF8000-AF8FFF (base 16) boekel\r
855 pennsylvania blvd\r
HONGKONG 999077\r
HK\r
\r
-70-B3-D5 (hex) Shenzhen Rongda Computer Co.,Ltd\r
-289000-289FFF (base 16) Shenzhen Rongda Computer Co.,Ltd\r
- Room A616, Aoshida Building, Zhongkang Road, Futian District\r
- Shenzhen Guangdong 518049\r
- CN\r
-\r
70-B3-D5 (hex) FIBERNET LTD\r
041000-041FFF (base 16) FIBERNET LTD\r
9 Hakidma st. Hi-Tech City Park,\r
Dinkelsbuehl Bavaria 91550\r
DE\r
\r
+70-B3-D5 (hex) Akse srl\r
+128000-128FFF (base 16) Akse srl\r
+ Via Aldo Moro, 39\r
+ Reggio Emilia Italy 42124\r
+ IT\r
+\r
+70-B3-D5 (hex) AXING AG\r
+CA6000-CA6FFF (base 16) AXING AG\r
+ Gewerbehaus Moskau\r
+ Ramsen 8262\r
+ CH\r
+\r
+70-B3-D5 (hex) LLC NTZ Mekhanotronika\r
+6C0000-6C0FFF (base 16) LLC NTZ Mekhanotronika\r
+ Pionerstroya, build 23a\r
+ Saint-Petersburg 198206\r
+ RU\r
+\r
+70-B3-D5 (hex) NAL Research Corporation\r
+1B0000-1B0FFF (base 16) NAL Research Corporation\r
+ 11100 Endeavor Ct, Suite 300\r
+ Manassas VA 20109\r
+ US\r
+\r
+70-B3-D5 (hex) Arwin Technology Limited\r
+8C9000-8C9FFF (base 16) Arwin Technology Limited\r
+ Unit 215, 2/F, 19W, 19 Science Park West Avenue\r
+ Hong Kong 0\r
+ HK\r
+\r
+70-B3-D5 (hex) PNETWORKS\r
+EF0000-EF0FFF (base 16) PNETWORKS\r
+ TEKNOPARK Bul. 1/1A No: 201 Pendik ?stanbul\r
+ Istanbul 34906\r
+ TR\r
+\r
+70-B3-D5 (hex) Herholdt Controls srl\r
+C6B000-C6BFFF (base 16) Herholdt Controls srl\r
+ Via Mestre 13\r
+ Milan 20132\r
+ IT\r
+\r
+70-B3-D5 (hex) Atlas Lighting Products\r
+CB5000-CB5FFF (base 16) Atlas Lighting Products\r
+ 1406 S Mebane St\r
+ Burlington 27215\r
+ US\r
+\r
+70-B3-D5 (hex) Weble Sàrl\r
+96C000-96CFFF (base 16) Weble Sàrl\r
+ Rue du Jura 12\r
+ Bussigny Vaud 1030\r
+ CH\r
+\r
+70-B3-D5 (hex) Grossenbacher Systeme AG\r
+CE8000-CE8FFF (base 16) Grossenbacher Systeme AG\r
+ Spinnereistrasse 10\r
+ St. Gallen 9008\r
+ CH\r
+\r
+70-B3-D5 (hex) G.S.D GROUP INC.\r
+B01000-B01FFF (base 16) G.S.D GROUP INC.\r
+ 2010 RUE MICHELIN, SUITE 100\r
+ LAVAL Quebec H7L 5C2\r
+ CA\r
+\r
+70-B3-D5 (hex) DIC Corporation\r
+5C3000-5C3FFF (base 16) DIC Corporation\r
+ DIC Building,7-20,Nihonbashi 3-chome\r
+ Chuo-ku,Tokyo 103-8233\r
+ JP\r
+\r
+70-B3-D5 (hex) Medicomp, Inc\r
+F7C000-F7CFFF (base 16) Medicomp, Inc\r
+ 600 Atlantis Rd\r
+ Melbourne FL 32904\r
+ US\r
+\r
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd\r
+CAD000-CADFFF (base 16) YUYAMA MFG Co.,Ltd\r
+ 3-3-1\r
+ TOYONAKASHI OSAKA 561-0841\r
+ JP\r
+\r
+70-B3-D5 (hex) Shenzhen Rongda Computer Co.,Ltd\r
+289000-289FFF (base 16) Shenzhen Rongda Computer Co.,Ltd\r
+ 905, Block B, DuoCaiKeChuan Park, No.5 Guanle Road\r
+ Longhua District Shenzhen, Guangdong 518110\r
+ CN\r
+\r
+70-B3-D5 (hex) Sono-Tek Corporation\r
+5C2000-5C2FFF (base 16) Sono-Tek Corporation\r
+ 2012 Rte. 9W Bldg 3\r
+ Milton NY 12547\r
+ US\r
+\r
+70-B3-D5 (hex) Breas Medical AB\r
+CF9000-CF9FFF (base 16) Breas Medical AB\r
+ Företagsvägen 1\r
+ Mölnlycke SE-435 33\r
+ SE\r
+\r
+70-B3-D5 (hex) Davitor AB\r
+E60000-E60FFF (base 16) Davitor AB\r
+ Skordarevagen 5\r
+ Kalmar 39353\r
+ SE\r
+\r
+70-B3-D5 (hex) Coloet S.r.l.\r
+713000-713FFF (base 16) Coloet S.r.l.\r
+ Via Mascheroni, 20\r
+ MILANO Italy 20145\r
+ IT\r
+\r
+70-B3-D5 (hex) meoENERGY\r
+7FA000-7FAFFF (base 16) meoENERGY\r
+ Glacisstraße 9/1\r
+ Graz 8010\r
+ AT\r
+\r
+70-B3-D5 (hex) European Synchrotron Radiation Facility\r
+160000-160FFF (base 16) European Synchrotron Radiation Facility\r
+ 71, avenue des Martyrs\r
+ Grenoble Isère 38000\r
+ FR\r
+\r
+70-B3-D5 (hex) Radian Research, Inc.\r
+9BC000-9BCFFF (base 16) Radian Research, Inc.\r
+ 3852 Fortune Drive\r
+ Lafayette IN 47905\r
+ US\r
+\r
+70-B3-D5 (hex) VERTEL DIGITAL PRIVATE LIMITED\r
+912000-912FFF (base 16) VERTEL DIGITAL PRIVATE LIMITED\r
+ C-98, SECTOR-10 \r
+ NOIDA Uttar Pradesh 201301\r
+ IN\r
+\r
+70-B3-D5 (hex) ITALIANA PONTI RADIO SRL\r
+452000-452FFF (base 16) ITALIANA PONTI RADIO SRL\r
+ VIA CA' BASSA 67\r
+ VARESE VARESE 21100\r
+ IT\r
+\r
+70-B3-D5 (hex) Stuyts Engineering Haarlem BV\r
+D1D000-D1DFFF (base 16) Stuyts Engineering Haarlem BV\r
+ Hogeweg 40\r
+ Zandvoort Noord-Holland 2042GH\r
+ NL\r
+\r
+70-B3-D5 (hex) sonatest\r
+8FD000-8FDFFF (base 16) sonatest\r
+ 1175 Rue Lavigerie, Bur.90\r
+ Quebec Quebec G1V 4P1\r
+ CA\r
+\r
+70-B3-D5 (hex) IDZ Ltd\r
+7F6000-7F6FFF (base 16) IDZ Ltd\r
+ 160 CITY ROAD\r
+ LONDON Select One... EC1V 2NX\r
+ GB\r
+\r
70-B3-D5 (hex) DISMUNTEL SAL\r
92C000-92CFFF (base 16) DISMUNTEL SAL\r
Pol ind cotes\r
Taipei Taiwan 11070\r
TW\r
\r
-70-B3-D5 (hex) Private\r
-278000-278FFF (base 16) Private\r
-\r
70-B3-D5 (hex) Arrowvale Electronics\r
B07000-B07FFF (base 16) Arrowvale Electronics\r
Shawbank Road\r
East Pittsburgh PA 15112-1242\r
US\r
\r
-70-B3-D5 (hex) PoolDigital GmbH & Co. KG\r
-063000-063FFF (base 16) PoolDigital GmbH & Co. KG\r
- Kaffeegasse, 7\r
- Halsenbach 56283\r
- DE\r
-\r
70-B3-D5 (hex) HORIBA ABX SAS\r
AB8000-AB8FFF (base 16) HORIBA ABX SAS\r
rue du caducee\r
40-42 Rue Du Docteur Finlay\r
PARIS CEDEX 15 75732\r
FR\r
+\r
+70-B3-D5 (hex) Shanghai Armour Technology Co., Ltd.\r
+8E5000-8E5FFF (base 16) Shanghai Armour Technology Co., Ltd.\r
+ Room 411, building 10, 471 Guiping Road, Xuhui District\r
+ Shanghai Shanghai 200233\r
+ CN\r
+\r
+70-B3-D5 (hex) Hangzhou Weimu Technology Co.,Ltd.\r
+373000-373FFF (base 16) Hangzhou Weimu Technology Co.,Ltd.\r
+ 3 / f, building 1, yongle village, cangqian street, yuhang district\r
+ Hangzhou Zhejiang 310000\r
+ CN\r
+\r
+70-B3-D5 (hex) Coda Octopus Products Limited\r
+4D9000-4D9FFF (base 16) Coda Octopus Products Limited\r
+ 38 S. Gyle Crescent, South Gyle Business Park\r
+ Edinburgh Scotland EH12 9EB\r
+ GB\r
+\r
+70-B3-D5 (hex) Xirgo Technologies LLC\r
+CA0000-CA0FFF (base 16) Xirgo Technologies LLC\r
+ 188 Camino Ruiz\r
+ Camarillo CA 93012\r
+ US\r
+\r
+70-B3-D5 (hex) Xirgo Technologies LLC\r
+CEB000-CEBFFF (base 16) Xirgo Technologies LLC\r
+ 188 Camino Ruiz\r
+ Camarillo CA 93012\r
+ US\r
+\r
+70-B3-D5 (hex) GreenFlux\r
+A02000-A02FFF (base 16) GreenFlux\r
+ Mauritskade 63\r
+ Amsterdam 1092 AD\r
+ NL\r
+\r
+70-B3-D5 (hex) Iylus Inc.\r
+02C000-02CFFF (base 16) Iylus Inc.\r
+ 3100 Clarendon Blvd., Suite 200\r
+ Arlington VA 22201\r
+ US\r
+\r
+70-B3-D5 (hex) Walter Müller AG\r
+0E4000-0E4FFF (base 16) Walter Müller AG\r
+ Russikerstrasse 37\r
+ Fehraltorf Zürich 8320\r
+ CH\r
+\r
+70-B3-D5 (hex) COONTROL Tecnologia em Combustão LTDA EPP\r
+8E9000-8E9FFF (base 16) COONTROL Tecnologia em Combustão LTDA EPP\r
+ RUA ABRAHAN LINCOLS, 464, Jardim América\r
+ RIO DO SUL SANTA CATARINA 89160202\r
+ BR\r
+\r
+70-B3-D5 (hex) Private\r
+278000-278FFF (base 16) Private\r
+ 600 Atlantis Rd\r
+ Melbourne FL 32904\r
+ US\r
+\r
+70-B3-D5 (hex) Sensoronic Co.,Ltd\r
+D52000-D52FFF (base 16) Sensoronic Co.,Ltd\r
+ 1311ho, sambo techno tower, Jomaru-ro 385beongil,\r
+ Bucheon-si Gyeonggi-do 14556\r
+ KR\r
+\r
+70-B3-D5 (hex) Neusoft Reach Automotive Technology (Shenyang) Co.,Ltd\r
+E42000-E42FFF (base 16) Neusoft Reach Automotive Technology (Shenyang) Co.,Ltd\r
+ No.2 Xinxiu Street, Hunnan District, Shenyang\r
+ Shenyang Liaoning 110000\r
+ CN\r
+\r
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd\r
+196000-196FFF (base 16) YUYAMA MFG Co.,Ltd\r
+ 1-4-30\r
+ MEISHINGUCHI,TOYONAKA OSAKA 561-0841\r
+ JP\r
+\r
+70-B3-D5 (hex) Guan Show Technologe Co., Ltd.\r
+829000-829FFF (base 16) Guan Show Technologe Co., Ltd.\r
+ No.127, Jianguo 1st Rd., Lingya Dist.\r
+ Kaohsiung City 802\r
+ TW\r
+\r
+70-B3-D5 (hex) Thermokon Sensortechnik GmbH\r
+581000-581FFF (base 16) Thermokon Sensortechnik GmbH\r
+ Platanenweg 1\r
+ Mittenaar Hessen 35756\r
+ DE\r
+\r
+70-B3-D5 (hex) PoolDigital GmbH & Co. KG\r
+063000-063FFF (base 16) PoolDigital GmbH & Co. KG\r
+ Gablinger Weg 102\r
+ Augsburg 86156\r
+ DE\r
+\r
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme\r
+71A000-71AFFF (base 16) MB connect line GmbH Fernwartungssysteme\r
+ Winnettener Straße 6\r
+ Dinkelsbuehl Bavaria 91550\r
+ DE\r
+\r
+70-B3-D5 (hex) Loma Systems s.r.o.\r
+BC8000-BC8FFF (base 16) Loma Systems s.r.o.\r
+ Southwood\r
+ Farnborough Hampshire GU14 0NY\r
+ GB\r
+\r
+70-B3-D5 (hex) MECT SRL\r
+2C5000-2C5FFF (base 16) MECT SRL\r
+ VIA E. FERMI 57/59\r
+ ALPIGNANO string:TO 10091\r
+ IT\r
+\r
+70-B3-D5 (hex) CTROGERS LLC\r
+474000-474FFF (base 16) CTROGERS LLC\r
+ 815 1st Ave #174\r
+ Seattle WA 98104\r
+ US\r
+\r
+70-B3-D5 (hex) EIZO RUGGED SOLUTIONS\r
+5B9000-5B9FFF (base 16) EIZO RUGGED SOLUTIONS\r
+ 442 Northlake Blvd Suite 1008\r
+ Altamonte Springs FL 32701\r
+ US\r
+\r
+70-B3-D5 (hex) ISG Nordic AB\r
+DEF000-DEFFFF (base 16) ISG Nordic AB\r
+ Energigatan 9\r
+ KUNGSBACKA Select State SE-43437\r
+ SE\r
+\r
+70-B3-D5 (hex) PARAGON ID\r
+036000-036FFF (base 16) PARAGON ID\r
+ Les Aubépins\r
+ ARGENT SUR SAULDRE CHER 18410\r
+ FR\r
hwdb_files_test = files('''
60-autosuspend.hwdb
+ 60-autosuspend-fingerprint-reader.hwdb
60-evdev.hwdb
60-input-id.hwdb
60-keyboard.hwdb
############################################################
run_target(
- 'hwdb-update',
- command : [hwdb_update_sh, meson.current_source_dir()])
+ 'update-hwdb',
+ command : [update_hwdb_sh, meson.current_source_dir()])
run_target(
- 'autosuspend-update',
- command : [autosuspend_update_sh, project_source_root + '/tools/chromiumos'])
+ 'update-hwdb-autosuspend',
+ command : [update_hwdb_autosuspend_sh, project_source_root])
'KBD_LCD_MENU' in key):
error('Keycode {} unknown', key)
+def check_wheel_clicks(properties):
+ pairs = (('MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL', 'MOUSE_WHEEL_CLICK_COUNT'),
+ ('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', 'MOUSE_WHEEL_CLICK_ANGLE'),
+ ('MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL', 'MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL'),
+ ('MOUSE_WHEEL_CLICK_COUNT', 'MOUSE_WHEEL_CLICK_ANGLE'))
+ for pair in pairs:
+ if pair[0] in properties and pair[1] not in properties:
+ error('{} requires {} to be specified', *pair)
+
def check_properties(groups):
grammar = property_grammar()
for matches, props in groups:
- prop_names = set()
+ seen_props = {}
for prop in props:
# print('--', prop)
prop = prop.partition('#')[0].rstrip()
error('Failed to parse: {!r}', prop)
continue
# print('{!r}'.format(parsed))
- if parsed.NAME in prop_names:
+ if parsed.NAME in seen_props:
error('Property {} is duplicated', parsed.NAME)
- prop_names.add(parsed.NAME)
+ seen_props[parsed.NAME] = parsed.VALUE
if parsed.NAME == 'MOUSE_DPI':
check_one_default(prop, parsed.VALUE.SETTINGS)
elif parsed.NAME == 'ACCEL_MOUNT_MATRIX':
val = parsed.VALUE if isinstance(parsed.VALUE, str) else parsed.VALUE[0]
check_one_keycode(prop, val)
+ check_wheel_clicks(seen_props)
+
def print_summary(fname, groups):
n_matches = sum(len(matches) for matches, props in groups)
n_props = sum(len(props) for matches, props in groups)
#
# List of PCI ID's
#
-# Version: 2020.11.14
-# Date: 2020-11-14 03:15:02
+# Version: 2021.02.12
+# Date: 2021-02-12 03:15:01
#
# Maintained by Albert Pool, Martin Mares, and other volunteers from
# the PCI ID Project at https://pci-ids.ucw.cz/.
1d49 0200 ThinkSystem 430-8i SAS/SATA 12Gb HBA
1d49 0202 ThinkSystem 430-8e SAS/SATA 12Gb HBA
1d49 0204 ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA
-# PCIe switch SES management endpoint
- 00b2 PEX880xx PCIe Gen 4 Switch SES management endpoint
+ 00b2 PCIe Switch management endpoint
+ 1d49 0003 ThinkSystem 1611-8P PCIe Gen4 NVMe Switch Adapter
00be SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC)
00bf SAS3404 Fusion-MPT Tri-Mode I/O Controller Chip (IOC)
00c0 SAS3324 PCI-Express Fusion-MPT SAS-3
8086 0523 MegaRAID RAID Controller SRCS16
3050 SAS2008 PCI-Express Fusion-MPT SAS-2
6001 DX1 Multiformat Broadcast HD/SD Encoder/Decoder
+ c012 PEX880xx PCIe Gen 4 Switch
+ 1d49 0003 ThinkSystem 1611-8P PCIe Gen4 NVMe Switch Adapter
1001 Kolter Electronic
0010 PCI 1616 Measurement card with 32 digital I/O lines
0011 OPTO-PCI Opto-Isolated digital I/O board
1478 Navi 10 XL Upstream Port of PCI Express Switch
1479 Navi 10 XL Downstream Port of PCI Express Switch
154c Kryptos [Radeon RX 350]
+ 1462 7c28 MS-7C28 Motherboard
154e Garfield
1551 Arlene
1552 Pooky
15d8 Picasso
103c 8615 Pavilion Laptop 15-cw1xxx
17aa 5124 ThinkPad E595
+ ea50 cc10 RXi2-BP
15dd Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series]
103c 83c6 Radeon Vega 8 Mobile
+ 1043 876b PRIME Motherboard
1458 d000 Radeon RX Vega 11
+ ea50 cc10 RXi2-BP
15de Raven/Raven2/Fenghuang HDMI/DP Audio Controller
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME B450M-A Motherboard
17aa 5124 ThinkPad E595
+ ea50 cc10 RXi2-BP
15df Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor
103c 8615 Pavilion Laptop 15-cw1xxx
+ ea50 ce19 mCOM10-L1900
15ff Fenghuang [Zhongshan Subor Z+]
1607 Arden
1636 Renoir
+ 1638 Cezanne
+ 163f VanGogh
+ 164c Lucienne
1714 BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series]
103c 168b ProBook 4535s
3150 RV380/M24 [Mobility Radeon X600]
1179 ff50 Satellite P305D-S8995E
1458 a022 GA-MA770-DS3rev2.0 Motherboard
1458 a102 GA-880GMA-USB3
+ 1462 7596 760GM-E51(MS-7596) Motherboard
17f2 5000 KI690-AM2 Motherboard
4384 SBx00 PCI to PCI Bridge
4385 SBx00 SMBus Controller
1179 ff50 Satellite P305D-S8995E
1458 4385 GA-MA770-DS3rev2.0 Motherboard
1462 7368 K9AG Neo2
+ 1462 7596 760GM-E51(MS-7596) Motherboard
15d9 a811 H8DGU
174b 1001 PURE Fusion Mini
17f2 5000 KI690-AM2 Motherboard
1043 8389 M4A785TD Motherboard
105b 0e13 N15235/A74MX mainboard / AMD SB700
1458 b002 GA-MA770-DS3rev2.0 Motherboard
+ 1462 7596 760GM-E51(MS-7596) Motherboard
1849 4390 Motherboard (one of many)
4391 SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode]
103c 1609 ProLiant MicroServer N36L
1043 8443 M5A88-V EVO
105b 0e13 N15235/A74MX mainboard / AMD SB700
1458 5004 GA-880GMA-USB3
+ 1462 7596 760GM-E51(MS-7596) Motherboard
15d9 a811 H8DGU
174b 1001 PURE Fusion Mini
4397 SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
1043 8443 M5A88-V EVO
105b 0e13 N15235/A74MX mainboard / AMD SB700
1458 5004 GA-880GMA-USB3
+ 1462 7596 760GM-E51(MS-7596) Motherboard
15d9 a811 H8DGU
174b 1001 PURE Fusion Mini
4398 SB7x0 USB OHCI1 Controller
1019 2120 A785GM-M
1043 82ef M3A78-EH Motherboard
105b 0e13 N15235/A74MX mainboard / AMD SB700
+ 1462 7596 760GM-E51(MS-7596) Motherboard
15d9 a811 H8DGU
4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
1019 2120 A785GM-M
1043 8443 M5A88-V EVO
105b 0e13 N15235/A74MX mainboard / AMD SB700
1458 5004 GA-880GMA-USB3
+ 1462 7596 760GM-E51(MS-7596) Motherboard
174b 1001 PURE Fusion Mini
439c SB7x0/SB8x0/SB9x0 IDE Controller
1002 4392 MSI MS-7713 motherboard
103c 1609 ProLiant MicroServer N36L
1043 82ef M3A78-EH Motherboard
105b 0e13 N15235/A74MX mainboard / AMD SB700
+ 1462 7596 760GM-E51(MS-7596) Motherboard
439d SB7x0/SB8x0/SB9x0 LPC host controller
1019 2120 A785GM-M
103c 1609 ProLiant MicroServer N36L
1043 82ef M3A78-EH Motherboard
1043 8443 M5A88-V EVO
105b 0e13 N15235/A74MX mainboard / AMD SB700
+ 1462 7596 760GM-E51(MS-7596) Motherboard
174b 1001 PURE Fusion Mini
43a0 SB700/SB800/SB900 PCI to PCI bridge (PCIE port 0)
43a1 SB700/SB800/SB900 PCI to PCI bridge (PCIE port 1)
5964 RV280 [Radeon 9200 SE]
1002 5964 Radeon 9200 SE, 64-bit 128MB DDR, 200/166MHz
1043 c006 Radeon 9200 SE / TD / 128M
- 1458 4018 Radeon 9200 SE
+ 1458 4018 R92S128T (Radeon 9200 SE 128MB)
1458 4032 Radeon 9200 SE 128MB
147b 6191 R9200SE-DT
148c 2073 CN-AG92E
1002 5c63 Apple iBook G4 2004
144d c00c P30 notebook
5d44 RV280 [Radeon 9200 SE] (Secondary)
- 1458 4019 Radeon 9200 SE (Secondary)
+ 1458 4019 R92S128T (Radeon 9200 SE 128MB Secondary)
1458 4032 Radeon 9200 SE 128MB
147b 6190 R9200SE-DT (Secondary)
174b 7c12 Radeon 9200 SE (Secondary)
6607 Mars LE [Radeon HD 8530M / R5 M240]
6608 Oland GL [FirePro W2100]
13cc 3d28 MXRT-2600
+ 6609 Oland GL [FirePro W2100 / Barco MXRT 2600]
6610 Oland XT [Radeon HD 8670 / R7 250/350]
1019 0030 Radeon HD 8670
1028 2120 Radeon R7 250
6667 Jet ULT [Radeon R5 M230]
666f Sun LE [Radeon HD 8550M / R5 M230]
66a0 Vega 20 [Radeon Instinct]
- 66a1 Vega 20
+ 66a1 Vega 20 WKS GL-XE [Radeon Pro VII]
66a2 Vega 20
- 66a3 Vega 20
+ 66a3 Vega 20 [Radeon Pro Vega II/Radeon Pro Vega II Duo]
66a7 Vega 20 [Radeon Pro Vega 20]
66af Vega 20 [Radeon VII]
6704 Cayman PRO GL [FirePro V7900]
1043 04dd STRIX R9 390
148c 2358 Radeon R9 390
174b e324 Sapphire Nitro R9 390
+ 67b8 Hawaii XT [Radeon R9 290X Engineering Sample]
67b9 Vesuvius [Radeon R9 295X2]
67be Hawaii LE
67c0 Ellesmere [Radeon Pro WX 7100 Mobile]
1462 3418 Radeon RX 580 Armor 4G OC
1462 341b Radeon RX 570 Armor 8G OC
1462 341e Radeon RX 570 Armor 4G OC
+ 1462 809e Radeon RX 480 4GB
1462 8a92 Radeon RX 580
148c 2372 Radeon RX 480 [Red Dragon]
148c 2373 Radeon RX 470
148c 2379 Radeon RX 570 4G [Red Dragon]
1682 9470 Radeon RX 470
1682 9480 Radeon RX 480
+ 1682 9587 Radeon RX 590 FATBOY 8GB
1682 9588 Radeon RX 580 XTR
1682 c570 Radeon RX 570
1682 c580 Radeon RX 580
6864 Vega 10 [Radeon Pro V340]
6867 Vega 10 XL [Radeon Pro Vega 56]
6868 Vega 10 [Radeon PRO WX 8100/8200]
+ 6869 Vega 10 XGA [Radeon Pro Vega 48]
+ 686a Vega 10 LEA
+ 686b Vega 10 XTXA [Radeon Pro Vega 64X]
686c Vega 10 [Radeon Instinct MI25 MxGPU]
+ 686d Vega 10 GLXTA
+ 686e Vega 10 GLXLA
687f Vega 10 XL/XT [Radeon RX Vega 56/64]
1002 0b36 RX Vega64
1002 6b76 RX Vega64
1458 230c Radeon RX VEGA 56 GAMING OC 8G
+ 1da2 e376 Radeon RX VEGA 56 Pulse 8GB OC HBM2
6880 Lexington [Radeon HD 6550M]
103c 163c Pavilion dv6 Radeon HD 6550M
6888 Cypress XT [FirePro V8800]
17af 3000 Radeon HD 6510
17af 3010 Radeon HD 5630
68da Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570]
+ 1462 8071 VR5550-MD1G (Radeon HD 5550)
148c 3000 Radeon HD 6390
148c 3001 Radeon HD 6490
1545 7570 Radeon HD 7570
7312 Navi 10 [Radeon Pro W5700]
731f Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT]
1458 2313 Radeon RX 5700 XT Gaming OC
+ 1682 5701 RX 5700 XT RAW II
1da2 e411 Radeon RX 5600 XT
7340 Navi 14 [Radeon RX 5500/5500M / Pro 5500M]
7341 Navi 14 [Radeon Pro W5500]
7347 Navi 14 [Radeon Pro W5500M]
734f Navi 14 [Radeon Pro W5300M]
7360 Navi 12 [Radeon Pro 5600M]
+ 7388 Arcturus GL-XL
+ 738c Arcturus GL-XL [AMD Instinct MI100]
+ 738e Arcturus GL-XL
73bf Navi 21 [Radeon RX 6800/6800 XT / 6900 XT]
+ 1eae 6701 XFX Speedster MERC 319 AMD Radeon RX 6800 XT Black
73c3 Navi 22
73df Navi 22
+ 73e0 Navi 23
73ff Navi 23
7833 RS350 Host Bridge
7834 RS350 [Radeon 9100 PRO/XT IGP]
95cd RV620 GL [FirePro 2450]
95cf RV620 GL [FirePro 2260]
960f RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300]
+ 1462 7596 760GM-E51(MS-7596) Motherboard
9610 RS780 [Radeon HD 3200]
1458 d000 GA-MA78GM-S2H Motherboard
9611 RS780C [Radeon 3100]
9614 RS780D [Radeon HD 3300]
9615 RS780E [Radeon HD 3200]
9616 RS780L [Radeon 3000]
+# ID is probably a copy-paste error by a MSI developer from another mainboard, since all other ID numbers on this mainboard including the sub-device of this device has used subsystem ID 1462:7596
+ 1462 7501 760GM-E51(MS-7596) Motherboard
9640 Sumo [Radeon HD 6550D]
9641 Sumo [Radeon HD 6620G]
9642 SuperSumo [Radeon HD 6370D]
9809 Wrestler [Radeon HD 7310]
980a Wrestler [Radeon HD 7290]
9830 Kabini [Radeon HD 8400 / R3 Series]
+ 1043 8623 AM1I-A Motherboard
9831 Kabini [Radeon HD 8400E]
9832 Kabini [Radeon HD 8330]
1849 9832 QC5000-ITX/PH
9839 Kabini [Radeon HD 8180]
983d Temash [Radeon HD 8250/8280G]
9840 Kabini HDMI/DP Audio
+ 1043 8623 AM1I-A Motherboard
1849 9840 QC5000-ITX/PH
9850 Mullins [Radeon R3 Graphics]
9851 Mullins [Radeon R4/R5 Graphics]
1450 Family 17h (Models 00h-0fh) Root Complex
1451 Family 17h (Models 00h-0fh) I/O Memory Management Unit
1452 Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge
+ ea50 ce19 mCOM10-L1900
1453 Family 17h (Models 00h-0fh) PCIe GPP Bridge
1454 Family 17h (Models 00h-0fh) Internal PCIe GPP Bridge 0 to Bus B
1455 Zeppelin/Renoir PCIe Dummy Function
149b Starship Reserved SSP
149c Matisse USB 3.0 Host Controller
1462 7c37 X570-A PRO motherboard
+ 149d Vangogh CVIP
1510 Family 14h Processor Root Complex
174b 1001 PURE Fusion Mini
1512 Family 14h Processor Root Port
1534 Family 16h Processor Function 4
1535 Family 16h Processor Function 5
1536 Family 16h Processor Root Complex
+ 1043 8623 AM1I-A Motherboard
1849 1536 QC5000-ITX/PH
1537 Kabini/Mullins PSP-Platform Security Processor
1538 Family 16h Processor Function 0
15be Stoney Audio Processor
15d0 Raven/Raven2 Root Complex
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME B450M-A Motherboard
15d1 Raven/Raven2 IOMMU
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME B450M-A Motherboard
+ ea50 ce19 mCOM10-L1900
15d2 Raven/Raven2 PCIe Dummy Host Bridge
15d3 Raven/Raven2 PCIe GPP Bridge [6:0]
15d4 FireFlight USB 3.1
15d5 FireFlight USB 3.1
15da Raven/Raven2 PCIe Dummy Host Bridge
15db Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A
+ ea50 ce19 mCOM10-L1900
15dc Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B
+ ea50 ce19 mCOM10-L1900
15de Raven/Raven2/FireFlight HD Audio Controller
15df Family 17h (Models 10h-1fh) Platform Security Processor
+ 1043 876b PRIME Motherboard
17aa 5124 ThinkPad E595
+ ea50 ce19 mCOM10-L1900
15e0 Raven USB 3.1
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME Motherboard
17aa 5124 ThinkPad E595
+ ea50 ce19 mCOM10-L1900
15e1 Raven USB 3.1
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME Motherboard
17aa 5124 ThinkPad E595
+ ea50 ce19 mCOM10-L1900
15e2 Raven/Raven2/FireFlight/Renoir Audio Processor
17aa 5124 ThinkPad E595
15e3 Family 17h (Models 10h-1fh) HD Audio Controller
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 86c7 PRIME B450M-A Motherboard
17aa 5124 ThinkPad E595
15e4 Raven/Raven2/Renoir Sensor Fusion Hub
15e5 Raven2 USB 3.1
1642 Renoir WLAN
1643 Renoir BT
1644 Renoir I2S
+ 1648 VanGogh Root Complex
+ 1649 VanGogh PSP/CCP
1700 Family 12h/14h Processor Function 0
1701 Family 12h/14h Processor Function 1
1702 Family 12h/14h Processor Function 2
7801 FCH SATA Controller [AHCI mode]
103c 168b ProBook 4535s Notebook
103c 194e ProBook 455 G1 Notebook
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 7801 QC5000-ITX/PH
7802 FCH SATA Controller [RAID mode]
7807 FCH USB OHCI Controller
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 7807 QC5000-ITX/PH
7808 FCH USB EHCI Controller
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 7808 QC5000-ITX/PH
7809 FCH USB OHCI Controller
780b FCH SMBus Controller
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 780b QC5000-ITX/PH
780c FCH IDE Controller
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
1043 8444 F2A85-M Series
+ 1043 8576 AM1I-A Motherboard
17aa 3988 Z50-75
1849 8892 QC5000-ITX/PH
780e FCH LPC Bridge
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 780e QC5000-ITX/PH
780f FCH PCI Bridge
7814 FCH USB XHCI Controller
103c 194e ProBook 455 G1 Notebook
103c 1985 Pavilion 17-e163sg Notebook PC
+ 1043 8623 AM1I-A Motherboard
17aa 3988 Z50-75
1849 7814 QC5000-ITX/PH
7900 FCH SATA Controller [IDE mode]
7901 FCH SATA Controller [AHCI mode]
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME Motherboard
1462 7c37 X570-A PRO motherboard
+ ea50 ce19 mCOM10-L1900
7902 FCH SATA Controller [RAID mode]
7903 FCH SATA Controller [RAID mode]
7904 FCH SATA Controller [AHCI mode]
7908 FCH USB EHCI Controller
790b FCH SMBus Controller
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME Motherboard
1462 7c37 X570-A PRO motherboard
17aa 5124 ThinkPad E595
+ ea50 ce19 mCOM10-L1900
790e FCH LPC Bridge
103c 8615 Pavilion Laptop 15-cw1xxx
+ 1043 876b PRIME B450M-A Motherboard
1462 7c37 X570-A PRO motherboard
17aa 5124 ThinkPad E595
+ ea50 ce19 mCOM10-L1900
790f FCH PCI Bridge
7914 FCH USB XHCI Controller
9600 RS780 Host Bridge
1931 000a GlobeTrotter Fusion Quad Lite (PPP data)
1931 000b GlobeTrotter Fusion Quad Lite (GSM data)
807d 0035 PCI-USB2 (OHCI subsystem)
+ 8086 4d44 D850EMV2 motherboard
003b PCI to C-bus Bridge
003e NAPCCARD Cardbus Controller
0046 PowerVR PCX2 [midas]
14c2 0205 PTI-205N USB 2.0 Host Controller
1799 0002 Root Hub
807d 1043 PCI-USB2 (EHCI subsystem)
+ 8086 4d44 D850EMV2 motherboard
00e7 uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller
00f2 uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller
00f3 uPD6113x Multimedia Decoder/Processor [EMMA2]
103c 17e8 SN1000Q 16Gb Dual Port Fibre Channel Adapter
103c 1939 QMH2672 16Gb Dual Port Fibre Channel Adapter
103c 8002 3830C 16G Fibre Channel Host Bus Adapter
+ 1077 0241 QLE2670 16Gb Single Port Fibre Channel Adapter
2071 ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter
1077 0283 QLE2764 Quad Port 32Gb Fibre Channel to PCIe Adapter
1077 029e QLE2694 Quad Port 16Gb Fibre Channel to PCIe Adapter
2081 ISP2814-based 64/32G Fibre Channel to PCIe Controller
1077 02e1 QLE2874 Quad Port 64GFC PCIe Gen4 x16 Adapter
1077 02e3 QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter
+ 2089 ISP2854-based 64/32G Fibre Channel to PCIe Controller with StorCryption
+ 1077 02e8 QLE2884 Quad Port 64GFC PCIe Gen4 x16 Adapter with StorCryption
+ 1077 02ea QLE2784 Quad Port 32GFC PCIe Gen4 x16 Adapter with StorCryption
2100 QLA2100 64-bit Fibre Channel Adapter
1077 0001 QLA2100 64-bit Fibre Channel Adapter
2200 QLA2200 64-bit Fibre Channel Adapter
1590 0203 StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter
1590 0204 StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter
1590 022d 5830C 32Gb Dual Port Fibre Channel Adapter
+ 193d 100d NIC-FC680i-Mb-2x16G
2281 ISP2812-based 64/32G Fibre Channel to PCIe Controller
1077 02e2 QLE2872 Dual Port 64GFC PCIe Gen4 x8 Adapter
1077 02e4 QLE2772 Dual Port 32GFC PCIe Gen4 x8 Adapter
1077 02f3 QLogic 2x32Gb QLE2772 FC HBA
1590 02d3 SN1610Q - 1P Enhanced 32GFC Single Port Fibre Channel Host Bus Adapter
1590 02d4 SN1610Q – 2P Enhanced 32GFC Dual Port Fibre Channel Host Bus Adapter
+ 2289 ISP2852-based 64/32G Fibre Channel to PCIe Controller with StorCryption
+ 1077 02e9 QLE2882 Dual Port 64GFC PCIe Gen4 x8 Adapter with StorCryption
+ 1077 02eb QLE2782 Dual Port 32GFC PCIe Gen4 x8 Adapter with StorCryption
+ 1077 02ef QLE2880 Single Port 64GFC PCIe Gen4 x8 Adapter with StorCryption
+ 1077 02f1 QLE2780 Single Port 32GFC PCIe Gen4 x8 Adapter with StorCryption
2300 QLA2300 64-bit Fibre Channel Adapter
2312 ISP2312-based 2Gb Fibre Channel to PCI-X HBA
103c 0131 2Gb Fibre Channel - Single port [A7538A]
1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter
1590 0220 10/25GbE 2P QL41122HLRJ-HP Adapter
1590 02bd 10Gb 2P 524SFP+ NIC
+ 193d 1030 NIC-ETH681i-Mb-2x25G
+ 193d 1032 NIC-ETH682i-Mb-2x25G
8080 FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE)
1077 0001 10GE 2P QL41162HxRJ-DE Adapter
1077 0002 10GE 2P QL41112HxCU-DE Adapter
10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board
10b5 3196 Goramo PLX200SYN sync serial card
10b5 9050 PCI-I04 PCI Passive PC/CAN Interface
+ 12fe 0001 CAN-PCI/331 CAN bus controller
1369 8901 PCX11+ PCI
1369 8f01 VX222
1369 9401 PCX924
0a21 GT216M [GeForce GT 330M]
0a22 GT216 [GeForce 315]
0a23 GT216 [GeForce 210]
+ 0a24 GT216 [GeForce 405]
0a26 GT216 [GeForce 405]
0a27 GT216 [GeForce 405]
0a28 GT216M [GeForce GT 230M]
1aeb TU116 High Definition Audio Controller
1aec TU116 USB 3.1 Host Controller
1aed TU116 USB Type-C UCSI Controller
+ 1aef GA102 High Definition Audio Controller
1b00 GP102 [TITAN X]
1b01 GP102 [GeForce GTX 1080 Ti 10GB]
1b02 GP102 [TITAN Xp]
1b07 GP102 [P102-100]
1b30 GP102GL [Quadro P6000]
1b38 GP102GL [Tesla P40]
+ 1b39 GP102GL [Tesla P10]
1b70 GP102GL
1b78 GP102GL
1b80 GP104 [GeForce GTX 1080]
1c2d GP106M
1c30 GP106GL [Quadro P2000]
1c31 GP106GL [Quadro P2200]
- 1c35 GP106
- 1c36 GP106
+ 1c35 GP106M [Quadro P2000 Mobile]
+ 1c36 GP106 [P106M]
1c60 GP106BM [GeForce GTX 1060 Mobile 6GB]
103c 8390 GeForce GTX 1060 Max-Q 6GB
1c61 GP106BM [GeForce GTX 1050 Ti Mobile]
1f98 TU117M [GeForce MX450]
1f99 TU117M
1f9c TU117M [GeForce MX450]
+ 1f9d TU117M [GeForce GTX 1650 Mobile / Max-Q]
1fae TU117GL
1fb8 TU117GLM [Quadro T2000 Mobile / Max-Q]
1fb9 TU117GLM [Quadro T1000 Mobile]
+ 1fbb TU117GLM [Quadro T500 Mobile]
1fbf TU117GL
1fd9 TU117BM [GeForce GTX 1650 Mobile Refresh]
1ff9 TU117GLM [Quadro T1000 Mobile]
20b0 GA100 [A100 SXM4 40GB]
20b1 GA100 [A100 PCIe 40GB]
+ 20b2 GA100 [A100 SXM4 80GB]
20be GA100 [GRID A100A]
20bf GA100 [GRID A100B]
20f1 GA100 [A100 PCIe 40GB]
2192 TU116M [GeForce GTX 1650 Ti Mobile]
21ae TU116GL
21bf TU116GL
+ 21c2 TU116
21c4 TU116 [GeForce GTX 1660 SUPER]
21d1 TU116BM [GeForce GTX 1660 Ti Mobile]
2204 GA102 [GeForce RTX 3090]
+ 2205 GA102 [GeForce RTX 3080 Ti]
2206 GA102 [GeForce RTX 3080]
+ 10de 1467 GA102 [GeForce RTX 3080]
10de 146d GA102 [GeForce RTX 3080 20GB]
1462 3892 RTX 3080 10GB GAMING X TRIO
222b GA102 [GeForce RTX 3090 Engineering Sample]
222f GA102 [GeForce RTX 3080 11GB / 12GB Engineering Sample]
2230 GA102GL [RTX A6000]
+ 2235 GA102GL [RTX A40]
+ 2236 GA102GL
223f GA102GL
+ 228b GA104 High Definition Audio Controller
+ 2321 GA103
2482 GA104 [GeForce RTX 3070 Ti]
2484 GA104 [GeForce RTX 3070]
10de 146b GA104 [GeForce RTX 3070]
10de 14ae GA104 [GeForce RTX 3070 16GB]
2486 GA104 [GeForce RTX 3060 Ti]
- 249c GA104M [GeForce RTX 3070 Mobile / Max-Q 8GB/16GB]
+ 249c GA104M [GeForce RTX 3080 Mobile / Max-Q 8GB/16GB]
249d GA104M [GeForce RTX 3070 Mobile / Max-Q]
+ 249f GA104M
24ac GA104 [GeForce RTX 30x0 Engineering Sample]
24ad GA104 [GeForce RTX 3060 Engineering Sample]
24af GA104 [GeForce RTX 3070 Engineering Sample]
+ 24b6 GA104
+ 24b8 GA104
24bf GA104 [GeForce RTX 3070 Engineering Sample]
- 24dc GA104M [GeForce RTX 3070 Mobile 16GB]
+ 24dc GA104M [GeForce RTX 3080 Mobile / Max-Q 8GB/16GB]
24dd GA104M [GeForce RTX 3070 Mobile / Max-Q]
+ 2501 GA106 [GeForce RTX 3060]
+ 2503 GA106 [GeForce RTX 3060]
+ 2505 GA106
+ 2520 GA106M [GeForce RTX 3060 Mobile / Max-Q]
252f GA106 [GeForce RTX 3060 Engineering Sample]
+ 2560 GA106M [GeForce RTX 3060 Mobile / Max-Q]
+ 2583 GA107 [GeForce RTX 3050]
+ 25a2 GA107
+ 25a4 GA107
25af GA107 [GeForce RTX 3050 Engineering Sample]
10df Emulex Corporation
0720 OneConnect NIC (Skyhawk)
1590 0213 StoreFabric SN1200E 1-Port 16Gb Fibre Channel Adapter
1590 0214 StoreFabric SN1200E 2-Port 16Gb Fibre Channel Adapter
1590 022e Synergy 5330C 2-Port 32Gb Fibre Channel Mezz Card
+ 193d 1060 NIC-FC730i-Mb-2P
f011 Saturn: LightPulse Fibre Channel Host Adapter
f015 Saturn: LightPulse Fibre Channel Host Adapter
f085 LP850 Fibre Channel Host Adapter
10df f419 LPe35002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter
1590 02d5 StoreFabric SN1610E 1-Port 32Gb Fibre Channel Adapter
1590 02d6 StoreFabric SN1610E 2-Port 32Gb Fibre Channel Adapter
+ f500 LPe37000/LPe38000 Series 32Gb/64Gb Fibre Channel Adapter
f700 LP7000 Fibre Channel Host Adapter
f701 LP7000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
f800 LP8000 Fibre Channel Host Adapter
8111 Twist3 Frame Grabber
10ec Realtek Semiconductor Co., Ltd.
0139 RTL-8139/8139C/8139C+ Ethernet Controller
+ 3000 Killer E3000 2.5GbE Controller
5208 RTS5208 PCI Express Card Reader
5209 RTS5209 PCI Express Card Reader
5227 RTS5227 PCI Express Card Reader
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
1028 06e4 XPS 15 9550
+ 1028 06e6 Latitude 11 5175 2-in-1
17aa 224f ThinkPad X1 Carbon 5th Gen
5260 RTS5260 PCI Express Card Reader
5286 RTS5286 PCI Express Card Reader
8e2e 7000 KF-230TX
8e2e 7100 KF-230TX/2
a0a0 0007 ALN-325C
+ 8161 RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
+ 10ec 8168 TP-Link TG-3468 v4.0 Gigabit PCI Express Network Adapter
8167 RTL-8110SC/8169SC Gigabit Ethernet
105b 0e10 RTL-8110SC-GR on a N15235/A74MX mainboard
1458 e000 GA-MA69G-S3H Motherboard
1043 83a3 M4A785/P7P55 Motherboard
1043 8432 P8P67 and other motherboards
1043 8505 P8 series motherboard
+ 1043 8554 H81M-C Motherboard
+ 1043 859e AM1I-A Motherboard
+ 1043 8677 PRIME B450M-A Motherboard
105b 0d7c D270S/D250S Motherboard
10ec 8168 RTL8111/8168 PCI Express Gigabit Ethernet controller
144d c652 RTL8168 on a NP300E5C series laptop
1462 7522 X58 Pro-E
1462 7c37 X570-A PRO motherboard
1775 11cc CC11/CL11
+ 17aa 3098 ThinkCentre E73
17aa 3814 Z50-75
17aa 3823 Lenovo V130-15IGM Laptop - Type 81HL
17aa 5124 ThinkPad E595
7470 3468 TG-3468 Gigabit PCI Express Network Adapter
8086 2055 NUC Kit DN2820FYKH
8086 d615 Desktop Board D510MO/D525MW
+ ea50 ce19 mCOM10-L1900
8169 RTL8169 PCI Gigabit Ethernet Controller
1025 0079 Aspire 5024WLMi
10bd 3202 EP-320G-TX1 32-bit PCI Gigabit Ethernet Adapter
16ec 011f USR997903
1734 1091 D2030-A1
a0a0 0449 AK86-L motherboard
+ 816a RTL8111xP UART #1
+ ea50 ce19 mCOM10-L1900
+ 816b RTL8111xP UART #2
+ ea50 ce19 mCOM10-L1900
+ 816c RTL8111xP IPMI interface
+ ea50 ce19 mCOM10-L1900
+ 816d RTL811x EHCI host controller
+ ea50 ce19 mCOM10-L1900
8171 RTL8191SEvA Wireless LAN Controller
8172 RTL8191SEvB Wireless LAN Controller
8173 RTL8192SE Wireless LAN Controller
5005 Alveo U250
7038 FPGA Card XC7VX690T
17aa 402f FPGA XC7VX690T-3FFG1157E
+ 8019 Memory controller
8380 Ellips ProfiXpress Profibus Master
8381 Ellips Santos Frame Grabber
d154 Copley Controls CAN card (PCI-CAN-02)
1172 Altera Corporation
00a7 Stratix V
0530 Stratix IV
+ 646c KT-500/KT-521 board
1173 Adobe Systems, Inc
1174 Bridgeport Machines
1175 Mitron Computer Inc.
1179 Toshiba Corporation
0102 Extended IDE Controller
0103 EX-IDE Type-B
+ 010e PXP04 NVMe SSD
010f NVMe Controller
0110 NVMe SSD Controller Cx5
1028 1ffb Express Flash NVMe 960G (RI) U.2 (CD5)
1d49 4039 Thinksystem U.2 CM5 NVMe SSD
1d49 403a Thinksystem AIC CM5 NVMe SSD
0113 BG3 NVMe SSD Controller
+ 1179 0001 Toshiba KBG30ZMS128G 128GB NVMe SSD
0115 XG4 NVMe SSD Controller
+ 011a XG6 NVMe SSD Controller
0404 DVD Decoder card
0406 Tecra Video Capture device
0407 DVD Decoder card (Version 2)
a000 2000 Parallel Port
a000 6000 SPI
a000 7000 Local Bus
+ ea50 1c10 RXi2-BP
125c Aurora Technologies, Inc.
0101 Saturn 4520P
0640 Aries 16000P
0820 SM820 Lynx3D
0910 SM910
2262 SM2262/SM2262EN SSD Controller
+ 2263 SM2263EN/SM2263XT SSD Controller
1270 Olympus Optical Co., Ltd.
1271 GW Instruments
1272 Telematics International
1281 Yokogawa Electric Corporation
1282 Davicom Semiconductor, Inc.
6585 DM562P V90 Modem
- 9009 Ethernet 100/10 MBit
+ 9009 DM9009 Ethernet Controller
9100 21x4x DEC-Tulip compatible 10/100 Ethernet
- 9102 21x4x DEC-Tulip compatible 10/100 Ethernet
+ 9102 DM9102 Fast Ethernet Controller
# Subsystem ID is main ID reveresed.
0291 8212 DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit
9132 Ethernet 100/10 MBit
8888 IT8888F/G PCI to ISA Bridge with SMB [Golden Gate]
8889 IT8889F PCI to ISA Bridge
8892 IT8892E PCIe to PCI Bridge
+ 8086 200d DH61CR motherboard
8893 IT8893E PCIe to PCI Bridge
e886 IT8330G
1284 Sahara Networks, Inc.
2304 PI7C9X2G304 EL/SL PCIe2 3-Port/4-Lane Packet Switch
2404 PI7C9X2G404 EL/SL PCIe2 4-Port/4-Lane Packet Switch
2608 PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch
+ ea50 cc10 RXi2-BP
400a PI7C9X442SL PCI Express Bridge Port
400e PI7C9X442SL USB OHCI Controller
400f PI7C9X442SL USB EHCI Controller
8150 PCI to PCI Bridge
8152 PI7C8152A/PI7C8152B/PI7C8152BI PCI-to-PCI Bridge
8154 PI7C8154A/PI7C8154B/PI7C8154BI PCI-to-PCI Bridge
+ 8619 PI7C9X2G1616PR PCIe2 16-Port/16-Lane Packet Switch
e110 PI7C9X110 PCI Express to PCI bridge
1775 11cc CC11/CL11 CompactPCI Bridge
e111 PI7C9X111SL PCIe-to-PCI Reversible Bridge
12ea Zuken
12eb Aureal Semiconductor
0001 Vortex 1
+ 0000 0300 Terasound A3D PCI
104d 8036 AU8820 Vortex Digital Audio Processor
1092 2000 Sonic Impact A3D
1092 2100 Sonic Impact A3D
1092 2110 Sonic Impact A3D
1092 2200 Sonic Impact A3D
- 122d 1002 AU8820 Vortex Digital Audio Processor
+ 122d 1002 SC 338-A3D
12eb 0001 AU8820 Vortex Digital Audio Processor
5053 3355 Montego
50b2 1111 XLerate
134f Algo System Co Ltd
1350 Systec Co. Ltd
1351 Sonix Inc
-# nee Thales Idatys
-1353 Vierling Communication SAS
+# nee Vierling Communication SAS, nee Thales Idatys
+1353 dbeeSet Technology
0002 Proserver
0003 PCI-FUT
0004 PCI-S0
0005 PCI-FUT-S0
+ 0006 OTDU-1U (FPGA Zynq-7000)
+ 0007 OTDU-EX
1354 Dwave System Inc
1355 Kratos Analytical Ltd
1356 The Logical Co
a544 Exynos 8890 PCIe Root Complex
a800 XP941 PCIe SSD
a802 NVMe SSD Controller SM951/PM951
- a804 NVMe SSD Controller SM961/PM961
+ 144d a801 PM963 2.5" NVMe PCIe SSD
+ a804 NVMe SSD Controller SM961/PM961/SM963
+ 144d a801 SM963 2.5" NVMe PCIe SSD
a808 NVMe SSD Controller SM981/PM981/PM983
1d49 403b Thinksystem U.2 PM983 NVMe SSD
+ a80a NVMe SSD Controller PM9A1/980PRO
a820 NVMe SSD Controller 171X
1028 1f95 Express Flash NVMe XS1715 SSD 400GB
1028 1f96 Express Flash NVMe XS1715 SSD 800GB
103c 339d Ethernet 10Gb 2-port 530SFP+ Adapter
193d 1003 530F-B
193d 1006 530F-L
+ 193d 100f NIC-ETH522i-Mb-2x10G
1690 NetXtreme BCM57760 Gigabit Ethernet PCIe
1691 NetLink BCM57788 Gigabit Ethernet PCIe
1028 04aa XPS 8300
16a0 NetLink BCM5785 Fast Ethernet
16a1 BCM57840 NetXtreme II 10 Gigabit Ethernet
1043 866e PEB-10G/57840-2T 10GBase-T Network Adapter
+ 193d 100b NIC-ETH521i-Mb-4x10G
16a2 BCM57840 NetXtreme II 10/20-Gigabit Ethernet
103c 1916 FlexFabric 20Gb 2-port 630FLB Adapter
103c 1917 FlexFabric 20Gb 2-port 630M Adapter
1805 BCM57508 NetXtreme-E RDMA Partition
1806 BCM5750X NetXtreme-E Ethernet Virtual Function
1807 BCM5750X NetXtreme-E RDMA Virtual Function
+ 2711 BCM2711 PCIe Bridge
3352 BCM3352
3360 BCM3360
4210 BCM4210 iLine10 HomePNA 2.0
15b3 0021 MCX4421A-ACQN ConnectX-4 Lx EN OCP,2x25G
15b3 0025 ConnectX-4 Lx 25 GbE Dual Port SFP28 rNDC
193d 100a 620F-B
+ 193d 1031 NIC-ETH640i-Mb-2x25G
1016 MT27710 Family [ConnectX-4 Lx Virtual Function]
1017 MT27800 Family [ConnectX-5]
15b3 0006 ConnectX®-5 EN network interface card, 100GbE single-port QSFP28, PCIe3.0 x16, tall bracket; MCX515A-CCAT
15b3 0007 Mellanox ConnectX®-5 MCX516A-CCAT
15b3 0020 ConnectX®-5 EN network interface card, 10/25GbE dual-port SFP28, PCIe3.0 x8, tall bracket ; MCX512A-ACAT
15b3 0068 ConnectX®-5 EN network interface card for OCP2.0, Type 1, with host management, 25GbE dual-port SFP28, PCIe3.0 x8, no bracket Halogen free ; MCX542B-ACAN
+ 193d 1051 NIC-IB1040i-Mb-2P
1018 MT27800 Family [ConnectX-5 Virtual Function]
1019 MT28800 Family [ConnectX-5 Ex]
15b3 0008 ConnectX-5 Ex EN network interface card, 100GbE dual-port QSFP28, PCIe4.0 x16, tall bracket; MCX516A-CDAT
15b7 Sandisk Corp
2001 Skyhawk Series NVME SSD
5001 WD Black NVMe SSD
- 5002 WD Black 2018 / PC SN720 NVMe SSD
- 5003 WD Black 2018 / PC SN520 NVMe SSD
+ 5002 WD Black 2018/SN750 / PC SN720 NVMe SSD
+ 5003 WD Blue SN500 / PC SN520 NVMe SSD
5004 PC SN520 NVMe SSD
5005 PC SN520 NVMe SSD
- 5006 WD Black 2019/PC SN750 NVMe SSD
+ 5006 WD Black SN750 / PC SN730 NVMe SSD
5009 WD Blue SN550 NVMe SSD
15b7 5009 WD Blue SN550 NVMe SSD
+ 500b PC SN530 NVMe SSD
+ 1414 500b Xbox Series X
500d WD Ultrastar DC SN340 NVMe SSD
+ 5011 WD Black SN850
15b8 ADDI-DATA GmbH
1001 APCI1516 SP controller (16 digi outputs)
1003 APCI1032 SP controller (32 digi inputs w/ opto coupler)
0245 PCA7428CE_F1 - Analog Inputs isolated
0303 PCD-7006C Digital Input & Output PCI Card
0800 PCD8006 - PCIe digital Inputs/Outputs
+ 0840 PCA-8428 General-purpose multifunctional PCIe card with 8 analog inputs and 2 analog outputs
+ 0841 PCA-8429 General-purpose multifunctional PCIe card with 8 analog inputs
+ 0842 PCA-8438 General-purpose multifunctional PCIe card with 16 analog inputs and 2 analog outputs
+ 0843 PCA-8439 General-purpose multifunctional PCIe card with 16 analog inputs
ff00 CTU CAN FD PCIe Card
1761 Pickering Interfaces Ltd
1771 InnoVISION Multimedia Ltd.
0400 Datacenter Technologies QDF2432 PCI Express Root Port
0401 Datacenter Technologies QDF2400 PCI Express Root Port
1000 QCS405 PCIe Root Complex
+ 1101 QCA6390 Wireless Network Adapter [AX500-DBS (2x2)]
17cc NetChip Technology, Inc
2280 USB 2.0
17cd Cadence Design Systems, Inc.
19e5 d136 Hi1822 SP580 (4*25GE)
19e5 d141 Hi1822 SP583 (4*25GE)
19e5 d146 Hi1822 SP585 (4*25GE)
+ 3714 ES3000 V5 NVMe PCIe SSD
+ 19e5 5312 NVMe SSD ES3500P V5 2000GB 2.5" U.2
371e Hi1822 Family Virtual Bridge
+ 3754 ES3000 V6 NVMe PCIe SSD
+ 19e5 6122 NVMe SSD ES3600P V6 1600GB 2.5" U.2
+ 19e5 6123 NVMe SSD ES3600P V6 3200GB 2.5" U.2
+ 19e5 6124 NVMe SSD ES3600P V6 6400GB 2.5" U.2
+ 19e5 6141 NVMe SSD ES3800P V6 800GB 2.5" U.2
+ 19e5 6142 NVMe SSD ES3800P V6 1600GB 2.5" U.2
+ 19e5 6212 NVMe SSD ES3500P V6 1920GB 2.5" U.2
+ 19e5 6213 NVMe SSD ES3500P V6 3840GB 2.5" U.2
+ 19e5 6214 NVMe SSD ES3500P V6 7680GB 2.5" U.2
+ 19e5 6215 NVMe SSD ES3500P V6 15360GB 2.5" U.2
375e Hi1822 Family Virtual Function
379e Hi1822 Family Virtual Function
a120 HiSilicon PCIe Root Port with Gen4
1a4a SLAC National Accelerator Lab TID-AIR
1000 MCOR Power Supply Controller
1010 AMC EVR - Stockholm Timing Board
+ 1020 PGPCard - Gen3 Cameralink Interface
1030 PGPCard - Gen3 GIGe Interface
2000 PGPCard - 4 Lane
2001 PGPCard - 8 Lane Plus EVR
000b QEMU PCIe Expander bridge
000c QEMU PCIe Root port
000d QEMU XHCI Host Controller
+ 0010 QEMU NVM Express Controller
0100 QXL paravirtual graphic card
1af4 1100 QEMU Virtual Machine
1b37 Signal Processing Devices Sweden AB
9172 88SE9172 SATA 6Gb/s Controller
9178 88SE9170 PCIe SATA 6Gb/s Controller
917a 88SE9172 SATA III 6Gb/s RAID Controller
+ 9182 88SE9182 PCIe 2.0 x2 2-port SATA 6 Gb/s Controller
9183 88SS9183 PCIe SSD Controller
9192 88SE9172 SATA III 6Gb/s RAID Controller
91a0 88SE912x SATA 6Gb/s Controller [IDE mode]
91a4 88SE912x IDE Controller
+ 9215 88SE9215 PCIe 2.0 x1 4-port SATA 6 Gb/s Controller
9220 88SE9220 PCIe 2.0 x2 2-port SATA 6 Gb/s RAID Controller
- 9230 88SE9230 PCIe SATA 6Gb/s Controller
+ 9230 88SE9230 PCIe 2.0 x2 4-port SATA 6 Gb/s RAID Controller
1028 1fd6 BOSS-S1 Adapter
1028 1fdf BOSS-S1 Modular
1028 1fe2 BOSS-S1 Adapter
2402 Ultrastar DC SN640 NVMe SSD
2404 Ultrastar DC SN640 NVMe SSD
2500 Ultrastar DC SN840 NVMe SSD
+ 2600 Ultrastar DC ZN540 ZNS NVMe SSD
3714 PC SN730 NVMe SSD
3734 PC SN730 NVMe SSD
1b9a XAVi Technologies Corp.
1285 PC300 NVMe Solid State Drive 1TB
1327 BC501 NVMe Solid State Drive 512GB
1504 SC300 512GB M.2 2280 SATA Solid State Drive
+ 1527 PC401 NVMe Solid State Drive 256GB
243b PE6110 NVMe Solid State Drive
1c5c 0100 PE6110 NVMe Solid State Drive
2839 PE8000 Series NVMe Solid State Drive
1c5c 0100 PE8000 Series NVMe Solid State Drive
1c5f Beijing Memblaze Technology Co. Ltd.
- 000d PBlaze5 520/526 AIC
- 003d PBlaze5 920/926 AIC
- 010d PBlaze5 520/526 U.2
- 013d PBlaze5 920/926 U.2
+ 000d PBlaze5 520/526
+ 003d PBlaze5 920/926
+ 003e PBlaze6 6920
+ 1c5f 0a31 NVMe SSD PBlaze6 6920 3840GB 2.5" U.2
+ 1c5f 0a41 NVMe SSD PBlaze6 6920 7680GB 2.5" U.2
+ 1c5f 4a31 NVMe SSD PBlaze6 6920 3200GB 2.5" U.2
+ 1c5f 4a41 NVMe SSD PBlaze6 6920 6400GB 2.5" U.2
0540 PBlaze4 NVMe SSD
0550 PBlaze5 700/900
0555 PBlaze5 510/516
1d00 Pure Storage
1d05 Tongfang Hongkong Limited
1d0f Amazon.com, Inc.
+ 8061 NVMe EBS Controller
cd01 NVMe SSD Controller
ec20 Elastic Network Adapter (ENA)
efa0 Elastic Fabric Adapter (EFA)
1014 AR-MAN-U280 [Manitou Class Accelerator for U280]
1015 AR-ARK-BBDEV-FX0 [Arkville 32B DPDK Baseband Device]
1016 AR-ARK-BBDEV-FX1 [Arkville 64B DPDK Baseband Device]
+ 1017 AR-ARK-FX1 [Arkville 64B Multi-Homed Primary Endpoint]
+ 1018 AR-ARK-FX1 [Arkville 64B Multi-Homed Secondary Endpoint]
+ 1019 AR-ARK-FX1 [Arkville 64B Multi-Homed Tertiary Endpoint]
4200 A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument]
1d72 Xiaomi
1d78 DERA Storage
0100 RK3399 PCI Express Root Port
1808 RK1808 Neural Network Processor Card
1d8f Enyx
-1d93 YADRO (KNS Group)
+1d93 YADRO
1d94 Chengdu Haiguang IC Design Co., Ltd.
1450 Root Complex
1451 I/O Memory Management Unit
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1001 DSC Virtual Downstream Port
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1002 DSC Ethernet Controller
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1003 DSC Ethernet Controller VF
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1004 DSC Management Controller
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1007 DSC Storage Accelerator
1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB
1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB
1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB
- 1dd8 4007 DSP DSC-25 10/25G 2p OCP Card
- 1dd8 4008 DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC
+ 1dd8 4007 DSP DSC-25 Ent 10/25G OCP3 Card
+ 1dd8 4008 DSP DSC-25 10/25G 2p SFP28 Card
1dd8 400a DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card
1dd8 400c DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
- 1dd8 400d DSP DSC-100 100G 2p QSFP28 Card
+ 1dd8 400d DSP DSC-100 Ent 100Gb Card
+ 1dd8 400e DSC-25 10/25G 2-port 4G RAM 8G eMMC G1 Services Card
1de0 Groq
- 0000 Q100 Tensor Streaming Processor
+# rename due to conflict with a term in use by another company for an entirely different product.
+ 0000 TSP100 Tensor Streaming Processor
1de1 Tekram Technology Co.,Ltd.
0391 TRM-S1040 [DC-315 / DC-395 series]
2020 DC-390
e00a eMAG PCI Express Root Port 5
e00b eMAG PCI Express Root Port 6
e00c eMAG PCI Express Root Port 7
+# Root Complex A (RCA)
+ e100 Altra PCI Express Root Complex A
+# RCA port 0
+ e101 Altra PCI Express Root Port a0
+# RCA port 1
+ e102 Altra PCI Express Root Port a1
+# RCA port 2
+ e103 Altra PCI Express Root Port a2
+# RAC port 3
+ e104 Altra PCI Express Root Port a3
+# RCA port 4
+ e105 Altra PCI Express Root Port a4
+# RCA port 5
+ e106 Altra PCI Express Root Port a5
+# RCA port 6
+ e107 Altra PCI Express Root Port a6
+# RCA port 7
+ e108 Altra PCI Express Root Port a7
+# Root Complex B (RCB)
+ e110 Altra PCI Express Root Complex B
+# RCB port 0
+ e111 Altra PCI Express Root Port b0
+# RCB port 1
+ e112 Altra PCI Express Root Port b1
+# RCB port 2
+ e113 Altra PCI Express Root Port b2
+# RCB port 3
+ e114 Altra PCI Express Root Port b3
+# RCB port 4
+ e115 Altra PCI Express Root Port b4
+# RCB port 5
+ e116 Altra PCI Express Root Port b5
+# RCB port 6
+ e117 Altra PCI Express Root Port b6
+# RCB port 7
+ e118 Altra PCI Express Root Port b7
1df3 Ethernity Networks
0201 ACE-NIC40 Programmable Network Accelerator
1df3 0001 ENA1040
0002 T11 [CloudBlazer]
0003 T10s [CloudBlazer]
8011 I10 [CloudBlazer]
+ 8012 I10L [CloudBlazer]
# nee Thinci, Inc
1e38 Blaize, Inc
0102 Xplorer X1600
1601 NVMe SSD Controller MAP1601
1e4c GSI Technology
# Associative Processing Unit (APU)
- 0010 APU [Leda-G]
+ 0010 APU [Leda]
1e4c 0120 SE120
1e57 Beijing Panyi Technology Co., Ltd
0100 The device has already been deleted.
0000 0100 PY8800 64GB Accelerator
+1e60 Hailo Technologies Ltd.
+ 2864 Hailo-8 AI Processor
1e6b Axiado Corp.
1e7b Dataland
1e7c Brainchip Inc
# aka SED Systems
1e94 Calian SED
1e95 Solid State Storage Technology Corporation
+1ea0 Tencent Technology (Shenzhen) Company Limited
+ 2a16 Cloud Intelligent Inference Controller
1eab Hefei DATANG Storage Technology Co.,LTD.
+ 300a NVMe SSD Controller 300A
+ 300b NVMe SSD Controller 300B
1eae XFX Limited
1eb1 VeriSilicon Inc
1001 Video Accelerator
+1ed8 Digiteq Automotive
+ 0101 FG4 PCIe Frame Grabber
+1ed9 Myrtle.ai
+1ee9 SUSE LLC
# nee Tumsan Oy
1fc0 Ascom (Finland) Oy
0300 E2200 Dual E1/Rawpipe Card
2348 Racore
2010 8142 100VG/AnyLAN
2646 Kingston Technology Company, Inc.
+ 0010 HyperX Predator PCIe AHCI SSD
2263 A2000 NVMe SSD
+ 5008 U-SNS8154P3 NVMe SSD
+ 500d OM3PDP3 NVMe SSD
270b Xantel Corporation
270f Chaintech Computer Co. Ltd
2711 AVID Technology Inc.
0100 2nd Generation Core Processor Family DRAM Controller
1028 04aa XPS 8300
1043 844d P8P67/P8H67 Series Motherboard
+ 8086 200d DH61CR motherboard
0101 Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port
1028 04b2 Vostro 3350
106b 00dc MacBookPro8,2 [Core i7, 15", 2011]
1043 844d P8B WS Motherboard
0172 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
0176 3rd Gen Core processor Graphics Controller
+ 0201 Arctic Sound
0284 Comet Lake PCH-LP LPC Premium Controller/eSPI Controller
02a3 Comet Lake PCH-LP SMBus Host Controller
02a4 Comet Lake SPI (flash) Controller
02a6 Comet Lake North Peak
+ 02b0 Comet Lake PCI Express Root Port #9
+ 02b1 Comet Lake PCI Express Root Port #10
+ 02b3 Comet Lake PCI Express Root Port #12
+ 02b4 Comet Lake PCI Express Root Port #13
+ 02b8 Comet Lake PCI Express Root Port #1
+ 02bc Comet Lake PCI Express Root Port #5
+ 02c5 Comet Lake Serial IO I2C Host Controller
02c8 Comet Lake PCH-LP cAVS
02d3 Comet Lake SATA AHCI Controller
02e0 Comet Lake Management Engine Interface
02e8 Serial IO I2C Host Controller
02e9 Comet Lake Serial IO I2C Host Controller
+ 02ea Comet Lake PCH-LP LPSS: I2C Controller #2
02ed Comet Lake PCH-LP USB 3.1 xHCI Host Controller
02ef Comet Lake PCH-LP Shared SRAM
02f0 Comet Lake PCH-LP CNVi WiFi
040a Xeon E3-1200 v3 Processor Integrated Graphics Controller
0412 Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller
103c 1998 EliteDesk 800 G1
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
0416 4th Gen Core Processor Integrated Graphics Controller
17aa 220e ThinkPad T440p
1028 1fe9 Express Flash NVMe 4.0TB HHHL AIC (P4600)
0b26 Thunderbolt 4 Bridge [Goshen Ridge 2020]
0b27 Thunderbolt 4 USB Controller [Goshen Ridge 2020]
- 0b60 NVMe DC SSD [3DNAND, Beta Rock Controller]
+ 0b60 NVMe DC SSD [3DNAND, Sentinel Rock Controller]
1028 2060 NVMe SED MU U.2 1.6TB (P5600)
1028 2061 NVMe SED MU U.2 3.2TB (P5600)
1028 2062 NVMe SED MU U.2 6.4TB (P5600)
1028 2102 NVMe RI U.2 1.92TB (P5500)
1028 2103 NVMe RI U.2 3.84TB (P5500)
1028 2104 NVMe RI U.2 7.68TB (P5500)
+ 8086 8008 NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P5510)
0be0 Atom Processor D2xxx/N2xxx Integrated Graphics Controller
0be1 Atom Processor D2xxx/N2xxx Integrated Graphics Controller
105b 0d7c D270S/D250S Motherboard
0bf7 Atom Processor D2xxx/N2xxx DRAM Controller
0c00 4th Gen Core Processor DRAM Controller
103c 1998 EliteDesk 800 G1
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
0c01 Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller
0c04 Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
8086 4532 Desktop Board D815EEA2/D815EFV
8086 4541 D815EEA Motherboard
8086 4557 D815EGEW Mainboard
+ 1136 Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
+ 1137 Thunderbolt 4 NHI [Maple Ridge 4C 2020]
+ 1138 Thunderbolt 4 USB Controller [Maple Ridge 4C 2020]
1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller
8086 1161 82806AA PCI64 Hub APIC
1162 Xscale 80200 Big Endian Companion Chip
1503 82579V Gigabit Network Connection
1043 849c P8P67 Deluxe Motherboard
10cf 161c LIFEBOOK E752
+ 8086 200d DH61CR motherboard
1507 Ethernet Express Module X520-P2
1508 82598EB Gigabit BX Network Connection
1509 82580 Gigabit Network Connection
156f Ethernet Connection I219-LM
1028 06dc Latitude E7470
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
1570 Ethernet Connection I219-V
1571 Ethernet Virtual Function 700 Series
1572 Ethernet Controller X710 for 10GbE SFP+
17aa 0000 ThinkServer X710 AnyFabric for 10GbE SFP+
17aa 4001 ThinkServer X710-4 AnyFabric for 10GbE SFP+
17aa 4002 ThinkServer X710-2 AnyFabric for 10GbE SFP+
+ 193d 1020 NIC-ETH561F-sL-4x10G
+ 193d 1021 NIC-ETH561F-sL-2x10G
19e5 d11c Ethernet 2-port X710 10Gb SFP+ Adapter SP330
1bd4 0056 Ethernet Network Adapter X710-BM2 for OCP NIC 3.0
8086 0000 Ethernet Converged Network Adapter X710
1577 DSL6540 Thunderbolt 3 NHI [Alpine Ridge 4C 2015]
1578 DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
157b I210 Gigabit Network Connection
+ ea50 cc10 RXi2-BP
157c I210 Gigabit Backplane Connection
157d DSL5110 Thunderbolt 2 NHI (Low Power) [Win Ridge 2C 2014]
157e DSL5110 Thunderbolt 2 Bridge (Low Power) [Win Ridge 2C 2014]
1059 0170 RD-01213 10GbE interface
1590 0000 Ethernet 2-port 563i Adapter
1590 00f8 Ethernet 2-port 563i Adapter
+ 193d 100e NIC-ETH561i-Mb-4x10G
8086 0000 Ethernet Converged Network Adapter XL710-Q2
1583 Ethernet Controller XL710 for 40GbE QSFP+
1028 0000 Ethernet 40G 2P XL710 QSFP+ rNDC
1591 Ethernet Controller E810-C for backplane
1592 Ethernet Controller E810-C for QSFP
1137 02bf E810CQDA2 2x100 GbE QSFP28 PCIe NIC
+ 8086 0001 Ethernet Network Adapter E810-C-Q1
8086 0002 Ethernet Network Adapter E810-C-Q2
8086 0004 Ethernet Network Adapter E810-C-Q2
8086 0005 Ethernet Network Adapter E810-C-Q1 for OCP3.0
8086 000a Ethernet Network Adapter E810-C-Q1 for OCP
8086 000b Ethernet 100G 2P E810-C Adapter
8086 000c Ethernet 100G 2P E810-C OCP
+ 8086 000d Ethernet Network Adapter E810-L-Q2 for OCP 3.0
1593 Ethernet Controller E810-C for SFP
1137 02c3 E810XXVDA4 4x25/10 GbE SFP28 PCIe NIC
8086 0002 Ethernet Network Adapter E810-L-2
1137 0000 X710TLG GbE RJ45 PCIe NIC
1137 02c1 X710T2LG 2x10 GbE RJ45 PCIe NIC
1137 02c2 X710T4LG 4x10 GbE RJ45 PCIe NIC
+ 1137 02d9 Ethernet Network Adapter X710-T2L OCP 3.0
+ 1137 02da Ethernet Network Adapter X710-T4L OCP 3.0
8086 0000 Ethernet Network Adapter X710-TL
8086 0001 Ethernet Network Adapter X710-T4L
8086 0002 Ethernet Network Adapter X710-T4L
18a0 C4xxx Series QAT
18a1 C4XXX Series QAT Virtual Function
1900 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
- 1901 6th-9th Gen Core Processor PCIe Controller (x16)
+ 1901 6th-10th Gen Core Processor PCIe Controller (x16)
1902 HD Graphics 510
1903 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
1028 06e4 XPS 15 9550
+ 1028 06e6 Latitude 11 5175 2-in-1
103c 825b OMEN-17-w001nv
17aa 225d ThinkPad T480
1904 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1028 06dc Latitude E7470
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
17aa 382a B51-80 Laptop
1905 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x8)
1906 HD Graphics 510
1909 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x4)
190c Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
190f Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1910 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1028 06e4 XPS 15 9550
1028 06dc Latitude E7470
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
1918 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1919 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
191b HD Graphics 530
1028 06e4 XPS 15 9550
103c 825b OMEN-17-w001nv
191d HD Graphics P530
191e HD Graphics 515
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
191f Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers
1921 HD Graphics 520
1926 Iris Graphics 540
1c02 6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller
1028 04aa XPS 8300
1043 844d P8 series motherboard
+ 8086 200d DH61CR motherboard
8086 7270 Server Board S1200BT Family
1c03 6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller
1028 04a3 Precision M4600
17aa 21cf ThinkPad T520
# Realtek ALC888 audio codec
8086 2008 DQ67SW board
+ 8086 200d DH61CR motherboard
8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011]
1c22 6 Series/C200 Series Chipset Family SMBus Controller
1028 04a3 Precision M4600
1028 04da Vostro 3750
1043 844d P8 series motherboard
17aa 21cf ThinkPad T520
+ 8086 200d DH61CR motherboard
8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2
1c24 6 Series/C200 Series Chipset Family Thermal Management Controller
1c25 6 Series/C200 Series Chipset Family DMI to PCI Bridge
1028 04da Vostro 3750
1043 844d P8 series motherboard
17aa 21cf ThinkPad T520
+ 8086 200d DH61CR motherboard
8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2
1c27 6 Series/C200 Series Chipset Family USB Universal Host Controller #1
8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011]
1028 04da Vostro 3750
1043 844d P8 series motherboard
17aa 21cf ThinkPad T520
+ 8086 200d DH61CR motherboard
8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2
1c33 6 Series/C200 Series Chipset Family LAN Controller
1c35 6 Series/C200 Series Chipset Family VECI Controller
1028 04da Vostro 3750
1043 844d P8 series motherboard
17aa 21cf ThinkPad T520
+ 8086 200d DH61CR motherboard
8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011]
1c3b 6 Series/C200 Series Chipset Family MEI Controller #2
1c3c 6 Series/C200 Series Chipset Family IDE-r Controller
1c5a Upgraded Q67 Express Chipset LPC Controller
1c5b 6 Series/C200 Series Chipset Family LPC Controller
1c5c H61 Express Chipset LPC Controller
+ 8086 200d DH61CR motherboard
1c5d 6 Series/C200 Series Chipset Family LPC Controller
1c5e 6 Series/C200 Series Chipset Family LPC Controller
1c5f 6 Series/C200 Series Chipset Family LPC Controller
147b 0507 TH7II-RAID
8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
+ 8086 4d44 D850EMV2 motherboard
8086 5744 S845WD1-E mainboard
2443 82801BA/BAM SMBus Controller
1014 01c6 Netvista A40/A40p
147b 0507 TH7II-RAID
8086 4557 D815EGEW Mainboard
8086 4656 Desktop Board D815EFV
+ 8086 4d44 D850EMV2 motherboard
2446 82801BA/BAM AC'97 Modem Controller
1025 1016 Travelmate 612 TX
104d 80df Vaio PCG-FX403
15d9 3280 Supermicro P4SBE Mainboard
8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
+ 8086 4d44 D850EMV2 motherboard
8086 5744 S845WD1-E mainboard
244c 82801BAM ISA Bridge (LPC)
244e 82801 PCI Bridge
103c 0934 Compaq nw8240/nx8220
103c 0944 Compaq nc6220 Notebook PC
103c 099c NX6110/NC6120
+ 1043 82d9 Asus Eee PC 900
104d 81b7 Vaio VGN-S3XP
a304 81b7 Vaio VGN-S3XP
e4bf 0ccd CCD-CALYPSO
1028 022f Inspiron 1525
103c 30c0 Compaq 6710b
103c 30c1 Compaq 6910p
+ 103c 30c5 Compaq 8510p
103c 30cc Pavilion dv6700
103c 30d9 Presario C700
1043 1017 X58LE
2a41 Mobile 4 Series Chipset PCI Express Graphics Port
e4bf cc4d CCM-BOOGIE
2a42 Mobile 4 Series Chipset Integrated Graphics Controller
+ 1028 02aa Dell Inspiron 1545
17aa 2112 ThinkPad T400
e4bf cc4d CCM-BOOGIE
2a43 Mobile 4 Series Chipset Integrated Graphics Controller
8086 4210 Dual Band Wireless AC 3165
3166 Dual Band Wireless-AC 3165 Plus Bluetooth
8086 4210 Dual Band Wireless-AC 3165
- 3184 UHD Graphics 605
- 3185 UHD Graphics 605
+ 3184 GeminiLake [UHD Graphics 605]
+ 3185 GeminiLake [UHD Graphics 600]
318c Celeron/Pentium Silver Processor Dynamic Platform and Thermal Framework Processor Participant
318e Celeron/Pentium Silver Processor NorthPeak
3190 Celeron/Pentium Silver Processor Gaussian Mixture Model
17aa 380b V130-15IGM Laptop (Lenovo) - Type 81HL
319a Celeron/Pentium Silver Processor Trusted Execution Engine Interface
31a2 Celeron/Pentium Silver Processor Integrated Sensor Solution
+ 31a8 Celeron/Pentium Silver Processor USB 3.0 xHCI Controller
+ 1849 31a8 Celeron/Pentium Silver Processor USB 3.0 xHCI Controller
31ac Celeron/Pentium Silver Processor Serial IO I2C Host Controller
31ae Celeron/Pentium Silver Processor Serial IO I2C Host Controller
31bc Celeron/Pentium Silver Processor Serial IO UART Host Controller
31da Gemini Lake PCI Express Root Port
31db Gemini Lake PCI Express Root Port
31dc AC 1550i Wireless
+ 31e3 Celeron/Pentium Silver Processor SATA Controller
+ 31e8 Celeron/Pentium Silver Processor LPC Controller
31ee Celeron/Pentium Silver Processor Serial IO UART Host Controller
31f0 Gemini Lake Host Bridge
3200 GD31244 PCI-X SATA HBA
34aa Ice Lake-LP Serial IO SPI Controller #0
34ab Ice Lake-LP Serial IO SPI Controller #1
34b0 Ice Lake-LP PCI Express Root Port #9
+ 34b7 Ice Lake-LP PCI Express Root Port #16
34bc Ice Lake-LP PCI Express Root Port #5
34c5 Ice Lake-LP Serial IO I2c Controller #4
34c6 Ice Lake-LP Serial IO I2c Controller #5
- 34c8 Smart Sound Technology Audio Controller
+ 34c8 Ice Lake-LP Smart Sound Technology Audio Controller
34d3 Ice Lake-LP SATA Controller [AHCI mode]
- 34e0 Management Engine Interface
+ 34e0 Ice Lake-LP Management Engine
34e8 Ice Lake-LP Serial IO I2C Controller #0
34e9 Ice Lake-LP Serial IO I2C Controller #1
34ea Ice Lake-LP Serial IO I2C Controller #2
34eb Ice Lake-LP Serial IO I2C Controller #3
34ed Ice Lake-LP USB 3.1 xHCI Host Controller
+ 34ef Ice Lake-LP DRAM Controller
34f0 Killer Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)
34f8 Ice Lake-LP SD Controller
+ 34fc Ice Lake-LP Integrated Sensor Solution
3500 6311ESB/6321ESB PCI Express Upstream Port
103c 31fe ProLiant DL140 G3
15d9 9680 X7DBN Motherboard
3e81 8th Gen Core Processor PCIe Controller (x16)
3e85 8th Gen Core Processor PCIe Controller (x8)
3e89 8th Gen Core Processor PCIe Controller (x4)
- 3e91 8th Gen Core Processor Gaussian Mixture Model
- 3e92 UHD Graphics 630 (Desktop)
+ 3e90 CoffeeLake-S GT1 [UHD Graphics 610]
+ 3e91 CoffeeLake-S GT2 [UHD Graphics 630]
+ 3e92 CometLake-S GT2 [UHD Graphics 630]
1028 0869 Vostro 3470
- 3e93 UHD Graphics 610
- 3e96 HD Graphics P630
- 3e98 UHD Graphics 630 (Desktop 9 Series)
- 3e9b UHD Graphics 630 (Mobile)
- 3ea0 UHD Graphics 620 (Whiskey Lake)
+ 3e93 CoffeeLake-S GT1 [UHD Graphics 610]
+ 3e96 CoffeeLake-S GT2 [UHD Graphics P630]
+ 3e98 CoffeeLake-S GT2 [UHD Graphics 630]
+ 3e9b CoffeeLake-H GT2 [UHD Graphics 630]
+ 3ea0 WhiskeyLake-U GT2 [UHD Graphics 620]
1028 089e Inspiron 5482
- 3ea5 Iris Plus Graphics 655
+ 3ea5 CoffeeLake-U GT3e [Iris Plus Graphics 655]
3ec2 8th Gen Core Processor Host Bridge/DRAM Registers
1028 0869 Vostro 3470
1043 8694 PRIME H310M-D
4032 5400 Chipset IOxAPIC
4035 5400 Chipset FBD Registers
4036 5400 Chipset FBD Registers
+ 4041 NVMe Datacenter SSD [Optane]
4100 Moorestown Graphics and Video
4108 Atom Processor E6xx Integrated Graphics Controller
4109 Atom Processor E6xx Integrated Graphics Controller
4115 Atom Processor E6xx PCI Host Bridge #2
4116 Atom Processor E6xx PCI Host Bridge #3
4117 Atom Processor E6xx PCI Host Bridge #4
+ 4140 NVMe Datacenter SSD [Optane]
+ 1028 2134 NVMe Datacenter SSD [Optane] SED 400GB 2.5" U.2 (P5800X)
+ 1028 2135 NVMe Datacenter SSD [Optane] SED 800GB 2.5" U.2 (P5800X)
+ 1028 2136 NVMe Datacenter SSD [Optane] SED 1.6GB 2.5" U.2 (P5800X)
+ 1028 2137 NVMe Datacenter SSD [Optane] 400GB 2.5" U.2 (P5800X)
+ 1028 2138 NVMe Datacenter SSD [Optane] 800GB 2.5" U.2 (P5800X)
+ 1028 2139 NVMe Datacenter SSD [Optane] 1.6TB 2.5" U.2 (P5800X)
4220 PRO/Wireless 2200BG [Calexico2] Network Connection
103c 0934 Compaq nw8240/nx8220
103c 12f6 nc6120/nc6220/nw8240/nx8220
8086 1316 WiMAX/WiFi Link 5150 ABG
444e Turbo Memory Controller
467f Volume Management Device NVMe RAID Controller
+ 4680 AlderLake-S GT1
+ 46a0 AlderLake-P GT2
+ 4905 DG1 [Iris Xe MAX Graphics]
+ 4906 DG1 [Iris Xe Pod]
+ 4907 SG1 [Server GPU SG-18M]
+ 4908 DG1 [Iris Xe Graphics]
4c3d Volume Management Device NVMe RAID Controller
+ 4f80 DG2
+ 4f81 DG2
+ 4f82 DG2
5001 LE80578
5002 LE80578 Graphics Processor Unit
5009 LE80578 Video Display Controller
1993 0ded mGuard-PCI AV#2
1993 0dee mGuard-PCI AV#1
1993 0def mGuard-PCI AV#0
+ 8603 Ice Lake-LP Dynamic Tuning Processor Participant
87c0 UHD Graphics 617
8800 Platform Controller Hub EG20T PCI Express Port
8801 Platform Controller Hub EG20T Packet Hub
8818 Platform Controller Hub EG20T Controller Area Network (CAN) Controller
8819 Platform Controller Hub EG20T IEEE 1588 Hardware Assist
8a0d Ice Lake Thunderbolt 3 NHI #1
+ 8a12 Ice Lake-LP Processor Host Bridge/DRAM Registers
8a13 Ice Lake Thunderbolt 3 USB Controller
8a17 Ice Lake Thunderbolt 3 NHI #0
+ 8a19 Image Signal Processor
8a1d Ice Lake Thunderbolt 3 PCI Express Root Port #0
8a1f Ice Lake Thunderbolt 3 PCI Express Root Port #1
8a21 Ice Lake Thunderbolt 3 PCI Express Root Port #2
8c01 8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile
8c02 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
103c 1998 EliteDesk 800 G1
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
8c03 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
103c 1909 ZBook 15
103c 1998 EliteDesk 800 G1
1043 8534 ASUS H81I-PLUS
17aa 220e ThinkPad T440p
+ 17aa 3098 ThinkCentre E73
8c11 8 Series/C220 Series Chipset Family PCI Express Root Port #1
8c12 8 Series/C220 Series Chipset Family PCI Express Root Port #2
103c 1998 EliteDesk 800 G1
8c18 8 Series/C220 Series Chipset Family PCI Express Root Port #5
8c19 8 Series/C220 Series Chipset Family PCI Express Root Port #5
8c1a 8 Series/C220 Series Chipset Family PCI Express Root Port #6
+ 17aa 3098 ThinkCentre E73
8c1b 8 Series/C220 Series Chipset Family PCI Express Root Port #6
8c1c 8 Series/C220 Series Chipset Family PCI Express Root Port #7
8c1d 8 Series/C220 Series Chipset Family PCI Express Root Port #7
103c 1909 ZBook 15
103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
8c23 8 Series Chipset Family CHAP Counters
8c24 8 Series Chipset Family Thermal Management Controller
103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 2210 ThinkPad T540p
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
2210 17aa ThinkPad T540p
8c2d 8 Series/C220 Series Chipset Family USB EHCI #2
103c 1909 ZBook 15
103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
8c31 8 Series/C220 Series Chipset Family USB xHCI
103c 1909 ZBook 15
103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
8c33 8 Series/C220 Series Chipset Family LAN Controller
8c34 8 Series/C220 Series Chipset Family NAND Controller
103c 1909 ZBook 15
103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
+ 17aa 3098 ThinkCentre E73
17aa 309f ThinkCentre M83
8c3b 8 Series/C220 Series Chipset Family MEI Controller #2
8c3c 8 Series/C220 Series Chipset Family IDE-r Controller
8c5a 8 Series/C220 Series Chipset Family LPC Controller
8c5b 8 Series/C220 Series Chipset Family LPC Controller
8c5c H81 Express LPC Controller
+ 17aa 3098 ThinkCentre E73
8c5d 8 Series/C220 Series Chipset Family LPC Controller
8c5e 8 Series/C220 Series Chipset Family LPC Controller
8c5f 8 Series/C220 Series Chipset Family LPC Controller
9622 Integrated RAID
9641 Integrated RAID
96a1 Integrated RAID
+ 9a03 TigerLake-LP Dynamic Tuning Processor Participant
9a09 11th Gen Core Processor PCIe Controller
9a0b Volume Management Device NVMe RAID Controller
- 9a13 Tiger Lake-LP Thunderbolt USB Controller
+ 9a0d Tiger Lake-LP Telemetry Aggregator
+ 9a13 Tiger Lake-LP Thunderbolt 4 USB Controller
9a14 11th Gen Core Processor Host Bridge/DRAM Registers
- 9a17 Tiger Lake-H Thunderbolt USB Controller
- 9a1b Tiger Lake-LP Thunderbolt NHI #0
- 9a1d Tiger Lake-LP Thunderbolt NHI #1
- 9a1f Tiger Lake-H Thunderbolt NHI #0
- 9a21 Tiger Lake-H Thunderbolt NHI #1
- 9a23 Tiger Lake-LP Thunderbolt PCI Express Root Port #0
- 9a25 Tiger Lake-LP Thunderbolt PCI Express Root Port #1
- 9a27 Tiger Lake-LP Thunderbolt PCI Express Root Port #2
- 9a29 Tiger Lake-LP Thunderbolt PCI Express Root Port #3
- 9a2b Tiger Lake-H Thunderbolt PCI Express Root Port #0
- 9a2d Tiger Lake-H Thunderbolt PCI Express Root Port #1
- 9a2f Tiger Lake-H Thunderbolt PCI Express Root Port #2
- 9a31 Tiger Lake-H Thunderbolt PCI Express Root Port #3
+ 9a17 Tiger Lake-H Thunderbolt 4 USB Controller
+ 9a1b Tiger Lake-LP Thunderbolt 4 NHI #0
+ 9a1d Tiger Lake-LP Thunderbolt 4 NHI #1
+ 9a1f Tiger Lake-H Thunderbolt 4 NHI #0
+ 9a21 Tiger Lake-H Thunderbolt 4 NHI #1
+ 9a23 Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #0
+ 9a25 Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #1
+ 9a27 Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #2
+ 9a29 Tiger Lake-LP Thunderbolt 4 PCI Express Root Port #3
+ 9a2b Tiger Lake-H Thunderbolt 4 PCI Express Root Port #0
+ 9a2d Tiger Lake-H Thunderbolt 4 PCI Express Root Port #1
+ 9a2f Tiger Lake-H Thunderbolt 4 PCI Express Root Port #2
+ 9a31 Tiger Lake-H Thunderbolt 4 PCI Express Root Port #3
9a33 Tiger Lake Trace Hub
- 9a49 Iris Xe Graphics
- 9b41 UHD Graphics
+ 9a49 TigerLake GT2 [Iris Xe Graphics]
+ 9b41 CometLake-U GT2 [UHD Graphics]
9b44 10th Gen Core Processor Host Bridge/DRAM Registers
+ 9b53 Comet Lake-S 6c Host Bridge/DRAM Controller
9b54 10th Gen Core Processor Host Bridge/DRAM Registers
9b61 Comet Lake-U v1 4c Host Bridge/DRAM Controller
+ 9b63 10th Gen Core Processor Host Bridge/DRAM Registers
9b64 10th Gen Core Processor Host Bridge/DRAM Registers
- 9bc4 UHD Graphics
- 9bc8 UHD Graphics 630
+ 9bc4 CometLake-H GT2 [UHD Graphics]
+ 9bc5 CometLake-S GT2 [UHD Graphics 630]
+ 9bc8 CometLake-S GT2 [UHD Graphics 630]
9c00 8 Series SATA Controller 1 [IDE mode]
9c01 8 Series SATA Controller 1 [IDE mode]
9c02 8 Series SATA Controller 1 [AHCI mode]
9d03 Sunrise Point-LP SATA Controller [AHCI mode]
1025 115f Acer Aspire E5-575G
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 225d ThinkPad T480
9d16 Sunrise Point-LP PCI Express Root Port #7
9d17 Sunrise Point-LP PCI Express Root Port #8
9d18 Sunrise Point-LP PCI Express Root Port #9
+ 17aa 2247 ThinkPad T570
17aa 382a B51-80 Laptop
9d19 Sunrise Point-LP PCI Express Root Port #10
9d1a Sunrise Point-LP PCI Express Root Port #11
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
17aa 224f ThinkPad X1 Carbon 5th Gen
17aa 225d ThinkPad T480
17aa 382a B51-80 Laptop
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 2247 ThinkPad T570
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 2247 ThinkPad T570
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 2247 ThinkPad T570
17aa 382a B51-80 Laptop
9d32 CSI-2 Host Controller
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
9d35 Sunrise Point-LP Integrated Sensor Hub
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
9d3a Sunrise Point-LP CSME HECI #1
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 2247 ThinkPad T570
17aa 382a B51-80 Laptop
9d3d Sunrise Point-LP Active Management Technology - SOL
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
9d43 Sunrise Point-LP LPC Controller
17aa 382a B51-80 Laptop
9d46 LPC/eSPI Controller
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
9d48 Sunrise Point-LP LPC Controller
1028 06dc Latitude E7470
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
9d4e Sunrise Point LPC Controller/eSPI Controller
17aa 225d ThinkPad T480
9d50 Sunrise Point LPC Controller
9d60 Sunrise Point-LP Serial IO I2C Controller #0
1025 115f Acer Aspire E5-575G
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
17aa 225d ThinkPad T480
8086 9d60 100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C]
9d61 Sunrise Point-LP Serial IO I2C Controller #1
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
9d62 Sunrise Point-LP Serial IO I2C Controller #2
1028 06d6 Latitude 7275 tablet
+ 1028 06e6 Latitude 11 5175 2-in-1
9d63 Sunrise Point-LP Serial IO I2C Controller #3
9d64 Sunrise Point-LP Serial IO I2C Controller #4
9d65 Sunrise Point-LP Serial IO I2C Controller #5
9d70 Sunrise Point-LP HD Audio
1028 06d6 Latitude 7275 tablet
1028 06dc Latitude E7470
+ 1028 06e6 Latitude 11 5175 2-in-1
1028 06f3 Latitude 3570
103c 8079 EliteBook 840 G3
+ 17aa 2247 ThinkPad T570
17aa 382a B51-80 Laptop
9d71 Sunrise Point-LP HD Audio
1025 1094 Acer Aspire E5-575G
a0a9 Tiger Lake-LP Serial IO UART Controller #1
a0ab Tiger Lake-LP Serial IO SPI Controller #1
a0b0 Tiger Lake-LP PCI Express Root Port #9
+ a0bd Tigerlake PCH-LP PCI Express Root Port #6
a0bf Tiger Lake-LP PCI Express Root Port #8
a0c5 Tiger Lake-LP Serial IO I2C Controller #4
a0c6 Tiger Lake-LP Serial IO I2C Controller #5
a379 Cannon Lake PCH Thermal Controller
1028 0869 Vostro 3470
a382 400 Series Chipset Family SATA AHCI Controller
+ a3a1 Memory controller
a3a3 Comet Lake PCH-V SMBus Host Controller
+ a3af Comet Lake PCH-V USB Controller
a3b1 Comet Lake PCH-V Thermal Subsystem
a620 6400/6402 Advanced Memory Buffer (AMB)
abc0 Omni-Path Fabric Switch Silicon 100 Series
8088 Beijing Wangxun Technology Co., Ltd.
0101 WX1860A2 Gigabit Ethernet Controller
8088 0201 Dual-Port Ethernet Network Adaptor SF200T
+ 8088 4201 Dual-Port Ethernet Network Adaptor SF200T (WOL)
+ 8088 8201 Dual-Port Ethernet Network Adaptor SF200T (NCSI)
+ 8088 c201 Dual-Port Ethernet Network Adaptor SF200T (WOL, NCSI)
0102 WX1860A2S Gigabit Ethernet Controller
8088 0210 Dual-Port Ethernet Network Adaptor SF200T-S
0103 WX1860A4 Gigabit Ethernet Controller
8088 0401 Qual-Port Ethernet Network Adaptor SF400T
8088 0440 Qual-Port Ethernet Network Adaptor SF400-OCP
+ 8088 4103 Quad-Port Ethernet Network Adaptor SF400T (WOL)
+ 8088 8103 Quad-Port Ethernet Network Adaptor SF400T (NCSI)
+ 8088 c103 Quad-Port Ethernet Network Adaptor SF400T (WOL, NCSI)
0104 WX1860A4S Gigabit Ethernet Controller
8088 0410 Qual-Port Ethernet Network Adaptor SF400T-S
0105 WX1860AL2 Gigabit Ethernet Controller
8088 0202 Dual-Port Ethernet Network Adaptor SF200HT
+ 8088 4202 Dual-Port Ethernet Network Adaptor SF200HT (WOL)
+ 8088 8202 Dual-Port Ethernet Network Adaptor SF200HT (NCSI)
+ 8088 c202 Dual-Port Ethernet Network Adaptor SF200HT (WOL, NCSI)
0106 WX1860AL2S Gigabit Ethernet Controller
8088 0220 Dual-Port Ethernet Network Adaptor SF200HT-S
0107 WX1860AL4 Gigabit Ethernet Controller
8088 0402 Qual-Port Ethernet Network Adaptor SF400HT
+ 8088 4402 Quad-Port Ethernet Network Adaptor SF400HT (WOL)
+ 8088 8402 Quad-Port Ethernet Network Adaptor SF400HT (NCSI)
+ 8088 c402 Quad-Port Ethernet Network Adaptor SF400HT (WOL, NCSI)
0108 WX1860AL4S Gigabit Ethernet Controller
8088 0420 Qual-Port Ethernet Network Adaptor SF400HT-S
+ 0109 WX1860-LC Gigabit Ethernet Controller
+ 010a WX1860A1 Gigabit Ethernet Controller
+# add new device ID
+ 010b WX1860AL1 Gigabit Ethernet Controller
+ 8088 0102 Single-Port Ethernet Network Adaptor SF100HT
+ 8088 4102 Single-Port Ethernet Network Adaptor SF100HT (WOL)
+ 8088 8102 Single-Port Ethernet Network Adaptor SF100HT (NCSI)
+ 8088 c102 Single-Port Ethernet Network Adaptor SF100HT (WOL, NCSI)
+ 0111 WX1860A2 Ethernet Controller Virtual Function
+ 0113 WX1860A4 Ethernet Controller Virtual Function
+ 0115 WX1860AL2 Ethernet Controller Virtual Function
+ 0117 WX1860AL4 Ethernet Controller Virtual Function
+ 0119 WX1860-LC Gigabit Ethernet Controller Virtual Function
+ 011a WX1860A1 Gigabit Ethernet Controller Virtual Function
+ 011b WX1860AL1 Gigabit Ethernet Controller Virtual Function
+ 1000 Ethernet Controller RP1000 Virtual Function for 10GbE SFP+
1001 Ethernet Controller RP1000 for 10GbE SFP+
8088 0000 Ethernet Network Adaptor RP1000 for 10GbE SFP+
+ 2000 Ethernet Controller RP2000 Virtual Function for 10GbE SFP+
2001 Ethernet Controller RP2000 for 10GbE SFP+
8088 2000 Ethernet Network Adaptor RP2000 for 10GbE SFP+
80ee InnoTek Systemberatung GmbH
4021 MT camera
e000 Winbond
e000 W89C940
-e159 Tiger Jet Network Inc.
+e159 Tiger Jet Network Inc. / ICP DAS
0001 Tiger3XX Modem/ISDN interface
0059 0001 128k ISDN-S/T Adapter
0059 0003 128k ISDN-U Adapter
0046 PCI-766 Analog Output Card
0052 PCI-703 Analog I/O Card
0800 PCI-800 Digital I/O Card
+ea50 Emerson Automation Solutions
# The main chip of all these devices is by Xilinx -> It could also be a Xilinx ID.
ea60 RME
9896 Digi32
<tr class="odd"><td>MILCOTS</td><td>MLC</td><td>07/15/2020</td> </tr>
<tr class="even"><td>NZXT (PNP same EDID)_</td><td>NXT</td><td>07/15/2020</td> </tr>
<tr class="odd"><td>Unicompute Technology Co., Ltd.</td><td>UTC</td><td>10/19/2020</td> </tr>
+ <tr class="even"><td>TECHNOGYM S.p.A.</td><td>TGW</td><td>01/08/2021</td> </tr>
</tbody>
</table>
</body>
# The latest version can be obtained from
# http://www.linux-usb.org/usb.ids
#
-# Version: 2020.08.26
-# Date: 2020-08-26 20:34:09
+# Version: 2021.01.29
+# Date: 2021-01-29 20:34:11
#
# Vendors, devices and interfaces. Please keep sorted.
0155 5800 XpressMusic (Multimedia mode)
0156 5800 XpressMusic (Storage mode)
0157 5800 XpressMusic (Imaging mode)
+ 0189 N810 Internet Tablet WiMAX
0199 6700 Classic (msc)
019a 6700 Classic (PC Suite)
019b 6700 Classic (mtp)
01b1 6303 classic Phone (Mass storage mode)
01b2 6303 classic Phone (Printing and media mode)
01c7 N900 (Storage Mode)
- 01c8 N900 (PC-Suite Mode)
+ 01c8 N900/N950 (PC-Suite Mode)
0228 5530 XpressMusic
023a 6730 Classic
026a N97 (mass storage)
03c1 C7-00 (Media transfer mode)
03c2 Sim
03cd C7-00 (Nokia Suite mode)
- 03d1 N950
+ 03d1 N950 (Storage Mode)
+ 03d2 N950 (PC Suite mode)
0400 7600 Phone Parent
0401 6650 GSM Phone
0402 6255 Phone Parent
0423 6682 Phone Parent
0428 6230i Modem
0429 6230i MultiMedia Card
- 0431 770 Internet Tablet
+ 0431 770/N800 Internet Tablet
0432 N90 Phone Parent
0435 E70 (IP Passthrough/RNDIS mode)
0436 E60 (IP Passthrough/RNDIS mode)
04f9 6300 (PC Suite mode)
0508 E65 (PC Suite mode)
0509 E65 (Storage mode)
- 0518 N9 Phone
+ 0518 N9 (Storage mode)
+ 0519 N9 (RNDIS/Ethernet mode)
+ 051a N9 (PC Suite mode)
054d C2-01
0600 Digital Pen SU-1B
0610 CS-15 (Internet Stick 3G modem)
05fc Harman
0001 Soundcraft Si Multi Digital Card
0010 Soundcraft Si MADI combo card
+ 0021 Soundcraft Signature 12 MTK
7849 Harman/Kardon SoundSticks
05fd InterAct, Inc.
0239 SV-239 HammerHead Digital
32b3 TEXA
d1a6 TXT Multihub
d1a7 TXT Multihub
+3310 MUDITA Sp. z o.o.
+ 0100 Pure
+ 0101 Pure tethering
3333 InLine
3333 2 port KVM switch model 60652K
3334 AEI
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="json" />
<varlistentry>
- <term><option>--no-legend</option></term>
+ <term><option>-1</option></term>
- <listitem><para>Do not print column headers.</para></listitem>
+ <listitem><para>Show information of the most recent core dump only, instead of listing all known core
+ dumps. (Equivalent to <option>--reverse -n 1</option></para></listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="no-pager" />
-
<varlistentry>
- <term><option>-1</option></term>
+ <term><option>-n</option> <replaceable>INT</replaceable></term>
- <listitem><para>Show information of a single core dump only, instead of listing
- all known core dumps.</para></listitem>
+ <listitem><para>Show at most the specified number of entries. The specified parameter must be an
+ integer greater or equal to 1.</para></listitem>
</varlistentry>
<varlistentry>
exit 1
fi
-# make sure the rules have been regenerated (in case man/update-man-rules was just run)
+# make sure the rules have been regenerated (in case update-man-rules was just run)
ninja -C "@BUILD_ROOT@" version.h
target="man/$1.html"
<term><option>-s</option></term>
<term><option>--signal=</option></term>
- <listitem><para>When used with <command>kill-session</command>
- or <command>kill-user</command>, choose which signal to send
- to selected processes. Must be one of the well known signal
- specifiers, such as <constant>SIGTERM</constant>,
- <constant>SIGINT</constant> or <constant>SIGSTOP</constant>.
- If omitted, defaults to
- <constant>SIGTERM</constant>.</para></listitem>
+ <listitem><para>When used with <command>kill-session</command> or <command>kill-user</command>,
+ choose which signal to send to selected processes. Must be one of the well known signal specifiers,
+ such as <constant>SIGTERM</constant>, <constant>SIGINT</constant> or <constant>SIGSTOP</constant>.
+ If omitted, defaults to <constant>SIGTERM</constant>.</para>
+
+ <para>The special value <literal>help</literal> will list the known values and the program will exit
+ immediately, and the special value <literal>list</literal> will list known values along with the
+ numerical signal numbers and the program will exit immediately.</para></listitem>
</varlistentry>
<varlistentry>
<option>all</option>.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><option>-s</option></term>
- <term><option>--signal=</option></term>
-
- <listitem><para>When used with <command>kill</command>, choose
- which signal to send to selected processes. Must be one of the
- well-known signal specifiers, such as
- <constant>SIGTERM</constant>, <constant>SIGINT</constant> or
- <constant>SIGSTOP</constant>. If omitted, defaults to
- <constant>SIGTERM</constant>.</para></listitem>
- </varlistentry>
+ <xi:include href="standard-options.xml" xpointer="signal" />
<varlistentry>
<term><option>--uid=</option></term>
exit 1
fi
-# make sure the rules have been regenerated (in case man/update-man-rules was just run)
+# make sure the rules have been regenerated (in case update-man-rules was just run)
ninja -C "@BUILD_ROOT@" version.h
page="$(echo "$1" | sed 's/\./\\./')"
############################################################
-if dbus_docs.length() > 0
- custom_target(
- 'update-dbus-docs',
- output : 'update-dbus-docs',
- command : [update_dbus_docs_py,
- '--build-dir=@0@'.format(project_build_root),
- '@INPUT@'],
- input : dbus_docs)
-
- if conf.get('BUILD_MODE') == 'BUILD_MODE_DEVELOPER'
- test('dbus-docs-fresh',
- update_dbus_docs_py,
- args : ['--build-dir=@0@'.format(project_build_root),
- '--test'] + dbus_docs)
- endif
-endif
-
-############################################################
-
-if git.found()
- custom_target(
- 'update-man-rules',
- output : 'update-man-rules',
- command : ['sh', '-c',
- 'cd @0@ && '.format(meson.build_root()) +
- 'python3 @0@/tools/update-man-rules.py $(git ls-files ":/man/*.xml") >t && '.format(project_source_root) +
- 'mv t @0@/rules/meson.build'.format(meson.current_source_dir())],
- depend_files : custom_entities_ent)
-endif
-
-############################################################
-
configure_file(
input : 'man.in',
output : 'man',
<term>carrier</term>
<listitem>
<para>the link has a carrier, or for bond or bridge master, all bonding or bridge slave
- network interfaces are enslaved to the master.</para>
+ network interfaces are enslaved to the master</para>
</listitem>
</varlistentry>
<varlistentry>
is false. Defaults to yes.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RouteTable=</varname></term>
+ <listitem><para>Defines the route table name. Takes a whitespace-separated list of the pairs of
+ route table name and number. The route table name and number in each pair are separated with a
+ colon, i.e., <literal><replaceable>name</replaceable>:<replaceable>number</replaceable></literal>.
+ The route table name must not be <literal>default</literal>, <literal>main</literal>, or
+ <literal>local</literal>, as these route table names are predefined with route table number 253,
+ 254, and 255, respectively. The route table number must be an integer in the range 1…4294967295.
+ This setting can be specified multiple times. If an empty string is specified, then the list
+ specified earlier are cleared. Defaults to unset.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
</varlistentry>
<varlistentry>
- <term><varname>DefaultMemoryPressureLimitPercent=</varname></term>
+ <term><varname>DefaultMemoryPressureLimit=</varname></term>
<listitem><para>Sets the limit for memory pressure on the unit's cgroup before <command>systemd-oomd</command>
- will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
+ will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimit=</varname>.
The memory pressure for this property represents the fraction of time in a 10 second window in which all tasks
in the cgroup were delayed. For each monitored cgroup, if the memory pressure on that cgroup exceeds the
- limit set for more than 30 seconds, <command>systemd-oomd</command> will act on eligible descendant cgroups,
+ limit set for longer than the duration set by <varname>DefaultMemoryPressureDurationSec=</varname>,
+ <command>systemd-oomd</command> will act on eligible descendant cgroups,
starting from the ones with the most reclaim activity to the least reclaim activity. Which cgroups are
monitored and what action gets taken depends on what the unit has configured for
<varname>ManagedOOMMemoryPressure=</varname>. Takes a percentage value between 0% and 100%, inclusive.
Defaults to 60%.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DefaultMemoryPressureDurationSec=</varname></term>
+
+ <listitem><para>Sets the amount of time a unit's cgroup needs to have exceeded memory pressure limits before
+ <command>systemd-oomd</command> will take action. Memory pressure limits are defined by
+ <varname>DefaultMemoryPressureLimit=</varname> and <varname>ManagedOOMMemoryPressureLimit=</varname>.
+ Defaults to 30 seconds when this property is unset or set to 0.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
in b interactive);
FlushDevices(in b interactive);
PowerOff(in b interactive);
+ PowerOffWithFlags(in t flags);
Reboot(in b interactive);
+ RebootWithFlags(in t flags);
Halt(in b interactive);
+ HaltWithFlags(in t flags);
Suspend(in b interactive);
+ SuspendWithFlags(in t flags);
Hibernate(in b interactive);
+ HibernateWithFlags(in t flags);
HybridSleep(in b interactive);
+ HybridSleepWithFlags(in t flags);
SuspendThenHibernate(in b interactive);
+ SuspendThenHibernateWithFlags(in t flags);
CanPowerOff(out s result);
CanReboot(out s result);
CanHalt(out s result);
<variablelist class="dbus-method" generated="True" extra-ref="PowerOff()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="PowerOffWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Reboot()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RebootWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Halt()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HaltWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Suspend()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="SuspendWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="Hibernate()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HibernateWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="HybridSleep()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="HybridSleepWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="SuspendThenHibernate()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="SuspendThenHibernateWithFlags()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="CanPowerOff()"/>
<variablelist class="dbus-method" generated="True" extra-ref="CanReboot()"/>
using an RTC timer and hibernated. The only argument is the polkit interactivity boolean
<varname>interactive</varname> (see below). The main purpose of these calls is that they enforce
polkit policy and hence allow powering off/rebooting/suspending/hibernating even by unprivileged
- users. They also enforce inhibition locks. UIs should expose these calls as the primary mechanism to
- poweroff/reboot/suspend/hibernate the machine.</para>
+ users. They also enforce inhibition locks for non-privileged users. UIs should expose these calls
+ as the primary mechanism to poweroff/reboot/suspend/hibernate the machine. Methods
+ <function>PowerOffWithFlags()</function>, <function>RebootWithFlags()</function>,
+ <function>HaltWithFlags()</function>, <function>SuspendWithFlags()</function>,
+ <function>HibernateWithFlags()</function>, <function>HybridSleepWithFlags()</function> and
+ <function>SuspendThenHibernateWithFlags()</function> add <varname>flags</varname> to allow for
+ extendability, defined as follows:</para>
+ <programlisting>
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
+ </programlisting>
+ <para> When the <varname>flags</varname> is 0 then these methods behave just like the versions
+ without flags. When <constant>SD_LOGIND_ROOT_CHECK_INHIBITORS</constant> (0x01) is set, active
+ inhibitors are honoured for privileged users too.</para>
<para><function>SetRebootParameter()</function> sets a parameter for a subsequent reboot operation.
See the description of <command>reboot</command> in
--- /dev/null
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" >
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
+
+<refentry id="org.freedesktop.portable1" conditional='ENABLE_PORTABLED'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>org.freedesktop.portable1</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>org.freedesktop.portable1</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>org.freedesktop.portable1</refname>
+ <refpurpose>The D-Bus interface of systemd-portabled</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Introduction</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd-portabled.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ is a system service that may be used to attach, detach and inspect portable services. This page describes the
+ D-Bus interface.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>The Manager Object</title>
+
+ <para>The service exposes the following interfaces on the Manager object on the bus:</para>
+
+ <programlisting executable="systemd-portabled" node="/org/freedesktop/portable1" interface="org.freedesktop.portable1.Manager">
+node /org/freedesktop/portable1 {
+ interface org.freedesktop.portable1.Manager {
+ methods:
+ GetImage(in s image,
+ out o object);
+ ListImages(out a(ssbtttso) UNNAMED);
+ GetImageOSRelease(in s image,
+ out a{ss} os_release);
+ GetImageMetadata(in s image,
+ in as matches,
+ out s image,
+ out ay os_release,
+ out a{say} units);
+ GetImageState(in s image,
+ out s state);
+ AttachImage(in s image,
+ in as matches,
+ in s profile,
+ in b runtime,
+ in s copy_mode,
+ out a(sss) changes);
+ DetachImage(in s image,
+ in b runtime,
+ out a(sss) changes);
+ ReattachImage(in s image,
+ in as matches,
+ in s profile,
+ in b runtime,
+ in s copy_mode,
+ out a(sss) changes_removed,
+ out a(sss) changes_updated);
+ RemoveImage(in s image);
+ MarkImageReadOnly(in s image,
+ in b read_only);
+ SetImageLimit(in s image,
+ in t limit);
+ SetPoolLimit(in t limit);
+ properties:
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s PoolPath = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t PoolUsage = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t PoolLimit = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly as Profiles = ['...', ...];
+ };
+ interface org.freedesktop.DBus.Peer { ... };
+ interface org.freedesktop.DBus.Introspectable { ... };
+ interface org.freedesktop.DBus.Properties { ... };
+};
+ </programlisting>
+
+ <!--Autogenerated cross-references for systemd.directives, do not edit-->
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.portable1.Manager"/>
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.portable1.Manager"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetImage()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="ListImages()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetImageOSRelease()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetImageMetadata()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetImageState()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="AttachImage()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="DetachImage()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="ReattachImage()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveImage()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="MarkImageReadOnly()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="SetImageLimit()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="SetPoolLimit()"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="PoolPath"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="PoolUsage"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="PoolLimit"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Profiles"/>
+
+ <!--End of Autogenerated section-->
+
+ <refsect2>
+ <title>Methods</title>
+
+ <para><function>GetImage()</function> may be used to get the image object path of the image with the
+ specified name.</para>
+
+ <para><function>ListImages()</function> returns an array of all currently known images. The
+ structures in the array consist of the following fields: image name, type, read-only flag, creation
+ time, modification time, current disk space, usage and image object path.</para>
+
+ <para><function>GetImageOSRelease()</function> retrieves the OS release information of an image.
+ This method returns an array of key value pairs read from the
+ <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file in
+ the image and is useful to identify the operating system used in a portable service.</para>
+
+ <para><function>GetImageMetadata()</function> retrieves metadata associated with an image.
+ This method returns the image name, the image's <citerefentry><refentrytitle>os-release</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> content in the form of a (streamable) array of bytes,
+ and a list of portable units contained in the image, in the form of a string (unit name) and
+ an array of bytes with the content.</para>
+
+ <para><function>GetImageState()</function> retrieves the image state as one of the following
+ strings:
+ <itemizedlist>
+ <listitem><para>detached</para></listitem>
+
+ <listitem><para>attached</para></listitem>
+
+ <listitem><para>attached-runtime</para></listitem>
+
+ <listitem><para>enabled</para></listitem>
+
+ <listitem><para>enabled-runtime</para></listitem>
+
+ <listitem><para>running</para></listitem>
+
+ <listitem><para>running-runtime</para></listitem>
+ </itemizedlist></para>
+
+ <para><function>AttachImage()</function> attaches a portable image to the system.
+ This method takes an image path or name, a list of strings that will be used to search for
+ unit files inside the image (partial or complete matches), a string indicating which
+ portable profile to use for the image (see <varname>Profiles</varname> property for
+ a list of available profiles), a boolean indicating whether to attach the image only
+ for the current boot session, and a string representing the preferred copy mode
+ (whether to copy the image or to just symlink it) with the following possible values:
+ <itemizedlist>
+ <listitem><para>(null)</para></listitem>
+
+ <listitem><para>copy</para></listitem>
+
+ <listitem><para>symlink</para></listitem>
+ </itemizedlist>
+ This method returns the list of changes applied to the system (for example, which unit was
+ added and is now available as a system service). Each change is represented as a triplet of
+ strings: the type of change applied, the path on which it was applied, and the source
+ (if any). The type of change applied will be one of the following possible values:
+ <itemizedlist>
+ <listitem><para>copy</para></listitem>
+
+ <listitem><para>symlink</para></listitem>
+
+ <listitem><para>write</para></listitem>
+
+ <listitem><para>mkdir</para></listitem>
+ </itemizedlist>
+ Note that an image cannot be attached if a unit that it contains is already present
+ on the system.</para>
+
+ <para><function>DetachImage()</function> detaches a portable image from the system.
+ This method takes an image path or name, and a boolean indicating whether the image to
+ detach was attached only for the current boot session or persistently. This method
+ returns the list of changes applied to the system (for example, which unit was removed
+ and is no longer available as a system service). Each change is represented as a triplet of
+ strings: the type of change applied, the path on which it was applied, and the source
+ (if any). The type of change applied will be one of the following possible values:
+ <itemizedlist>
+ <listitem><para>unlink</para></listitem>
+ </itemizedlist>
+ Note that an image cannot be detached if a unit that it contains is running.</para>
+
+ <para><function>ReattachImage()</function> combines the effects of the
+ <function>AttachImage()</function> method and the <function>DetachImage()</function> method.
+ The difference is that it is allowed to reattach an image while one or more of its units
+ are running. The reattach operation will fail if no matching image is attached.
+ The input parameters match the <function>AttachImage()</function> method, and the return
+ parameters are the combination of the return parameters of the
+ <function>DetachImage()</function> method (first array, units that were removed) and the
+ <function>AttachImage()</function> method (second array, units that were updated or added).</para>
+
+ <para><function>RemoveImage()</function> removes the image with the specified name.</para>
+
+ <para><function>MarkImageReadOnly()</function> toggles the read-only flag of an image.</para>
+
+ <para><function>SetPoolLimit()</function> sets an overall quota limit on the pool of images.</para>
+
+ <para><function>SetImageLimit()</function> sets a per-image quota limit.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Properties</title>
+
+ <para><varname>PoolPath</varname> specifies the file system path where images are written to.</para>
+
+ <para><varname>PoolUsage</varname> specifies the current usage size of the image pool in bytes.</para>
+
+ <para><varname>PoolLimit</varname> specifies the size limit of the image pool in bytes.</para>
+
+ <para><varname>Profiles</varname> specifies the available runtime profiles for portable services.</para>
+ </refsect2>
+ </refsect1>
+
+ <refsect1>
+ <title>The Image Object</title>
+
+ <para>The service exposes the following interfaces on the Image object on the bus:</para>
+
+ <programlisting executable="systemd-portabled" node="/org/freedesktop/portable1" interface="org.freedesktop.portable1.Image">
+node /org/freedesktop/portable1 {
+ interface org.freedesktop.portable1.Image {
+ methods:
+ GetOSRelease(out a{ss} UNNAMED);
+ GetMetadata(in as matches,
+ out s image,
+ out ay os_release,
+ out a{say} units);
+ GetState(out s UNNAMED);
+ Attach(in as matches,
+ in s profile,
+ in b runtime,
+ in s copy_mode,
+ out a(sss) changes);
+ Detach(in b runtime,
+ out a(sss) changes);
+ Reattach(in as matches,
+ in s profile,
+ in b runtime,
+ in s copy_mode,
+ out a(sss) changes_removed,
+ out a(sss) changes_updated);
+ Remove();
+ MarkReadOnly(in b read_only);
+ SetLimit(in t limit);
+ properties:
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s Name = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s Path = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s Type = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly b ReadOnly = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t CreationTimestamp = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t ModificationTimestamp = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t Usage = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t Limit = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t UsageExclusive = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly t LimitExclusive = ...;
+ };
+ interface org.freedesktop.DBus.Peer { ... };
+ interface org.freedesktop.DBus.Introspectable { ... };
+ interface org.freedesktop.DBus.Properties { ... };
+};
+ </programlisting>
+
+ <!--method GetOSRelease is not documented!-->
+
+ <!--method GetMetadata is not documented!-->
+
+ <!--method GetState is not documented!-->
+
+ <!--method Attach is not documented!-->
+
+ <!--method Detach is not documented!-->
+
+ <!--method Reattach is not documented!-->
+
+ <!--method Remove is not documented!-->
+
+ <!--method MarkReadOnly is not documented!-->
+
+ <!--method SetLimit is not documented!-->
+
+ <!--Autogenerated cross-references for systemd.directives, do not edit-->
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.portable1.Image"/>
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.portable1.Image"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetOSRelease()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetMetadata()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="GetState()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="Attach()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="Detach()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="Reattach()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="Remove()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="MarkReadOnly()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="SetLimit()"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Name"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Path"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Type"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ReadOnly"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="CreationTimestamp"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ModificationTimestamp"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Usage"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="Limit"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="UsageExclusive"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="LimitExclusive"/>
+
+ <!--End of Autogenerated section-->
+
+ <refsect2>
+ <title>Methods</title>
+
+ <para>The following methods implement the same operation as the respective methods on the
+ <interfacename>Manager</interfacename> object (see above). However, these methods operate on the image
+ object and hence does not take an image name parameter. Invoking the methods directly on the Manager
+ object has the advantage of not requiring a <function>GetImage()</function> call to get the image object
+ for a specific image name. Calling the methods on the Manager object is hence a round trip
+ optimization. List of methods:
+ <itemizedlist>
+ <listitem><para>GetOSRelease()</para></listitem>
+
+ <listitem><para>GetMetadata()</para></listitem>
+
+ <listitem><para>GetState()</para></listitem>
+
+ <listitem><para>Attach()</para></listitem>
+
+ <listitem><para>Detach()</para></listitem>
+
+ <listitem><para>Reattach()</para></listitem>
+
+ <listitem><para>Remove()</para></listitem>
+
+ <listitem><para>MarkReadOnly()</para></listitem>
+
+ <listitem><para>SetLimit()</para></listitem>
+ </itemizedlist></para>
+ </refsect2>
+
+ <refsect2>
+ <title>Properties</title>
+
+ <para><varname>Name</varname> specifies the image name.</para>
+
+ <para><varname>Path</varname> specifies the file system path where image is stored.</para>
+
+ <para><varname>Type</varname> specifies the image type.</para>
+
+ <para><varname>ReadOnly</varname> specifies whether the image is read-only.</para>
+
+ <para><varname>CreationTimestamp</varname> specifies the image creation timestamp.</para>
+
+ <para><varname>ModificationTimestamp</varname> specifies the image modification timestamp.</para>
+
+ <para><varname>Usage</varname> specifies the image disk usage.</para>
+
+ <para><varname>Limit</varname> specifies the image disk usage limit.</para>
+
+ <para><varname>UsageExclusive</varname> specifies the image disk usage (exclusive).</para>
+
+ <para><varname>LimitExclusive</varname> specifies the image disk usage limit (exclusive).</para>
+ </refsect2>
+ </refsect1>
+
+ <refsect1>
+ <title>Versioning</title>
+
+ <para>These D-Bus interfaces follow <ulink url="http://0pointer.de/blog/projects/versioning-dbus.html">
+ the usual interface versioning guidelines</ulink>.</para>
+ </refsect1>
+</refentry>
in s destination,
in b read_only,
in b mkdir);
+ MountImageUnit(in s name,
+ in s source,
+ in s destination,
+ in b read_only,
+ in b mkdir,
+ in a(ss) options);
RefUnit(in s name);
UnrefUnit(in s name);
StartTransientUnit(in s name,
UnsetEnvironment(in as names);
UnsetAndSetEnvironment(in as names,
in as assignments);
+ EnqueueMarkedJobs(out ao jobs);
ListUnitFiles(out a(ss) unit_files);
ListUnitFilesByPatterns(in as states,
in as patterns,
<variablelist class="dbus-method" generated="True" extra-ref="BindMountUnit()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="MountImageUnit()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="RefUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="UnrefUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="UnsetAndSetEnvironment()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="EnqueueMarkedJobs()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="ListUnitFiles()"/>
<variablelist class="dbus-method" generated="True" extra-ref="ListUnitFilesByPatterns()"/>
the "Try" flavor is used in which case a service that isn't running is not affected by the restart. The
"ReloadOrRestart" flavors attempt a reload if the unit supports it and use a restart otherwise.</para>
+ <para><function>EnqueueMarkedJobs()</function> creates reload/restart jobs for units which have been
+ appropriately marked, see <varname>Marks</varname> property above. This is equivalent to calling
+ <function>TryRestartUnit()</function> or <function>ReloadOrTryRestartUnit()</function> for the marked
+ units.</para>
+
<para><function>BindMountUnit()</function> can be used to bind mount new files or directories into
a running service mount namespace.</para>
+ <para><function>MountImageUnit()</function> can be used to mount new images into a running service
+ mount namespace.</para>
+
<para><function>KillUnit()</function> may be used to kill (i.e. send a signal to) all processes of a
unit. It takes the unit <varname>name</varname>, an enum <varname>who</varname> and a UNIX
<varname>signal</varname> number to send. The <varname>who</varname> enum is one of
readonly b IgnoreOnIsolate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NeedDaemonReload = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly as Markers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t JobTimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<variablelist class="dbus-property" generated="True" extra-ref="NeedDaemonReload"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="Markers"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="JobTimeoutUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="JobRunningTimeoutUSec"/>
<para><varname>NeedDaemonReload</varname> is a boolean that indicates whether the configuration file
this unit is loaded from (i.e. <varname>FragmentPath</varname> or <varname>SourcePath</varname>) has
- changed since the configuration was read and hence whether a configuration reload is
- recommended.</para>
+ changed since the configuration was read and hence whether a configuration reload is recommended.
+ </para>
+
+ <para><varname>Markers</varname> is an array of string flags that can be set using
+ <function>SetUnitProperties()</function> to indicate that the service should be reloaded or
+ restarted. Currently known values are <literal>needs-restart</literal> and
+ <literal>needs-reload</literal>. Package scripts may use the first to mark units for later restart when
+ a new version of the package is installed. Configuration management scripts may use the second to mark
+ units for a later reload when the configuration is adjusted. Those flags are not set by the manager,
+ except to unset as appropriate when when the unit is stopped, restarted, or reloaded.</para>
<para><varname>JobTimeoutUSec</varname> maps directly to the corresponding configuration setting in the
unit file.</para>
in s destination,
in b read_only,
in b mkdir);
+ MountImage(in s source,
+ in s destination,
+ in b read_only,
+ in b mkdir,
+ in a(ss) options);
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as ExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as NoExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property InaccessiblePaths is not documented!-->
+ <!--property ExecPaths is not documented!-->
+
+ <!--property NoExecPaths is not documented!-->
+
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="BindMount()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="MountImage()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="GetProcesses()"/>
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="InaccessiblePaths"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecPaths"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
<refsect2>
<title>Methods</title>
- <para><function>BindMount()</function> implements the same operation as the respective method on the
- <interfacename>Manager</interfacename> object (see above). However, this method operates on the service
- object and hence does not take a unit name parameter. Invoking the methods directly on the Manager
- object has the advantage of not requiring a <function>GetUnit()</function> call to get the unit object
- for a specific unit name. Calling the methods on the Manager object is hence a round trip
- optimization.</para>
+ <para><function>BindMount()</function> and <function>MountImage()</function> implement the same operations
+ as the respective methods on the <interfacename>Manager</interfacename> object (see above). However, these
+ methods operate on the service object and hence do not take a unit name parameter. Invoking the methods
+ directly on the Manager object has the advantage of not requiring a <function>GetUnit()</function> call
+ to get the unit object for a specific unit name. Calling the methods on the Manager object is hence a round
+ trip optimization.</para>
</refsect2>
<refsect2>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as ExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as NoExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property InaccessiblePaths is not documented!-->
+ <!--property ExecPaths is not documented!-->
+
+ <!--property NoExecPaths is not documented!-->
+
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="InaccessiblePaths"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecPaths"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as ExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as NoExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property InaccessiblePaths is not documented!-->
+ <!--property ExecPaths is not documented!-->
+
+ <!--property NoExecPaths is not documented!-->
+
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="InaccessiblePaths"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecPaths"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as ExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as NoExecPaths = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<!--property InaccessiblePaths is not documented!-->
+ <!--property ExecPaths is not documented!-->
+
+ <!--property NoExecPaths is not documented!-->
+
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="InaccessiblePaths"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecPaths"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<!--End of Autogenerated section-->
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
+
+ <!--property ManagedOOMPreference is not documented!-->
<!--property KillMode is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
to be used in case the unit names do not match the image name as described in the <command>attach</command>.</para>
</varlistentry>
+ <varlistentry>
+ <term><command>reattach</command> <replaceable>IMAGE</replaceable> [<replaceable>PREFIX…</replaceable>]</term>
+
+ <listitem><para>Detaches an existing portable service image from the host, and immediately attaches it again.
+ This is useful in case the image was replaced. Running units are not stopped during the process. Partial matching,
+ to allow for different versions in the image name, is allowed: only the part before the first <literal>_</literal>
+ character has to match. If the new image doesn't exist, the existing one will not be detached. The parameters
+ follow the same syntax as the <command>attach</command> command.</para></listitem>
+
+ <para>If <option>--now</option> and/or <option>--enable</option> are passed, the portable service(s) are
+ immediately stopped if removed, started and/or enabled if added, or restarted if updated. Prefixes are also
+ accepted, in the same way as described in the <command>attach</command> case.</para>
+ </varlistentry>
+
<varlistentry>
<term><command>inspect</command> <replaceable>IMAGE</replaceable> [<replaceable>PREFIX…</replaceable>]</term>
<varlistentry>
<term><option>--now</option></term>
- <listitem><para>Immediately start/stop the portable service after attaching/before detaching.</para></listitem>
+ <listitem><para>Immediately start/stop/restart the portable service after attaching/before
+ detaching/after upgrading.</para></listitem>
</varlistentry>
<varlistentry>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>org.freedesktop.portable1</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-portabled.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
<varlistentry>
<term><command>query</command> <replaceable>HOSTNAME|ADDRESS</replaceable>…</term>
- <listitem><para>Resolve domain names, IPv4 and IPv6 addresses.</para></listitem>
+ <listitem><para>Resolve domain names, as well as IPv4 and IPv6 addresses. When used in conjuntion
+ with <option>--type=</option> or <option>--class=</option> (see below), resolves low-level DNS
+ resource records.</para>
+
+ <para>If a single-label domain name is specified it is searched for according to the configured
+ search domains — unless <option>--search=no</option> or
+ <option>--type=</option>/<option>--class=</option> are specified, both of which turn this logic
+ off.</para>
+
+ <para>If an international domain name is specified, it is automatically translated according to IDNA
+ rules when resolved via classic DNS — but not for look-ups via MulticastDNS or LLMNR. If
+ <option>--type=</option>/<option>--class=</option> is used IDNA translation is turned off and domain
+ names are processed as specified.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-c</option> <replaceable>CLASS</replaceable></term>
<term><option>--class=</option><replaceable>CLASS</replaceable></term>
- <listitem><para>Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to
- look up. If these options are used a DNS resource record set matching the specified class and type is
- requested. The class defaults to IN if only a type is specified.
- The special value <literal>help</literal> may be used to list known values.
- </para></listitem>
+ <listitem><para>When used in conjunction with the <command>query</command> command, specifies the DNS
+ resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to look up. If these options
+ are used a DNS resource record set matching the specified class and type is requested. The class
+ defaults to IN if only a type is specified. The special value <literal>help</literal> may be used to
+ list known values.</para>
+
+ <para>Without these options <command>resolvectl query</command> provides high-level domain name to
+ address and address to domain name resolution. With these options it provides low-level DNS resource
+ record resolution. The search domain logic is automatically turned off when these options are used,
+ i.e. specified domain names need to be fully qualified domain names. Moreover, IDNA internal domain
+ name translation is turned off as well, i.e. international domain names should be specified in
+ <literal>xn--…</literal> notation, unless look-up in MulticastDNS/LLMNR is desired, in which case
+ UTF-8 characters should be used.</para></listitem>
</varlistentry>
<varlistentry>
returned.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--validate=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), DNSSEC validation is applied as usual — under the condition that it is enabled for the
+ network and for <filename>systemd-resolved.service</filename> as a whole. If false, DNSSEC validation
+ is disabled for the specific query, regardless of whether it is enabled for the network or in the
+ service. Note that setting this option to true does not force DNSSEC validation on systems/networks
+ where DNSSEC is turned off. This option is only suitable to turn off such validation where otherwise
+ enabled, not enable validation where otherwise disabled.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--synthesize=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), select domains are resolved on the local system, among them
+ <literal>localhost</literal> and <literal>_gateway</literal> or entries from
+ <filename>/etc/hosts</filename>. If false these domains are not resolved locally, and either fail (in
+ case of <literal>localhost</literal> or <literal>_gateway</literal> and suchlike) or go to the
+ network via regular DNS/mDNS/LLMNR lookups (in case of <filename>/etc/hosts</filename>
+ entries).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--cache=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), lookups use the local DNS resource record cache. If false, lookups are routed to the
+ network instead, regardless if already available in the local cache.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--zone=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), lookups are answered from locally registered LLMNR or mDNS resource records, if
+ defined. If false, locally registered LLMNR/mDNS records are not considered for the lookup
+ request.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--trust-anchor=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), lookups for DS and DNSKEY are answered from the local DNSSEC trust anchors if
+ possible. If false, the local trust store is not considered for the lookup request.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--network=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), lookups are answered via DNS, LLMNR or mDNS network requests if they cannot be
+ synthesized locally, or be answered from the local cache, zone or trust anchors (see above). If false,
+ the request is not answered from the network and will thus fail if none of the indicated sources can
+ answer them.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--search=</option><replaceable>BOOL</replaceable></term>
- <listitem><para>Takes a boolean parameter. If true (the default), any specified single-label hostnames will be
- searched in the domains configured in the search domain list, if it is non-empty. Otherwise, the search domain
- logic is disabled.</para></listitem>
+ <listitem><para>Takes a boolean parameter. If true (the default), any specified single-label
+ hostnames will be searched in the domains configured in the search domain list, if it is
+ non-empty. Otherwise, the search domain logic is disabled. Note that this option has no effect if
+ <option>--type=</option> is used (see above), in which case the search domain logic is
+ unconditionally turned off.</para></listitem>
</varlistentry>
<varlistentry>
# Do not edit. Generated by update-man-rules.py.
# Update with:
-# ninja -C build man/update-man-rules
+# ninja -C build update-man-rules
manpages = [
['binfmt.d', '5', [], 'ENABLE_BINFMT'],
['bootctl', '1', [], 'ENABLE_EFI'],
['coredump.conf', '5', ['coredump.conf.d'], 'ENABLE_COREDUMP'],
['coredumpctl', '1', [], 'ENABLE_COREDUMP'],
['crypttab', '5', [], 'HAVE_LIBCRYPTSETUP'],
- ['veritytab', '5', [], 'HAVE_LIBCRYPTSETUP'],
['daemon', '7', [], ''],
['dnssec-trust-anchors.d',
'5',
['org.freedesktop.login1', '5', [], 'ENABLE_LOGIND'],
['org.freedesktop.machine1', '5', [], 'ENABLE_MACHINED'],
['org.freedesktop.oom1', '5', [], 'ENABLE_OOMD'],
+ ['org.freedesktop.portable1', '5', [], 'ENABLE_PORTABLED'],
['org.freedesktop.resolve1', '5', [], 'ENABLE_RESOLVE'],
['org.freedesktop.systemd1', '5', [], ''],
['org.freedesktop.timedate1', '5', [], 'ENABLE_TIMEDATED'],
'sd_bus_reply_method_errorf',
'sd_bus_reply_method_errorfv'],
''],
- ['sd_bus_reply_method_return', '3', ['sd_bus_reply_method_returnv'], ''],
+ ['sd_bus_reply_method_return',
+ '3',
+ ['sd_bus_reply', 'sd_bus_reply_method_returnv'],
+ ''],
['sd_bus_request_name',
'3',
['sd_bus_release_name',
['systemd-user-runtime-dir', 'user-runtime-dir@.service'],
''],
['userdbctl', '1', [], 'ENABLE_USERDB'],
- ['vconsole.conf', '5', [], 'ENABLE_VCONSOLE']
+ ['vconsole.conf', '5', [], 'ENABLE_VCONSOLE'],
+ ['veritytab', '5', [], 'HAVE_LIBCRYPTSETUP']
]
# Really, do not edit.
<citerefentry><refentrytitle>sd_bus_query_sender_privilege</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_reply_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_reply_method_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sd_bus_reply</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send_to</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<refsect1>
<title>Description</title>
- <para><function>sd_bus_message_read_strv()</function> gives access to an array of strings in message
- <parameter>m</parameter>. The "read pointer" in the message must be right before an array of strings. On
- success, a pointer to the <constant>NULL</constant>-terminated array of strings is returned in the output
- parameter <parameter>l</parameter>. Note that ownership of this array is transferred to the caller.
- Hence, the caller is responsible for freeing this array and its contents.</para>
+ <para><function>sd_bus_message_read_strv()</function> gives access to an array of string-like items in
+ message <parameter>m</parameter>. The "read pointer" in the message must be right before an array of
+ strings (D-Bus type <literal>as</literal>), object paths (D-Bus type <literal>ao</literal>), or
+ signatures (D-Bus type <literal>ag</literal>). On success, a pointer to a
+ <constant>NULL</constant>-terminated array of strings is returned in the output parameter
+ <parameter>l</parameter>. Note that ownership of this array is transferred to the caller. Hence, the
+ caller is responsible for freeing this array and its contents.</para>
</refsect1>
<refsect1>
<listitem><para>The message cannot be parsed.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENXIO</constant></term>
+
+ <listitem><para>The message "read pointer" is not right before an array of the appropriate type.
+ </para></listitem>
+ </varlistentry>
</variablelist>
</refsect2>
</refsect1>
<refnamediv>
<refname>sd_bus_reply_method_return</refname>
<refname>sd_bus_reply_method_returnv</refname>
+ <refname>sd_bus_reply</refname>
<refpurpose>Reply to a D-Bus method call</refpurpose>
</refnamediv>
<paramdef>const char *<parameter>types</parameter></paramdef>
<paramdef>va_list <parameter>ap</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int sd_bus_reply</funcdef>
+ <paramdef>const sd_bus_message *<parameter>call</parameter></paramdef>
+ <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
If no reply is expected to <parameter>call</parameter>, this function succeeds without sending a
reply.</para>
+
+ <para><function>sd_bus_reply()</function> takes a complete bus message object created with either
+ <citerefentry><refentrytitle>sd_bus_new_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
+ <citerefentry><refentrytitle>sd_bus_new_method_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and sends it as a reply to the <parameter>call</parameter> message.</para>
</refsect1>
<refsect1>
</para>
<para>Message <parameter>call</parameter> is not attached to a bus.</para>
+
+ <para>Message <parameter>m</parameter> is not a method reply message.</para>
</listitem>
</varlistentry>
<function>poll()</function> and
<function>sd_journal_process()</function> into one.</para>
- <para><function>sd_journal_reliable_fd()</function> may be used to
- check whether the wakeup events from the file descriptor returned
- by <function>sd_journal_get_fd()</function> are known to be
- immediately triggered. On certain file systems where file change
- events from the OS are not available (such as NFS) changes need to
- be polled for repeatedly, and hence are detected only with a
- certain latency. This call will return a positive value if the
- journal changes are detected immediately and zero when they need
- to be polled for and hence might be noticed only with a certain
- latency. Note that there is usually no need to invoke this function
- directly as <function>sd_journal_get_timeout()</function> on these
- file systems will ask for timeouts explicitly anyway.</para>
+ <para><function>sd_journal_reliable_fd()</function> may be used to check whether the wake-up events from
+ the file descriptor returned by <function>sd_journal_get_fd()</function> are known to be quickly
+ triggered. On certain file systems where file change events from the OS are not available (such as NFS)
+ changes need to be polled for repeatedly, and hence are detected only with a considerable latency. This
+ call will return a positive value if the journal changes are detected quickly and zero when they need to
+ be polled for. Note that there is usually no need to invoke this function directly as
+ <function>sd_journal_get_timeout()</function> will request appropriate timeouts anyway.</para>
+
+ <para>Note that all of the above change notification interfaces do not report changes
+ instantly. Latencies are introduced for multiple reasons: as mentioned certain storage backends require
+ time-based polling, in other cases wake-ups are optimized by coalescing events, and the OS introduces
+ additional IO/CPU scheduling latencies.</para>
</refsect1>
<refsect1>
<refsection id='main-conf'>
<title>Configuration Directories and Precedence</title>
- <para>The default configuration is defined during compilation, so a
- configuration file is only needed when it is necessary to deviate
- from those defaults. By default, the configuration file in
- <filename>/etc/systemd/</filename> contains commented out entries
- showing the defaults as a guide to the administrator. This file
- can be edited to create local overrides.
+ <para>The default configuration is set during compilation, so configuration is only needed when it is
+ necessary to deviate from those defaults. Initially, the main configuration file in
+ <filename>/etc/systemd/</filename> contains commented out entries showing the defaults as a guide to the
+ administrator. Local overrides can be created by editing this file or by creating drop-ins, see below.
</para>
- <para>When packages need to customize the configuration, they can install configuration snippets in
- <filename>/usr/lib/systemd/*.conf.d/</filename> or <filename>/usr/local/lib/systemd/*.conf.d/</filename>.
- The main configuration file is read before any of the configuration directories, and has the lowest
- precedence; entries in a file in any configuration directory override entries in the single configuration
- file. Files in the <filename>*.conf.d/</filename> configuration subdirectories are sorted by their
- filename in lexicographic order, regardless of in which of the subdirectories they reside. When multiple
- files specify the same option, for options which accept just a single value, the entry in the file with
- the lexicographically latest name takes precedence. For options which accept a list of values, entries
- are collected as they occur in files sorted lexicographically.</para>
+ <para>In addition to the "main" configuration file, drop-in configuration snippets are read from
+ <filename>/usr/lib/systemd/*.conf.d/</filename>, <filename>/usr/local/lib/systemd/*.conf.d/</filename>,
+ and <filename>/etc/systemd/*.conf.d/</filename>. Those drop-ins have higher precedence and override the
+ main configuration file. Files in the <filename>*.conf.d/</filename> configuration subdirectories are
+ sorted by their filename in lexicographic order, regardless of in which of the subdirectories they
+ reside. When multiple files specify the same option, for options which accept just a single value, the
+ entry in the file sorted last takes precedence, and for options which accept a list of values, entries
+ are collected as they occur in the sorted files.</para>
- <para>Files in <filename>/etc/</filename> are reserved for the local administrator, who may use this
- logic to override the configuration files installed by vendor packages. It is recommended to prefix all
- filenames in those subdirectories with a two-digit number and a dash, to simplify the ordering of the
- files.</para>
+ <para>When packages need to customize the configuration, they can install drop-ins under
+ <filename>/usr/</filename>. Files in <filename>/etc/</filename> are reserved for the local administrator,
+ who may use this logic to override the configuration files installed by vendor packages. Drop-ins have to
+ be used to override package drop-ins, since the main configuration file has lower precedence. It is
+ recommended to prefix all filenames in those subdirectories with a two-digit number and a dash, to
+ simplify the ordering of the files.</para>
- <para>To disable a configuration file supplied by the vendor, the
- recommended way is to place a symlink to
- <filename>/dev/null</filename> in the configuration directory in
- <filename>/etc/</filename>, with the same filename as the vendor
- configuration file.</para>
+ <para>To disable a configuration file supplied by the vendor, the recommended way is to place a symlink
+ to <filename>/dev/null</filename> in the configuration directory in <filename>/etc/</filename>, with the
+ same filename as the vendor configuration file.</para>
</refsection>
</refsection>
Before each file, the filename is printed as a comment.</para>
</listitem>
</varlistentry>
+
+ <varlistentry id='json'>
+ <term><option>--json=</option><replaceable>MODE</replaceable></term>
+
+ <listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
+ shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
+ (for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
+ off JSON output, the default).</para></listitem>
+ </varlistentry>
+
+ <varlistentry id='signal'>
+ <term><option>-s</option></term>
+ <term><option>--signal=</option></term>
+
+ <listitem>
+ <para>When used with <command>kill</command>, choose which signal to send to selected processes. Must
+ be one of the well-known signal specifiers such as <constant>SIGTERM</constant>,
+ <constant>SIGINT</constant> or <constant>SIGSTOP</constant>. If omitted, defaults to
+ <option>SIGTERM</option>.</para>
+
+ <para>The special value <literal>help</literal> will list the known values and the program will exit
+ immediately, and the special value <literal>list</literal> will list known values along with the
+ numerical signal numbers and the program will exit immediately.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5)
</programlisting>
- <para>The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White
- indicates an <literal>inactive</literal> or <literal>deactivating</literal> state. Red indicates a
- <literal>failed</literal> or <literal>error</literal> state and green indicates an
- <literal>active</literal>, <literal>reloading</literal> or <literal>activating</literal> state.
+ <para>The dot ("●") uses color on supported terminals to summarize the unit state at a glance. Along with
+ its color, its shape varies according to its state: <literal>inactive</literal> or
+ <literal>maintenance</literal> is a white circle ("○"), <literal>active</literal> is a green dot ("●"),
+ <literal>deactivating</literal> is a white dot, <literal>failed</literal> or <literal>error</literal> is
+ a red cross ("×"), and <literal>reloading</literal> is a green clockwise circle arrow ("↻").
</para>
<para>The "Loaded:" line in the output will show <literal>loaded</literal> if the unit has been loaded into
<option>ExecStartPre=</option>, etc.) </para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>mount-image</command> <replaceable>UNIT</replaceable> <replaceable>IMAGE</replaceable> [<replaceable>PATH</replaceable> [<replaceable>PARTITION_NAME</replaceable>:<replaceable>MOUNT_OPTIONS</replaceable>]]</term>
+
+ <listitem><para>Mounts an image from the host into the specified unit's view. The first path argument is the source
+ image on the host, the second path argument is the destination directory in the unit's view (ie: inside
+ <option>RootImage=</option>/<option>RootDirectory=</option>). Any following argument is interpreted as a
+ colon-separated tuple of partition name and comma-separated list of mount options for that partition. The format is the
+ same as the service <option>MountImages=</option> setting. When combined with the <option>--read-only</option> switch, a
+ ready-only mount is created. When combined with the <option>--mkdir</option> switch, the destination path is first
+ created before the mount is applied. Note that this option is currently only supported for units that run within a mount
+ namespace (e.g.: with <option>RootImage=</option>, <option>PrivateMounts=</option>, etc.).
+ Note that the namespace mentioned here, where the image mount will be added to, is the one where the main service
+ process runs, as other processes run in distinct namespaces (e.g.: <option>ExecReload=</option>,
+ <option>ExecStartPre=</option>, etc.). Example:
+ <programlisting>systemctl mount-image foo.service /tmp/img.raw /var/lib/image root:ro,nosuid</programlisting>
+ <programlisting>systemctl mount-image --mkdir bar.service /tmp/img.raw /var/lib/baz/img</programlisting></para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>service-log-level</command> <replaceable>SERVICE</replaceable> [<replaceable>LEVEL</replaceable>]</term>
<para>For more information on the preset policy format, see
<citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- For more information on the concept of presets, please consult the
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
- document.</para>
+ </para>
</listitem>
</varlistentry>
is defined. If omitted, defaults to
<option>all</option>.</para>
</listitem>
-
</varlistentry>
- <varlistentry>
- <term><option>-s</option></term>
- <term><option>--signal=</option></term>
-
- <listitem>
- <para>When used with <command>kill</command>, choose which
- signal to send to selected processes. Must be one of the
- well-known signal specifiers such as <constant>SIGTERM</constant>, <constant>SIGINT</constant> or
- <constant>SIGSTOP</constant>. If omitted, defaults to
- <option>SIGTERM</option>.</para>
- </listitem>
- </varlistentry>
+ <xi:include href="standard-options.xml" xpointer="signal" />
<varlistentry>
<term><option>--what=</option></term>
<term><option>--timestamp=</option></term>
<listitem>
- <para>Takes one of <literal>pretty</literal> (the default),
- <literal>us</literal>, <literal>µs</literal>, <literal>utc</literal>.
- Changes the format of printed timestamps.
- <literal>pretty</literal>: <literal>Day YYYY-MM-DD HH:MM:SS TZ</literal>
- <literal>us</literal> or <literal>µs</literal>: <literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ</literal>
- <literal>utc</literal>: <literal>Day YYYY-MM-DD HH:MM:SS UTC</literal></para>
- <literal>us+utc</literal> or <literal>µs+utc</literal>: <literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC</literal>
+ <para>Change the format of printed timestamps. The following values may be used:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>pretty</option> (this is the default)</term>
+ <listitem><para><literal>Day YYYY-MM-DD HH:MM:SS TZ</literal></para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>us</option></term>
+ <term><option>µs</option></term>
+ <listitem><para><literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ</literal></para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>utc</option></term>
+ <listitem><para><literal>Day YYYY-MM-DD HH:MM:SS UTC</literal></para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>us+utc</option></term>
+ <term><option>µs+utc</option></term>
+ <listitem><para><literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC</literal></para></listitem>
+ </varlistentry>
+ </variablelist>
</listitem>
</varlistentry>
a directory, but a regular file, device node, socket or FIFO.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--marked</option></term>
+
+ <listitem><para>Only allowed with <command>reload-or-restart</command>. Enqueues restart jobs for all
+ units that have the <literal>needs-restart</literal> mark, and reload jobs for units that have the
+ <literal>needs-reload</literal> mark. When a unit marked for reload does not support reload, restart
+ will be queued. Those properties can be set using <command>set-property Marks</command>.</para>
+
+ <para>Unless <option>--no-block</option> is used, <command>systemctl</command> will wait for the
+ queued jobs to finish.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--read-only</option></term>
operation begins.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><option>--json=</option><replaceable>MODE</replaceable></term>
-
- <listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
- shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
- (for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
- off json output).</para></listitem>
- </varlistentry>
-
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
<listitem><para>Takes one of <literal>disabled</literal>, <literal>loop</literal>,
<literal>all</literal>, <literal>crypto</literal>. If <literal>disabled</literal> the image is
- accessed with empty block discarding turned off. if <literal>loop</literal> discarding is enabled if
+ accessed with empty block discarding turned off. If <literal>loop</literal> discarding is enabled if
operating on a regular file. If <literal>crypt</literal> discarding is enabled even on encrypted file
systems. If <literal>all</literal> discarding is unconditionally enabled.</para></listitem>
</varlistentry>
<term><option>--root-hash-sig=</option></term>
<term><option>--verity-data=</option></term>
- <listitem><para>Configure various aspects of Verity data integrity for the OS
- image. <option>--root-hash=</option> expects a hex-encoding top-level Verity hash to use for setting
- up the Verity integrity protection. <option>--root-hash-sig=</option> expects the path to a file
- containing a PKCS#7 signature file for the hash. This signature is passed to the kernel during
- activation, which will match it against signature keys available in the kernel
- keyring. <option>--verity-data=</option> expects the path to a file with the Verity data to use for
- the OS image, in case it is stored in a detached file. It is recommended to embed the Verity data
- directly in the image, using the Verity mechanisms in the <ulink
- url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>.</para></listitem>
+ <listitem><para>Configure various aspects of Verity data integrity for the OS image. Option
+ <option>--root-hash=</option> specifies a hex-encoded top-level Verity hash to use for setting up the
+ Verity integrity protection. Option <option>--root-hash-sig=</option> specifies the path to a file
+ containing a PKCS#7 signature for the hash. This signature is passed to the kernel during activation,
+ which will match it against signature keys available in the kernel keyring. Option
+ <option>--verity-data=</option> specifies a path to a file with the Verity data to use for the OS
+ image, in case it is stored in a detached file. It is recommended to embed the Verity data directly
+ in the image, using the Verity mechanisms in the <ulink
+ url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>.
+ </para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="json" />
</variablelist>
</refsect1>
<varlistentry>
<term><option>--copy</option></term>
- <listitem><para>Copy locale, keymap, time zone and root password from
- the host. This is equivalent to specifying
+ <listitem><para>Copy locale, keymap, time zone, root password and shell from the host. This is
+ equivalent to specifying
<option>--copy-locale</option>,
<option>--copy-keymap</option>,
<option>--copy-timezone</option>,
<para>You will need a kernel compiled with PSI support. This is available in Linux 4.20 and above.</para>
- <para>The system must also have swap enabled for <command>systemd-oomd</command> to function correctly. With swap
- enabled, the system spends enough time swapping pages to let <command>systemd-oomd</command> react.
+ <para>It is highly recommended for the system to have swap enabled for <command>systemd-oomd</command> to function
+ optimally. With swap enabled, the system spends enough time swapping pages to let <command>systemd-oomd</command> react.
Without swap, the system enters a livelocked state much more quickly and may prevent <command>systemd-oomd</command>
from responding in a reasonable amount of time. See
<ulink url="https://chrisdown.name/2018/01/02/in-defence-of-swap.html">"In defence of swap: common misconceptions"</ulink>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>portablectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>portablectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>org.freedesktop.portable1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
thus preserving the existing information contained in the pstore, and clearing
pstore storage for future error events.</para>
- <para>Linux provides a persistent storage file system, pstore, that can store
- error records when the kernel dies (or reboots or powers-off). These records in
- turn can be referenced to debug kernel problems (currently the kernel stuffs
- the tail of the dmesg, which also contains a stack backtrace, into pstore).</para>
+ <para>Linux provides a persistent storage file system, pstore, that can store error records when the
+ kernel dies (or reboots or powers-off). These records in turn can be referenced to debug kernel problems
+ (currently the kernel stores the tail of the kernel log, which also contains a stack backtrace, into
+ pstore).</para>
<para>The pstore file system supports a variety of backends that map onto persistent
storage, such as the ACPI ERST and UEFI variables. The pstore backends
pstore.</para>
<para>The pstore service is independent of the kdump service. In cloud environments
- specifically, host and guest filesystems are on remote filesystems (eg. iSCSI
+ specifically, host and guest filesystems are on remote filesystems (e.g. iSCSI
or NFS), thus kdump relies (implicitly and/or explicitly) upon proper operation
of networking software *and* hardware *and* infrastructure. Thus it may not be
possible to capture a kernel coredump to a file since writes over the network
debugging.</para>
<para>The <command>systemd-pstore</command> executable does the actual work. Upon starting,
- the <filename>pstore.conf</filename> file is read and the <filename>/sys/fs/pstore</filename>
+ the <filename>pstore.conf</filename> file is read and the <filename>/sys/fs/pstore/</filename>
directory contents are processed according to the options. Pstore files are written to the
- journal, and optionally saved into <filename>/var/lib/systemd/pstore</filename>.</para>
+ journal, and optionally saved into <filename>/var/lib/systemd/pstore/</filename>.</para>
</refsect1>
<refsect1>
</refsect2>
<refsect2>
- <title>Controlling kernel parameters</title>
+ <title>Kernel parameters</title>
<para> The kernel has two parameters,
<filename>/sys/module/kernel/parameters/crash_kexec_post_notifiers</filename> and
- <filename>/sys/module/printk/parameters/always_kmsg_dump</filename>,
- that control writes into pstore.
- The crash_kexec_post_notifiers parameter enables the kernel to write
- dmesg (including stack trace) into pstore upon a panic or crash, and
- printk.always_kmsg_dump parameter enables the kernel to write dmesg
- upon a normal shutdown (shutdown, reboot, halt). These kernel
- parameters are managed via the
+ <filename>/sys/module/printk/parameters/always_kmsg_dump</filename>, that control writes into pstore.
+ The first enables storing of the kernel log (including stack trace) into pstore upon a panic or crash,
+ and the second enables storing of the kernel log upon a normal shutdown (shutdown, reboot, halt). These
+ parameters can be managed via the
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
mechanism, specifically the file <filename>/usr/lib/tmpfiles/systemd-pstore.conf</filename>.
</para>
and graphic illustrating the changes applied.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><option>--json=</option><replaceable>MODE</replaceable></term>
-
- <listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
- shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
- (for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
- off json output).</para></listitem>
- </varlistentry>
-
<varlistentry>
<term><option>--definitions=</option></term>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="json" />
</variablelist>
</refsect1>
<para>This section provides a short summary of differences in the stub resolver implemented by
<citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry> together
- with <command>systemd-resolved</command> and the tranditional stub resolver implemented in
+ with <command>systemd-resolved</command> and the traditional stub resolver implemented in
<citerefentry><refentrytitle>nss-dns</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<itemizedlist>
with newer ones, for example to install a locally compiled development version of some low-level
component over the immutable OS image without doing a full OS rebuild or modifying the nominally
immutable image. (e.g. "install" a locally built package with <command>DESTDIR=/var/lib/extensions/mytest
- make install && systemd-sysext --refresh</command>, making it available in
+ make install && systemd-sysext refresh</command>, making it available in
<filename>/usr/</filename> as if it was installed in the OS image itself.) This case works regardless if
the underlying host <filename>/usr/</filename> is managed as immutable disk image or is a traditional
package manager controlled (i.e. writable) tree.</para>
<refsect1>
<title>Commands</title>
- <para>The following command switches are understood:</para>
+ <para>The following commands are understood:</para>
<variablelist>
<varlistentry>
- <term><option>--merge</option></term>
- <term><option>-m</option></term>
+ <term><option>status</option></term>
+
+ <listitem><para>When invoked without any command verb, or when <option>status</option> is specified
+ the current merge status is shown, separately for both <filename>/usr/</filename> and
+ <filename>/opt/</filename>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>merge</option></term>
<listitem><para>Merges all currently installed system extension images into
<filename>/usr/</filename> and <filename>/opt/</filename>, by overmounting these hierarchies with an
<literal>overlayfs</literal> file system combining the underlying hierarchies with those included in
</varlistentry>
<varlistentry>
- <term><option>--unmerge</option></term>
- <term><option>-u</option></term>
+ <term><option>unmerge</option></term>
<listitem><para>Unmerges all currently installed system extension images from
<filename>/usr/</filename> and <filename>/opt/</filename>, by unmounting the
- <literal>overlayfs</literal> file systems created by <option>--merge</option>
+ <literal>overlayfs</literal> file systems created by <option>merge</option>
prior.</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>--refresh</option></term>
- <term><option>-R</option></term>
- <listitem><para>A combination of <option>--unmerge</option> and <option>--merge</option>: if already
+ <term><option>refresh</option></term>
+ <listitem><para>A combination of <option>unmerge</option> and <option>merge</option>: if already
mounted the existing <literal>overlayfs</literal> instance is unmounted temporarily, and then
replaced by a new version. This command is useful after installing/removing system extension images,
in order to update the <literal>overlayfs</literal> file system accordingly. If no system extensions
- are installed when this command is executed, the equivalent of <option>--unmerge</option> is
+ are installed when this command is executed, the equivalent of <option>unmerge</option> is
executed, without establishing any new <literal>overlayfs</literal> instance. Note that currently
there's a brief moment where neither the old nor the new <literal>overlayfs</literal> file system is
mounted. This implies that all resources supplied by a system extension will briefly disappear — even
</varlistentry>
<varlistentry>
- <term><option>--list</option></term>
- <term><option>-l</option></term>
+ <term><option>list</option></term>
<listitem><para>A brief list of installed extension images is shown.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
-
- <para>When invoked without any command switches, the current merge status is shown, separately for both
- <filename>/usr/</filename> and <filename>/opt/</filename>.</para>
</refsect1>
<refsect1>
</varlistentry>
<varlistentry>
- <term><option>--json=</option></term>
+ <term><option>--force</option></term>
- <listitem><para>Generate JSON output, instead of human readable tabular output. Takes one of
- <literal>short</literal>, <literal>pretty</literal> or <literal>off</literal> in order to control the
- output style, or explicitly disabling JSON output.</para></listitem>
+ <listitem><para>When merging system extensions into <filename>/usr/</filename> and
+ <filename>/opt/</filename>, ignore version incompatibilities, i.e. force merging regardless of
+ whether the version information included in the extension images matches the host or
+ not.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="json" />
</variablelist>
</refsect1>
<listitem><para>Configure the default value for the per-unit <varname>TasksMax=</varname> setting. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. This setting applies to all unit types that support resource control settings, with the exception
- of slice units. Defaults to 15% of the sysctl setting <varname>kernel.pid_max=</varname> or root cgroup <varname>pids.max</varname>.
+ of slice units. Defaults to 15% of the minimum of <varname>kernel.pid_max=</varname>, <varname>kernel.threads-max=</varname>
+ and root cgroup <varname>pids.max</varname>.
Kernel has a default value for <varname>kernel.pid_max=</varname> and an algorithm of counting in case of more than 32 cores.
For example with the default <varname>kernel.pid_max=</varname>, <varname>DefaultTasksMax=</varname> defaults to 4915,
but might be greater in other systems or smaller in OS containers.</para></listitem>
group records. Internally it talks to all other user/group record services running on the system in
parallel and forwards any information discovered. This simplifies clients substantially since they need
to talk to a single service only instead of all of them in
- parallel. <constant>io.systemd.NameSeviceSwitch</constant> provides compatibility with classic UNIX/glibc
+ parallel. <constant>io.systemd.NameServiceSwitch</constant> provides compatibility with classic UNIX/glibc
NSS user records, i.e. converts <type>struct passwd</type> and <type>struct group</type> records as
acquired with APIs such as <citerefentry
project='man-pages'><refentrytitle>getpwnam</refentrytitle><manvolnum>1</manvolnum></citerefentry> to JSON
<para>The <varname>MountAPIVFS=</varname> and <varname>PrivateUsers=</varname> settings are particularly useful
in conjunction with <varname>RootDirectory=</varname>. For details, see below.</para>
+ <para>If <varname>RootDirectory=</varname>/<varname>RootImage=</varname> are used together with
+ <varname>NotifyAccess=</varname> the notification socket is automatically mounted from the host into
+ the root environment, to ensure the notification interface can work correctly.</para>
+
+ <para>Note that services using <varname>RootDirectory=</varname>/<varname>RootImage=</varname> will
+ not be able to log via the syslog or journal protocols to the host logging infrastructure, unless the
+ relevant sockets are mounted from the host, specifically:</para>
+
+ <example>
+ <title>Mounting logging sockets into root environment</title>
+
+ <programlisting>BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout</programlisting>
+ </example>
+
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<term><varname>ProcSubset=</varname></term>
<listitem><para>Takes one of <literal>all</literal> (the default) and <literal>pid</literal>. If
- the latter all files and directories not directly associated with process management and introspection
- are made invisible in the <filename>/proc/</filename> file system configured for the unit's
- processes. This controls the <literal>subset=</literal> mount option of the <literal>procfs</literal>
- instance for the unit. For further details see <ulink
+ <literal>pid</literal>, all files and directories not directly associated with process management and
+ introspection are made invisible in the <filename>/proc/</filename> file system configured for the
+ unit's processes. This controls the <literal>subset=</literal> mount option of the
+ <literal>procfs</literal> instance for the unit. For further details see <ulink
url="https://www.kernel.org/doc/html/latest/filesystems/proc.html#mount-options">The /proc
Filesystem</ulink>. Note that Linux exposes various kernel APIs via <filename>/proc/</filename>,
which are made unavailable with this setting. Since these APIs are used frequently this option is
enforcement. For example, time limits specified for <varname>LimitCPU=</varname> will be rounded up
implicitly to multiples of 1s. For <varname>LimitNICE=</varname> the value may be specified in two
syntaxes: if prefixed with <literal>+</literal> or <literal>-</literal>, the value is understood as
- regular Linux nice value in the range -20..19. If not prefixed like this the value is understood as
- raw resource limit parameter in the range 0..40 (with 0 being equivalent to 1).</para>
+ regular Linux nice value in the range -20…19. If not prefixed like this the value is understood as
+ raw resource limit parameter in the range 0…40 (with 0 being equivalent to 1).</para>
<para>Note that most process resource limits configured with these options are per-process, and
processes may fork in order to acquire a new set of resources that are accounted independently of the
<term><varname>ReadWritePaths=</varname></term>
<term><varname>ReadOnlyPaths=</varname></term>
<term><varname>InaccessiblePaths=</varname></term>
+ <term><varname>ExecPaths=</varname></term>
+ <term><varname>NoExecPaths=</varname></term>
<listitem><para>Sets up a new file system namespace for executed processes. These options may be used
to limit access a process has to the file system. Each setting takes a space-separated list of paths
<varname>BindPaths=</varname>, or <varname>BindReadOnlyPaths=</varname> inside it. For a more flexible option,
see <varname>TemporaryFileSystem=</varname>.</para>
+ <para>Content in paths listed in <varname>NoExecPaths=</varname> are not executable even if the usual
+ file access controls would permit this. Nest <varname>ExecPaths=</varname> inside of
+ <varname>NoExecPaths=</varname> in order to provide executable content within non-executable
+ directories.</para>
+
<para>Non-directory paths may be specified as well. These options may be specified more than once,
in which case all paths listed will have limited access from within the namespace. If the empty string is
assigned to this option, the specific list is reset, and all prior assignments have no effect.</para>
- <para>Paths in <varname>ReadWritePaths=</varname>, <varname>ReadOnlyPaths=</varname> and
- <varname>InaccessiblePaths=</varname> may be prefixed with <literal>-</literal>, in which case they will be
+ <para>Paths in <varname>ReadWritePaths=</varname>, <varname>ReadOnlyPaths=</varname>,
+ <varname>InaccessiblePaths=</varname>, <varname>ExecPaths=</varname> and
+ <varname>NoExecPaths=</varname> may be prefixed with <literal>-</literal>, in which case they will be
ignored when they do not exist. If prefixed with <literal>+</literal> the paths are taken relative to the root
directory of the unit, as configured with <varname>RootDirectory=</varname>/<varname>RootImage=</varname>,
instead of relative to the root directory of the host (see above). When combining <literal>-</literal> and
<varname>CapabilityBoundingSet=~CAP_SYS_ADMIN</varname> or
<varname>SystemCallFilter=~@mount</varname>.</para>
+ <para>Simple allow-list example using these directives:
+ <programlisting>[Service]
+ReadOnlyPaths=/
+ReadWritePaths=/var /run
+InaccessiblePaths=-/lost+found
+NoExecPaths=/
+ExecPaths=/usr/sbin/my_daemon /usr/lib /usr/lib64
+</programlisting></para>
+
<xi:include href="system-only.xml" xpointer="plural"/></listitem>
</varlistentry>
executed processes and mounts private <filename>/tmp/</filename> and <filename>/var/tmp/</filename>
directories inside it that are not shared by processes outside of the namespace. This is useful to
secure access to temporary files of the process, but makes sharing between processes via
- <filename>/tmp/</filename> or <filename>/var/tmp/</filename> impossible. If this is enabled, all
- temporary files created by a service in these directories will be removed after the service is
- stopped. Defaults to false. It is possible to run two or more units within the same private
- <filename>/tmp/</filename> and <filename>/var/tmp/</filename> namespace by using the
- <varname>JoinsNamespaceOf=</varname> directive, see
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
- details. This setting is implied if <varname>DynamicUser=</varname> is set. For this setting the same
- restrictions regarding mount propagation and privileges apply as for
+ <filename>/tmp/</filename> or <filename>/var/tmp/</filename> impossible. If true, all temporary files
+ created by a service in these directories will be removed after the service is stopped. Defaults to
+ false. It is possible to run two or more units within the same private <filename>/tmp/</filename> and
+ <filename>/var/tmp/</filename> namespace by using the <varname>JoinsNamespaceOf=</varname> directive,
+ see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details. This setting is implied if <varname>DynamicUser=</varname> is set. For this setting the
+ same restrictions regarding mount propagation and privileges apply as for
<varname>ReadOnlyPaths=</varname> and related calls, see above. Enabling this setting has the side
effect of adding <varname>Requires=</varname> and <varname>After=</varname> dependencies on all mount
units necessary to access <filename>/tmp/</filename> and <filename>/var/tmp/</filename>. Moreover an
<varname>ExecStart=</varname> command line use <literal>${CREDENTIALS_DIRECTORY}/mycred</literal>,
e.g. <literal>ExecStart=cat ${CREDENTIALS_DIRECTORY}/mycred</literal>.</para>
- <para>Currently, an accumulated credential size limit of 1M bytes per unit is
- enforced.</para>
+ <para>Currently, an accumulated credential size limit of 1 MB per unit is enforced.</para>
<para>If referencing an <constant>AF_UNIX</constant> stream socket to connect to, the connection will
originate from an abstract namespace socket, that includes information about the unit and the
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>$SYSTEMD_EXEC_PID</varname></term>
+
+ <listitem><para>The PID of the unit process (e.g. process invoked by
+ <varname>ExecStart=</varname>). The child process can use this information to determine
+ whether the process is directly invoked by the service manager or indirectly as a child of
+ another process by comparing this value with the current PID (as similar to the scheme used in
+ <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ with <varname>$LISTEN_PID</varname> and <varname>$LISTEN_FDS</varname>).</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>$TERM</varname></term>
</listitem>
</varlistentry>
<varlistentry>
- <term><varname>TxQueueLength=</varname></term>
+ <term><varname>TransmitQueues=</varname></term>
+ <listitem>
+ <para>Specifies the device's number of transmit queues. An integer in the range 1…4096.
+ When unset, the kernel's default will be used.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>ReceiveQueues=</varname></term>
+ <listitem>
+ <para>Specifies the device's number of receive queues. An integer in the range 1…4096.
+ When unset, the kernel's default will be used.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>TransmitQueueLength=</varname></term>
<listitem>
<para>Specifies the transmit queue length of the device in number of packets. An unsigned integer
- in the range 0..4294967294. When unset, the kernel's default will be used.</para>
+ in the range 0…4294967294. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>Specifies the maximum size of a Generic Segment Offload (GSO) packet the
device should accept. The usual suffixes K, M, G, are supported and are
- understood to the base of 1024. An unsigned integer in the range 1â\80\9465536.
+ understood to the base of 1024. An unsigned integer in the range 1â\80¦65536.
Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>GenericSegmentOffloadMaxSegments=</varname></term>
<listitem>
- <para>Specifies the maximum number of a Generic Segment Offload (GSO) segments the device should accept.
- An unsigned integer in the range 1—65535. Defaults to unset.</para>
+ <para>Specifies the maximum number of a Generic Segment Offload (GSO) segments the device should
+ accept. An unsigned integer in the range 1…65535. Defaults to unset.</para>
</listitem>
</varlistentry>
<title>History</title>
<para>The following "naming schemes" have been defined (which may be chosen at system boot-up time via
- the <varname>net.naming-scheme=</varname> kernel command line switch, see above:</para>
+ the <varname>net.naming-scheme=</varname> kernel command line switch, see above):</para>
<variablelist>
<varlistentry>
<varlistentry>
<term><constant>v247</constant></term>
- <listitem><para>If the PCI slot is associated with PCI bridge and that has multiple child network
- controllers then all of them might derive the same value of <varname>ID_NET_NAME_SLOT</varname>
- property. That could cause naming conflict if the property is selected as a device name. Now, we detect the
- situation, slot - bridge relation, and we don't produce the <varname>ID_NET_NAME_SLOT</varname> property to
- avoid possible naming conflict.</para></listitem>
+ <listitem><para>When a PCI slot is associated with a PCI bridge that has multiple child network
+ controllers, the same value of the <varname>ID_NET_NAME_SLOT</varname> property might be derived
+ for those controllers. This would cause a naming conflict if the property is selected as the device
+ name. Now, we detect this situation and don't produce the <varname>ID_NET_NAME_SLOT</varname>
+ property.</para></listitem>
</varlistentry>
</variablelist>
<term><varname>BroadcastMulticastQueueLength=</varname></term>
<listitem>
<para>Specifies the length of the receive queue for broadcast/multicast packets. An unsigned
- integer in the range 0â\80\944294967294. Defaults to unset.</para>
+ integer in the range 0â\80¦4294967294. Defaults to unset.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>VNI=</varname></term>
<listitem>
- <para>The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1-16777215.</para>
+ <para>The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1…16777215.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>PeerTunnelId=</varname></term>
<listitem>
- <para>Specifies the peer tunnel id. Takes a number in the range 1â\80\944294967295. The value used must
+ <para>Specifies the peer tunnel id. Takes a number in the range 1â\80¦4294967295. The value used must
match the <literal>TunnelId=</literal> value being used at the peer. This setting is compulsory.
</para>
</listitem>
<varlistentry>
<term><varname>ERSPANIndex=</varname></term>
<listitem>
- <para>Specifies the ERSPAN index field for the interface, an integer in the range 1-1048575 associated with
+ <para>Specifies the ERSPAN index field for the interface, an integer in the range 1…1048575 associated with
the ERSPAN traffic's source port and direction. This field is mandatory.
</para>
</listitem>
<para>The <varname>Protocol=</varname> specifies the protocol number of the packets arriving
at the UDP port. When <varname>Encapsulation=FooOverUDP</varname>, this field is mandatory
and is not set by default. Takes an IP protocol name such as <literal>gre</literal> or
- <literal>ipip</literal>, or an integer within the range 1-255. When
+ <literal>ipip</literal>, or an integer within the range 1…255. When
<varname>Encapsulation=GenericUDPEncapsulation</varname>, this must not be specified.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AdActorSystemPriority=</varname></term>
<listitem>
- <para>Specifies the 802.3ad actor system priority. Takes a number in the range 1â\80\9465535.</para>
+ <para>Specifies the 802.3ad actor system priority. Takes a number in the range 1â\80¦65535.</para>
</listitem>
</varlistentry>
<para>Link groups are similar to port ranges found in managed switches.
When network interfaces are added to a numbered group, operations on
all the interfaces from that group can be performed at once. An unsigned
- integer in the range 0—4294967294. Defaults to unset.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><varname>TransmitQueues=</varname></term>
- <listitem>
- <para>Specifies the devices's number of transmit queues. An integer in the range 1...4096.
- When unset, the kernel's default will be used.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><varname>ReceiveQueues=</varname></term>
- <listitem>
- <para>Specifies the devices's number of receive queues. An integer in the range 1...4096.
- When unset, the kernel's default will be used.</para>
+ integer in the range 0…4294967294. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
if <literal>RequiredForOnline=no</literal>.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>ActivationPolicy=</varname></term>
+ <listitem>
+ <para>Specifies the policy for <command>systemd-networkd</command> managing the link
+ administrative state. Specifically, this controls how <command>systemd-networkd</command>
+ changes the network device's <literal>IFF_UP</literal> flag, which is sometimes
+ controlled by system administrators by running e.g., <command>ip set dev eth0 up</command>
+ or <command>ip set dev eth0 down</command>, and can also be changed with
+ <command>networkctl up eth0</command> or <command>networkctl down eth0</command>.</para>
+
+ <para>Takes one of <literal>up</literal>, <literal>always-up</literal>,
+ <literal>manual</literal>, <literal>always-down</literal>, <literal>down</literal>,
+ or <literal>bound</literal>. When <literal>manual</literal>, <command>systemd-networkd</command>
+ will not change the link's admin state automatically; the system administrator must bring the
+ interface up or down manually, as desired. When <literal>up</literal> (the default) or
+ <literal>always-up</literal>, or <literal>down</literal> or <literal>always-down</literal>,
+ <command>systemd-networkd</command> will set the link up or down, respectively,
+ when the interface is (re)configured. When <literal>always-up</literal> or
+ <literal>always-down</literal>, <command>systemd-networkd</command> will set the link up
+ or down, respectively, any time <command>systemd-networkd</command> detects a change in
+ the administrative state. When <varname>BindCarrier=</varname> is also set, this is
+ automatically set to <literal>bound</literal> and any other value is ignored.</para>
+
+ <para>The administrative state is not the same as the carrier state, so using
+ <literal>always-up</literal> does not mean the link will never lose carrier. The link
+ carrier depends on both the administrative state as well as the network device's physical
+ connection. However, to avoid reconfiguration failures, when using <literal>always-up</literal>,
+ <varname>IgnoreCarrierLoss=</varname> is forced to true.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<term><varname>VirtualFunction=</varname></term>
<listitem>
<para>Specifies a Virtual Function (VF), lightweight PCIe function designed solely to move data
- in and out. Takes an unsigned integer in the range 0..2147483646. This option is compulsory.</para>
+ in and out. Takes an unsigned integer in the range 0…2147483646. This option is compulsory.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>VLANId=</varname></term>
<listitem>
- <para>Specifies VLAN ID of the virtual function. Takes an unsigned integer in the range 1..4095.</para>
+ <para>Specifies VLAN ID of the virtual function. Takes an unsigned integer in the range 1…4095.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>QualityOfService=</varname></term>
<listitem>
- <para>Specifies quality of service of the virtual function. Takes an unsigned integer in the range 1..4294967294.</para>
+ <para>Specifies quality of service of the virtual function. Takes an unsigned integer in the range 1…4294967294.</para>
</listitem>
</varlistentry>
<listitem>
<para>A link name or a list of link names. When set, controls the behavior of the current
link. When all links in the list are in an operational down state, the current link is brought
- down. When at least one link has carrier, the current interface is brought up.
- </para>
+ down. When at least one link has carrier, the current interface is brought up.</para>
+
+ <para>This forces <varname>ActivationPolicy=</varname> to be set to <literal>bound</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>DNS=</varname></term>
<listitem>
- <para>A DNS server address, which must be in the format
- described in
+ <para>A DNS server address, which must be in the format described in
<citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
This option may be specified more than once. Each address can optionally take a port number
separated with <literal>:</literal>, a network interface name or index separated with
When IPv6 address is specified with a port number, then the address must be in the square
brackets. That is, the acceptable full formats are
<literal>111.222.333.444:9953%ifname#example.com</literal> for IPv4 and
- <literal>[1111:2222::3333]:9953%ifname#example.com</literal> for IPv6. This setting can be
- specified multiple times. If an empty string is assigned, then the all previous assignments
- are cleared. This setting is read by
+ <literal>[1111:2222::3333]:9953%ifname#example.com</literal> for IPv6. If an empty string is
+ assigned, then the all previous assignments are cleared. This setting is read by
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
of the interface even if its carrier is lost. When unset, the value specified with
<option>ConfigureWithoutCarrier=</option> is used.
</para>
+
+ <para>When <varname>ActivationPolicy=</varname> is set to <literal>always-up</literal>, this
+ is forced to <literal>true</literal>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>PreferredLifetime=</varname></term>
<listitem>
- <para>Allows the default "preferred lifetime" of the address to be overridden.
- Only three settings are accepted: <literal>forever</literal> or <literal>infinity</literal>
- which is the default and means that the address never expires, and <literal>0</literal> which means
- that the address is considered immediately "expired" and will not be used,
- unless explicitly requested. A setting of PreferredLifetime=0 is useful for
- addresses which are added to be used only by a specific application,
- which is then configured to use them explicitly.</para>
+ <para>Allows the default "preferred lifetime" of the address to be overridden. Only three
+ settings are accepted: <literal>forever</literal>, <literal>infinity</literal>, which is the
+ default and means that the address never expires, and <literal>0</literal>, which means that the
+ address is considered immediately "expired" and will not be used, unless explicitly requested. A
+ setting of <option>PreferredLifetime=0</option> is useful for addresses which are added to be
+ used only by a specific application, which is then configured to use them explicitly.</para>
</listitem>
</varlistentry>
<varlistentry>
<literal>global</literal> (valid everywhere on the network, even through a gateway),
<literal>link</literal> (only valid on this device, will not traverse a gateway) or
<literal>host</literal> (only valid within the device itself, e.g. 127.0.0.1)
- or an unsigned integer in the range 0â\80\94255.
+ or an unsigned integer in the range 0â\80¦255.
Defaults to <literal>global</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Table=</varname></term>
<listitem>
- <para>Specifies the routing table identifier to lookup if the rule selector matches. Takes
- one of <literal>default</literal>, <literal>main</literal>, and <literal>local</literal>,
+ <para>Specifies the routing table identifier to lookup if the rule selector matches. Takes one of predefined names
+ <literal>default</literal>, <literal>main</literal>, and <literal>local</literal>, and names defined in <varname>RouteTable=</varname>
+ in <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
or a number between 1 and 4294967295. Defaults to <literal>main</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SuppressPrefixLength=</varname></term>
<listitem>
- <para>Takes a number <replaceable>N</replaceable> in the range 0-128 and rejects routing
+ <para>Takes a number <replaceable>N</replaceable> in the range 0…128 and rejects routing
decisions that have a prefix length of <replaceable>N</replaceable> or less. Defaults to
unset.</para>
</listitem>
set, then the gateway address provided by DHCPv4 or IPv6 RA is used.</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><varname>GatewayOnLink=</varname></term>
- <listitem>
- <para>Takes a boolean. If set to true, the kernel does not have
- to check if the gateway is reachable directly by the current machine (i.e., the kernel does
- not need to check if the gateway is attached to the local network), so that we can insert the
- route in the kernel table without it being complained about. Defaults to <literal>no</literal>.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>GatewayOnLink=</varname></term>
+ <listitem>
+ <para>Takes a boolean. If set to true, the kernel does not have to check if the gateway is
+ reachable directly by the current machine (i.e., the kernel does not need to check if the
+ gateway is attached to the local network), so that we can insert the route in the kernel
+ table without it being complained about. Defaults to <literal>no</literal>.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>Destination=</varname></term>
<listitem>
<varlistentry>
<term><varname>Table=</varname></term>
<listitem>
- <para>The table identifier for the route. Takes <literal>default</literal>,
- <literal>main</literal>, <literal>local</literal> or a number between 1 and 4294967295.
- The table can be retrieved using <command>ip route show table <replaceable>num</replaceable></command>.
- If unset and <varname>Type=</varname> is <literal>local</literal>, <literal>broadcast</literal>,
- <literal>anycast</literal>, or <literal>nat</literal>, then <literal>local</literal> is used.
+ <para>The table identifier for the route. Takes one of predefined names <literal>default</literal>, <literal>main</literal>,
+ and <literal>local</literal>, and names defined in <varname>RouteTable=</varname> in <citerefentry><refentrytitle>networkd.conf</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry>, or a number between 1 and 4294967295. The table can be retrieved using
+ <command>ip route show table <replaceable>num</replaceable></command>. If unset and <varname>Type=</varname> is <literal>local</literal>,
+ <literal>broadcast</literal>, <literal>anycast</literal>, or <literal>nat</literal>, then <literal>local</literal> is used.
In other cases, defaults to <literal>main</literal>.
</para>
</listitem>
<varlistentry>
<term><varname>RequestOptions=</varname></term>
<listitem>
- <para>When configured, allows to set arbitrary request options in the DHCPv4 request options list and will be
- sent to the DHCPV4 server. A whitespace-separated list of integers in the range 1..254. Defaults to unset.</para>
+ <para>Sets request options to be sent to the server in the DHCPv4 request options list. A
+ whitespace-separated list of integers in the range 1…254. Defaults to unset.</para>
</listitem>
</varlistentry>
<para>Send an arbitrary raw option in the DHCPv4 request. Takes a DHCP option number, data type
and data separated with a colon
(<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
- The option number must be an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
- <literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
- <literal>string</literal>. Special characters in the data string may be escaped using
- <ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
+ The option number must be an integer in the range 1…254. The type takes one of
+ <literal>uint8</literal>, <literal>uint16</literal>, <literal>uint32</literal>,
+ <literal>ipv4address</literal>, or <literal>string</literal>. Special characters in the data
+ string may be escaped using <ulink
+ url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.</para>
</listitem>
<varlistentry>
<term><varname>SendVendorOption=</varname></term>
<listitem>
- <para>Send an arbitrary vendor option in the DHCPv4 request. Takes a DHCP option number, data type
- and data separated with a colon
+ <para>Send an arbitrary vendor option in the DHCPv4 request. Takes a DHCP option number, data
+ type and data separated with a colon
(<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
- The option number must be an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
- <literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
- <literal>string</literal>. Special characters in the data string may be escaped using
- <ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
+ The option number must be an integer in the range 1…254. The type takes one of
+ <literal>uint8</literal>, <literal>uint16</literal>, <literal>uint32</literal>,
+ <literal>ipv4address</literal>, or <literal>string</literal>. Special characters in the data
+ string may be escaped using <ulink
+ url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.</para>
</listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>UseFQDN=</varname></term>
+ <listitem>
+ <para>Equivalent of <varname>UseHostname=</varname> in the [DHCPv4] section.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<term><varname>MUDURL=</varname></term>
<listitem>
<para>When configured, the specified Manufacturer Usage Description (MUD) URL will be sent to
- the DHCPV6 server. The syntax and semantics are the same as for <varname>MUDURL=</varname> in the
+ the DHCPv6 server. The syntax and semantics are the same as for <varname>MUDURL=</varname> in the
[DHCPv4] section described above.</para>
</listitem>
</varlistentry>
<term><varname>RequestOptions=</varname></term>
<listitem>
<para>When configured, allows to set arbitrary request options in the DHCPv6 request options list
- that will be sent to the DHCPV6 server. A whitespace-separated list of integers in the range
- 1..254. Defaults to unset.</para>
+ that will be sent to the DHCPv6 server. A whitespace-separated list of integers in the range
+ 1…254. Defaults to unset.</para>
</listitem>
</varlistentry>
<term><varname>SendOption=</varname></term>
<listitem>
<para>As in the [DHCPv4] section, however because DHCPv6 uses 16-bit fields to store
- option numbers, the option number is an integer in the range 1..65536.</para>
+ option numbers, the option number is an integer in the range 1…65536.</para>
</listitem>
</varlistentry>
servers set. The "uplink" interface is determined by the default route of the system with the highest
priority. Note that this information is acquired at the time the lease is handed out, and does not
take uplink interfaces into account that acquire DNS server information at a later point. If no
- suitable uplinkg interface is found the DNS server data from <filename>/etc/resolv.conf</filename> is
+ suitable uplink interface is found the DNS server data from <filename>/etc/resolv.conf</filename> is
used. Also, note that the leases are not refreshed if the uplink network configuration changes. To
ensure clients regularly acquire the most current uplink DNS server information, it is thus advisable
to shorten the DHCP lease time via <varname>MaxLeaseTimeSec=</varname> described
<listitem>
<para>Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type
and data (<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
- The option number is an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
+ The option number is an integer in the range 1…254. The type takes one of <literal>uint8</literal>,
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, <literal>ipv6address</literal>, or
<literal>string</literal>. Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
<listitem>
<para>Send a vendor option with value via DHCPv4 server. Takes a DHCP option number, data type
and data (<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
- The option number is an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
+ The option number is an integer in the range 1…254. The type takes one of <literal>uint8</literal>,
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
<literal>string</literal>. Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
<term><varname>VNI=</varname></term>
<listitem>
<para>The VXLAN Network Identifier (or VXLAN Segment ID) to use to connect to
- the remote VXLAN tunnel endpoint. Takes a number in the range 1-16777215.
+ the remote VXLAN tunnel endpoint. Takes a number in the range 1…16777215.
Defaults to unset.</para>
</listitem>
</varlistentry>
<term><varname>BitRate=</varname></term>
<listitem>
<para>The bitrate of CAN device in bits per second. The usual SI prefixes (K, M) with the base of 1000 can
- be used here. Takes a number in the range 1..4294967295.</para>
+ be used here. Takes a number in the range 1…4294967295.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>PacketLimit=</varname></term>
<listitem>
- <para>Specifies the hard limit on the queue size in number of packets. When this limit is reached, incoming packets are
- dropped. An unsigned integer in the range 1–4294967294. Defaults to unset and kernel's default is used.</para>
+ <para>Specifies the hard limit on the queue size in number of packets. When this limit is reached,
+ incoming packets are dropped. An unsigned integer in the range 1…4294967294. Defaults to unset and
+ kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>PacketLimit=</varname></term>
<listitem>
- <para>Specifies the hard limit on the queue size in number of packets. When this limit is reached, incoming packets are
- dropped. An unsigned integer ranges 1 to 4294967294. Defaults to unset and kernel's default is used.</para>
+ <para>Specifies the hard limit on the queue size in number of packets. When this limit is reached,
+ incoming packets are dropped. An unsigned integer ranges 1 to 4294967294. Defaults to unset and
+ kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>PacketLimit=</varname></term>
<listitem>
- <para>Specifies the hard limit on the FIFO size in number of packets. The size limit (a buffer
- size) to prevent it from overflowing in case it is unable to dequeue packets as quickly as it
- receives them. When this limit is reached, incoming packets are dropped. An unsigned integer in the
- range 0–4294967294. Defaults to unset and kernel's default is used.</para>
+ <para>Specifies the hard limit on the number of packets in the FIFO queue. The size limit prevents
+ overflow in case the kernel is unable to dequeue packets as quickly as it receives them. When this
+ limit is reached, incoming packets are dropped. An unsigned integer in the range
+ 0–4294967294. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
separated list of numbers. The first number indicates which band the packets with priority 0 should
be put to, the second is for priority 1, and so on. There can be up to 16 numbers in the list. If
there are fewer, the default band that traffic with one of the unmentioned priorities goes to is
- the last one. Each band number must be in the range 0..255. This setting can be specified multiple
+ the last one. Each band number must be in the range 0…255. This setting can be specified multiple
times. If an empty string is assigned, then the all previous assignments are cleared.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>VirtualQueues=</varname></term>
<listitem>
- <para>Specifies the number of virtual queues. Takes a integer in the range 1-16. Defaults to unset and kernel's default is used.</para>
+ <para>Specifies the number of virtual queues. Takes a integer in the range 1…16. Defaults to unset
+ and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Weight=</varname></term>
<listitem>
- <para>Specifies the weight of the class. Takes an integer in the range 1..1023. Defaults to
+ <para>Specifies the weight of the class. Takes an integer in the range 1…1023. Defaults to
unset in which case the kernel default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MaxPacketBytes=</varname></term>
<listitem>
- <para>Specifies the maximum packet size in bytes for the class. When suffixed with K, M, or G, the specified
- size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1024. When unset,
- the kernel default is used.</para>
+ <para>Specifies the maximum packet size in bytes for the class. When suffixed with K, M, or G, the
+ specified size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of
+ 1024. When unset, the kernel default is used.</para>
</listitem>
</varlistentry>
</variablelist>
<refsect1>
<title>Description</title>
- <para>Preset files may be used to encode policy which units shall
- be enabled by default and which ones shall be disabled. They are
- read by <command>systemctl preset</command> (for more information
- see
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)
- which uses this information to enable or disable a unit according
- to preset policy. <command>systemctl preset</command> is used by
- the post install scriptlets of RPM packages (or other OS package
- formats), to enable/disable specific units by default on package
- installation, enforcing distribution, spin or administrator preset
- policy. This allows choosing a certain set of units to be
- enabled/disabled even before installing the actual package.</para>
-
- <para>For more information on the preset logic please have a look
- at the <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/Preset">Presets</ulink>
- document.</para>
-
- <para>It is not recommended to ship preset files within the
- respective software packages implementing the units, but rather
- centralize them in a distribution or spin default policy, which
- can be amended by administrator policy.</para>
+ <para>Preset files may be used to encode policy which units shall be enabled by default and which ones
+ shall be disabled. They are read by <command>systemctl preset</command> which uses this information to
+ enable or disable a unit. Depending on that policy, <command>systemctl preset</command> is identical to
+ <command>systemctl enable</command> or <command>systemctl disable</command>.
+
+ <command>systemctl preset</command> is used by the post install scriptlets of rpm packages (or other OS
+ package formats), to enable/disable specific units by default on package installation, enforcing
+ distribution, spin or administrator preset policy. This allows choosing a certain set of units to be
+ enabled/disabled even before installing the actual package. For more information, see
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+
+ <para>It is not recommended to ship preset files within the respective software packages implementing the
+ units, but rather centralize them in a distribution or spin default policy, which can be amended by
+ administrator policy, see below.</para>
<para>If no preset files exist, <command>systemctl
preset</command> will enable all units that are installed by
override all other preset policy files.</para>
</refsect1>
+ <refsect1>
+ <title>Motivation for the preset logic</title>
+
+ <para>Different distributions have different policies on which services shall be enabled by default when
+ the package they are shipped in is installed. On Fedora all services stay off by default, so that
+ installing a package will not cause a service to be enabled (with some exceptions). On Debian all
+ services are immediately enabled by default, so that installing a package will cause its services to be
+ enabled right-away.</para>
+
+ <para>Even within a single distribution, different spins (flavours, remixes, whatever you might want to
+ call them) of a distribution also have different policies on what services to enable, and what services
+ to leave off. For example, Fedora Workstation will enable <command>gdm</command> as display manager by
+ default, while the Fedora KDE spin will enable <command>sddm</command> instead.</para>
+
+ <para>Different sites might also have different policies what to turn on by default and what to turn
+ off. For example, one administrator would prefer to enforce the policy of "<command>sshd</command> should
+ be always on, but everything else off", while another one might say "<command>snmpd</command> always on,
+ and for everything else use the distribution policy defaults".</para>
+
+ <para>Traditionally, policy about which services shall be enabled were implemented in each package
+ individually. This made it cumbersome to implement different policies per spin or per site, or to create
+ software packages that do the right thing on more than one distribution. The enablement mechanism was
+ also encoding the enablement policy.</para>
+
+ <para>The preset mechanism allows clean separation of the enablement mechanism (inside the package
+ scriptlets, by invoking <command>systemctl preset</command>) and enablement policy (centralized in the
+ preset files), and lifts the configuration out of individual packages. Preset files may be written for
+ specific distributions, for specific spins or for specific sites, in order to enforce different policies
+ as needed. It is recommended to apply the policy encoded in preset files in package installation
+ scriptlets.</para>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-delta</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
+
+ <para><citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ has a discussion of packaging scriptlets.</para>
+
+ <para>Fedora page introducing the use of presets:
+ <ulink url="https://fedoraproject.org/wiki/Features/PackagePresets">Features/PackagePresets</ulink>.
+ </para>
</refsect1>
</refentry>
<listitem>
<para>Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices
or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper
- CPU indices separated by a dash.</para>
+ NUMA nodes indices separated by a dash.</para>
<para>Setting <varname>AllowedMemoryNodes=</varname> doesn't guarantee that all of the memory NUMA nodes will
be used by the processes as it may be limited by parent units. The effective configuration is reported as
</varlistentry>
<varlistentry>
- <term><varname>ManagedOOMMemoryPressureLimitPercent=</varname></term>
+ <term><varname>ManagedOOMMemoryPressureLimit=</varname></term>
<listitem>
<para>Overrides the default memory pressure limit set by
- <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for this unit
- (cgroup). Takes a percentage value between 0% and 100%, inclusive. This property is ignored unless
- <varname>ManagedOOMMemoryPressure=</varname><option>kill</option>. Defaults to 0%, which means use the
- default set by <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ this unit (cgroup). Takes a percentage value between 0% and 100%, inclusive. This property is
+ ignored unless <varname>ManagedOOMMemoryPressure=</varname><option>kill</option>. Defaults to 0%,
+ which means to use the default set by
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>ManagedOOMPreference=none|avoid|omit</varname></term>
+
+ <listitem>
+ <para>Allows deprioritizing or omitting this unit's cgroup as a candidate when <command>systemd-oomd</command>
+ needs to act. Requires support for extended attributes (see
+ <citerefentry project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
+ in order to use <option>avoid</option> or <option>omit</option>. Additionally, <command>systemd-oomd</command>
+ will ignore these extended attributes if the unit's cgroup is not owned by the root user.</para>
+
+ <para>If this property is set to <option>avoid</option>, the service manager will set the
+ "user.oomd_avoid" extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees
+ this extended attribute on a cgroup set to "1" when choosing between candidates, it will only select the
+ cgroup with "user.oomd_avoid" if there are no other viable candidates.</para>
+
+ <para>If this property is set to <option>omit</option>, the service manager will set the "user.oomd_omit"
+ extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees the this extended
+ attribute on the cgroup set to "1", it will ignore the cgroup as a candidate and will not perform any actions
+ on the cgroup.</para>
+
+ <para>It is recommended to use <option>avoid</option> and <option>omit</option> sparingly as it can adversely
+ affect <command>systemd-oomd</command>'s kill behavior. Also note that these extended attributes are not
+ applied recursively to cgroups under this unit's cgroup.</para>
+
+ <para>Defaults to <option>none</option> which means no extended attributes will be set and systemd-oomd will
+ sort this unit's cgroup as defined in
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ and <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> (if this
+ unit's cgroup becomes a candidate).</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
abnormally by a signal, or hit a timeout.</para>
<table>
- <title>Exit causes and the effect of the <varname>Restart=</varname> settings on them</title>
+ <title>Exit causes and the effect of the <varname>Restart=</varname> settings</title>
<tgroup cols='2'>
<colspec colname='path' />
<para>The XDG specification defines a way to autostart applications using XDG desktop files.
systemd ships
<citerefentry><refentrytitle>systemd-xdg-autostart-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for the XDG desktop files in autostart directories.
- Desktop Environments can opt-in to use this service by adding a <varname>Wants=</varname>
- dependency on <literal>xdg-desktop-autostart.target</literal>.</para>
+ for the XDG desktop files in autostart directories. Desktop Environments can opt-in to use this
+ service by adding a <varname>Wants=</varname> dependency on
+ <filename>xdg-desktop-autostart.target</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
<para><command>userdbctl</command> may be used to inspect user and groups (as well as group memberships)
of the system. This client utility inquires user/group information provided by various system services,
both operating on JSON user/group records (as defined by the <ulink
- url="https://systemd.io/USER_RECORD">JSON User Record</ulink> and <ulink
- url="https://systemd.io/GROUP_RECORD">JSON Group Record</ulink> definitions), and classic UNIX NSS/glibc
+ url="https://systemd.io/USER_RECORD">JSON User Records</ulink> and <ulink
+ url="https://systemd.io/GROUP_RECORD">JSON Group Records</ulink> definitions), and classic UNIX NSS/glibc
user and group records. This tool is primarily a client to the <ulink
url="https://systemd.io/USER_GROUP_API">User/Group Record Lookup API via Varlink</ulink>.</para>
</refsect1>
</varlistentry>
<varlistentry>
- <term><constant>io.systemd.NameSeviceSwitch</constant></term>
+ <term><constant>io.systemd.NameServiceSwitch</constant></term>
<listitem><para>This service is (also) provided by
<citerefentry><refentrytitle>systemd-userdbd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<para>Note that <command>userdbctl</command> has internal support for NSS-based lookups too. This means
that if neither <constant>io.systemd.Multiplexer</constant> nor
- <constant>io.systemd.NameSeviceSwitch</constant> are running look-ups into the basic user/group
+ <constant>io.systemd.NameServiceSwitch</constant> are running look-ups into the basic user/group
databases will still work.</para>
</refsect1>
else
split_usr = get_option('split-usr') == 'true'
endif
+if split_usr
+ warning('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n'
+ + ' split-usr mode is going to be removed\n' +
+ '\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
+endif
conf.set10('HAVE_SPLIT_USR', split_usr,
description : '/usr/bin and /bin directories are separate')
conf.set10('ENABLE_PAM_HOME', have)
have = get_option('oomd')
-if have == 'auto'
- have = get_option('mode') == 'developer'
-else
- have = have == 'true'
- if have and get_option('mode') != 'developer'
- warning('oomd is not ready for release mode (yet)')
- endif
-endif
conf.set10('ENABLE_OOMD', have)
substs.set10('ENABLE_OOMD', have)
############################################################
-autosuspend_update_sh = find_program('tools/autosuspend-update.sh')
-hwdb_update_sh = find_program('tools/hwdb-update.sh')
+generate_gperfs = find_program('tools/generate-gperfs.py')
make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
make_directive_index_py = find_program('tools/make-directive-index.py')
make_man_index_py = find_program('tools/make-man-index.py')
-syscall_table_update_sh = find_program('tools/syscall-table-update.sh')
-xml_helper_py = find_program('tools/xml_helper.py')
-update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
-generate_gperfs = find_program('tools/generate-gperfs.py')
+update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
+update_hwdb_sh = find_program('tools/update-hwdb.sh')
+update_hwdb_autosuspend_sh = find_program('tools/update-hwdb-autosuspend.sh')
+update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh')
+xml_helper_py = find_program('tools/xml_helper.py')
#####################################################################
basic_includes = include_directories(
'src/basic',
+ 'src/fundamental',
'src/systemd',
'.')
subdir('po')
subdir('catalog')
+subdir('src/fundamental')
subdir('src/basic')
subdir('src/libsystemd')
subdir('src/shared')
libsystemd_sources,
basic_sources,
basic_gcrypt_sources,
+ fundamental_sources,
disable_mempool_c,
include_directories : libsystemd_includes,
build_by_default : static_libsystemd != 'false',
install_libudev_static = static_library(
'udev',
basic_sources,
+ fundamental_sources,
shared_sources,
libsystemd_sources,
libudev_sources,
subdir('src/portable')
subdir('src/pstore')
subdir('src/resolve')
+subdir('src/rpm')
subdir('src/shutdown')
subdir('src/sysext')
subdir('src/systemctl')
link_with : [libshared],
install_rpath : rootlibexecdir,
install : true,
- install_dir : rootlibexecdir)
+ install_dir : rootbindir)
endif
if conf.get('ENABLE_USERDB') == 1
public_programs += executable(
'udevadm',
udevadm_sources,
- c_args : '-DLOG_REALM=LOG_REALM_UDEV',
include_directories : includes,
link_with : [libudevd_core],
dependencies : [versiondep,
'docs/TRANSIENT-SETTINGS.md',
'docs/TRANSLATORS.md',
'docs/UIDS-GIDS.md',
- 'src/libsystemd/sd-bus/GVARIANT-SERIALIZATION',
+ 'docs/GVARIANT-SERIALIZATION.md',
install_dir : docdir)
meson.add_install_script('sh', '-c', mkdir_p.format(systemdstatedir))
depends : [man, libsystemd, libudev],
command : [check_api_docs_sh, libsystemd.full_path(), libudev.full_path()])
+############################################################
+
+if dbus_docs.length() > 0
+ custom_target(
+ 'update-dbus-docs',
+ output : 'update-dbus-docs',
+ command : [update_dbus_docs_py,
+ '--build-dir=@0@'.format(project_build_root),
+ '@INPUT@'],
+ input : dbus_docs)
+
+ if conf.get('BUILD_MODE') == 'BUILD_MODE_DEVELOPER'
+ test('dbus-docs-fresh',
+ update_dbus_docs_py,
+ args : ['--build-dir=@0@'.format(project_build_root),
+ '--test'] + dbus_docs)
+ endif
+endif
+
+custom_target(
+ 'update-man-rules',
+ output : 'update-man-rules',
+ command : ['sh', '-c',
+ 'cd @0@ && '.format(meson.build_root()) +
+ 'python3 @0@/tools/update-man-rules.py $(find @0@ -wholename "*/man/*.xml") >t && '.format(project_source_root) +
+ 'mv t @0@/man/rules/meson.build'.format(meson.current_source_dir())],
+ depend_files : custom_entities_ent)
+
############################################################
watchdog_opt = service_watchdog == '' ? 'disabled' : service_watchdog
conf.get('SYSTEM_ALLOC_UID_MIN')),
'system GIDs: <=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_GID_MAX'),
conf.get('SYSTEM_ALLOC_GID_MIN')),
- 'dynamic UIDs: @0@â\80\93@1@'.format(dynamic_uid_min, dynamic_uid_max),
- 'container UID bases: @0@â\80\93@1@'.format(container_uid_base_min, container_uid_base_max),
+ 'dynamic UIDs: @0@â\80¦@1@'.format(dynamic_uid_min, dynamic_uid_max),
+ 'container UID bases: @0@â\80¦@1@'.format(container_uid_base_min, container_uid_base_max),
'/dev/kvm access mode: @0@'.format(get_option('dev-kvm-mode')),
'render group access mode: @0@'.format(get_option('group-render-mode')),
'certificate root directory: @0@'.format(get_option('certificate-root')),
description : 'install the coredump handler')
option('pstore', type : 'boolean',
description : 'install the pstore archival tool')
-option('oomd', type : 'combo', choices : ['auto', 'true', 'false'],
+option('oomd', type : 'boolean',
description : 'install the userspace oom killer')
option('logind', type : 'boolean',
description : 'install the systemd-logind stack')
fi
cd "$BUILDDIR"
-ninja
+ninja "$@"
if [ "$WITH_TESTS" = 1 ] ; then
for id in 1 2 3; do
getent group $id > /dev/null || groupadd -g $id testgroup$id
<?xml version="1.0"?>
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<its:rules xmlns:its="http://www.w3.org/2005/11/its"
version="2.0">
<its:translateRule selector="//*" translate="no"/>
<?xml version="1.0"?>
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<locatingRules>
<locatingRule name="polkit policy" pattern="*.policy">
<documentRule localName="policyconfig" target="polkit.its"/>
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
# Moo, 2018. #zanata
msgid ""
msgstr ""
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the systemd package.
-# A S Alam <amanpreet.alam@gmail.com>, 2020.
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# A S Alam <amanpreet.alam@gmail.com>, 2020, 2021.
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
-"PO-Revision-Date: 2020-12-21 07:36+0000\n"
+"PO-Revision-Date: 2021-01-24 16:38+0000\n"
"Last-Translator: A S Alam <amanpreet.alam@gmail.com>\n"
"Language-Team: Punjabi <https://translate.fedoraproject.org/projects/systemd/"
"master/pa/>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.3.2\n"
+"X-Generator: Weblate 4.4.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
-msgstr "ਦਿੱਤਾ ਵਾà¨\95 ਸਿਸà¨\9fਮ ਨà©\82à©° ਵਾਪਸ à¨à©\87à¨\9cਣ ਲà¨\88 ਪਰਮਾਣà¨\95ਿਤਾ à¨\9aਾਹà©\80ਦਾ ਹੈ।"
+msgstr "ਦਿੱਤਾ ਵਾà¨\95 ਸਿਸà¨\9fਮ ਨà©\82à©° ਵਾਪਸ à¨à©\87à¨\9cਣ ਲà¨\88 ਪਰਮਾਣà¨\95ਿਤਾ à¨\9aਾਹà©\80ਦà©\80 ਹੈ।"
#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
-msgstr ""
+msgstr "systemd ਹਾਲਤ ਮੁੜ ਲੋਡ ਕਰੋ"
#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
# Sebastian Rasmussen <sebras@gmail.com>, 2015.
# Andreas Henriksson <andreas@fatal.se>, 2016.
# Josef Andersson <l10nl18nsweja@gmail.com>, 2015, 2017.
-# Göran Uddeborg <goeran@uddeborg.se>, 2020.
+# Göran Uddeborg <goeran@uddeborg.se>, 2020, 2021.
# Luna Jernberg <bittin@reimu.nl>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
-"PO-Revision-Date: 2020-12-16 12:36+0000\n"
-"Last-Translator: Luna Jernberg <bittin@reimu.nl>\n"
+"PO-Revision-Date: 2021-02-10 15:40+0000\n"
+"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <https://translate.fedoraproject.org/projects/systemd/"
"master/sv/>\n"
"Language: sv\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.3.2\n"
+"X-Generator: Weblate 4.4.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
#: src/home/org.freedesktop.home1.policy:13
msgid "Create a home area"
-msgstr ""
+msgstr "Skapa en hemarea"
#: src/home/org.freedesktop.home1.policy:14
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to create a user's home area."
-msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+msgstr "Autentisering krävs för att skapa en användares hemarea."
#: src/home/org.freedesktop.home1.policy:23
msgid "Remove a home area"
-msgstr ""
+msgstr "Ta bort en hemarea"
#: src/home/org.freedesktop.home1.policy:24
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to remove a user's home area."
-msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+msgstr "Autentisering krävs för att ta bort en användares hemarea."
#: src/home/org.freedesktop.home1.policy:33
msgid "Check credentials of a home area"
-msgstr ""
+msgstr "Kontrollera kreditiven för en hemarea"
#: src/home/org.freedesktop.home1.policy:34
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to manage active sessions, users and seats."
msgid ""
"Authentication is required to check credentials against a user's home area."
msgstr ""
-"Autentisering krävs för att hantera aktiva sessioner, användare och platser."
+"Autentisering krävs för att kontrollera kreditiven mot en användares hemarea."
#: src/home/org.freedesktop.home1.policy:43
msgid "Update a home area"
-msgstr ""
+msgstr "Uppdatera en hemarea"
#: src/home/org.freedesktop.home1.policy:44
-#, fuzzy
-#| msgid "Authentication is required to attach a device to a seat."
msgid "Authentication is required to update a user's home area."
-msgstr "Autentisering krävs för att binda en enhet till en plats."
+msgstr "Autentisering krävs för att uppdatera en användares hemarea."
#: src/home/org.freedesktop.home1.policy:53
msgid "Resize a home area"
-msgstr ""
+msgstr "Ändra storlek på en hemarea"
#: src/home/org.freedesktop.home1.policy:54
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to resize a user's home area."
-msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+msgstr "Autentisering krävs för att ändra storlek på en hemarea."
#: src/home/org.freedesktop.home1.policy:63
msgid "Change password of a home area"
-msgstr ""
+msgstr "Ändra lösenord för en hemarea"
#: src/home/org.freedesktop.home1.policy:64
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to manage active sessions, users and seats."
msgid ""
"Authentication is required to change the password of a user's home area."
-msgstr ""
-"Autentisering krävs för att hantera aktiva sessioner, användare och platser."
+msgstr "Autentisering krävs för att ändra lösenorded för en användares hemarea."
#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set hostname"
#: src/hostname/org.freedesktop.hostname1.policy:51
msgid "Get product UUID"
-msgstr ""
+msgstr "Hämta produkt-UUID"
#: src/hostname/org.freedesktop.hostname1.policy:52
-#, fuzzy
-#| msgid "Authentication is required to reload '$(unit)'."
msgid "Authentication is required to get product UUID."
-msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"."
+msgstr "Autentisering krävs för att hämta produkt-UUID."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
"av brytaren för datorhöljet."
#: src/login/org.freedesktop.login1.policy:117
-#, fuzzy
-#| msgid "Allow applications to inhibit system handling of the power key"
msgid "Allow applications to inhibit system handling of the reboot key"
-msgstr "Tillåt program att hindra systemhantering av strömknappen"
+msgstr "Tillåt program att hindra systemhantering av omstartsknappen"
#: src/login/org.freedesktop.login1.policy:118
-#, fuzzy
-#| msgid ""
-#| "Authentication is required for an application to inhibit system handling "
-#| "of the power key."
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the reboot key."
msgstr ""
"Autentisering krävs för att tillåta ett program att hindra systemhantering "
-"av strömknappen."
+"av omstartsknappen."
#: src/login/org.freedesktop.login1.policy:128
msgid "Allow non-logged-in user to run programs"
msgstr "Stoppa systemet även då ett program hindrar det"
#: src/login/org.freedesktop.login1.policy:258
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to hibernate the system while an application "
-#| "is inhibiting this."
msgid ""
"Authentication is required to halt the system while an application is "
"inhibiting this."
msgstr ""
-"Autentisering krävs för att försätta ett program i viloläge även då ett "
-"program hindrar det."
+"Autentisering krävs för att stoppa systemet även då ett program hindrar det."
#: src/login/org.freedesktop.login1.policy:268
msgid "Suspend the system"
"Authentication is required to suspend the system while an application is "
"inhibiting this."
msgstr ""
-"Autentisering krävs för att försätta ett program i vänteläge även då ett "
-"program hindrar det."
+"Autentisering krävs för att försätta systemet i sovläge även då ett program "
+"hindrar det."
#: src/login/org.freedesktop.login1.policy:300
msgid "Hibernate the system"
"Authentication is required to hibernate the system while an application is "
"inhibiting this."
msgstr ""
-"Autentisering krävs för att försätta ett program i viloläge även då ett "
-"program hindrar det."
+"Autentisering krävs för att försätta systemet i viloläge även då ett program "
+"hindrar det."
#: src/login/org.freedesktop.login1.policy:332
msgid "Manage active sessions, users and seats"
#: src/login/org.freedesktop.login1.policy:352
msgid "Set the reboot \"reason\" in the kernel"
-msgstr ""
+msgstr "Sätt ”orsaken” för omstart i kärnan"
#: src/login/org.freedesktop.login1.policy:353
-#, fuzzy
-#| msgid "Authentication is required to set the system timezone."
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
-msgstr "Autentisering krävs för att ställa in systemets tidszon."
+msgstr "Autentisering krävs för att ställa in ”orsaken” för omstart i kärnan."
#: src/login/org.freedesktop.login1.policy:363
-#, fuzzy
-#| msgid "Allow indication to the firmware to boot to setup interface"
msgid "Indicate to the firmware to boot to setup interface"
msgstr ""
-"Tillåt indikering till firmware att starta upp i inställningsgränssnitt"
+"Indikera till den fasta programvaran att starta upp till "
+"inställningsgränssnittet"
#: src/login/org.freedesktop.login1.policy:364
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
msgstr ""
-"Autentisering krävs för att indikera till firmware att starta upp till "
-"inställningsgränssnitt."
+"Autentisering krävs för att indikera till den fasta programvaran att starta "
+"upp till inställningsgränssnitt."
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot to the boot loader menu"
-msgstr ""
+msgstr "Indikera till startprogrammet att starta upp i uppstartsladdmenyn"
#: src/login/org.freedesktop.login1.policy:375
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to indicate to the firmware to boot to setup "
-#| "interface."
msgid ""
"Authentication is required to indicate to the boot loader to boot to the "
"boot loader menu."
msgstr ""
-"Autentisering krävs för att indikera till firmware att starta upp till "
-"inställningsgränssnitt."
+"Autentisering krävs för att indikera till uppstartsladdaren att starta upp "
+"uppstartsladdmenyn."
#: src/login/org.freedesktop.login1.policy:385
msgid "Indicate to the boot loader to boot a specific entry"
-msgstr ""
+msgstr "Indikera till uppstartsladdaren att starta en specifik post"
#: src/login/org.freedesktop.login1.policy:386
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to indicate to the firmware to boot to setup "
-#| "interface."
msgid ""
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
msgstr ""
-"Autentisering krävs för att indikera till firmware att starta upp till "
-"inställningsgränssnitt."
+"Autentisering krävs för att indikera till uppstartsladdaren att starta upp "
+"till en specifik uppstartsladdspost."
#: src/login/org.freedesktop.login1.policy:396
msgid "Set a wall message"
#: src/login/org.freedesktop.login1.policy:406
msgid "Change Session"
-msgstr ""
+msgstr "Ändra session"
#: src/login/org.freedesktop.login1.policy:407
-#, fuzzy
-#| msgid "Authentication is required to halt the system."
msgid "Authentication is required to change the virtual terminal."
-msgstr "Autentisering krävs för att stoppa systemet."
+msgstr "Autentisering krävs för att ändra den virtuella terminalen."
#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
#: src/network/org.freedesktop.network1.policy:22
msgid "Set NTP servers"
-msgstr ""
+msgstr "Ange NTP-servrar"
#: src/network/org.freedesktop.network1.policy:23
msgid "Authentication is required to set NTP servers."
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
msgid "Set DNS servers"
-msgstr ""
+msgstr "Ange DNS-servrar"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
msgid "Set domains"
-msgstr ""
+msgstr "Ange domäner"
#: src/network/org.freedesktop.network1.policy:45
#: src/resolve/org.freedesktop.resolve1.policy:56
-#, fuzzy
-#| msgid "Authentication is required to stop '$(unit)'."
msgid "Authentication is required to set domains."
-msgstr "Autentisering krävs för att stoppa \"$(unit)\"."
+msgstr "Autentisering krävs för att ange domäner."
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
-msgstr ""
+msgstr "Ange standardrutt"
#: src/network/org.freedesktop.network1.policy:56
#: src/resolve/org.freedesktop.resolve1.policy:67
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to set default route."
-msgstr "Autentisering krävs för att ställa in lokalt värdnamn."
+msgstr "Autentisering krävs för att ange standardrutten."
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to enable or disable LLMNR."
-msgstr "Autentisering krävs för att försätta systemet i viloläge."
+msgstr "Autentisering krävs för att aktivera eller avaktivera LLMNR."
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
#: src/network/org.freedesktop.network1.policy:78
#: src/resolve/org.freedesktop.resolve1.policy:89
-#, fuzzy
-#| msgid "Authentication is required to log into the local host."
msgid "Authentication is required to enable or disable multicast DNS."
-msgstr "Autentisering krävs för att logga in på den lokala värden"
+msgstr "Autentisering krävs för att aktivera eller avaktivera multicast-DNS."
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
#: src/network/org.freedesktop.network1.policy:89
#: src/resolve/org.freedesktop.resolve1.policy:100
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr "Autentisering krävs för att ställa in lokalt värdnamn."
+msgstr "Autentisering krävs för att aktivera eller avaktivera DNS över TLS."
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
#: src/network/org.freedesktop.network1.policy:100
#: src/resolve/org.freedesktop.resolve1.policy:111
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to enable or disable DNSSEC."
-msgstr "Autentisering krävs för att försätta systemet i viloläge."
+msgstr "Autentisering krävs för att aktivera eller avaktivera DNSSEC."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
msgid "Set DNSSEC Negative Trust Anchors"
-msgstr ""
+msgstr "Ange DNSSEC negativa förtroendeankare"
#: src/network/org.freedesktop.network1.policy:111
#: src/resolve/org.freedesktop.resolve1.policy:122
-#, fuzzy
-#| msgid "Authentication is required to set the system locale."
msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
-msgstr "Autentisering krävs för att ställa in systemlokal."
+msgstr "Autentisering krävs för att ange DNSSEC negativa förtroendeankare."
#: src/network/org.freedesktop.network1.policy:121
msgid "Revert NTP settings"
-msgstr ""
+msgstr "Återställ NTP-inställningar"
#: src/network/org.freedesktop.network1.policy:122
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to reset NTP settings."
-msgstr "Autentisering krävs för ställa in systemtiden."
+msgstr "Autentisering krävs för återställa NTP-inställningar."
#: src/network/org.freedesktop.network1.policy:132
msgid "Revert DNS settings"
-msgstr ""
+msgstr "Återställ DNS-inställningar"
#: src/network/org.freedesktop.network1.policy:133
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to reset DNS settings."
-msgstr "Autentisering krävs för ställa in systemtiden."
+msgstr "Autentisering krävs för att återställa DNS-inställningar."
#: src/network/org.freedesktop.network1.policy:143
msgid "DHCP server sends force renew message"
-msgstr ""
+msgstr "DHCP-servern skickar tvingande förnyelsemeddelande"
#: src/network/org.freedesktop.network1.policy:144
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to send force renew message."
-msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+msgstr "Autentisering krävs för att skicka tvingande förnyelsemeddelande."
#: src/network/org.freedesktop.network1.policy:154
msgid "Renew dynamic addresses"
-msgstr ""
+msgstr "Förnya dynamiska adresser"
#: src/network/org.freedesktop.network1.policy:155
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to renew dynamic addresses."
-msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+msgstr "Autentisering krävs för att förnya dynamiska adresser."
#: src/network/org.freedesktop.network1.policy:165
msgid "Reload network settings"
-msgstr ""
+msgstr "Läs om nätverksinställningarna"
#: src/network/org.freedesktop.network1.policy:166
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to reload network settings."
-msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+msgstr "Autentisering krävs för läsa om nätverksinställningarna."
#: src/network/org.freedesktop.network1.policy:176
msgid "Reconfigure network interface"
-msgstr ""
+msgstr "Konfigurera om nätverksgränssnitt"
#: src/network/org.freedesktop.network1.policy:177
-#, fuzzy
-#| msgid "Authentication is required to reboot the system."
msgid "Authentication is required to reconfigure network interface."
-msgstr "Autentisering krävs för att starta om systemet."
+msgstr "Autentisering krävs för att konfigurera om nätverksgränssnitt."
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
-msgstr ""
+msgstr "Inspektera en portabel tjänsteavbild"
#: src/portable/org.freedesktop.portable1.policy:14
-#, fuzzy
-#| msgid "Authentication is required to import a VM or container image"
msgid "Authentication is required to inspect a portable service image."
-msgstr "Autentisering krävs för att importera en VM eller behållaravbildning"
+msgstr "Autentisering krävs för att inspektera en portabel tjänsteavbild."
#: src/portable/org.freedesktop.portable1.policy:23
msgid "Attach or detach a portable service image"
-msgstr ""
+msgstr "Koppla in eller koppla ifrån en portabel tjänsteavbild"
#: src/portable/org.freedesktop.portable1.policy:24
-#, fuzzy
-#| msgid "Authentication is required to attach a device to a seat."
msgid ""
"Authentication is required to attach or detach a portable service image."
-msgstr "Autentisering krävs för att binda en enhet till en plats."
+msgstr ""
+"Autentisering krävs för att koppla in eller koppla ifrån en portabel "
+"tjänsteavbild."
#: src/portable/org.freedesktop.portable1.policy:34
msgid "Delete or modify portable service image"
-msgstr ""
+msgstr "Radera eller modifiera en portabel tjänsteavbild"
#: src/portable/org.freedesktop.portable1.policy:35
-#, fuzzy
-#| msgid "Authentication is required to download a VM or container image"
msgid ""
"Authentication is required to delete or modify a portable service image."
-msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning"
+msgstr ""
+"Autentisering krävs för att radera eller modifiera en portabel tjänsteavbild."
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
msgstr "Registrera en DNS-SD-tjänst"
#: src/resolve/org.freedesktop.resolve1.policy:23
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to register a DNS-SD service"
-msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+msgstr "Autentisering krävs för att registrera en DNS-SD-tjänst"
#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
msgstr "Avregistrera en DNS-SD-tjänst"
#: src/resolve/org.freedesktop.resolve1.policy:34
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to unregister a DNS-SD service"
-msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+msgstr "Autentisering krävs för att avregistrera en DNS-SD-tjänst"
#: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings"
-msgstr ""
+msgstr "Återställ namnuppslagningsinställningar"
#: src/resolve/org.freedesktop.resolve1.policy:133
-#, fuzzy
-#| msgid "Authentication is required to set the system keyboard settings."
msgid "Authentication is required to reset name resolution settings."
-msgstr ""
-"Autentisering krävs för att ställa in systeminställningar för tangentbord."
+msgstr "Autentisering krävs för att återställa namnuppslagningsinställningar."
#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
#: src/core/dbus-unit.c:361
msgid "Authentication is required to reload '$(unit)'."
-msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"."
+msgstr "Autentisering krävs för att läsa om \"$(unit)\"."
#: src/core/dbus-unit.c:362 src/core/dbus-unit.c:363
msgid "Authentication is required to restart '$(unit)'."
msgstr "Autentisering krävs för att starta om \"$(unit)\"."
#: src/core/dbus-unit.c:535
-#, fuzzy
-#| msgid "Authentication is required to set properties on '$(unit)'."
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
-msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"."
+msgstr ""
+"Autentisering krävs för att skicka en UNIX-signal till processerna i "
+"”$(unit)”."
#: src/core/dbus-unit.c:566
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"."
#: src/core/dbus-unit.c:708
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgid ""
"Authentication is required to delete files and directories associated with "
"'$(unit)'."
msgstr ""
-"Autentisering krävs för att återställa det \"fallerade\" tillståndet för "
-"\"$(unit)\"."
+"Autentisering krävs för att radera filer och kataloger associerade med "
+"”$(unit)”."
#: src/core/dbus-unit.c:757
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgid ""
"Authentication is required to freeze or thaw the processes of '$(unit)' unit."
msgstr ""
-"Autentisering krävs för att återställa det \"fallerade\" tillståndet för "
-"\"$(unit)\"."
+"Autentisering krävs för att frysa eller töa processerna i enheten ”$(unit)”."
#~ msgid ""
#~ "Authentication is required to halt the system while an application asked "
IMPORT{builtin}="blkid --noraid"
# probe filesystem metadata of disks
-KERNEL!="sr*", IMPORT{builtin}="blkid"
+KERNEL!="sr*|mmcblk[0-9]boot[0-9]", IMPORT{builtin}="blkid"
# by-label/by-uuid links (filesystem metadata)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local OPTS='-h --help --version --no-pager --no-legend -o --output -F --field -1
-r --reverse -S --since -U --until -D --directory -q --quiet --debugger
- -A --debugger-arguments'
+ -A --debugger-arguments --json -n'
local -A VERBS=(
[LIST]='list info'
compopt -o filenames
elif __contains_word "$prev" '--field -F'; then
comps=$( compgen -W '${__journal_fields[*]}' -- "$cur" )
+ elif __contains_word "$prev" '--json'; then
+ comps=$( compgen -W 'pretty short off' -- "$cur" )
elif [[ $cur = -* ]]; then
comps=${OPTS}
elif __contains_word "$prev" ${VERBS[*]} &&
[STANDALONE]='--all -a --help -h --no-pager --version
--no-legend --no-ask-password -l --full --value'
[ARG]='--host -H --kill-who --property -p --signal -s -M --machine
- -n --lines -o --output'
+ -n --lines -o --output -P'
)
if __contains_word "$prev" ${OPTS[ARG]}; then
--machine|-M)
comps=$( __get_machines )
;;
- --property|-p)
+ --property|-p|-P)
comps=''
;;
--output|-o)
local -A VERBS=(
[STANDALONE]='list'
- [IMAGE]='attach detach inspect is-attached set-limit'
+ [IMAGE]='attach detach reattach inspect is-attached set-limit'
[IMAGES]='remove'
[IMAGE_WITH_BOOL]='read-only'
)
list-timers list-units list-unit-files poweroff
reboot rescue show-environment suspend get-default
is-system-running preset-all'
- [FILE]='link switch-root bind'
+ [FILE]='link switch-root bind mount-image'
[TARGETS]='set-default'
[MACHINES]='list-machines'
[LOG_LEVEL]='log-level'
"list-dependencies:Show unit dependency tree"
"clean:Remove configuration, state, cache, logs or runtime data of units"
"bind:Bind mount a path from the host into a unit's namespace"
+ "mount-image:Mount an image from the host into a unit's namespace"
)
local -a machine_commands=(
_files
}
+(( $+functions[_systemctl_mount-image] )) || _systemctl_mount-image() {
+ _files
+ }
+
# no systemctl completion for:
# [STANDALONE]='daemon-reexec daemon-reload default
# emergency exit halt kexec list-jobs list-units
"Report whether we are connected to an external power source.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
- " -v --verbose Show state as text\n"
- , program_invocation_short_name);
+ " -v --verbose Show state as text\n",
+ program_invocation_short_name);
}
static int parse_argv(int argc, char *argv[]) {
" --fdname=NAME[:NAME...] Specify names for file descriptors\n"
" --inetd Enable inetd file descriptor passing protocol\n"
"\nNote: file descriptors from sd_listen_fds() will be passed through.\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
if (a->default_dependencies_only && !info->default_dependencies) {
badness = UINT64_MAX;
- d = strdup("Service runs in special boot phase, option does not apply");
+ d = strdup("Service runs in special boot phase, option is not appropriate");
if (!d)
return log_oom();
} else {
#include "path-util.h"
#include "strv.h"
#include "unit-name.h"
+#include "unit-serialize.h"
static int prepare_filename(const char *filename, char **ret) {
int r;
STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
-struct boot_times {
+typedef struct BootTimes {
usec_t firmware_time;
usec_t loader_time;
usec_t kernel_time;
* (so it is stored here for reference).
*/
usec_t reverse_offset;
-};
+} BootTimes;
-struct unit_times {
+typedef struct UnitTimes {
bool has_data;
char *name;
usec_t activating;
usec_t deactivated;
usec_t deactivating;
usec_t time;
-};
+} UnitTimes;
-struct host_info {
+typedef struct HostInfo {
char *hostname;
char *kernel_name;
char *kernel_release;
char *os_pretty_name;
char *virtualization;
char *architecture;
-};
+} HostInfo;
static int acquire_bus(sd_bus **bus, bool *use_full_bus) {
bool user = arg_scope != UNIT_FILE_SYSTEM;
return 0;
}
-static int compare_unit_start(const struct unit_times *a, const struct unit_times *b) {
+static int compare_unit_start(const UnitTimes *a, const UnitTimes *b) {
return CMP(a->activating, b->activating);
}
-static void unit_times_free(struct unit_times *t) {
- struct unit_times *p;
-
- for (p = t; p->has_data; p++)
+static UnitTimes* unit_times_free_array(UnitTimes *t) {
+ for (UnitTimes *p = t; p && p->has_data; p++)
free(p->name);
- free(t);
+ return mfree(t);
}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct unit_times *, unit_times_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array);
static void subtract_timestamp(usec_t *a, usec_t b) {
assert(a);
}
}
-static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
+static int acquire_boot_times(sd_bus *bus, BootTimes **bt) {
static const struct bus_properties_map property_map[] = {
- { "FirmwareTimestampMonotonic", "t", NULL, offsetof(struct boot_times, firmware_time) },
- { "LoaderTimestampMonotonic", "t", NULL, offsetof(struct boot_times, loader_time) },
- { "KernelTimestamp", "t", NULL, offsetof(struct boot_times, kernel_time) },
- { "InitRDTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_time) },
- { "UserspaceTimestampMonotonic", "t", NULL, offsetof(struct boot_times, userspace_time) },
- { "FinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, finish_time) },
- { "SecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_start_time) },
- { "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_finish_time) },
- { "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_start_time) },
- { "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_finish_time) },
- { "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_start_time) },
- { "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_finish_time) },
- { "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_start_time) },
- { "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_finish_time) },
- { "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_start_time) },
- { "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_finish_time) },
- { "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_start_time) },
- { "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_finish_time) },
+ { "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) },
+ { "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) },
+ { "KernelTimestamp", "t", NULL, offsetof(BootTimes, kernel_time) },
+ { "InitRDTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_time) },
+ { "UserspaceTimestampMonotonic", "t", NULL, offsetof(BootTimes, userspace_time) },
+ { "FinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, finish_time) },
+ { "SecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_start_time) },
+ { "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_finish_time) },
+ { "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_start_time) },
+ { "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_finish_time) },
+ { "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_start_time) },
+ { "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_finish_time) },
+ { "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_start_time) },
+ { "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_finish_time) },
+ { "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_start_time) },
+ { "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_finish_time) },
+ { "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_start_time) },
+ { "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_finish_time) },
{},
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- static struct boot_times times;
+ static BootTimes times;
static bool cached = false;
int r;
} else {
/*
* User-instance-specific or container-system-specific timestamps processing
- * (see comment to reverse_offset in struct boot_times).
+ * (see comment to reverse_offset in BootTimes).
*/
times.reverse_offset = times.userspace_time;
return 0;
}
-static void free_host_info(struct host_info *hi) {
+static HostInfo* free_host_info(HostInfo *hi) {
if (!hi)
- return;
+ return NULL;
free(hi->hostname);
free(hi->kernel_name);
free(hi->os_pretty_name);
free(hi->virtualization);
free(hi->architecture);
- free(hi);
+ return mfree(hi);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info *, free_host_info);
+DEFINE_TRIVIAL_CLEANUP_FUNC(HostInfo *, free_host_info);
-static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
+static int acquire_time_data(sd_bus *bus, UnitTimes **out) {
static const struct bus_properties_map property_map[] = {
- { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activating) },
- { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activated) },
- { "ActiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivating) },
- { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivated) },
+ { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) },
+ { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) },
+ { "ActiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivating) },
+ { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivated) },
{},
};
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(unit_times_freep) struct unit_times *unit_times = NULL;
- struct boot_times *boot_times = NULL;
+ _cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL;
+ BootTimes *boot_times = NULL;
size_t allocated = 0, c = 0;
UnitInfo u;
int r;
return bus_log_parse_error(r);
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
- struct unit_times *t;
+ UnitTimes *t;
if (!GREEDY_REALLOC(unit_times, allocated, c + 2))
return log_oom();
return c;
}
-static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
+static int acquire_host_info(sd_bus *bus, HostInfo **hi) {
static const struct bus_properties_map hostname_map[] = {
- { "Hostname", "s", NULL, offsetof(struct host_info, hostname) },
- { "KernelName", "s", NULL, offsetof(struct host_info, kernel_name) },
- { "KernelRelease", "s", NULL, offsetof(struct host_info, kernel_release) },
- { "KernelVersion", "s", NULL, offsetof(struct host_info, kernel_version) },
- { "OperatingSystemPrettyName", "s", NULL, offsetof(struct host_info, os_pretty_name) },
+ { "Hostname", "s", NULL, offsetof(HostInfo, hostname) },
+ { "KernelName", "s", NULL, offsetof(HostInfo, kernel_name) },
+ { "KernelRelease", "s", NULL, offsetof(HostInfo, kernel_release) },
+ { "KernelVersion", "s", NULL, offsetof(HostInfo, kernel_version) },
+ { "OperatingSystemPrettyName", "s", NULL, offsetof(HostInfo, os_pretty_name) },
{}
};
static const struct bus_properties_map manager_map[] = {
- { "Virtualization", "s", NULL, offsetof(struct host_info, virtualization) },
- { "Architecture", "s", NULL, offsetof(struct host_info, architecture) },
+ { "Virtualization", "s", NULL, offsetof(HostInfo, virtualization) },
+ { "Architecture", "s", NULL, offsetof(HostInfo, architecture) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL;
- _cleanup_(free_host_infop) struct host_info *host;
+ _cleanup_(free_host_infop) HostInfo *host = NULL;
int r;
- host = new0(struct host_info, 1);
+ host = new0(HostInfo, 1);
if (!host)
return log_oom();
static int pretty_boot_time(sd_bus *bus, char **_buf) {
char ts[FORMAT_TIMESPAN_MAX];
- struct boot_times *t;
+ BootTimes *t;
static char buf[4096];
size_t size;
char *ptr;
}
static void svg_graph_box(double height, double begin, double end) {
- long long i;
-
/* outside box, fill */
svg("<rect class=\"box\" x=\"0\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
SCALE_X * (end - begin),
SCALE_Y * height);
- for (i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
+ for (long long i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
/* lines for each second */
if (i % 5000000 == 0)
svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
}
}
-static int plot_unit_times(struct unit_times *u, double width, int y) {
+static int plot_unit_times(UnitTimes *u, double width, int y) {
char ts[FORMAT_TIMESPAN_MAX];
bool b;
}
static int analyze_plot(int argc, char *argv[], void *userdata) {
- _cleanup_(free_host_infop) struct host_info *host = NULL;
+ _cleanup_(free_host_infop) HostInfo *host = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_(unit_times_freep) struct unit_times *times = NULL;
+ _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
_cleanup_free_ char *pretty_times = NULL;
bool use_full_bus = arg_scope == UNIT_FILE_SYSTEM;
- struct boot_times *boot;
- struct unit_times *u;
+ BootTimes *boot;
+ UnitTimes *u;
int n, m = 1, y = 0, r;
double width;
unsigned level,
unsigned branches,
bool last,
- struct unit_times *times,
- struct boot_times *boot) {
+ UnitTimes *times,
+ BootTimes *boot) {
- unsigned i;
char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX];
- for (i = level; i != 0; i--)
+ for (unsigned i = level; i != 0; i--)
printf("%s", special_glyph(branches & (1 << (i-1)) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
static int list_dependencies_compare(char *const *a, char *const *b) {
usec_t usa = 0, usb = 0;
- struct unit_times *times;
+ UnitTimes *times;
times = hashmap_get(unit_times_hashmap, *a);
if (times)
return CMP(usb, usa);
}
-static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) {
+static bool times_in_range(const UnitTimes *times, const BootTimes *boot) {
return times && times->activated > 0 && times->activated <= boot->finish_time;
}
int r;
usec_t service_longest = 0;
int to_print = 0;
- struct unit_times *times;
- struct boot_times *boot;
+ UnitTimes *times;
+ BootTimes *boot;
if (strv_extend(units, name))
return log_oom();
static int list_dependencies(sd_bus *bus, const char *name) {
_cleanup_strv_free_ char **units = NULL;
char ts[FORMAT_TIMESPAN_MAX];
- struct unit_times *times;
+ UnitTimes *times;
int r;
const char *id;
_cleanup_free_ char *path = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- struct boot_times *boot;
+ BootTimes *boot;
assert(bus);
static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_(unit_times_freep) struct unit_times *times = NULL;
- struct unit_times *u;
+ _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
Hashmap *h;
int n, r;
if (!h)
return log_oom();
- for (u = times; u->has_data; u++) {
+ for (UnitTimes *u = times; u->has_data; u++) {
r = hashmap_put(h, u->name, u);
if (r < 0)
return log_error_errno(r, "Failed to add entry to hashmap: %m");
static int analyze_blame(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_(unit_times_freep) struct unit_times *times = NULL;
+ _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
- struct unit_times *u;
TableCell *cell;
int n, r;
if (r < 0)
return r;
- for (u = times; u->has_data; u++) {
+ for (UnitTimes *u = times; u->has_data; u++) {
if (u->time <= 0)
continue;
if (r < 0)
return r;
- r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, "");
+ r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, NULL);
if (r < 0)
log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
status = exit_status_from_string(argv[i]);
if (status < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid exit status \"%s\".", argv[i]);
+ return log_error_errno(status, "Invalid exit status \"%s\".", argv[i]);
assert(status >= 0 && (size_t) status < ELEMENTSOF(exit_status_mappings));
r = table_add_many(table,
if (strv_isempty(strv_skip(argv, 1))) {
_cleanup_set_free_ Set *kernel = NULL, *known = NULL;
const char *sys;
- int i, k;
+ int k;
NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
if (set_put_strdup(&known, sys) < 0)
k = load_kernel_syscalls(&kernel);
- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
+ for (int i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
const SyscallFilterSet *set = syscall_filter_sets + i;
if (!first)
puts("");
" --generators[=BOOL] Do [not] run unit generators (requires privileges)\n"
" --iterations=N Show the specified number of iterations\n"
" --base-time=TIMESTAMP Calculate calendar times relative to specified time\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , dot_link
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ dot_link,
+ link);
/* When updating this list, including descriptions, apply changes to
* shell-completion/bash/systemd-analyze and shell-completion/zsh/_systemd-analyze too. */
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
" --accept-cached Accept cached passwords\n"
" --multiple List multiple passwords if available\n"
" --no-output Do not print password to standard output\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
"\n%sSave and restore backlight brightness at shutdown and boot.%s\n\n"
" save Save current brightness\n"
" load Set brightness to be the previously saved value\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
unsigned max_brightness, brightness;
int r;
- log_setup_service();
+ log_setup();
if (strv_contains(strv_skip(argv, 1), "--help"))
return help();
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "static const char* const af_names[] = { "
}
(void*)memset(_new_, 0, _xsize_); \
})
-/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time
- * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
-#define TAKE_PTR(ptr) \
- ({ \
- typeof(ptr) _ptr_ = (ptr); \
- (ptr) = NULL; \
- _ptr_; \
- })
-
#if HAS_FEATURE_MEMORY_SANITIZER
# define msan_unpoison(r, s) __msan_unpoison(r, s)
#else
ARCHITECTURE_ARC,
ARCHITECTURE_ARC_BE,
_ARCHITECTURE_MAX,
- _ARCHITECTURE_INVALID = -1
+ _ARCHITECTURE_INVALID = -EINVAL,
};
int uname_architecture(void);
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "const char *arphrd_to_name(int id) {"
print " switch(id) {"
int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret) {
uint64_t level, lowest = (uint64_t) -1, lowest_qgroupid = 0;
_cleanup_free_ uint64_t *qgroups = NULL;
- int r, n, i;
+ int r, n;
assert(fd >= 0);
assert(ret);
if (n < 0)
return n;
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
uint64_t id;
r = btrfs_qgroupid_split(qgroups[i], &level, &id);
.lim.max_rfer = referenced_max,
.lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER,
};
- unsigned c;
int r;
assert(fd >= 0);
args.qgroupid = qgroupid;
- for (c = 0;; c++) {
+ for (unsigned c = 0;; c++) {
if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0) {
if (errno == EBUSY && c < 10) {
.create = b,
.qgroupid = qgroupid,
};
- unsigned c;
int r;
r = btrfs_is_filesystem(fd);
if (r == 0)
return -ENOTTY;
- for (c = 0;; c++) {
+ for (unsigned c = 0;; c++) {
if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) {
/* On old kernels if quota is not enabled, we get EINVAL. On newer kernels we get
int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) {
_cleanup_free_ uint64_t *qgroups = NULL;
uint64_t subvol_id;
- int i, n, r;
+ int n, r;
/* Destroys the specified qgroup, but unassigns it from all
* its parents first. Also, it recursively destroys all
if (n < 0)
return n;
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
uint64_t id;
r = btrfs_qgroupid_split(qgroups[i], NULL, &id);
.src = child,
.dst = parent,
};
- unsigned c;
int r;
r = btrfs_is_filesystem(fd);
if (r == 0)
return -ENOTTY;
- for (c = 0;; c++) {
+ for (unsigned c = 0;; c++) {
r = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args);
if (r < 0) {
if (errno == EBUSY && c < 10) {
static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_subvol_id) {
_cleanup_free_ uint64_t *old_qgroups = NULL, *old_parent_qgroups = NULL;
bool copy_from_parent = false, insert_intermediary_qgroup = false;
- int n_old_qgroups, n_old_parent_qgroups, r, i;
+ int n_old_qgroups, n_old_parent_qgroups, r;
uint64_t old_parent_id;
assert(fd >= 0);
return n_old_parent_qgroups;
}
- for (i = 0; i < n_old_qgroups; i++) {
+ for (int i = 0; i < n_old_qgroups; i++) {
uint64_t id;
- int j;
r = btrfs_qgroupid_split(old_qgroups[i], NULL, &id);
if (r < 0)
break;
}
- for (j = 0; j < n_old_parent_qgroups; j++)
+ for (int j = 0; j < n_old_parent_qgroups; j++)
if (old_parent_qgroups[j] == old_qgroups[i])
/* The old subvolume shared a common
* parent qgroup with its parent
if (insert_intermediary_qgroup) {
uint64_t lowest = 256, new_qgroupid;
bool created = false;
- int i;
/* Determine the lowest qgroup that the parent
* subvolume is assigned to. */
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
uint64_t level;
r = btrfs_qgroupid_split(qgroups[i], &level, NULL);
if (r >= 0)
changed = created = true;
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
r = btrfs_qgroup_assign(fd, new_qgroupid, qgroups[i]);
if (r < 0 && r != -EEXIST) {
if (created)
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "static const char* const capability_names[] = { "
}
#include "util.h"
int have_effective_cap(int value) {
- _cleanup_cap_free_ cap_t cap;
+ _cleanup_cap_free_ cap_t cap = NULL;
cap_flag_value_t fv;
cap = cap_get_proc();
int drop_capability(cap_value_t cv);
-DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(cap_t, cap_free, NULL);
#define _cleanup_cap_free_ _cleanup_(cap_freep)
static inline void cap_free_charpp(char **p) {
return r;
}
+int cg_get_xattr_bool(const char *controller, const char *path, const char *name) {
+ _cleanup_free_ char *val = NULL;
+ int r;
+
+ assert(path);
+ assert(name);
+
+ r = cg_get_xattr_malloc(controller, path, name, &val);
+ if (r < 0)
+ return r;
+
+ return parse_boolean(val);
+}
+
int cg_remove_xattr(const char *controller, const char *path, const char *name) {
_cleanup_free_ char *fs = NULL;
int r;
}
int cg_path_get_unit(const char *path, char **ret) {
+ _cleanup_free_ char *unit = NULL;
const char *e;
- char *unit;
int r;
assert(path);
return r;
/* We skipped over the slices, don't accept any now */
- if (endswith(unit, ".slice")) {
- free(unit);
+ if (endswith(unit, ".slice"))
return -ENXIO;
- }
- *ret = unit;
+ *ret = TAKE_PTR(unit);
return 0;
}
return 0;
}
+int cg_get_owner(const char *controller, const char *path, uid_t *ret_uid) {
+ _cleanup_free_ char *f = NULL;
+ struct stat stats;
+ int r;
+
+ assert(ret_uid);
+
+ r = cg_get_path(controller, path, NULL, &f);
+ if (r < 0)
+ return r;
+
+ r = stat(f, &stats);
+ if (r < 0)
+ return -errno;
+
+ *ret_uid = stats.st_uid;
+ return 0;
+}
+
int cg_get_keyed_attribute_full(
const char *controller,
const char *path,
struct utsname u;
assert_se(uname(&u) >= 0);
- if (str_verscmp(u.release, "4.15") < 0)
+ if (strverscmp_improved(u.release, "4.15") < 0)
needed_mask = CGROUP_MASK_CPU;
else
needed_mask = 0;
};
DEFINE_STRING_TABLE_LOOKUP(managed_oom_mode, ManagedOOMMode);
+
+static const char* const managed_oom_preference_table[_MANAGED_OOM_PREFERENCE_MAX] = {
+ [MANAGED_OOM_PREFERENCE_NONE] = "none",
+ [MANAGED_OOM_PREFERENCE_AVOID] = "avoid",
+ [MANAGED_OOM_PREFERENCE_OMIT] = "omit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(managed_oom_preference, ManagedOOMPreference);
CGROUP_CONTROLLER_BPF_DEVICES,
_CGROUP_CONTROLLER_MAX,
- _CGROUP_CONTROLLER_INVALID = -1,
+ _CGROUP_CONTROLLER_INVALID = -EINVAL,
} CGroupController;
#define CGROUP_CONTROLLER_TO_MASK(c) (1U << (c))
CGROUP_IO_WIOPS_MAX,
_CGROUP_IO_LIMIT_TYPE_MAX,
- _CGROUP_IO_LIMIT_TYPE_INVALID = -1
+ _CGROUP_IO_LIMIT_TYPE_INVALID = -EINVAL,
} CGroupIOLimitType;
extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute, bool *ret);
int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
+int cg_get_owner(const char *controller, const char *path, uid_t *ret_uid);
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
int cg_get_xattr_malloc(const char *controller, const char *path, const char *name, char **ret);
+/* Returns negative on error, and 0 or 1 on success for the bool value */
+int cg_get_xattr_bool(const char *controller, const char *path, const char *name);
int cg_remove_xattr(const char *controller, const char *path, const char *name);
int cg_install_release_agent(const char *controller, const char *agent);
MANAGED_OOM_AUTO,
MANAGED_OOM_KILL,
_MANAGED_OOM_MODE_MAX,
- _MANAGED_OOM_MODE_INVALID = -1,
+ _MANAGED_OOM_MODE_INVALID = -EINVAL,
} ManagedOOMMode;
const char* managed_oom_mode_to_string(ManagedOOMMode m) _const_;
ManagedOOMMode managed_oom_mode_from_string(const char *s) _pure_;
+
+typedef enum ManagedOOMPreference {
+ MANAGED_OOM_PREFERENCE_NONE = 0,
+ MANAGED_OOM_PREFERENCE_AVOID = 1,
+ MANAGED_OOM_PREFERENCE_OMIT = 2,
+ _MANAGED_OOM_PREFERENCE_MAX,
+ _MANAGED_OOM_PREFERENCE_INVALID = -1
+} ManagedOOMPreference;
+
+const char* managed_oom_preference_to_string(ManagedOOMPreference a) _const_;
+ManagedOOMPreference managed_oom_preference_from_string(const char *s) _pure_;
uid_is_valid(override_uid) ? override_uid : st->st_uid,
gid_is_valid(override_gid) ? override_gid : st->st_gid,
AT_SYMLINK_NOFOLLOW) < 0)
- return -errno;
+ r = -errno;
- return 0;
+ (void) utimensat(dt, to, (struct timespec[]) { st->st_atim, st->st_mtim }, AT_SYMLINK_NOFOLLOW);
+ return r;
}
/* Encapsulates the database we store potential hardlink targets in */
void *userdata) {
_cleanup_close_ int fdf = -1, fdt = -1;
- struct timespec ts[2];
int r, q;
assert(from);
if (fchmod(fdt, st->st_mode & 07777) < 0)
r = -errno;
- ts[0] = st->st_atim;
- ts[1] = st->st_mtim;
- (void) futimens(fdt, ts);
+ (void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim });
(void) copy_xattr(fdf, fdt);
q = close(fdt);
if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
r = -errno;
+ (void) utimensat(dt, to, (struct timespec[]) { st->st_atim, st->st_mtim }, AT_SYMLINK_NOFOLLOW);
+
(void) memorize_hardlink(hardlink_context, st, dt, to);
return r;
}
if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
r = -errno;
+ (void) utimensat(dt, to, (struct timespec[]) { st->st_atim, st->st_mtim }, AT_SYMLINK_NOFOLLOW);
+
(void) memorize_hardlink(hardlink_context, st, dt, to);
return r;
}
}
if (created) {
- struct timespec ut[2] = {
- st->st_atim,
- st->st_mtim
- };
-
if (fchown(fdt,
uid_is_valid(override_uid) ? override_uid : st->st_uid,
gid_is_valid(override_gid) ? override_gid : st->st_gid) < 0)
r = -errno;
(void) copy_xattr(dirfd(d), fdt);
- (void) futimens(fdt, ut);
+ (void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim });
}
return r;
void *userdata) {
struct stat st;
+ int r;
assert(dirfd >= 0);
assert(to);
if (fstat(dirfd, &st) < 0)
return -errno;
- if (!S_ISDIR(st.st_mode))
- return -ENOTDIR;
+ r = stat_verify_directory(&st);
+ if (r < 0)
+ return r;
return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata);
}
void *userdata) {
struct stat st;
+ int r;
assert(from);
assert(to);
if (lstat(from, &st) < 0)
return -errno;
- if (!S_ISDIR(st.st_mode))
- return -ENOTDIR;
+ r = stat_verify_directory(&st);
+ if (r < 0)
+ return r;
return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata);
}
}
int copy_times(int fdf, int fdt, CopyFlags flags) {
- struct timespec ut[2];
struct stat st;
assert(fdf >= 0);
if (fstat(fdf, &st) < 0)
return -errno;
- ut[0] = st.st_atim;
- ut[1] = st.st_mtim;
-
- if (futimens(fdt, ut) < 0)
+ if (futimens(fdt, (struct timespec[2]) { st.st_atim, st.st_mtim }) < 0)
return -errno;
if (FLAGS_SET(flags, COPY_CRTIME)) {
#include "macro.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
int dlsym_many_and_warn(void *dl, int level, ...);
if (cache < 0) {
if (detect_container() > 0)
cache = false;
- else
+ else {
cache = access("/sys/firmware/efi/", F_OK) >= 0;
+ if (!cache && errno != ENOENT)
+ log_debug_errno(errno, "Unable to test whether /sys/firmware/efi/ exists, assuming EFI not available: %m");
+ }
}
return cache;
if (!p)
return -ENOMEM;
- r = strv_env_replace(m, p);
- if (r < 0) {
- free(p);
+ r = strv_env_replace_consume(m, p);
+ if (r < 0)
return r;
- }
if (n_pushed)
(*n_pushed)++;
#include "extract-word.h"
#include "macro.h"
#include "parse-util.h"
+#include "process-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
return l;
}
-int strv_env_replace(char ***l, char *p) {
+int strv_env_replace_consume(char ***l, char *p) {
const char *t, *name;
char **f;
int r;
assert(p);
- /* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
- * in-place. Does not copy p. p must be a valid key=value assignment.
- */
+ /* Replace first occurrence of the env var or add a new one in the string list. Drop other
+ * occurrences. Edits in-place. Does not copy p and CONSUMES p EVEN ON FAILURE.
+ *
+ * p must be a valid key=value assignment. */
t = strchr(p, '=');
- if (!t)
+ if (!t) {
+ free(p);
return -EINVAL;
+ }
name = strndupa(p, t - p);
}
/* We didn't find a match, we need to append p or create a new strv */
- r = strv_push(l, p);
+ r = strv_consume(l, p);
if (r < 0)
return r;
return 1;
}
-char **strv_env_set(char **x, const char *p) {
- _cleanup_strv_free_ char **ret = NULL;
- size_t n, m;
- char **k;
+int strv_env_replace_strdup(char ***l, const char *assignment) {
+ /* Like strv_env_replace_consume(), but copies the argument. */
- /* Overrides the env var setting of p, returns a new copy */
+ char *p = strdup(assignment);
+ if (!p)
+ return -ENOMEM;
- n = strv_length(x);
- m = n + 2;
- if (m < n) /* overflow? */
- return NULL;
+ return strv_env_replace_consume(l, p);
+}
- ret = new(char*, m);
- if (!ret)
- return NULL;
+int strv_env_assign(char ***l, const char *key, const char *value) {
+ if (!env_name_is_valid(key))
+ return -EINVAL;
- *ret = NULL;
- k = ret;
+ /* NULL removes assignment, "" creates an empty assignment. */
- if (env_append(ret, &k, x) < 0)
- return NULL;
+ if (!value) {
+ strv_env_unset(*l, key);
+ return 0;
+ }
- if (env_append(ret, &k, STRV_MAKE(p)) < 0)
- return NULL;
+ char *p = strjoin(key, "=", value);
+ if (!p)
+ return -ENOMEM;
- return TAKE_PTR(ret);
+ return strv_env_replace_consume(l, p);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
return -errno;
return 0;
}
+
+int setenv_systemd_exec_pid(bool update_only) {
+ char str[DECIMAL_STR_MAX(pid_t)];
+ const char *e;
+
+ /* Update $SYSTEMD_EXEC_PID=pid except when '*' is set for the variable. */
+
+ e = secure_getenv("SYSTEMD_EXEC_PID");
+ if (!e && update_only)
+ return 0;
+
+ if (streq_ptr(e, "*"))
+ return 0;
+
+ xsprintf(str, PID_FMT, getpid_cached());
+
+ if (setenv("SYSTEMD_EXEC_PID", str, 1) < 0)
+ return -errno;
+
+ return 1;
+}
char **strv_env_merge(size_t n_lists, ...);
char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
-char **strv_env_set(char **x, const char *p); /* New copy ... */
char **strv_env_unset(char **l, const char *p); /* In place ... */
char **strv_env_unset_many(char **l, ...) _sentinel_;
-int strv_env_replace(char ***l, char *p); /* In place ... */
+int strv_env_replace_consume(char ***l, char *p); /* In place ... */
+int strv_env_replace_strdup(char ***l, const char *assignment);
+int strv_env_assign(char ***l, const char *key, const char *value);
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
char *strv_env_get(char **x, const char *n) _pure_;
/* Like setenv, but calls unsetenv if value == NULL. */
int set_unset_env(const char *name, const char *value, bool overwrite);
+
+int setenv_systemd_exec_pid(bool update_only);
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "static const char* const errno_names[] = { "
}
}
void close_many(const int fds[], size_t n_fd) {
- size_t i;
-
assert(fds || n_fd <= 0);
- for (i = 0; i < n_fd; i++)
+ for (size_t i = 0; i < n_fd; i++)
safe_close(fds[i]);
}
}
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
- size_t i;
-
assert(n_fdset == 0 || fdset);
- for (i = 0; i < n_fdset; i++)
+ for (size_t i = 0; i < n_fdset; i++)
if (fdset[i] == fd)
return true;
safe_fclose(*f);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, pclose, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
#define _cleanup_close_ _cleanup_(closep)
#define _cleanup_fclose_ _cleanup_(fclosep)
return EOL_NONE;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, funlockfile, NULL);
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
size_t n = 0, allocated = 0, count = 0;
{ "K", UINT64_C(1000) },
};
const suffix_table *table;
- size_t n, i;
+ size_t n;
assert_cc(ELEMENTSOF(table_iec) == ELEMENTSOF(table_si));
table = flag & FORMAT_BYTES_USE_IEC ? table_iec : table_si;
n = ELEMENTSOF(table_iec);
- for (i = 0; i < n; i++)
+ for (size_t i = 0; i < n; i++)
if (t >= table[i].factor) {
if (flag & FORMAT_BYTES_BELOW_POINT) {
snprintf(buf, l,
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
}
-int conservative_rename(
+int conservative_renameat(
int olddirfd, const char *oldpath,
int newdirfd, const char *newpath) {
goto do_rename;
for (;;) {
- char buf1[16*1024];
- char buf2[sizeof(buf1) + 1];
+ uint8_t buf1[16*1024];
+ uint8_t buf2[sizeof(buf1)];
ssize_t l1, l2;
l1 = read(old_fd, buf1, sizeof(buf1));
if (l1 < 0)
goto do_rename;
- l2 = read(new_fd, buf2, l1 + 1);
- if (l1 != l2)
- goto do_rename;
+ if (l1 == sizeof(buf1))
+ /* Read the full block, hence read a full block in the other file too */
- if (l1 == 0) /* EOF on both! And everything's the same so far, yay! */
- break;
+ l2 = read(new_fd, buf2, l1);
+ else {
+ assert((size_t) l1 < sizeof(buf1));
+
+ /* Short read. This hence was the last block in the first file, and then came
+ * EOF. Read one byte more in the second file, so that we can verify we hit EOF there
+ * too. */
+
+ assert((size_t) (l1 + 1) <= sizeof(buf2));
+ l2 = read(new_fd, buf2, l1 + 1);
+ }
+ if (l2 != l1)
+ goto do_rename;
if (memcmp(buf1, buf2, l1) != 0)
goto do_rename;
+
+ if ((size_t) l1 < sizeof(buf1)) /* We hit EOF on the first file, and the second file too, hence exit
+ * now. */
+ break;
}
is_same:
int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd);
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
-static inline void rmdir_and_free(char *p) {
+static inline char *rmdir_and_free(char *p) {
PROTECT_ERRNO;
+
+ if (!p)
+ return NULL;
+
(void) rmdir(p);
free(p);
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free);
-static inline void unlink_and_free(char *p) {
+static inline char* unlink_and_free(char *p) {
+ if (!p)
+ return NULL;
+
(void) unlink_noerrno(p);
free(p);
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
int path_is_encrypted(const char *path);
-int conservative_rename(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
+int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
+static inline int conservative_rename(const char *oldpath, const char *newpath) {
+ return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
+}
void initialize_libgcrypt(bool secmem);
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out);
-DEFINE_TRIVIAL_CLEANUP_FUNC(gcry_md_hd_t, gcry_md_close);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, gcry_md_close, NULL);
#endif
static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
$1 -E -dM -include sys/socket.h -include "$2" -include "$3" - </dev/null | \
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
$1 -dM -include linux/if_arp.h -include "$2" - </dev/null | \
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
$1 -dM -include linux/capability.h -include "$2" -include "$3" - </dev/null | \
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
$1 -dM -include errno.h - </dev/null | \
}
void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
- size_t i;
-
- for (i = 0; i < iovw->count; i++)
+ for (size_t i = 0; i < iovw->count; i++)
iovw->iovec[i].iov_base = (char *)iovw->iovec[i].iov_base - old + new;
}
size_t iovw_size(struct iovec_wrapper *iovw) {
- size_t n = 0, i;
+ size_t n = 0;
- for (i = 0; i < iovw->count; i++)
+ for (size_t i = 0; i < iovw->count; i++)
n += iovw->iovec[i].iov_len;
return n;
#!/usr/bin/env bash
-
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
for i in *.h */*.h; do
_cleanup_close_ int fd = -1;
size_t sz = 0;
struct stat st;
- size_t i;
int r;
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
}
e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
- for (i = 0; i < h->namehash_size; i++) {
+ for (size_t i = 0; i < h->namehash_size; i++) {
char *z;
if (e[i].locrec_offset == 0)
[SPECIAL_GLYPH_TREE_SPACE] = " ",
[SPECIAL_GLYPH_TRIANGULAR_BULLET] = ">",
[SPECIAL_GLYPH_BLACK_CIRCLE] = "*",
+ [SPECIAL_GLYPH_WHITE_CIRCLE] = "*",
+ [SPECIAL_GLYPH_MULTIPLICATION_SIGN] = "x",
+ [SPECIAL_GLYPH_CIRCLE_ARROW] = "*",
[SPECIAL_GLYPH_BULLET] = "*",
[SPECIAL_GLYPH_MU] = "u",
[SPECIAL_GLYPH_CHECK_MARK] = "+",
/* Single glyphs in both cases */
[SPECIAL_GLYPH_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
[SPECIAL_GLYPH_BLACK_CIRCLE] = "\342\227\217", /* ● */
+ [SPECIAL_GLYPH_WHITE_CIRCLE] = "\u25CB", /* ○ */
+ [SPECIAL_GLYPH_MULTIPLICATION_SIGN] = "\u00D7", /* × */
+ [SPECIAL_GLYPH_CIRCLE_ARROW] = "\u21BB", /* ↻ */
[SPECIAL_GLYPH_BULLET] = "\342\200\242", /* • */
[SPECIAL_GLYPH_MU] = "\316\274", /* μ (actually called: GREEK SMALL LETTER MU) */
[SPECIAL_GLYPH_CHECK_MARK] = "\342\234\223", /* ✓ */
}
void locale_variables_free(char *l[_VARIABLE_LC_MAX]) {
- LocaleVariable i;
-
if (!l)
return;
- for (i = 0; i < _VARIABLE_LC_MAX; i++)
+ for (LocaleVariable i = 0; i < _VARIABLE_LC_MAX; i++)
l[i] = mfree(l[i]);
}
VARIABLE_LC_MEASUREMENT,
VARIABLE_LC_IDENTIFICATION,
_VARIABLE_LC_MAX,
- _VARIABLE_LC_INVALID = -1
+ _VARIABLE_LC_INVALID = -EINVAL,
} LocaleVariable;
int get_locales(char ***l);
SPECIAL_GLYPH_TREE_SPACE,
SPECIAL_GLYPH_TRIANGULAR_BULLET,
SPECIAL_GLYPH_BLACK_CIRCLE,
+ SPECIAL_GLYPH_WHITE_CIRCLE,
+ SPECIAL_GLYPH_MULTIPLICATION_SIGN,
+ SPECIAL_GLYPH_CIRCLE_ARROW,
SPECIAL_GLYPH_BULLET,
SPECIAL_GLYPH_MU,
SPECIAL_GLYPH_CHECK_MARK,
#define SNDBUF_SIZE (8*1024*1024)
static LogTarget log_target = LOG_TARGET_CONSOLE;
-static int log_max_level[] = {LOG_INFO, LOG_INFO};
-assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
+static int log_max_level = LOG_INFO;
static int log_facility = LOG_DAEMON;
static int console_fd = STDERR_FILENO;
console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
}
-void log_set_max_level_realm(LogRealm realm, int level) {
+void log_set_max_level(int level) {
assert((level & LOG_PRIMASK) == level);
- assert(realm < ELEMENTSOF(log_max_level));
- log_max_level[realm] = level;
+ log_max_level = level;
}
void log_set_facility(int facility) {
const char *lon = "", *loff = "";
if (log_get_show_color()) {
lon = ansi_highlight_yellow4();
- loff = ANSI_NORMAL;
+ loff = ansi_normal();
}
(void) snprintf(location, sizeof location, "%s%s:%i%s: ", lon, file, line, loff);
const char *func,
char *buffer) {
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
PROTECT_ERRNO;
/* This modifies the buffer... */
- if (_likely_(LOG_PRI(level) > log_max_level[realm]))
+ if (_likely_(LOG_PRI(level) > log_max_level))
return -ERRNO_VALUE(error);
return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
}
-int log_internalv_realm(
+int log_internalv(
int level,
int error,
const char *file,
const char *format,
va_list ap) {
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
char buffer[LINE_MAX];
PROTECT_ERRNO;
- if (_likely_(LOG_PRI(level) > log_max_level[realm]))
+ if (_likely_(LOG_PRI(level) > log_max_level))
return -ERRNO_VALUE(error);
/* Make sure that %m maps to the specified error (or "Success"). */
return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
}
-int log_internal_realm(
+int log_internal(
int level,
int error,
const char *file,
int r;
va_start(ap, format);
- r = log_internalv_realm(level, error, file, line, func, format, ap);
+ r = log_internalv(level, error, file, line, func, format, ap);
va_end(ap);
return r;
PROTECT_ERRNO;
char *buffer, *b;
- if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
+ if (_likely_(LOG_PRI(level) > log_max_level))
return -ERRNO_VALUE(error);
/* Make sure that %m maps to the specified error (or "Success"). */
const char *format) {
static char buffer[LINE_MAX];
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
- if (_likely_(LOG_PRI(level) > log_max_level[realm]))
+ if (_likely_(LOG_PRI(level) > log_max_level))
return;
DISABLE_WARNING_FORMAT_NONLITERAL;
log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
}
-_noreturn_ void log_assert_failed_realm(
- LogRealm realm,
+_noreturn_ void log_assert_failed(
const char *text,
const char *file,
int line,
const char *func) {
- log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+ log_assert(LOG_CRIT, text, file, line, func,
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
abort();
}
-_noreturn_ void log_assert_failed_unreachable_realm(
- LogRealm realm,
+_noreturn_ void log_assert_failed_unreachable(
const char *text,
const char *file,
int line,
const char *func) {
- log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+ log_assert(LOG_CRIT, text, file, line, func,
"Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
abort();
}
-void log_assert_failed_return_realm(
- LogRealm realm,
+void log_assert_failed_return(
const char *text,
const char *file,
int line,
const char *func) {
PROTECT_ERRNO;
- log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
+ log_assert(LOG_DEBUG, text, file, line, func,
"Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
}
int log_oom_internal(int level, const char *file, int line, const char *func) {
- return log_internal_realm(level, ENOMEM, file, line, func, "Out of memory.");
+ return log_internal(level, ENOMEM, file, line, func, "Out of memory.");
}
int log_format_iovec(
const char *func,
const char *format, ...) {
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
char buf[LINE_MAX];
bool found = false;
PROTECT_ERRNO;
va_list ap;
- if (_likely_(LOG_PRI(level) > log_max_level[realm]) ||
+ if (_likely_(LOG_PRI(level) > log_max_level) ||
log_target == LOG_TARGET_NULL)
return -ERRNO_VALUE(error);
const struct iovec input_iovec[],
size_t n_input_iovec) {
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
PROTECT_ERRNO;
size_t i;
char *m;
- if (_likely_(LOG_PRI(level) > log_max_level[realm]) ||
+ if (_likely_(LOG_PRI(level) > log_max_level) ||
log_target == LOG_TARGET_NULL)
return -ERRNO_VALUE(error);
t = log_target_from_string(e);
if (t < 0)
- return -EINVAL;
+ return t;
log_set_target(t);
return 0;
}
-int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
+int log_set_max_level_from_string(const char *e) {
int t;
t = log_level_from_string(e);
if (t < 0)
- return -EINVAL;
+ return t;
- log_set_max_level_realm(realm, t);
+ log_set_max_level(t);
return 0;
}
return 0;
}
-void log_parse_environment_realm(LogRealm realm) {
- if (getpid_cached() == 1 || get_ctty_devnr(0, NULL) < 0)
- /* Only try to read the command line in daemons. We assume that anything that has a
- * controlling tty is user stuff. For PID1 we do a special check in case it hasn't
- * closed the console yet. */
- (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
+static bool should_parse_proc_cmdline(void) {
+ const char *e;
+ pid_t p;
+
+ /* PID1 always reads the kernel command line. */
+ if (getpid_cached() == 1)
+ return true;
+
+ /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
+ * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
+ e = getenv("SYSTEMD_EXEC_PID");
+ if (!e)
+ return false;
+
+ if (streq(e, "*"))
+ /* For testing. */
+ return true;
- log_parse_environment_cli_realm(realm);
+ if (parse_pid(e, &p) < 0) {
+ /* We know that systemd sets the variable correctly. Something else must have set it. */
+ log_debug("Failed to parse \"$SYSTEMD_EXEC_PID=%s\". Ignoring.", e);
+ return false;
+ }
+
+ return getpid_cached() == p;
}
-void log_parse_environment_cli_realm(LogRealm realm) {
+void log_parse_environment(void) {
+ const char *e;
+
/* Do not call from library code. */
- const char *e;
+ if (should_parse_proc_cmdline())
+ (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
e = getenv("SYSTEMD_LOG_TARGET");
if (e && log_set_target_from_string(e) < 0)
log_warning("Failed to parse log target '%s'. Ignoring.", e);
e = getenv("SYSTEMD_LOG_LEVEL");
- if (e && log_set_max_level_from_string_realm(realm, e) < 0)
+ if (e && log_set_max_level_from_string(e) < 0)
log_warning("Failed to parse log level '%s'. Ignoring.", e);
e = getenv("SYSTEMD_LOG_COLOR");
return log_target;
}
-int log_get_max_level_realm(LogRealm realm) {
- return log_max_level[realm];
+int log_get_max_level(void) {
+ return log_max_level;
}
void log_show_color(bool b) {
va_list ap;
const char *unit_fmt = NULL;
- if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]) ||
+ if (_likely_(LOG_PRI(level) > log_max_level) ||
log_target == LOG_TARGET_NULL)
return -ERRNO_VALUE(error);
if (config_file) {
if (config_line > 0)
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
NULL);
else
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
NULL);
} else if (unit)
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
NULL);
else
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
return 0;
}
-void log_setup_service(void) {
- /* Sets up logging the way it is most appropriate for running a program as a service. Note that using this
- * doesn't make the binary unsuitable for invocation on the command line, as log output will still go to the
- * terminal if invoked interactively. */
-
+void log_setup(void) {
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
(void) log_open();
-}
-
-void log_setup_cli(void) {
- /* Sets up logging the way it is most appropriate for running a program as a CLI utility. */
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment_cli();
- (void) log_open();
if (log_on_console() && show_color < 0)
log_show_color(true);
}
struct iovec;
struct signalfd_siginfo;
-typedef enum LogRealm {
- LOG_REALM_SYSTEMD,
- LOG_REALM_UDEV,
- _LOG_REALM_MAX,
-} LogRealm;
-
-#ifndef LOG_REALM
-# define LOG_REALM LOG_REALM_SYSTEMD
-#endif
-
typedef enum LogTarget{
LOG_TARGET_CONSOLE,
LOG_TARGET_CONSOLE_PREFIXED,
LOG_TARGET_AUTO, /* console if stderr is not journal, JOURNAL_OR_KMSG otherwise */
LOG_TARGET_NULL,
_LOG_TARGET_MAX,
- _LOG_TARGET_INVALID = -1
+ _LOG_TARGET_INVALID = -EINVAL,
} LogTarget;
/* Note to readers: << and >> have lower precedence than & and | */
-#define LOG_REALM_PLUS_LEVEL(realm, level) ((realm) << 10 | (level))
-#define LOG_REALM_REMOVE_LEVEL(realm_level) ((realm_level) >> 10)
#define SYNTHETIC_ERRNO(num) (1 << 30 | (num))
#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1)
#define ERRNO_VALUE(val) (abs(val) & 255)
+const char *log_target_to_string(LogTarget target) _const_;
+LogTarget log_target_from_string(const char *s) _pure_;
void log_set_target(LogTarget target);
+int log_set_target_from_string(const char *e);
+LogTarget log_get_target(void) _pure_;
-void log_set_max_level_realm(LogRealm realm, int level);
-
-#define log_set_max_level(level) \
- log_set_max_level_realm(LOG_REALM, (level))
-
-static inline void log_set_max_level_all_realms(int level) {
- for (LogRealm realm = 0; realm < _LOG_REALM_MAX; realm++)
- log_set_max_level_realm(realm, level);
-}
+void log_set_max_level(int level);
+int log_set_max_level_from_string(const char *e);
+int log_get_max_level(void) _pure_;
void log_set_facility(int facility);
-int log_set_target_from_string(const char *e);
-int log_set_max_level_from_string_realm(LogRealm realm, const char *e);
-#define log_set_max_level_from_string(e) \
- log_set_max_level_from_string_realm(LOG_REALM, (e))
-
void log_show_color(bool b);
bool log_get_show_color(void) _pure_;
void log_show_location(bool b);
int log_show_time_from_string(const char *e);
int log_show_tid_from_string(const char *e);
-LogTarget log_get_target(void) _pure_;
-int log_get_max_level_realm(LogRealm realm) _pure_;
-#define log_get_max_level() \
- log_get_max_level_realm(LOG_REALM)
-
/* Functions below that open and close logs or configure logging based on the
* environment should not be called from library code — this is always a job
- * for the application itself.
- */
+ * for the application itself. */
assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1);
#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1])
void log_close(void);
void log_forget_fds(void);
-void log_parse_environment_realm(LogRealm realm);
-void log_parse_environment_cli_realm(LogRealm realm);
-#define log_parse_environment() \
- log_parse_environment_realm(LOG_REALM)
-#define log_parse_environment_cli() \
- log_parse_environment_cli_realm(LOG_REALM)
+void log_parse_environment(void);
int log_dispatch_internal(
int level,
const char *extra_field,
char *buffer);
-int log_internal_realm(
+int log_internal(
int level,
int error,
const char *file,
int line,
const char *func,
const char *format, ...) _printf_(6,7);
-#define log_internal(level, ...) \
- log_internal_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
-int log_internalv_realm(
+int log_internalv(
int level,
int error,
const char *file,
const char *func,
const char *format,
va_list ap) _printf_(6,0);
-#define log_internalv(level, ...) \
- log_internalv_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
-/* Realm is fixed to LOG_REALM_SYSTEMD for those */
int log_object_internalv(
int level,
int error,
char *buffer);
/* Logging for various assertions */
-_noreturn_ void log_assert_failed_realm(
- LogRealm realm,
+_noreturn_ void log_assert_failed(
const char *text,
const char *file,
int line,
const char *func);
-#define log_assert_failed(text, ...) \
- log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__)
-_noreturn_ void log_assert_failed_unreachable_realm(
- LogRealm realm,
+_noreturn_ void log_assert_failed_unreachable(
const char *text,
const char *file,
int line,
const char *func);
-#define log_assert_failed_unreachable(text, ...) \
- log_assert_failed_unreachable_realm(LOG_REALM, (text), __VA_ARGS__)
-void log_assert_failed_return_realm(
- LogRealm realm,
+void log_assert_failed_return(
const char *text,
const char *file,
int line,
const char *func);
-#define log_assert_failed_return(text, ...) \
- log_assert_failed_return_realm(LOG_REALM, (text), __VA_ARGS__)
#define log_dispatch(level, error, buffer) \
log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer)
/* Logging with level */
-#define log_full_errno_realm(realm, level, error, ...) \
+#define log_full_errno(level, error, ...) \
({ \
- int _level = (level), _e = (error), _realm = (realm); \
- (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \
- ? log_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \
- PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
+ int _level = (level), _e = (error); \
+ (log_get_max_level() >= LOG_PRI(_level)) \
+ ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
: -ERRNO_VALUE(_e); \
})
-#define log_full_errno(level, error, ...) \
- log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__)
-
#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__)
int log_emergency_level(void);
#endif
/* Structured logging */
-#define log_struct_errno(level, error, ...) \
- log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL)
+#define log_struct_errno(level, error, ...) \
+ log_struct_internal(level, error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL)
#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
#define log_struct_iovec_errno(level, error, iovec, n_iovec) \
- log_struct_iovec_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec)
+ log_struct_iovec_internal(level, error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec)
#define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec)
/* This modifies the buffer passed! */
-#define log_dump(level, buffer) \
- log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- 0, PROJECT_FILE, __LINE__, __func__, buffer)
+#define log_dump(level, buffer) \
+ log_dump_internal(level, 0, PROJECT_FILE, __LINE__, __func__, buffer)
-#define log_oom() log_oom_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, LOG_ERR), PROJECT_FILE, __LINE__, __func__)
-#define log_oom_debug() log_oom_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, LOG_DEBUG), PROJECT_FILE, __LINE__, __func__)
+#define log_oom() log_oom_internal(LOG_ERR, PROJECT_FILE, __LINE__, __func__)
+#define log_oom_debug() log_oom_internal(LOG_DEBUG, PROJECT_FILE, __LINE__, __func__)
bool log_on_console(void) _pure_;
-const char *log_target_to_string(LogTarget target) _const_;
-LogTarget log_target_from_string(const char *s) _pure_;
-
/* Helper to prepare various field for structured logging */
#define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__
#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
-void log_setup_service(void);
-void log_setup_cli(void);
+void log_setup(void);
#include <stdbool.h>
#include <unistd.h>
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
+
+/* For internal use only */
+#define SD_LOGIND_INTERACTIVE (UINT64_C(1) << 63)
+
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
+
bool session_id_valid(const char *id);
static inline bool logind_running(void) {
#include <sys/sysmacros.h>
#include <sys/types.h>
+#include "macro-fundamental.h"
+
#define _printf_(a, b) __attribute__((__format__(printf, a, b)))
#ifdef __clang__
# define _alloc_(...)
#define _sentinel_ __attribute__((__sentinel__))
#define _section_(x) __attribute__((__section__(x)))
#define _used_ __attribute__((__used__))
-#define _unused_ __attribute__((__unused__))
#define _destructor_ __attribute__((__destructor__))
-#define _pure_ __attribute__((__pure__))
-#define _const_ __attribute__((__const__))
#define _deprecated_ __attribute__((__deprecated__))
#define _packed_ __attribute__((__packed__))
#define _malloc_ __attribute__((__malloc__))
#define _align_(x) __attribute__((__aligned__(x)))
#define _alignas_(x) __attribute__((__aligned__(__alignof(x))))
#define _alignptr_ __attribute__((__aligned__(sizeof(void*))))
-#define _cleanup_(x) __attribute__((__cleanup__(x)))
#if __GNUC__ >= 7
#define _fallthrough_ __attribute__((__fallthrough__))
#else
#define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x)
-#define XCONCATENATE(x, y) x ## y
-#define CONCATENATE(x, y) XCONCATENATE(x, y)
-
-#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
-#define UNIQ __COUNTER__
-
/* builtins */
#if __SIZEOF_INT__ == 4
#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
return m;
}
-#ifndef __COVERITY__
-# define VOID_0 ((void)0)
-#else
-# define VOID_0 ((void*)0)
-#endif
-
-#define ELEMENTSOF(x) \
- (__builtin_choose_expr( \
- !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
- sizeof(x)/sizeof((x)[0]), \
- VOID_0))
-
/*
* STRLEN - return the length of a string literal, minus the trailing NUL byte.
* Contrary to strlen(), this is a constant expression.
(type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \
})
-#undef MAX
-#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
-#define __MAX(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
- })
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define CONST_MAX(_A, _B) \
- (__builtin_choose_expr( \
- __builtin_constant_p(_A) && \
- __builtin_constant_p(_B) && \
- __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
- ((_A) > (_B)) ? (_A) : (_B), \
- VOID_0))
-
-/* takes two types and returns the size of the larger one */
-#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
-
-#define MAX3(x, y, z) \
- ({ \
- const typeof(x) _c = MAX(x, y); \
- MAX(_c, z); \
- })
-
-#define MAX4(x, y, z, a) \
- ({ \
- const typeof(x) _d = MAX3(x, y, z); \
- MAX(_d, a); \
- })
-
-#undef MIN
-#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
-#define __MIN(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
- })
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define CONST_MIN(_A, _B) \
- (__builtin_choose_expr( \
- __builtin_constant_p(_A) && \
- __builtin_constant_p(_B) && \
- __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
- ((_A) < (_B)) ? (_A) : (_B), \
- VOID_0))
-
-#define MIN3(x, y, z) \
- ({ \
- const typeof(x) _c = MIN(x, y); \
- MIN(_c, z); \
- })
-
-#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
-#define __LESS_BY(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \
- })
-
-#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
-#define __CMP(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
- })
-
-#undef CLAMP
-#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
-#define __CLAMP(xq, x, lowq, low, highq, high) \
- ({ \
- const typeof(x) UNIQ_T(X, xq) = (x); \
- const typeof(low) UNIQ_T(LOW, lowq) = (low); \
- const typeof(high) UNIQ_T(HIGH, highq) = (high); \
- UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \
- UNIQ_T(HIGH, highq) : \
- UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \
- UNIQ_T(LOW, lowq) : \
- UNIQ_T(X, xq); \
- })
-
-/* [(x + y - 1) / y] suffers from an integer overflow, even though the
- * computation should be possible in the given type. Therefore, we use
- * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
- * quotient and the remainder, so both should be equally fast. */
-#define DIV_ROUND_UP(x, y) __DIV_ROUND_UP(UNIQ, (x), UNIQ, (y))
-#define __DIV_ROUND_UP(xq, x, yq, y) \
- ({ \
- const typeof(x) UNIQ_T(X, xq) = (x); \
- const typeof(y) UNIQ_T(Y, yq) = (y); \
- (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
- })
-
#ifdef __COVERITY__
/* Use special definitions of assertion macros in order to prevent
#define assert_not_reached(t) \
log_assert_failed_unreachable(t, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__)
-#if defined(static_assert)
-#define assert_cc(expr) \
- static_assert(expr, #expr)
-#else
-#define assert_cc(expr) \
- struct CONCATENATE(_assert_struct_, __COUNTER__) { \
- char x[(expr) ? 0 : -1]; \
- }
-#endif
-
#define assert_return(expr, r) \
do { \
if (!assert_log(expr, #expr)) \
#define FLAGS_SET(v, flags) \
((~(v) & (flags)) == 0)
-#define CASE_F(X) case X:
-#define CASE_F_1(CASE, X) CASE_F(X)
-#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
-#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
-#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
-#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
-#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
-#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
-#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
-#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
-#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
-#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
-#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
-#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
-#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
-#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
-#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
-#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
-#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
-#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
-#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
-
-#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
-#define FOR_EACH_MAKE_CASE(...) \
- GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
- CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
- (CASE_F,__VA_ARGS__)
-
-#define IN_SET(x, ...) \
- ({ \
- bool _found = false; \
- /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
- * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
- * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
- * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
- static const long double __assert_in_set[] _unused_ = { __VA_ARGS__ }; \
- assert_cc(ELEMENTSOF(__assert_in_set) <= 20); \
- switch(x) { \
- FOR_EACH_MAKE_CASE(__VA_ARGS__) \
- _found = true; \
- break; \
- default: \
- break; \
- } \
- _found; \
- })
-
#define SWAP_TWO(x, y) do { \
typeof(x) _t = (x); \
(x) = (y); \
func(p); \
}
+/* When func() returns the void value (NULL, -1, …) of the appropriate type */
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
+ *p = func(*p); \
+ }
+
+/* When func() doesn't return the appropriate type, set variable to empty afterwards */
+#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \
+ static inline void func##p(type *p) { \
+ if (*p != (empty)) { \
func(*p); \
+ *p = (empty); \
+ } \
}
#define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \
run_target(
'update-syscall-tables',
- command : [syscall_table_update_sh, meson.current_source_dir()] + arch_list)
+ command : [update_syscall_tables_sh, meson.current_source_dir()] + arch_list)
-syscall_names_text = files('syscall-names.text')
+syscall_list_txt = files('syscall-list.txt')
syscall_lists = []
foreach arch: arch_list
- syscall_lists += files('syscalls-@0@'.format(arch))
+ syscall_lists += files('syscalls-@0@.txt'.format(arch))
endforeach
missing_syscalls_py = find_program('missing_syscalls.py')
libbasic = static_library(
'basic',
basic_sources,
+ fundamental_sources,
include_directories : basic_includes,
dependencies : [versiondep,
threads,
-/* This file is generated. Do not edit! */
+/* SPDX-License-Identifier: LGPL-2.1-or-later
+ * This file is generated. Do not edit! */
#ifndef __IGNORE_bpf
# if defined(__aarch64__)
# warning "bpf() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_bpf && __NR_bpf >= 0
# if defined systemd_NR_bpf
assert_cc(__NR_bpf == systemd_NR_bpf);
# warning "close_range() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_close_range && __NR_close_range >= 0
# if defined systemd_NR_close_range
assert_cc(__NR_close_range == systemd_NR_close_range);
# warning "copy_file_range() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_copy_file_range && __NR_copy_file_range >= 0
# if defined systemd_NR_copy_file_range
assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range);
# warning "getrandom() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_getrandom && __NR_getrandom >= 0
# if defined systemd_NR_getrandom
assert_cc(__NR_getrandom == systemd_NR_getrandom);
# warning "memfd_create() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_memfd_create && __NR_memfd_create >= 0
# if defined systemd_NR_memfd_create
assert_cc(__NR_memfd_create == systemd_NR_memfd_create);
# warning "name_to_handle_at() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0
# if defined systemd_NR_name_to_handle_at
assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at);
# warning "pidfd_open() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_pidfd_open && __NR_pidfd_open >= 0
# if defined systemd_NR_pidfd_open
assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open);
# warning "pidfd_send_signal() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0
# if defined systemd_NR_pidfd_send_signal
assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal);
# warning "pkey_mprotect() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0
# if defined systemd_NR_pkey_mprotect
assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect);
# warning "renameat2() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_renameat2 && __NR_renameat2 >= 0
# if defined systemd_NR_renameat2
assert_cc(__NR_renameat2 == systemd_NR_renameat2);
# warning "setns() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_setns && __NR_setns >= 0
# if defined systemd_NR_setns
assert_cc(__NR_setns == systemd_NR_setns);
# warning "statx() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_statx && __NR_statx >= 0
# if defined systemd_NR_statx
assert_cc(__NR_statx == systemd_NR_statx);
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
import sys
import functools
yield items[0], int(items[1])
def parse_syscall_tables(filenames):
- return {filename.split('-')[-1]: parse_syscall_table(filename)
+ return {filename.split('-')[-1][:-4]: parse_syscall_table(filename)
for filename in filenames}
DEF_TEMPLATE = '''\
# warning "{syscall}() syscall number is unknown for your architecture"
# endif
-/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_{syscall} && __NR_{syscall} >= 0
# if defined systemd_NR_{syscall}
assert_cc(__NR_{syscall} == systemd_NR_{syscall});
file=out)
def print_syscall_defs(syscalls, tables, out):
- print('/* This file is generated. Do not edit! */\n', file=out)
+ print('''\
+/* SPDX-License-Identifier: LGPL-2.1-or-later
+ * This file is generated. Do not edit! */
+''' , file=out)
for syscall in syscalls:
print_syscall_def(syscall, tables, out)
}
int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
- size_t i;
unsigned val = 0;
const char *s;
s = *p;
/* accept any number of digits, strtoull is limited to 19 */
- for (i=0; i < digits; i++,s++) {
+ for (size_t i = 0; i < digits; i++,s++) {
if (*s < '0' || *s > '9') {
if (i == 0)
return -EINVAL;
return 0;
}
-int parse_percent_unbounded(const char *p) {
+static int parse_parts_value_whole(const char *p, const char *symbol) {
const char *pc, *n;
int r, v;
- pc = endswith(p, "%");
+ pc = endswith(p, symbol);
if (!pc)
return -EINVAL;
return v;
}
+static int parse_parts_value_with_tenths_place(const char *p, const char *symbol) {
+ const char *pc, *dot, *n;
+ int r, q, v;
+
+ pc = endswith(p, symbol);
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 2 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9')
+ return -EINVAL;
+ q = dot[1] - '0';
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v < 0)
+ return -ERANGE;
+ if (v > (INT_MAX - q) / 10)
+ return -ERANGE;
+
+ v = v * 10 + q;
+ return v;
+}
+
+static int parse_parts_value_with_hundredths_place(const char *p, const char *symbol) {
+ const char *pc, *dot, *n;
+ int r, q, v;
+
+ pc = endswith(p, symbol);
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 3 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9' || dot[2] < '0' || dot[2] > '9')
+ return -EINVAL;
+ q = (dot[1] - '0') * 10 + (dot[2] - '0');
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v < 0)
+ return -ERANGE;
+ if (v > (INT_MAX - q) / 100)
+ return -ERANGE;
+
+ v = v * 100 + q;
+ return v;
+}
+
+int parse_percent_unbounded(const char *p) {
+ return parse_parts_value_whole(p, "%");
+}
+
int parse_percent(const char *p) {
int v;
}
int parse_permille_unbounded(const char *p) {
- const char *pc, *pm, *dot, *n;
- int r, q, v;
+ const char *pm;
pm = endswith(p, "‰");
- if (pm) {
- n = strndupa(p, pm - p);
- r = safe_atoi(n, &v);
- if (r < 0)
- return r;
- if (v < 0)
- return -ERANGE;
- } else {
- pc = endswith(p, "%");
- if (!pc)
- return -EINVAL;
-
- dot = memchr(p, '.', pc - p);
- if (dot) {
- if (dot + 2 != pc)
- return -EINVAL;
- if (dot[1] < '0' || dot[1] > '9')
- return -EINVAL;
- q = dot[1] - '0';
- n = strndupa(p, dot - p);
- } else {
- q = 0;
- n = strndupa(p, pc - p);
- }
- r = safe_atoi(n, &v);
- if (r < 0)
- return r;
- if (v < 0)
- return -ERANGE;
- if (v > (INT_MAX - q) / 10)
- return -ERANGE;
+ if (pm)
+ return parse_parts_value_whole(p, "‰");
- v = v * 10 + q;
- }
-
- return v;
+ return parse_parts_value_with_tenths_place(p, "%");
}
int parse_permille(const char *p) {
return v;
}
+int parse_permyriad_unbounded(const char *p) {
+ const char *pm;
+
+ pm = endswith(p, "‱");
+ if (pm)
+ return parse_parts_value_whole(p, "‱");
+
+ pm = endswith(p, "‰");
+ if (pm)
+ return parse_parts_value_with_tenths_place(p, "‰");
+
+ return parse_parts_value_with_hundredths_place(p, "%");
+}
+
+int parse_permyriad(const char *p) {
+ int v;
+
+ v = parse_permyriad_unbounded(p);
+ if (v > 10000)
+ return -ERANGE;
+
+ return v;
+}
+
int parse_nice(const char *p, int *ret) {
int n, r;
int parse_permille_unbounded(const char *p);
int parse_permille(const char *p);
+int parse_permyriad_unbounded(const char *p);
+int parse_permyriad(const char *p);
+
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
static int check_x_access(const char *path, int *ret_fd) {
_cleanup_close_ int fd = -1;
- const char *with_dash;
int r;
- if (ret_fd) {
- /* We need to use O_PATH because there may be executables for which we have only exec
- * permissions, but not read (usually suid executables). */
- fd = open(path, O_PATH|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- r = access_fd(fd, X_OK);
- if (r < 0)
- return r;
- } else {
- /* Let's optimize things a bit by not opening the file if we don't need the fd. */
- if (access(path, X_OK) < 0)
- return -errno;
- }
-
- with_dash = strjoina(path, "/");
+ /* We need to use O_PATH because there may be executables for which we have only exec
+ * permissions, but not read (usually suid executables). */
+ fd = open(path, O_PATH|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
- /* If this passes, it must be a directory. */
- if (access(with_dash, X_OK) >= 0)
- return -EISDIR;
+ r = fd_verify_regular(fd);
+ if (r < 0)
+ return r;
- if (errno != ENOTDIR)
- return -errno;
+ r = access_fd(fd, X_OK);
+ if (r < 0)
+ return r;
if (ret_fd)
*ret_fd = TAKE_FD(fd);
return executable_is_good(checker);
}
-int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {
- char *p;
- int r;
-
- /*
- * This function is intended to be used in command line
- * parsers, to handle paths that are passed in. It makes the
- * path absolute, and reduces it to NULL if omitted or
- * root (the latter optionally).
- *
- * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON
- * SUCCESS! Hence, do not pass in uninitialized pointers.
- */
-
- if (isempty(path)) {
- *arg = mfree(*arg);
- return 0;
- }
-
- r = path_make_absolute_cwd(path, &p);
- if (r < 0)
- return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
-
- path_simplify(p, false);
- if (suppress_root && empty_or_root(p))
- p = mfree(p);
-
- free_and_replace(*arg, p);
-
- return 0;
-}
-
char* dirname_malloc(const char *path) {
char *d, *dir, *dir2;
* Also, the empty string is mapped to itself.
*
* This is different than basename(), which returns "" when a trailing slash is present.
+ *
+ * This always succeeds (except if you pass NULL in which case it returns NULL, too).
*/
unsigned l, k;
int path_extract_filename(const char *p, char **ret) {
_cleanup_free_ char *a = NULL;
- const char *c, *e = NULL, *q;
+ const char *c;
/* Extracts the filename part (i.e. right-most component) from a path, i.e. string that passes
- * filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. */
+ * filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. Returns
+ * -EADDRNOTAVAIL if specified parameter includes no filename (i.e. is "/" or so). Returns -EINVAL if
+ * not a valid path in the first place. */
- if (!p)
+ if (!path_is_valid(p))
return -EINVAL;
- c = last_path_component(p);
-
- for (q = c; *q != 0; q++)
- if (*q != '/')
- e = q + 1;
+ /* Special case the root dir, because in that case we simply have no filename, but
+ * last_path_component() won't complain */
+ if (path_equal(p, "/"))
+ return -EADDRNOTAVAIL;
- if (!e) /* no valid character? */
- return -EINVAL;
+ c = last_path_component(p);
- a = strndup(c, e - c);
+ a = strndup(c, strcspn(c, "/"));
if (!a)
return -ENOMEM;
return -EINVAL;
*ret = TAKE_PTR(a);
-
return 0;
}
if (*e != 0)
return false;
- if (e - p > FILENAME_MAX) /* FILENAME_MAX is counted *without* the trailing NUL byte */
+ if (e - p > NAME_MAX) /* NAME_MAX is counted *without* the trailing NUL byte */
return false;
return true;
if (isempty(p))
return false;
- if (strlen(p) >= PATH_MAX) /* PATH_MAX is counted *with* the trailing NUL byte */
- return false;
+ for (const char *e = p;;) {
+ size_t n;
- return true;
+ /* Skip over slashes */
+ e += strspn(e, "/");
+ if (e - p >= PATH_MAX) /* Already reached the maximum length for a path? (PATH_MAX is counted
+ * *with* the trailing NUL byte) */
+ return false;
+ if (*e == 0) /* End of string? Yay! */
+ return true;
+
+ /* Skip over one component */
+ n = strcspn(e, "/");
+ if (n > NAME_MAX) /* One component larger than NAME_MAX? (NAME_MAX is counted *without* the
+ * trailing NUL byte) */
+ return false;
+
+ e += n;
+ }
}
bool path_is_normalized(const char *p) {
_ret; \
})
-int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg);
-
char* dirname_malloc(const char *path);
const char *last_path_component(const char *path);
int path_extract_filename(const char *p, char **ret);
return 1;
}
+
+int random_u64_range(uint64_t m) {
+ uint64_t x, remainder;
+
+ /* Generates a random number in the range 0…m-1, unbiased. (Java's algorithm) */
+
+ if (m == 0) /* Let's take m == 0 as special case to return an integer from the full range */
+ return random_u64();
+ if (m == 1)
+ return 0;
+
+ remainder = UINT64_MAX % m;
+
+ do {
+ x = random_u64();
+ } while (x >= UINT64_MAX - remainder);
+
+ return x % m;
+}
size_t random_pool_size(void);
int random_write_entropy(int fd, const void *seed, size_t size, bool credit);
+
+int random_u64_range(uint64_t max);
fixed.rlim_max == highest.rlim_max)
return 0;
+ log_debug("Failed at setting rlimit " RLIM_FMT " for resource RLIMIT_%s. Will attempt setting value " RLIM_FMT " instead.", rlim->rlim_max, rlimit_to_string(resource), fixed.rlim_max);
+
if (setrlimit(resource, &fixed) < 0)
return -errno;
}
int setrlimit_closest_all(const struct rlimit *const *rlim, int *which_failed) {
- int i, r;
+ int r;
assert(rlim);
/* On failure returns the limit's index that failed in *which_failed, but only if non-NULL */
- for (i = 0; i < _RLIMIT_MAX; i++) {
+ for (int i = 0; i < _RLIMIT_MAX; i++) {
if (!rlim[i])
continue;
int rm_rf(const char *path, RemoveFlags flags);
/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
-static inline void rm_rf_physical_and_free(char *p) {
+static inline char *rm_rf_physical_and_free(char *p) {
PROTECT_ERRNO;
+
+ if (!p)
+ return NULL;
+
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
free(p);
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_physical_and_free);
/* Similar as above, but also has magic btrfs subvolume powers */
-static inline void rm_rf_subvolume_and_free(char *p) {
+static inline char *rm_rf_subvolume_and_free(char *p) {
PROTECT_ERRNO;
+
+ if (!p)
+ return NULL;
+
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
free(p);
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_subvolume_and_free);
#include "time-util.h"
#if HAVE_SELINUX
-DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(context_t, context_free, NULL);
#define _cleanup_context_free_ _cleanup_(context_freep)
static int mac_selinux_reload(int seqno);
int _e = (error); \
\
int _r = (log_get_max_level() >= LOG_PRI(_level)) \
- ? log_internal_realm(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
+ ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
: -ERRNO_VALUE(_e); \
_enforcing ? _r : 0; \
})
#if HAVE_SELINUX
#include <selinux/selinux.h>
-DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, freecon, NULL);
#define _cleanup_freecon_ _cleanup_(freeconp)
#endif
static volatile sig_atomic_t n_sigbus_queue = 0;
static void sigbus_push(void *addr) {
- unsigned u;
-
assert(addr);
/* Find a free place, increase the number of entries and leave, if we can */
- for (u = 0; u < SIGBUS_QUEUE_MAX; u++)
+ for (size_t u = 0; u < SIGBUS_QUEUE_MAX; u++)
if (__sync_bool_compare_and_swap(&sigbus_queue[u], NULL, addr)) {
__sync_fetch_and_add(&n_sigbus_queue, 1);
return;
.sa_handler = SIG_DFL,
.sa_flags = SA_RESTART,
};
- int sig, r = 0;
+ int r = 0;
- for (sig = 1; sig < _NSIG; sig++) {
+ for (int sig = 1; sig < _NSIG; sig++) {
/* These two cannot be caught... */
if (IN_SET(sig, SIGKILL, SIGSTOP))
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
const char *signal_to_string(int signo) {
- static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
+ static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int)];
const char *name;
name = __signal_to_string(signo);
SMACK_ATTR_IPIN,
SMACK_ATTR_IPOUT,
_SMACK_ATTR_MAX,
- _SMACK_ATTR_INVALID = -1,
+ _SMACK_ATTR_INVALID = -EINVAL,
} SmackAttr;
bool mac_smack_use(void);
if (isempty(p))
return false;
+ /* A valid ifindex? If so, it's valid iff IFNAME_VALID_NUMERIC is set */
+ if (parse_ifindex(p) >= 0)
+ return flags & IFNAME_VALID_NUMERIC;
+
if (flags & IFNAME_VALID_ALTERNATIVE) {
if (strlen(p) >= ALTIFNAMSIZ)
return false;
numeric = numeric && (*t >= '0' && *t <= '9');
}
- if (numeric) {
- if (!(flags & IFNAME_VALID_NUMERIC))
- return false;
-
- /* Verify that the number is well-formatted and in range. */
- if (parse_ifindex(p) < 0)
- return false;
- }
+ /* It's fully numeric but didn't parse as valid ifindex above? if so, it must be too large or zero or
+ * so, let's refuse that. */
+ if (numeric)
+ return false;
return true;
}
SOCKET_ADDRESS_BOTH,
SOCKET_ADDRESS_IPV6_ONLY,
_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
- _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1
+ _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -EINVAL,
} SocketAddressBindIPv6Only;
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
int ip_tos_from_string(const char *s);
typedef enum {
- IFNAME_VALID_ALTERNATIVE = 1 << 0,
- IFNAME_VALID_NUMERIC = 1 << 1,
- _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
+ IFNAME_VALID_ALTERNATIVE = 1 << 0,
+ IFNAME_VALID_NUMERIC = 1 << 1,
+ _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
} IfnameValidFlags;
bool ifname_valid_full(const char *p, IfnameValidFlags flags);
static inline bool ifname_valid(const char *p) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
- if (path)
+ if (path) {
fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
- else
- fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
- if (fd < 0)
- return -errno;
+ if (fd < 0)
+ return -errno;
+ } else {
+ /* Note that DUPing is not enough, as the internal pointer
+ * would still be shared and moved by FOREACH_DIRENT. */
+ fd = fd_reopen(dir_fd, O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+ }
d = take_fdopendir(&fd);
if (!d)
* ...
*/
-struct strbuf *strbuf_new(void) {
+struct strbuf* strbuf_new(void) {
struct strbuf *str;
str = new(struct strbuf, 1);
}
/* clean up everything */
-void strbuf_cleanup(struct strbuf *str) {
+struct strbuf* strbuf_free(struct strbuf *str) {
if (!str)
- return;
+ return NULL;
strbuf_complete(str);
free(str->buf);
- free(str);
+ return mfree(str);
}
static int strbuf_children_cmp(const struct strbuf_child_entry *n1,
struct strbuf_node *child;
};
-struct strbuf *strbuf_new(void);
+struct strbuf* strbuf_new(void);
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
void strbuf_complete(struct strbuf *str);
-void strbuf_cleanup(struct strbuf *str);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup);
+struct strbuf* strbuf_free(struct strbuf *str);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_free);
ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
if (!key)
- return -1;
+ return -EINVAL;
for (size_t i = 0; i < len; ++i)
if (streq_ptr(table[i], key))
return (ssize_t) i;
- return -1;
+ return -EINVAL;
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
scope type name##_from_string(const char *s) { \
if (!s) \
- return -1; \
+ return -EINVAL; \
int b = parse_boolean(s); \
if (b == 0) \
return (type) 0; \
unsigned u = 0; \
type i; \
if (!s) \
- return (type) -1; \
+ return -EINVAL; \
i = (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
if (i >= 0) \
return i; \
- if (safe_atou(s, &u) >= 0 && u <= max) \
- return (type) u; \
- return (type) -1; \
- } \
+ if (safe_atou(s, &u) < 0) \
+ return -EINVAL; \
+ if (u > max) \
+ return -EINVAL; \
+ return (type) u; \
+ }
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
#define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,)
+#define DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes) \
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,static)
/* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
#define DUMP_STRING_TABLE(name,type,max) \
do { \
- type _k; \
flockfile(stdout); \
- for (_k = 0; _k < (max); _k++) { \
+ for (type _k = 0; _k < (max); _k++) { \
const char *_t; \
_t = name##_to_string(_k); \
if (!_t) \
#include "utf8.h"
#include "util.h"
-int strcmp_ptr(const char *a, const char *b) {
- /* Like strcmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-int strcasecmp_ptr(const char *a, const char *b) {
- /* Like strcasecmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcasecmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-char* endswith(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (memcmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* endswith_no_case(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (strcasecmp(s + sl - pl, postfix) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
char* first_word(const char *s, const char *word) {
size_t sl, wl;
const char *p;
}
char *strrep(const char *s, unsigned n) {
- size_t l;
char *r, *p;
- unsigned i;
+ size_t l;
assert(s);
if (!r)
return NULL;
- for (i = 0; i < n; i++)
+ for (unsigned i = 0; i < n; i++)
p = stpcpy(p, s);
*p = 0;
#include "alloc-util.h"
#include "macro.h"
+#include "string-util-fundamental.h"
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define ALPHANUMERICAL LETTERS DIGITS
#define HEXDIGITS DIGITS "abcdefABCDEF"
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
-#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
-
-int strcmp_ptr(const char *a, const char *b) _pure_;
-int strcasecmp_ptr(const char *a, const char *b) _pure_;
-
-static inline bool streq_ptr(const char *a, const char *b) {
- return strcmp_ptr(a, b) == 0;
-}
-
-static inline bool strcaseeq_ptr(const char *a, const char *b) {
- return strcasecmp_ptr(a, b) == 0;
-}
-
static inline char* strstr_ptr(const char *haystack, const char *needle) {
if (!haystack || !needle)
return NULL;
return s ?: "n/a";
}
-static inline const char* yes_no(bool b) {
- return b ? "yes" : "no";
-}
-
static inline const char* true_false(bool b) {
return b ? "true" : "false";
}
return b ? "enable" : "disable";
}
-static inline bool isempty(const char *p) {
- return !p || !p[0];
-}
-
static inline const char *empty_to_null(const char *p) {
return isempty(p) ? NULL : p;
}
return empty_or_dash(p) ? NULL : p;
}
-static inline char *startswith(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-static inline char *startswith_no_case(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncasecmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-char *endswith(const char *s, const char *postfix) _pure_;
-char *endswith_no_case(const char *s, const char *postfix) _pure_;
-
char *first_word(const char *s, const char *word) _pure_;
char *strnappend(const char *s, const char *suffix, size_t length);
if (on)
*on = ansi_highlight_red();
if (off)
- *off = ANSI_NORMAL;
+ *off = ansi_normal();
if (highlight)
- *highlight = ANSI_HIGHLIGHT;
+ *highlight = ansi_highlight();
} else if (priority <= LOG_WARNING) {
if (on)
*on = ansi_highlight_yellow();
if (off)
- *off = ANSI_NORMAL;
+ *off = ansi_normal();
if (highlight)
- *highlight = ANSI_HIGHLIGHT;
+ *highlight = ansi_highlight();
} else if (priority <= LOG_NOTICE) {
if (on)
- *on = ANSI_HIGHLIGHT;
+ *on = ansi_highlight();
if (off)
- *off = ANSI_NORMAL;
+ *off = ansi_normal();
if (highlight)
*highlight = ansi_highlight_red();
if (on)
*on = ansi_grey();
if (off)
- *off = ANSI_NORMAL;
+ *off = ansi_normal();
if (highlight)
*highlight = ansi_highlight_red();
}
/* Only 256 colors. */
COLOR_256 = 256,
- _COLOR_INVALID = -1,
+ _COLOR_INVALID = -EINVAL,
} ColorMode;
int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
{ "us", 1 },
};
- size_t i;
char *p = buf;
bool something = false;
/* The result of this function can be parsed with parse_sec */
- for (i = 0; i < ELEMENTSOF(table); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(table); i++) {
int k = 0;
size_t n;
bool done = false;
{ "us", 1ULL },
{ "µs", 1ULL },
};
- size_t i;
- for (i = 0; i < ELEMENTSOF(table); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(table); i++) {
char *e;
e = startswith(p, table[i].suffix);
TIMESTAMP_UTC,
TIMESTAMP_US_UTC,
_TIMESTAMP_STYLE_MAX,
- _TIMESTAMP_STYLE_INVALID = -1,
+ _TIMESTAMP_STYLE_INVALID = -EINVAL,
} TimestampStyle;
#define USEC_INFINITY ((usec_t) UINT64_MAX)
const char *fn;
char *t, *x;
uint64_t u;
- unsigned i;
assert(ret);
x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
u = random_u64();
- for (i = 0; i < 16; i++) {
+ for (unsigned i = 0; i < 16; i++) {
*(x++) = hexchar(u & 0xF);
u >>= 4;
}
int tempfn_random_child(const char *p, const char *extra, char **ret) {
char *t, *x;
uint64_t u;
- unsigned i;
int r;
assert(ret);
x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
u = random_u64();
- for (i = 0; i < 16; i++) {
+ for (unsigned i = 0; i < 16; i++) {
*(x++) = hexchar(u & 0xF);
u >>= 4;
}
DEFINE_STRING_TABLE_LOOKUP(freezer_state, FreezerState);
+static const char* const unit_marker_table[_UNIT_MARKER_MAX] = {
+ [UNIT_MARKER_NEEDS_RELOAD] = "needs-reload",
+ [UNIT_MARKER_NEEDS_RESTART] = "needs-restart",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(unit_marker, UnitMarker);
+
static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
[AUTOMOUNT_DEAD] = "dead",
[AUTOMOUNT_WAITING] = "waiting",
};
DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
+
+SpecialGlyph unit_active_state_to_glyph(UnitActiveState state) {
+ switch (state) {
+ case UNIT_ACTIVE:
+ return SPECIAL_GLYPH_BLACK_CIRCLE;
+ case UNIT_RELOADING:
+ return SPECIAL_GLYPH_CIRCLE_ARROW;
+ case UNIT_INACTIVE:
+ return SPECIAL_GLYPH_WHITE_CIRCLE;
+ case UNIT_FAILED:
+ return SPECIAL_GLYPH_MULTIPLICATION_SIGN;
+ case UNIT_ACTIVATING:
+ case UNIT_DEACTIVATING:
+ return SPECIAL_GLYPH_BLACK_CIRCLE;
+ case UNIT_MAINTENANCE:
+ return SPECIAL_GLYPH_WHITE_CIRCLE;
+
+ default:
+ return SPECIAL_GLYPH_BLACK_CIRCLE;
+ }
+}
#include <stdbool.h>
+#include "locale-util.h"
#include "macro.h"
/* The enum order is used to order unit jobs in the job queue
UNIT_SLICE,
UNIT_SCOPE,
_UNIT_TYPE_MAX,
- _UNIT_TYPE_INVALID = -1
+ _UNIT_TYPE_INVALID = -EINVAL,
} UnitType;
typedef enum UnitLoadState {
UNIT_MERGED,
UNIT_MASKED,
_UNIT_LOAD_STATE_MAX,
- _UNIT_LOAD_STATE_INVALID = -1
+ _UNIT_LOAD_STATE_INVALID = -EINVAL,
} UnitLoadState;
typedef enum UnitActiveState {
UNIT_DEACTIVATING,
UNIT_MAINTENANCE,
_UNIT_ACTIVE_STATE_MAX,
- _UNIT_ACTIVE_STATE_INVALID = -1
+ _UNIT_ACTIVE_STATE_INVALID = -EINVAL,
} UnitActiveState;
typedef enum FreezerState {
FREEZER_FROZEN,
FREEZER_THAWING,
_FREEZER_STATE_MAX,
- _FREEZER_STATE_INVALID = -1
+ _FREEZER_STATE_INVALID = -EINVAL,
} FreezerState;
+typedef enum UnitMarker {
+ UNIT_MARKER_NEEDS_RELOAD,
+ UNIT_MARKER_NEEDS_RESTART,
+ _UNIT_MARKER_MAX,
+ _UNIT_MARKER_INVALID = -1
+} UnitMarker;
+
typedef enum AutomountState {
AUTOMOUNT_DEAD,
AUTOMOUNT_WAITING,
AUTOMOUNT_RUNNING,
AUTOMOUNT_FAILED,
_AUTOMOUNT_STATE_MAX,
- _AUTOMOUNT_STATE_INVALID = -1
+ _AUTOMOUNT_STATE_INVALID = -EINVAL,
} AutomountState;
/* We simply watch devices, we cannot plug/unplug them. That
DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
DEVICE_PLUGGED, /* announced by udev */
_DEVICE_STATE_MAX,
- _DEVICE_STATE_INVALID = -1
+ _DEVICE_STATE_INVALID = -EINVAL,
} DeviceState;
typedef enum MountState {
MOUNT_FAILED,
MOUNT_CLEANING,
_MOUNT_STATE_MAX,
- _MOUNT_STATE_INVALID = -1
+ _MOUNT_STATE_INVALID = -EINVAL,
} MountState;
typedef enum PathState {
PATH_RUNNING,
PATH_FAILED,
_PATH_STATE_MAX,
- _PATH_STATE_INVALID = -1
+ _PATH_STATE_INVALID = -EINVAL,
} PathState;
typedef enum ScopeState {
SCOPE_STOP_SIGKILL,
SCOPE_FAILED,
_SCOPE_STATE_MAX,
- _SCOPE_STATE_INVALID = -1
+ _SCOPE_STATE_INVALID = -EINVAL,
} ScopeState;
typedef enum ServiceState {
SERVICE_AUTO_RESTART,
SERVICE_CLEANING,
_SERVICE_STATE_MAX,
- _SERVICE_STATE_INVALID = -1
+ _SERVICE_STATE_INVALID = -EINVAL,
} ServiceState;
typedef enum SliceState {
SLICE_DEAD,
SLICE_ACTIVE,
_SLICE_STATE_MAX,
- _SLICE_STATE_INVALID = -1
+ _SLICE_STATE_INVALID = -EINVAL,
} SliceState;
typedef enum SocketState {
SOCKET_FAILED,
SOCKET_CLEANING,
_SOCKET_STATE_MAX,
- _SOCKET_STATE_INVALID = -1
+ _SOCKET_STATE_INVALID = -EINVAL,
} SocketState;
typedef enum SwapState {
SWAP_FAILED,
SWAP_CLEANING,
_SWAP_STATE_MAX,
- _SWAP_STATE_INVALID = -1
+ _SWAP_STATE_INVALID = -EINVAL,
} SwapState;
typedef enum TargetState {
TARGET_DEAD,
TARGET_ACTIVE,
_TARGET_STATE_MAX,
- _TARGET_STATE_INVALID = -1
+ _TARGET_STATE_INVALID = -EINVAL,
} TargetState;
typedef enum TimerState {
TIMER_ELAPSED,
TIMER_FAILED,
_TIMER_STATE_MAX,
- _TIMER_STATE_INVALID = -1
+ _TIMER_STATE_INVALID = -EINVAL,
} TimerState;
typedef enum UnitDependency {
UNIT_REFERENCED_BY,
_UNIT_DEPENDENCY_MAX,
- _UNIT_DEPENDENCY_INVALID = -1
+ _UNIT_DEPENDENCY_INVALID = -EINVAL,
} UnitDependency;
typedef enum NotifyAccess {
NOTIFY_MAIN,
NOTIFY_EXEC,
_NOTIFY_ACCESS_MAX,
- _NOTIFY_ACCESS_INVALID = -1
+ _NOTIFY_ACCESS_INVALID = -EINVAL,
} NotifyAccess;
char *unit_dbus_path_from_name(const char *name);
const char *freezer_state_to_string(FreezerState i) _const_;
FreezerState freezer_state_from_string(const char *s) _pure_;
+const char *unit_marker_to_string(UnitMarker m) _const_;
+UnitMarker unit_marker_from_string(const char *s) _pure_;
+
const char* automount_state_to_string(AutomountState i) _const_;
AutomountState automount_state_from_string(const char *s) _pure_;
const char* notify_access_to_string(NotifyAccess i) _const_;
NotifyAccess notify_access_from_string(const char *s) _pure_;
+
+SpecialGlyph unit_active_state_to_glyph(UnitActiveState state);
/* Check if the symlink goes outside of our search path.
* If yes, it's a linked unit file or mask, and we don't care about the target name.
- * Let's just store the link destination directly.
+ * Let's just store the link source directly.
* If not, let's verify that it's a good symlink. */
char *tail = path_startswith_strv(simplified, lp->search_path);
- if (tail) {
+ if (!tail) {
+ log_debug("%s: linked unit file: %s → %s",
+ __func__, filename, simplified);
+
+ dst = filename;
+ } else {
+
bool self_alias;
dst = basename(simplified);
}
log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst);
- } else {
- dst = simplified;
-
- log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst);
}
} else {
const char* runlevel_to_target(const char *word) {
const char * const *rlmap_ptr;
- size_t i;
if (!word)
return NULL;
rlmap_ptr = in_initrd() ? rlmap_initrd : rlmap;
- for (i = 0; rlmap_ptr[i]; i += 2)
+ for (size_t i = 0; rlmap_ptr[i]; i += 2)
if (streq(word, rlmap_ptr[i]))
return rlmap_ptr[i+1];
UNIT_FILE_TRANSIENT,
UNIT_FILE_BAD,
_UNIT_FILE_STATE_MAX,
- _UNIT_FILE_STATE_INVALID = -1
+ _UNIT_FILE_STATE_INVALID = -EINVAL,
};
enum UnitFileScope {
UNIT_FILE_GLOBAL,
UNIT_FILE_USER,
_UNIT_FILE_SCOPE_MAX,
- _UNIT_FILE_SCOPE_INVALID = -1
+ _UNIT_FILE_SCOPE_INVALID = -EINVAL,
};
bool unit_type_may_alias(UnitType type) _const_;
type = unit_type_from_string(suffix + 1);
if (type < 0)
- return -EINVAL;
+ return type;
return unit_name_build_from_type(prefix, instance, type, ret);
}
UNIT_NAME_TEMPLATE = 1 << 1, /* Allow foo@.service */
UNIT_NAME_INSTANCE = 1 << 2, /* Allow foo@bar.service */
UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE,
- _UNIT_NAME_INVALID = -1,
+ _UNIT_NAME_INVALID = -EINVAL,
} UnitNameFlags;
bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_;
/* decode one unicode char */
int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
char32_t unichar;
- size_t len, i;
+ size_t len;
assert(str);
return -EINVAL;
}
- for (i = 1; i < len; i++) {
+ for (size_t i = 1; i < len; i++) {
if (((char32_t)str[i] & 0xc0) != 0x80)
return -EINVAL;
}
char *ascii_is_valid_n(const char *str, size_t len) {
- size_t i;
-
/* Very similar to ascii_is_valid(), but checks exactly len
* bytes and rejects any NULs in that range. */
assert(str);
- for (i = 0; i < len; i++)
+ for (size_t i = 0; i < len; i++)
if ((unsigned char) str[i] >= 128 || str[i] == 0)
return NULL;
char16_t *utf8_to_utf16(const char *s, size_t length) {
char16_t *n, *p;
- size_t i;
int r;
assert(s);
p = n;
- for (i = 0; i < length;) {
+ for (size_t i = 0; i < length;) {
char32_t unichar;
size_t e;
/* validate one encoded unicode char and return its length */
int utf8_encoded_valid_unichar(const char *str, size_t length /* bytes */) {
char32_t unichar;
- size_t len, i;
+ size_t len;
int r;
assert(str);
return 1;
/* check if expected encoded chars are available */
- for (i = 0; i < len; i++)
+ for (size_t i = 0; i < len; i++)
if ((str[i] & 0x80) != 0x80)
return -EINVAL;
return 0;
}
-/* This is a direct translation of str_verscmp from boot.c */
-static bool is_digit(int c) {
- return c >= '0' && c <= '9';
-}
-
-static int c_order(int c) {
- if (c == 0 || is_digit(c))
- return 0;
-
- if ((c >= 'a') && (c <= 'z'))
- return c;
-
- return c + 0x10000;
-}
-
-int str_verscmp(const char *s1, const char *s2) {
- const char *os1, *os2;
-
- assert(s1);
- assert(s2);
-
- os1 = s1;
- os2 = s2;
-
- while (*s1 || *s2) {
- int first;
-
- while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
- int order;
-
- order = c_order(*s1) - c_order(*s2);
- if (order != 0)
- return order;
- s1++;
- s2++;
- }
-
- while (*s1 == '0')
- s1++;
- while (*s2 == '0')
- s2++;
-
- first = 0;
- while (is_digit(*s1) && is_digit(*s2)) {
- if (first == 0)
- first = *s1 - *s2;
- s1++;
- s2++;
- }
-
- if (is_digit(*s1))
- return 1;
- if (is_digit(*s2))
- return -1;
-
- if (first != 0)
- return first;
- }
-
- return strcmp(os1, os2);
-}
-
/* Turn off core dumps but only if we're running outside of a container. */
void disable_coredumps(void) {
int r;
int version(void);
-int str_verscmp(const char *s1, const char *s2);
-
void disable_coredumps(void);
#include <unistd.h>
#include "alloc-util.h"
+#include "cgroup-util.h"
#include "dirent-util.h"
#include "env-util.h"
#include "fd-util.h"
/* https://wiki.freebsd.org/bhyve */
{ "BHYVE", VIRTUALIZATION_BHYVE },
};
- unsigned i;
int r;
- for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
_cleanup_free_ char *s = NULL;
unsigned j;
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
+static int running_in_cgroupns(void) {
+ int r;
+
+ if (!cg_ns_supported())
+ return false;
+
+ r = cg_all_unified();
+ if (r < 0)
+ return r;
+
+ if (r) {
+ /* cgroup v2 */
+
+ r = access("/sys/fs/cgroup/cgroup.events", F_OK);
+ if (r < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ /* All kernel versions have cgroup.events in nested cgroups. */
+ return false;
+ }
+
+ /* There's no cgroup.type in the root cgroup, and future kernel versions
+ * are unlikely to add it since cgroup.type is something that makes no sense
+ * whatsoever in the root cgroup. */
+ r = access("/sys/fs/cgroup/cgroup.type", F_OK);
+ if (r == 0)
+ return true;
+ if (r < 0 && errno != ENOENT)
+ return -errno;
+
+ /* On older kernel versions, there's no cgroup.type */
+ r = access("/sys/kernel/cgroup/features", F_OK);
+ if (r < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ /* This is an old kernel that we know for sure has cgroup.events
+ * only in nested cgroups. */
+ return true;
+ }
+
+ /* This is a recent kernel, and cgroup.type doesn't exist, so we must be
+ * in the root cgroup. */
+ return false;
+ } else {
+ /* cgroup v1 */
+
+ /* If systemd controller is not mounted, do not even bother. */
+ r = access("/sys/fs/cgroup/systemd", F_OK);
+ if (r < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ return false;
+ }
+
+ /* release_agent only exists in the root cgroup. */
+ r = access("/sys/fs/cgroup/systemd/release_agent", F_OK);
+ if (r < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ return true;
+ }
+
+ return false;
+ }
+}
+
+static int detect_container_files(void) {
+ unsigned i;
+
+ static const struct {
+ const char *file_path;
+ int id;
+ } container_file_table[] = {
+ /* https://github.com/containers/podman/issues/6192 */
+ /* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */
+ { "/run/.containerenv", VIRTUALIZATION_PODMAN },
+ /* https://github.com/moby/moby/issues/18355 */
+ /* Docker must be the last in this table, see below. */
+ { "/.dockerenv", VIRTUALIZATION_DOCKER },
+ };
+
+ for (i = 0; i < ELEMENTSOF(container_file_table); i++) {
+ if (access(container_file_table[i].file_path, F_OK) >= 0)
+ return container_file_table[i].id;
+
+ if (errno != ENOENT)
+ log_debug_errno(errno,
+ "Checking if %s exists failed, ignoring: %m",
+ container_file_table[i].file_path);
+ }
+
+ return VIRTUALIZATION_NONE;
+}
+
int detect_container(void) {
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
_cleanup_free_ char *m = NULL, *o = NULL, *p = NULL;
*/
e = getenv("container");
if (!e)
- goto none;
+ goto check_files;
if (isempty(e)) {
r = VIRTUALIZATION_NONE;
goto finish;
if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
-none:
- /* If that didn't work, give up, assume no container manager. */
+check_files:
+ /* Check for existence of some well-known files. We only do this after checking
+ * for other specific container managers, otherwise we risk mistaking another
+ * container manager for Docker: the /.dockerenv file could inadvertently end up
+ * in a file system image. */
+ r = detect_container_files();
+ if (r)
+ goto finish;
+
+ r = running_in_cgroupns();
+ if (r > 0) {
+ r = VIRTUALIZATION_CONTAINER_OTHER;
+ goto finish;
+ }
+ if (r < 0)
+ log_debug_errno(r, "Failed to detect cgroup namespace: %m");
+
+ /* If none of that worked, give up, assume no container manager. */
r = VIRTUALIZATION_NONE;
goto finish;
translate_name:
+ if (streq(e, "oci")) {
+ /* Some images hardcode container=oci, but OCI is not a specific container manager.
+ * Try to detect one based on well-known files. */
+ r = detect_container_files();
+ if (!r)
+ r = VIRTUALIZATION_CONTAINER_OTHER;
+ goto finish;
+ }
r = container_from_string(e);
if (r < 0)
r = VIRTUALIZATION_CONTAINER_OTHER;
VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,
_VIRTUALIZATION_MAX,
- _VIRTUALIZATION_INVALID = -1
+ _VIRTUALIZATION_INVALID = -EINVAL,
};
static inline bool VIRTUALIZATION_IS_VM(int x) {
" --cat-config Show configuration files\n"
" --no-pager Do not pipe output into a pager\n"
" --unregister Unregister all existing entries\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
if (r <= 0)
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
- log_setup_service();
+ log_setup();
umask(0022);
" -h --help Show this help\n"
" --version Print version\n"
" --path=PATH Path to the $BOOT partition (may be used multiple times)\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
"\n%sVerify system operational state.%s\n\n"
" -h --help Show this help\n"
" --version Print version\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
b += strcspn(b, " ");
b += strspn(b, " ");
- return strverscmp(a, b);
+ return strverscmp_improved(a, b);
}
static int version_check(int fd_from, const char *from, int fd_to, const char *to) {
" --no-pager Do not pipe output into a pager\n"
" --graceful Don't fail when the ESP cannot be found or EFI\n"
" variables cannot be written\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal()
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
printf(" Firmware: %s%s (%s)%s\n", ansi_highlight(), strna(fw_type), strna(fw_info), ansi_normal());
printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot()));
printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
+ printf(" TPM2 Support: %s\n", yes_no(efi_has_tpm2()));
k = efi_get_reboot_to_firmware();
if (k > 0)
#include "console.h"
#include "crc32.h"
#include "disk.h"
+#include "efi-loader-features.h"
#include "graphics.h"
#include "linux.h"
-#include "loader-features.h"
#include "measure.h"
#include "pe.h"
#include "random-seed.h"
+#include "secure-boot.h"
#include "shim.h"
#include "util.h"
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " GIT_VERSION " ####";
-static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
-
enum loader_type {
LOADER_UNDEFINED,
LOADER_EFI,
while (!exit) {
EFI_STATUS err;
UINT64 key;
- UINTN i;
+ UINTN j;
- i = len - first;
- if (i >= x_max-1)
- i = x_max-1;
- CopyMem(print, line + first, i * sizeof(CHAR16));
- while (clear > 0 && i < x_max-1) {
+ j = len - first;
+ if (j >= x_max-1)
+ j = x_max-1;
+ CopyMem(print, line + first, j * sizeof(CHAR16));
+ while (clear > 0 && j < x_max-1) {
clear--;
- print[i++] = ' ';
+ print[j++] = ' ';
}
- print[i] = '\0';
+ print[j] = '\0';
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos);
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'):
/* kill-word */
clear = 0;
- for (i = first + cursor; i < len && line[i] == ' '; i++)
+
+ UINTN k;
+ for (k = first + cursor; k < len && line[k] == ' '; k++)
clear++;
- for (; i < len && line[i] != ' '; i++)
+ for (; k < len && line[k] != ' '; k++)
clear++;
- for (i = first + cursor; i + clear < len; i++)
+ for (UINTN i = first + cursor; i + clear < len; i++)
line[i] = line[i + clear];
len -= clear;
line[len] = '\0';
}
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- for (i = first + cursor; i + clear < len; i++)
+ for (UINTN i = first + cursor; i + clear < len; i++)
line[i] = line[i + clear];
len -= clear;
line[len] = '\0';
continue;
if (first + cursor == len)
continue;
- for (i = first + cursor; i < len; i++)
+ for (UINTN i = first + cursor; i < len; i++)
line[i] = line[i+1];
clear = 1;
len--;
continue;
if (first == 0 && cursor == 0)
continue;
- for (i = first + cursor-1; i < len; i++)
+ for (UINTN i = first + cursor-1; i < len; i++)
line[i] = line[i+1];
clear = 1;
len--;
case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff):
if (len+1 == size)
continue;
- for (i = len; i > first + cursor; i--)
+ for (UINTN i = len; i > first + cursor; i--)
line[i] = line[i-1];
line[first + cursor] = KEYCHAR(key);
len++;
}
static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
- UINTN i;
-
if (key == 0)
return -1;
/* select entry by number key */
if (key >= '1' && key <= '9') {
- i = key - '0';
+ UINTN i = key - '0';
if (i > config->entry_count)
i = config->entry_count;
return i-1;
}
/* find matching key in config entries */
- for (i = start; i < config->entry_count; i++)
+ for (UINTN i = start; i < config->entry_count; i++)
if (config->entries[i]->key == key)
return i;
- for (i = 0; i < start; i++)
+ for (UINTN i = 0; i < start; i++)
if (config->entries[i]->key == key)
return i;
}
static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
- UINT64 key;
- UINTN i;
- _cleanup_freepool_ CHAR8 *bootvar = NULL, *modevar = NULL, *indvar = NULL;
+ UINT64 key, indvar;
+ UINTN timeout;
+ BOOLEAN modevar;
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
- UINTN x, y, size;
+ UINTN x, y;
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS)
Print(L"console size: %d x %d\n", x, y);
- if (efivar_get_raw(&global_guid, L"SecureBoot", &bootvar, &size) == EFI_SUCCESS)
- Print(L"SecureBoot: %s\n", yes_no(*bootvar > 0));
+ Print(L"SecureBoot: %s\n", yes_no(secure_boot_enabled()));
- if (efivar_get_raw(&global_guid, L"SetupMode", &modevar, &size) == EFI_SUCCESS)
- Print(L"SetupMode: %s\n", *modevar > 0 ? L"setup" : L"user");
+ if (efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &modevar) == EFI_SUCCESS)
+ Print(L"SetupMode: %s\n", modevar ? L"setup" : L"user");
if (shim_loaded())
Print(L"Shim: present\n");
- if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &indvar, &size) == EFI_SUCCESS)
- Print(L"OsIndicationsSupported: %d\n", (UINT64)*indvar);
+ if (efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &indvar) == EFI_SUCCESS)
+ Print(L"OsIndicationsSupported: %d\n", indvar);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
Print(L"entry EFI var idx: %d\n", config->idx_default_efivar);
Print(L"\n");
- if (efivar_get_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS)
- Print(L"LoaderConfigTimeout: %u\n", i);
+ if (efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &timeout) == EFI_SUCCESS)
+ Print(L"LoaderConfigTimeout: %u\n", timeout);
if (config->entry_oneshot)
Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot);
- if (efivar_get(L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS)
+ if (efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS)
Print(L"LoaderDevicePartUUID: %s\n", partstr);
- if (efivar_get(L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS)
+ if (efivar_get(LOADER_GUID, L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS)
Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
ConfigEntry *entry;
if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q'))
UINTN idx_last;
BOOLEAN refresh;
BOOLEAN highlight;
- UINTN i;
UINTN line_width;
CHAR16 **lines;
UINTN x_start;
/* length of the longest entry */
line_width = 5;
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
UINTN entry_len;
entry_len = StrLen(config->entries[i]->title_show);
/* menu entries title lines */
lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
- for (i = 0; i < config->entry_count; i++) {
- UINTN j, k;
+ for (UINTN i = 0; i < config->entry_count; i++) {
+ UINTN j;
lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16)));
for (j = 0; j < x_start; j++)
lines[i][j] = ' ';
- for (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++)
+ for (UINTN k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++)
lines[i][j] = config->entries[i]->title_show[k];
for (; j < x_max; j++)
status = NULL;
clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
- for (i = 0; i < x_max; i++)
+ for (UINTN i = 0; i < x_max; i++)
clearline[i] = ' ';
- clearline[i] = 0;
+ clearline[x_max] = 0;
while (!exit) {
UINT64 key;
if (refresh) {
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
if (i < idx_first || i > idx_last)
continue;
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first);
case KEYPRESS(0, 0, 'd'):
if (config->idx_default_efivar != (INTN)idx_highlight) {
/* store the selected entry in a persistent EFI variable */
- efivar_set(L"LoaderEntryDefault", config->entries[idx_highlight]->id, TRUE);
+ efivar_set(
+ LOADER_GUID,
+ L"LoaderEntryDefault",
+ config->entries[idx_highlight]->id,
+ EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = idx_highlight;
status = StrDuplicate(L"Default boot entry selected.");
} else {
/* clear the default entry EFI variable */
- efivar_set(L"LoaderEntryDefault", NULL, TRUE);
+ efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = -1;
status = StrDuplicate(L"Default boot entry cleared.");
}
case KEYPRESS(0, 0, 'T'):
if (config->timeout_sec_efivar > 0) {
config->timeout_sec_efivar--;
- efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
+ efivar_set_uint_string(
+ LOADER_GUID,
+ L"LoaderConfigTimeout",
+ config->timeout_sec_efivar,
+ EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){
config->timeout_sec_efivar = -1;
- efivar_set(L"LoaderConfigTimeout", NULL, TRUE);
+ efivar_set(
+ LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_config > 0)
status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
config->timeout_sec_config);
if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0)
config->timeout_sec_efivar++;
config->timeout_sec_efivar++;
- efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
+ efivar_set_uint_string(
+ LOADER_GUID,
+ L"LoaderConfigTimeout",
+ config->timeout_sec_efivar,
+ EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.",
config->timeout_sec_efivar);
*chosen_entry = config->entries[idx_highlight];
- for (i = 0; i < config->entry_count; i++)
+ for (UINTN i = 0; i < config->entry_count; i++)
FreePool(lines[i]);
FreePool(lines);
FreePool(clearline);
FreePool(entry);
}
-static BOOLEAN is_digit(CHAR16 c) {
- return (c >= '0') && (c <= '9');
-}
-
-static UINTN c_order(CHAR16 c) {
- if (c == '\0')
- return 0;
- if (is_digit(c))
- return 0;
- else if ((c >= 'a') && (c <= 'z'))
- return c;
- else
- return c + 0x10000;
-}
-
-static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) {
- CHAR16 *os1 = s1;
- CHAR16 *os2 = s2;
-
- while (*s1 || *s2) {
- INTN first;
-
- while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
- INTN order;
-
- order = c_order(*s1) - c_order(*s2);
- if (order != 0)
- return order;
- s1++;
- s2++;
- }
-
- while (*s1 == '0')
- s1++;
- while (*s2 == '0')
- s2++;
-
- first = 0;
- while (is_digit(*s1) && is_digit(*s2)) {
- if (first == 0)
- first = *s1 - *s2;
- s1++;
- s2++;
- }
-
- if (is_digit(*s1))
- return 1;
- if (is_digit(*s2))
- return -1;
-
- if (first != 0)
- return first;
- }
-
- return StrCmp(os1, os2);
-}
-
static CHAR8 *line_get_key_value(
CHAR8 *content,
CHAR8 *sep,
/* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on
* success */
new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name);
- efivar_set(L"LoaderBootCountPath", new_path, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, 0);
/* If the file we just renamed is the loader path, then let's update that. */
if (StrCmp(entry->loader, old_path) == 0) {
if (!EFI_ERROR(err))
config_defaults_load_from_file(config, content);
- err = efivar_get_int(L"LoaderConfigTimeout", &sec);
+ err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &sec);
if (!EFI_ERROR(err)) {
config->timeout_sec_efivar = sec > INTN_MAX ? INTN_MAX : sec;
config->timeout_sec = sec;
} else
config->timeout_sec_efivar = -1;
- err = efivar_get_int(L"LoaderConfigTimeoutOneShot", &sec);
+ err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &sec);
if (!EFI_ERROR(err)) {
/* Unset variable now, after all it's "one shot". */
- (void) efivar_set(L"LoaderConfigTimeoutOneShot", NULL, TRUE);
+ (void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
config->timeout_sec = sec;
config->force_menu = TRUE; /* force the menu when this is set */
UINTN bufsize;
EFI_FILE_INFO *f;
_cleanup_freepool_ CHAR8 *content = NULL;
- UINTN len;
bufsize = sizeof(buf);
err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf);
if (f->Attribute & EFI_FILE_DIRECTORY)
continue;
- len = StrLen(f->FileName);
- if (len < 6)
+ if (!endswith_no_case(f->FileName, L".conf"))
continue;
- if (StriCmp(f->FileName + len - 5, L".conf") != 0)
- continue;
- if (StrnCmp(f->FileName, L"auto-", 5) == 0)
+ if (startswith(f->FileName, L"auto-"))
continue;
err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
if (a->tries_left == 0 && b->tries_left != 0)
return -1;
- r = str_verscmp(a->id, b->id);
+ r = strverscmp_improved(a->id, b->id);
if (r != 0)
return r;
}
static VOID config_sort_entries(Config *config) {
- UINTN i;
-
- for (i = 1; i < config->entry_count; i++) {
+ for (UINTN i = 1; i < config->entry_count; i++) {
BOOLEAN more;
- UINTN k;
more = FALSE;
- for (k = 0; k < config->entry_count - i; k++) {
+ for (UINTN k = 0; k < config->entry_count - i; k++) {
ConfigEntry *entry;
if (config_entry_compare(config->entries[k], config->entries[k+1]) <= 0)
}
static INTN config_entry_find(Config *config, CHAR16 *id) {
- UINTN i;
-
- for (i = 0; i < config->entry_count; i++)
+ for (UINTN i = 0; i < config->entry_count; i++)
if (StrCmp(config->entries[i]->id, id) == 0)
return (INTN) i;
* The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read.
*/
- err = efivar_get(L"LoaderEntryOneShot", &entry_oneshot);
+ err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &entry_oneshot);
if (!EFI_ERROR(err)) {
config->entry_oneshot = StrDuplicate(entry_oneshot);
- efivar_set(L"LoaderEntryOneShot", NULL, TRUE);
+ efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
i = config_entry_find(config, entry_oneshot);
if (i >= 0) {
* the 'd' key in the loader selection menu, the entry is marked with
* an '*'.
*/
- err = efivar_get(L"LoaderEntryDefault", &entry_default);
+ err = efivar_get(LOADER_GUID, L"LoaderEntryDefault", &entry_default);
if (!EFI_ERROR(err)) {
i = config_entry_find(config, entry_default);
static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
BOOLEAN non_unique = FALSE;
- UINTN i, k;
- for (i = 0; i < entry_count; i++)
+ for (UINTN i = 0; i < entry_count; i++)
entries[i]->non_unique = FALSE;
- for (i = 0; i < entry_count; i++)
- for (k = 0; k < entry_count; k++) {
+ for (UINTN i = 0; i < entry_count; i++)
+ for (UINTN k = 0; k < entry_count; k++) {
if (i == k)
continue;
if (StrCmp(entries[i]->title_show, entries[k]->title_show) != 0)
/* generate a unique title, avoiding non-distinguishable menu entries */
static VOID config_title_generate(Config *config) {
- UINTN i;
-
/* set title */
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *title;
FreePool(config->entries[i]->title_show);
return;
/* add version to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s;
if (!config->entries[i]->non_unique)
return;
/* add machine-id to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s;
_cleanup_freepool_ CHAR16 *m = NULL;
return;
/* add file name to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s;
if (!config->entries[i]->non_unique)
/* look for systemd-boot magic string */
err = file_read(root_dir, loader, 0, 100*1024, &content, &len);
- if (!EFI_ERROR(err)) {
- CHAR8 *start = content;
- CHAR8 *last = content + len - sizeof(magic) - 1;
-
- for (; start <= last; start++)
+ if (!EFI_ERROR(err))
+ for (CHAR8 *start = content; start <= content + len - sizeof(magic) - 1; start++)
if (start[0] == magic[0] && CompareMem(start, magic, sizeof(magic) - 1) == 0)
return FALSE;
- }
}
/* check existence */
err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles);
if (!EFI_ERROR(err)) {
- UINTN i;
-
- for (i = 0; i < handle_count; i++) {
+ for (UINTN i = 0; i < handle_count; i++) {
EFI_FILE *root;
BOOLEAN found;
UINTN szs[ELEMENTSOF(sections)-1] = {};
UINTN addrs[ELEMENTSOF(sections)-1] = {};
CHAR8 *content = NULL;
- UINTN len;
CHAR8 *line;
UINTN pos = 0;
CHAR8 *key, *value;
continue;
if (f->Attribute & EFI_FILE_DIRECTORY)
continue;
- len = StrLen(f->FileName);
- if (len < 5)
+ if (!endswith_no_case(f->FileName, L".efi"))
continue;
- if (StriCmp(f->FileName + len - 4, L".efi") != 0)
- continue;
- if (StrnCmp(f->FileName, L"auto-", 5) == 0)
+ if (startswith(f->FileName, L"auto-"))
continue;
/* look for .osrel and .cmdline sections in the .efi binary */
uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
}
-/* Note that this is in GUID format, i.e. the first 32bit, and the following pair of 16bit are byteswapped. */
-static const UINT8 xbootldr_guid[16] = {
- 0xff, 0xc2, 0x13, 0xbc, 0xe6, 0x59, 0x62, 0x42, 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72
-};
+#define XBOOTLDR_GUID \
+ &(const EFI_GUID) { 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } }
-EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) {
+static EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) {
EFI_DEVICE_PATH *parent;
UINTN len;
Config *config,
EFI_HANDLE *device) {
- EFI_DEVICE_PATH *partition_path, *node, *disk_path, *copy;
+ EFI_DEVICE_PATH *partition_path, *disk_path, *copy;
UINT32 found_partition_number = (UINT32) -1;
UINT64 found_partition_start = (UINT64) -1;
UINT64 found_partition_size = (UINT64) -1;
if (!partition_path)
return;
- for (node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
+ for (EFI_DEVICE_PATH *node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
EFI_HANDLE disk_handle;
EFI_BLOCK_IO *block_io;
EFI_DEVICE_PATH *p;
- UINTN nr;
/* First, Let's look for the SCSI/SATA/USB/… device path node, i.e. one above the media
* devices */
continue;
/* Try both copies of the GPT header, in case one is corrupted */
- for (nr = 0; nr < 2; nr++) {
+ for (UINTN nr = 0; nr < 2; nr++) {
_cleanup_freepool_ EFI_PARTITION_ENTRY* entries = NULL;
union {
EFI_PARTITION_TABLE_HEADER gpt_header;
} gpt_header_buffer;
const EFI_PARTITION_TABLE_HEADER *h = &gpt_header_buffer.gpt_header;
UINT64 where;
- UINTN i, sz;
+ UINTN sz;
UINT32 c;
if (nr == 0)
if (c != h->PartitionEntryArrayCRC32)
continue;
- for (i = 0; i < h->NumberOfPartitionEntries; i++) {
+ for (UINTN i = 0; i < h->NumberOfPartitionEntries; i++) {
EFI_PARTITION_ENTRY *entry;
entry = (EFI_PARTITION_ENTRY*) ((UINT8*) entries + h->SizeOfPartitionEntry * i);
- if (CompareMem(&entry->PartitionTypeGUID, xbootldr_guid, 16) == 0) {
+ if (CompareMem(&entry->PartitionTypeGUID, XBOOTLDR_GUID, 16) == 0) {
UINT64 end;
/* Let's use memcpy(), in case the structs are not aligned (they really should be though) */
copy = DuplicateDevicePath(partition_path);
/* Patch in the data we found */
- for (node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
+ for (EFI_DEVICE_PATH *node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
HARDDRIVE_DEVICE_PATH *hd;
if (DevicePathType(node) != MEDIA_DEVICE_PATH)
#endif
}
- efivar_set_time_usec(L"LoaderTimeExecUSec", 0);
+ efivar_set_time_usec(LOADER_GUID, L"LoaderTimeExecUSec", 0);
err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL);
out_unload:
uefi_call_wrapper(BS->UnloadImage, 1, image);
}
static EFI_STATUS reboot_into_firmware(VOID) {
- _cleanup_freepool_ CHAR8 *b = NULL;
- UINTN size;
- UINT64 osind;
+ UINT64 old, new;
EFI_STATUS err;
- osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
+ new = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
- err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size);
+ err = efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &old);
if (!EFI_ERROR(err))
- osind |= (UINT64)*b;
+ new |= old;
- err = efivar_set_raw(&global_guid, L"OsIndications", &osind, sizeof(UINT64), TRUE);
+ err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, EFI_VARIABLE_NON_VOLATILE);
if (EFI_ERROR(err))
return err;
}
static VOID config_free(Config *config) {
- UINTN i;
-
- for (i = 0; i < config->entry_count; i++)
+ for (UINTN i = 0; i < config->entry_count; i++)
config_entry_free(config->entries[i]);
FreePool(config->entries);
FreePool(config->entry_default_pattern);
static VOID config_write_entries_to_variable(Config *config) {
_cleanup_freepool_ CHAR16 *buffer = NULL;
- UINTN i, sz = 0;
+ UINTN sz = 0;
CHAR16 *p;
- for (i = 0; i < config->entry_count; i++)
+ for (UINTN i = 0; i < config->entry_count; i++)
sz += StrLen(config->entries[i]->id) + 1;
p = buffer = AllocatePool(sz * sizeof(CHAR16));
- for (i = 0; i < config->entry_count; i++) {
+ for (UINTN i = 0; i < config->entry_count; i++) {
UINTN l;
l = StrLen(config->entries[i]->id) + 1;
}
/* Store the full list of discovered entries. */
- (void) efivar_set_raw(&loader_guid, L"LoaderEntries", buffer, (UINT8*) p - (UINT8*) buffer, FALSE);
+ (void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, (UINT8 *) p - (UINT8 *) buffer, 0);
}
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
0;
_cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
- CHAR8 *b;
- UINTN size;
+ UINT64 osind = 0;
EFI_LOADED_IMAGE *loaded_image;
EFI_FILE *root_dir;
CHAR16 *loaded_image_path;
InitializeLib(image, sys_table);
init_usec = time_usec();
- efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
- efivar_set(L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE);
+ efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
+ efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- efivar_set(L"LoaderFirmwareInfo", infostr, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0);
typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- efivar_set(L"LoaderFirmwareType", typestr, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0);
- (void) efivar_set_raw(&loader_guid, L"LoaderFeatures", &loader_features, sizeof(loader_features), FALSE);
+ (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0);
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
/* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
- efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) {
/* the filesystem path to this image, to prevent adding ourselves to the menu */
loaded_image_path = DevicePathToStr(loaded_image->FilePath);
- efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderImageIdentifier", loaded_image_path, 0);
config_load_defaults(&config, root_dir);
L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi");
config_entry_add_osx(&config);
- if (config.auto_firmware && efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
- UINT64 osind = (UINT64)*b;
-
+ if (config.auto_firmware && efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &osind) == EFI_SUCCESS) {
if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
config_entry_add_call(&config,
L"auto-reboot-to-firmware-setup",
L"Reboot Into Firmware Interface",
reboot_into_firmware);
- FreePool(b);
}
if (config.entry_count == 0) {
entry = config.entries[config.idx_default];
if (menu) {
- efivar_set_time_usec(L"LoaderTimeMenuUSec", 0);
+ efivar_set_time_usec(LOADER_GUID, L"LoaderTimeMenuUSec", 0);
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL);
if (!menu_run(&config, &entry, loaded_image_path))
break;
config_entry_bump_counters(entry, root_dir);
/* Export the selected boot entry to the system */
- (VOID) efivar_set(L"LoaderEntrySelected", entry->id, FALSE);
+ (VOID) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
/* Optionally, read a random seed off the ESP and pass it to the OS */
(VOID) process_random_seed(root_dir, config.random_seed_mode);
#define SYSTEM_FONT_WIDTH 8
#define SYSTEM_FONT_HEIGHT 19
-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
- { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
+#define EFI_SIMPLE_TEXT_INPUT_EX_GUID \
+ &(EFI_GUID) { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
- EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked;
UINTN index;
EFI_STATUS err;
if (!checked) {
- err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx);
+ err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
if (EFI_ERROR(err))
TextInputEx = NULL;
const UINT8 *p = buf;
UINT32 crc = seed;
- UINTN i;
- for (i = 0; i < len; i++) {
+ for (UINTN i = 0; i < len; i++) {
UINT8 x = *p++;
if (i >= exclude_off && i < exclude_off + exclude_len)
#include <efi.h>
#include <efilib.h>
+#include "disk.h"
#include "util.h"
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
device_path = DevicePathFromHandle(handle);
if (device_path) {
_cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL;
- EFI_DEVICE_PATH *path;
paths = UnpackDevicePath(device_path);
- for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
+ for (EFI_DEVICE_PATH *path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
HARDDRIVE_DEVICE_PATH *drive;
if (DevicePathType(path) != MEDIA_DEVICE_PATH)
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <efi.h>
+
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]);
#include "graphics.h"
#include "util.h"
+#define EFI_CONSOLE_CONTROL_GUID \
+ &(EFI_GUID) { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }
+
EFI_STATUS graphics_mode(BOOLEAN on) {
- #define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
- { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } };
struct _EFI_CONSOLE_CONTROL_PROTOCOL;
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
} EFI_CONSOLE_CONTROL_PROTOCOL;
- EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
EFI_CONSOLE_CONTROL_SCREEN_MODE new;
EFI_CONSOLE_CONTROL_SCREEN_MODE current;
BOOLEAN stdin_locked;
EFI_STATUS err;
- err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl);
+ err = LibLocateProtocol(EFI_CONSOLE_CONTROL_GUID, (VOID **)&ConsoleControl);
if (EFI_ERROR(err))
/* console control protocol is nonstandard and might not exist. */
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
*/
#pragma once
+#include <efi.h>
+
EFI_STATUS graphics_mode(BOOLEAN on);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <efi.h>
+
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
struct setup_header {
#include <efi.h>
#include <efilib.h>
+
#include "measure.h"
-#define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
+#define EFI_TCG_GUID \
+ &(EFI_GUID) { 0xf541796d, 0xa62e, 0x4954, { 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } }
typedef struct _TCG_VERSION {
UINT8 Major;
EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
} EFI_TCG;
-#define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
+#define EFI_TCG2_GUID \
+ &(EFI_GUID) { 0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f } }
typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
}
static EFI_TCG * tcg1_interface_check(void) {
- EFI_GUID tpm_guid = EFI_TCG_PROTOCOL_GUID;
EFI_STATUS status;
EFI_TCG *tcg;
TCG_BOOT_SERVICE_CAPABILITY capability;
EFI_PHYSICAL_ADDRESS event_log_location;
EFI_PHYSICAL_ADDRESS event_log_last_entry;
- status = LibLocateProtocol(&tpm_guid, (void **) &tcg);
+ status = LibLocateProtocol(EFI_TCG_GUID, (void **) &tcg);
if (EFI_ERROR(status))
return NULL;
}
static EFI_TCG2 * tcg2_interface_check(void) {
- EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
EFI_STATUS status;
EFI_TCG2 *tcg;
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability;
- status = LibLocateProtocol(&tpm2_guid, (void **) &tcg);
+ status = LibLocateProtocol(EFI_TCG2_GUID, (void **) &tcg);
if (EFI_ERROR(status))
return NULL;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <efi.h>
+
EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
graphics.c
measure.c
pe.c
+ secure-boot.c
util.c
'''.split()
if have_gnu_efi
compile_args = ['-Wall',
'-Wextra',
- '-std=gnu90',
- '-nostdinc',
+ '-std=gnu99',
+ '-nostdlib',
'-fpic',
'-fshort-wchar',
'-ffreestanding',
'-Wno-missing-field-initializers',
'-isystem', efi_incdir,
'-isystem', join_paths(efi_incdir, gnu_efi_path_arch),
+ '-I', fundamental_path,
+ '-DSD_BOOT',
'-include', efi_config_h,
'-include', version_h]
if efi_arch == 'x86_64'
systemd_boot_objects = []
stub_objects = []
- foreach file : common_sources + systemd_boot_sources + stub_sources
- o_file = custom_target(file + '.o',
+ foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources
+ o_file = custom_target(file.split('/')[-1] + '.o',
input : file,
- output : file + '.o',
+ output : file.split('/')[-1] + '.o',
command : efi_cc + ['-c', '@INPUT@', '-o', '@OUTPUT@']
+ compile_args,
- depend_files : efi_headers)
- if (common_sources + systemd_boot_sources).contains(file)
+ depend_files : efi_headers + fundamental_headers)
+ if (fundamental_source_paths + common_sources + systemd_boot_sources).contains(file)
systemd_boot_objects += o_file
endif
- if (common_sources + stub_sources).contains(file)
+ if (fundamental_source_paths + common_sources + stub_sources).contains(file)
stub_objects += o_file
endif
endforeach
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
if nm -D -u "$1" | grep ' U '; then
EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
struct DosFileHeader *dos;
struct PeHeader *pe;
- UINTN i;
UINTN offset;
dos = (struct DosFileHeader *)base;
offset = dos->ExeHeader + sizeof(*pe) + pe->FileHeader.SizeOfOptionalHeader;
- for (i = 0; i < pe->FileHeader.NumberOfSections; i++) {
+ for (UINTN i = 0; i < pe->FileHeader.NumberOfSections; i++) {
struct PeSectionHeader *sect;
- UINTN j;
sect = (struct PeSectionHeader *)&base[offset];
- for (j = 0; sections[j]; j++) {
+ for (UINTN j = 0; sections[j]; j++) {
if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0)
continue;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <efi.h>
+
EFI_STATUS pe_memory_locate_sections(CHAR8 *base,
CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path,
#include "missing_efi.h"
#include "random-seed.h"
+#include "secure-boot.h"
#include "sha256.h"
#include "util.h"
-#include "shim.h"
#define RANDOM_MAX_SIZE_MIN (32U)
#define RANDOM_MAX_SIZE_MAX (32U*1024U)
-static const EFI_GUID rng_protocol_guid = EFI_RNG_PROTOCOL_GUID;
+#define EFI_RNG_GUID &(EFI_GUID) EFI_RNG_PROTOCOL_GUID
/* SHA256 gives us 256/8=32 bytes */
#define HASH_VALUE_SIZE 32
/* Try to acquire the specified number of bytes from the UEFI RNG */
- err = LibLocateProtocol((EFI_GUID*) &rng_protocol_guid, (VOID**) &rng);
+ err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng);
if (EFI_ERROR(err))
return err;
if (!rng)
VOID **ret) {
_cleanup_freepool_ VOID *output = NULL;
- UINTN i;
/* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
* range counter_start…counter_start+n-1. */
if (!output)
return log_oom();
- for (i = 0; i < n; i++)
+ for (UINTN i = 0; i < n; i++)
hash_once(old_seed, rng, size,
system_token, system_token_size,
counter_start + i,
return EFI_SUCCESS;
}
-EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
+static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
_cleanup_freepool_ CHAR8 *data = NULL;
EFI_STATUS err;
UINTN size;
- err = efivar_get_raw(&loader_guid, L"LoaderSystemToken", &data, &size);
+ err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND)
Print(L"Failed to read LoaderSystemToken EFI variable: %r", err);
0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }},
};
- UINTN i;
-
- for (i = 0; i < ELEMENTSOF(array); i++) {
+ for (UINTN i = 0; i < ELEMENTSOF(array); i++) {
struct sha256_ctx hash;
uint8_t result[HASH_VALUE_SIZE];
}
/* We are good to go */
- err = efivar_set_raw(&loader_guid, L"LoaderRandomSeed", for_kernel, size, FALSE);
+ err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
if (EFI_ERROR(err)) {
Print(L"Failed to write random seed to EFI variable: %r\n", err);
return err;
#pragma once
#include <efi.h>
+#include <errno.h>
typedef enum RandomSeedMode {
RANDOM_SEED_OFF,
RANDOM_SEED_WITH_SYSTEM_TOKEN,
RANDOM_SEED_ALWAYS,
_RANDOM_SEED_MODE_MAX,
- _RANDOM_SEED_MODE_INVALID = -1,
+ _RANDOM_SEED_MODE_INVALID = -EINVAL,
} RandomSeedMode;
EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "secure-boot.h"
+#include "util.h"
+
+BOOLEAN secure_boot_enabled(void) {
+ BOOLEAN secure;
+ EFI_STATUS err;
+
+ err = efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SecureBoot", &secure);
+
+ return !EFI_ERROR(err) && secure;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <efi.h>
+
+BOOLEAN secure_boot_enabled(void);
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */
UINT32 bytes = ctx->buflen;
- UINTN pad, i;
+ UINTN pad;
/* Now count remaining bytes. */
ctx->total64 += bytes;
sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
/* Put result from CTX in first 32 bytes following RESBUF. */
- for (i = 0; i < 8; ++i)
+ for (UINTN i = 0; i < 8; ++i)
((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]);
return resbuf;
UINT32 f_save = f;
UINT32 g_save = g;
UINT32 h_save = h;
- UINTN t;
/* Operators defined in FIPS 180-2:4.1.2. */
#define Ch(x, y, z) ((x & y) ^ (~x & z))
#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
- for (t = 0; t < 16; ++t) {
+ for (UINTN t = 0; t < 16; ++t) {
W[t] = SWAP (*words);
++words;
}
- for (t = 16; t < 64; ++t)
+ for (UINTN t = 16; t < 64; ++t)
W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
/* The actual computation according to FIPS 180-2:6.2.2 step 3. */
- for (t = 0; t < 64; ++t) {
+ for (UINTN t = 0; t < 64; ++t) {
UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
UINT32 T2 = S0 (a) + Maj (a, b, c);
h = g;
EFI_STATUS __sysv_abi__ (*read_header) (VOID *data, UINT32 datasize, VOID *context);
};
-static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
-static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
-
-static const EFI_GUID security_protocol_guid = { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } };
-static const EFI_GUID security2_protocol_guid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
-static const EFI_GUID shim_lock_guid = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
+#define SIMPLE_FS_GUID &(EFI_GUID) SIMPLE_FILE_SYSTEM_PROTOCOL
+#define SECURITY_PROTOCOL_GUID \
+ &(EFI_GUID) { 0xa46423e3, 0x4617, 0x49f1, { 0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }
+#define SECURITY_PROTOCOL2_GUID \
+ &(EFI_GUID) { 0x94ab2f58, 0x1438, 0x4ef1, { 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }
+#define SHIM_LOCK_GUID \
+ &(EFI_GUID) { 0x605dab50, 0xe046, 0x4300, { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }
BOOLEAN shim_loaded(void) {
struct ShimLock *shim_lock;
- return uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS;
+ return uefi_call_wrapper(BS->LocateProtocol, 3, SHIM_LOCK_GUID, NULL, (VOID**) &shim_lock) == EFI_SUCCESS;
}
static BOOLEAN shim_validate(VOID *data, UINT32 size) {
if (!data)
return FALSE;
- if (uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) != EFI_SUCCESS)
+ if (uefi_call_wrapper(BS->LocateProtocol, 3, SHIM_LOCK_GUID, NULL, (VOID**) &shim_lock) != EFI_SUCCESS)
return FALSE;
if (!shim_lock)
return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
}
-BOOLEAN secure_boot_enabled(void) {
- _cleanup_freepool_ CHAR8 *b = NULL;
- UINTN size;
-
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
- return *b > 0;
-
- return FALSE;
-}
-
/*
* See the UEFI Platform Initialization manual (Vol2: DXE) for this
*/
dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const);
- status = uefi_call_wrapper(BS->LocateDevicePath, 3, (EFI_GUID*) &simple_fs_guid, &dev_path, &h);
+ status = uefi_call_wrapper(BS->LocateDevicePath, 3, SIMPLE_FS_GUID, &dev_path, &h);
if (status != EFI_SUCCESS)
return status;
* to fail, since SECURITY2 was introduced in PI 1.2.1.
* Use security2_protocol == NULL as indicator.
*/
- uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol);
+ uefi_call_wrapper(BS->LocateProtocol, 3, SECURITY_PROTOCOL2_GUID, NULL, (VOID**) &security2_protocol);
- status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol);
+ status = uefi_call_wrapper(BS->LocateProtocol, 3, SECURITY_PROTOCOL_GUID, NULL, (VOID**) &security_protocol);
/* This one is mandatory, so there's a serious problem */
if (status != EFI_SUCCESS)
return status;
*/
#pragma once
-BOOLEAN shim_loaded(void);
+#include <efi.h>
-BOOLEAN secure_boot_enabled(void);
+BOOLEAN shim_loaded(void);
EFI_STATUS security_policy_install(void);
UINT8 reserved;
} __attribute__((packed));
-EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib,
+static EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib,
struct bmp_map **ret_map, UINT8 **pixmap) {
struct bmp_file *file;
struct bmp_dib *dib;
*dst = (rb | g);
}
-EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
+static EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
struct bmp_dib *dib, struct bmp_map *map,
UINT8 *pixmap) {
UINT8 *in;
- UINTN y;
/* transform and copy pixels */
in = pixmap;
- for (y = 0; y < dib->y; y++) {
+ for (UINTN y = 0; y < dib->y; y++) {
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out;
UINTN row_size;
- UINTN x;
out = &buf[(dib->y - y - 1) * dib->x];
- for (x = 0; x < dib->x; x++, in++, out++) {
+ for (UINTN x = 0; x < dib->x; x++, in++, out++) {
switch (dib->depth) {
case 1: {
- UINTN i;
-
- for (i = 0; i < 8 && x < dib->x; i++) {
+ for (UINTN i = 0; i < 8 && x < dib->x; i++) {
out->Red = map[((*in) >> (7 - i)) & 1].red;
out->Green = map[((*in) >> (7 - i)) & 1].green;
out->Blue = map[((*in) >> (7 - i)) & 1].blue;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <efi.h>
+
EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background);
#include "linux.h"
#include "measure.h"
#include "pe.h"
+#include "secure-boot.h"
#include "splash.h"
#include "util.h"
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
-static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
-
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE *loaded_image;
- _cleanup_freepool_ CHAR8 *b = NULL;
- UINTN size;
- BOOLEAN secure = FALSE;
CHAR8 *sections[] = {
(CHAR8 *)".cmdline",
(CHAR8 *)".linux",
return err;
}
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
- if (*b > 0)
- secure = TRUE;
-
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
if (EFI_ERROR(err)) {
Print(L"Unable to locate embedded .linux section: %r ", err);
}
if (szs[0] > 0)
- cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]);
+ cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0];
cmdline_len = szs[0];
/* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */
- if ((!secure || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) {
+ if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 &&
+ *(CHAR16 *) loaded_image->LoadOptions > 0x1F) {
CHAR16 *options;
CHAR8 *line;
- UINTN i;
options = (CHAR16 *)loaded_image->LoadOptions;
cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
line = AllocatePool(cmdline_len);
- for (i = 0; i < cmdline_len; i++)
+ for (UINTN i = 0; i < cmdline_len; i++)
line[i] = options[i];
cmdline = line;
}
/* Export the device path this image is started from, if it's not set yet */
- if (efivar_get_raw(&loader_guid, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS)
+ if (efivar_get_raw(LOADER_GUID, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS)
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
- efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
/* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */
- if (efivar_get_raw(&loader_guid, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) {
+ if (efivar_get_raw(LOADER_GUID, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s;
s = DevicePathToStr(loaded_image->FilePath);
- efivar_set(L"LoaderImageIdentifier", s, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderImageIdentifier", s, 0);
}
/* if LoaderFirmwareInfo is not set, let's set it */
- if (efivar_get_raw(&loader_guid, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
+ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- efivar_set(L"LoaderFirmwareInfo", s, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0);
}
/* ditto for LoaderFirmwareType */
- if (efivar_get_raw(&loader_guid, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
+ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- efivar_set(L"LoaderFirmwareType", s, FALSE);
+ efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0);
}
/* add StubInfo */
- if (efivar_get_raw(&loader_guid, L"StubInfo", NULL, NULL) != EFI_SUCCESS)
- efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE);
+ if (efivar_get_raw(LOADER_GUID, L"StubInfo", NULL, NULL) != EFI_SUCCESS)
+ efivar_set(LOADER_GUID, L"StubInfo", L"systemd-stub " GIT_VERSION, 0);
if (szs[3] > 0)
graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);
#include "util.h"
-/*
- * Allocated random UUID, intended to be shared across tools that implement
- * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
- * associated EFI variables.
- */
-const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
-
#ifdef __x86_64__
UINT64 ticks_read(VOID) {
UINT64 a, d;
return EFI_INVALID_PARAMETER;
}
-EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent) {
- UINT32 flags;
-
- flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
- if (persistent)
- flags |= EFI_VARIABLE_NON_VOLATILE;
-
+EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags) {
+ flags |= EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf);
}
-EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) {
- return efivar_set_raw(&loader_guid, name, value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
+EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags) {
+ return efivar_set_raw(vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, flags);
}
-EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
+EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, UINT32 flags) {
CHAR16 str[32];
SPrint(str, 32, L"%u", i);
- return efivar_set(name, str, persistent);
+ return efivar_set(vendor, name, str, flags);
+}
+
+EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 value, UINT32 flags) {
+ UINT8 buf[4];
+
+ buf[0] = (UINT8)(value >> 0U & 0xFF);
+ buf[1] = (UINT8)(value >> 8U & 0xFF);
+ buf[2] = (UINT8)(value >> 16U & 0xFF);
+ buf[3] = (UINT8)(value >> 24U & 0xFF);
+
+ return efivar_set_raw(vendor, name, buf, sizeof(buf), flags);
+}
+
+EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, UINT32 flags) {
+ UINT8 buf[8];
+
+ buf[0] = (UINT8)(value >> 0U & 0xFF);
+ buf[1] = (UINT8)(value >> 8U & 0xFF);
+ buf[2] = (UINT8)(value >> 16U & 0xFF);
+ buf[3] = (UINT8)(value >> 24U & 0xFF);
+ buf[4] = (UINT8)(value >> 32U & 0xFF);
+ buf[5] = (UINT8)(value >> 40U & 0xFF);
+ buf[6] = (UINT8)(value >> 48U & 0xFF);
+ buf[7] = (UINT8)(value >> 56U & 0xFF);
+
+ return efivar_set_raw(vendor, name, buf, sizeof(buf), flags);
}
-EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value) {
+EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) {
_cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err;
CHAR16 *val;
UINTN size;
- err = efivar_get_raw(&loader_guid, name, &buf, &size);
+ err = efivar_get_raw(vendor, name, &buf, &size);
if (EFI_ERROR(err))
return err;
return EFI_SUCCESS;
}
-EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i) {
+EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i) {
_cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err;
- err = efivar_get(name, &val);
+ err = efivar_get(vendor, name, &val);
if (!EFI_ERROR(err) && i)
*i = Atoi(val);
return err;
}
+EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret) {
+ _cleanup_freepool_ CHAR8 *buf = NULL;
+ UINTN size;
+ EFI_STATUS err;
+
+ err = efivar_get_raw(vendor, name, &buf, &size);
+ if (!EFI_ERROR(err) && ret) {
+ if (size != sizeof(UINT32))
+ return EFI_BUFFER_TOO_SMALL;
+
+ *ret = (UINT32) buf[0] << 0U | (UINT32) buf[1] << 8U | (UINT32) buf[2] << 16U |
+ (UINT32) buf[3] << 24U;
+ }
+
+ return err;
+}
+
+EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret) {
+ _cleanup_freepool_ CHAR8 *buf = NULL;
+ UINTN size;
+ EFI_STATUS err;
+
+ err = efivar_get_raw(vendor, name, &buf, &size);
+ if (!EFI_ERROR(err) && ret) {
+ if (size != sizeof(UINT64))
+ return EFI_BUFFER_TOO_SMALL;
+
+ *ret = (UINT64) buf[0] << 0U | (UINT64) buf[1] << 8U | (UINT64) buf[2] << 16U |
+ (UINT64) buf[3] << 24U | (UINT64) buf[4] << 32U | (UINT64) buf[5] << 40U |
+ (UINT64) buf[6] << 48U | (UINT64) buf[7] << 56U;
+ }
+
+ return err;
+}
+
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size) {
_cleanup_freepool_ CHAR8 *buf = NULL;
UINTN l;
return err;
}
-VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
+EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret) {
+ _cleanup_freepool_ CHAR8 *b = NULL;
+ UINTN size;
+ EFI_STATUS err;
+
+ err = efivar_get_raw(vendor, name, &b, &size);
+ if (!EFI_ERROR(err))
+ *ret = *b > 0;
+
+ return err;
+}
+
+VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec) {
CHAR16 str[32];
if (usec == 0)
return;
SPrint(str, 32, L"%ld", usec);
- efivar_set(name, str, FALSE);
+ efivar_set(vendor, name, str, 0);
}
static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
CHAR16 unichar;
UINTN len;
- UINTN i;
if (!(stra[0] & 0x80))
len = 1;
break;
}
- for (i = 1; i < len; i++) {
+ for (UINTN i = 1; i < len; i++) {
if ((stra[i] & 0xc0) != 0x80)
return -1;
unichar <<= 6;
#include <efi.h>
#include <efilib.h>
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
+#include "string-util-fundamental.h"
+
#define OFFSETOF(x,y) __builtin_offsetof(x,y)
static inline UINTN ALIGN_TO(UINTN l, UINTN ali) {
return ((l + ali - 1) & ~(ali - 1));
}
-static inline const CHAR16 *yes_no(BOOLEAN b) {
- return b ? L"yes" : L"no";
-}
-
EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
UINT64 ticks_read(void);
UINT64 ticks_freq(void);
UINT64 time_usec(void);
-EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent);
-EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent);
-EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent);
-VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec);
+EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags);
+EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags);
+EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, UINT32 flags);
+EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *NAME, UINT32 value, UINT32 flags);
+EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, UINT32 flags);
+VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec);
-EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value);
+EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value);
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size);
-EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i);
+EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i);
+EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret);
+EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret);
+EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret);
CHAR8 *strchra(CHAR8 *s, CHAR8 c);
CHAR16 *stra_to_path(CHAR8 *stra);
FreePool(q);
}
-#define _cleanup_(x) __attribute__((__cleanup__(x)))
#define _cleanup_freepool_ _cleanup_(FreePoolp)
static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
uefi_call_wrapper((*handle)->Close, 1, *handle);
}
-extern const EFI_GUID loader_guid;
+/*
+ * Allocated random UUID, intended to be shared across tools that implement
+ * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
+ * associated EFI variables.
+ */
+#define LOADER_GUID \
+ &(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
+#define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
#define UINTN_MAX (~(UINTN)0)
#define INTN_MAX ((INTN)(UINTN_MAX>>1))
-#define TAKE_PTR(ptr) \
- ({ \
- typeof(ptr) _ptr_ = (ptr); \
- (ptr) = NULL; \
- _ptr_; \
- })
-
EFI_STATUS log_oom(void);
#include "log.h"
#include "main-func.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
if (r < 0)
return log_error_errno(r, "Failed to set columns to display: %m");
- table_set_header(table, arg_legend);
-
HASHMAP_FOREACH_KEY(v, k, names) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
return log_error_errno(r, "Failed to fill line: %m");
}
- if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
- (void) pager_open(arg_pager_flags);
-
- r = table_print_json(table, NULL, arg_json_format_flags);
- if (r < 0)
- return table_log_print_error(r);
-
- return 0;
+ return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
}
static void print_subtree(const char *prefix, const char *path, char **l) {
r = sd_bus_call_method(bus, service, path,
"org.freedesktop.DBus.Introspectable", "Introspect",
- &error, &reply, "");
+ &error, &reply, NULL);
if (r < 0) {
printf("%sFailed to introspect object %s of service %s: %s%s\n",
ansi_highlight_red(),
return member_compare_func(*a, *b);
}
-static void member_free(Member *m) {
+static Member* member_free(Member *m) {
if (!m)
- return;
+ return NULL;
free(m->interface);
free(m->name);
free(m->signature);
free(m->result);
free(m->value);
- free(m);
+ return mfree(m);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
-static void member_set_free(Set *s) {
- set_free_with_destructor(s, member_free);
+static Set* member_set_free(Set *s) {
+ return set_free_with_destructor(s, member_free);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
static int on_interface(const char *interface, uint64_t flags, void *userdata) {
r = sd_bus_call_method(bus, argv[1], argv[2],
"org.freedesktop.DBus.Introspectable", "Introspect",
- &error, &reply_xml, "");
+ &error, &reply_xml, NULL);
if (r < 0)
return log_error_errno(r, "Failed to introspect object %s of service %s: %s",
argv[2], argv[1], bus_error_message(&error, r));
if (r < 0)
return log_oom();
+ (void) pager_open(arg_pager_flags);
+
printf("%s [OPTIONS...] COMMAND ...\n\n"
"%sIntrospect the D-Bus IPC bus.%s\n"
"\nCommands:\n"
" --watch-bind=BOOL Wait for bus AF_UNIX socket to be bound in the file\n"
" system\n"
" --destination=SERVICE Destination service of a signal\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
break;
case ARG_JSON:
- r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags);
+ r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
static int run(int argc, char *argv[]) {
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
" -l --full Do not ellipsize output\n"
" -k Include kernel threads in output\n"
" -M --machine= Show container\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
static int run(int argc, char *argv[]) {
int r, output_flags;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
return EXIT_FAILURE;
}
- log_setup_service();
+ log_setup();
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0) {
" -b --batch Run in batch mode, accepting no input\n"
" --depth=DEPTH Maximum traversal depth (default: %u)\n"
" -M --machine= Show container\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , arg_depth
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ arg_depth,
+ link);
return 0;
}
CGroupMask mask;
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
case '?':
case 'h':
-#define ON ANSI_HIGHLIGHT
-#define OFF ANSI_NORMAL
-
fprintf(stdout,
- "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks/procs; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n"
- "\t<" ON "+" OFF "> Inc. delay; <" ON "-" OFF "> Dec. delay; <" ON "%%" OFF "> Toggle time; <" ON "SPACE" OFF "> Refresh\n"
- "\t<" ON "P" OFF "> Toggle count userspace processes; <" ON "k" OFF "> Toggle count all processes\n"
- "\t<" ON "r" OFF "> Count processes recursively; <" ON "q" OFF "> Quit");
+ "\t<%1$sp%2$s> By path; <%1$st%2$s> By tasks/procs; <%1$sc%2$s> By CPU; <%1$sm%2$s> By memory; <%1$si%2$s> By I/O\n"
+ "\t<%1$s+%2$s> Inc. delay; <%1$s-%2$s> Dec. delay; <%1$s%%%2$s> Toggle time; <%1$sSPACE%2$s> Refresh\n"
+ "\t<%1$sP%2$s> Toggle count userspace processes; <%1$sk%2$s> Toggle count all processes\n"
+ "\t<%1$sr%2$s> Count processes recursively; <%1$sq%2$s> Quit",
+ ansi_highlight(), ansi_normal());
fflush(stdout);
sleep(3);
break;
#include "strv.h"
#if HAVE_APPARMOR
-DEFINE_TRIVIAL_CLEANUP_FUNC(aa_policy_cache *, aa_policy_cache_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(aa_features *, aa_features_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_policy_cache *, aa_policy_cache_unref, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_features *, aa_features_unref, NULL);
#endif
int mac_apparmor_setup(void) {
#if HAVE_APPARMOR
- int r;
_cleanup_(aa_policy_cache_unrefp) aa_policy_cache *policy_cache = NULL;
_cleanup_(aa_features_unrefp) aa_features *features = NULL;
const char *current_file;
_cleanup_free_ char *current_profile = NULL, *cache_dir_path = NULL;
+ int r;
if (!mac_apparmor_use()) {
log_debug("AppArmor either not supported by the kernel or disabled.");
int ioctl_fd;
};
-static void expire_data_free(struct expire_data *data) {
+static struct expire_data* expire_data_free(struct expire_data *data) {
if (!data)
- return;
+ return NULL;
safe_close(data->dev_autofs_fd);
safe_close(data->ioctl_fd);
- free(data);
+ return mfree(data);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
_AUTOMOUNT_RESULT_MAX,
- _AUTOMOUNT_RESULT_INVALID = -1
+ _AUTOMOUNT_RESULT_INVALID = -EINVAL,
} AutomountResult;
struct Automount {
.moom_swap = MANAGED_OOM_AUTO,
.moom_mem_pressure = MANAGED_OOM_AUTO,
+ .moom_preference = MANAGED_OOM_PREFERENCE_NONE,
};
}
"%sDelegate: %s\n"
"%sManagedOOMSwap: %s\n"
"%sManagedOOMMemoryPressure: %s\n"
- "%sManagedOOMMemoryPressureLimitPercent: %d%%\n",
+ "%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n"
+ "%sManagedOOMPreference: %s%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
prefix, yes_no(c->delegate),
prefix, managed_oom_mode_to_string(c->moom_swap),
prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
- prefix, c->moom_mem_pressure_limit);
+ prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100,
+ prefix, managed_oom_preference_to_string(c->moom_preference));
if (c->delegate) {
_cleanup_free_ char *t = NULL;
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low);
UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min);
+void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path) {
+ CGroupContext *c;
+ int r;
+
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return;
+
+ if (c->moom_preference == MANAGED_OOM_PREFERENCE_OMIT) {
+ r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit", "1", 1, 0);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to set oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
+ }
+
+ if (c->moom_preference == MANAGED_OOM_PREFERENCE_AVOID) {
+ r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid", "1", 1, 0);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to set oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
+ }
+
+ if (c->moom_preference != MANAGED_OOM_PREFERENCE_AVOID) {
+ r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid");
+ if (r != -ENODATA)
+ log_unit_debug_errno(u, r, "Failed to remove oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
+ }
+
+ if (c->moom_preference != MANAGED_OOM_PREFERENCE_OMIT) {
+ r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit");
+ if (r != -ENODATA)
+ log_unit_debug_errno(u, r, "Failed to remove oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
+ }
+}
+
static void cgroup_xattr_apply(Unit *u) {
char ids[SD_ID128_STRING_MAX];
int r;
if (r != -ENODATA)
log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", u->cgroup_path);
}
+
+ cgroup_oomd_xattr_apply(u, u->cgroup_path);
}
static int lookup_block_device(const char *p, dev_t *ret) {
return r;
}
+static void set_io_weight(Unit *u, const char *controller, uint64_t weight) {
+ char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
+ const char *p;
+
+ p = strjoina(controller, ".weight");
+ xsprintf(buf, "default %" PRIu64 "\n", weight);
+ (void) set_attribute_and_warn(u, controller, p, buf);
+
+ /* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
+ * See also: https://github.com/systemd/systemd/pull/13335 and
+ * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9.
+ * The range is 1..1000 apparently. */
+ p = strjoina(controller, ".bfq.weight");
+ xsprintf(buf, "%" PRIu64 "\n", (weight + 9) / 10);
+ (void) set_attribute_and_warn(u, controller, p, buf);
+}
+
static void cgroup_context_apply(
Unit *u,
CGroupMask apply_mask,
* controller), and in case of containers we want to leave control of these attributes to the container manager
* (and we couldn't access that stuff anyway, even if we tried if proper delegation is used). */
if ((apply_mask & CGROUP_MASK_IO) && !is_local_root) {
- char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
bool has_io, has_blockio;
uint64_t weight;
} else
weight = CGROUP_WEIGHT_DEFAULT;
- xsprintf(buf, "default %" PRIu64 "\n", weight);
- (void) set_attribute_and_warn(u, "io", "io.weight", buf);
-
- /* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
- * See also: https://github.com/systemd/systemd/pull/13335 */
- xsprintf(buf, "%" PRIu64 "\n", weight);
- (void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf);
+ set_io_weight(u, "io", weight);
if (has_io) {
CGroupIODeviceLatency *latency;
/* Applying a 'weight' never makes sense for the host root cgroup, and for containers this should be
* left to our container manager, too. */
if (!is_local_root) {
- char buf[DECIMAL_STR_MAX(uint64_t)+1];
uint64_t weight;
if (has_io) {
else
weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
- xsprintf(buf, "%" PRIu64 "\n", weight);
- (void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf);
-
- /* FIXME: drop this when distro kernels properly support BFQ through "blkio.weight"
- * See also: https://github.com/systemd/systemd/pull/13335 */
- xsprintf(buf, "%" PRIu64 "\n", weight);
- (void) set_attribute_and_warn(u, "blkio", "blkio.bfq.weight", buf);
+ set_io_weight(u, "blkio", weight);
if (has_io) {
CGroupIODeviceWeight *w;
else if (r == 0)
return 0;
- r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.systemd_oomd_kill", &value);
+ r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.oomd_kill", &value);
if (r < 0 && r != -ENODATA)
return r;
return 1;
}
-static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
- [CGROUP_DEVICE_POLICY_AUTO] = "auto",
- [CGROUP_DEVICE_POLICY_CLOSED] = "closed",
- [CGROUP_DEVICE_POLICY_STRICT] = "strict",
-};
-
int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
_cleanup_free_ char *v = NULL;
int r;
return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
}
+static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
+ [CGROUP_DEVICE_POLICY_AUTO] = "auto",
+ [CGROUP_DEVICE_POLICY_CLOSED] = "closed",
+ [CGROUP_DEVICE_POLICY_STRICT] = "strict",
+};
+
DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
static const char* const freezer_action_table[_FREEZER_ACTION_MAX] = {
CGROUP_DEVICE_POLICY_STRICT,
_CGROUP_DEVICE_POLICY_MAX,
- _CGROUP_DEVICE_POLICY_INVALID = -1
+ _CGROUP_DEVICE_POLICY_INVALID = -EINVAL,
} CGroupDevicePolicy;
typedef enum FreezerAction {
FREEZER_THAW,
_FREEZER_ACTION_MAX,
- _FREEZER_ACTION_INVALID = -1,
+ _FREEZER_ACTION_INVALID = -EINVAL,
} FreezerAction;
struct CGroupDeviceAllow {
/* Settings for systemd-oomd */
ManagedOOMMode moom_swap;
ManagedOOMMode moom_mem_pressure;
- int moom_mem_pressure_limit;
+ uint32_t moom_mem_pressure_limit_permyriad;
+ ManagedOOMPreference moom_preference;
};
/* Used when querying IP accounting data */
CGROUP_IP_EGRESS_BYTES,
CGROUP_IP_EGRESS_PACKETS,
_CGROUP_IP_ACCOUNTING_METRIC_MAX,
- _CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1,
+ _CGROUP_IP_ACCOUNTING_METRIC_INVALID = -EINVAL,
} CGroupIPAccountingMetric;
/* Used when querying IO accounting data */
CGROUP_IO_READ_OPERATIONS,
CGROUP_IO_WRITE_OPERATIONS,
_CGROUP_IO_ACCOUNTING_METRIC_MAX,
- _CGROUP_IO_ACCOUNTING_METRIC_INVALID = -1,
+ _CGROUP_IO_ACCOUNTING_METRIC_INVALID = -EINVAL,
} CGroupIOAccountingMetric;
typedef struct Unit Unit;
int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode);
+void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path);
+
CGroupMask unit_get_own_mask(Unit *u);
CGroupMask unit_get_delegate_mask(Unit *u);
CGroupMask unit_get_members_mask(Unit *u);
JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)),
JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)),
JSON_BUILD_PAIR("property", JSON_BUILD_STRING(property)),
- JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit))));
+ JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit_permyriad))));
}
int manager_varlink_send_managed_oom_update(Unit *u) {
if (!MANAGER_IS_SYSTEM(m))
return 0;
- r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID);
+ r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
static int property_get_cgroup_mask(
sd_bus *bus,
sd_bus_error *error) {
CGroupMask *mask = userdata;
- CGroupController ctrl;
int r;
assert(bus);
if (r < 0)
return r;
- for (ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
+ for (CGroupController ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) {
if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0)
continue;
SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
- SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPercent", "s", bus_property_get_percent, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
+ SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPermyriad", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit_permyriad), 0),
+ SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
SD_BUS_VTABLE_END
};
p = cgroup_device_policy_from_string(policy);
if (p < 0)
- return -EINVAL;
+ return p;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->device_policy = p;
return 1;
}
- if (streq(name, "ManagedOOMMemoryPressureLimitPercent")) {
+ if (streq(name, "ManagedOOMMemoryPressureLimitPermyriad")) {
+ uint32_t v;
+
if (!UNIT_VTABLE(u)->can_set_managed_oom)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
- r = bus_set_transient_percent(u, name, &c->moom_mem_pressure_limit, message, flags, error);
+ r = sd_bus_message_read(message, "u", &v);
if (r < 0)
return r;
+ if (v > 10000)
+ return -ERANGE;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ c->moom_mem_pressure_limit_permyriad = v;
+ unit_write_settingf(u, flags, name, "ManagedOOMMemoryPressureLimit=%" PRIu32 ".%02" PRIu32 "%%", v / 100, v % 100);
+ }
+
if (c->moom_mem_pressure == MANAGED_OOM_KILL)
(void) manager_varlink_send_managed_oom_update(u);
return 1;
}
+ if (streq(name, "ManagedOOMPreference")) {
+ ManagedOOMPreference p;
+ const char *pref;
+
+ r = sd_bus_message_read(message, "s", &pref);
+ if (r < 0)
+ return r;
+
+ p = managed_oom_preference_from_string(pref);
+ if (p < 0)
+ return -EINVAL;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ c->moom_preference = p;
+ unit_write_settingf(u, flags, name, "ManagedOOMPreference=%s", pref);
+ }
+
+ return 1;
+ }
+
if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
sd_bus_error *error) {
ExecContext *c = userdata;
- unsigned i;
bool ro;
int r;
if (r < 0)
return r;
- for (i = 0; i < c->n_bind_mounts; i++) {
+ for (size_t i = 0; i < c->n_bind_mounts; i++) {
if (ro != c->bind_mounts[i].read_only)
continue;
sd_bus_error *error) {
ExecContext *c = userdata;
- unsigned i;
int r;
assert(bus);
if (r < 0)
return r;
- for (i = 0; i < c->n_temporary_filesystems; i++) {
+ for (unsigned i = 0; i < c->n_temporary_filesystems; i++) {
TemporaryFileSystem *t = c->temporary_filesystems + i;
r = sd_bus_message_append(
sd_bus_error *error) {
ExecContext *c = userdata;
- size_t i;
int r;
assert(bus);
if (r < 0)
return r;
- for (i = 0; i < c->n_log_extra_fields; i++) {
+ for (size_t i = 0; i < c->n_log_extra_fields; i++) {
r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len);
if (r < 0)
return r;
SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
-/* ret_format_str is an accumulator, so if it has any pre-existing content, new options will be appended to it */
-static int read_mount_options(sd_bus_message *message, sd_bus_error *error, MountOptions **ret_options, char **ret_format_str, const char *separator) {
- _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
- _cleanup_free_ char *format_str = NULL;
- const char *mount_options, *partition;
- int r;
-
- assert(message);
- assert(ret_options);
- assert(ret_format_str);
- assert(separator);
-
- r = sd_bus_message_enter_container(message, 'a', "(ss)");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) {
- _cleanup_free_ char *previous = NULL, *escaped = NULL;
- _cleanup_free_ MountOptions *o = NULL;
- PartitionDesignator partition_designator;
-
- if (chars_intersect(mount_options, WHITESPACE))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- "Invalid mount options string, contains whitespace character(s): %s", mount_options);
-
- partition_designator = partition_designator_from_string(partition);
- if (partition_designator < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid partition name %s", partition);
-
- /* Need to store them in the unit with the escapes, so that they can be parsed again */
- escaped = shell_escape(mount_options, ":");
- if (!escaped)
- return -ENOMEM;
-
- previous = TAKE_PTR(format_str);
- format_str = strjoin(previous, previous ? separator : "", partition, ":", escaped);
- if (!format_str)
- return -ENOMEM;
-
- o = new(MountOptions, 1);
- if (!o)
- return -ENOMEM;
- *o = (MountOptions) {
- .partition_designator = partition_designator,
- .options = strdup(mount_options),
- };
- if (!o->options)
- return -ENOMEM;
- LIST_APPEND(mount_options, options, TAKE_PTR(o));
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(message);
- if (r < 0)
- return r;
-
- if (!LIST_IS_EMPTY(options)) {
- char *final = strjoin(*ret_format_str, !isempty(*ret_format_str) ? separator : "", format_str);
- if (!final)
- return -ENOMEM;
- free_and_replace(*ret_format_str, final);
- LIST_JOIN(mount_options, *ret_options, options);
- }
-
- return 0;
-}
-
int bus_exec_context_set_transient_property(
Unit *u,
ExecContext *c,
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
_cleanup_free_ char *format_str = NULL;
- r = read_mount_options(message, error, &options, &format_str, " ");
+ r = bus_read_mount_options(message, error, &options, &format_str, " ");
if (r < 0)
return r;
return 1;
} else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
- "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
+ "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths", "ExecPaths", "NoExecPaths")) {
_cleanup_strv_free_ char **l = NULL;
char ***dirs;
char **p;
dirs = &c->read_write_paths;
else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
dirs = &c->read_only_paths;
+ else if (streq(name, "ExecPaths"))
+ dirs = &c->exec_paths;
+ else if (streq(name, "NoExecPaths"))
+ dirs = &c->no_exec_paths;
else /* "InaccessiblePaths" */
dirs = &c->inaccessible_paths;
return -ENOMEM;
free_and_replace(format_str, tuple);
- r = read_mount_options(message, error, &options, &format_str, ":");
+ r = bus_read_mount_options(message, error, &options, &format_str, ":");
if (r < 0)
return r;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ Job **list = NULL;
Job *j = userdata;
- int r, i, n;
+ int r, n;
if (strstr(sd_bus_message_get_member(message), "After"))
n = job_get_after(j, &list);
if (r < 0)
return r;
- for (i = 0; i < n; i ++) {
+ for (int i = 0; i < n; i ++) {
_cleanup_free_ char *unit_path = NULL, *job_path = NULL;
job_path = job_dbus_path(list[i]);
#include "virt.h"
#include "watchdog.h"
-/* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state there, and if
- * we can't we'll fail badly. */
+/* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state
+ * there, and if we can't we'll fail badly. */
#define RELOAD_DISK_SPACE_MIN (UINT64_C(16) * UINT64_C(1024) * UINT64_C(1024))
static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
assert(message);
assert(ret_unit);
- /* More or less a wrapper around manager_get_unit() that generates nice errors and has one trick up its sleeve:
- * if the name is specified empty we use the client's unit. */
+ /* More or less a wrapper around manager_get_unit() that generates nice errors and has one trick up
+ * its sleeve: if the name is specified empty we use the client's unit. */
if (isempty(name)) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
u = manager_get_unit_by_pid(m, pid);
if (!u)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client " PID_FMT " not member of any unit.", pid);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT,
+ "Client " PID_FMT " not member of any unit.", pid);
} else {
u = hashmap_get(m->units_by_invocation_id, &id);
if (!u)
if (r < 0)
return r;
- /* So here's a special trick: the bus path we return actually references the unit by its invocation ID instead
- * of the unit name. This means it stays valid only as long as the invocation ID stays the same. */
+ /* So here's a special trick: the bus path we return actually references the unit by its invocation
+ * ID instead of the unit name. This means it stays valid only as long as the invocation ID stays the
+ * same. */
path = unit_dbus_path_invocation_id(u);
if (!path)
return -ENOMEM;
u = manager_get_unit_by_cgroup(m, cgroup);
if (!u)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT,
+ "Control group '%s' is not valid or not managed by this instance",
+ cgroup);
return reply_unit_path(u, message, error);
}
return method_generic_unit_operation(message, userdata, error, bus_service_method_bind_mount, GENERIC_UNIT_VALIDATE_LOADED);
}
+static int method_mount_image_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ /* Only add mounts on fully loaded units */
+ return method_generic_unit_operation(message, userdata, error, bus_service_method_mount_image, GENERIC_UNIT_VALIDATE_LOADED);
+}
+
static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
/* Only allow reffing of fully loaded units, and make sure reffing a unit loads it. */
return method_generic_unit_operation(message, userdata, error, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED);
t = unit_name_to_type(name);
if (t < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid unit name or type.");
if (!unit_vtable[t]->can_transient)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Unit type %s does not support transient units.",
+ unit_type_to_string(t));
r = manager_load_unit(m, name, NULL, error, &u);
if (r < 0)
return r;
if (!unit_is_pristine(u))
- return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS,
+ "Unit %s already exists.", name);
/* OK, the unit failed to load and is unreferenced, now let's
* fill in the transient data instead */
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Reboot is only supported for system managers.");
m->objective = MANAGER_REBOOT;
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Powering off is only supported for system managers.");
m->objective = MANAGER_POWEROFF;
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Halt is only supported for system managers.");
m->objective = MANAGER_HALT;
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "KExec is only supported for system managers.");
m->objective = MANAGER_KEXEC;
if (available < RELOAD_DISK_SPACE_MIN) {
char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
- log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfully. "
+ log_warning("Dangerously low amount of free space on /run/systemd, root switching might fail.\n"
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
format_bytes(fb_available, sizeof(fb_available), available),
format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Root switching is only supported by system manager.");
r = sd_bus_message_read(message, "ss", &root, &init);
if (r < 0)
return r;
if (isempty(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory may not be the empty string.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root directory may not be the empty string.");
if (!path_is_absolute(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root path '%s' is not absolute.", root);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root path '%s' is not absolute.", root);
if (path_equal(root, "/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory cannot be the old root directory.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root directory cannot be the old root directory.");
/* Safety check */
if (isempty(init)) {
r = path_is_os_tree(root);
if (r < 0)
- return sd_bus_error_set_errnof(error, r, "Failed to determine whether root path '%s' contains an OS tree: %m", root);
+ return sd_bus_error_set_errnof(error, r,
+ "Failed to determine whether root path '%s' contains an OS tree: %m",
+ root);
if (r == 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path '%s' does not seem to be an OS tree. os-release file is missing.", root);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Specified switch root path '%s' does not seem to be an OS tree. os-release file is missing.",
+ root);
} else {
_cleanup_free_ char *chased = NULL;
if (!path_is_absolute(init))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Path to init binary '%s' not absolute.", init);
r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased, NULL);
if (r < 0)
- return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);
+ return sd_bus_error_set_errnof(error, r,
+ "Could not resolve init executable %s: %m", init);
if (laccess(chased, X_OK) < 0) {
if (errno == EACCES)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Init binary %s is not executable.", init);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Init binary %s is not executable.", init);
- return sd_bus_error_set_errnof(error, r, "Could not check whether init binary %s is executable: %m", init);
+ return sd_bus_error_set_errnof(error, r,
+ "Could not check whether init binary %s is executable: %m", init);
}
}
return r;
if (!strv_env_name_or_assignment_is_valid(minus))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid environment variable names or assignments");
r = bus_verify_set_environment_async(m, message, error);
if (r < 0)
return r;
if (!strv_env_name_or_assignment_is_valid(minus))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid environment variable names or assignments");
if (!strv_env_is_valid(plus))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid environment assignments");
r = bus_verify_set_environment_async(m, message, error);
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Dynamic users are only supported in the system instance.");
if (!valid_user_group_name(name, VALID_USER_RELAX))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "User name invalid: %s", name);
r = dynamic_user_lookup_name(m, name, &uid);
if (r == -ESRCH)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user %s does not exist.", name);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER,
+ "Dynamic user %s does not exist.", name);
if (r < 0)
return r;
return r;
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Dynamic users are only supported in the system instance.");
if (!uid_is_valid(uid))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User ID invalid: " UID_FMT, uid);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "User ID invalid: " UID_FMT, uid);
r = dynamic_user_lookup_uid(m, uid, &name);
if (r == -ESRCH)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user ID " UID_FMT " does not exist.", uid);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER,
+ "Dynamic user ID " UID_FMT " does not exist.", uid);
if (r < 0)
return r;
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
if (!MANAGER_IS_SYSTEM(m))
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Dynamic users are only supported in the system instance.");
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
if (r == -EAGAIN) /* not realized yet? */
continue;
if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to look up a dynamic user.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED,
+ "Failed to look up a dynamic user.");
r = sd_bus_message_append(reply, "(us)", uid, d->name);
if (r < 0)
return sd_bus_send(NULL, reply, NULL);
}
+static int method_enqueue_marked_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = mac_selinux_access_check(message, "start", error);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_manage_units_async(m, message, error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ log_info("Queuing reload/restart jobs for marked units…");
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "o");
+ if (r < 0)
+ return r;
+
+ Unit *u;
+ char *k;
+ int ret = 0;
+ HASHMAP_FOREACH_KEY(u, k, m->units) {
+ /* ignore aliases */
+ if (u->id != k)
+ continue;
+
+ BusUnitQueueFlags flags;
+ if (FLAGS_SET(u->markers, 1u << UNIT_MARKER_NEEDS_RESTART))
+ flags = 0;
+ else if (FLAGS_SET(u->markers, 1u << UNIT_MARKER_NEEDS_RELOAD))
+ flags = BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
+ else
+ continue;
+
+ r = mac_selinux_unit_access_check(u, message, "start", error);
+ if (r >= 0)
+ r = bus_unit_queue_job_one(message, u,
+ JOB_TRY_RESTART, JOB_FAIL, flags,
+ reply, error);
+ if (r < 0) {
+ if (ERRNO_IS_RESOURCE(r))
+ return r;
+ if (ret >= 0)
+ ret = r;
+ sd_bus_error_free(error);
+ }
+ }
+
+ if (ret < 0)
+ return sd_bus_error_set_errnof(error, ret,
+ "Failed to enqueue some jobs, see logs for details: %m");
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
assert(bus);
- r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
+ r = sd_bus_message_new_signal(bus, &message,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitFilesChanged");
if (r < 0)
return r;
UnitFileChange *changes,
size_t n_changes) {
- size_t i;
int r;
- for (i = 0; i < n_changes; i++)
+ for (size_t i = 0; i < n_changes; i++)
switch(changes[i].type) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
bool bad = false, good = false;
- size_t i;
int r;
if (unit_file_changes_have_modification(changes, n_changes)) {
if (r < 0)
goto fail;
- for (i = 0; i < n_changes; i++) {
+ for (size_t i = 0; i < n_changes; i++) {
if (changes[i].type < 0) {
bad = true;
good = true;
}
- /* If there was a failed change, and no successful change, then return the first failure as proper method call
- * error. */
+ /* If there was a failed change, and no successful change, then return the first failure as proper
+ * method call error. */
if (bad && !good)
return install_error(error, 0, changes, n_changes);
return r;
if (u->type != UNIT_SCOPE)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit '%s' is not a scope unit, refusing.", name);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Unit '%s' is not a scope unit, refusing.", name);
return bus_scope_method_abandon(message, u, error);
}
if (!isempty(t)) {
mode = show_status_from_string(t);
if (mode < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid show status '%s'", t);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid show status '%s'", t);
}
manager_override_show_status(m, mode, "bus");
NULL,,
method_bind_mount_unit,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("MountImageUnit",
+ "sssbba(ss)",
+ SD_BUS_PARAM(name)
+ SD_BUS_PARAM(source)
+ SD_BUS_PARAM(destination)
+ SD_BUS_PARAM(read_only)
+ SD_BUS_PARAM(mkdir)
+ SD_BUS_PARAM(options),
+ NULL,,
+ method_mount_image_unit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("RefUnit",
"s",
SD_BUS_PARAM(name),
NULL,,
method_unset_and_set_environment,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("EnqueueMarkedJobs",
+ NULL,,
+ "ao",
+ SD_BUS_PARAM(jobs),
+ method_enqueue_marked_jobs,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ListUnitFiles",
NULL,,
"a(ss)",
assert(bus);
assert(times);
- r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
+ r = sd_bus_message_new_signal(bus,
+ &message,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartupFinished");
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
-int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- int read_only, make_file_or_directory;
+static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_bus_error *error, bool is_image) {
+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
const char *dest, *src, *propagate_directory;
+ int read_only, make_file_or_directory;
Unit *u = userdata;
ExecContext *c;
pid_t unit_pid;
if (!path_is_absolute(src) || !path_is_normalized(src))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
- if (isempty(dest))
+ if (!is_image && isempty(dest))
dest = src;
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
+ if (is_image) {
+ r = bus_read_mount_options(message, error, &options, NULL, "");
+ if (r < 0)
+ return r;
+ }
+
r = bus_verify_manage_units_async_full(
u,
- "bind-mount",
+ is_image ? "mount-image" : "bind-mount",
CAP_SYS_ADMIN,
- N_("Authentication is required to bind mount on '$(unit)'."),
+ N_("Authentication is required to mount on '$(unit)'."),
true,
message,
error);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
- r = bind_mount_in_namespace(unit_pid,
- propagate_directory,
- "/run/systemd/incoming/",
- src, dest, read_only, make_file_or_directory);
+ if (is_image)
+ r = mount_image_in_namespace(unit_pid,
+ propagate_directory,
+ "/run/systemd/incoming/",
+ src, dest, read_only, make_file_or_directory, options);
+ else
+ r = bind_mount_in_namespace(unit_pid,
+ propagate_directory,
+ "/run/systemd/incoming/",
+ src, dest, read_only, make_file_or_directory);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in unit's namespace: %m", src, dest);
return sd_bus_reply_method_return(message, NULL);
}
+int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_service_method_mount(message, userdata, error, false);
+}
+
+int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_service_method_mount(message, userdata, error, true);
+}
+
const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
bus_service_method_bind_mount,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("MountImage",
+ "ssbba(ss)",
+ SD_BUS_PARAM(source)
+ SD_BUS_PARAM(destination)
+ SD_BUS_PARAM(read_only)
+ SD_BUS_PARAM(mkdir)
+ SD_BUS_PARAM(options),
+ NULL,,
+ bus_service_method_mount_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+
/* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_service_commit_properties(Unit *u);
b = timer_base_from_string(name);
if (b < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base %s", name);
r = sd_bus_message_read(message, "t", &usec);
if (r < 0)
return sd_bus_message_append(reply, "(ss)", NULL, NULL);
}
+static int property_get_markers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ unsigned *markers = userdata;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(markers);
+
+ r = sd_bus_message_open_container(reply, 'a', "s");
+ if (r < 0)
+ return r;
+
+ /* Make sure out values fit in the bitfield. */
+ assert_cc(_UNIT_MARKER_MAX <= sizeof(((Unit){}).markers) * 8);
+
+ for (UnitMarker m = 0; m < _UNIT_MARKER_MAX; m++)
+ if (FLAGS_SET(*markers, 1u << m)) {
+ r = sd_bus_message_append(reply, "s", unit_marker_to_string(m));
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(reply);
+}
+
static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
[JOB_START] = N_("Authentication is required to start '$(unit)'."),
[JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
sd_bus_error *error) {
Unit *u = userdata;
- const char *i;
int r;
assert(bus);
if (r < 0)
return r;
- for (i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
- int c, k;
+ for (const char *i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
+ int c;
c = sd_bus_track_count_name(u->bus_track, i);
if (c < 0)
return c;
/* Add the item multiple times if the ref count for each is above 1 */
- for (k = 0; k < c; k++) {
+ for (int k = 0; k < c; k++) {
r = sd_bus_message_append(reply, "s", i);
if (r < 0)
return r;
SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Markers", "as", property_get_markers, offsetof(Unit, markers), 0),
SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
}
-int bus_unit_queue_job(
+int bus_unit_queue_job_one(
sd_bus_message *message,
Unit *u,
JobType type,
JobMode mode,
BusUnitQueueFlags flags,
+ sd_bus_message *reply,
sd_bus_error *error) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
_cleanup_set_free_ Set *affected = NULL;
+ _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
Job *j, *a;
int r;
- assert(message);
- assert(u);
- assert(type >= 0 && type < _JOB_TYPE_MAX);
- assert(mode >= 0 && mode < _JOB_MODE_MAX);
-
- r = mac_selinux_unit_access_check(
- u, message,
- job_type_to_access_method(type),
- error);
- if (r < 0)
- return r;
-
- if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
- if (type == JOB_RESTART)
- type = JOB_RELOAD_OR_START;
- else if (type == JOB_TRY_RESTART)
- type = JOB_TRY_RELOAD;
- }
-
- if (type == JOB_STOP &&
- IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
- unit_active_state(u) == UNIT_INACTIVE)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
-
- if ((type == JOB_START && u->refuse_manual_start) ||
- (type == JOB_STOP && u->refuse_manual_stop) ||
- (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
- (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
- return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
-
if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
affected = set_new(NULL);
if (!affected)
/* The classic response is just a job object path */
if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
- return sd_bus_reply_method_return(message, "o", job_path);
+ return sd_bus_message_append(reply, "o", job_path);
/* In verbose mode respond with the anchor job plus everything that has been affected */
- r = sd_bus_message_new_method_return(message, &reply);
- if (r < 0)
- return r;
unit_path = unit_dbus_path(j->unit);
if (!unit_path)
return r;
SET_FOREACH(a, affected) {
-
if (a->id == j->id)
continue;
return r;
}
- r = sd_bus_message_close_container(reply);
+ return sd_bus_message_close_container(reply);
+}
+
+int bus_unit_queue_job(
+ sd_bus_message *message,
+ Unit *u,
+ JobType type,
+ JobMode mode,
+ BusUnitQueueFlags flags,
+ sd_bus_error *error) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ assert(message);
+ assert(u);
+ assert(type >= 0 && type < _JOB_TYPE_MAX);
+ assert(mode >= 0 && mode < _JOB_MODE_MAX);
+
+ r = mac_selinux_unit_access_check(
+ u, message,
+ job_type_to_access_method(type),
+ error);
+ if (r < 0)
+ return r;
+
+ if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
+ if (type == JOB_RESTART)
+ type = JOB_RELOAD_OR_START;
+ else if (type == JOB_TRY_RESTART)
+ type = JOB_TRY_RELOAD;
+ }
+
+ if (type == JOB_STOP &&
+ IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
+ unit_active_state(u) == UNIT_INACTIVE)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
+
+ if ((type == JOB_START && u->refuse_manual_start) ||
+ (type == JOB_STOP && u->refuse_manual_stop) ||
+ (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
+ (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
+ return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = bus_unit_queue_job_one(message, u, type, mode, flags, reply, error);
if (r < 0)
return r;
assert(name);
assert(message);
- /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient
- * units that are being created). */
+ /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for
+ * transient units that are being created). */
if (streq(name, "Description")) {
const char *d;
return 1;
}
+ /* A setting that only applies to active units. We don't actually write this to /run, this state is
+ * managed internally. "+foo" sets flag foo, "-foo" unsets flag foo, just "foo" resets flags to
+ * foo. The last type cannot be mixed with "+" or "-". */
+
+ if (streq(name, "Markers")) {
+ unsigned settings = 0, mask = 0;
+ bool some_plus_minus = false, some_absolute = false;
+
+ r = sd_bus_message_enter_container(message, 'a', "s");
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ const char *word;
+ bool b;
+
+ r = sd_bus_message_read(message, "s", &word);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (IN_SET(word[0], '+', '-')) {
+ b = word[0] == '+';
+ word++;
+ some_plus_minus = true;
+ } else {
+ b = true;
+ some_absolute = true;
+ }
+
+ UnitMarker m = unit_marker_from_string(word);
+ if (m < 0)
+ return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+ "Unknown marker \"%s\".", word);
+
+ SET_FLAG(settings, 1u << m, b);
+ SET_FLAG(mask, 1u << m, true);
+ }
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (some_plus_minus && some_absolute)
+ return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Bad marker syntax.");
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ if (some_absolute)
+ u->markers = settings;
+ else
+ u->markers = settings | (u->markers & ~mask);
+ }
+
+ return 1;
+ }
+
return 0;
}
UnitWriteFlags flags,
sd_bus_error *error) {
- UnitDependency d = _UNIT_DEPENDENCY_INVALID;
+ UnitDependency d;
int r;
assert(u);
assert(name);
assert(message);
- /* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
- * has been created. */
+ /* Handles settings when transient units are created. This settings cannot be altered anymore after
+ * the unit has been created. */
if (streq(name, "SourcePath"))
return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
return r;
if (!UNIT_VTABLE(u)->bus_set_property)
- return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY,
+ "Objects of this type do not support setting properties.");
r = sd_bus_message_enter_container(message, 'v', NULL);
if (r < 0)
return r;
if (r == 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY,
+ "Cannot set property %s, or unknown property.", name);
r = sd_bus_message_exit_container(message);
if (r < 0)
return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
- return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to load properly: %m.", u->id);
+ return sd_bus_error_set_errnof(error, u->load_error,
+ "Unit %s failed to load properly, please adjust/correct and reload service manager: %m", u->id);
case UNIT_MASKED:
return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
assert(u);
- /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
- * error */
+ /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet,
+ * return an error */
if (!u->bus_track)
return -EUNATCH;
BUS_UNIT_QUEUE_VERBOSE_REPLY = 1 << 1,
} BusUnitQueueFlags;
-int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, BusUnitQueueFlags flags, sd_bus_error *error);
+int bus_unit_queue_job_one(
+ sd_bus_message *message,
+ Unit *u,
+ JobType type,
+ JobMode mode,
+ BusUnitQueueFlags flags,
+ sd_bus_message *reply,
+ sd_bus_error *error);
+int bus_unit_queue_job(
+ sd_bus_message *message,
+ Unit *u,
+ JobType type,
+ JobMode mode,
+ BusUnitQueueFlags flags,
+ sd_bus_error *error);
int bus_unit_validate_load_state(Unit *u, sd_bus_error *error);
int bus_unit_track_add_name(Unit *u, const char *name);
#include "bus-polkit.h"
#include "bus-util.h"
#include "dbus-util.h"
+#include "escape.h"
#include "parse-util.h"
#include "path-util.h"
#include "unit-printf.h"
return 1;
}
-int bus_set_transient_percent(
- Unit *u,
- const char *name,
- int *p,
- sd_bus_message *message,
- UnitWriteFlags flags,
- sd_bus_error *error) {
-
- const char *v;
- int r;
-
- assert(p);
-
- r = sd_bus_message_read(message, "s", &v);
- if (r < 0)
- return r;
-
- r = parse_percent(v);
- if (r < 0)
- return r;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- *p = r;
- unit_write_settingf(u, flags, name, "%s=%d%%", name, r);
- }
-
- return 1;
-}
-
int bus_set_transient_usec_internal(
Unit *u,
const char *name,
&u->manager->polkit_registry,
error);
}
+
+/* ret_format_str is an accumulator, so if it has any pre-existing content, new options will be appended to it */
+int bus_read_mount_options(
+ sd_bus_message *message,
+ sd_bus_error *error,
+ MountOptions **ret_options,
+ char **ret_format_str,
+ const char *separator) {
+
+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
+ _cleanup_free_ char *format_str = NULL;
+ const char *mount_options, *partition;
+ int r;
+
+ assert(message);
+ assert(ret_options);
+ assert(separator);
+
+ r = sd_bus_message_enter_container(message, 'a', "(ss)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) {
+ _cleanup_free_ char *previous = NULL, *escaped = NULL;
+ _cleanup_free_ MountOptions *o = NULL;
+ PartitionDesignator partition_designator;
+
+ if (chars_intersect(mount_options, WHITESPACE))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid mount options string, contains whitespace character(s): %s", mount_options);
+
+ partition_designator = partition_designator_from_string(partition);
+ if (partition_designator < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid partition name %s", partition);
+
+ /* Need to store the options with the escapes, so that they can be parsed again */
+ escaped = shell_escape(mount_options, ":");
+ if (!escaped)
+ return -ENOMEM;
+
+ previous = TAKE_PTR(format_str);
+ format_str = strjoin(previous, previous ? separator : "", partition, ":", escaped);
+ if (!format_str)
+ return -ENOMEM;
+
+ o = new(MountOptions, 1);
+ if (!o)
+ return -ENOMEM;
+ *o = (MountOptions) {
+ .partition_designator = partition_designator,
+ .options = strdup(mount_options),
+ };
+ if (!o->options)
+ return -ENOMEM;
+ LIST_APPEND(mount_options, options, TAKE_PTR(o));
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (!LIST_IS_EMPTY(options)) {
+ if (ret_format_str) {
+ char *final = strjoin(*ret_format_str, !isempty(*ret_format_str) ? separator : "", format_str);
+ if (!final)
+ return -ENOMEM;
+ free_and_replace(*ret_format_str, final);
+ }
+ LIST_JOIN(mount_options, *ret_options, options);
+ }
+
+ return 0;
+}
#include "sd-bus.h"
+#include "dissect-image.h"
#include "unit.h"
int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
-int bus_set_transient_percent(Unit *u, const char *name, int *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) {
return bus_set_transient_usec_internal(u, name, p, false, message, flags, error);
return bus_set_transient_usec_internal(u, name, p, true, message, flags, error);
}
int bus_verify_manage_units_async_full(Unit *u, const char *verb, int capability, const char *polkit_message, bool interactive, sd_bus_message *call, sd_bus_error *error);
+
+int bus_read_mount_options(sd_bus_message *message, sd_bus_error *error, MountOptions **ret_options, char **ret_format_str, const char *separator);
static int device_found_to_string_many(DeviceFound flags, char **ret) {
_cleanup_free_ char *s = NULL;
- unsigned i;
assert(ret);
- for (i = 0; i < ELEMENTSOF(device_found_map); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(device_found_map); i++) {
if (!FLAGS_SET(flags, device_found_map[i].flag))
continue;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <errno.h>
+
typedef enum EmergencyAction {
EMERGENCY_ACTION_NONE,
EMERGENCY_ACTION_REBOOT,
_EMERGENCY_ACTION_FIRST_USER_ACTION = EMERGENCY_ACTION_EXIT,
EMERGENCY_ACTION_EXIT_FORCE,
_EMERGENCY_ACTION_MAX,
- _EMERGENCY_ACTION_INVALID = -1
+ _EMERGENCY_ACTION_INVALID = -EINVAL,
} EmergencyAction;
typedef enum EmergencyActionFlags {
#include "terminal-util.h"
#include "tmpfile-util.h"
#include "umask-util.h"
-#include "unit.h"
+#include "unit-serialize.h"
#include "user-util.h"
#include "utmp-wtmp.h"
assert(p);
assert(ret);
-#define N_ENV_VARS 16
+#define N_ENV_VARS 17
our_env = new0(char*, N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
if (!our_env)
return -ENOMEM;
our_env[n_env++] = x;
}
+ if (asprintf(&x, "SYSTEMD_EXEC_PID=" PID_FMT, getpid_cached()) < 0)
+ return -ENOMEM;
+
+ our_env[n_env++] = x;
+
our_env[n_env++] = NULL;
assert(n_env <= N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
#undef N_ENV_VARS
if (!strv_isempty(context->read_write_paths) ||
!strv_isempty(context->read_only_paths) ||
- !strv_isempty(context->inaccessible_paths))
+ !strv_isempty(context->inaccessible_paths) ||
+ !strv_isempty(context->exec_paths) ||
+ !strv_isempty(context->no_exec_paths))
return true;
if (context->n_bind_mounts > 0)
if (context->mount_flags == MS_SHARED)
log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring");
- if (exec_context_has_credentials(context) && params->prefix[EXEC_DIRECTORY_RUNTIME]) {
+ if (exec_context_has_credentials(context) &&
+ params->prefix[EXEC_DIRECTORY_RUNTIME] &&
+ FLAGS_SET(params->flags, EXEC_WRITE_CREDENTIALS)) {
creds_path = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "credentials", u->id);
if (!creds_path) {
r = -ENOMEM;
&ns_info, context->read_write_paths,
needs_sandboxing ? context->read_only_paths : NULL,
needs_sandboxing ? context->inaccessible_paths : NULL,
+ needs_sandboxing ? context->exec_paths : NULL,
+ needs_sandboxing ? context->no_exec_paths : NULL,
empty_directories,
bind_mounts,
n_bind_mounts,
context->root_verity,
propagate_dir,
incoming_dir,
+ root_dir || root_image ? params->notify_socket : NULL,
DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
error_path);
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path);
+
+ /* Normally we would not propagate the oomd xattrs to children but since we created this
+ * sub-cgroup internally we should do it. */
+ cgroup_oomd_xattr_apply(unit, subcgroup_path);
}
}
c->read_only_paths = strv_free(c->read_only_paths);
c->read_write_paths = strv_free(c->read_write_paths);
c->inaccessible_paths = strv_free(c->inaccessible_paths);
+ c->exec_paths = strv_free(c->exec_paths);
+ c->no_exec_paths = strv_free(c->no_exec_paths);
bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
c->bind_mounts = NULL;
}
void exec_command_done_array(ExecCommand *c, size_t n) {
- size_t i;
-
- for (i = 0; i < n; i++)
+ for (size_t i = 0; i < n; i++)
exec_command_done(c+i);
}
fprintf(f, " %s", *g);
}
+static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv) {
+ assert(f);
+ assert(prefix);
+ assert(name);
+
+ if (!strv_isempty(strv)) {
+ fprintf(f, "%s%s:", name, prefix);
+ strv_fprintf(f, strv);
+ fputs("\n", f);
+ }
+}
+
void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX];
int r;
fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
- if (!strv_isempty(c->supplementary_groups)) {
- fprintf(f, "%sSupplementaryGroups:", prefix);
- strv_fprintf(f, c->supplementary_groups);
- fputs("\n", f);
- }
+ strv_dump(f, prefix, "SupplementaryGroups", c->supplementary_groups);
if (c->pam_name)
fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
- if (!strv_isempty(c->read_write_paths)) {
- fprintf(f, "%sReadWritePaths:", prefix);
- strv_fprintf(f, c->read_write_paths);
- fputs("\n", f);
- }
-
- if (!strv_isempty(c->read_only_paths)) {
- fprintf(f, "%sReadOnlyPaths:", prefix);
- strv_fprintf(f, c->read_only_paths);
- fputs("\n", f);
- }
-
- if (!strv_isempty(c->inaccessible_paths)) {
- fprintf(f, "%sInaccessiblePaths:", prefix);
- strv_fprintf(f, c->inaccessible_paths);
- fputs("\n", f);
- }
+ strv_dump(f, prefix, "ReadWritePaths", c->read_write_paths);
+ strv_dump(f, prefix, "ReadOnlyPaths", c->read_only_paths);
+ strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
+ strv_dump(f, prefix, "ExecPaths", c->exec_paths);
+ strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
for (size_t i = 0; i < c->n_bind_mounts; i++)
fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
EXEC_UTMP_LOGIN,
EXEC_UTMP_USER,
_EXEC_UTMP_MODE_MAX,
- _EXEC_UTMP_MODE_INVALID = -1
+ _EXEC_UTMP_MODE_INVALID = -EINVAL,
} ExecUtmpMode;
typedef enum ExecInput {
EXEC_INPUT_DATA,
EXEC_INPUT_FILE,
_EXEC_INPUT_MAX,
- _EXEC_INPUT_INVALID = -1
+ _EXEC_INPUT_INVALID = -EINVAL,
} ExecInput;
typedef enum ExecOutput {
EXEC_OUTPUT_FILE_APPEND,
EXEC_OUTPUT_FILE_TRUNCATE,
_EXEC_OUTPUT_MAX,
- _EXEC_OUTPUT_INVALID = -1
+ _EXEC_OUTPUT_INVALID = -EINVAL,
} ExecOutput;
typedef enum ExecPreserveMode {
EXEC_PRESERVE_YES,
EXEC_PRESERVE_RESTART,
_EXEC_PRESERVE_MODE_MAX,
- _EXEC_PRESERVE_MODE_INVALID = -1
+ _EXEC_PRESERVE_MODE_INVALID = -EINVAL,
} ExecPreserveMode;
typedef enum ExecKeyringMode {
EXEC_KEYRING_PRIVATE,
EXEC_KEYRING_SHARED,
_EXEC_KEYRING_MODE_MAX,
- _EXEC_KEYRING_MODE_INVALID = -1,
+ _EXEC_KEYRING_MODE_INVALID = -EINVAL,
} ExecKeyringMode;
/* Contains start and exit information about an executed command. */
EXEC_DIRECTORY_LOGS,
EXEC_DIRECTORY_CONFIGURATION,
_EXEC_DIRECTORY_TYPE_MAX,
- _EXEC_DIRECTORY_TYPE_INVALID = -1,
+ _EXEC_DIRECTORY_TYPE_INVALID = -EINVAL,
} ExecDirectoryType;
typedef struct ExecDirectory {
EXEC_CLEAN_CONFIGURATION = 1U << EXEC_DIRECTORY_CONFIGURATION,
EXEC_CLEAN_NONE = 0,
EXEC_CLEAN_ALL = (1U << _EXEC_DIRECTORY_TYPE_MAX) - 1,
- _EXEC_CLEAN_MASK_INVALID = -1,
+ _EXEC_CLEAN_MASK_INVALID = -EINVAL,
} ExecCleanMask;
/* A credential configured with SetCredential= */
char *apparmor_profile;
char *smack_process_label;
- char **read_write_paths, **read_only_paths, **inaccessible_paths;
+ char **read_write_paths, **read_only_paths, **inaccessible_paths, **exec_paths, **no_exec_paths;
unsigned long mount_flags;
BindMount *bind_mounts;
size_t n_bind_mounts;
/* An fd that is closed by the execve(), and thus will result in EOF when the execve() is done */
int exec_fd;
+
+ const char *notify_socket;
};
#include "unit.h"
#include "install.h"
#include "load-fragment.h"
#include "string-util.h"
-#include "unit.h"
+#include "unit-serialize.h"
#include "utf8.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
return;
/* Show condition check message if the job did not actually do anything due to failed condition. */
- if ((t == JOB_START && result == JOB_DONE && !u->condition_result) ||
- (t == JOB_START && result == JOB_SKIPPED)) {
+ if (t == JOB_START && result == JOB_DONE && !u->condition_result) {
log_struct(LOG_INFO,
"MESSAGE=Condition check resulted in %s being skipped.", unit_status_string(u),
"JOB_ID=%" PRIu32, job_id,
JOB_RELOAD_OR_START, /* if running, reload, otherwise start */
_JOB_TYPE_MAX,
- _JOB_TYPE_INVALID = -1
+ _JOB_TYPE_INVALID = -EINVAL,
};
enum JobState {
JOB_WAITING,
JOB_RUNNING,
_JOB_STATE_MAX,
- _JOB_STATE_INVALID = -1
+ _JOB_STATE_INVALID = -EINVAL,
};
enum JobMode {
JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */
JOB_TRIGGERING, /* Adds TRIGGERED_BY dependencies to the same transaction */
_JOB_MODE_MAX,
- _JOB_MODE_INVALID = -1
+ _JOB_MODE_INVALID = -EINVAL,
};
enum JobResult {
JOB_COLLECTED, /* Job was garbage collected, since nothing needed it anymore */
JOB_ONCE, /* Unit was started before, and hence can't be started again */
_JOB_RESULT_MAX,
- _JOB_RESULT_INVALID = -1
+ _JOB_RESULT_INVALID = -EINVAL,
};
#include "unit.h"
KILL_MIXED,
KILL_NONE,
_KILL_MODE_MAX,
- _KILL_MODE_INVALID = -1
+ _KILL_MODE_INVALID = -EINVAL,
} KillMode;
struct KillContext {
KILL_CONTROL_FAIL,
KILL_ALL_FAIL,
_KILL_WHO_MAX,
- _KILL_WHO_INVALID = -1
+ _KILL_WHO_INVALID = -EINVAL,
} KillWho;
void kill_context_init(KillContext *c);
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
keywords=0 ; FS="," ;
print "extern const char load_fragment_gperf_nulstr[];" ;
+m4_dnl SPDX-License-Identifier: LGPL-2.1-or-later
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
$1.ReadWritePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths)
$1.ReadOnlyPaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths)
$1.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths)
+$1.ExecPaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.exec_paths)
+$1.NoExecPaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.no_exec_paths)
$1.BindPaths, config_parse_bind_paths, 0, offsetof($1, exec_context)
$1.BindReadOnlyPaths, config_parse_bind_paths, 0, offsetof($1, exec_context)
$1.TemporaryFileSystem, config_parse_temporary_filesystems, 0, offsetof($1, exec_context)
$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system)
$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home)
$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags)
-$1.MountAPIVFS, config_parse_bool, 0, offsetof($1, exec_context.mount_apivfs)
+$1.MountAPIVFS, config_parse_exec_mount_apivfs, 0, offsetof($1, exec_context)
$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality)
$1.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof($1, exec_context.runtime_directory_preserve_mode)
$1.RuntimeDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode)
$1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress)
$1.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_swap)
$1.ManagedOOMMemoryPressure, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_mem_pressure)
-$1.ManagedOOMMemoryPressureLimitPercent, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit)
+$1.ManagedOOMMemoryPressureLimit, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit_permyriad)
+$1.ManagedOOMPreference, config_parse_managed_oom_preference, 0, offsetof($1, cgroup_context.moom_preference)
$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_managed_oom_preference, managed_oom_preference, ManagedOOMPreference, "Failed to parse ManagedOOMPreference=");
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
m = kill_mode_from_string(rvalue);
if (m < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, m,
"Failed to parse kill mode specification, ignoring: %s", rvalue);
return 0;
}
return 0;
}
- if (free_and_strdup(&s->bind_to_device, rvalue) < 0)
- return log_oom();
-
- return 0;
+ return free_and_strdup_warn(&s->bind_to_device, rvalue);
}
int config_parse_exec_input(
} else {
ei = exec_input_from_string(rvalue);
if (ei < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, ei, "Failed to parse input specifier, ignoring: %s", rvalue);
return 0;
}
}
} else {
eo = exec_output_from_string(rvalue);
if (eo < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, eo, "Failed to parse output specifier, ignoring: %s", rvalue);
return 0;
}
}
x = ioprio_class_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, x, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
return 0;
}
x = sched_policy_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, x, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
return 0;
}
partition_designator = partition_designator_from_string(partition);
if (partition_designator < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid partition name %s, ignoring", partition);
+ log_syntax(unit, LOG_WARNING, filename, line, partition_designator,
+ "Invalid partition name %s, ignoring", partition);
continue;
}
r = unit_full_printf(u, mount_options, &mount_options_resolved);
type = unit_name_to_type(p);
if (type < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, type, "Unit type not valid, ignoring: %s", rvalue);
return 0;
}
if (unit_has_name(u, p)) {
b = path_type_from_string(lvalue);
if (b < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, b, "Failed to parse path type, ignoring: %s", lvalue);
return 0;
}
}
for (const char *p = rvalue;; ) {
- _cleanup_free_ char *word = NULL, *k = NULL;
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
}
if (u) {
- r = unit_full_printf(u, word, &k);
+ r = unit_full_printf(u, word, &resolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
} else
- k = TAKE_PTR(word);
+ resolved = TAKE_PTR(word);
- if (!env_assignment_is_valid(k)) {
+ if (!env_assignment_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid environment assignment, ignoring: %s", k);
+ "Invalid environment assignment, ignoring: %s", resolved);
continue;
}
- r = strv_env_replace(env, k);
+ r = strv_env_replace_consume(env, TAKE_PTR(resolved));
if (r < 0)
- return log_oom();
-
- k = NULL;
+ return log_error_errno(r, "Failed to update environment: %m");
}
}
}
e = parse_errno(rvalue);
- if (e <= 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue);
+ if (e < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, e, "Failed to parse error number, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (e == 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid error number, ignoring: %s", rvalue);
return 0;
}
m = managed_oom_mode_from_string(rvalue);
if (m < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid syntax, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, m, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
*mode = m;
const char *rvalue,
void *data,
void *userdata) {
- int *limit = data;
+ uint32_t *limit = data;
UnitType t;
int r;
return 0;
}
- r = parse_percent(rvalue);
+ r = parse_permyriad(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse limit percent value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse memory pressure limit value, ignoring: %s", rvalue);
return 0;
}
} else {
r = signal_from_string(word);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse value, ignoring: %s", word);
continue;
}
partition_designator = partition_designator_from_string(partition);
if (partition_designator < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid partition name %s, ignoring", partition);
+ log_syntax(unit, LOG_WARNING, filename, line, partition_designator,
+ "Invalid partition name %s, ignoring", partition);
continue;
}
r = unit_full_printf(u, mount_options, &mount_options_resolved);
}
}
- /* We do the merge dance here because for some unit types, the unit might have aliases which are not
+ /* Call merge_by_names with the name derived from the fragment path as the preferred name.
+ *
+ * We do the merge dance here because for some unit types, the unit might have aliases which are not
* declared in the file system. In particular, this is true (and frequent) for device and swap units.
*/
- Unit *merged;
const char *id = u->id;
_cleanup_free_ char *free_id = NULL;
}
}
- merged = u;
+ Unit *merged = u;
r = merge_by_names(&merged, names, id);
if (r < 0)
return r;
} else {
t = exec_output_from_string(rvalue);
if (t < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, t, "Failed to parse output type, ignoring: %s", rvalue);
return 0;
}
CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mem_pressure_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);
#include "mount-setup.h"
#include "os-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
return 0;
if (path_is_absolute(value))
- (void) parse_path_argument_and_warn(value, false, &arg_early_core_pattern);
+ (void) parse_path_argument(value, false, &arg_early_core_pattern);
else
log_warning("Specified core pattern '%s' is not an absolute path, ignoring.", value);
if (proc_cmdline_value_missing(key, value))
return 0;
- if (env_assignment_is_valid(value)) {
- char **env;
-
- env = strv_env_set(arg_default_environment, value);
- if (!env)
+ if (!env_assignment_is_valid(value))
+ log_warning("Environment variable assignment '%s' is not valid. Ignoring.", value);
+ else {
+ r = strv_env_replace_strdup(&arg_default_environment, value);
+ if (r < 0)
return log_oom();
-
- arg_default_environment = env;
- } else
- log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
+ }
} else if (proc_cmdline_key_streq(key, "systemd.machine_id")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- (void) parse_path_argument_and_warn(value, false, &arg_watchdog_device);
+ (void) parse_path_argument(value, false, &arg_watchdog_device);
} else if (proc_cmdline_key_streq(key, "systemd.clock_usec")) {
};
int c, r;
+ bool user_arg_seen = false;
assert(argc >= 1);
assert(argv);
case ARG_USER:
arg_system = false;
+ user_arg_seen = true;
break;
case ARG_TEST:
}
if (optind < argc && getpid_cached() != 1)
- /* Hmm, when we aren't run as init system
- * let's complain about excess arguments */
+ /* Hmm, when we aren't run as init system let's complain about excess arguments */
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Excess arguments.");
+
+ if (arg_action == ACTION_RUN && !arg_system && !user_arg_seen)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Excess arguments.");
+ "Explicit --user argument required to run as user manager.");
return 0;
}
" --log-time[=BOOL] Prefix log messages with current time\n"
" --default-standard-output= Set default standard output for services\n"
" --default-standard-error= Set default standard error output for services\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , ansi_underline(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
+ ansi_normal(),
+ link);
return 0;
}
#include "transaction.h"
#include "umask-util.h"
#include "unit-name.h"
+#include "unit-serialize.h"
#include "user-util.h"
#include "virt.h"
#include "watchdog.h"
SIGCHLD, /* Child died */
SIGTERM, /* Reexecute daemon */
SIGHUP, /* Reload configuration */
- SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
+ SIGUSR1, /* systemd: reconnect to D-Bus */
SIGUSR2, /* systemd: dump status */
SIGINT, /* Kernel sends us this on control-alt-del */
SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
/* Import locale variables LC_*= from configuration */
(void) locale_setup(&m->transient_environment);
} else {
- _cleanup_free_ char *k = NULL;
-
- /* The user manager passes its own environment
- * along to its children, except for $PATH. */
+ /* The user manager passes its own environment along to its children, except for $PATH. */
m->transient_environment = strv_copy(environ);
if (!m->transient_environment)
return log_oom();
- k = strdup("PATH=" DEFAULT_USER_PATH);
- if (!k)
- return log_oom();
-
- r = strv_env_replace(&m->transient_environment, k);
+ r = strv_env_replace_strdup(&m->transient_environment, "PATH=" DEFAULT_USER_PATH);
if (r < 0)
return log_oom();
- TAKE_PTR(k);
}
sanitize_environment(m->transient_environment);
is_bad = false;
}
- if (u->refs_by_target) {
- const UnitRef *ref;
-
- LIST_FOREACH(refs_by_target, ref, u->refs_by_target) {
- unit_gc_sweep(ref->source, gc_marker);
+ const UnitRef *ref;
+ LIST_FOREACH(refs_by_target, ref, u->refs_by_target) {
+ unit_gc_sweep(ref->source, gc_marker);
- if (ref->source->gc_marker == gc_marker + GC_OFFSET_GOOD)
- goto good;
+ if (ref->source->gc_marker == gc_marker + GC_OFFSET_GOOD)
+ goto good;
- if (ref->source->gc_marker != gc_marker + GC_OFFSET_BAD)
- is_bad = false;
- }
+ if (ref->source->gc_marker != gc_marker + GC_OFFSET_BAD)
+ is_bad = false;
}
if (is_bad)
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
if (IN_SET(n, -EAGAIN, -EINTR))
return 0; /* Spurious wakeup, try again */
+ if (n == -EXFULL) {
+ log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
+ return 0;
+ }
if (n < 0)
/* If this is any other, real error, then let's stop processing this socket. This of course
* means we won't take notification messages anymore, but that's still better than busy
#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
static void manager_serialize_uid_refs_internal(
- Manager *m,
FILE *f,
- Hashmap **uid_refs,
+ Hashmap *uid_refs,
const char *field_name) {
void *p, *k;
- assert(m);
assert(f);
- assert(uid_refs);
assert(field_name);
/* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
* the actual counter of it is better rebuild after a reload/reexec. */
- HASHMAP_FOREACH_KEY(p, k, *uid_refs) {
+ HASHMAP_FOREACH_KEY(p, k, uid_refs) {
uint32_t c;
uid_t uid;
}
static void manager_serialize_uid_refs(Manager *m, FILE *f) {
- manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid");
+ manager_serialize_uid_refs_internal(f, m->uid_refs, "destroy-ipc-uid");
}
static void manager_serialize_gid_refs(Manager *m, FILE *f) {
- manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid");
+ manager_serialize_uid_refs_internal(f, m->gid_refs, "destroy-ipc-gid");
}
int manager_serialize(
}
static void manager_deserialize_uid_refs_one_internal(
- Manager *m,
Hashmap** uid_refs,
const char *value) {
uint32_t c;
int r;
- assert(m);
assert(uid_refs);
assert(value);
r = parse_uid(value, &uid);
if (r < 0 || uid == 0) {
- log_debug("Unable to parse UID reference serialization: " UID_FMT, uid);
+ log_debug("Unable to parse UID/GID reference serialization: " UID_FMT, uid);
return;
}
- r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops);
- if (r < 0) {
+ if (hashmap_ensure_allocated(uid_refs, &trivial_hash_ops) < 0) {
log_oom();
return;
}
r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
if (r < 0) {
- log_debug_errno(r, "Failed to add UID reference entry: %m");
+ log_debug_errno(r, "Failed to add UID/GID reference entry: %m");
return;
}
}
static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
- manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value);
+ manager_deserialize_uid_refs_one_internal(&m->uid_refs, value);
}
static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
- manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value);
+ manager_deserialize_uid_refs_one_internal(&m->gid_refs, value);
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
/* Clean up runtime objects no longer referenced */
manager_vacuum(m);
+ /* Clean up deserialized tracked clients */
+ m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
+
/* Consider the reload process complete now. */
assert(m->n_reloading > 0);
m->n_reloading--;
RUN_WITH_UMASK(0022)
r = execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, gather_environment,
- args, NULL, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
+ args, NULL, m->transient_environment,
+ EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS | EXEC_DIR_SET_SYSTEMD_EXEC_PID);
return r;
}
RUN_WITH_UMASK(0022)
(void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, NULL, NULL,
- (char**) argv, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
+ (char**) argv, m->transient_environment,
+ EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS | EXEC_DIR_SET_SYSTEMD_EXEC_PID);
r = 0;
}
static void manager_unref_uid_internal(
- Manager *m,
- Hashmap **uid_refs,
+ Hashmap *uid_refs,
uid_t uid,
bool destroy_now,
int (*_clean_ipc)(uid_t uid)) {
uint32_t c, n;
- assert(m);
- assert(uid_refs);
assert(uid_is_valid(uid));
assert(_clean_ipc);
if (uid == 0) /* We don't keep track of root, and will never destroy it */
return;
- c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
+ c = PTR_TO_UINT32(hashmap_get(uid_refs, UID_TO_PTR(uid)));
n = c & ~DESTROY_IPC_FLAG;
assert(n > 0);
n--;
if (destroy_now && n == 0) {
- hashmap_remove(*uid_refs, UID_TO_PTR(uid));
+ hashmap_remove(uid_refs, UID_TO_PTR(uid));
if (c & DESTROY_IPC_FLAG) {
log_debug("%s " UID_FMT " is no longer referenced, cleaning up its IPC.",
}
} else {
c = n | (c & DESTROY_IPC_FLAG);
- assert_se(hashmap_update(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)) >= 0);
+ assert_se(hashmap_update(uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)) >= 0);
}
}
void manager_unref_uid(Manager *m, uid_t uid, bool destroy_now) {
- manager_unref_uid_internal(m, &m->uid_refs, uid, destroy_now, clean_ipc_by_uid);
+ manager_unref_uid_internal(m->uid_refs, uid, destroy_now, clean_ipc_by_uid);
}
void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now) {
- manager_unref_uid_internal(m, &m->gid_refs, (uid_t) gid, destroy_now, clean_ipc_by_gid);
+ manager_unref_uid_internal(m->gid_refs, (uid_t) gid, destroy_now, clean_ipc_by_gid);
}
static int manager_ref_uid_internal(
- Manager *m,
Hashmap **uid_refs,
uid_t uid,
bool clean_ipc) {
uint32_t c, n;
int r;
- assert(m);
assert(uid_refs);
assert(uid_is_valid(uid));
}
int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc) {
- return manager_ref_uid_internal(m, &m->uid_refs, uid, clean_ipc);
+ return manager_ref_uid_internal(&m->uid_refs, uid, clean_ipc);
}
int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc) {
- return manager_ref_uid_internal(m, &m->gid_refs, (uid_t) gid, clean_ipc);
+ return manager_ref_uid_internal(&m->gid_refs, (uid_t) gid, clean_ipc);
}
static void manager_vacuum_uid_refs_internal(
- Manager *m,
- Hashmap **uid_refs,
+ Hashmap *uid_refs,
int (*_clean_ipc)(uid_t uid)) {
void *p, *k;
- assert(m);
- assert(uid_refs);
assert(_clean_ipc);
- HASHMAP_FOREACH_KEY(p, k, *uid_refs) {
+ HASHMAP_FOREACH_KEY(p, k, uid_refs) {
uint32_t c, n;
uid_t uid;
(void) _clean_ipc(uid);
}
- assert_se(hashmap_remove(*uid_refs, k) == p);
+ assert_se(hashmap_remove(uid_refs, k) == p);
}
}
static void manager_vacuum_uid_refs(Manager *m) {
- manager_vacuum_uid_refs_internal(m, &m->uid_refs, clean_ipc_by_uid);
+ manager_vacuum_uid_refs_internal(m->uid_refs, clean_ipc_by_uid);
}
static void manager_vacuum_gid_refs(Manager *m) {
- manager_vacuum_uid_refs_internal(m, &m->gid_refs, clean_ipc_by_gid);
+ manager_vacuum_uid_refs_internal(m->gid_refs, clean_ipc_by_gid);
}
static void manager_vacuum(Manager *m) {
MANAGER_MAINTENANCE,
MANAGER_STOPPING,
_MANAGER_STATE_MAX,
- _MANAGER_STATE_INVALID = -1
+ _MANAGER_STATE_INVALID = -EINVAL,
} ManagerState;
typedef enum ManagerObjective {
MANAGER_KEXEC,
MANAGER_SWITCH_ROOT,
_MANAGER_OBJECTIVE_MAX,
- _MANAGER_OBJECTIVE_INVALID = -1
+ _MANAGER_OBJECTIVE_INVALID = -EINVAL,
} ManagerObjective;
typedef enum StatusType {
OOM_STOP, /* The kernel kills the process it wants to kill, and we stop the unit */
OOM_KILL, /* The kernel kills the process it wants to kill, and all others in the unit, and we stop the unit */
_OOM_POLICY_MAX,
- _OOM_POLICY_INVALID = -1
+ _OOM_POLICY_INVALID = -EINVAL,
} OOMPolicy;
/* Notes:
MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START,
MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH,
_MANAGER_TIMESTAMP_MAX,
- _MANAGER_TIMESTAMP_INVALID = -1,
+ _MANAGER_TIMESTAMP_INVALID = -EINVAL,
} ManagerTimestamp;
typedef enum WatchdogType {
/* The stat() data the last time we saw /etc/localtime */
usec_t etc_localtime_mtime;
- bool etc_localtime_accessible:1;
+ bool etc_localtime_accessible;
- ManagerObjective objective:5;
+ ManagerObjective objective;
/* Flags */
- bool dispatching_load_queue:1;
+ bool dispatching_load_queue;
- bool taint_usr:1;
+ bool taint_usr;
/* Have we already sent out the READY=1 notification? */
- bool ready_sent:1;
+ bool ready_sent;
/* Have we already printed the taint line if necessary? */
- bool taint_logged:1;
+ bool taint_logged;
/* Have we ever changed the "kernel.pid_max" sysctl? */
- bool sysctl_pid_max_changed:1;
+ bool sysctl_pid_max_changed;
- ManagerTestRunFlags test_run_flags:8;
+ ManagerTestRunFlags test_run_flags;
/* If non-zero, exit with the following value when the systemd
* process terminate. Useful for containers: systemd-nspawn could get
int original_log_level;
LogTarget original_log_target;
- bool log_level_overridden:1;
- bool log_target_overridden:1;
+ bool log_level_overridden;
+ bool log_target_overridden;
struct rlimit *rlimit[_RLIMIT_MAX];
int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc);
void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now);
-int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now);
+int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc);
char *manager_taint_string(Manager *m);
transaction.h
unit-printf.c
unit-printf.h
+ unit-serialize.c
+ unit-serialize.h
unit.c
unit.h
'''.split()
systemd_sources = files('main.c')
-in_files = [['macros.systemd', rpmmacrosdir],
- ['system.conf', pkgsysconfdir],
+in_files = [['system.conf', pkgsysconfdir],
['user.conf', pkgsysconfdir],
- ['systemd.pc', pkgconfigdatadir],
- ['triggers.systemd', '']]
+ ['systemd.pc', pkgconfigdatadir]]
foreach item : in_files
file = item[0]
p = get_mount_parameters_fragment(m);
if (p && mount_is_bind(p)) {
r = mkdir_p_label(p->what, m->directory_mode);
- if (r < 0)
+ /* mkdir_p_label() can return -EEXIST if the target path exists and is not a directory - which is
+ * totally OK, in case the user wants us to overmount a non-directory inode. */
+ if (r < 0 && r != -EEXIST)
log_unit_error_errno(UNIT(m), r, "Failed to make bind mount source '%s': %m", p->what);
}
if (streq(key, "state")) {
MountState state;
- if ((state = mount_state_from_string(value)) < 0)
- log_unit_debug(u, "Failed to parse state value: %s", value);
+ state = mount_state_from_string(value);
+ if (state < 0)
+ log_unit_debug_errno(u, state, "Failed to parse state value: %s", value);
else
m->deserialized_state = state;
f = mount_result_from_string(value);
if (f < 0)
- log_unit_debug(u, "Failed to parse result value: %s", value);
+ log_unit_debug_errno(u, f, "Failed to parse result value: %s", value);
else if (f != MOUNT_SUCCESS)
m->result = f;
f = mount_result_from_string(value);
if (f < 0)
- log_unit_debug(u, "Failed to parse reload result value: %s", value);
+ log_unit_debug_errno(u, f, "Failed to parse reload result value: %s", value);
else if (f != MOUNT_SUCCESS)
m->reload_result = f;
r = safe_atou(value, &m->n_retry_umount);
if (r < 0)
- log_unit_debug(u, "Failed to parse n-retry-umount value: %s", value);
+ log_unit_debug_errno(u, r, "Failed to parse n-retry-umount value: %s", value);
} else if (streq(key, "control-pid")) {
- if (parse_pid(value, &m->control_pid) < 0)
- log_unit_debug(u, "Failed to parse control-pid value: %s", value);
+ r = parse_pid(value, &m->control_pid);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to parse control-pid value: %s", value);
} else if (streq(key, "control-command")) {
MountExecCommand id;
id = mount_exec_command_from_string(value);
if (id < 0)
- log_unit_debug(u, "Failed to parse exec-command value: %s", value);
+ log_unit_debug_errno(u, id, "Failed to parse exec-command value: %s", value);
else {
m->control_command_id = id;
m->control_command = m->exec_command + id;
MOUNT_EXEC_UNMOUNT,
MOUNT_EXEC_REMOUNT,
_MOUNT_EXEC_COMMAND_MAX,
- _MOUNT_EXEC_COMMAND_INVALID = -1
+ _MOUNT_EXEC_COMMAND_INVALID = -EINVAL,
} MountExecCommand;
typedef enum MountResult {
MOUNT_FAILURE_START_LIMIT_HIT,
MOUNT_FAILURE_PROTOCOL,
_MOUNT_RESULT_MAX,
- _MOUNT_RESULT_INVALID = -1
+ _MOUNT_RESULT_INVALID = -EINVAL,
} MountResult;
typedef struct MountParameters {
RUN,
READONLY,
READWRITE,
+ NOEXEC,
+ EXEC,
TMPFS,
READWRITE_IMPLICIT, /* Should have the lowest priority. */
_MOUNT_MODE_MAX,
bool has_prefix:1; /* Already is prefixed by the root dir? */
bool read_only:1; /* Shall this mount point be read-only? */
bool nosuid:1; /* Shall set MS_NOSUID on the mount itself */
+ bool noexec:1; /* Shall set MS_NOEXEC on the mount itself */
+ bool exec:1; /* Shall clear MS_NOEXEC on the mount itself */
bool applied:1; /* Already applied */
char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */
+ const char *unprefixed_path_const; /* If the path was amended with a prefix, these will save the original */
+ char *unprefixed_path_malloc;
const char *source_const; /* The source path, for bind mounts or images */
char *source_malloc;
const char *options_const;/* Mount options for tmpfs */
[TMPFS] = "tmpfs",
[MOUNT_IMAGES] = "mount-images",
[READWRITE_IMPLICIT] = "rw-implicit",
+ [EXEC] = "exec",
+ [NOEXEC] = "noexec",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(mount_mode, MountMode);
return p->path_malloc ?: p->path_const;
}
+static const char *mount_entry_unprefixed_path(const MountEntry *p) {
+ assert(p);
+
+ /* Returns the unprefixed path (ie: before prefix_where_needed() ran), if any */
+
+ return p->unprefixed_path_malloc ?: p->unprefixed_path_const ?: mount_entry_path(p);
+}
+
+static void mount_entry_consume_prefix(MountEntry *p, char *new_path) {
+ assert(p);
+ assert(p->path_malloc || p->path_const);
+ assert(new_path);
+
+ /* Saves current path in unprefixed_ variable, and takes over new_path */
+
+ free_and_replace(p->unprefixed_path_malloc, p->path_malloc);
+ /* If we didn't have a path on the heap, then it's a static one */
+ if (!p->unprefixed_path_malloc)
+ p->unprefixed_path_const = p->path_const;
+ p->path_malloc = new_path;
+ p->has_prefix = true;
+}
+
static bool mount_entry_read_only(const MountEntry *p) {
assert(p);
return p->read_only || IN_SET(p->mode, READONLY, INACCESSIBLE, PRIVATE_TMP_READONLY);
}
+static bool mount_entry_noexec(const MountEntry *p) {
+ assert(p);
+
+ return p->noexec || IN_SET(p->mode, NOEXEC, INACCESSIBLE, SYSFS, PROCFS);
+}
+
+static bool mount_entry_exec(const MountEntry *p) {
+ assert(p);
+
+ return p->exec || p->mode == EXEC;
+}
+
static const char *mount_entry_source(const MountEntry *p) {
assert(p);
assert(p);
p->path_malloc = mfree(p->path_malloc);
+ p->unprefixed_path_malloc = mfree(p->unprefixed_path_malloc);
p->source_malloc = mfree(p->source_malloc);
p->options_malloc = mfree(p->options_malloc);
p->image_options = mount_options_free_all(p->image_options);
}
static int append_bind_mounts(MountEntry **p, const BindMount *binds, size_t n) {
- size_t i;
-
assert(p);
- for (i = 0; i < n; i++) {
+ for (size_t i = 0; i < n; i++) {
const BindMount *b = binds + i;
*((*p)++) = (MountEntry) {
}
static int append_static_mounts(MountEntry **p, const MountEntry *mounts, size_t n, bool ignore_protect) {
- size_t i;
-
assert(p);
assert(mounts);
/* Adds a list of static pre-defined entries */
- for (i = 0; i < n; i++)
+ for (size_t i = 0; i < n; i++)
*((*p)++) = (MountEntry) {
.path_const = mount_entry_path(mounts+i),
.mode = mounts[i].mode,
}
static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directory) {
- size_t i;
-
/* Prefixes all paths in the bind mount table with the root directory if the entry needs that. */
- for (i = 0; i < n; i++) {
+ assert(m || n == 0);
+
+ for (size_t i = 0; i < n; i++) {
char *s;
if (m[i].has_prefix)
if (!s)
return -ENOMEM;
- free_and_replace(m[i].path_malloc, s);
- m[i].has_prefix = true;
+ mount_entry_consume_prefix(&m[i], s);
}
return 0;
path_equal(mount_entry_path(f), mount_entry_path(previous)) &&
!f->applied && !previous->applied) {
log_debug("%s (%s) is duplicate.", mount_entry_path(f), mount_mode_to_string(f->mode));
- previous->read_only = previous->read_only || mount_entry_read_only(f); /* Propagate the read-only flag to the remaining entry */
+ /* Propagate the flags to the remaining entry */
+ previous->read_only = previous->read_only || mount_entry_read_only(f);
+ previous->noexec = previous->noexec || mount_entry_noexec(f);
+ previous->exec = previous->exec || mount_entry_exec(f);
mount_entry_done(f);
continue;
}
assert(m);
entry_path = mount_entry_path(m);
- inner_path = m->path_const;
+ inner_path = mount_entry_unprefixed_path(m);
/* First, get rid of everything that is below if there is anything. Then, overmount with our new tmpfs */
}
static int mount_images(const MountEntry *m) {
- _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
- _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
- _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
- _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
- DissectImageFlags dissect_image_flags;
int r;
assert(m);
- r = verity_settings_load(&verity, mount_entry_source(m), NULL, NULL);
- if (r < 0)
- return log_debug_errno(r, "Failed to load root hash: %m");
-
- dissect_image_flags =
- (m->read_only ? DISSECT_IMAGE_READ_ONLY : 0) |
- (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0);
-
- r = loop_device_make_by_path(
- mount_entry_source(m),
- m->read_only ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
- verity.data_path ? 0 : LO_FLAGS_PARTSCAN,
- &loop_device);
- if (r < 0)
- return log_debug_errno(r, "Failed to create loop device for image: %m");
-
- r = dissect_image(
- loop_device->fd,
- &verity,
- m->image_options,
- dissect_image_flags,
- &dissected_image);
- /* No partition table? Might be a single-filesystem image, try again */
- if (!verity.data_path && r == -ENOPKG)
- r = dissect_image(
- loop_device->fd,
- &verity,
- m->image_options,
- dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
- &dissected_image);
- if (r < 0)
- return log_debug_errno(r, "Failed to dissect image: %m");
-
- r = dissected_image_decrypt(
- dissected_image,
- NULL,
- &verity,
- dissect_image_flags,
- &decrypted_image);
- if (r < 0)
- return log_debug_errno(r, "Failed to decrypt dissected image: %m");
-
- r = mkdir_p_label(mount_entry_path(m), 0755);
- if (r < 0)
- return log_debug_errno(r, "Failed to create destination directory %s: %m", mount_entry_path(m));
- r = umount_recursive(mount_entry_path(m), 0);
- if (r < 0)
- return log_debug_errno(r, "Failed to umount under destination directory %s: %m", mount_entry_path(m));
-
- r = dissected_image_mount(dissected_image, mount_entry_path(m), UID_INVALID, dissect_image_flags);
+ r = verity_dissect_and_mount(mount_entry_source(m), mount_entry_path(m), m->image_options);
+ if (r == -ENOENT && m->ignore)
+ return 0;
if (r < 0)
- return log_debug_errno(r, "Failed to mount image: %m");
-
- if (decrypted_image) {
- r = decrypted_image_relinquish(decrypted_image);
- if (r < 0)
- return log_debug_errno(r, "Failed to relinquish decrypted image: %m");
- }
-
- loop_device_relinquish(loop_device);
+ return log_debug_errno(r, "Failed to mount image %s on %s: %m", mount_entry_source(m), mount_entry_path(m));
return 1;
}
log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target);
- free_and_replace(m->path_malloc, target);
- m->has_prefix = true;
+ mount_entry_consume_prefix(m, TAKE_PTR(target));
m->n_followed ++;
case READONLY:
case READWRITE:
case READWRITE_IMPLICIT:
+ case EXEC:
+ case NOEXEC:
r = path_is_mount_point(mount_entry_path(m), root_directory, 0);
if (r == -ENOENT && m->ignore)
return 0;
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m",
mount_entry_path(m));
if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY
- * bit for the mount point if needed. */
+ * and MS_NOEXEC bits for the mount point if needed. */
return 0;
/* This isn't a mount point yet, let's make it one. */
what = mount_entry_path(m);
else
r = bind_remount_one_with_mountinfo(mount_entry_path(m), new_flags, flags_mask, proc_self_mountinfo);
- /* Not that we only turn on the MS_RDONLY flag here, we never turn it off. Something that was marked
+ /* Note that we only turn on the MS_RDONLY flag here, we never turn it off. Something that was marked
* read-only already stays this way. This improves compatibility with container managers, where we
* won't attempt to undo read-only mounts already applied. */
return 0;
}
+static int make_noexec(const MountEntry *m, char **deny_list, FILE *proc_self_mountinfo) {
+ unsigned long new_flags = 0, flags_mask = 0;
+ bool submounts = false;
+ int r = 0;
+
+ assert(m);
+ assert(proc_self_mountinfo);
+
+ if (mount_entry_noexec(m)) {
+ new_flags |= MS_NOEXEC;
+ flags_mask |= MS_NOEXEC;
+ } else if (mount_entry_exec(m)) {
+ new_flags &= ~MS_NOEXEC;
+ flags_mask |= MS_NOEXEC;
+ }
+
+ if (flags_mask == 0) /* No Change? */
+ return 0;
+
+ submounts = !IN_SET(m->mode, EMPTY_DIR, TMPFS);
+
+ if (submounts)
+ r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), new_flags, flags_mask, deny_list, proc_self_mountinfo);
+ else
+ r = bind_remount_one_with_mountinfo(mount_entry_path(m), new_flags, flags_mask, proc_self_mountinfo);
+
+ if (r == -ENOENT && m->ignore)
+ return 0;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to re-mount '%s'%s: %m", mount_entry_path(m),
+ submounts ? " and its submounts" : "");
+ return 0;
+}
+
static bool namespace_info_mount_apivfs(const NamespaceInfo *ns_info) {
assert(ns_info);
char** read_write_paths,
char** read_only_paths,
char** inaccessible_paths,
+ char** exec_paths,
+ char** no_exec_paths,
char** empty_directories,
size_t n_bind_mounts,
size_t n_temporary_filesystems,
const char* var_tmp_dir,
const char *creds_path,
const char* log_namespace,
- bool setup_propagate) {
+ bool setup_propagate,
+ const char* notify_socket) {
size_t protect_home_cnt;
size_t protect_system_cnt =
strv_length(read_write_paths) +
strv_length(read_only_paths) +
strv_length(inaccessible_paths) +
+ strv_length(exec_paths) +
+ strv_length(no_exec_paths) +
strv_length(empty_directories) +
n_bind_mounts +
n_mount_images +
n_temporary_filesystems +
- (setup_propagate ? 1 : 0) + /* /run/systemd/incoming */
ns_info->private_dev +
(ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) +
(ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) +
(ns_info->protect_hostname ? 2 : 0) +
(namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0) +
(creds_path ? 2 : 1) +
- !!log_namespace;
+ !!log_namespace +
+ setup_propagate + /* /run/systemd/incoming */
+ !!notify_socket;
}
static void normalize_mounts(const char *root_directory, MountEntry *mounts, size_t *n_mounts) {
char** read_write_paths,
char** read_only_paths,
char** inaccessible_paths,
+ char** exec_paths,
+ char** no_exec_paths,
char** empty_directories,
const BindMount *bind_mounts,
size_t n_bind_mounts,
const char *verity_data_path,
const char *propagate_dir,
const char *incoming_dir,
+ const char *notify_socket,
DissectImageFlags dissect_image_flags,
char **error_path) {
read_write_paths,
read_only_paths,
inaccessible_paths,
+ exec_paths,
+ no_exec_paths,
empty_directories,
n_bind_mounts,
n_temporary_filesystems,
tmp_dir, var_tmp_dir,
creds_path,
log_namespace,
- setup_propagate);
+ setup_propagate,
+ notify_socket);
if (n_mounts > 0) {
m = mounts = new0(MountEntry, n_mounts);
if (r < 0)
goto finish;
+ r = append_access_mounts(&m, exec_paths, EXEC, require_prefix);
+ if (r < 0)
+ goto finish;
+
+ r = append_access_mounts(&m, no_exec_paths, NOEXEC, require_prefix);
+ if (r < 0)
+ goto finish;
+
r = append_empty_dir_mounts(&m, empty_directories);
if (r < 0)
goto finish;
.read_only = true,
};
+ if (notify_socket)
+ *(m++) = (MountEntry) {
+ .path_const = notify_socket,
+ .source_const = notify_socket,
+ .mode = BIND_MOUNT,
+ .read_only = true,
+ };
+
assert(mounts + n_mounts == m);
/* Prepend the root directory where that's necessary */
goto finish;
}
}
+
+ /* Third round, flip the noexec bits with a simplified deny list. */
+ for (m = mounts, j = 0; m < mounts + n_mounts; ++m)
+ if (IN_SET(m->mode, EXEC, NOEXEC))
+ deny_list[j++] = (char*) mount_entry_path(m);
+ deny_list[j] = NULL;
+
+ for (m = mounts; m < mounts + n_mounts; ++m) {
+ r = make_noexec(m, deny_list, proc_self_mountinfo);
+ if (r < 0) {
+ if (error_path && mount_entry_path(m))
+ *error_path = strdup(mount_entry_path(m));
+ goto finish;
+ }
+ }
}
/* MS_MOVE does not work on MS_SHARED so the remount MS_SHARED will be done later */
}
void bind_mount_free_many(BindMount *b, size_t n) {
- size_t i;
-
assert(b || n == 0);
- for (i = 0; i < n; i++) {
+ for (size_t i = 0; i < n; i++) {
free(b[i].source);
free(b[i].destination);
}
}
MountImage* mount_image_free_many(MountImage *m, size_t *n) {
- size_t i;
-
assert(n);
assert(m || *n == 0);
- for (i = 0; i < *n; i++) {
+ for (size_t i = 0; i < *n; i++) {
free(m[i].source);
free(m[i].destination);
mount_options_free_all(m[i].mount_options);
}
void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n) {
- size_t i;
-
assert(t || n == 0);
- for (i = 0; i < n; i++) {
+ for (size_t i = 0; i < n; i++) {
free(t[i].path);
free(t[i].options);
}
PROTECT_HOME_READ_ONLY,
PROTECT_HOME_TMPFS,
_PROTECT_HOME_MAX,
- _PROTECT_HOME_INVALID = -1
+ _PROTECT_HOME_INVALID = -EINVAL,
} ProtectHome;
typedef enum NamespaceType {
NAMESPACE_PID,
NAMESPACE_NET,
_NAMESPACE_TYPE_MAX,
- _NAMESPACE_TYPE_INVALID = -1,
+ _NAMESPACE_TYPE_INVALID = -EINVAL,
} NamespaceType;
typedef enum ProtectSystem {
PROTECT_SYSTEM_FULL,
PROTECT_SYSTEM_STRICT,
_PROTECT_SYSTEM_MAX,
- _PROTECT_SYSTEM_INVALID = -1
+ _PROTECT_SYSTEM_INVALID = -EINVAL,
} ProtectSystem;
typedef enum ProtectProc {
PROTECT_PROC_INVISIBLE, /* hidepid=invisible */
PROTECT_PROC_PTRACEABLE, /* hidepid=ptraceable */
_PROTECT_PROC_MAX,
- _PROTECT_PROC_INVALID = -1,
+ _PROTECT_PROC_INVALID = -EINVAL,
} ProtectProc;
typedef enum ProcSubset {
PROC_SUBSET_ALL,
PROC_SUBSET_PID, /* subset=pid */
_PROC_SUBSET_MAX,
- _PROC_SUBSET_INVALID = -1,
+ _PROC_SUBSET_INVALID = -EINVAL,
} ProcSubset;
struct NamespaceInfo {
char **read_write_paths,
char **read_only_paths,
char **inaccessible_paths,
+ char **exec_paths,
+ char **no_exec_paths,
char **empty_directories,
const BindMount *bind_mounts,
size_t n_bind_mounts,
const char *root_verity,
const char *propagate_dir,
const char *incoming_dir,
+ const char *notify_socket,
DissectImageFlags dissected_image_flags,
char **error_path);
#define RUN_SYSTEMD_EMPTY "/run/systemd/empty"
-static inline void namespace_cleanup_tmpdir(char *p) {
+static inline char* namespace_cleanup_tmpdir(char *p) {
PROTECT_ERRNO;
if (!streq_ptr(p, RUN_SYSTEMD_EMPTY))
(void) rmdir(p);
- free(p);
+ return mfree(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, namespace_cleanup_tmpdir);
send_interface="org.freedesktop.systemd1.Manager"
send_member="BindMountUnit"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="MountImageUnit"/>
+
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="KillUnit"/>
send_interface="org.freedesktop.systemd1.Service"
send_member="BindMount"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Service"
+ send_member="MountImage"/>
+
<!-- Managed via polkit or other criteria: org.freedesktop.systemd1.Scope interface -->
<allow send_destination="org.freedesktop.systemd1"
PATH_CHANGED,
PATH_MODIFIED,
_PATH_TYPE_MAX,
- _PATH_TYPE_INVALID = -1
+ _PATH_TYPE_INVALID = -EINVAL,
} PathType;
typedef struct PathSpec {
PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
_PATH_RESULT_MAX,
- _PATH_RESULT_INVALID = -1
+ _PATH_RESULT_INVALID = -EINVAL,
} PathResult;
struct Path {
SCOPE_FAILURE_RESOURCES,
SCOPE_FAILURE_TIMEOUT,
_SCOPE_RESULT_MAX,
- _SCOPE_RESULT_INVALID = -1
+ _SCOPE_RESULT_INVALID = -EINVAL,
} ScopeResult;
struct Scope {
unit_notify(UNIT(s), table[old_state], table[state],
(s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) |
- (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0) |
- (s->result == SERVICE_SKIP_CONDITION ? UNIT_NOTIFY_SKIP_CONDITION : 0));
+ (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0));
}
static usec_t service_coldplug_timeout(Service *s) {
if (!our_env)
return -ENOMEM;
- if (service_exec_needs_notify_socket(s, flags))
+ if (service_exec_needs_notify_socket(s, flags)) {
if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0)
return -ENOMEM;
+ exec_params.notify_socket = UNIT(s)->manager->notify_socket;
+ }
+
if (s->main_pid > 0)
if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0)
return -ENOMEM;
STATE_EXEC_COMMAND_PATH,
STATE_EXEC_COMMAND_ARGS,
_STATE_EXEC_COMMAND_MAX,
- _STATE_EXEC_COMMAND_INVALID = -1,
+ _STATE_EXEC_COMMAND_INVALID = -EINVAL,
} state;
assert(s);
case STATE_EXEC_COMMAND_TYPE:
id = service_exec_command_from_string(arg);
if (id < 0)
- return -EINVAL;
+ return id;
state = STATE_EXEC_COMMAND_INDEX;
break;
case STATE_EXEC_COMMAND_INDEX:
r = safe_atou(arg, &idx);
if (r < 0)
- return -EINVAL;
+ return r;
state = STATE_EXEC_COMMAND_PATH;
break;
} else if (s->control_pid == pid) {
s->control_pid = 0;
- /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */
- if (f == SERVICE_FAILURE_EXIT_CODE && s->state == SERVICE_CONDITION && status < 255)
- f = SERVICE_SKIP_CONDITION;
-
if (s->control_command) {
exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
f = SERVICE_SUCCESS;
}
+ /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */
+ if (s->state == SERVICE_CONDITION) {
+ if (f == SERVICE_FAILURE_EXIT_CODE && status < 255) {
+ UNIT(s)->condition_result = false;
+ f = SERVICE_SKIP_CONDITION;
+ } else if (f == SERVICE_SUCCESS)
+ UNIT(s)->condition_result = true;
+ }
+
unit_log_process_exit(
u,
"Control process",
},
.finished_start_job = {
[JOB_FAILED] = "Failed to start %s.",
- [JOB_SKIPPED] = "Skipped %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Stopped %s.",
SERVICE_RESTART_ON_ABORT,
SERVICE_RESTART_ALWAYS,
_SERVICE_RESTART_MAX,
- _SERVICE_RESTART_INVALID = -1
+ _SERVICE_RESTART_INVALID = -EINVAL,
} ServiceRestart;
typedef enum ServiceType {
SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */
SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */
_SERVICE_TYPE_MAX,
- _SERVICE_TYPE_INVALID = -1
+ _SERVICE_TYPE_INVALID = -EINVAL,
} ServiceType;
typedef enum ServiceExecCommand {
SERVICE_EXEC_STOP,
SERVICE_EXEC_STOP_POST,
_SERVICE_EXEC_COMMAND_MAX,
- _SERVICE_EXEC_COMMAND_INVALID = -1
+ _SERVICE_EXEC_COMMAND_INVALID = -EINVAL,
} ServiceExecCommand;
typedef enum NotifyState {
NOTIFY_RELOADING,
NOTIFY_STOPPING,
_NOTIFY_STATE_MAX,
- _NOTIFY_STATE_INVALID = -1
+ _NOTIFY_STATE_INVALID = -EINVAL,
} NotifyState;
/* The values of this enum are referenced in man/systemd.exec.xml and src/shared/bus-unit-util.c.
SERVICE_FAILURE_OOM_KILL,
SERVICE_SKIP_CONDITION,
_SERVICE_RESULT_MAX,
- _SERVICE_RESULT_INVALID = -1
+ _SERVICE_RESULT_INVALID = -EINVAL,
} ServiceResult;
typedef enum ServiceTimeoutFailureMode {
SERVICE_TIMEOUT_ABORT,
SERVICE_TIMEOUT_KILL,
_SERVICE_TIMEOUT_FAILURE_MODE_MAX,
- _SERVICE_TIMEOUT_FAILURE_MODE_INVALID = -1
+ _SERVICE_TIMEOUT_FAILURE_MODE_INVALID = -EINVAL,
} ServiceTimeoutFailureMode;
struct ServiceFDStore {
SHOW_STATUS_TEMPORARY, /* enabled temporarily, may flip back to _AUTO */
SHOW_STATUS_YES, /* printing of status is enabled */
_SHOW_STATUS_MAX,
- _SHOW_STATUS_INVALID = -1,
+ _SHOW_STATUS_INVALID = -EINVAL,
} ShowStatus;
typedef enum ShowStatusFlags {
STATUS_UNIT_FORMAT_NAME,
STATUS_UNIT_FORMAT_DESCRIPTION,
_STATUS_UNIT_FORMAT_MAX,
- _STATUS_UNIT_FORMAT_INVALID = -1,
+ _STATUS_UNIT_FORMAT_INVALID = -EINVAL,
} StatusUnitFormat;
static inline bool show_status_on(ShowStatus s) {
if (s->remove_on_stop)
STRV_FOREACH(i, s->symlinks)
(void) unlink(*i);
+
+ /* Note that we don't return NULL here, since s has not been freed. */
}
static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
static int usbffs_dispatch_eps(SocketPort *p) {
_cleanup_free_ struct dirent **ent = NULL;
- size_t n, k, i;
+ size_t n, k;
int r;
r = scandir(p->path, &ent, usbffs_select_ep, alphasort);
p->n_auxiliary_fds = n;
k = 0;
- for (i = 0; i < n; ++i) {
+ for (size_t i = 0; i < n; ++i) {
_cleanup_free_ char *ep = NULL;
ep = path_make_absolute(ent[i]->d_name, p->path);
p->n_auxiliary_fds = 0;
clear:
- for (i = 0; i < n; ++i)
+ for (size_t i = 0; i < n; ++i)
free(ent[i]);
return r;
return fd;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(Socket *, socket_close_fds);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(Socket *, socket_close_fds, NULL);
-static int socket_open_fds(Socket *_s) {
- _cleanup_(socket_close_fdsp) Socket *s = _s;
+static int socket_open_fds(Socket *orig_s) {
+ _cleanup_(socket_close_fdsp) Socket *s = orig_s;
_cleanup_(mac_selinux_freep) char *label = NULL;
bool know_label = false;
SocketPort *p;
SOCKET_EXEC_STOP_PRE,
SOCKET_EXEC_STOP_POST,
_SOCKET_EXEC_COMMAND_MAX,
- _SOCKET_EXEC_COMMAND_INVALID = -1
+ _SOCKET_EXEC_COMMAND_INVALID = -EINVAL,
} SocketExecCommand;
typedef enum SocketType {
SOCKET_MQUEUE,
SOCKET_USB_FUNCTION,
_SOCKET_TYPE_MAX,
- _SOCKET_TYPE_INVALID = -1
+ _SOCKET_TYPE_INVALID = -EINVAL,
} SocketType;
typedef enum SocketResult {
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
_SOCKET_RESULT_MAX,
- _SOCKET_RESULT_INVALID = -1
+ _SOCKET_RESULT_INVALID = -EINVAL,
} SocketResult;
typedef struct SocketPort {
SOCKET_TIMESTAMPING_US, /* SO_TIMESTAMP */
SOCKET_TIMESTAMPING_NS, /* SO_TIMESTAMPNS */
_SOCKET_TIMESTAMPING_MAX,
- _SOCKET_TIMESTAMPING_INVALID = -1,
+ _SOCKET_TIMESTAMPING_INVALID = -EINVAL,
} SocketTimestamping;
struct Socket {
}
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
- unsigned i;
-
assert(m);
rewind(m->proc_swaps);
(void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
- for (i = 1;; i++) {
+ for (unsigned i = 1;; i++) {
_cleanup_free_ char *dev = NULL, *d = NULL;
int prio = 0, k;
SWAP_EXEC_ACTIVATE,
SWAP_EXEC_DEACTIVATE,
_SWAP_EXEC_COMMAND_MAX,
- _SWAP_EXEC_COMMAND_INVALID = -1
+ _SWAP_EXEC_COMMAND_INVALID = -EINVAL,
} SwapExecCommand;
typedef enum SwapResult {
SWAP_FAILURE_CORE_DUMP,
SWAP_FAILURE_START_LIMIT_HIT,
_SWAP_RESULT_MAX,
- _SWAP_RESULT_INVALID = -1
+ _SWAP_RESULT_INVALID = -EINVAL,
} SwapResult;
typedef struct SwapParameters {
};
int r;
- unsigned k;
assert(t);
/* Imply ordering for requirement dependencies on target units. Note that when the user created a contradicting
* ordering manually we won't add anything in here to make sure we don't create a loop. */
- for (k = 0; k < ELEMENTSOF(deps); k++) {
+ for (size_t k = 0; k < ELEMENTSOF(deps); k++) {
Unit *other;
void *v;
TIMER_UNIT_INACTIVE,
TIMER_CALENDAR,
_TIMER_BASE_MAX,
- _TIMER_BASE_INVALID = -1
+ _TIMER_BASE_INVALID = -EINVAL,
} TimerBase;
typedef struct TimerValue {
TIMER_FAILURE_RESOURCES,
TIMER_FAILURE_START_LIMIT_HIT,
_TIMER_RESULT_MAX,
- _TIMER_RESULT_INVALID = -1
+ _TIMER_RESULT_INVALID = -EINVAL,
} TimerResult;
struct Timer {
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bus-util.h"
+#include "dbus.h"
+#include "fileio-label.h"
+#include "fileio.h"
+#include "format-util.h"
+#include "parse-util.h"
+#include "serialize.h"
+#include "string-table.h"
+#include "unit-serialize.h"
+#include "user-util.h"
+
+static int serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
+ _cleanup_free_ char *s = NULL;
+ int r;
+
+ assert(f);
+ assert(key);
+
+ if (mask == 0)
+ return 0;
+
+ r = cg_mask_to_string(mask, &s);
+ if (r < 0)
+ return log_error_errno(r, "Failed to format cgroup mask: %m");
+
+ return serialize_item(f, key, s);
+}
+
+/* Make sure out values fit in the bitfield. */
+assert_cc(_UNIT_MARKER_MAX <= sizeof(((Unit){}).markers) * 8);
+
+static int serialize_markers(FILE *f, unsigned markers) {
+ assert(f);
+
+ if (markers == 0)
+ return 0;
+
+ fputs("markers=", f);
+ for (UnitMarker m = 0; m < _UNIT_MARKER_MAX; m++)
+ if (FLAGS_SET(markers, 1u << m))
+ fputs(unit_marker_to_string(m), f);
+ fputc('\n', f);
+ return 0;
+}
+
+static int deserialize_markers(Unit *u, const char *value) {
+ assert(u);
+ assert(value);
+ int r;
+
+ for (const char *p = value;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r <= 0)
+ return r;
+
+ UnitMarker m = unit_marker_from_string(word);
+ if (m < 0) {
+ log_unit_debug_errno(u, m, "Unknown unit marker \"%s\", ignoring.", word);
+ continue;
+ }
+
+ u->markers |= 1u << m;
+ }
+}
+
+static const char *const ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IP_INGRESS_BYTES] = "ip-accounting-ingress-bytes",
+ [CGROUP_IP_INGRESS_PACKETS] = "ip-accounting-ingress-packets",
+ [CGROUP_IP_EGRESS_BYTES] = "ip-accounting-egress-bytes",
+ [CGROUP_IP_EGRESS_PACKETS] = "ip-accounting-egress-packets",
+};
+
+static const char *const io_accounting_metric_field_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-base",
+ [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-base",
+ [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-base",
+ [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-base",
+};
+
+static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+ [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-last",
+ [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-last",
+ [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-last",
+ [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last",
+};
+
+int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
+ int r;
+
+ assert(u);
+ assert(f);
+ assert(fds);
+
+ if (unit_can_serialize(u)) {
+ r = UNIT_VTABLE(u)->serialize(u, f, fds);
+ if (r < 0)
+ return r;
+ }
+
+ (void) serialize_dual_timestamp(f, "state-change-timestamp", &u->state_change_timestamp);
+
+ (void) serialize_dual_timestamp(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
+ (void) serialize_dual_timestamp(f, "active-enter-timestamp", &u->active_enter_timestamp);
+ (void) serialize_dual_timestamp(f, "active-exit-timestamp", &u->active_exit_timestamp);
+ (void) serialize_dual_timestamp(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
+
+ (void) serialize_dual_timestamp(f, "condition-timestamp", &u->condition_timestamp);
+ (void) serialize_dual_timestamp(f, "assert-timestamp", &u->assert_timestamp);
+
+ if (dual_timestamp_is_set(&u->condition_timestamp))
+ (void) serialize_bool(f, "condition-result", u->condition_result);
+
+ if (dual_timestamp_is_set(&u->assert_timestamp))
+ (void) serialize_bool(f, "assert-result", u->assert_result);
+
+ (void) serialize_bool(f, "transient", u->transient);
+ (void) serialize_bool(f, "in-audit", u->in_audit);
+
+ (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id);
+ (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max);
+ (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields);
+ (void) serialize_bool(f, "exported-log-rate-limit-interval", u->exported_log_ratelimit_interval);
+ (void) serialize_bool(f, "exported-log-rate-limit-burst", u->exported_log_ratelimit_burst);
+
+ (void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base);
+ if (u->cpu_usage_last != NSEC_INFINITY)
+ (void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last);
+
+ if (u->managed_oom_kill_last > 0)
+ (void) serialize_item_format(f, "managed-oom-kill-last", "%" PRIu64, u->managed_oom_kill_last);
+
+ if (u->oom_kill_last > 0)
+ (void) serialize_item_format(f, "oom-kill-last", "%" PRIu64, u->oom_kill_last);
+
+ for (CGroupIOAccountingMetric im = 0; im < _CGROUP_IO_ACCOUNTING_METRIC_MAX; im++) {
+ (void) serialize_item_format(f, io_accounting_metric_field_base[im], "%" PRIu64, u->io_accounting_base[im]);
+
+ if (u->io_accounting_last[im] != UINT64_MAX)
+ (void) serialize_item_format(f, io_accounting_metric_field_last[im], "%" PRIu64, u->io_accounting_last[im]);
+ }
+
+ if (u->cgroup_path)
+ (void) serialize_item(f, "cgroup", u->cgroup_path);
+
+ (void) serialize_bool(f, "cgroup-realized", u->cgroup_realized);
+ (void) serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
+ (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
+ (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
+
+ if (uid_is_valid(u->ref_uid))
+ (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
+ if (gid_is_valid(u->ref_gid))
+ (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid);
+
+ if (!sd_id128_is_null(u->invocation_id))
+ (void) serialize_item_format(f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id));
+
+ (void) serialize_item_format(f, "freezer-state", "%s", freezer_state_to_string(unit_freezer_state(u)));
+ (void) serialize_markers(f, u->markers);
+
+ bus_track_serialize(u->bus_track, f, "ref");
+
+ for (CGroupIPAccountingMetric m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) {
+ uint64_t v;
+
+ r = unit_get_ip_accounting(u, m, &v);
+ if (r >= 0)
+ (void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v);
+ }
+
+ if (serialize_jobs) {
+ if (u->job) {
+ fputs("job\n", f);
+ job_serialize(u->job, f);
+ }
+
+ if (u->nop_job) {
+ fputs("job\n", f);
+ job_serialize(u->nop_job, f);
+ }
+ }
+
+ /* End marker */
+ fputc('\n', f);
+ return 0;
+}
+
+static int unit_deserialize_job(Unit *u, FILE *f) {
+ _cleanup_(job_freep) Job *j = NULL;
+ int r;
+
+ assert(u);
+ assert(f);
+
+ j = job_new_raw(u);
+ if (!j)
+ return log_oom();
+
+ r = job_deserialize(j, f);
+ if (r < 0)
+ return r;
+
+ r = job_install_deserialized(j);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(j);
+ return 0;
+}
+
+#define MATCH_DESERIALIZE(key, l, v, parse_func, target) \
+ ({ \
+ bool _deserialize_matched = streq(l, key); \
+ if (_deserialize_matched) { \
+ int _deserialize_r = parse_func(v); \
+ if (_deserialize_r < 0) \
+ log_unit_debug_errno(u, _deserialize_r, \
+ "Failed to parse \"%s=%s\", ignoring.", l, v); \
+ else \
+ target = _deserialize_r; \
+ }; \
+ _deserialize_matched; \
+ })
+
+#define MATCH_DESERIALIZE_IMMEDIATE(key, l, v, parse_func, target) \
+ ({ \
+ bool _deserialize_matched = streq(l, key); \
+ if (_deserialize_matched) { \
+ int _deserialize_r = parse_func(v, &target); \
+ if (_deserialize_r < 0) \
+ log_unit_debug_errno(u, _deserialize_r, \
+ "Failed to parse \"%s=%s\", ignoring", l, v); \
+ }; \
+ _deserialize_matched; \
+ })
+
+int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
+ int r;
+
+ assert(u);
+ assert(f);
+ assert(fds);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ char *l, *v;
+ ssize_t m;
+ size_t k;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read serialization line: %m");
+ if (r == 0) /* eof */
+ break;
+
+ l = strstrip(line);
+ if (isempty(l)) /* End marker */
+ break;
+
+ k = strcspn(l, "=");
+
+ if (l[k] == '=') {
+ l[k] = 0;
+ v = l+k+1;
+ } else
+ v = l+k;
+
+ if (streq(l, "job")) {
+ if (v[0] == '\0') {
+ /* New-style serialized job */
+ r = unit_deserialize_job(u, f);
+ if (r < 0)
+ return r;
+ } else /* Legacy for pre-44 */
+ log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
+ continue;
+ } else if (streq(l, "state-change-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->state_change_timestamp);
+ continue;
+ } else if (streq(l, "inactive-exit-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->inactive_exit_timestamp);
+ continue;
+ } else if (streq(l, "active-enter-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->active_enter_timestamp);
+ continue;
+ } else if (streq(l, "active-exit-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->active_exit_timestamp);
+ continue;
+ } else if (streq(l, "inactive-enter-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->inactive_enter_timestamp);
+ continue;
+ } else if (streq(l, "condition-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->condition_timestamp);
+ continue;
+ } else if (streq(l, "assert-timestamp")) {
+ (void) deserialize_dual_timestamp(v, &u->assert_timestamp);
+ continue;
+
+ } else if (MATCH_DESERIALIZE("condition-result", l, v, parse_boolean, u->condition_result))
+ continue;
+
+ else if (MATCH_DESERIALIZE("assert-result", l, v, parse_boolean, u->assert_result))
+ continue;
+
+ else if (MATCH_DESERIALIZE("transient", l, v, parse_boolean, u->transient))
+ continue;
+
+ else if (MATCH_DESERIALIZE("in-audit", l, v, parse_boolean, u->in_audit))
+ continue;
+
+ else if (MATCH_DESERIALIZE("exported-invocation-id", l, v, parse_boolean, u->exported_invocation_id))
+ continue;
+
+ else if (MATCH_DESERIALIZE("exported-log-level-max", l, v, parse_boolean, u->exported_log_level_max))
+ continue;
+
+ else if (MATCH_DESERIALIZE("exported-log-extra-fields", l, v, parse_boolean, u->exported_log_extra_fields))
+ continue;
+
+ else if (MATCH_DESERIALIZE("exported-log-rate-limit-interval", l, v, parse_boolean, u->exported_log_ratelimit_interval))
+ continue;
+
+ else if (MATCH_DESERIALIZE("exported-log-rate-limit-burst", l, v, parse_boolean, u->exported_log_ratelimit_burst))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("cpu-usage-base", l, v, safe_atou64, u->cpu_usage_base) ||
+ MATCH_DESERIALIZE_IMMEDIATE("cpuacct-usage-base", l, v, safe_atou64, u->cpu_usage_base))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("cpu-usage-last", l, v, safe_atou64, u->cpu_usage_last))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("managed-oom-kill-last", l, v, safe_atou64, u->managed_oom_kill_last))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("oom-kill-last", l, v, safe_atou64, u->oom_kill_last))
+ continue;
+
+ else if (streq(l, "cgroup")) {
+ r = unit_set_cgroup_path(u, v);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v);
+
+ (void) unit_watch_cgroup(u);
+ (void) unit_watch_cgroup_memory(u);
+
+ continue;
+
+ } else if (MATCH_DESERIALIZE("cgroup-realized", l, v, parse_boolean, u->cgroup_realized))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-realized-mask", l, v, cg_mask_from_string, u->cgroup_realized_mask))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-enabled-mask", l, v, cg_mask_from_string, u->cgroup_enabled_mask))
+ continue;
+
+ else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-invalidated-mask", l, v, cg_mask_from_string, u->cgroup_invalidated_mask))
+ continue;
+
+ else if (streq(l, "ref-uid")) {
+ uid_t uid;
+
+ r = parse_uid(v, &uid);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
+ else
+ unit_ref_uid_gid(u, uid, GID_INVALID);
+ continue;
+
+ } else if (streq(l, "ref-gid")) {
+ gid_t gid;
+
+ r = parse_gid(v, &gid);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
+ else
+ unit_ref_uid_gid(u, UID_INVALID, gid);
+ continue;
+
+ } else if (streq(l, "ref")) {
+ r = strv_extend(&u->deserialized_refs, v);
+ if (r < 0)
+ return log_oom();
+ continue;
+
+ } else if (streq(l, "invocation-id")) {
+ sd_id128_t id;
+
+ r = sd_id128_from_string(v, &id);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
+ else {
+ r = unit_set_invocation_id(u, id);
+ if (r < 0)
+ log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m");
+ }
+
+ continue;
+
+ } else if (MATCH_DESERIALIZE("freezer-state", l, v, freezer_state_from_string, u->freezer_state))
+ continue;
+
+ else if (streq(l, "markers")) {
+ r = deserialize_markers(u, v);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to deserialize \"%s=%s\", ignoring: %m", l, v);
+ continue;
+ }
+
+ /* Check if this is an IP accounting metric serialization field */
+ m = string_table_lookup(ip_accounting_metric_field, ELEMENTSOF(ip_accounting_metric_field), l);
+ if (m >= 0) {
+ uint64_t c;
+
+ r = safe_atou64(v, &c);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse IP accounting value %s, ignoring.", v);
+ else
+ u->ip_accounting_extra[m] = c;
+ continue;
+ }
+
+ m = string_table_lookup(io_accounting_metric_field_base, ELEMENTSOF(io_accounting_metric_field_base), l);
+ if (m >= 0) {
+ uint64_t c;
+
+ r = safe_atou64(v, &c);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse IO accounting base value %s, ignoring.", v);
+ else
+ u->io_accounting_base[m] = c;
+ continue;
+ }
+
+ m = string_table_lookup(io_accounting_metric_field_last, ELEMENTSOF(io_accounting_metric_field_last), l);
+ if (m >= 0) {
+ uint64_t c;
+
+ r = safe_atou64(v, &c);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse IO accounting last value %s, ignoring.", v);
+ else
+ u->io_accounting_last[m] = c;
+ continue;
+ }
+
+ if (unit_can_serialize(u)) {
+ r = exec_runtime_deserialize_compat(u, l, v, fds);
+ if (r < 0) {
+ log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
+ continue;
+ }
+
+ /* Returns positive if key was handled by the call */
+ if (r > 0)
+ continue;
+
+ r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
+ if (r < 0)
+ log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
+ }
+ }
+
+ /* Versions before 228 did not carry a state change timestamp. In this case, take the current
+ * time. This is useful, so that timeouts based on this timestamp don't trigger too early, and is
+ * in-line with the logic from before 228 where the base for timeouts was not persistent across
+ * reboots. */
+
+ if (!dual_timestamp_is_set(&u->state_change_timestamp))
+ dual_timestamp_get(&u->state_change_timestamp);
+
+ /* Let's make sure that everything that is deserialized also gets any potential new cgroup settings
+ * applied after we are done. For that we invalidate anything already realized, so that we can
+ * realize it again. */
+ unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
+ unit_invalidate_cgroup_bpf(u);
+
+ return 0;
+}
+
+int unit_deserialize_skip(FILE *f) {
+ int r;
+ assert(f);
+
+ /* Skip serialized data for this unit. We don't know what it is. */
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ char *l;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read serialization line: %m");
+ if (r == 0)
+ return 0;
+
+ l = strstrip(line);
+
+ /* End marker */
+ if (isempty(l))
+ return 1;
+ }
+}
+
+static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependencyMask mask, bool *space) {
+ const struct {
+ UnitDependencyMask mask;
+ const char *name;
+ } table[] = {
+ { UNIT_DEPENDENCY_FILE, "file" },
+ { UNIT_DEPENDENCY_IMPLICIT, "implicit" },
+ { UNIT_DEPENDENCY_DEFAULT, "default" },
+ { UNIT_DEPENDENCY_UDEV, "udev" },
+ { UNIT_DEPENDENCY_PATH, "path" },
+ { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" },
+ { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT, "mountinfo-default" },
+ { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" },
+ };
+
+ assert(f);
+ assert(kind);
+ assert(space);
+
+ for (size_t i = 0; i < ELEMENTSOF(table); i++) {
+
+ if (mask == 0)
+ break;
+
+ if (FLAGS_SET(mask, table[i].mask)) {
+ if (*space)
+ fputc(' ', f);
+ else
+ *space = true;
+
+ fputs(kind, f);
+ fputs("-", f);
+ fputs(table[i].name, f);
+
+ mask &= ~table[i].mask;
+ }
+ }
+
+ assert(mask == 0);
+}
+
+void unit_dump(Unit *u, FILE *f, const char *prefix) {
+ char *t, **j;
+ const char *prefix2;
+ char timestamp[5][FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX];
+ Unit *following;
+ _cleanup_set_free_ Set *following_set = NULL;
+ CGroupMask m;
+ int r;
+
+ assert(u);
+ assert(u->type >= 0);
+
+ prefix = strempty(prefix);
+ prefix2 = strjoina(prefix, "\t");
+
+ fprintf(f,
+ "%s-> Unit %s:\n",
+ prefix, u->id);
+
+ SET_FOREACH(t, u->aliases)
+ fprintf(f, "%s\tAlias: %s\n", prefix, t);
+
+ fprintf(f,
+ "%s\tDescription: %s\n"
+ "%s\tInstance: %s\n"
+ "%s\tUnit Load State: %s\n"
+ "%s\tUnit Active State: %s\n"
+ "%s\tState Change Timestamp: %s\n"
+ "%s\tInactive Exit Timestamp: %s\n"
+ "%s\tActive Enter Timestamp: %s\n"
+ "%s\tActive Exit Timestamp: %s\n"
+ "%s\tInactive Enter Timestamp: %s\n"
+ "%s\tMay GC: %s\n"
+ "%s\tNeed Daemon Reload: %s\n"
+ "%s\tTransient: %s\n"
+ "%s\tPerpetual: %s\n"
+ "%s\tGarbage Collection Mode: %s\n"
+ "%s\tSlice: %s\n"
+ "%s\tCGroup: %s\n"
+ "%s\tCGroup realized: %s\n",
+ prefix, unit_description(u),
+ prefix, strna(u->instance),
+ prefix, unit_load_state_to_string(u->load_state),
+ prefix, unit_active_state_to_string(unit_active_state(u)),
+ prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->state_change_timestamp.realtime)),
+ prefix, strna(format_timestamp(timestamp[1], sizeof(timestamp[1]), u->inactive_exit_timestamp.realtime)),
+ prefix, strna(format_timestamp(timestamp[2], sizeof(timestamp[2]), u->active_enter_timestamp.realtime)),
+ prefix, strna(format_timestamp(timestamp[3], sizeof(timestamp[3]), u->active_exit_timestamp.realtime)),
+ prefix, strna(format_timestamp(timestamp[4], sizeof(timestamp[4]), u->inactive_enter_timestamp.realtime)),
+ prefix, yes_no(unit_may_gc(u)),
+ prefix, yes_no(unit_need_daemon_reload(u)),
+ prefix, yes_no(u->transient),
+ prefix, yes_no(u->perpetual),
+ prefix, collect_mode_to_string(u->collect_mode),
+ prefix, strna(unit_slice_name(u)),
+ prefix, strna(u->cgroup_path),
+ prefix, yes_no(u->cgroup_realized));
+
+ if (u->markers != 0) {
+ fprintf(f, "%s\tMarkers:", prefix);
+
+ for (UnitMarker marker = 0; marker < _UNIT_MARKER_MAX; marker++)
+ if (FLAGS_SET(u->markers, 1u << marker))
+ fprintf(f, " %s", unit_marker_to_string(marker));
+ fputs("\n", f);
+ }
+
+ if (u->cgroup_realized_mask != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
+ fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
+ }
+
+ if (u->cgroup_enabled_mask != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(u->cgroup_enabled_mask, &s);
+ fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
+ }
+
+ m = unit_get_own_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
+ }
+
+ m = unit_get_members_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
+ }
+
+ m = unit_get_delegate_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s));
+ }
+
+ if (!sd_id128_is_null(u->invocation_id))
+ fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n",
+ prefix, SD_ID128_FORMAT_VAL(u->invocation_id));
+
+ STRV_FOREACH(j, u->documentation)
+ fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
+
+ following = unit_following(u);
+ if (following)
+ fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
+
+ r = unit_following_set(u, &following_set);
+ if (r >= 0) {
+ Unit *other;
+
+ SET_FOREACH(other, following_set)
+ fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id);
+ }
+
+ if (u->fragment_path)
+ fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
+
+ if (u->source_path)
+ fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
+
+ STRV_FOREACH(j, u->dropin_paths)
+ fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
+
+ if (u->failure_action != EMERGENCY_ACTION_NONE)
+ fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action));
+ if (u->failure_action_exit_status >= 0)
+ fprintf(f, "%s\tFailure Action Exit Status: %i\n", prefix, u->failure_action_exit_status);
+ if (u->success_action != EMERGENCY_ACTION_NONE)
+ fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action));
+ if (u->success_action_exit_status >= 0)
+ fprintf(f, "%s\tSuccess Action Exit Status: %i\n", prefix, u->success_action_exit_status);
+
+ if (u->job_timeout != USEC_INFINITY)
+ fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
+
+ if (u->job_timeout_action != EMERGENCY_ACTION_NONE)
+ fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action));
+
+ if (u->job_timeout_reboot_arg)
+ fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg);
+
+ condition_dump_list(u->conditions, f, prefix, condition_type_to_string);
+ condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
+
+ if (dual_timestamp_is_set(&u->condition_timestamp))
+ fprintf(f,
+ "%s\tCondition Timestamp: %s\n"
+ "%s\tCondition Result: %s\n",
+ prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->condition_timestamp.realtime)),
+ prefix, yes_no(u->condition_result));
+
+ if (dual_timestamp_is_set(&u->assert_timestamp))
+ fprintf(f,
+ "%s\tAssert Timestamp: %s\n"
+ "%s\tAssert Result: %s\n",
+ prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->assert_timestamp.realtime)),
+ prefix, yes_no(u->assert_result));
+
+ for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
+ UnitDependencyInfo di;
+ Unit *other;
+
+ HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) {
+ bool space = false;
+
+ fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id);
+
+ print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
+ print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
+
+ fputs(")\n", f);
+ }
+ }
+
+ if (!hashmap_isempty(u->requires_mounts_for)) {
+ UnitDependencyInfo di;
+ const char *path;
+
+ HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) {
+ bool space = false;
+
+ fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path);
+
+ print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
+ print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
+
+ fputs(")\n", f);
+ }
+ }
+
+ if (u->load_state == UNIT_LOADED) {
+
+ fprintf(f,
+ "%s\tStopWhenUnneeded: %s\n"
+ "%s\tRefuseManualStart: %s\n"
+ "%s\tRefuseManualStop: %s\n"
+ "%s\tDefaultDependencies: %s\n"
+ "%s\tOnFailureJobMode: %s\n"
+ "%s\tIgnoreOnIsolate: %s\n",
+ prefix, yes_no(u->stop_when_unneeded),
+ prefix, yes_no(u->refuse_manual_start),
+ prefix, yes_no(u->refuse_manual_stop),
+ prefix, yes_no(u->default_dependencies),
+ prefix, job_mode_to_string(u->on_failure_job_mode),
+ prefix, yes_no(u->ignore_on_isolate));
+
+ if (UNIT_VTABLE(u)->dump)
+ UNIT_VTABLE(u)->dump(u, f, prefix2);
+
+ } else if (u->load_state == UNIT_MERGED)
+ fprintf(f,
+ "%s\tMerged into: %s\n",
+ prefix, u->merged_into->id);
+ else if (u->load_state == UNIT_ERROR)
+ fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error));
+
+ for (const char *n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
+ fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
+
+ if (u->job)
+ job_dump(u->job, f, prefix2);
+
+ if (u->nop_job)
+ job_dump(u->nop_job, f, prefix2);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdio.h>
+
+#include "unit.h"
+#include "fdset.h"
+
+int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
+int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
+int unit_deserialize_skip(FILE *f);
+
+void unit_dump(Unit *u, FILE *f, const char *prefix);
#include "fileio.h"
#include "format-util.h"
#include "id128-util.h"
-#include "io-util.h"
#include "install.h"
+#include "io-util.h"
#include "label.h"
#include "load-dropin.h"
#include "load-fragment.h"
#include "macro.h"
#include "missing_audit.h"
#include "mkdir.h"
-#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
-#include "serialize.h"
#include "set.h"
#include "signal-util.h"
#include "sparse-endian.h"
static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency);
-Unit *unit_new(Manager *m, size_t size) {
+Unit* unit_new(Manager *m, size_t size) {
Unit *u;
assert(m);
cgroup_context_done(cc);
}
-void unit_free(Unit *u) {
+Unit* unit_free(Unit *u) {
char *t;
if (!u)
- return;
+ return NULL;
u->transient_file = safe_fclose(u->transient_file);
set_free_free(u->aliases);
free(u->id);
- free(u);
+ return mfree(u);
}
FreezerState unit_freezer_state(Unit *u) {
return unit_description(u);
}
-static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependencyMask mask, bool *space) {
- const struct {
- UnitDependencyMask mask;
- const char *name;
- } table[] = {
- { UNIT_DEPENDENCY_FILE, "file" },
- { UNIT_DEPENDENCY_IMPLICIT, "implicit" },
- { UNIT_DEPENDENCY_DEFAULT, "default" },
- { UNIT_DEPENDENCY_UDEV, "udev" },
- { UNIT_DEPENDENCY_PATH, "path" },
- { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" },
- { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT, "mountinfo-default" },
- { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" },
- };
-
- assert(f);
- assert(kind);
- assert(space);
-
- for (size_t i = 0; i < ELEMENTSOF(table); i++) {
-
- if (mask == 0)
- break;
-
- if (FLAGS_SET(mask, table[i].mask)) {
- if (*space)
- fputc(' ', f);
- else
- *space = true;
-
- fputs(kind, f);
- fputs("-", f);
- fputs(table[i].name, f);
-
- mask &= ~table[i].mask;
- }
- }
-
- assert(mask == 0);
-}
-
-void unit_dump(Unit *u, FILE *f, const char *prefix) {
- char *t, **j;
- const char *prefix2;
- char timestamp[5][FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX];
- Unit *following;
- _cleanup_set_free_ Set *following_set = NULL;
- CGroupMask m;
- int r;
-
- assert(u);
- assert(u->type >= 0);
-
- prefix = strempty(prefix);
- prefix2 = strjoina(prefix, "\t");
-
- fprintf(f,
- "%s-> Unit %s:\n",
- prefix, u->id);
-
- SET_FOREACH(t, u->aliases)
- fprintf(f, "%s\tAlias: %s\n", prefix, t);
-
- fprintf(f,
- "%s\tDescription: %s\n"
- "%s\tInstance: %s\n"
- "%s\tUnit Load State: %s\n"
- "%s\tUnit Active State: %s\n"
- "%s\tState Change Timestamp: %s\n"
- "%s\tInactive Exit Timestamp: %s\n"
- "%s\tActive Enter Timestamp: %s\n"
- "%s\tActive Exit Timestamp: %s\n"
- "%s\tInactive Enter Timestamp: %s\n"
- "%s\tMay GC: %s\n"
- "%s\tNeed Daemon Reload: %s\n"
- "%s\tTransient: %s\n"
- "%s\tPerpetual: %s\n"
- "%s\tGarbage Collection Mode: %s\n"
- "%s\tSlice: %s\n"
- "%s\tCGroup: %s\n"
- "%s\tCGroup realized: %s\n",
- prefix, unit_description(u),
- prefix, strna(u->instance),
- prefix, unit_load_state_to_string(u->load_state),
- prefix, unit_active_state_to_string(unit_active_state(u)),
- prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->state_change_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp[1], sizeof(timestamp[1]), u->inactive_exit_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp[2], sizeof(timestamp[2]), u->active_enter_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp[3], sizeof(timestamp[3]), u->active_exit_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp[4], sizeof(timestamp[4]), u->inactive_enter_timestamp.realtime)),
- prefix, yes_no(unit_may_gc(u)),
- prefix, yes_no(unit_need_daemon_reload(u)),
- prefix, yes_no(u->transient),
- prefix, yes_no(u->perpetual),
- prefix, collect_mode_to_string(u->collect_mode),
- prefix, strna(unit_slice_name(u)),
- prefix, strna(u->cgroup_path),
- prefix, yes_no(u->cgroup_realized));
-
- if (u->cgroup_realized_mask != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
- fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
- }
-
- if (u->cgroup_enabled_mask != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(u->cgroup_enabled_mask, &s);
- fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
- }
-
- m = unit_get_own_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
- }
-
- m = unit_get_members_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
- }
-
- m = unit_get_delegate_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s));
- }
-
- if (!sd_id128_is_null(u->invocation_id))
- fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n",
- prefix, SD_ID128_FORMAT_VAL(u->invocation_id));
-
- STRV_FOREACH(j, u->documentation)
- fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
-
- following = unit_following(u);
- if (following)
- fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
-
- r = unit_following_set(u, &following_set);
- if (r >= 0) {
- Unit *other;
-
- SET_FOREACH(other, following_set)
- fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id);
- }
-
- if (u->fragment_path)
- fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
-
- if (u->source_path)
- fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
-
- STRV_FOREACH(j, u->dropin_paths)
- fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
-
- if (u->failure_action != EMERGENCY_ACTION_NONE)
- fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action));
- if (u->failure_action_exit_status >= 0)
- fprintf(f, "%s\tFailure Action Exit Status: %i\n", prefix, u->failure_action_exit_status);
- if (u->success_action != EMERGENCY_ACTION_NONE)
- fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action));
- if (u->success_action_exit_status >= 0)
- fprintf(f, "%s\tSuccess Action Exit Status: %i\n", prefix, u->success_action_exit_status);
-
- if (u->job_timeout != USEC_INFINITY)
- fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
-
- if (u->job_timeout_action != EMERGENCY_ACTION_NONE)
- fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action));
-
- if (u->job_timeout_reboot_arg)
- fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg);
-
- condition_dump_list(u->conditions, f, prefix, condition_type_to_string);
- condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
-
- if (dual_timestamp_is_set(&u->condition_timestamp))
- fprintf(f,
- "%s\tCondition Timestamp: %s\n"
- "%s\tCondition Result: %s\n",
- prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->condition_timestamp.realtime)),
- prefix, yes_no(u->condition_result));
-
- if (dual_timestamp_is_set(&u->assert_timestamp))
- fprintf(f,
- "%s\tAssert Timestamp: %s\n"
- "%s\tAssert Result: %s\n",
- prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->assert_timestamp.realtime)),
- prefix, yes_no(u->assert_result));
-
- for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
- UnitDependencyInfo di;
- Unit *other;
-
- HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) {
- bool space = false;
-
- fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id);
-
- print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
- print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
-
- fputs(")\n", f);
- }
- }
-
- if (!hashmap_isempty(u->requires_mounts_for)) {
- UnitDependencyInfo di;
- const char *path;
-
- HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) {
- bool space = false;
-
- fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path);
-
- print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
- print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
-
- fputs(")\n", f);
- }
- }
-
- if (u->load_state == UNIT_LOADED) {
-
- fprintf(f,
- "%s\tStopWhenUnneeded: %s\n"
- "%s\tRefuseManualStart: %s\n"
- "%s\tRefuseManualStop: %s\n"
- "%s\tDefaultDependencies: %s\n"
- "%s\tOnFailureJobMode: %s\n"
- "%s\tIgnoreOnIsolate: %s\n",
- prefix, yes_no(u->stop_when_unneeded),
- prefix, yes_no(u->refuse_manual_start),
- prefix, yes_no(u->refuse_manual_stop),
- prefix, yes_no(u->default_dependencies),
- prefix, job_mode_to_string(u->on_failure_job_mode),
- prefix, yes_no(u->ignore_on_isolate));
-
- if (UNIT_VTABLE(u)->dump)
- UNIT_VTABLE(u)->dump(u, f, prefix2);
-
- } else if (u->load_state == UNIT_MERGED)
- fprintf(f,
- "%s\tMerged into: %s\n",
- prefix, u->merged_into->id);
- else if (u->load_state == UNIT_ERROR)
- fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error));
-
- for (const char *n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
- fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
-
- if (u->job)
- job_dump(u->job, f, prefix2);
-
- if (u->nop_job)
- job_dump(u->nop_job, f, prefix2);
-}
-
/* Common implementation for multiple backends */
int unit_load_fragment_and_dropin(Unit *u, bool fragment_required) {
int r;
if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
if (ns == UNIT_FAILED)
result = JOB_FAILED;
- else if (FLAGS_SET(flags, UNIT_NOTIFY_SKIP_CONDITION))
- result = JOB_SKIPPED;
else
result = JOB_DONE;
/* Make sure the cgroup and state files are always removed when we become inactive */
if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
+ SET_FLAG(u->markers,
+ (1u << UNIT_MARKER_NEEDS_RELOAD)|(1u << UNIT_MARKER_NEEDS_RESTART),
+ false);
unit_prune_cgroup(u);
unit_unlink_state_files(u);
- }
+ } else if (ns != os && ns == UNIT_RELOADING)
+ SET_FLAG(u->markers, 1u << UNIT_MARKER_NEEDS_RELOAD, false);
unit_update_on_console(u);
return unit_dbus_path_from_name(u->invocation_id_string);
}
-static int unit_set_invocation_id(Unit *u, sd_id128_t id) {
+int unit_set_invocation_id(Unit *u, sd_id128_t id) {
int r;
assert(u);
return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
}
-static int serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
- _cleanup_free_ char *s = NULL;
- int r;
-
- assert(f);
- assert(key);
-
- if (mask == 0)
- return 0;
-
- r = cg_mask_to_string(mask, &s);
- if (r < 0)
- return log_error_errno(r, "Failed to format cgroup mask: %m");
-
- return serialize_item(f, key, s);
-}
-
-static const char *const ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
- [CGROUP_IP_INGRESS_BYTES] = "ip-accounting-ingress-bytes",
- [CGROUP_IP_INGRESS_PACKETS] = "ip-accounting-ingress-packets",
- [CGROUP_IP_EGRESS_BYTES] = "ip-accounting-egress-bytes",
- [CGROUP_IP_EGRESS_PACKETS] = "ip-accounting-egress-packets",
-};
-
-static const char *const io_accounting_metric_field_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
- [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-base",
- [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-base",
- [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-base",
- [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-base",
-};
-
-static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
- [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-last",
- [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-last",
- [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-last",
- [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last",
-};
-
-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
- int r;
-
- assert(u);
- assert(f);
- assert(fds);
-
- if (unit_can_serialize(u)) {
- r = UNIT_VTABLE(u)->serialize(u, f, fds);
- if (r < 0)
- return r;
- }
-
- (void) serialize_dual_timestamp(f, "state-change-timestamp", &u->state_change_timestamp);
-
- (void) serialize_dual_timestamp(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
- (void) serialize_dual_timestamp(f, "active-enter-timestamp", &u->active_enter_timestamp);
- (void) serialize_dual_timestamp(f, "active-exit-timestamp", &u->active_exit_timestamp);
- (void) serialize_dual_timestamp(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
-
- (void) serialize_dual_timestamp(f, "condition-timestamp", &u->condition_timestamp);
- (void) serialize_dual_timestamp(f, "assert-timestamp", &u->assert_timestamp);
-
- if (dual_timestamp_is_set(&u->condition_timestamp))
- (void) serialize_bool(f, "condition-result", u->condition_result);
-
- if (dual_timestamp_is_set(&u->assert_timestamp))
- (void) serialize_bool(f, "assert-result", u->assert_result);
-
- (void) serialize_bool(f, "transient", u->transient);
- (void) serialize_bool(f, "in-audit", u->in_audit);
-
- (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id);
- (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max);
- (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields);
- (void) serialize_bool(f, "exported-log-rate-limit-interval", u->exported_log_ratelimit_interval);
- (void) serialize_bool(f, "exported-log-rate-limit-burst", u->exported_log_ratelimit_burst);
-
- (void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base);
- if (u->cpu_usage_last != NSEC_INFINITY)
- (void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last);
-
- if (u->managed_oom_kill_last > 0)
- (void) serialize_item_format(f, "managed-oom-kill-last", "%" PRIu64, u->managed_oom_kill_last);
-
- if (u->oom_kill_last > 0)
- (void) serialize_item_format(f, "oom-kill-last", "%" PRIu64, u->oom_kill_last);
-
- for (CGroupIOAccountingMetric im = 0; im < _CGROUP_IO_ACCOUNTING_METRIC_MAX; im++) {
- (void) serialize_item_format(f, io_accounting_metric_field_base[im], "%" PRIu64, u->io_accounting_base[im]);
-
- if (u->io_accounting_last[im] != UINT64_MAX)
- (void) serialize_item_format(f, io_accounting_metric_field_last[im], "%" PRIu64, u->io_accounting_last[im]);
- }
-
- if (u->cgroup_path)
- (void) serialize_item(f, "cgroup", u->cgroup_path);
-
- (void) serialize_bool(f, "cgroup-realized", u->cgroup_realized);
- (void) serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
- (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
- (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
-
- if (uid_is_valid(u->ref_uid))
- (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
- if (gid_is_valid(u->ref_gid))
- (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid);
-
- if (!sd_id128_is_null(u->invocation_id))
- (void) serialize_item_format(f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id));
-
- (void) serialize_item_format(f, "freezer-state", "%s", freezer_state_to_string(unit_freezer_state(u)));
-
- bus_track_serialize(u->bus_track, f, "ref");
-
- for (CGroupIPAccountingMetric m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) {
- uint64_t v;
-
- r = unit_get_ip_accounting(u, m, &v);
- if (r >= 0)
- (void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v);
- }
-
- if (serialize_jobs) {
- if (u->job) {
- fputs("job\n", f);
- job_serialize(u->job, f);
- }
-
- if (u->nop_job) {
- fputs("job\n", f);
- job_serialize(u->nop_job, f);
- }
- }
-
- /* End marker */
- fputc('\n', f);
- return 0;
-}
-
-static int unit_deserialize_job(Unit *u, FILE *f) {
- _cleanup_(job_freep) Job *j = NULL;
- int r;
-
- assert(u);
- assert(f);
-
- j = job_new_raw(u);
- if (!j)
- return log_oom();
-
- r = job_deserialize(j, f);
- if (r < 0)
- return r;
-
- r = job_install_deserialized(j);
- if (r < 0)
- return r;
-
- TAKE_PTR(j);
- return 0;
-}
-
-int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
- int r;
-
- assert(u);
- assert(f);
- assert(fds);
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
- char *l, *v;
- ssize_t m;
- size_t k;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return log_error_errno(r, "Failed to read serialization line: %m");
- if (r == 0) /* eof */
- break;
-
- l = strstrip(line);
- if (isempty(l)) /* End marker */
- break;
-
- k = strcspn(l, "=");
-
- if (l[k] == '=') {
- l[k] = 0;
- v = l+k+1;
- } else
- v = l+k;
-
- if (streq(l, "job")) {
- if (v[0] == '\0') {
- /* New-style serialized job */
- r = unit_deserialize_job(u, f);
- if (r < 0)
- return r;
- } else /* Legacy for pre-44 */
- log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
- continue;
- } else if (streq(l, "state-change-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->state_change_timestamp);
- continue;
- } else if (streq(l, "inactive-exit-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->inactive_exit_timestamp);
- continue;
- } else if (streq(l, "active-enter-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->active_enter_timestamp);
- continue;
- } else if (streq(l, "active-exit-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->active_exit_timestamp);
- continue;
- } else if (streq(l, "inactive-enter-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->inactive_enter_timestamp);
- continue;
- } else if (streq(l, "condition-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->condition_timestamp);
- continue;
- } else if (streq(l, "assert-timestamp")) {
- (void) deserialize_dual_timestamp(v, &u->assert_timestamp);
- continue;
- } else if (streq(l, "condition-result")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse condition result value %s, ignoring.", v);
- else
- u->condition_result = r;
-
- continue;
-
- } else if (streq(l, "assert-result")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse assert result value %s, ignoring.", v);
- else
- u->assert_result = r;
-
- continue;
-
- } else if (streq(l, "transient")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse transient bool %s, ignoring.", v);
- else
- u->transient = r;
-
- continue;
-
- } else if (streq(l, "in-audit")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse in-audit bool %s, ignoring.", v);
- else
- u->in_audit = r;
-
- continue;
-
- } else if (streq(l, "exported-invocation-id")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse exported invocation ID bool %s, ignoring.", v);
- else
- u->exported_invocation_id = r;
-
- continue;
-
- } else if (streq(l, "exported-log-level-max")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse exported log level max bool %s, ignoring.", v);
- else
- u->exported_log_level_max = r;
-
- continue;
-
- } else if (streq(l, "exported-log-extra-fields")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse exported log extra fields bool %s, ignoring.", v);
- else
- u->exported_log_extra_fields = r;
-
- continue;
-
- } else if (streq(l, "exported-log-rate-limit-interval")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse exported log rate limit interval %s, ignoring.", v);
- else
- u->exported_log_ratelimit_interval = r;
-
- continue;
-
- } else if (streq(l, "exported-log-rate-limit-burst")) {
-
- r = parse_boolean(v);
- if (r < 0)
- log_unit_debug(u, "Failed to parse exported log rate limit burst %s, ignoring.", v);
- else
- u->exported_log_ratelimit_burst = r;
-
- continue;
-
- } else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")) {
-
- r = safe_atou64(v, &u->cpu_usage_base);
- if (r < 0)
- log_unit_debug(u, "Failed to parse CPU usage base %s, ignoring.", v);
-
- continue;
-
- } else if (streq(l, "cpu-usage-last")) {
-
- r = safe_atou64(v, &u->cpu_usage_last);
- if (r < 0)
- log_unit_debug(u, "Failed to read CPU usage last %s, ignoring.", v);
-
- continue;
-
- } else if (streq(l, "managed-oom-kill-last")) {
-
- r = safe_atou64(v, &u->managed_oom_kill_last);
- if (r < 0)
- log_unit_debug(u, "Failed to read managed OOM kill last %s, ignoring.", v);
-
- continue;
-
- } else if (streq(l, "oom-kill-last")) {
-
- r = safe_atou64(v, &u->oom_kill_last);
- if (r < 0)
- log_unit_debug(u, "Failed to read OOM kill last %s, ignoring.", v);
-
- continue;
-
- } else if (streq(l, "cgroup")) {
-
- r = unit_set_cgroup_path(u, v);
- if (r < 0)
- log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v);
-
- (void) unit_watch_cgroup(u);
- (void) unit_watch_cgroup_memory(u);
-
- continue;
- } else if (streq(l, "cgroup-realized")) {
- int b;
-
- b = parse_boolean(v);
- if (b < 0)
- log_unit_debug(u, "Failed to parse cgroup-realized bool %s, ignoring.", v);
- else
- u->cgroup_realized = b;
-
- continue;
-
- } else if (streq(l, "cgroup-realized-mask")) {
-
- r = cg_mask_from_string(v, &u->cgroup_realized_mask);
- if (r < 0)
- log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v);
- continue;
-
- } else if (streq(l, "cgroup-enabled-mask")) {
-
- r = cg_mask_from_string(v, &u->cgroup_enabled_mask);
- if (r < 0)
- log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v);
- continue;
-
- } else if (streq(l, "cgroup-invalidated-mask")) {
-
- r = cg_mask_from_string(v, &u->cgroup_invalidated_mask);
- if (r < 0)
- log_unit_debug(u, "Failed to parse cgroup-invalidated-mask %s, ignoring.", v);
- continue;
-
- } else if (streq(l, "ref-uid")) {
- uid_t uid;
-
- r = parse_uid(v, &uid);
- if (r < 0)
- log_unit_debug(u, "Failed to parse referenced UID %s, ignoring.", v);
- else
- unit_ref_uid_gid(u, uid, GID_INVALID);
-
- continue;
-
- } else if (streq(l, "ref-gid")) {
- gid_t gid;
-
- r = parse_gid(v, &gid);
- if (r < 0)
- log_unit_debug(u, "Failed to parse referenced GID %s, ignoring.", v);
- else
- unit_ref_uid_gid(u, UID_INVALID, gid);
-
- continue;
-
- } else if (streq(l, "ref")) {
-
- r = strv_extend(&u->deserialized_refs, v);
- if (r < 0)
- return log_oom();
-
- continue;
- } else if (streq(l, "invocation-id")) {
- sd_id128_t id;
-
- r = sd_id128_from_string(v, &id);
- if (r < 0)
- log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v);
- else {
- r = unit_set_invocation_id(u, id);
- if (r < 0)
- log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m");
- }
-
- continue;
- } else if (streq(l, "freezer-state")) {
- FreezerState s;
-
- s = freezer_state_from_string(v);
- if (s < 0)
- log_unit_debug(u, "Failed to deserialize freezer-state '%s', ignoring.", v);
- else
- u->freezer_state = s;
-
- continue;
- }
-
- /* Check if this is an IP accounting metric serialization field */
- m = string_table_lookup(ip_accounting_metric_field, ELEMENTSOF(ip_accounting_metric_field), l);
- if (m >= 0) {
- uint64_t c;
-
- r = safe_atou64(v, &c);
- if (r < 0)
- log_unit_debug(u, "Failed to parse IP accounting value %s, ignoring.", v);
- else
- u->ip_accounting_extra[m] = c;
- continue;
- }
-
- m = string_table_lookup(io_accounting_metric_field_base, ELEMENTSOF(io_accounting_metric_field_base), l);
- if (m >= 0) {
- uint64_t c;
-
- r = safe_atou64(v, &c);
- if (r < 0)
- log_unit_debug(u, "Failed to parse IO accounting base value %s, ignoring.", v);
- else
- u->io_accounting_base[m] = c;
- continue;
- }
-
- m = string_table_lookup(io_accounting_metric_field_last, ELEMENTSOF(io_accounting_metric_field_last), l);
- if (m >= 0) {
- uint64_t c;
-
- r = safe_atou64(v, &c);
- if (r < 0)
- log_unit_debug(u, "Failed to parse IO accounting last value %s, ignoring.", v);
- else
- u->io_accounting_last[m] = c;
- continue;
- }
-
- if (unit_can_serialize(u)) {
- r = exec_runtime_deserialize_compat(u, l, v, fds);
- if (r < 0) {
- log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
- continue;
- }
-
- /* Returns positive if key was handled by the call */
- if (r > 0)
- continue;
-
- r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
- if (r < 0)
- log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
- }
- }
-
- /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is
- * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from
- * before 228 where the base for timeouts was not persistent across reboots. */
-
- if (!dual_timestamp_is_set(&u->state_change_timestamp))
- dual_timestamp_get(&u->state_change_timestamp);
-
- /* Let's make sure that everything that is deserialized also gets any potential new cgroup settings applied
- * after we are done. For that we invalidate anything already realized, so that we can realize it again. */
- unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
- unit_invalidate_cgroup_bpf(u);
-
- return 0;
-}
-
-int unit_deserialize_skip(FILE *f) {
- int r;
- assert(f);
-
- /* Skip serialized data for this unit. We don't know what it is. */
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
- char *l;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return log_error_errno(r, "Failed to read serialization line: %m");
- if (r == 0)
- return 0;
-
- l = strstrip(line);
-
- /* End marker */
- if (isempty(l))
- return 1;
- }
-}
-
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
_cleanup_free_ char *e = NULL;
Unit *device;
"MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
- LOG_UNIT_MESSAGE(u, "Succeeded."));
+ LOG_UNIT_MESSAGE(u, "Deactivated successfully."));
}
void unit_log_failure(Unit *u, const char *result) {
#include <stdlib.h>
#include <unistd.h>
+#include "sd-id128.h"
+
#include "bpf-program.h"
#include "condition.h"
#include "emergency-action.h"
KILL_KILL,
KILL_WATCHDOG,
_KILL_OPERATION_MAX,
- _KILL_OPERATION_INVALID = -1
+ _KILL_OPERATION_INVALID = -EINVAL,
} KillOperation;
typedef enum CollectMode {
COLLECT_INACTIVE,
COLLECT_INACTIVE_OR_FAILED,
_COLLECT_MODE_MAX,
- _COLLECT_MODE_INVALID = -1,
+ _COLLECT_MODE_INVALID = -EINVAL,
} CollectMode;
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
UnitLoadState load_state;
Unit *merged_into;
- FreezerState freezer_state;
- sd_bus_message *pending_freezer_message;
-
char *id; /* The one special name that we use for identification */
char *instance;
/* If this is a transient unit we are currently writing, this is where we are writing it to */
FILE *transient_file;
+ /* Freezer state */
+ sd_bus_message *pending_freezer_message;
+ FreezerState freezer_state;
+
+ /* Job timeout and action to take */
+ EmergencyAction job_timeout_action;
+ usec_t job_timeout;
+ usec_t job_running_timeout;
+ char *job_timeout_reboot_arg;
+
/* If there is something to do with this unit, then this is the installed job for it */
Job *job;
sd_bus_track *bus_track;
char **deserialized_refs;
- /* Job timeout and action to take */
- usec_t job_timeout;
- usec_t job_running_timeout;
- bool job_running_timeout_set:1;
- EmergencyAction job_timeout_action;
- char *job_timeout_reboot_arg;
-
/* References to this */
LIST_HEAD(UnitRef, refs_by_target);
RateLimit start_ratelimit;
EmergencyAction start_limit_action;
+ /* The unit has been marked for reload, restart, etc. Stored as 1u << marker1 | 1u << marker2. */
+ unsigned markers;
+
/* What to do on failure or success */
EmergencyAction success_action, failure_action;
int success_action_exit_status, failure_action_exit_status;
bool sent_dbus_new_signal:1;
+ bool job_running_timeout_set:1;
+
bool in_audit:1;
bool on_console:1;
return hashmap_first_key(u->dependencies[UNIT_TRIGGERS]);
}
-Unit *unit_new(Manager *m, size_t size);
-void unit_free(Unit *u);
+Unit* unit_new(Manager *m, size_t size);
+Unit* unit_free(Unit *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret);
const char* unit_sub_state_to_string(Unit *u);
-void unit_dump(Unit *u, FILE *f, const char *prefix);
-
bool unit_can_reload(Unit *u) _pure_;
bool unit_can_start(Unit *u) _pure_;
bool unit_can_stop(Unit *u) _pure_;
typedef enum UnitNotifyFlags {
UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0,
UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
- UNIT_NOTIFY_SKIP_CONDITION = 1 << 2,
} UnitNotifyFlags;
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
bool unit_can_serialize(Unit *u) _pure_;
-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
-int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
-int unit_deserialize_skip(FILE *f);
-
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid);
+int unit_set_invocation_id(Unit *u, sd_id128_t id);
int unit_acquire_invocation_id(Unit *u);
bool unit_shall_confirm_spawn(Unit *u);
#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */
-struct vacuum_candidate {
+typedef struct VacuumCandidate {
unsigned n_files;
char *oldest_file;
usec_t oldest_mtime;
-};
+} VacuumCandidate;
-static void vacuum_candidate_free(struct vacuum_candidate *c) {
+static VacuumCandidate* vacuum_candidate_free(VacuumCandidate *c) {
if (!c)
- return;
+ return NULL;
free(c->oldest_file);
- free(c);
+ return mfree(c);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(VacuumCandidate*, vacuum_candidate_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free);
-
-static void vacuum_candidate_hashmap_free(Hashmap *h) {
- hashmap_free_with_destructor(h, vacuum_candidate_free);
+static Hashmap* vacuum_candidate_hashmap_free(Hashmap *h) {
+ return hashmap_free_with_destructor(h, vacuum_candidate_free);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free);
for (;;) {
_cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL;
- struct vacuum_candidate *worst = NULL;
+ VacuumCandidate *worst = NULL;
struct dirent *de;
uint64_t sum = 0;
rewinddir(d);
FOREACH_DIRENT(de, d, goto fail) {
- struct vacuum_candidate *c;
+ VacuumCandidate *c;
struct stat st;
uid_t uid;
usec_t t;
}
} else {
- _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL;
+ _cleanup_(vacuum_candidate_freep) VacuumCandidate *n = NULL;
- n = new0(struct vacuum_candidate, 1);
+ n = new0(VacuumCandidate, 1);
if (!n)
return log_oom();
COREDUMP_STORAGE_EXTERNAL,
COREDUMP_STORAGE_JOURNAL,
_COREDUMP_STORAGE_MAX,
- _COREDUMP_STORAGE_INVALID = -1
+ _COREDUMP_STORAGE_INVALID = -EINVAL,
} CoredumpStorage;
static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
};
int r = 0;
- unsigned i;
assert(fd >= 0);
/* Attach some metadata to coredumps via extended
* attributes. Just because we can. */
- for (i = 0; i < _META_MAX; i++) {
+ for (unsigned i = 0; i < _META_MAX; i++) {
int k;
if (isempty(context->meta[i]) || !xattrs[i])
}
static int save_context(Context *context, const struct iovec_wrapper *iovw) {
- unsigned n, i, count = 0;
+ unsigned count = 0;
const char *unit;
int r;
/* The context does not allocate any memory on its own */
- for (n = 0; n < iovw->count; n++) {
+ for (size_t n = 0; n < iovw->count; n++) {
struct iovec *iovec = iovw->iovec + n;
- for (i = 0; i < ELEMENTSOF(meta_field_names); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
char *p;
/* Note that these strings are NUL terminated, because we made sure that a
Context context = {};
struct iovec_wrapper iovw = {};
struct iovec iovec;
- int i, r;
+ int r;
assert(fd >= 0);
- log_setup_service();
+ log_setup();
log_debug("Processing coredump received on stdin...");
goto finish;
/* Make sure we received at least all fields we need. */
- for (i = 0; i < _META_MANDATORY_MAX; i++)
+ for (int i = 0; i < _META_MANDATORY_MAX; i++)
if (!context.meta[i]) {
r = log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"A mandatory argument (%i) has not been sent, aborting.",
.un.sun_path = "/run/systemd/coredump",
};
_cleanup_close_ int fd = -1;
- size_t i;
int r;
assert(iovw);
if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
return log_error_errno(errno, "Failed to connect to coredump service: %m");
- for (i = 0; i < iovw->count; i++) {
+ for (size_t i = 0; i < iovw->count; i++) {
struct msghdr mh = {
.msg_iov = iovw->iovec + i,
.msg_iovlen = 1,
int argc, char **argv) {
_cleanup_free_ char *free_timestamp = NULL;
- int i, r, signo;
+ int r, signo;
char *t;
/* We gather all metadata that were passed via argv[] into an array of iovecs that
"Not enough arguments passed by the kernel (%i, expected %i).",
argc, _META_ARGV_MAX);
- for (i = 0; i < _META_ARGV_MAX; i++) {
+ for (int i = 0; i < _META_ARGV_MAX; i++) {
t = argv[i];
Context context = {};
struct iovec_wrapper *iovw;
char *message;
- size_t i;
int r;
_cleanup_(journal_importer_cleanup) JournalImporter importer = JOURNAL_IMPORTER_INIT(STDIN_FILENO);
/* The imported iovecs are not supposed to be freed by us so let's store
* them at the end of the array so we can skip them while freeing the
* rest. */
- for (i = 0; i < importer.iovw.count; i++) {
+ for (size_t i = 0; i < importer.iovw.count; i++) {
struct iovec *iovec = importer.iovw.iovec + i;
iovw_put(iovw, iovec->iov_base, iovec->iov_len);
#include "compress.h"
#include "def.h"
#include "fd-util.h"
+#include "format-table.h"
#include "fs-util.h"
#include "glob-util.h"
#include "journal-internal.h"
#include "macro.h"
#include "main-func.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
static char **arg_debugger_args = NULL;
static const char *arg_directory = NULL;
static char **arg_file = NULL;
+static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
-static int arg_no_legend = false;
-static int arg_one = false;
+static int arg_legend = true;
+static size_t arg_rows_max = SIZE_MAX;
static const char* arg_output = NULL;
static bool arg_reverse = false;
static bool arg_quiet = false;
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] COMMAND ...\n\n"
- "%sList or retrieve coredumps from the journal.%s\n"
- "\nCommands:\n"
+ printf("%1$s [OPTIONS...] COMMAND ...\n\n"
+ "%5$sList or retrieve coredumps from the journal.%6$s\n"
+ "\n%3$sCommands:%4$s\n"
" list [MATCHES...] List available coredumps (default)\n"
" info [MATCHES...] Show detailed information about one or more coredumps\n"
" dump [MATCHES...] Print first matching coredump to stdout\n"
" debug [MATCHES...] Start a debugger for the first matching coredump\n"
- "\nOptions:\n"
+ "\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version string\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not print the column headers\n"
+ " --json=pretty|short|off\n"
+ " Generate JSON output\n"
" --debugger=DEBUGGER Use the given debugger\n"
" -A --debugger-arguments=ARGS Pass the given arguments to the debugger\n"
+ " -n INT Show maximum number of rows\n"
" -1 Show information about most recent entry only\n"
" -S --since=DATE Only print coredumps since the date\n"
" -U --until=DATE Only print coredumps until the date\n"
" --file=PATH Use journal file\n"
" -D --directory=DIR Use journal files from directory\n\n"
" -q --quiet Do not show info messages and privilege warning\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
+ ARG_JSON,
ARG_DEBUGGER,
ARG_FILE,
};
{ "since", required_argument, NULL, 'S' },
{ "until", required_argument, NULL, 'U' },
{ "quiet", no_argument, NULL, 'q' },
+ { "json", required_argument, NULL, ARG_JSON },
{}
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hA:o:F:1D:rS:U:q", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hA:o:F:1D:rS:U:qn:", options, NULL)) >= 0)
switch(c) {
case 'h':
return help();
break;
case ARG_NO_LEGEND:
- arg_no_legend = true;
+ arg_legend = false;
break;
case ARG_DEBUGGER:
break;
case '1':
- arg_one = true;
+ arg_rows_max = 1;
+ arg_reverse = true;
+ break;
+
+ case 'n': {
+ unsigned n;
+
+ r = safe_atou(optarg, &n);
+ if (r < 0 || n < 1)
+ return log_error_errno(r < 0 ? r : SYNTHETIC_ERRNO(EINVAL),
+ "Invalid numeric parameter to -n: %s", optarg);
+
+ arg_rows_max = n;
break;
+ }
case 'D':
arg_directory = optarg;
arg_quiet = true;
break;
+ case ARG_JSON:
+ r = parse_json_argument(optarg, &arg_json_format_flags);
+ if (r <= 0)
+ return r;
+
+ break;
+
case '?':
return -EINVAL;
continue; \
}
-static int print_list(FILE* file, sd_journal *j, int had_legend) {
+static void analyze_coredump_file(
+ const char *path,
+ const char **ret_state,
+ const char **ret_color,
+ uint64_t *ret_size) {
+
+ _cleanup_close_ int fd = -1;
+ struct stat st;
+ int r;
+
+ assert(path);
+ assert(ret_state);
+ assert(ret_color);
+ assert(ret_size);
+
+ fd = open(path, O_PATH|O_CLOEXEC);
+ if (fd < 0) {
+ if (errno == ENOENT) {
+ *ret_state = "missing";
+ *ret_color = ansi_grey();
+ *ret_size = UINT64_MAX;
+ return;
+ }
+
+ r = -errno;
+ } else
+ r = access_fd(fd, R_OK);
+ if (ERRNO_IS_PRIVILEGE(r)) {
+ *ret_state = "inaccessible";
+ *ret_color = ansi_highlight_yellow();
+ *ret_size = UINT64_MAX;
+ return;
+ }
+ if (r < 0)
+ goto error;
+
+ if (fstat(fd, &st) < 0)
+ goto error;
+
+ if (!S_ISREG(st.st_mode))
+ goto error;
+
+ *ret_state = "present";
+ *ret_color = NULL;
+ *ret_size = st.st_size;
+ return;
+
+error:
+ *ret_state = "error";
+ *ret_color = ansi_highlight_red();
+ *ret_size = UINT64_MAX;
+}
+
+static int print_list(FILE* file, sd_journal *j, Table *t) {
_cleanup_free_ char
*mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
*sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
*filename = NULL, *truncated = NULL, *coredump = NULL;
const void *d;
size_t l;
- usec_t t;
- char buf[FORMAT_TIMESTAMP_MAX];
- int r;
- const char *present;
+ usec_t ts;
+ int r, signal_as_int = 0;
+ const char *present = NULL, *color = NULL;
+ uint64_t size = UINT64_MAX;
bool normal_coredump;
+ uid_t uid_as_int = UID_INVALID;
+ gid_t gid_as_int = GID_INVALID;
+ pid_t pid_as_int = 0;
assert(file);
assert(j);
+ assert(t);
SD_JOURNAL_FOREACH_DATA(j, d, l) {
RETRIEVE(d, l, "MESSAGE_ID", mid);
RETRIEVE(d, l, "COREDUMP", coredump);
}
- if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) {
- log_warning("Empty coredump log entry");
- return -EINVAL;
- }
+ if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Empty coredump log entry");
- r = sd_journal_get_realtime_usec(j, &t);
+ (void) parse_uid(uid, &uid_as_int);
+ (void) parse_gid(gid, &gid_as_int);
+ (void) parse_pid(pid, &pid_as_int);
+ signal_as_int = signal_from_string(sgnl);
+
+ r = sd_journal_get_realtime_usec(j, &ts);
if (r < 0)
return log_error_errno(r, "Failed to get realtime timestamp: %m");
- format_timestamp(buf, sizeof(buf), t);
-
- if (!had_legend && !arg_no_legend)
- fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n",
- FORMAT_TIMESTAMP_WIDTH, "TIME",
- 6, "PID",
- 5, "UID",
- 5, "GID",
- 3, "SIG",
- 9, "COREFILE",
- "EXE");
-
normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR);
if (filename)
- if (access(filename, R_OK) == 0)
- present = "present";
- else if (errno == ENOENT)
- present = "missing";
- else
- present = "error";
+ analyze_coredump_file(filename, &present, &color, &size);
else if (coredump)
present = "journal";
- else if (normal_coredump)
+ else if (normal_coredump) {
present = "none";
- else
- present = "-";
+ color = ansi_grey();
+ } else
+ present = NULL;
- if (STR_IN_SET(present, "present", "journal") && truncated && parse_boolean(truncated) > 0)
+ if (STRPTR_IN_SET(present, "present", "journal") && truncated && parse_boolean(truncated) > 0)
present = "truncated";
- fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n",
- FORMAT_TIMESTAMP_WIDTH, buf,
- 6, strna(pid),
- 5, strna(uid),
- 5, strna(gid),
- 3, normal_coredump ? strna(sgnl) : "-",
- 9, present,
- strna(exe ?: (comm ?: cmdline)));
+ r = table_add_many(
+ t,
+ TABLE_TIMESTAMP, ts,
+ TABLE_PID, pid_as_int,
+ TABLE_UID, uid_as_int,
+ TABLE_GID, gid_as_int,
+ TABLE_SIGNAL, normal_coredump ? signal_as_int : 0,
+ TABLE_STRING, present,
+ TABLE_SET_COLOR, color,
+ TABLE_STRING, exe ?: comm ?: cmdline,
+ TABLE_SIZE, size);
+ if (r < 0)
+ return table_log_add_error(r);
return 0;
}
fprintf(file, " Hostname: %s\n", hostname);
if (filename) {
- bool inacc, trunc;
-
- inacc = access(filename, R_OK) < 0;
- trunc = truncated && parse_boolean(truncated) > 0;
-
- if (inacc || trunc)
- fprintf(file, " Storage: %s%s (%s%s%s)%s\n",
- ansi_highlight_red(),
- filename,
- inacc ? "inaccessible" : "",
- inacc && trunc ? ", " : "",
- trunc ? "truncated" : "",
- ansi_normal());
- else
- fprintf(file, " Storage: %s\n", filename);
- }
+ const char *state = NULL, *color = NULL;
+ uint64_t size = UINT64_MAX;
+ char buf[FORMAT_BYTES_MAX];
- else if (coredump)
+ analyze_coredump_file(filename, &state, &color, &size);
+
+ if (STRPTR_IN_SET(state, "present", "journal") && truncated && parse_boolean(truncated) > 0)
+ state = "truncated";
+
+ fprintf(file,
+ " Storage: %s%s (%s)%s\n",
+ strempty(color),
+ filename,
+ state,
+ ansi_normal());
+
+ if (size != UINT64_MAX)
+ fprintf(file,
+ " Disk Size: %s\n",
+ format_bytes(buf, sizeof(buf), size));
+ } else if (coredump)
fprintf(file, " Storage: journal\n");
else
fprintf(file, " Storage: none\n");
return r;
}
-static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) {
+static int print_entry(
+ sd_journal *j,
+ size_t n_found,
+ Table *t) {
+
assert(j);
- if (verb_is_info)
- return print_info(stdout, j, n_found);
+ if (t)
+ return print_list(stdout, j, t);
else if (arg_field)
return print_field(stdout, j);
else
- return print_list(stdout, j, n_found);
+ return print_info(stdout, j, n_found > 0);
}
static int dump_list(int argc, char **argv, void *userdata) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
- unsigned n_found = 0;
+ _cleanup_(table_unrefp) Table *t = NULL;
+ size_t n_found = 0;
bool verb_is_info;
int r;
- verb_is_info = (argc >= 1 && streq(argv[0], "info"));
+ verb_is_info = argc >= 1 && streq(argv[0], "info");
r = acquire_journal(&j, argv + 1);
if (r < 0)
return r;
- (void) pager_open(arg_pager_flags);
+ /* The coredumps are likely compressed, and for just listing them we don't need to decompress them,
+ * so let's pick a fairly low data threshold here */
+ (void) sd_journal_set_data_threshold(j, 4096);
+
+ if (!verb_is_info && !arg_field) {
+ t = table_new("time", "pid", "uid", "gid", "sig", "corefile", "exe", "size");
+ if (!t)
+ return log_oom();
+
+ (void) table_set_align_percent(t, TABLE_HEADER_CELL(1), 100);
+ (void) table_set_align_percent(t, TABLE_HEADER_CELL(2), 100);
+ (void) table_set_align_percent(t, TABLE_HEADER_CELL(3), 100);
+ (void) table_set_align_percent(t, TABLE_HEADER_CELL(7), 100);
- /* The coredumps are likely to compressed, and for just
- * listing them we don't need to decompress them, so let's
- * pick a fairly low data threshold here */
- sd_journal_set_data_threshold(j, 4096);
+ (void) table_set_empty_string(t, "-");
+ } else
+ (void) pager_open(arg_pager_flags);
/* "info" without pattern implies "-1" */
- if (arg_one || (verb_is_info && argc == 1)) {
+ if ((arg_rows_max == 1 && arg_reverse) || (verb_is_info && argc == 1)) {
r = focus(j);
if (r < 0)
return r;
- return print_entry(j, 0, verb_is_info);
+ r = print_entry(j, 0, t);
+ if (r < 0)
+ return r;
} else {
if (arg_since != USEC_INFINITY && !arg_reverse)
r = sd_journal_seek_realtime_usec(j, arg_since);
r = sd_journal_next(j);
else
r = sd_journal_previous(j);
-
if (r < 0)
return log_error_errno(r, "Failed to iterate through journal: %m");
-
if (r == 0)
break;
continue;
}
- r = print_entry(j, n_found++, verb_is_info);
+ r = print_entry(j, n_found++, t);
if (r < 0)
return r;
+
+ if (arg_rows_max != SIZE_MAX && n_found >= arg_rows_max)
+ break;
}
if (!arg_field && n_found <= 0) {
}
}
+ if (t) {
+ r = table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
int r, units_active;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
#include "libfido2-util.h"
#include "main-func.h"
#include "memory-util.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pkcs11-util.h"
" Specify TPM2 PCRs to seal against\n"
" --wipe-slot=SLOT1,SLOT2,…\n"
" Wipe specified slots\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many arguments, refusing.");
- r = parse_path_argument_and_warn(argv[optind], false, &arg_node);
+ r = parse_path_argument(argv[optind], false, &arg_node);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <errno.h>
+
typedef enum EnrollType {
ENROLL_PASSWORD,
ENROLL_RECOVERY,
ENROLL_FIDO2,
ENROLL_TPM2,
_ENROLL_TYPE_MAX,
- _ENROLL_TYPE_INVALID = -1,
+ _ENROLL_TYPE_INVALID = -EINVAL,
} EnrollType;
typedef enum WipeScope {
WIPE_ALL, /* wipe all slots */
WIPE_EMPTY_PASSPHRASE, /* wipe slots with empty passphrases plus listed slots */
_WIPE_SCOPE_MAX,
- _WIPE_SCOPE_INVALID = -1,
+ _WIPE_SCOPE_INVALID = -EINVAL,
} WipeScope;
const char* enroll_type_to_string(EnrollType t);
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
if (r != 2)
- return free_and_strdup(&arg_default_options, value) < 0 ? log_oom() : 0;
+ return free_and_strdup_warn(&arg_default_options, value);
if (warn_uuid_invalid(uuid, key))
return 0;
return 0;
n = strspn(value, ALPHANUMERICAL "-");
- if (value[n] != '=') {
- if (free_and_strdup(&arg_default_keyfile, value) < 0)
- return log_oom();
- return 0;
- }
+ if (value[n] != '=')
+ return free_and_strdup_warn(&arg_default_keyfile, value);
uuid = strndup(value, n);
if (!uuid)
printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n"
"%s detach VOLUME\n\n"
"Attaches or detaches an encrypted block device.\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ program_invocation_short_name,
+ link);
return 0;
}
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program requires at least two arguments.");
- log_setup_service();
+ log_setup();
cryptsetup_enable_logging(cd);
else if (r > 0)
t = skip_dev_prefix(DEBUGTTY);
- if (free_and_strdup(&arg_debug_shell, t) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_debug_shell, t);
} else if (streq(key, "systemd.unit")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- r = free_and_strdup(&arg_default_unit, value);
- if (r < 0)
- return log_error_errno(r, "Failed to set default unit %s: %m", value);
+ return free_and_strdup_warn(&arg_default_unit, value);
} else if (!value) {
const char *target;
target = runlevel_to_target(key);
- if (target) {
- r = free_and_strdup(&arg_default_unit, target);
- if (r < 0)
- return log_error_errno(r, "Failed to set default unit %s: %m", target);
- }
+ if (target)
+ return free_and_strdup_warn(&arg_default_unit, target);
}
return 0;
" --no-pager Do not pipe output into a pager\n"
" --diff[=1|0] Show a diff when overridden files differ\n"
" -t --type=LIST... Only display a selected set of override types\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
static int run(int argc, char *argv[]) {
int r, k, n_found = 0;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
" --private-users Only detect whether we are running in a user namespace\n"
" -q --quiet Don't output anything, just set return value\n"
" --list List all known and detectable types of virtualization\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
* to detect whether we are being run in a virtualized
* environment or not */
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "mkdir.h"
#include "mount-util.h"
#include "namespace-util.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
+static PagerFlags arg_pager_flags = 0;
+static bool arg_legend = true;
STATIC_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done);
"%1$s [OPTIONS...] --copy-to IMAGE [SOURCE] PATH\n\n"
"%5$sDissect a file system OS image.%6$s\n\n"
"%3$sOptions:%4$s\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not show the headers and footers\n"
" -r --read-only Mount read-only\n"
" --fsck=BOOL Run fsck before mounting\n"
" --mkdir Make mount directory before mounting, if missing\n"
" -M Shortcut for --mount --mkdir\n"
" -x --copy-from Copy files from image to host\n"
" -a --copy-to Copy files from host to image\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal());
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
enum {
ARG_VERSION = 0x100,
+ ARG_NO_PAGER,
+ ARG_NO_LEGEND,
ARG_DISCARD,
ARG_FSCK,
ARG_ROOT_HASH,
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "mount", no_argument, NULL, 'm' },
{ "read-only", no_argument, NULL, 'r' },
{ "discard", required_argument, NULL, ARG_DISCARD },
case ARG_VERSION:
return version();
+ case ARG_NO_PAGER:
+ arg_pager_flags |= PAGER_DISABLE;
+ break;
+
+ case ARG_NO_LEGEND:
+ arg_legend = false;
+ break;
+
case 'm':
arg_action = ACTION_MOUNT;
break;
}
case ARG_VERITY_DATA:
- r = parse_path_argument_and_warn(optarg, false, &arg_verity_settings.data_path);
+ r = parse_path_argument(optarg, false, &arg_verity_settings.data_path);
if (r < 0)
return r;
break;
break;
case ARG_JSON:
- r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags);
+ r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
assert(m);
assert(d);
+ if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
+ (void) pager_open(arg_pager_flags);
+
if (arg_json_format_flags & JSON_FORMAT_OFF)
printf(" Name: %s\n", basename(arg_image));
}
if (arg_json_format_flags & JSON_FORMAT_OFF) {
- r = table_print(t, stdout);
+ (void) table_set_header(t, arg_legend);
+
+ r = table_print(t, NULL);
if (r < 0)
return table_log_print_error(r);
} else {
" -u --unescape Unescape strings\n"
" -m --mangle Mangle strings\n"
" -p --path When escaping/unescaping assume the string is a path\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
case ARG_VERSION:
return version();
- case ARG_SUFFIX:
-
- if (unit_type_from_string(optarg) < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid unit suffix type %s.", optarg);
+ case ARG_SUFFIX: {
+ UnitType t = unit_type_from_string(optarg);
+ if (t < 0)
+ return log_error_errno(t, "Invalid unit suffix type \"%s\".", optarg);
arg_suffix = optarg;
break;
+ }
case ARG_TEMPLATE:
-
if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Template name %s is not valid.", optarg);
char **i;
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "mkdir.h"
#include "mount-util.h"
#include "os-util.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
}
log_info("Selected '%s'.", l[u-1]);
- if (free_and_strdup(ret, l[u-1]) < 0)
- return log_oom();
-
- return 0;
+ return free_and_strdup_warn(ret, l[u-1]);
}
if (!is_valid(p)) {
" --force Overwrite existing files\n"
" --delete-root-password Delete root password\n"
" --welcome=no Disable the welcome text\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
return version();
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
+ r = parse_path_argument(optarg, true, &arg_root);
if (r < 0)
return r;
break;
case ARG_IMAGE:
- r = parse_path_argument_and_warn(optarg, false, &arg_image);
+ r = parse_path_argument(optarg, false, &arg_image);
if (r < 0)
return r;
break;
break;
case ARG_MACHINE_ID:
- if (sd_id128_from_string(optarg, &arg_machine_id) < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse machine id %s.", optarg);
+ r = sd_id128_from_string(optarg, &arg_machine_id);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse machine id %s.", optarg);
break;
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
umask(0022);
}
for (;;) {
- int pass, m;
+ int pass;
unsigned long cur, max;
_cleanup_free_ char *device = NULL;
double p;
last = t;
p = percent(pass, cur, max);
- fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
- fflush(console);
+ r = fprintf(console, "\r%s: fsck %3.1f%% complete...\r", device, p);
+ if (r < 0)
+ return -EIO; /* No point in continuing if something happened to our output stream */
- if (m > clear)
- clear = m;
+ fflush(console);
+ clear = MAX(clear, r);
}
if (clear > 0) {
- unsigned j;
-
fputc('\r', console);
- for (j = 0; j < (unsigned) clear; j++)
+ for (int j = 0; j < clear; j++)
fputc(' ', console);
fputc('\r', console);
fflush(console);
int r, exit_status;
pid_t pid;
- log_setup_service();
+ log_setup();
if (argc > 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_root_what, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_root_what, value);
} else if (streq(key, "rootfstype")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_root_fstype, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_root_fstype, value);
} else if (streq(key, "rootflags")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_root_hash, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_root_hash, value);
} else if (streq(key, "mount.usr")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_usr_what, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_usr_what, value);
} else if (streq(key, "mount.usrfstype")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_usr_fstype, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_usr_fstype, value);
} else if (streq(key, "mount.usrflags")) {
if (value) {
m = volatile_mode_from_string(value);
if (m < 0)
- log_warning("Failed to parse systemd.volatile= argument: %s", value);
+ log_warning_errno(m, "Failed to parse systemd.volatile= argument: %s", value);
else
arg_volatile_mode = m;
} else
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifndef SD_BOOT
+#include <assert.h>
+#endif
+
+#include "type.h"
+
+#define _const_ __attribute__((__const__))
+#define _pure_ __attribute__((__pure__))
+#define _unused_ __attribute__((__unused__))
+#define _cleanup_(x) __attribute__((__cleanup__(x)))
+
+#ifndef __COVERITY__
+# define VOID_0 ((void)0)
+#else
+# define VOID_0 ((void*)0)
+#endif
+
+#define ELEMENTSOF(x) \
+ (__builtin_choose_expr( \
+ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
+ sizeof(x)/sizeof((x)[0]), \
+ VOID_0))
+
+#define XCONCATENATE(x, y) x ## y
+#define CONCATENATE(x, y) XCONCATENATE(x, y)
+
+#ifdef SD_BOOT
+#define assert(expr) do {} while (false)
+#endif
+
+#if defined(static_assert)
+#define assert_cc(expr) \
+ static_assert(expr, #expr)
+#else
+#define assert_cc(expr) \
+ struct CONCATENATE(_assert_struct_, __COUNTER__) { \
+ char x[(expr) ? 0 : -1]; \
+ }
+#endif
+
+#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
+#define UNIQ __COUNTER__
+
+#undef MAX
+#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
+#define __MAX(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
+ })
+
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define CONST_MAX(_A, _B) \
+ (__builtin_choose_expr( \
+ __builtin_constant_p(_A) && \
+ __builtin_constant_p(_B) && \
+ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
+ ((_A) > (_B)) ? (_A) : (_B), \
+ VOID_0))
+
+/* takes two types and returns the size of the larger one */
+#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
+
+#define MAX3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MAX(x, y); \
+ MAX(_c, z); \
+ })
+
+#define MAX4(x, y, z, a) \
+ ({ \
+ const typeof(x) _d = MAX3(x, y, z); \
+ MAX(_d, a); \
+ })
+
+#undef MIN
+#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
+#define __MIN(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
+ })
+
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define CONST_MIN(_A, _B) \
+ (__builtin_choose_expr( \
+ __builtin_constant_p(_A) && \
+ __builtin_constant_p(_B) && \
+ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
+ ((_A) < (_B)) ? (_A) : (_B), \
+ VOID_0))
+
+#define MIN3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MIN(x, y); \
+ MIN(_c, z); \
+ })
+
+#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
+#define __LESS_BY(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \
+ })
+
+#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
+#define __CMP(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
+ })
+
+#undef CLAMP
+#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
+#define __CLAMP(xq, x, lowq, low, highq, high) \
+ ({ \
+ const typeof(x) UNIQ_T(X, xq) = (x); \
+ const typeof(low) UNIQ_T(LOW, lowq) = (low); \
+ const typeof(high) UNIQ_T(HIGH, highq) = (high); \
+ UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \
+ UNIQ_T(HIGH, highq) : \
+ UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \
+ UNIQ_T(LOW, lowq) : \
+ UNIQ_T(X, xq); \
+ })
+
+/* [(x + y - 1) / y] suffers from an integer overflow, even though the
+ * computation should be possible in the given type. Therefore, we use
+ * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
+ * quotient and the remainder, so both should be equally fast. */
+#define DIV_ROUND_UP(x, y) __DIV_ROUND_UP(UNIQ, (x), UNIQ, (y))
+#define __DIV_ROUND_UP(xq, x, yq, y) \
+ ({ \
+ const typeof(x) UNIQ_T(X, xq) = (x); \
+ const typeof(y) UNIQ_T(Y, yq) = (y); \
+ (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
+ })
+
+#define CASE_F(X) case X:
+#define CASE_F_1(CASE, X) CASE_F(X)
+#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
+#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
+#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
+#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
+#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
+#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
+#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
+#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
+#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
+#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
+#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
+#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
+#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
+#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
+#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
+#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
+#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
+#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
+#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
+
+#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
+#define FOR_EACH_MAKE_CASE(...) \
+ GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
+ CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
+ (CASE_F,__VA_ARGS__)
+
+#define IN_SET(x, ...) \
+ ({ \
+ sd_bool _found = false; \
+ /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
+ * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
+ * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
+ * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
+ static const long double __assert_in_set[] _unused_ = { __VA_ARGS__ }; \
+ assert_cc(ELEMENTSOF(__assert_in_set) <= 20); \
+ switch(x) { \
+ FOR_EACH_MAKE_CASE(__VA_ARGS__) \
+ _found = true; \
+ break; \
+ default: \
+ break; \
+ } \
+ _found; \
+ })
+
+/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time
+ * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
+#define TAKE_PTR(ptr) \
+ ({ \
+ typeof(ptr) _ptr_ = (ptr); \
+ (ptr) = NULL; \
+ _ptr_; \
+ })
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+fundamental_path = meson.current_source_dir()
+
+fundamental_headers = files(
+ 'efi-loader-features.h',
+ 'macro-fundamental.h',
+ 'string-util-fundamental.h',
+ 'type.h')
+
+sources = '''
+ string-util-fundamental.c
+'''.split()
+
+# for sd-boot
+fundamental_source_paths = []
+foreach s : sources
+ fundamental_source_paths += join_paths(meson.current_source_dir(), s)
+endforeach
+
+# for libbasic
+fundamental_sources = files(sources) + fundamental_headers
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef SD_BOOT
+#include <ctype.h>
+
+#include "macro.h"
+#endif
+#include "string-util-fundamental.h"
+
+sd_char *startswith(const sd_char *s, const sd_char *prefix) {
+ sd_size_t l;
+
+ assert(s);
+ assert(prefix);
+
+ l = strlen(prefix);
+ if (!strneq(s, prefix, l))
+ return NULL;
+
+ return (sd_char*) s + l;
+}
+
+#ifndef SD_BOOT
+sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
+ sd_size_t l;
+
+ assert(s);
+ assert(prefix);
+
+ l = strlen(prefix);
+ if (!strncaseeq(s, prefix, l))
+ return NULL;
+
+ return (sd_char*) s + l;
+}
+#endif
+
+sd_char* endswith(const sd_char *s, const sd_char *postfix) {
+ sd_size_t sl, pl;
+
+ assert(s);
+ assert(postfix);
+
+ sl = strlen(s);
+ pl = strlen(postfix);
+
+ if (pl == 0)
+ return (sd_char*) s + sl;
+
+ if (sl < pl)
+ return NULL;
+
+ if (strcmp(s + sl - pl, postfix) != 0)
+ return NULL;
+
+ return (sd_char*) s + sl - pl;
+}
+
+sd_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
+ sd_size_t sl, pl;
+
+ assert(s);
+ assert(postfix);
+
+ sl = strlen(s);
+ pl = strlen(postfix);
+
+ if (pl == 0)
+ return (sd_char*) s + sl;
+
+ if (sl < pl)
+ return NULL;
+
+ if (strcasecmp(s + sl - pl, postfix) != 0)
+ return NULL;
+
+ return (sd_char*) s + sl - pl;
+}
+
+#ifdef SD_BOOT
+static sd_bool isdigit(sd_char a) {
+ return a >= '0' && a <= '9';
+}
+#endif
+
+static sd_bool is_alpha(sd_char a) {
+ /* Locale independent version of isalpha(). */
+ return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
+}
+
+static sd_bool is_valid_version_char(sd_char a) {
+ return isdigit(a) || is_alpha(a) || IN_SET(a, '~', '-', '^', '.');
+}
+
+sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
+
+ /* This is based on RPM's rpmvercmp(). But this explicitly handles '-' and '.', as we usually
+ * want to directly compare strings which contain both version and release; e.g.
+ * '247.2-3.1.fc33.x86_64' or '5.11.0-0.rc5.20210128git76c057c84d28.137.fc34'.
+ * Unlike rpmvercmp(), this distiguishes e.g. 123a and 123.a, and 123a is newer.
+ *
+ * This splits the input strings into segments. Each segment is numeric or alpha, and may be
+ * prefixed with the following:
+ * '~' : used for pre-releases, a segment prefixed with this is the oldest,
+ * '-' : used for the separator between version and release,
+ * '^' : used for patched releases, a segment with this is newer than one with '-'.
+ * '.' : used for point releases.
+ * Note, no prefix segment is the newest. All non-supported characters are dropped, and
+ * handled as a separator of segments, e.g., 123_a is equivalent to 123a.
+ *
+ * By using this, version strings can be sorted like following:
+ * (older) 122.1
+ * ^ 123~rc1-1
+ * | 123
+ * | 123-a
+ * | 123-a.1
+ * | 123-1
+ * | 123-1.1
+ * | 123^post1
+ * | 123.a-1
+ * | 123.1-1
+ * v 123a-1
+ * (newer) 124-1
+ */
+
+ if (isempty(a) || isempty(b))
+ return strcmp_ptr(a, b);
+
+ for (;;) {
+ const sd_char *aa, *bb;
+ sd_int r;
+
+ /* Drop leading invalid characters. */
+ while (*a != '\0' && !is_valid_version_char(*a))
+ a++;
+ while (*b != '\0' && !is_valid_version_char(*b))
+ b++;
+
+ /* Handle '~'. Used for pre-releases, e.g. 123~rc1, or 4.5~alpha1 */
+ if (*a == '~' || *b == '~') {
+ /* The string prefixed with '~' is older. */
+ r = CMP(*a != '~', *b != '~');
+ if (r != 0)
+ return r;
+
+ /* Now both strings are prefixed with '~'. Compare remaining strings. */
+ a++;
+ b++;
+ }
+
+ /* If at least one string reaches the end, then longer is newer.
+ * Note that except for '~' prefixed segments, a string has more segments is newer.
+ * So, this check must be after the '~' check. */
+ if (*a == '\0' || *b == '\0')
+ return strcmp(a, b);
+
+ /* Handle '-', which separates version and release, e.g 123.4-3.1.fc33.x86_64 */
+ if (*a == '-' || *b == '-') {
+ /* The string prefixed with '-' is older (e.g., 123-9 vs 123.1-1) */
+ r = CMP(*a != '-', *b != '-');
+ if (r != 0)
+ return r;
+
+ a++;
+ b++;
+ }
+
+ /* Handle '^'. Used for patched release. */
+ if (*a == '^' || *b == '^') {
+ r = CMP(*a != '^', *b != '^');
+ if (r != 0)
+ return r;
+
+ a++;
+ b++;
+ }
+
+ /* Handle '.'. Used for point releases. */
+ if (*a == '.' || *b == '.') {
+ r = CMP(*a != '.', *b != '.');
+ if (r != 0)
+ return r;
+
+ a++;
+ b++;
+ }
+
+ if (isdigit(*a) || isdigit(*b)) {
+ /* Skip leading '0', to make 00123 equivalent to 123. */
+ while (*a == '0')
+ a++;
+ while (*b == '0')
+ b++;
+
+ /* Find the leading numeric segments. One may be an empty string. So,
+ * numeric segments are always newer than alpha segments. */
+ for (aa = a; *aa != '\0' && isdigit(*aa); aa++)
+ ;
+ for (bb = b; *bb != '\0' && isdigit(*bb); bb++)
+ ;
+
+ /* To compare numeric segments without parsing their values, first compare the
+ * lengths of the segments. Eg. 12345 vs 123, longer is newer. */
+ r = CMP(aa - a, bb - b);
+ if (r != 0)
+ return r;
+
+ /* Then, compare them as strings. */
+ r = strncmp(a, b, aa - a);
+ if (r != 0)
+ return r;
+ } else {
+ /* Find the leading non-numeric segments. */
+ for (aa = a; *aa != '\0' && is_alpha(*aa); aa++)
+ ;
+ for (bb = b; *bb != '\0' && is_alpha(*bb); bb++)
+ ;
+
+ /* Note that the segments are usually not NUL-terminated. */
+ r = strncmp(a, b, MIN(aa - a, bb - b));
+ if (r != 0)
+ return r;
+
+ /* Longer is newer, e.g. abc vs abcde. */
+ r = CMP(aa - a, bb - b);
+ if (r != 0)
+ return r;
+ }
+
+ /* The current segments are equivalent. Let's compare the next one. */
+ a = aa;
+ b = bb;
+ }
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifdef SD_BOOT
+#include <efi.h>
+#include <efilib.h>
+#else
+#include <string.h>
+#endif
+
+#include "macro-fundamental.h"
+
+#ifdef SD_BOOT
+#define strlen(a) StrLen((a))
+#define strcmp(a, b) StrCmp((a), (b))
+#define strncmp(a, b, n) StrnCmp((a), (b), (n))
+#define strcasecmp(a, b) StriCmp((a), (b))
+#define STR_C(str) (L ## str)
+#else
+#define STR_C(str) (str)
+#endif
+
+#define streq(a,b) (strcmp((a),(b)) == 0)
+#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
+#ifndef SD_BOOT
+#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
+#endif
+
+static inline sd_int strcmp_ptr(const sd_char *a, const sd_char *b) {
+ if (a && b)
+ return strcmp(a, b);
+
+ return CMP(a, b);
+}
+
+static inline sd_int strcasecmp_ptr(const sd_char *a, const sd_char *b) {
+ if (a && b)
+ return strcasecmp(a, b);
+
+ return CMP(a, b);
+}
+
+static inline sd_bool streq_ptr(const sd_char *a, const sd_char *b) {
+ return strcmp_ptr(a, b) == 0;
+}
+
+static inline sd_bool strcaseeq_ptr(const sd_char *a, const sd_char *b) {
+ return strcasecmp_ptr(a, b) == 0;
+}
+
+sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_;
+#ifndef SD_BOOT
+sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_;
+#endif
+sd_char *endswith(const sd_char *s, const sd_char *postfix) _pure_;
+sd_char *endswith_no_case(const sd_char *s, const sd_char *postfix) _pure_;
+
+static inline sd_bool isempty(const sd_char *a) {
+ return !a || a[0] == '\0';
+}
+
+static inline const sd_char *yes_no(sd_bool b) {
+ return b ? STR_C("yes") : STR_C("no");
+}
+
+sd_int strverscmp_improved(const sd_char *a, const sd_char *b);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifdef SD_BOOT
+#include <efi.h>
+
+typedef BOOLEAN sd_bool;
+typedef CHAR16 sd_char;
+typedef INTN sd_int;
+typedef UINTN sd_size_t;
+
+#define true TRUE
+#define false FALSE
+#else
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef bool sd_bool;
+typedef char sd_char;
+typedef int sd_int;
+typedef size_t sd_size_t;
+#endif
#define MIN_NUMBER_OF_RUNS 4
int main(int argc, char **argv) {
- int i, r;
- size_t size;
- char *name;
+ int r;
test_setup_logging(LOG_DEBUG);
- for (i = 1; i < argc; i++) {
+ for (int i = 1; i < argc; i++) {
_cleanup_free_ char *buf = NULL;
+ size_t size;
+ char *name;
name = argv[i];
r = read_full_file(name, &buf, &size);
return EXIT_FAILURE;
}
- log_setup_service();
+ log_setup();
umask(0022);
#include "main-func.h"
#include "memory-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pkcs11-util.h"
_cleanup_(table_unrefp) Table *table = NULL;
int r;
- (void) pager_open(arg_pager_flags);
-
r = acquire_bus(&bus);
if (r < 0)
return r;
if (r < 0)
return table_log_sort_error(r);
- table_set_header(table, arg_legend);
-
- r = table_print_json(table, stdout, arg_json_format_flags);
+ r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
if (r < 0)
- return table_log_print_error(r);
+ return r;
}
if (arg_legend && (arg_json_format_flags & JSON_FORMAT_OFF)) {
" --kill-processes=BOOL Whether to kill user processes when sessions\n"
" terminate\n"
" --auto-login=BOOL Try to log this user in automatically\n"
- "\nSee the %6$s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , ansi_underline(), ansi_normal()
- , link
- );
+ "\nSee the %6$s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
+ ansi_normal(),
+ link);
return 0;
}
break;
}
- r = parse_path_argument_and_warn(optarg, false, &hd);
+ r = parse_path_argument(optarg, false, &hd);
if (r < 0)
return r;
l = rlimit_from_string_harder(field);
if (l < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown resource limit type: %s", field);
+ return log_error_errno(l, "Unknown resource limit type: %s", field);
if (isempty(eq + 1)) {
/* Remove only the specific rlimit */
break;
}
- r = parse_path_argument_and_warn(optarg, false, &v);
+ r = parse_path_argument(optarg, false, &v);
if (r < 0)
return r;
break;
case ARG_SETENV: {
- _cleanup_free_ char **l = NULL, **k = NULL;
+ _cleanup_free_ char **l = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *ne = NULL;
JsonVariant *e;
}
if (!env_assignment_is_valid(optarg))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Environment assignment '%s' not valid.", optarg);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Environment assignment '%s' not valid.", optarg);
e = json_variant_by_key(arg_identity_extra, "environment");
if (e) {
return log_error_errno(r, "Failed to parse JSON environment field: %m");
}
- k = strv_env_set(l, optarg);
- if (!k)
- return log_oom();
+ r = strv_env_replace_strdup(&l, optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to replace JSON environment field: %m");
- strv_sort(k);
+ strv_sort(l);
- r = json_variant_new_array_strv(&ne, k);
+ r = json_variant_new_array_strv(&ne, l);
if (r < 0)
return log_error_errno(r, "Failed to allocate environment list JSON: %m");
break;
case ARG_JSON:
- r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags);
+ r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
int r;
- log_setup_cli();
+ log_setup();
r = redirect_bus_mgr();
if (r < 0)
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
_exit(EXIT_FAILURE);
}
+ r = setenv_systemd_exec_pid(true);
+ if (r < 0)
+ log_warning_errno(r, "Failed to update $SYSTEMD_EXEC_PID, ignoring: %m");
+
r = rearrange_stdio(stdin_fd, stdout_fd, STDERR_FILENO);
if (r < 0) {
log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m");
HOME_AUTHENTICATING_WHILE_ACTIVE,
HOME_AUTHENTICATING_FOR_ACQUIRE, /* authenticating because Acquire() was called */
_HOME_STATE_MAX,
- _HOME_STATE_INVALID = -1
+ _HOME_STATE_INVALID = -EINVAL,
} HomeState;
static inline bool HOME_STATE_IS_ACTIVE(HomeState state) {
assert(m);
assert(!m->varlink_server);
- r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID);
+ r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");
return 1;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
static int manager_generate_key_pair(Manager *m) {
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
}
DEFINE_PRIVATE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY*, EVP_PKEY_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
static int manager_load_public_key_one(Manager *m, const char *path) {
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
OPERATION_DEACTIVATE_FORCE, /* enqueued on hard $HOME unplug */
OPERATION_IMMEDIATE, /* this is never enqueued, it's just a marker we immediately started executing an operation without enqueuing anything first. */
_OPERATION_MAX,
- _OPERATION_INVALID = -1,
+ _OPERATION_INVALID = -EINVAL,
} OperationType;
/* Encapsulates an operation on one or more home directories. This has two uses:
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-homed.service",
"A service to create, remove, change or inspect home areas.",
blkid_loff_t offset = 0, size = 0;
blkid_partlist pl;
bool found = false;
- int r, i, n;
+ int r, n;
assert(fd >= 0);
assert(label);
if (n < 0)
return errno > 0 ? -errno : -EIO;
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
blkid_partition pp;
- sd_id128_t id;
+ sd_id128_t id = SD_ID128_NULL;
const char *sid;
errno = 0;
PasswordCache *cache,
UserRecord **ret_luks_home_record) {
- int r, token;
+ int r;
assert(cd);
assert(h);
- for (token = 0;; token++) {
+ for (int token = 0;; token++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *rr = NULL;
_cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL;
_cleanup_(user_record_unrefp) UserRecord *lhr = NULL;
return 0;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
static int make_partition_table(
int fd,
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
_cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
_cleanup_free_ char *path = NULL, *disk_uuid_as_string = NULL;
- size_t n_partitions, i;
+ size_t n_partitions;
sd_id128_t disk_uuid;
bool found = false;
int r;
return log_error_errno(r, "Failed to acquire partition table: %m");
n_partitions = fdisk_table_get_nents(t);
- for (i = 0; i < n_partitions; i++) {
+ for (size_t i = 0; i < n_partitions; i++) {
struct fdisk_partition *p;
p = fdisk_table_get_partition(t, i);
PasswordCache *cache, /* the passwords acquired via PKCS#11/FIDO2 security tokens */
char **effective_passwords /* new passwords */) {
- size_t volume_key_size, i, max_key_slots, n_effective;
+ size_t volume_key_size, max_key_slots, n_effective;
_cleanup_(erase_and_freep) void *volume_key = NULL;
struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf;
const char *type;
build_good_pbkdf(&good_pbkdf, h);
build_minimal_pbkdf(&minimal_pbkdf, h);
- for (i = 0; i < max_key_slots; i++) {
+ for (size_t i = 0; i < max_key_slots; i++) {
r = crypt_keyslot_destroy(setup->crypt_device, i);
if (r < 0 && !IN_SET(r, -ENOENT, -EINVAL)) /* Returns EINVAL or ENOENT if there's no key in this slot already */
return log_error_errno(r, "Failed to destroy LUKS password: %m");
start = now(CLOCK_MONOTONIC);
- log_setup_service();
+ log_setup();
umask(0022);
return json_variant_format(j, 0, ret);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_MD_CTX*, EVP_MD_CTX_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
_cleanup_(json_variant_unrefp) JsonVariant *encoded = NULL, *v = NULL;
USER_RECONCILE_REQUIRE_NEWER, /* host version must be newer than embedded version */
USER_RECONCILE_REQUIRE_NEWER_OR_EQUAL, /* similar, but may also be equal */
_USER_RECONCILE_MODE_MAX,
- _USER_RECONCILE_MODE_INVALID = -1,
+ _USER_RECONCILE_MODE_INVALID = -EINVAL,
} UserReconcileMode;
enum { /* return values */
#include "alloc-util.h"
#include "architecture.h"
+#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-map-properties.h"
+#include "format-table.h"
+#include "hostname-setup.h"
#include "hostname-util.h"
#include "main-func.h"
#include "pretty-print.h"
const char *hardware_model;
} StatusInfo;
-static void print_status_info(StatusInfo *i) {
+static int print_status_info(StatusInfo *i) {
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_id128_t mid = {}, bid = {};
+ TableCell *cell;
int r;
assert(i);
- printf(" Static hostname: %s\n", strna(i->static_hostname));
+ table = table_new("key", "value");
+ if (!table)
+ return log_oom();
+
+ assert_se(cell = table_get_cell(table, 0, 0));
+ (void) table_set_ellipsize_percent(table, cell, 100);
+ (void) table_set_align_percent(table, cell, 100);
+
+ table_set_header(table, false);
+
+ r = table_set_empty_string(table, "n/a");
+ if (r < 0)
+ return log_oom();
+
+ r = table_add_many(table,
+ TABLE_STRING, "Static hostname:",
+ TABLE_STRING, i->static_hostname);
+ if (r < 0)
+ return table_log_add_error(r);
if (!isempty(i->pretty_hostname) &&
- !streq_ptr(i->pretty_hostname, i->static_hostname))
- printf(" Pretty hostname: %s\n", i->pretty_hostname);
+ !streq_ptr(i->pretty_hostname, i->static_hostname)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Pretty hostname:",
+ TABLE_STRING, i->pretty_hostname);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
if (!isempty(i->hostname) &&
- !streq_ptr(i->hostname, i->static_hostname))
- printf("Transient hostname: %s\n", i->hostname);
+ !streq_ptr(i->hostname, i->static_hostname)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Transient hostname:",
+ TABLE_STRING, i->hostname);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->icon_name))
- printf(" Icon name: %s\n",
- strna(i->icon_name));
+ if (!isempty(i->icon_name)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Icon name:",
+ TABLE_STRING, i->icon_name);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->chassis))
- printf(" Chassis: %s\n",
- strna(i->chassis));
+ if (!isempty(i->chassis)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Chassis:",
+ TABLE_STRING, i->chassis);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->deployment))
- printf(" Deployment: %s\n", i->deployment);
+ if (!isempty(i->deployment)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Deployment:",
+ TABLE_STRING, i->deployment);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->location))
- printf(" Location: %s\n", i->location);
+ if (!isempty(i->location)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Location:",
+ TABLE_STRING, i->location);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
r = sd_id128_get_machine(&mid);
- if (r >= 0)
- printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid));
+ if (r >= 0) {
+ r = table_add_many(table,
+ TABLE_STRING, "Machine ID:",
+ TABLE_ID128, mid);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
r = sd_id128_get_boot(&bid);
- if (r >= 0)
- printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid));
+ if (r >= 0) {
+ r = table_add_many(table,
+ TABLE_STRING, "Boot ID:",
+ TABLE_ID128, bid);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->virtualization))
- printf(" Virtualization: %s\n", i->virtualization);
+ if (!isempty(i->virtualization)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Virtualization:",
+ TABLE_STRING, i->virtualization);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
if (!isempty(i->os_pretty_name)) {
_cleanup_free_ char *formatted = NULL;
t = formatted;
}
- printf(" Operating System: %s\n", t);
+ r = table_add_many(table,
+ TABLE_STRING, "Operating System:",
+ TABLE_STRING, t);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ if (!isempty(i->os_cpe_name)) {
+ r = table_add_many(table,
+ TABLE_STRING, "CPE OS Name:",
+ TABLE_STRING, i->os_cpe_name);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ if (!isempty(i->kernel_name) && !isempty(i->kernel_release)) {
+ const char *v;
+
+ v = strjoina(i->kernel_name, " ", i->kernel_release);
+ r = table_add_many(table,
+ TABLE_STRING, "Kernel:",
+ TABLE_STRING, v);
+ if (r < 0)
+ return table_log_add_error(r);
}
- if (!isempty(i->os_cpe_name))
- printf(" CPE OS Name: %s\n", i->os_cpe_name);
+ if (!isempty(i->architecture)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Architecture:",
+ TABLE_STRING, i->architecture);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->kernel_name) && !isempty(i->kernel_release))
- printf(" Kernel: %s %s\n", i->kernel_name, i->kernel_release);
+ if (!isempty(i->hardware_vendor)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Hardware Vendor:",
+ TABLE_STRING, i->hardware_vendor);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->architecture))
- printf(" Architecture: %s\n", i->architecture);
+ if (!isempty(i->hardware_model)) {
+ r = table_add_many(table,
+ TABLE_STRING, "Hardware Model:",
+ TABLE_STRING, i->hardware_model);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
- if (!isempty(i->hardware_vendor))
- printf(" Hardware Vendor: %s\n", i->hardware_vendor);
+ r = table_print(table, NULL);
+ if (r < 0)
+ return table_log_print_error(r);
- if (!isempty(i->hardware_model))
- printf(" Hardware Model: %s\n", i->hardware_model);
+ return 0;
}
-static int show_one_name(sd_bus *bus, const char* attr) {
+static int get_one_name(sd_bus *bus, const char* attr, char **ret) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *s;
int r;
+ assert(bus);
+ assert(attr);
+
+ /* This obtains one string property, and copy it if 'ret' is set, or print it otherwise. */
+
r = sd_bus_get_property(
bus,
"org.freedesktop.hostname1",
if (r < 0)
return bus_log_parse_error(r);
- printf("%s\n", s);
+ if (ret) {
+ char *str;
+
+ str = strdup(s);
+ if (!str)
+ return log_oom();
+
+ *ret = str;
+ } else
+ printf("%s\n", s);
return 0;
}
-static int show_all_names(sd_bus *bus, sd_bus_error *error) {
+static int show_all_names(sd_bus *bus) {
StatusInfo info = {};
static const struct bus_properties_map hostname_map[] = {
};
_cleanup_(sd_bus_message_unrefp) sd_bus_message *host_message = NULL, *manager_message = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
r = bus_map_all_properties(bus,
"/org/freedesktop/hostname1",
hostname_map,
0,
- error,
+ &error,
&host_message,
&info);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to query system properties: %s", bus_error_message(&error, r));
r = bus_map_all_properties(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
manager_map,
0,
- error,
+ &error,
&manager_message,
&info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query system properties: %s", bus_error_message(&error, r));
- print_status_info(&info);
-
- return r;
+ return print_status_info(&info);
}
static int show_status(int argc, char **argv, void *userdata) {
sd_bus *bus = userdata;
- int r;
if (arg_pretty || arg_static || arg_transient) {
const char *attr;
attr = arg_pretty ? "PrettyHostname" :
arg_static ? "StaticHostname" : "Hostname";
- return show_one_name(bus, attr);
- } else {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- r = show_all_names(bus, &error);
- if (r < 0)
- return log_error_errno(r, "Failed to query system properties: %s", bus_error_message(&error, r));
-
- return 0;
+ return get_one_name(bus, attr, NULL);
}
+
+ return show_all_names(bus);
}
-static int set_simple_string(sd_bus *bus, const char *method, const char *value) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r = 0;
+static int set_simple_string_internal(sd_bus *bus, sd_bus_error *error, const char *target, const char *method, const char *value) {
+ _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
+ int r;
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+ if (!error)
+ error = &e;
+
r = sd_bus_call_method(
bus,
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
method,
- &error, NULL,
+ error, NULL,
"sb", value, arg_ask_password);
if (r < 0)
- return log_error_errno(r, "Could not set property: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Could not set %s: %s", target, bus_error_message(error, r));
return 0;
}
+static int set_simple_string(sd_bus *bus, const char *target, const char *method, const char *value) {
+ return set_simple_string_internal(bus, NULL, target, method, value);
+}
+
static int set_hostname(int argc, char **argv, void *userdata) {
_cleanup_free_ char *h = NULL;
const char *hostname = argv[1];
sd_bus *bus = userdata;
- int r;
+ bool implicit = false, show_hint = false;
+ int r, ret = 0;
if (!arg_pretty && !arg_static && !arg_transient)
- arg_pretty = arg_static = arg_transient = true;
+ arg_pretty = arg_static = arg_transient = implicit = true;
+
+ if (!implicit && !arg_static && arg_transient) {
+ _cleanup_free_ char *source = NULL;
+
+ r = get_one_name(bus, "HostnameSource", &source);
+ if (r < 0)
+ return r;
+
+ if (hostname_source_from_string(source) == HOSTNAME_STATIC)
+ log_info("Hint: static hostname is already set, so the specified transient hostname will not be used.");
+ }
if (arg_pretty) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *p;
/* If the passed hostname is already valid, then assume the user doesn't know anything about pretty
* hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic
* hostname. */
- if (arg_static && hostname_is_valid(hostname, VALID_HOSTNAME_TRAILING_DOT))
+ if (implicit && hostname_is_valid(hostname, VALID_HOSTNAME_TRAILING_DOT))
p = ""; /* No pretty hostname (as it is redundant), just a static one */
else
p = hostname; /* Use the passed name as pretty hostname */
- r = set_simple_string(bus, "SetPrettyHostname", p);
- if (r < 0)
- return r;
+ r = set_simple_string_internal(bus, &error, "pretty hostname", "SetPrettyHostname", p);
+ if (r < 0) {
+ if (implicit &&
+ sd_bus_error_has_names(&error,
+ BUS_ERROR_FILE_IS_PROTECTED,
+ BUS_ERROR_READ_ONLY_FILESYSTEM)) {
+ show_hint = true;
+ ret = r;
+ } else
+ return r;
+ }
/* Now that we set the pretty hostname, let's clean up the parameter and use that as static
* hostname. If the hostname was already valid as static hostname, this will only chop off the trailing
}
if (arg_static) {
- r = set_simple_string(bus, "SetStaticHostname", hostname);
- if (r < 0)
- return r;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ r = set_simple_string_internal(bus, &error, "static hostname", "SetStaticHostname", hostname);
+ if (r < 0) {
+ if (implicit &&
+ sd_bus_error_has_names(&error,
+ BUS_ERROR_FILE_IS_PROTECTED,
+ BUS_ERROR_READ_ONLY_FILESYSTEM)) {
+ show_hint = true;
+ ret = r;
+ } else
+ return r;
+ }
}
if (arg_transient) {
- r = set_simple_string(bus, "SetHostname", hostname);
+ r = set_simple_string(bus, "transient hostname", "SetHostname", hostname);
if (r < 0)
return r;
}
- return 0;
+ if (show_hint)
+ log_info("Hint: use --transient option when /etc/machine-info or /etc/hostname cannot be modified (e.g. located in read-only filesystem).");
+
+ return ret;
}
static int set_icon_name(int argc, char **argv, void *userdata) {
- return set_simple_string(userdata, "SetIconName", argv[1]);
+ return set_simple_string(userdata, "icon", "SetIconName", argv[1]);
}
static int set_chassis(int argc, char **argv, void *userdata) {
- return set_simple_string(userdata, "SetChassis", argv[1]);
+ return set_simple_string(userdata, "chassis", "SetChassis", argv[1]);
}
static int set_deployment(int argc, char **argv, void *userdata) {
- return set_simple_string(userdata, "SetDeployment", argv[1]);
+ return set_simple_string(userdata, "deployment", "SetDeployment", argv[1]);
}
static int set_location(int argc, char **argv, void *userdata) {
- return set_simple_string(userdata, "SetLocation", argv[1]);
+ return set_simple_string(userdata, "location", "SetLocation", argv[1]);
}
static int help(void) {
" --transient Only set transient hostname\n"
" --static Only set static hostname\n"
" --pretty Only set pretty hostname\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
PROP_OS_CPE_NAME,
PROP_OS_HOME_URL,
_PROP_MAX,
- _PROP_INVALID = -1,
+ _PROP_INVALID = -EINVAL,
};
typedef struct Context {
return r; /* 0 if no change, 1 if something was done */
}
+static void unset_statp(struct stat **p) {
+ if (!*p)
+ return;
+
+ **p = (struct stat) {};
+}
+
static int context_write_data_static_hostname(Context *c) {
+ _cleanup_(unset_statp) struct stat *s = NULL;
+ int r;
+
assert(c);
+ /* Make sure that if we fail here, we invalidate the cached information, since it was updated
+ * already, even if we can't make it hit the disk. */
+ s = &c->etc_hostname_stat;
+
if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
- if (unlink("/etc/hostname") < 0)
- return errno == ENOENT ? 0 : -errno;
+ if (unlink("/etc/hostname") < 0 && errno != ENOENT)
+ return -errno;
+
+ TAKE_PTR(s);
return 0;
}
- return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
+ r = write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(s);
+ return 0;
}
static int context_write_data_machine_info(Context *c) {
-
+ _cleanup_(unset_statp) struct stat *s = NULL;
static const char * const name[_PROP_MAX] = {
[PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
[PROP_ICON_NAME] = "ICON_NAME",
[PROP_DEPLOYMENT] = "DEPLOYMENT",
[PROP_LOCATION] = "LOCATION",
};
-
_cleanup_strv_free_ char **l = NULL;
int r;
assert(c);
+ /* Make sure that if we fail here, we invalidate the cached information, since it was updated
+ * already, even if we can't make it hit the disk. */
+ s = &c->etc_machine_info_stat;
+
r = load_env_file(NULL, "/etc/machine-info", &l);
if (r < 0 && r != -ENOENT)
return r;
for (int p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
- _cleanup_free_ char *t = NULL;
- char **u;
-
assert(name[p]);
- if (isempty(c->data[p])) {
- strv_env_unset(l, name[p]);
- continue;
- }
-
- t = strjoin(name[p], "=", c->data[p]);
- if (!t)
- return -ENOMEM;
-
- u = strv_env_set(l, t);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
+ r = strv_env_assign(&l, name[p], empty_to_null(c->data[p]));
+ if (r < 0)
+ return r;
}
if (strv_isempty(l)) {
- if (unlink("/etc/machine-info") < 0)
- return errno == ENOENT ? 0 : -errno;
+ if (unlink("/etc/machine-info") < 0 && errno != ENOENT)
+ return -errno;
+ TAKE_PTR(s);
return 0;
}
- return write_env_file_label("/etc/machine-info", l);
+ r = write_env_file_label("/etc/machine-info", l);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(s);
+ return 0;
}
static int property_get_hardware_vendor(
/* We always go through with the procedure below without comparing to the current hostname, because
* we might want to adjust hostname source information even if the actual hostname is unchanged. */
- if (!hostname_is_valid(name, 0))
+ if (name && !hostname_is_valid(name, 0))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
context_read_etc_hostname(c);
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- r = free_and_strdup(&c->data[PROP_STATIC_HOSTNAME], name);
+ r = free_and_strdup_warn(&c->data[PROP_STATIC_HOSTNAME], name);
if (r < 0)
return r;
r = context_write_data_static_hostname(c);
if (r < 0) {
log_error_errno(r, "Failed to write static hostname: %m");
+ if (ERRNO_IS_PRIVILEGE(r))
+ return sd_bus_error_set(error, BUS_ERROR_FILE_IS_PROTECTED, "Not allowed to update /etc/hostname.");
+ if (r == -EROFS)
+ return sd_bus_error_set(error, BUS_ERROR_READ_ONLY_FILESYSTEM, "/etc/hostname is in a read-only filesystem.");
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
}
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- r = free_and_strdup(&c->data[prop], name);
+ r = free_and_strdup_warn(&c->data[prop], name);
if (r < 0)
return r;
r = context_write_data_machine_info(c);
if (r < 0) {
log_error_errno(r, "Failed to write machine info: %m");
+ if (ERRNO_IS_PRIVILEGE(r))
+ return sd_bus_error_set(error, BUS_ERROR_FILE_IS_PROTECTED, "Not allowed to update /etc/machine-info.");
+ if (r == -EROFS)
+ return sd_bus_error_set(error, BUS_ERROR_READ_ONLY_FILESYSTEM, "/etc/machine-info is in a read-only filesystem.");
return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m");
}
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-hostnamed.service",
"Manage the system hostname and related metadata.",
" -s --strict When updating, return non-zero exit value on any parsing error\n"
" --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
" -r --root=PATH Alternative root path in the filesystem\n\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
" -p --pretty Generate samples of program code\n"
" -a --app-specific=ID Generate app-specific IDs\n"
" -u --uuid Output in UUID format\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
static int run(int argc, char *argv[]) {
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
if (!c)
return -ENOMEM;
- /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */
+ if (DEBUG_LOGGING)
+ (void) curl_easy_setopt(c, CURLOPT_VERBOSE, 1L);
if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK)
return -EIO;
int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value);
int curl_parse_http_time(const char *t, usec_t *ret);
-DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup);
-DEFINE_TRIVIAL_CLEANUP_FUNC(CURLM*, curl_multi_cleanup);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURL*, curl_easy_cleanup, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURLM*, curl_multi_cleanup, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct curl_slist*, curl_slist_free_all, NULL);
#include "sd-id128.h"
#include "alloc-util.h"
+#include "discover-image.h"
#include "export-raw.h"
#include "export-tar.h"
#include "fd-util.h"
#include "fs-util.h"
#include "hostname-util.h"
#include "import-util.h"
-#include "machine-image.h"
#include "main-func.h"
#include "signal-util.h"
#include "string-util.h"
#include "alloc-util.h"
#include "btrfs-util.h"
#include "capability-util.h"
+#include "chattr-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "tmpfile-util.h"
#include "util.h"
int import_make_read_only_fd(int fd) {
+ struct stat st;
int r;
assert(fd >= 0);
/* First, let's make this a read-only subvolume if it refers
* to a subvolume */
r = btrfs_subvol_set_read_only_fd(fd, true);
- if (IN_SET(r, -ENOTTY, -ENOTDIR, -EINVAL)) {
- struct stat st;
+ if (r >= 0)
+ return 0;
- /* This doesn't refer to a subvolume, or the file
- * system isn't even btrfs. In that, case fall back to
- * chmod()ing */
+ if (!ERRNO_IS_NOT_SUPPORTED(r) && !IN_SET(r, -ENOTDIR, -EINVAL))
+ return log_error_errno(r, "Failed to make subvolume read-only: %m");
- r = fstat(fd, &st);
- if (r < 0)
- return log_error_errno(errno, "Failed to stat temporary image: %m");
+ /* This doesn't refer to a subvolume, or the file system isn't even btrfs. In that, case fall back to
+ * chmod()ing */
- /* Drop "w" flag */
- if (fchmod(fd, st.st_mode & 07555) < 0)
- return log_error_errno(errno, "Failed to chmod() final image: %m");
+ r = fstat(fd, &st);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to stat image: %m");
- return 0;
+ if (S_ISDIR(st.st_mode)) {
+ /* For directories set the immutable flag on the dir itself */
- } else if (r < 0)
- return log_error_errno(r, "Failed to make subvolume read-only: %m");
+ r = chattr_fd(fd, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set +i attribute on directory image: %m");
+
+ } else if (S_ISREG(st.st_mode)) {
+ /* For regular files drop "w" flags */
+
+ if ((st.st_mode & 0222) != 0)
+ if (fchmod(fd, st.st_mode & 07555) < 0)
+ return log_error_errno(errno, "Failed to chmod() image: %m");
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EBADFD), "Image of unexpected type");
return 0;
}
}
if (unshare(CLONE_NEWNET) < 0)
- log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
+ log_warning_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
r = capability_bounding_set_drop(retain, true);
if (r < 0)
- log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
+ log_warning_errno(r, "Failed to drop capabilities, ignoring: %m");
/* Try "gtar" before "tar". We only test things upstream with GNU tar. Some distros appear to
* install a different implementation as "tar" (in particular some that do not support the
}
int import_mangle_os_tree(const char *path) {
+ _cleanup_free_ char *child = NULL, *t = NULL, *joined = NULL;
_cleanup_closedir_ DIR *d = NULL, *cd = NULL;
- _cleanup_free_ char *child = NULL, *t = NULL;
- const char *joined;
struct dirent *de;
+ struct stat st;
int r;
assert(path);
if (errno != 0)
return log_error_errno(errno, "Failed to iterate through directory '%s': %m", path);
- log_debug("Directory '%s' does not look like a directory tree, and has multiple children, leaving as it is.", path);
+ log_debug("Directory '%s' does not look like an OS tree, and has multiple children, leaving as it is.", path);
return 0;
}
- joined = prefix_roota(path, child);
+ if (fstatat(dirfd(d), child, &st, AT_SYMLINK_NOFOLLOW) < 0)
+ return log_debug_errno(errno, "Failed to stat file '%s/%s': %m", path, child);
+ r = stat_verify_directory(&st);
+ if (r < 0) {
+ log_debug_errno(r, "Child '%s' of directory '%s' is not a directory, leaving things as they are.", child, path);
+ return 0;
+ }
+
+ joined = path_join(path, child);
+ if (!joined)
+ return log_oom();
r = path_is_os_tree(joined);
if (r == -ENOTDIR) {
- log_debug("Directory '%s' does not look like a directory tree, and contains a single regular file only, leaving as it is.", path);
+ log_debug("Directory '%s' does not look like an OS tree, and contains a single regular file only, leaving as it is.", path);
return 0;
}
if (r < 0)
if (unlinkat(dirfd(d), t, AT_REMOVEDIR) < 0)
return log_error_errno(errno, "Failed to remove temporary directory '%s/%s': %m", path, t);
+ r = futimens(dirfd(d), (struct timespec[2]) { st.st_atim, st.st_mtim });
+ if (r < 0)
+ log_debug_errno(r, "Failed to adjust top-level timestamps '%s', ignoring: %m", path);
+
+ r = fchmod_and_chown(dirfd(d), st.st_mode, st.st_uid, st.st_gid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to adjust top-level directory mode/ownership '%s': %m", path);
+
log_info("Successfully rearranged OS tree.");
return 0;
#include <sys/types.h>
+typedef enum ImportFlags {
+ IMPORT_FORCE = 1 << 0, /* replace existing image */
+ IMPORT_READ_ONLY = 1 << 1, /* make generated image read-only */
+
+ IMPORT_FLAGS_MASK = IMPORT_FORCE|IMPORT_READ_ONLY,
+} ImportFlags;
+
int import_make_read_only_fd(int fd);
int import_make_read_only(const char *path);
return 1;
}
+void import_uncompress_force_off(ImportCompress *c) {
+ assert(c);
+
+ c->type = IMPORT_COMPRESS_UNCOMPRESSED;
+ c->encoding = false;
+}
+
int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) {
int r;
if (!IN_SET(lzr, LZMA_OK, LZMA_STREAM_END))
return -EIO;
- r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata);
- if (r < 0)
- return r;
+ if (c->xz.avail_out < sizeof(buffer)) {
+ r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata);
+ if (r < 0)
+ return r;
+ }
}
break;
if (!IN_SET(r, Z_OK, Z_STREAM_END))
return -EIO;
- r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata);
- if (r < 0)
- return r;
+ if (c->gzip.avail_out < sizeof(buffer)) {
+ r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata);
+ if (r < 0)
+ return r;
+ }
}
break;
if (!IN_SET(r, BZ_OK, BZ_STREAM_END))
return -EIO;
- r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata);
- if (r < 0)
- return r;
+ if (c->bzip2.avail_out < sizeof(buffer)) {
+ r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata);
+ if (r < 0)
+ return r;
+ }
}
break;
IMPORT_COMPRESS_GZIP,
IMPORT_COMPRESS_BZIP2,
_IMPORT_COMPRESS_TYPE_MAX,
- _IMPORT_COMPRESS_TYPE_INVALID = -1,
+ _IMPORT_COMPRESS_TYPE_INVALID = -EINVAL,
} ImportCompressType;
typedef struct ImportCompress {
void import_compress_free(ImportCompress *c);
int import_uncompress_detect(ImportCompress *c, const void *data, size_t size);
+void import_uncompress_force_off(ImportCompress *c);
int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata);
int import_compress_init(ImportCompress *c, ImportCompressType t);
#include "alloc-util.h"
#include "btrfs-util.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-util.h"
-#include "machine-image.h"
#include "mkdir.h"
#include "ratelimit.h"
#include "rm-rf.h"
if (r < 0)
goto finish;
+ (void) import_assign_pool_quota_and_warn(arg_image_root);
(void) import_assign_pool_quota_and_warn(temp_path);
if (arg_read_only) {
void *userdata;
char *local;
- bool force_local;
- bool read_only;
+ ImportFlags flags;
char *temp_path;
char *final_path;
sd_event_unref(i->event);
- if (i->temp_path) {
- (void) unlink(i->temp_path);
- free(i->temp_path);
- }
+ unlink_and_free(i->temp_path);
import_compress_free(&i->compress);
(void) copy_xattr(i->input_fd, i->output_fd);
}
- if (i->read_only) {
+ if (i->flags & IMPORT_READ_ONLY) {
r = import_make_read_only_fd(i->output_fd);
if (r < 0)
return r;
}
- if (i->force_local)
+ if (i->flags & IMPORT_FORCE)
(void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
r = log_error_errno(errno, "Failed to read input file: %m");
goto finish;
}
- if (l == 0) {
- if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
- log_error("Premature end of file.");
- r = -EIO;
- goto finish;
- }
-
- r = raw_import_finish(i);
- goto finish;
- }
i->buffer_size += l;
if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
- r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
- if (r < 0) {
- log_error_errno(r, "Failed to detect file compression: %m");
- goto finish;
+
+ if (l == 0) { /* EOF */
+ log_debug("File too short to be compressed, as no compression signature fits in, thus assuming uncompressed.");
+ import_uncompress_force_off(&i->compress);
+ } else {
+ r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
+ if (r < 0) {
+ log_error_errno(r, "Failed to detect file compression: %m");
+ goto finish;
+ }
+ if (r == 0) /* Need more data */
+ return 0;
}
- if (r == 0) /* Need more data */
- return 0;
r = raw_import_open_disk(i);
if (r < 0)
r = raw_import_try_reflink(i);
if (r < 0)
goto finish;
- if (r > 0) {
- r = raw_import_finish(i);
- goto finish;
- }
+ if (r > 0)
+ goto complete;
}
r = import_uncompress(&i->compress, i->buffer, i->buffer_size, raw_import_write, i);
i->written_compressed += i->buffer_size;
i->buffer_size = 0;
+ if (l == 0) /* EOF */
+ goto complete;
+
raw_import_report_progress(i);
return 0;
+complete:
+ r = raw_import_finish(i);
+
finish:
if (i->on_finished)
i->on_finished(i, r, i->userdata);
return raw_import_process(i);
}
-int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only) {
+int raw_import_start(RawImport *i, int fd, const char *local, ImportFlags flags) {
int r;
assert(i);
assert(fd >= 0);
assert(local);
+ assert(!(flags & ~IMPORT_FLAGS_MASK));
if (!hostname_is_valid(local, 0))
return -EINVAL;
r = free_and_strdup(&i->local, local);
if (r < 0)
return r;
- i->force_local = force_local;
- i->read_only = read_only;
+
+ i->flags = flags;
if (fstat(fd, &i->st) < 0)
return -errno;
#include "sd-event.h"
+#include "import-common.h"
#include "import-util.h"
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(RawImport*, raw_import_unref);
-int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only);
+int raw_import_start(RawImport *i, int fd, const char *local, ImportFlags flags);
void *userdata;
char *local;
- bool force_local;
- bool read_only;
+ ImportFlags flags;
char *temp_path;
char *final_path;
(void) wait_for_terminate(i->tar_pid, NULL);
}
- if (i->temp_path) {
- (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
- free(i->temp_path);
- }
+ rm_rf_subvolume_and_free(i->temp_path);
import_compress_free(&i->compress);
if (r < 0)
return r;
- if (i->read_only) {
+ if (i->flags & IMPORT_READ_ONLY) {
r = import_make_read_only(i->temp_path);
if (r < 0)
return r;
}
- if (i->force_local)
+ if (i->flags & IMPORT_FORCE)
(void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
r = btrfs_subvol_make_fallback(i->temp_path, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create directory/subvolume %s: %m", i->temp_path);
- if (r > 0) /* actually btrfs subvol */
+ if (r > 0) { /* actually btrfs subvol */
+ (void) import_assign_pool_quota_and_warn(i->image_root);
(void) import_assign_pool_quota_and_warn(i->temp_path);
+ }
i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
if (i->tar_fd < 0)
r = log_error_errno(errno, "Failed to read input file: %m");
goto finish;
}
- if (l == 0) {
- if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
- log_error("Premature end of file.");
- r = -EIO;
- goto finish;
- }
-
- r = tar_import_finish(i);
- goto finish;
- }
i->buffer_size += l;
if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
- r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
- if (r < 0) {
- log_error_errno(r, "Failed to detect file compression: %m");
- goto finish;
+
+ if (l == 0) { /* EOF */
+ log_debug("File too short to be compressed, as no compression signature fits in, thus assuming uncompressed.");
+ import_uncompress_force_off(&i->compress);
+ } else {
+ r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
+ if (r < 0) {
+ log_error_errno(r, "Failed to detect file compression: %m");
+ goto finish;
+ }
+ if (r == 0) /* Need more data */
+ return 0;
}
- if (r == 0) /* Need more data */
- return 0;
r = tar_import_fork_tar(i);
if (r < 0)
i->written_compressed += i->buffer_size;
i->buffer_size = 0;
+ if (l == 0) { /* EOF */
+ r = tar_import_finish(i);
+ goto finish;
+ }
+
tar_import_report_progress(i);
return 0;
return tar_import_process(i);
}
-int tar_import_start(TarImport *i, int fd, const char *local, bool force_local, bool read_only) {
+int tar_import_start(TarImport *i, int fd, const char *local, ImportFlags flags) {
int r;
assert(i);
assert(fd >= 0);
assert(local);
+ assert(!(flags & ~IMPORT_FLAGS_MASK));
if (!hostname_is_valid(local, 0))
return -EINVAL;
r = free_and_strdup(&i->local, local);
if (r < 0)
return r;
- i->force_local = force_local;
- i->read_only = read_only;
+
+ i->flags = flags;
if (fstat(fd, &i->st) < 0)
return -errno;
#include "sd-event.h"
+#include "import-common.h"
#include "import-util.h"
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(TarImport*, tar_import_unref);
-int tar_import_start(TarImport *import, int fd, const char *local, bool force_local, bool read_only);
+int tar_import_start(TarImport *import, int fd, const char *local, ImportFlags flags);
#include "sd-id128.h"
#include "alloc-util.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "fs-util.h"
#include "hostname-util.h"
#include "import-raw.h"
#include "import-tar.h"
#include "import-util.h"
-#include "machine-image.h"
#include "main-func.h"
#include "signal-util.h"
#include "string-util.h"
#include "verbs.h"
-static bool arg_force = false;
-static bool arg_read_only = false;
static const char *arg_image_root = "/var/lib/machines";
+static ImportFlags arg_import_flags = 0;
static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
log_notice("Transfer aborted.");
int r, fd;
if (argc >= 2)
- path = argv[1];
- path = empty_or_dash_to_null(path);
+ path = empty_or_dash_to_null(argv[1]);
if (argc >= 3)
- local = argv[2];
+ local = empty_or_dash_to_null(argv[2]);
else if (path)
local = basename(path);
- local = empty_or_dash_to_null(local);
if (local) {
r = tar_strip_suffixes(local, &ll);
"Local image name '%s' is not valid.",
local);
- if (!arg_force) {
+ if (!FLAGS_SET(arg_import_flags, IMPORT_FORCE)) {
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- } else {
+ } else
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
"Image '%s' already exists.",
local);
- }
}
} else
local = "imported";
if (r < 0)
return log_error_errno(r, "Failed to allocate importer: %m");
- r = tar_import_start(import, fd, local, arg_force, arg_read_only);
+ r = tar_import_start(import, fd, local, arg_import_flags);
if (r < 0)
return log_error_errno(r, "Failed to import image: %m");
int r, fd;
if (argc >= 2)
- path = argv[1];
- path = empty_or_dash_to_null(path);
+ path = empty_or_dash_to_null(argv[1]);
if (argc >= 3)
- local = argv[2];
+ local = empty_or_dash_to_null(argv[2]);
else if (path)
local = basename(path);
- local = empty_or_dash_to_null(local);
if (local) {
r = raw_strip_suffixes(local, &ll);
"Local image name '%s' is not valid.",
local);
- if (!arg_force) {
+ if (!FLAGS_SET(arg_import_flags, IMPORT_FORCE)) {
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- } else {
+ } else
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
"Image '%s' already exists.",
local);
- }
}
} else
local = "imported";
if (r < 0)
return log_error_errno(r, "Failed to allocate importer: %m");
- r = raw_import_start(import, fd, local, arg_force, arg_read_only);
+ r = raw_import_start(import, fd, local, arg_import_flags);
if (r < 0)
return log_error_errno(r, "Failed to import image: %m");
return version();
case ARG_FORCE:
- arg_force = true;
+ arg_import_flags |= IMPORT_FORCE;
break;
case ARG_IMAGE_ROOT:
break;
case ARG_READ_ONLY:
- arg_read_only = true;
+ arg_import_flags |= IMPORT_READ_ONLY;
break;
case '?':
#include "bus-log-control-api.h"
#include "bus-polkit.h"
#include "def.h"
+#include "env-util.h"
#include "fd-util.h"
#include "float.h"
#include "hostname-util.h"
TRANSFER_PULL_TAR,
TRANSFER_PULL_RAW,
_TRANSFER_TYPE_MAX,
- _TRANSFER_TYPE_INVALID = -1,
+ _TRANSFER_TYPE_INVALID = -EINVAL,
} TransferType;
struct Transfer {
_exit(EXIT_FAILURE);
}
+ r = setenv_systemd_exec_pid(true);
+ if (r < 0)
+ log_warning_errno(r, "Failed to update $SYSTEMD_EXEC_PID, ignoring: %m");
+
switch (t->type) {
case TRANSFER_IMPORT_TAR:
_cleanup_(manager_unrefp) Manager *m = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-importd.service",
"VM and container image import and export service.",
return 0;
}
-int pull_make_local_copy(const char *final, const char *image_root, const char *local, bool force_local) {
+int pull_make_local_copy(const char *final, const char *image_root, const char *local, PullFlags flags) {
const char *p;
int r;
p = prefix_roota(image_root, local);
- if (force_local)
+ if (FLAGS_SET(flags, PULL_FORCE))
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
r = btrfs_subvol_snapshot(final, p,
_cleanup_(pull_job_unrefp) PullJob *checksum_job = NULL, *signature_job = NULL;
int r;
- const char *chksums = NULL;
assert(ret_checksum_job);
assert(ret_signature_job);
if (verify != IMPORT_VERIFY_NO) {
_cleanup_free_ char *checksum_url = NULL, *fn = NULL;
+ const char *chksums = NULL;
/* Queue jobs for the checksum file for the image. */
r = import_url_last_component(url, &fn);
signature_job->uncompressed_max = signature_job->compressed_max = 1ULL * 1024ULL * 1024ULL;
}
- *ret_checksum_job = checksum_job;
- *ret_signature_job = signature_job;
-
- checksum_job = signature_job = NULL;
+ *ret_checksum_job = TAKE_PTR(checksum_job);
+ *ret_signature_job = TAKE_PTR(signature_job);
return 0;
}
return 1;
}
-int pull_verify(PullJob *main_job,
- PullJob *roothash_job,
- PullJob *settings_job,
- PullJob *checksum_job,
- PullJob *signature_job) {
+static int verify_gpg(
+ const void *payload, size_t payload_size,
+ const void *signature, size_t signature_size) {
_cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 };
- _cleanup_close_ int sig_file = -1;
char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX";
_cleanup_(sigkill_waitp) pid_t pid = 0;
bool gpg_home_created = false;
int r;
- assert(main_job);
- assert(main_job->state == PULL_JOB_DONE);
-
- if (!checksum_job)
- return 0;
-
- assert(main_job->calc_checksum);
- assert(main_job->checksum);
-
- assert(checksum_job->state == PULL_JOB_DONE);
-
- if (!checksum_job->payload || checksum_job->payload_size <= 0)
- return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
- "Checksum is empty, cannot verify.");
-
- r = verify_one(checksum_job, main_job);
- if (r < 0)
- return r;
-
- r = verify_one(checksum_job, roothash_job);
- if (r < 0)
- return r;
-
- r = verify_one(checksum_job, settings_job);
- if (r < 0)
- return r;
-
- if (!signature_job)
- return 0;
-
- if (checksum_job->style == VERIFICATION_PER_FILE)
- signature_job = checksum_job;
-
- assert(signature_job->state == PULL_JOB_DONE);
-
- if (!signature_job->payload || signature_job->payload_size <= 0)
- return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
- "Signature is empty, cannot verify.");
+ assert(payload || payload_size == 0);
+ assert(signature || signature_size == 0);
r = pipe2(gpg_pipe, O_CLOEXEC);
if (r < 0)
return log_error_errno(errno, "Failed to create pipe for gpg: %m");
- sig_file = mkostemp(sig_file_path, O_RDWR);
- if (sig_file < 0)
- return log_error_errno(errno, "Failed to create temporary file: %m");
+ if (signature_size > 0) {
+ _cleanup_close_ int sig_file = -1;
- r = loop_write(sig_file, signature_job->payload, signature_job->payload_size, false);
- if (r < 0) {
- log_error_errno(r, "Failed to write to temporary file: %m");
- goto finish;
+ sig_file = mkostemp(sig_file_path, O_RDWR);
+ if (sig_file < 0)
+ return log_error_errno(errno, "Failed to create temporary file: %m");
+
+ r = loop_write(sig_file, signature, signature_size, false);
+ if (r < 0) {
+ log_error_errno(r, "Failed to write to temporary file: %m");
+ goto finish;
+ }
}
if (!mkdtemp(gpg_home)) {
NULL, /* dash */
NULL /* trailing NULL */
};
- unsigned k = ELEMENTSOF(cmd) - 6;
+ size_t k = ELEMENTSOF(cmd) - 6;
/* Child */
cmd[k++] = strjoina("--homedir=", gpg_home);
- /* We add the user keyring only to the command line
- * arguments, if it's around since gpg fails
+ /* We add the user keyring only to the command line arguments, if it's around since gpg fails
* otherwise. */
if (access(USER_KEYRING_PATH, F_OK) >= 0)
cmd[k++] = "--keyring=" USER_KEYRING_PATH;
cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH;
cmd[k++] = "--verify";
- if (checksum_job->style == VERIFICATION_PER_DIRECTORY) {
+ if (signature) {
cmd[k++] = sig_file_path;
cmd[k++] = "-";
cmd[k++] = NULL;
gpg_pipe[0] = safe_close(gpg_pipe[0]);
- r = loop_write(gpg_pipe[1], checksum_job->payload, checksum_job->payload_size, false);
+ r = loop_write(gpg_pipe[1], payload, payload_size, false);
if (r < 0) {
log_error_errno(r, "Failed to write to pipe: %m");
goto finish;
}
finish:
- (void) unlink(sig_file_path);
+ if (signature_size > 0)
+ (void) unlink(sig_file_path);
if (gpg_home_created)
(void) rm_rf(gpg_home, REMOVE_ROOT|REMOVE_PHYSICAL);
return r;
}
+
+int pull_verify(ImportVerify verify,
+ PullJob *main_job,
+ PullJob *checksum_job,
+ PullJob *signature_job,
+ PullJob *settings_job,
+ PullJob *roothash_job,
+ PullJob *roothash_signature_job,
+ PullJob *verity_job) {
+
+ VerificationStyle style;
+ PullJob *j;
+ int r;
+
+ assert(main_job);
+ assert(main_job->state == PULL_JOB_DONE);
+
+ if (verify == IMPORT_VERIFY_NO)
+ return 0;
+
+ assert(main_job->calc_checksum);
+ assert(main_job->checksum);
+ assert(checksum_job);
+ assert(checksum_job->state == PULL_JOB_DONE);
+
+ if (!checksum_job->payload || checksum_job->payload_size <= 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Checksum is empty, cannot verify.");
+
+ FOREACH_POINTER(j, main_job, settings_job, roothash_job, roothash_signature_job, verity_job) {
+ r = verify_one(checksum_job, j);
+ if (r < 0)
+ return r;
+ }
+
+ if (verify == IMPORT_VERIFY_CHECKSUM)
+ return 0;
+
+ r = verification_style_from_url(checksum_job->url, &style);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine verification style from URL '%s': %m", checksum_job->url);
+
+ if (style == VERIFICATION_PER_DIRECTORY) {
+ assert(signature_job);
+ assert(signature_job->state == PULL_JOB_DONE);
+
+ if (!signature_job->payload || signature_job->payload_size <= 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Signature is empty, cannot verify.");
+
+ return verify_gpg(checksum_job->payload, checksum_job->payload_size, signature_job->payload, signature_job->payload_size);
+ } else
+ return verify_gpg(checksum_job->payload, checksum_job->payload_size, NULL, 0);
+}
+
+int verification_style_from_url(const char *url, VerificationStyle *ret) {
+ _cleanup_free_ char *last = NULL;
+ int r;
+
+ assert(url);
+ assert(ret);
+
+ /* Determines which kind of verification style is appropriate for this url */
+
+ r = import_url_last_component(url, &last);
+ if (r < 0)
+ return r;
+
+ if (streq(last, "SHA256SUMS")) {
+ *ret = VERIFICATION_PER_DIRECTORY;
+ return 0;
+ }
+
+ if (endswith(last, ".sha256")) {
+ *ret = VERIFICATION_PER_FILE;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int pull_job_restart_with_sha256sum(PullJob *j, char **ret) {
+ VerificationStyle style;
+ int r;
+
+ assert(j);
+
+ /* Generic implementation of a PullJobNotFound handler, that restarts the job requesting SHA256SUMS */
+
+ r = verification_style_from_url(j->url, &style);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine verification style of URL '%s': %m", j->url);
+
+ if (style == VERIFICATION_PER_DIRECTORY) /* Nothing to do anymore */
+ return 0;
+
+ assert(style == VERIFICATION_PER_FILE); /* This must have been .sha256 style URL before */
+
+ log_debug("Got 404 for %s, now trying to get SHA256SUMS instead.", j->url);
+
+ r = import_url_change_last_component(j->url, "SHA256SUMS", ret);
+ if (r < 0)
+ return log_error_errno(r, "Failed to replace SHA256SUMS suffix: %m");
+
+ return 1;
+}
#include "import-util.h"
#include "pull-job.h"
-int pull_make_local_copy(const char *final, const char *root, const char *local, bool force_local);
+typedef enum PullFlags {
+ PULL_FORCE = 1 << 0, /* replace existing image */
+ PULL_SETTINGS = 1 << 1, /* .nspawn settings file */
+ PULL_ROOTHASH = 1 << 2, /* only for raw: .roothash file for verity */
+ PULL_ROOTHASH_SIGNATURE = 1 << 3, /* only for raw: .roothash.p7s file for verity */
+ PULL_VERITY = 1 << 4, /* only for raw: .verity file for verity */
+
+ /* The supported flags for the tar and the raw pulling */
+ PULL_FLAGS_MASK_TAR = PULL_FORCE|PULL_SETTINGS,
+ PULL_FLAGS_MASK_RAW = PULL_FORCE|PULL_SETTINGS|PULL_ROOTHASH|PULL_ROOTHASH_SIGNATURE|PULL_VERITY,
+} PullFlags;
+
+int pull_make_local_copy(const char *final, const char *root, const char *local, PullFlags flags);
int pull_find_old_etags(const char *url, const char *root, int dt, const char *prefix, const char *suffix, char ***etags);
int pull_make_auxiliary_job(PullJob **ret, const char *url, int (*strip_suffixes)(const char *name, char **ret), const char *suffix, CurlGlue *glue, PullJobFinished on_finished, void *userdata);
int pull_make_verification_jobs(PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata);
-int pull_verify(PullJob *main_job, PullJob *roothash_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job);
+int pull_verify(ImportVerify verify, PullJob *main_job, PullJob *checksum_job, PullJob *signature_job, PullJob *settings_job, PullJob *roothash_job, PullJob *roothash_signature_job, PullJob *verity_job);
+
+typedef enum VerificationStyle {
+ VERIFICATION_PER_FILE, /* SuSE-style ".sha256" files with inline gpg signature */
+ VERIFICATION_PER_DIRECTORY, /* Ubuntu-style SHA256SUM files with detached SHA256SUM.gpg signatures */
+ _VERIFICATION_STYLE_MAX,
+ _VERIFICATION_STYLE_INVALID = -EINVAL,
+} VerificationStyle;
+
+int verification_style_from_url(const char *url, VerificationStyle *style);
+
+int pull_job_restart_with_sha256sum(PullJob *job, char **ret);
j->on_finished(j);
}
-static int pull_job_restart(PullJob *j) {
+static int pull_job_restart(PullJob *j, const char *new_url) {
int r;
- char *chksum_url = NULL;
- r = import_url_change_last_component(j->url, "SHA256SUMS", &chksum_url);
+ assert(j);
+ assert(new_url);
+
+ r = free_and_strdup(&j->url, new_url);
if (r < 0)
return r;
- free(j->url);
- j->url = chksum_url;
j->state = PULL_JOB_INIT;
+ j->error = 0;
j->payload = mfree(j->payload);
j->payload_size = 0;
j->payload_allocated = 0;
j->written_compressed = 0;
j->written_uncompressed = 0;
+ j->content_length = UINT64_MAX;
+ j->etag = mfree(j->etag);
+ j->etag_exists = false;
+ j->mtime = 0;
+ j->checksum = mfree(j->checksum);
+
+ curl_glue_remove_and_free(j->glue, j->curl);
+ j->curl = NULL;
+
+ curl_slist_free_all(j->request_header);
+ j->request_header = NULL;
+
+ import_compress_free(&j->compress);
+
+ if (j->checksum_context) {
+ gcry_md_close(j->checksum_context);
+ j->checksum_context = NULL;
+ }
r = pull_job_begin(j);
if (r < 0)
r = 0;
goto finish;
} else if (status >= 300) {
- if (status == 404 && j->style == VERIFICATION_PER_FILE) {
- /* retry pull job with SHA256SUMS file */
- r = pull_job_restart(j);
+ if (status == 404 && j->on_not_found) {
+ _cleanup_free_ char *new_url = NULL;
+
+ /* This resource wasn't found, but the implementor wants to maybe let us know a new URL, query for it. */
+ r = j->on_not_found(j, &new_url);
if (r < 0)
goto finish;
- code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status);
- if (code != CURLE_OK) {
- log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
- r = -EIO;
- goto finish;
- }
+ if (r > 0) { /* A new url to use */
+ assert(new_url);
+
+ r = pull_job_restart(j, new_url);
+ if (r < 0)
+ goto finish;
+
+ code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status);
+ if (code != CURLE_OK) {
+ log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
+ r = -EIO;
+ goto finish;
+ }
- if (status == 0) {
- j->style = VERIFICATION_PER_DIRECTORY;
- return;
+ if (status == 0)
+ return;
}
}
return 0;
}
+static int http_status_ok(CURLcode status) {
+ /* Consider all HTTP status code in the 2xx range as OK */
+ return status >= 200 && status <= 299;
+}
+
+static int http_status_etag_exists(CURLcode status) {
+ /* This one is special, it's triggered by our etag mgmt logic */
+ return status == 304;
+}
+
static size_t pull_job_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) {
- PullJob *j = userdata;
+ _cleanup_free_ char *length = NULL, *last_modified = NULL, *etag = NULL;
size_t sz = size * nmemb;
- _cleanup_free_ char *length = NULL, *last_modified = NULL;
- char *etag;
+ PullJob *j = userdata;
+ CURLcode code;
+ long status;
int r;
assert(contents);
assert(j->state == PULL_JOB_ANALYZING);
- r = curl_header_strdup(contents, sz, "ETag:", &etag);
- if (r < 0) {
- log_oom();
+ code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status);
+ if (code != CURLE_OK) {
+ log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
+ r = -EIO;
goto fail;
}
- if (r > 0) {
- free(j->etag);
- j->etag = etag;
- if (strv_contains(j->old_etags, j->etag)) {
- log_info("Image already downloaded. Skipping download.");
- j->etag_exists = true;
- pull_job_finish(j, 0);
+ if (http_status_ok(status) || http_status_etag_exists(status)) {
+ /* Check Etag on OK and etag exists responses. */
+
+ r = curl_header_strdup(contents, sz, "ETag:", &etag);
+ if (r < 0) {
+ log_oom();
+ goto fail;
+ }
+ if (r > 0) {
+ free_and_replace(j->etag, etag);
+
+ if (strv_contains(j->old_etags, j->etag)) {
+ log_info("Image already downloaded. Skipping download. (%s)", j->etag);
+ j->etag_exists = true;
+ pull_job_finish(j, 0);
+ return sz;
+ }
+
return sz;
}
+ }
+ if (!http_status_ok(status)) /* Let's ignore the rest here, these requests are probably redirects and
+ * stuff where the headers aren't interesting to us */
return sz;
- }
r = curl_header_strdup(contents, sz, "Content-Length:", &length);
if (r < 0) {
.start_usec = now(CLOCK_MONOTONIC),
.compressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU, /* 64GB safety limit */
.uncompressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU, /* 64GB safety limit */
- .style = VERIFICATION_STYLE_UNSET,
.url = TAKE_PTR(u),
};
typedef int (*PullJobOpenDisk)(PullJob *job);
typedef int (*PullJobHeader)(PullJob *job, const char *header, size_t sz);
typedef void (*PullJobProgress)(PullJob *job);
+typedef int (*PullJobNotFound)(PullJob *job, char **ret_new_url);
typedef enum PullJobState {
PULL_JOB_INIT,
PULL_JOB_ANALYZING, /* Still reading into ->payload, to figure out what we have */
- PULL_JOB_RUNNING, /* Writing to destination */
+ PULL_JOB_RUNNING, /* Writing to destination */
PULL_JOB_DONE,
PULL_JOB_FAILED,
_PULL_JOB_STATE_MAX,
- _PULL_JOB_STATE_INVALID = -1,
+ _PULL_JOB_STATE_INVALID = -EINVAL,
} PullJobState;
-typedef enum VerificationStyle {
- VERIFICATION_STYLE_UNSET,
- VERIFICATION_PER_FILE, /* SuSE-style ".sha256" files with inline signature */
- VERIFICATION_PER_DIRECTORY, /* Ubuntu-style SHA256SUM files with detach SHA256SUM.gpg signatures */
-} VerificationStyle;
-
#define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED))
struct PullJob {
PullJobOpenDisk on_open_disk;
PullJobHeader on_header;
PullJobProgress on_progress;
+ PullJobNotFound on_not_found;
CurlGlue *glue;
CURL *curl;
gcry_md_hd_t checksum_context;
char *checksum;
-
- VerificationStyle style;
};
int pull_job_new(PullJob **job, const char *url, CurlGlue *glue, void *userdata);
sd_event *event;
CurlGlue *glue;
+ PullFlags flags;
+ ImportVerify verify;
char *image_root;
PullJob *raw_job;
- PullJob *roothash_job;
- PullJob *settings_job;
PullJob *checksum_job;
PullJob *signature_job;
+ PullJob *settings_job;
+ PullJob *roothash_job;
+ PullJob *roothash_signature_job;
+ PullJob *verity_job;
RawPullFinished on_finished;
void *userdata;
char *local;
- bool force_local;
- bool settings;
- bool roothash;
char *final_path;
char *temp_path;
char *roothash_path;
char *roothash_temp_path;
- ImportVerify verify;
+ char *roothash_signature_path;
+ char *roothash_signature_temp_path;
+
+ char *verity_path;
+ char *verity_temp_path;
};
RawPull* raw_pull_unref(RawPull *i) {
return NULL;
pull_job_unref(i->raw_job);
- pull_job_unref(i->settings_job);
- pull_job_unref(i->roothash_job);
pull_job_unref(i->checksum_job);
pull_job_unref(i->signature_job);
+ pull_job_unref(i->settings_job);
+ pull_job_unref(i->roothash_job);
+ pull_job_unref(i->roothash_signature_job);
+ pull_job_unref(i->verity_job);
curl_glue_unref(i->glue);
sd_event_unref(i->event);
- if (i->temp_path) {
- (void) unlink(i->temp_path);
- free(i->temp_path);
- }
-
- if (i->roothash_temp_path) {
- (void) unlink(i->roothash_temp_path);
- free(i->roothash_temp_path);
- }
-
- if (i->settings_temp_path) {
- (void) unlink(i->settings_temp_path);
- free(i->settings_temp_path);
- }
+ unlink_and_free(i->temp_path);
+ unlink_and_free(i->settings_temp_path);
+ unlink_and_free(i->roothash_temp_path);
+ unlink_and_free(i->roothash_signature_temp_path);
+ unlink_and_free(i->verity_temp_path);
free(i->final_path);
- free(i->roothash_path);
free(i->settings_path);
+ free(i->roothash_path);
+ free(i->roothash_signature_path);
+ free(i->verity_path);
free(i->image_root);
free(i->local);
+
return mfree(i);
}
percent = 0;
+ if (i->checksum_job) {
+ percent += i->checksum_job->progress_percent * 5 / 100;
+ remain -= 5;
+ }
+
+ if (i->signature_job) {
+ percent += i->signature_job->progress_percent * 5 / 100;
+ remain -= 5;
+ }
+
if (i->settings_job) {
percent += i->settings_job->progress_percent * 5 / 100;
remain -= 5;
remain -= 5;
}
- if (i->checksum_job) {
- percent += i->checksum_job->progress_percent * 5 / 100;
+ if (i->roothash_signature_job) {
+ percent += i->roothash_signature_job->progress_percent * 5 / 100;
remain -= 5;
}
- if (i->signature_job) {
- percent += i->signature_job->progress_percent * 5 / 100;
- remain -= 5;
+ if (i->verity_job) {
+ percent += i->verity_job->progress_percent * 10 / 100;
+ remain -= 10;
}
if (i->raw_job)
local = strjoina(i->image_root, "/", i->local, suffix);
- r = copy_file_atomic(*path, local, 0644, 0, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0));
+ r = copy_file_atomic(*path, local, 0644, 0, 0, COPY_REFLINK | (FLAGS_SET(i->flags, PULL_FORCE) ? COPY_REPLACE : 0));
if (r == -EEXIST)
log_warning_errno(r, "File %s already exists, not replacing.", local);
else if (r == -ENOENT)
p = strjoina(i->image_root, "/", i->local, ".raw");
- if (i->force_local)
+ if (FLAGS_SET(i->flags, PULL_FORCE))
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
r = tempfn_random(p, NULL, &tp);
log_info("Created new local image '%s'.", i->local);
- if (i->roothash) {
+ if (FLAGS_SET(i->flags, PULL_SETTINGS)) {
+ r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path);
+ if (r < 0)
+ return r;
+ }
+
+ if (FLAGS_SET(i->flags, PULL_ROOTHASH)) {
r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path);
if (r < 0)
return r;
}
- if (i->settings) {
- r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path);
+ if (FLAGS_SET(i->flags, PULL_ROOTHASH_SIGNATURE)) {
+ r = raw_pull_copy_auxiliary_file(i, ".roothash.p7s", &i->roothash_signature_path);
+ if (r < 0)
+ return r;
+ }
+
+ if (FLAGS_SET(i->flags, PULL_VERITY)) {
+ r = raw_pull_copy_auxiliary_file(i, ".verity", &i->verity_path);
if (r < 0)
return r;
}
if (!PULL_JOB_IS_COMPLETE(i->raw_job))
return false;
- if (i->roothash_job && !PULL_JOB_IS_COMPLETE(i->roothash_job))
+ if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
+ return false;
+ if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
return false;
if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
return false;
- if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
+ if (i->roothash_job && !PULL_JOB_IS_COMPLETE(i->roothash_job))
return false;
- if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
+ if (i->roothash_signature_job && !PULL_JOB_IS_COMPLETE(i->roothash_signature_job))
+ return false;
+ if (i->verity_job && !PULL_JOB_IS_COMPLETE(i->verity_job))
return false;
return true;
assert(j->userdata);
i = j->userdata;
- if (j == i->roothash_job) {
+ if (j == i->settings_job) {
+ if (j->error != 0)
+ log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
+ } else if (j == i->roothash_job) {
if (j->error != 0)
log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without.");
- } else if (j == i->settings_job) {
+ } else if (j == i->roothash_signature_job) {
if (j->error != 0)
- log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
+ log_info_errno(j->error, "Root hash signature file could not be retrieved, proceeding without.");
+ } else if (j == i->verity_job) {
+ if (j->error != 0)
+ log_info_errno(j->error, "Verity integrity file could not be retrieved, proceeding without. %s", j->url);
} else if (j->error != 0 && j != i->signature_job) {
if (j == i->checksum_job)
log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
goto finish;
}
- /* This is invoked if either the download completed
- * successfully, or the download was skipped because we
- * already have the etag. In this case ->etag_exists is
- * true.
+ /* This is invoked if either the download completed successfully, or the download was skipped because
+ * we already have the etag. In this case ->etag_exists is true.
*
* We only do something when we got all three files */
if (!raw_pull_is_done(i))
return;
- if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
- log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+ if (i->signature_job && i->signature_job->error != 0) {
+ VerificationStyle style;
- r = i->signature_job->error;
- goto finish;
+ r = verification_style_from_url(i->checksum_job->url, &style);
+ if (r < 0) {
+ log_error_errno(r, "Failed to determine verification style from checksum URL: %m");
+ goto finish;
+ }
+
+ if (style == VERIFICATION_PER_DIRECTORY) { /* A failed signature file download only matters
+ * in per-directory verification mode, since only
+ * then the signature is detached, and thus a file
+ * of its own. */
+ log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+ r = i->signature_job->error;
+ goto finish;
+ }
}
- if (i->roothash_job)
- i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
if (i->settings_job)
i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
+ if (i->roothash_job)
+ i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
+ if (i->roothash_signature_job)
+ i->roothash_signature_job->disk_fd = safe_close(i->roothash_signature_job->disk_fd);
+ if (i->verity_job)
+ i->verity_job->disk_fd = safe_close(i->verity_job->disk_fd);
r = raw_pull_determine_path(i, ".raw", &i->final_path);
if (r < 0)
raw_pull_report_progress(i, RAW_VERIFYING);
- r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job);
+ r = pull_verify(i->verify,
+ i->raw_job,
+ i->checksum_job,
+ i->signature_job,
+ i->settings_job,
+ i->roothash_job,
+ i->roothash_signature_job,
+ i->verity_job);
if (r < 0)
goto finish;
return 0;
}
+static int raw_pull_job_on_open_disk_settings(PullJob *j) {
+ RawPull *i;
+
+ assert(j);
+ assert(j->userdata);
+
+ i = j->userdata;
+ assert(i->settings_job == j);
+
+ return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path);
+}
+
static int raw_pull_job_on_open_disk_roothash(PullJob *j) {
RawPull *i;
return raw_pull_job_on_open_disk_generic(i, j, "roothash", &i->roothash_temp_path);
}
-static int raw_pull_job_on_open_disk_settings(PullJob *j) {
+static int raw_pull_job_on_open_disk_roothash_signature(PullJob *j) {
RawPull *i;
assert(j);
assert(j->userdata);
i = j->userdata;
- assert(i->settings_job == j);
+ assert(i->roothash_signature_job == j);
- return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path);
+ return raw_pull_job_on_open_disk_generic(i, j, "roothash.p7s", &i->roothash_signature_temp_path);
+}
+
+static int raw_pull_job_on_open_disk_verity(PullJob *j) {
+ RawPull *i;
+
+ assert(j);
+ assert(j->userdata);
+
+ i = j->userdata;
+ assert(i->verity_job == j);
+
+ return raw_pull_job_on_open_disk_generic(i, j, "verity", &i->verity_temp_path);
}
static void raw_pull_job_on_progress(PullJob *j) {
RawPull *i,
const char *url,
const char *local,
- bool force_local,
- ImportVerify verify,
- bool settings,
- bool roothash) {
+ PullFlags flags,
+ ImportVerify verify) {
int r;
assert(i);
assert(verify < _IMPORT_VERIFY_MAX);
assert(verify >= 0);
+ assert(!(flags & ~PULL_FLAGS_MASK_RAW));
if (!http_url_is_valid(url))
return -EINVAL;
if (r < 0)
return r;
- i->force_local = force_local;
+ i->flags = flags;
i->verify = verify;
- i->settings = settings;
- i->roothash = roothash;
/* Queue job for the image itself */
r = pull_job_new(&i->raw_job, url, i->glue, i);
if (r < 0)
return r;
- if (roothash) {
+ r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
+ if (FLAGS_SET(flags, PULL_SETTINGS)) {
+ r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
+ i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
+ i->settings_job->on_progress = raw_pull_job_on_progress;
+ i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+ }
+
+ if (FLAGS_SET(flags, PULL_ROOTHASH)) {
r = pull_make_auxiliary_job(&i->roothash_job, url, raw_strip_suffixes, ".roothash", i->glue, raw_pull_job_on_finished, i);
if (r < 0)
return r;
i->roothash_job->calc_checksum = verify != IMPORT_VERIFY_NO;
}
- if (settings) {
- r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i);
+ if (FLAGS_SET(flags, PULL_ROOTHASH_SIGNATURE)) {
+ r = pull_make_auxiliary_job(&i->roothash_signature_job, url, raw_strip_suffixes, ".roothash.p7s", i->glue, raw_pull_job_on_finished, i);
if (r < 0)
return r;
- i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
- i->settings_job->on_progress = raw_pull_job_on_progress;
- i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+ i->roothash_signature_job->on_open_disk = raw_pull_job_on_open_disk_roothash_signature;
+ i->roothash_signature_job->on_progress = raw_pull_job_on_progress;
+ i->roothash_signature_job->calc_checksum = verify != IMPORT_VERIFY_NO;
}
- r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
- if (r < 0)
- return r;
+ if (FLAGS_SET(flags, PULL_VERITY)) {
+ r = pull_make_auxiliary_job(&i->verity_job, url, raw_strip_suffixes, ".verity", i->glue, raw_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
+ i->verity_job->on_open_disk = raw_pull_job_on_open_disk_verity;
+ i->verity_job->on_progress = raw_pull_job_on_progress;
+ i->verity_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+ }
r = pull_job_begin(i->raw_job);
if (r < 0)
return r;
- if (i->roothash_job) {
- r = pull_job_begin(i->roothash_job);
+ if (i->checksum_job) {
+ i->checksum_job->on_progress = raw_pull_job_on_progress;
+ i->checksum_job->on_not_found = pull_job_restart_with_sha256sum;
+
+ r = pull_job_begin(i->checksum_job);
+ if (r < 0)
+ return r;
+ }
+
+ if (i->signature_job) {
+ i->signature_job->on_progress = raw_pull_job_on_progress;
+
+ r = pull_job_begin(i->signature_job);
if (r < 0)
return r;
}
return r;
}
- if (i->checksum_job) {
- i->checksum_job->on_progress = raw_pull_job_on_progress;
- i->checksum_job->style = VERIFICATION_PER_FILE;
-
- r = pull_job_begin(i->checksum_job);
+ if (i->roothash_job) {
+ r = pull_job_begin(i->roothash_job);
if (r < 0)
return r;
}
- if (i->signature_job) {
- i->signature_job->on_progress = raw_pull_job_on_progress;
+ if (i->roothash_signature_job) {
+ r = pull_job_begin(i->roothash_signature_job);
+ if (r < 0)
+ return r;
+ }
- r = pull_job_begin(i->signature_job);
+ if (i->verity_job) {
+ r = pull_job_begin(i->verity_job);
if (r < 0)
return r;
}
#include "import-util.h"
#include "macro.h"
+#include "pull-common.h"
typedef struct RawPull RawPull;
DEFINE_TRIVIAL_CLEANUP_FUNC(RawPull*, raw_pull_unref);
-int raw_pull_start(RawPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings, bool roothash);
+int raw_pull_start(RawPull *pull, const char *url, const char *local, PullFlags flags, ImportVerify verify);
sd_event *event;
CurlGlue *glue;
+ PullFlags flags;
+ ImportVerify verify;
char *image_root;
PullJob *tar_job;
- PullJob *settings_job;
PullJob *checksum_job;
PullJob *signature_job;
+ PullJob *settings_job;
TarPullFinished on_finished;
void *userdata;
char *local;
- bool force_local;
- bool settings;
pid_t tar_pid;
char *settings_path;
char *settings_temp_path;
-
- ImportVerify verify;
};
TarPull* tar_pull_unref(TarPull *i) {
}
pull_job_unref(i->tar_job);
- pull_job_unref(i->settings_job);
pull_job_unref(i->checksum_job);
pull_job_unref(i->signature_job);
+ pull_job_unref(i->settings_job);
curl_glue_unref(i->glue);
sd_event_unref(i->event);
- if (i->temp_path) {
- (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
- free(i->temp_path);
- }
-
- if (i->settings_temp_path) {
- (void) unlink(i->settings_temp_path);
- free(i->settings_temp_path);
- }
+ rm_rf_subvolume_and_free(i->temp_path);
+ unlink_and_free(i->settings_temp_path);
free(i->final_path);
free(i->settings_path);
percent = 0;
- if (i->settings_job) {
- percent += i->settings_job->progress_percent * 5 / 100;
- remain -= 5;
- }
-
if (i->checksum_job) {
percent += i->checksum_job->progress_percent * 5 / 100;
remain -= 5;
remain -= 5;
}
+ if (i->settings_job) {
+ percent += i->settings_job->progress_percent * 5 / 100;
+ remain -= 5;
+ }
+
if (i->tar_job)
percent += i->tar_job->progress_percent * remain / 100;
break;
if (!i->local)
return 0;
- r = pull_make_local_copy(i->final_path, i->image_root, i->local, i->force_local);
+ r = pull_make_local_copy(i->final_path, i->image_root, i->local, i->flags);
if (r < 0)
return r;
- if (i->settings) {
+ if (FLAGS_SET(i->flags, PULL_SETTINGS)) {
const char *local_settings;
assert(i->settings_job);
local_settings = strjoina(i->image_root, "/", i->local, ".nspawn");
- r = copy_file_atomic(i->settings_path, local_settings, 0664, 0, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0));
+ r = copy_file_atomic(i->settings_path, local_settings, 0664, 0, 0, COPY_REFLINK | (FLAGS_SET(i->flags, PULL_FORCE) ? COPY_REPLACE : 0));
if (r == -EEXIST)
log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
else if (r == -ENOENT)
if (!PULL_JOB_IS_COMPLETE(i->tar_job))
return false;
- if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
- return false;
if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
return false;
if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
return false;
+ if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
+ return false;
return true;
}
if (!tar_pull_is_done(i))
return;
- if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
- log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+ if (i->signature_job && i->signature_job->error != 0) {
+ VerificationStyle style;
- r = i->signature_job->error;
- goto finish;
+ r = verification_style_from_url(i->checksum_job->url, &style);
+ if (r < 0) {
+ log_error_errno(r, "Failed to determine verification style from checksum URL: %m");
+ goto finish;
+ }
+
+ if (style == VERIFICATION_PER_DIRECTORY) { /* A failed signature file download only matters
+ * in per-directory verification mode, since only
+ * then the signature is detached, and thus a file
+ * of its own. */
+ log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+ r = i->signature_job->error;
+ goto finish;
+ }
}
i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd);
tar_pull_report_progress(i, TAR_VERIFYING);
- r = pull_verify(i->tar_job, NULL, i->settings_job, i->checksum_job, i->signature_job);
+ r = pull_verify(i->verify,
+ i->tar_job,
+ i->checksum_job,
+ i->signature_job,
+ i->settings_job,
+ /* roothash_job = */ NULL,
+ /* roothash_signature_job = */ NULL,
+ /* verity_job = */ NULL);
if (r < 0)
goto finish;
r = btrfs_subvol_make_fallback(i->temp_path, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create directory/subvolume %s: %m", i->temp_path);
- if (r > 0) /* actually btrfs subvol */
+ if (r > 0) { /* actually btrfs subvol */
+ (void) import_assign_pool_quota_and_warn(i->image_root);
(void) import_assign_pool_quota_and_warn(i->temp_path);
+ }
j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
if (j->disk_fd < 0)
TarPull *i,
const char *url,
const char *local,
- bool force_local,
- ImportVerify verify,
- bool settings) {
+ PullFlags flags,
+ ImportVerify verify) {
int r;
assert(i);
assert(verify < _IMPORT_VERIFY_MAX);
assert(verify >= 0);
+ assert(!(flags & ~PULL_FLAGS_MASK_TAR));
if (!http_url_is_valid(url))
return -EINVAL;
if (r < 0)
return r;
- i->force_local = force_local;
+ i->flags = flags;
i->verify = verify;
- i->settings = settings;
/* Set up download job for TAR file */
r = pull_job_new(&i->tar_job, url, i->glue, i);
if (r < 0)
return r;
+ /* Set up download of checksum/signature files */
+ r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
/* Set up download job for the settings file (.nspawn) */
- if (settings) {
+ if (FLAGS_SET(flags, PULL_SETTINGS)) {
r = pull_make_auxiliary_job(&i->settings_job, url, tar_strip_suffixes, ".nspawn", i->glue, tar_pull_job_on_finished, i);
if (r < 0)
return r;
i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
}
- /* Set up download of checksum/signature files */
- r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_pull_job_on_finished, i);
- if (r < 0)
- return r;
-
r = pull_job_begin(i->tar_job);
if (r < 0)
return r;
- if (i->settings_job) {
- r = pull_job_begin(i->settings_job);
- if (r < 0)
- return r;
- }
-
if (i->checksum_job) {
i->checksum_job->on_progress = tar_pull_job_on_progress;
- i->checksum_job->style = VERIFICATION_PER_FILE;
+ i->checksum_job->on_not_found = pull_job_restart_with_sha256sum;
r = pull_job_begin(i->checksum_job);
if (r < 0)
return r;
}
+ if (i->settings_job) {
+ r = pull_job_begin(i->settings_job);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
#include "import-util.h"
#include "macro.h"
+#include "pull-common.h"
typedef struct TarPull TarPull;
DEFINE_TRIVIAL_CLEANUP_FUNC(TarPull*, tar_pull_unref);
-int tar_pull_start(TarPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings);
+int tar_pull_start(TarPull *pull, const char *url, const char *local, PullFlags flags, ImportVerify verify);
#include "sd-id128.h"
#include "alloc-util.h"
+#include "discover-image.h"
#include "hostname-util.h"
#include "import-util.h"
-#include "machine-image.h"
#include "main-func.h"
#include "parse-util.h"
#include "pull-raw.h"
#include "verbs.h"
#include "web-util.h"
-static bool arg_force = false;
static const char *arg_image_root = "/var/lib/machines";
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static bool arg_settings = true;
-static bool arg_roothash = true;
+static PullFlags arg_pull_flags = PULL_SETTINGS | PULL_ROOTHASH | PULL_ROOTHASH_SIGNATURE | PULL_VERITY;
static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
log_notice("Transfer aborted.");
"Local image name '%s' is not valid.",
local);
- if (!arg_force) {
+ if (!FLAGS_SET(arg_pull_flags, PULL_FORCE)) {
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
if (r < 0)
return log_error_errno(r, "Failed to allocate puller: %m");
- r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings);
+ r = tar_pull_start(pull, url, local, arg_pull_flags & PULL_FLAGS_MASK_TAR, arg_verify);
if (r < 0)
return log_error_errno(r, "Failed to pull image: %m");
"Local image name '%s' is not valid.",
local);
- if (!arg_force) {
+ if (!FLAGS_SET(arg_pull_flags, PULL_FORCE)) {
r = image_find(IMAGE_MACHINE, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
if (r < 0)
return log_error_errno(r, "Failed to allocate puller: %m");
- r = raw_pull_start(pull, url, local, arg_force, arg_verify, arg_settings, arg_roothash);
+ r = raw_pull_start(pull, url, local, arg_pull_flags & PULL_FLAGS_MASK_RAW, arg_verify);
if (r < 0)
return log_error_errno(r, "Failed to pull image: %m");
" 'checksum', 'signature'\n"
" --settings=BOOL Download settings file with image\n"
" --roothash=BOOL Download root hash file with image\n"
+ " --roothash-signature=BOOL\n"
+ " Download root hash signature file with image\n"
+ " --verity=BOOL Download verity file with image\n"
" --image-root=PATH Image root directory\n\n"
"Commands:\n"
" tar URL [NAME] Download a TAR image\n"
ARG_VERIFY,
ARG_SETTINGS,
ARG_ROOTHASH,
+ ARG_ROOTHASH_SIGNATURE,
+ ARG_VERITY,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "force", no_argument, NULL, ARG_FORCE },
- { "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
- { "verify", required_argument, NULL, ARG_VERIFY },
- { "settings", required_argument, NULL, ARG_SETTINGS },
- { "roothash", required_argument, NULL, ARG_ROOTHASH },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "force", no_argument, NULL, ARG_FORCE },
+ { "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
+ { "verify", required_argument, NULL, ARG_VERIFY },
+ { "settings", required_argument, NULL, ARG_SETTINGS },
+ { "roothash", required_argument, NULL, ARG_ROOTHASH },
+ { "roothash-signature", required_argument, NULL, ARG_ROOTHASH_SIGNATURE },
+ { "verity", required_argument, NULL, ARG_VERITY },
{}
};
return version();
case ARG_FORCE:
- arg_force = true;
+ arg_pull_flags |= PULL_FORCE;
break;
case ARG_IMAGE_ROOT:
if (r < 0)
return log_error_errno(r, "Failed to parse --settings= parameter '%s': %m", optarg);
- arg_settings = r;
+ SET_FLAG(arg_pull_flags, PULL_SETTINGS, r);
break;
case ARG_ROOTHASH:
if (r < 0)
return log_error_errno(r, "Failed to parse --roothash= parameter '%s': %m", optarg);
- arg_roothash = r;
+ SET_FLAG(arg_pull_flags, PULL_ROOTHASH, r);
+
+ /* If we were asked to turn off the root hash, implicitly also turn off the root hash signature */
+ if (!r)
+ SET_FLAG(arg_pull_flags, PULL_ROOTHASH_SIGNATURE, false);
+ break;
+
+ case ARG_ROOTHASH_SIGNATURE:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --roothash-signature= parameter '%s': %m", optarg);
+
+ SET_FLAG(arg_pull_flags, PULL_ROOTHASH_SIGNATURE, r);
+ break;
+
+ case ARG_VERITY:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --verity= parameter '%s': %m", optarg);
+
+ SET_FLAG(arg_pull_flags, PULL_VERITY, r);
break;
case '?':
return 0;
}
-static void fifo_free(Fifo *f) {
- assert(f);
+static Fifo* fifo_free(Fifo *f) {
+ if (!f)
+ return NULL;
if (f->server) {
assert(f->server->n_fifos > 0);
safe_close(f->fd);
}
- free(f);
+ return mfree(f);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program does not take arguments.");
- log_setup_service();
+ log_setup();
umask(0022);
<!DOCTYPE html>
+<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<html>
<head>
<title>Journal</title>
#include "strv.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- _cleanup_fclose_ FILE *dev_null = NULL;
- RemoteServer s = {};
- char name[] = "/tmp/fuzz-journal-remote.XXXXXX.journal";
+ int fdin;
void *mem;
- int fdin; /* will be closed by journal_remote handler after EOF */
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journal-remote.XXXXXX.journal";
_cleanup_close_ int fdout = -1;
- sd_journal *j;
- OutputMode mode;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
+ RemoteServer s = {};
int r;
if (size <= 2)
if (!getenv("SYSTEMD_LOG_LEVEL"))
log_set_max_level(LOG_CRIT);
- assert_se((fdin = memfd_new_and_map("fuzz-journal-remote", size, &mem)) >= 0);
+ fdin = memfd_new_and_map("fuzz-journal-remote", size, &mem);
+ if (fdin < 0)
+ return log_error_errno(fdin, "memfd_new_and_map() failed: %m");
+
memcpy(mem, data, size);
assert_se(munmap(mem, size) == 0);
fdout = mkostemps(name, STRLEN(".journal"), O_CLOEXEC);
- assert_se(fdout >= 0);
+ if (fdout < 0)
+ return log_error_errno(errno, "mkostemps() failed: %m");
/* In */
- assert_se(journal_remote_server_init(&s, name, JOURNAL_WRITE_SPLIT_NONE, false, false) >= 0);
-
- assert_se(journal_remote_add_source(&s, fdin, (char*) "fuzz-data", false) > 0);
+ r = journal_remote_server_init(&s, name, JOURNAL_WRITE_SPLIT_NONE, false, false);
+ if (r < 0) {
+ assert_se(IN_SET(r, -ENOMEM, -EMFILE, -ENFILE));
+ return r;
+ }
- while (s.active) {
- r = journal_remote_handle_raw_source(NULL, fdin, 0, &s);
- assert_se(r >= 0);
+ r = journal_remote_add_source(&s, fdin, (char*) "fuzz-data", false);
+ if (r < 0) {
+ safe_close(fdin);
+ return r;
}
+ assert(r > 0);
+
+ while (s.active)
+ assert_se(journal_remote_handle_raw_source(NULL, fdin, 0, &s) >= 0);
journal_remote_server_destroy(&s);
assert_se(close(fdin) < 0 && errno == EBADF); /* Check that the fd is closed already */
/* Out */
r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0);
- assert_se(r >= 0);
+ if (r < 0) {
+ assert_se(IN_SET(r, -ENOMEM, -EMFILE, -ENFILE));
+ return r;
+ }
- if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0)
- assert_se(dev_null = fopen("/dev/null", "we"));
+ _cleanup_fclose_ FILE *dev_null = NULL;
+ if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
+ dev_null = fopen("/dev/null", "we");
+ if (!dev_null)
+ return log_error_errno(errno, "fopen(\"/dev/null\") failed: %m");
+ }
- for (mode = 0; mode < _OUTPUT_MODE_MAX; mode++) {
+ for (OutputMode mode = 0; mode < _OUTPUT_MODE_MAX; mode++) {
if (!dev_null)
log_info("/* %s */", output_mode_to_string(mode));
r = show_journal(dev_null ?: stdout, j, mode, 0, 0, -1, 0, NULL);
assert_se(r >= 0);
}
- sd_journal_close(j);
- unlink(name);
-
return 0;
}
" --key=KEY.PEM Server key in PEM format\n"
" --trust=CERT.PEM Certificate authority certificate in PEM format\n"
" -D --directory=PATH Serve journal files in directory\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
MHD_USE_THREAD_PER_CONNECTION;
int r, n;
- log_setup_service();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
" Specify a list of gnutls logging categories\n"
" --split-mode=none|host How many output files to create\n"
"\nNote: file descriptors from sd_listen_fds() will be consumed, too.\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
case ARG_SPLIT_MODE:
arg_split_mode = journal_write_split_mode_from_string(optarg);
if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid split mode: %s", optarg);
+ return log_error_errno(arg_split_mode, "Invalid split mode: %s", optarg);
break;
case ARG_COMPRESS:
if (optarg) {
r = parse_boolean(optarg);
if (r < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse --compress= parameter.");
+ return log_error_errno(r, "Failed to parse --compress= parameter.");
arg_compress = !!r;
} else
int r;
log_show_color(true);
- log_parse_environment_cli();
+ log_parse_environment();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
JOURNAL_WRITE_SPLIT_NONE,
JOURNAL_WRITE_SPLIT_HOST,
_JOURNAL_WRITE_SPLIT_MAX,
- _JOURNAL_WRITE_SPLIT_INVALID = -1
+ _JOURNAL_WRITE_SPLIT_INVALID = -EINVAL,
} JournalWriteSplitMode;
assert(url);
*u = (Uploader) {
- .input = -1
+ .input = -1,
};
host = STARTSWITH_SET(url, "http://", "https://");
" --follow[=BOOL] Do [not] wait for input\n"
" --save-state[=FILE] Save uploaded cursors (default \n"
" " STATE_FILE ")\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
int r;
log_show_color(true);
- log_parse_environment_cli();
+ log_parse_environment();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
import sys
import argparse
*/
int setup_gnutls_logger(char **categories);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Response*, MHD_destroy_response);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Daemon*, MHD_stop_daemon, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Response*, MHD_destroy_response, NULL);
" -p --priority=PRIORITY Set priority value (0..7)\n"
" --stderr-priority=PRIORITY Set priority value (0..7) used for stderr\n"
" --level-prefix=BOOL Control whether level prefix shall be parsed\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
_cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1;
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pcre2-dlopen.h"
} BootId;
#if HAVE_PCRE2
-DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_match_data*, sym_pcre2_match_data_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_code*, sym_pcre2_code_free, NULL);
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
int errorcode, r;
" --dump-catalog Show entries in the message catalog\n"
" --update-catalog Update the message catalog database\n"
" --setup-keys Generate a new FSS key pair\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal()
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
arg_output = output_mode_from_string(optarg);
if (arg_output < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown output format '%s'.", optarg);
+ return log_error_errno(arg_output, "Unknown output format '%s'.", optarg);
if (IN_SET(arg_output, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ, OUTPUT_CAT))
arg_quiet = true;
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ true, &arg_root);
+ r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
if (r < 0)
return r;
break;
case ARG_IMAGE:
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
if (r < 0)
return r;
break;
to = log_level_from_string(dots + 2);
if (from < 0 || to < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ return log_error_errno(from < 0 ? from : to,
"Failed to parse log level range %s", optarg);
arg_priorities = 0;
p = log_level_from_string(optarg);
if (p < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown log level %s", optarg);
+ return log_error_errno(p, "Unknown log level %s", optarg);
arg_priorities = 0;
num = log_facility_unshifted_from_string(fac);
if (num < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Bad --facility= argument \"%s\".", fac);
+ return log_error_errno(num, "Bad --facility= argument \"%s\".", fac);
if (set_ensure_put(&arg_facilities, NULL, INT_TO_PTR(num)) < 0)
return log_oom();
int n_shown = 0, r, poll_fd = -1;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
/* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
* split up into many files. */
ll = log_level_from_string(value);
if (ll < 0)
- return -EINVAL;
+ return ll;
c->log_level_max = ll;
return 0;
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
assert(s);
- r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY);
+ r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return r;
STORAGE_PERSISTENT,
STORAGE_NONE,
_STORAGE_MAX,
- _STORAGE_INVALID = -1
+ _STORAGE_INVALID = -EINVAL,
} Storage;
typedef enum SplitMode {
SPLIT_LOGIN, /* deprecated */
SPLIT_NONE,
_SPLIT_MAX,
- _SPLIT_INVALID = -1
+ _SPLIT_INVALID = -EINVAL,
} SplitMode;
typedef struct JournalCompressOptions {
LINE_BREAK_EOF,
LINE_BREAK_PID_CHANGE,
_LINE_BREAK_MAX,
- _LINE_BREAK_INVALID = -1,
+ _LINE_BREAK_INVALID = -EINVAL,
} LineBreak;
struct StdoutStream {
char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
};
-void stdout_stream_free(StdoutStream *s) {
+StdoutStream* stdout_stream_free(StdoutStream *s) {
if (!s)
- return;
+ return NULL;
if (s->server) {
free(s->state_file);
free(s->buffer);
- free(s);
+ return mfree(s);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
int server_open_stdout_socket(Server *s, const char *stdout_socket);
int server_restore_streams(Server *s, FDSet *fds);
-void stdout_stream_free(StdoutStream *s);
+StdoutStream* stdout_stream_free(StdoutStream *s);
int stdout_stream_install(Server *s, int fd, StdoutStream **ret);
void stdout_stream_destroy(StdoutStream *s);
void stdout_stream_send_notify(StdoutStream *s);
#!/usr/bin/env bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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/>.
COMMAND="$1"
KERNEL_VERSION="$2"
fi
if [[ $COMMAND != add ]]; then
- exit 0
+ exit 0
fi
# If the boot dir exists (e.g. $ESP/<machine-id>),
#!/usr/bin/env bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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/>.
COMMAND="$1"
KERNEL_VERSION="$2"
#!/usr/bin/env bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# 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/>.
COMMAND="$1"
KERNEL_VERSION="$2"
fi
cp "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" &&
- chown root:root "$ENTRY_DIR_ABS/linux" &&
- chmod 0644 "$ENTRY_DIR_ABS/linux" || {
- echo "Could not copy '$KERNEL_IMAGE to '$ENTRY_DIR_ABS/linux'." >&2
- exit 1
-}
+ chown root:root "$ENTRY_DIR_ABS/linux" &&
+ chmod 0644 "$ENTRY_DIR_ABS/linux" || {
+ echo "Could not copy '$KERNEL_IMAGE to '$ENTRY_DIR_ABS/linux'." >&2
+ exit 1
+ }
INITRD_OPTIONS=( "${@:${INITRD_OPTIONS_START}}" )
cp "${initrd}" "$ENTRY_DIR_ABS/${initrd_basename}" &&
chown root:root "$ENTRY_DIR_ABS/${initrd_basename}" &&
chmod 0644 "$ENTRY_DIR_ABS/${initrd_basename}" || {
- echo "Could not copy '${initrd}' to '$ENTRY_DIR_ABS/${initrd_basename}'." >&2
- exit 1
- }
+ echo "Could not copy '${initrd}' to '$ENTRY_DIR_ABS/${initrd_basename}'." >&2
+ exit 1
+ }
fi
done
if want_kernel_install
install_data('kernel-install',
- install_mode : 'rwxr-xr-x',
- install_dir : bindir)
+ install_mode : 'rwxr-xr-x')
install_data('00-entry-directory.install',
'50-depmod.install',
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
if (r < 0)
goto fail;
- if (rename(temp_path, lease_file) < 0) {
- r = -errno;
+ r = conservative_rename(temp_path, lease_file);
+ if (r < 0)
goto fail;
- }
return 0;
return 0;
}
-static void dhcp_request_free(DHCPRequest *req) {
+static DHCPRequest* dhcp_request_free(DHCPRequest *req) {
if (!req)
- return;
+ return NULL;
free(req->client_id.data);
- free(req);
+ return mfree(req);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
}
int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
- unsigned i;
int r = 0;
assert_return(server, -EINVAL);
assert(server->bound_leases);
- for (i = 0; i < server->pool_size; i++) {
+ for (uint32_t i = 0; i < server->pool_size; i++) {
DHCPLease *lease = server->bound_leases[i];
if (!lease || lease == &server->invalid_lease)
IPV4ACD_STATE_ANNOUNCING,
IPV4ACD_STATE_RUNNING,
_IPV4ACD_STATE_MAX,
- _IPV4ACD_STATE_INVALID = -1
+ _IPV4ACD_STATE_INVALID = -EINVAL,
} IPv4ACDState;
struct sd_ipv4acd {
LIBSYSTEMD_248 {
global:
sd_bus_open_user_machine;
+ sd_bus_reply;
sd_event_source_set_ratelimit;
sd_event_source_get_ratelimit;
sd_event_source_is_ratelimited;
-} LIBSYSTEMD_246;
+} LIBSYSTEMD_247;
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SOURCE, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_STUB_LOOP, ELOOP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRODUCT_UUID, EOPNOTSUPP),
+ SD_BUS_ERROR_MAP(BUS_ERROR_FILE_IS_PROTECTED, EACCES),
+ SD_BUS_ERROR_MAP(BUS_ERROR_READ_ONLY_FILESYSTEM, EROFS),
SD_BUS_ERROR_MAP(BUS_ERROR_SPEED_METER_INACTIVE, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_UNMANAGED_INTERFACE, EOPNOTSUPP),
#include "bus-error.h"
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
-#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
-#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_BAD_UNIT_SETTING "org.freedesktop.systemd1.BadUnitSetting"
-#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
-#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
-#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
-#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
-#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
+#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
+#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
+#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
+#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
+#define BUS_ERROR_BAD_UNIT_SETTING "org.freedesktop.systemd1.BadUnitSetting"
+#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
+#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
+#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
+#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
+#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
-#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
-#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
-#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
-#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
-#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
-#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
-#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
-#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
-#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
-#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
-#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
-#define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull"
-#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean"
-#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy"
-#define BUS_ERROR_UNIT_INACTIVE "org.freedesktop.systemd1.UnitInactive"
+#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
+#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
+#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
+#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
+#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
+#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
+#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
+#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
+#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
+#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
+#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
+#define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull"
+#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean"
+#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy"
+#define BUS_ERROR_UNIT_INACTIVE "org.freedesktop.systemd1.UnitInactive"
-#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
-#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
-#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
-#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
-#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
-#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
-#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
+#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
+#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
+#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
+#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
+#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
+#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
+#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
-#define BUS_ERROR_NO_SUCH_PORTABLE_IMAGE "org.freedesktop.portable1.NoSuchImage"
-#define BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE "org.freedesktop.portable1.BadImageType"
+#define BUS_ERROR_NO_SUCH_PORTABLE_IMAGE "org.freedesktop.portable1.NoSuchImage"
+#define BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE "org.freedesktop.portable1.BadImageType"
-#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
-#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
-#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
-#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
-#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
-#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
-#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
-#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
-#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
-#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
-#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
-#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
-#define BUS_ERROR_NOT_YOUR_DEVICE "org.freedesktop.login1.NotYourDevice"
+#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
+#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
+#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
+#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
+#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
+#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
+#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
+#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
+#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
+#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
+#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
+#define BUS_ERROR_NOT_YOUR_DEVICE "org.freedesktop.login1.NotYourDevice"
-#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
-#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"
+#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
+#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"
-#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
+#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
-#define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers"
-#define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply"
-#define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR"
-#define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
-#define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
-#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
-#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
-#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
-#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
-#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
-#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
-#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
-#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
-#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
-#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
+#define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers"
+#define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply"
+#define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR"
+#define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
+#define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
+#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
+#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
+#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
+#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
+#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
+#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
+#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
+#define BUS_ERROR_NO_SOURCE "org.freedesktop.resolve1.NoSource"
+#define BUS_ERROR_STUB_LOOP "org.freedesktop.resolve1.StubLoop"
+#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
+#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
+#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
-#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
-#define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress"
+#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
+#define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress"
-#define BUS_ERROR_NO_PRODUCT_UUID "org.freedesktop.hostname1.NoProductUUID"
+#define BUS_ERROR_NO_PRODUCT_UUID "org.freedesktop.hostname1.NoProductUUID"
+#define BUS_ERROR_FILE_IS_PROTECTED "org.freedesktop.hostname1.FileIsProtected"
+#define BUS_ERROR_READ_ONLY_FILESYSTEM "org.freedesktop.hostname1.ReadOnlyFilesystem"
-#define BUS_ERROR_SPEED_METER_INACTIVE "org.freedesktop.network1.SpeedMeterInactive"
-#define BUS_ERROR_UNMANAGED_INTERFACE "org.freedesktop.network1.UnmanagedInterface"
+#define BUS_ERROR_SPEED_METER_INACTIVE "org.freedesktop.network1.SpeedMeterInactive"
+#define BUS_ERROR_UNMANAGED_INTERFACE "org.freedesktop.network1.UnmanagedInterface"
-#define BUS_ERROR_NO_SUCH_HOME "org.freedesktop.home1.NoSuchHome"
-#define BUS_ERROR_UID_IN_USE "org.freedesktop.home1.UIDInUse"
-#define BUS_ERROR_USER_NAME_EXISTS "org.freedesktop.home1.UserNameExists"
-#define BUS_ERROR_HOME_EXISTS "org.freedesktop.home1.HomeExists"
-#define BUS_ERROR_HOME_ALREADY_ACTIVE "org.freedesktop.home1.HomeAlreadyActive"
-#define BUS_ERROR_HOME_ALREADY_FIXATED "org.freedesktop.home1.HomeAlreadyFixated"
-#define BUS_ERROR_HOME_UNFIXATED "org.freedesktop.home1.HomeUnfixated"
-#define BUS_ERROR_HOME_NOT_ACTIVE "org.freedesktop.home1.HomeNotActive"
-#define BUS_ERROR_HOME_ABSENT "org.freedesktop.home1.HomeAbsent"
-#define BUS_ERROR_HOME_BUSY "org.freedesktop.home1.HomeBusy"
-#define BUS_ERROR_BAD_PASSWORD "org.freedesktop.home1.BadPassword"
-#define BUS_ERROR_BAD_RECOVERY_KEY "org.freedesktop.home1.BadRecoveryKey"
-#define BUS_ERROR_LOW_PASSWORD_QUALITY "org.freedesktop.home1.LowPasswordQuality"
-#define BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN "org.freedesktop.home1.BadPasswordAndNoToken"
-#define BUS_ERROR_TOKEN_PIN_NEEDED "org.freedesktop.home1.TokenPinNeeded"
-#define BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED "org.freedesktop.home1.TokenProtectedAuthenticationPathNeeded"
-#define BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED "org.freedesktop.home1.TokenUserPresenceNeeded"
-#define BUS_ERROR_TOKEN_ACTION_TIMEOUT "org.freedesktop.home1.TokenActionTimeout"
-#define BUS_ERROR_TOKEN_PIN_LOCKED "org.freedesktop.home1.TokenPinLocked"
-#define BUS_ERROR_TOKEN_BAD_PIN "org.freedesktop.home1.BadPin"
+#define BUS_ERROR_NO_SUCH_HOME "org.freedesktop.home1.NoSuchHome"
+#define BUS_ERROR_UID_IN_USE "org.freedesktop.home1.UIDInUse"
+#define BUS_ERROR_USER_NAME_EXISTS "org.freedesktop.home1.UserNameExists"
+#define BUS_ERROR_HOME_EXISTS "org.freedesktop.home1.HomeExists"
+#define BUS_ERROR_HOME_ALREADY_ACTIVE "org.freedesktop.home1.HomeAlreadyActive"
+#define BUS_ERROR_HOME_ALREADY_FIXATED "org.freedesktop.home1.HomeAlreadyFixated"
+#define BUS_ERROR_HOME_UNFIXATED "org.freedesktop.home1.HomeUnfixated"
+#define BUS_ERROR_HOME_NOT_ACTIVE "org.freedesktop.home1.HomeNotActive"
+#define BUS_ERROR_HOME_ABSENT "org.freedesktop.home1.HomeAbsent"
+#define BUS_ERROR_HOME_BUSY "org.freedesktop.home1.HomeBusy"
+#define BUS_ERROR_BAD_PASSWORD "org.freedesktop.home1.BadPassword"
+#define BUS_ERROR_BAD_RECOVERY_KEY "org.freedesktop.home1.BadRecoveryKey"
+#define BUS_ERROR_LOW_PASSWORD_QUALITY "org.freedesktop.home1.LowPasswordQuality"
+#define BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN "org.freedesktop.home1.BadPasswordAndNoToken"
+#define BUS_ERROR_TOKEN_PIN_NEEDED "org.freedesktop.home1.TokenPinNeeded"
+#define BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED \
+ "org.freedesktop.home1.TokenProtectedAuthenticationPathNeeded"
+#define BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED "org.freedesktop.home1.TokenUserPresenceNeeded"
+#define BUS_ERROR_TOKEN_ACTION_TIMEOUT "org.freedesktop.home1.TokenActionTimeout"
+#define BUS_ERROR_TOKEN_PIN_LOCKED "org.freedesktop.home1.TokenPinLocked"
+#define BUS_ERROR_TOKEN_BAD_PIN "org.freedesktop.home1.BadPin"
#define BUS_ERROR_TOKEN_BAD_PIN_FEW_TRIES_LEFT "org.freedesktop.home1.BadPinFewTriesLeft"
-#define BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT "org.freedesktop.home1.BadPinOneTryLeft"
-#define BUS_ERROR_BAD_SIGNATURE "org.freedesktop.home1.BadSignature"
-#define BUS_ERROR_HOME_RECORD_MISMATCH "org.freedesktop.home1.RecordMismatch"
-#define BUS_ERROR_HOME_RECORD_DOWNGRADE "org.freedesktop.home1.RecordDowngrade"
-#define BUS_ERROR_HOME_RECORD_SIGNED "org.freedesktop.home1.RecordSigned"
-#define BUS_ERROR_BAD_HOME_SIZE "org.freedesktop.home1.BadHomeSize"
-#define BUS_ERROR_NO_PRIVATE_KEY "org.freedesktop.home1.NoPrivateKey"
-#define BUS_ERROR_HOME_LOCKED "org.freedesktop.home1.HomeLocked"
-#define BUS_ERROR_HOME_NOT_LOCKED "org.freedesktop.home1.HomeNotLocked"
-#define BUS_ERROR_NO_DISK_SPACE "org.freedesktop.home1.NoDiskSpace"
-#define BUS_ERROR_TOO_MANY_OPERATIONS "org.freedesktop.home1.TooManyOperations"
-#define BUS_ERROR_AUTHENTICATION_LIMIT_HIT "org.freedesktop.home1.AuthenticationLimitHit"
-#define BUS_ERROR_HOME_CANT_AUTHENTICATE "org.freedesktop.home1.HomeCantAuthenticate"
+#define BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT "org.freedesktop.home1.BadPinOneTryLeft"
+#define BUS_ERROR_BAD_SIGNATURE "org.freedesktop.home1.BadSignature"
+#define BUS_ERROR_HOME_RECORD_MISMATCH "org.freedesktop.home1.RecordMismatch"
+#define BUS_ERROR_HOME_RECORD_DOWNGRADE "org.freedesktop.home1.RecordDowngrade"
+#define BUS_ERROR_HOME_RECORD_SIGNED "org.freedesktop.home1.RecordSigned"
+#define BUS_ERROR_BAD_HOME_SIZE "org.freedesktop.home1.BadHomeSize"
+#define BUS_ERROR_NO_PRIVATE_KEY "org.freedesktop.home1.NoPrivateKey"
+#define BUS_ERROR_HOME_LOCKED "org.freedesktop.home1.HomeLocked"
+#define BUS_ERROR_HOME_NOT_LOCKED "org.freedesktop.home1.HomeNotLocked"
+#define BUS_ERROR_NO_DISK_SPACE "org.freedesktop.home1.NoDiskSpace"
+#define BUS_ERROR_TOO_MANY_OPERATIONS "org.freedesktop.home1.TooManyOperations"
+#define BUS_ERROR_AUTHENTICATION_LIMIT_HIT "org.freedesktop.home1.AuthenticationLimitHit"
+#define BUS_ERROR_HOME_CANT_AUTHENTICATE "org.freedesktop.home1.HomeCantAuthenticate"
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
return r;
}
- return sd_bus_send(call->bus, m, NULL);
+ return sd_bus_reply(call, m);
}
_public_ int sd_bus_reply_method_return(
if (r < 0)
return r;
- return sd_bus_send(call->bus, m, NULL);
+ return sd_bus_reply(call, m);
}
_public_ int sd_bus_reply_method_errorfv(
BUS_NODE_ENUMERATOR,
BUS_NODE_VTABLE,
BUS_NODE_OBJECT_MANAGER,
- _BUS_SLOT_INVALID = -1,
+ _BUS_SLOT_INVALID = -EINVAL,
} BusSlotType;
struct sd_bus_slot {
unsigned n_ref;
- BusSlotType type:5;
-
- /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object
- * they are associated with. This means the bus object stays allocated at least as long as there is a slot
- * around associated with it. If it is floating, then the slot's lifecycle is bound to the lifecycle of the
- * bus: it will be disconnected from the bus when the bus is destroyed, and it keeping the slot reffed hence
- * won't mean the bus stays reffed too. Internally this means the reference direction is reversed: floating
- * slots objects are referenced by the bus object, and not vice versa. */
- bool floating:1;
-
- bool match_added:1;
+ BusSlotType type:8;
+
+ /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the
+ * bus object they are associated with. This means the bus object stays allocated at least as long as
+ * there is a slot around associated with it. If it is floating, then the slot's lifecycle is bound
+ * to the lifecycle of the bus: it will be disconnected from the bus when the bus is destroyed, and
+ * it keeping the slot reffed hence won't mean the bus stays reffed too. Internally this means the
+ * reference direction is reversed: floating slots objects are referenced by the bus object, and not
+ * vice versa. */
+ bool floating;
+ bool match_added;
sd_bus *bus;
void *userdata;
}
void bus_flush_memfd(sd_bus *b) {
- unsigned i;
-
assert(b);
- for (i = 0; i < b->n_memfd_cache; i++)
+ for (unsigned i = 0; i < b->n_memfd_cache; i++)
close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
}
BUS_MATCH_ARG_HAS,
BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63,
_BUS_MATCH_NODE_TYPE_MAX,
- _BUS_MATCH_NODE_TYPE_INVALID = -1
+ _BUS_MATCH_NODE_TYPE_INVALID = -EINVAL,
};
struct bus_match_node {
}
int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
- const char *s;
+ char type;
+ const char *contents, *s;
int r;
assert(m);
assert(l);
- r = sd_bus_message_enter_container(m, 'a', "s");
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
+
+ if (type != SD_BUS_TYPE_ARRAY || !STR_IN_SET(contents, "s", "o", "g"))
+ return -ENXIO;
+
+ r = sd_bus_message_enter_container(m, 'a', NULL);
if (r <= 0)
return r;
- while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
+ /* sd_bus_message_read_basic() does content validation for us. */
+ while ((r = sd_bus_message_read_basic(m, *contents, &s)) > 0) {
r = strv_extend(l, s);
if (r < 0)
return r;
}
}
+int sd_bus_reply(const sd_bus_message *call, sd_bus_message *reply) {
+ assert_return(call, -EINVAL);
+ assert_return(call->sealed, -EPERM);
+ assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
+ assert_return(call->bus, -EINVAL);
+ assert_return(!bus_pid_changed(call->bus), -ECHILD);
+ assert_return(reply, -EINVAL);
+ assert_return(
+ IN_SET(reply->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR),
+ -EINVAL);
+
+ return sd_bus_send(call->bus, reply, NULL);
+}
+
static int process_timeout(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
const sd_bus_error temporarily_const_error = {
.name = SD_BUS_ERROR_ACCESS_DENIED,
.message = "oh! no",
- ._need_free = -1
+ ._need_free = -1,
};
assert_se(!sd_bus_error_is_set(&error));
assert_se(r >= 0);
assert_se(streq(s, "<<<hallo>>>"));
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
assert_se(r < 0);
sd_bus_error_free(&error);
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, NULL); /* NULL and "" are equivalent */
+ assert_se(r < 0);
+ assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
+
+ sd_bus_error_free(&error);
+
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
assert_se(r >= 0);
assert_se(streq(s, "<<<hallo>>>"));
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
assert_se(r >= 0);
assert_se(r >= 0);
assert_se(streq(s, "test"));
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
assert_se(r >= 0);
assert_se(r >= 0);
fputs(s, stdout);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
+
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL); /* NULL and "" are equivalent */
+ assert_se(r >= 0);
+
+ r = sd_bus_message_read(reply, "s", &s);
+ assert_se(r >= 0);
+ fputs(s, stdout);
+
+ reply = sd_bus_message_unref(reply);
r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
assert_se(r >= 0);
assert_se(r >= 0);
log_info("read %s", s);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
fputs(s, stdout);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
fputs(s, stdout);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
fputs(s, stdout);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", NULL);
assert_se(r >= 0);
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
sd_bus_error_free(&error);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
sd_bus_error_free(&error);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
assert_se(r >= 0);
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, NULL);
assert_se(r >= 0);
r = sd_bus_process(bus, &reply);
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_unref(reply);
- reply = NULL;
+ reply = sd_bus_message_unref(reply);
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, NULL);
assert_se(r >= 0);
sd_bus_flush(bus);
_public_ int sd_listen_fds(int unset_environment) {
const char *e;
- int n, r, fd;
+ int n, r;
pid_t pid;
e = getenv("LISTEN_PID");
goto finish;
}
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
+ for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
r = fd_cloexec(fd, true);
if (r < 0)
goto finish;
DEVICE_ENUMERATION_TYPE_DEVICES,
DEVICE_ENUMERATION_TYPE_SUBSYSTEMS,
_DEVICE_ENUMERATION_TYPE_MAX,
- _DEVICE_ENUMERATION_TYPE_INVALID = -1,
+ _DEVICE_ENUMERATION_TYPE_INVALID = -EINVAL,
} DeviceEnumerationType;
struct sd_device_enumerator {
}
static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumerator) {
- size_t i;
-
assert(enumerator);
- for (i = 0; i < enumerator->n_devices; i++)
+ for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
free(enumerator->devices);
int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
int r = 0, k;
- size_t i;
assert(enumerator);
enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
return 0;
- for (i = 0; i < enumerator->n_devices; i++)
+ for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
enumerator->n_devices = 0;
int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
const char *subsysdir;
int r = 0, k;
- size_t i;
assert(enumerator);
enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
return 0;
- for (i = 0; i < enumerator->n_devices; i++)
+ for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
enumerator->n_devices = 0;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <errno.h>
+
#include "sd-device.h"
typedef enum MonitorNetlinkGroup {
MONITOR_GROUP_KERNEL,
MONITOR_GROUP_UDEV,
_MONITOR_NETLINK_GROUP_MAX,
- _MONITOR_NETLINK_GROUP_INVALID = -1,
+ _MONITOR_NETLINK_GROUP_INVALID = -EINVAL,
} MonitorNetlinkGroup;
int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group, int fd);
return -ENOMEM;
}
- r = hashmap_ensure_allocated(&m->subsystem_filter, NULL);
+ r = hashmap_ensure_put(&m->subsystem_filter, NULL, s, d);
if (r < 0)
return r;
- r = hashmap_put(m->subsystem_filter, s, d);
- if (r < 0)
- return r;
+ TAKE_PTR(s);
+ TAKE_PTR(d);
- s = d = NULL;
m->filter_uptodate = false;
return 0;
a = device_action_from_string(action);
if (a < 0)
- return -EINVAL;
+ return a;
r = device_add_property_internal(device, "ACTION", action);
if (r < 0)
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *major = NULL, *minor = NULL;
- unsigned i = 0;
int r;
assert(ret);
if (r < 0)
return r;
- while (i < len) {
+ for (size_t i = 0; i < len; ) {
char *key;
const char *end;
- key = (char*)&nulstr[i];
+ key = (char*) &nulstr[i];
end = memchr(key, '\0', len - i);
if (!end)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
DEVICE_ACTION_BIND,
DEVICE_ACTION_UNBIND,
_DEVICE_ACTION_MAX,
- _DEVICE_ACTION_INVALID = -1,
+ _DEVICE_ACTION_INVALID = -EINVAL,
} DeviceAction;
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
free(device->properties_strv);
free(device->properties_nulstr);
- ordered_hashmap_free_free_free(device->properties);
- ordered_hashmap_free_free_free(device->properties_db);
- hashmap_free_free_free(device->sysattr_values);
+ ordered_hashmap_free(device->properties);
+ ordered_hashmap_free(device->properties_db);
+ hashmap_free(device->sysattr_values);
set_free(device->sysattrs);
set_free(device->all_tags);
set_free(device->current_tags);
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free);
-int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) {
+int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db) {
OrderedHashmap **properties;
assert(device);
- assert(_key);
+ assert(key);
if (db)
properties = &device->properties_db;
else
properties = &device->properties;
- if (_value) {
- _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL;
+ if (value) {
+ _cleanup_free_ char *new_key = NULL, *new_value = NULL, *old_key = NULL, *old_value = NULL;
int r;
- r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops);
+ r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops_free_free);
if (r < 0)
return r;
- key = strdup(_key);
- if (!key)
+ new_key = strdup(key);
+ if (!new_key)
return -ENOMEM;
- value = strdup(_value);
- if (!value)
+ new_value = strdup(value);
+ if (!new_value)
return -ENOMEM;
old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
- r = ordered_hashmap_replace(*properties, key, value);
+ /* ordered_hashmap_replace() does not fail when the hashmap already has the entry. */
+ r = ordered_hashmap_replace(*properties, new_key, new_value);
if (r < 0)
return r;
- key = NULL;
- value = NULL;
+ TAKE_PTR(new_key);
+ TAKE_PTR(new_value);
} else {
- _cleanup_free_ char *key = NULL;
- _cleanup_free_ char *value = NULL;
+ _cleanup_free_ char *old_key = NULL, *old_value = NULL;
- value = ordered_hashmap_remove2(*properties, _key, (void**) &key);
+ old_value = ordered_hashmap_remove2(*properties, key, (void**) &old_key);
}
if (!db) {
}
_public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
- char *syspath;
- char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
+ char id[DECIMAL_STR_MAX(unsigned) * 2 + 1], *syspath;
assert_return(ret, -EINVAL);
assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
}
int device_set_devnum(sd_device *device, const char *major, const char *minor) {
- unsigned maj = 0, min = 0;
+ unsigned maj, min = 0;
int r;
assert(device);
r = safe_atou(major, &maj);
if (r < 0)
return r;
- if (!maj)
+ if (maj == 0)
return 0;
if (minor) {
return 0;
}
-/* replaces the value if it already exists */
-static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) {
- _cleanup_free_ char *key = NULL;
- _cleanup_free_ char *value_old = NULL;
+static int device_add_sysattr_value(sd_device *device, const char *key, char *value) {
+ _cleanup_free_ char *new_key = NULL, *old_value = NULL;
int r;
assert(device);
- assert(_key);
+ assert(key);
- r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
- if (r < 0)
- return r;
+ /* This takes the reference of the input value. The input value may be NULL.
+ * This replaces the value if it already exists. */
- value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
- if (!key) {
- key = strdup(_key);
- if (!key)
+ old_value = hashmap_remove2(device->sysattr_values, key, (void **) &new_key);
+ if (!new_key) {
+ new_key = strdup(key);
+ if (!new_key)
return -ENOMEM;
}
- r = hashmap_put(device->sysattr_values, key, value);
+ r = hashmap_ensure_put(&device->sysattr_values, &string_hash_ops_free_free, new_key, value);
if (r < 0)
return r;
- TAKE_PTR(key);
+
+ TAKE_PTR(new_key);
return 0;
}
SOURCE_WATCHDOG,
SOURCE_INOTIFY,
_SOURCE_EVENT_SOURCE_TYPE_MAX,
- _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
+ _SOURCE_EVENT_SOURCE_TYPE_INVALID = -EINVAL,
} EventSourceType;
/* All objects we use in epoll events start with this value, so that
WAKEUP_SIGNAL_DATA,
WAKEUP_INOTIFY_DATA,
_WAKEUP_TYPE_MAX,
- _WAKEUP_TYPE_INVALID = -1,
+ _WAKEUP_TYPE_INVALID = -EINVAL,
} WakeupType;
struct inode_data;
char *description;
- EventSourceType type:5;
+ EventSourceType type;
signed int enabled:3;
bool pending:1;
bool dispatching:1;
e->epoll_fd = fd_move_above_stdio(e->epoll_fd);
if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) {
- log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s.");
+ log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 … 2^63 us will be logged every 5s.");
e->profile_delays = true;
}
return 0;
}
} else {
- r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops);
- if (r < 0)
- return r;
-
d = new(struct signal_data, 1);
if (!d)
return -ENOMEM;
.priority = priority,
};
- r = hashmap_put(e->signal_data, &d->priority, d);
+ r = hashmap_ensure_put(&e->signal_data, &uint64_hash_ops, &d->priority, d);
if (r < 0) {
free(d);
return r;
sd_event_unref(event);
}
-static void source_free(sd_event_source *s) {
+static sd_event_source* source_free(sd_event_source *s) {
assert(s);
source_disconnect(s);
s->destroy_callback(s->userdata);
free(s->description);
- free(s);
+ return mfree(s);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free);
fd = fd_move_above_stdio(fd);
- r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops);
- if (r < 0)
- return r;
-
d = new(struct inotify_data, 1);
if (!d)
return -ENOMEM;
.priority = priority,
};
- r = hashmap_put(e->inotify_data, &d->priority, d);
+ r = hashmap_ensure_put(&e->inotify_data, &uint64_hash_ops, &d->priority, d);
if (r < 0) {
d->fd = safe_close(d->fd);
free(d);
}
_public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
- size_t event_queue_max;
- int r, m, i;
+ size_t n_event_queue, m;
+ int r, msec;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
return 1;
}
- event_queue_max = MAX(e->n_sources, 1u);
- if (!GREEDY_REALLOC(e->event_queue, e->event_queue_allocated, event_queue_max))
+ n_event_queue = MAX(e->n_sources, 1u);
+ if (!GREEDY_REALLOC(e->event_queue, e->event_queue_allocated, n_event_queue))
return -ENOMEM;
/* If we still have inotify data buffered, then query the other fds, but don't wait on it */
if (e->inotify_data_buffered)
- timeout = 0;
+ msec = 0;
+ else
+ msec = timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC);
- m = epoll_wait(e->epoll_fd, e->event_queue, event_queue_max,
- timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC));
- if (m < 0) {
- if (errno == EINTR) {
- e->state = SD_EVENT_PENDING;
- return 1;
+ for (;;) {
+ r = epoll_wait(e->epoll_fd, e->event_queue, e->event_queue_allocated, msec);
+ if (r < 0) {
+ if (errno == EINTR) {
+ e->state = SD_EVENT_PENDING;
+ return 1;
+ }
+
+ r = -errno;
+ goto finish;
}
- r = -errno;
- goto finish;
+ m = (size_t) r;
+
+ if (m < e->event_queue_allocated)
+ break;
+
+ if (e->event_queue_allocated >= n_event_queue * 10)
+ break;
+
+ if (!GREEDY_REALLOC(e->event_queue, e->event_queue_allocated, e->event_queue_allocated + n_event_queue))
+ return -ENOMEM;
+
+ msec = 0;
}
triple_timestamp_get(&e->timestamp);
- for (i = 0; i < m; i++) {
+ for (size_t i = 0; i < m; i++) {
if (e->event_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG))
r = flush_timer(e, e->watchdog_fd, e->event_queue[i].events, NULL);
free(node);
}
-static void trie_free(struct trie *trie) {
+static struct trie* trie_free(struct trie *trie) {
if (!trie)
- return;
+ return NULL;
trie_node_cleanup(trie->root);
- strbuf_cleanup(trie->strings);
- free(trie);
+ strbuf_free(trie->strings);
+ return mfree(trie);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free);
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "const char *audit_type_to_string(int type) {\n\tswitch(type) {"
}
int catalog_update(const char* database, const char* root, const char* const* dirs) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- _cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
+ _cleanup_(strbuf_freep) struct strbuf *sb = NULL;
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
_cleanup_free_ CatalogItem *items = NULL;
ssize_t offset;
#include "util.h"
#if HAVE_LZ4
-DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext);
-DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_compressionContext_t, LZ4F_freeCompressionContext, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext, NULL);
#endif
#if HAVE_ZSTD
-DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_CCtx *, ZSTD_freeCCtx);
-DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_DCtx *, ZSTD_freeDCtx);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_CCtx*, ZSTD_freeCCtx, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_DCtx*, ZSTD_freeDCtx, NULL);
static int zstd_ret_to_errno(size_t ret) {
switch (ZSTD_getErrorCode(ret)) {
offset += n;
total_out += n;
- if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes)
- return log_debug_errno(SYNTHETIC_ERRNO(EFBIG),
- "Compressed stream longer than %" PRIu64 " bytes",
- max_bytes);
+ if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
+ r = log_debug_errno(SYNTHETIC_ERRNO(EFBIG),
+ "Compressed stream longer than %" PRIu64 " bytes", max_bytes);
+ goto cleanup;
+ }
if (size - offset < frame_size + 4) {
k = loop_write(fdt, buf, offset, false);
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
cpp="$1"
* context without involving another thread.
*/
int journal_file_set_offline(JournalFile *f, bool wait) {
+ int target_state;
bool restarted;
int r;
if (f->fd < 0 || !f->header)
return -EINVAL;
+ target_state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE;
+
/* An offlining journal is implicitly online and may modify f->header->state,
- * we must also join any potentially lingering offline thread when not online. */
- if (!journal_file_is_offlining(f) && f->header->state != STATE_ONLINE)
+ * we must also join any potentially lingering offline thread when already in
+ * the desired offline state.
+ */
+ if (!journal_file_is_offlining(f) && f->header->state == target_state)
return journal_file_set_offline_thread_join(f);
/* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */
}
static int journal_put_error(sd_journal *j, int r, const char *path) {
- char *copy;
+ _cleanup_free_ char *copy = NULL;
int k;
/* Memorize an error we encountered, and store which
if (r >= 0)
return r;
- k = hashmap_ensure_allocated(&j->errors, NULL);
- if (k < 0)
- return k;
-
if (path) {
copy = strdup(path);
if (!copy)
return -ENOMEM;
- } else
- copy = NULL;
+ }
- k = hashmap_put(j->errors, INT_TO_PTR(r), copy);
+ k = hashmap_ensure_put(&j->errors, NULL, INT_TO_PTR(r), copy);
if (k < 0) {
- free(copy);
-
if (k == -EEXIST)
return 0;
return k;
}
+ TAKE_PTR(copy);
return 0;
}
struct reply_callback {
sd_netlink_message_handler_t callback;
usec_t timeout;
- uint64_t serial;
+ uint32_t serial;
unsigned prioq_idx;
};
typedef enum NetlinkSlotType {
NETLINK_REPLY_CALLBACK,
NETLINK_MATCH_CALLBACK,
- _NETLINK_SLOT_INVALID = -1,
+ _NETLINK_SLOT_INVALID = -EINVAL,
} NetlinkSlotType;
struct sd_netlink_slot {
unsigned n_ref;
+ NetlinkSlotType type:8;
+ bool floating;
sd_netlink *netlink;
void *userdata;
sd_netlink_destroy_t destroy_callback;
- NetlinkSlotType type:2;
- bool floating:1;
char *description;
LIST_FIELDS(sd_netlink_slot, slots);
return 0;
}
-static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) {
+static int netlink_message_read_internal(
+ sd_netlink_message *m,
+ unsigned short type,
+ void **ret_data,
+ bool *ret_net_byteorder) {
+
struct netlink_attribute *attribute;
struct rtattr *rta;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
- assert_return(data, -EINVAL);
assert(m->n_containers < RTNL_CONTAINER_DEPTH);
rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
- *data = RTA_DATA(rta);
+ if (ret_data)
+ *ret_data = RTA_DATA(rta);
- if (net_byteorder)
- *net_byteorder = attribute->net_byteorder;
+ if (ret_net_byteorder)
+ *ret_net_byteorder = attribute->net_byteorder;
return RTA_PAYLOAD(rta);
}
return r;
}
+int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type) {
+ void *attr_data;
+ int r;
+
+ assert_return(m, -EINVAL);
+
+ /* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
+
+ r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_FLAG);
+ if (r < 0)
+ return r;
+
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
+ if (r == -ENODATA)
+ return 0;
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
_cleanup_strv_free_ char **s = NULL;
const NLTypeSystem *type_system;
[RTA_VIA] = { /* See struct rtvia */ },
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
- [RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
[RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
[RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
+ [RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
[RTA_UID] = { .type = NETLINK_TYPE_U32 },
[RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 },
[RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
[RTA_SPORT] = { .type = NETLINK_TYPE_U16 },
[RTA_DPORT] = { .type = NETLINK_TYPE_U16 },
+ [RTA_NH_ID] = { .type = NETLINK_TYPE_U32 },
};
static const NLTypeSystem rtnl_route_type_system = {
static const NLType rtnl_nexthop_types[] = {
[NHA_ID] = { .type = NETLINK_TYPE_U32 },
+ [NHA_GROUP] = { /* array of struct nexthop_grp */ },
+ [NHA_GROUP_TYPE] = { .type = NETLINK_TYPE_U16 },
+ [NHA_BLACKHOLE] = { .type = NETLINK_TYPE_FLAG },
[NHA_OIF] = { .type = NETLINK_TYPE_U32 },
[NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
+ [NHA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
+ [NHA_ENCAP] = { .type = NETLINK_TYPE_NESTED },
+ [NHA_GROUPS] = { .type = NETLINK_TYPE_FLAG },
+ [NHA_MASTER] = { .type = NETLINK_TYPE_U32 },
+ [NHA_FDB] = { .type = NETLINK_TYPE_FLAG },
};
static const NLTypeSystem rtnl_nexthop_type_system = {
NL_UNION_LINK_INFO_DATA_IFB,
NL_UNION_LINK_INFO_DATA_BAREUDP,
_NL_UNION_LINK_INFO_DATA_MAX,
- _NL_UNION_LINK_INFO_DATA_INVALID = -1
+ _NL_UNION_LINK_INFO_DATA_INVALID = -EINVAL,
} NLUnionLinkInfoData;
const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_;
NL_UNION_TCA_OPTION_DATA_SFB,
NL_UNION_TCA_OPTION_DATA_TBF,
_NL_UNION_TCA_OPTION_DATA_MAX,
- _NL_UNION_TCA_OPTION_DATA_INVALID = -1,
+ _NL_UNION_TCA_OPTION_DATA_INVALID = -EINVAL,
} NLUnionTCAOptionData;
const char *nl_union_tca_option_data_to_string(NLUnionTCAOptionData p) _const_;
NL_UNION_NFT_EXPR_DATA_META,
NL_UNION_NFT_EXPR_DATA_NAT,
_NL_UNION_NFT_EXPR_DATA_MAX,
- _NL_UNION_NFT_EXPR_DATA_INVALID = -1,
+ _NL_UNION_NFT_EXPR_DATA_INVALID = -EINVAL,
} NLUnionNFTExprData;
const char *nl_union_nft_expr_data_to_string(NLUnionNFTExprData p) _const_;
return 0;
}
-int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
- uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments) {
+int rtnl_set_link_properties(
+ sd_netlink **rtnl,
+ int ifindex,
+ const char *alias,
+ const struct ether_addr *mac,
+ uint32_t txqueues,
+ uint32_t rxqueues,
+ uint32_t txqueuelen,
+ uint32_t mtu,
+ uint32_t gso_max_size,
+ size_t gso_max_segments) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
assert(ifindex > 0);
- if (!alias && !mac && txqueuelen == UINT32_MAX && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
+ if (!alias && !mac && txqueues == 0 && rxqueues == 0 && txqueuelen == UINT32_MAX && mtu == 0 &&
+ gso_max_size == 0 && gso_max_segments == 0)
return 0;
if (!*rtnl) {
return r;
}
+ if (txqueues > 0) {
+ r = sd_netlink_message_append_u32(message, IFLA_NUM_TX_QUEUES, txqueues);
+ if (r < 0)
+ return r;
+ }
+
+ if (rxqueues > 0) {
+ r = sd_netlink_message_append_u32(message, IFLA_NUM_RX_QUEUES, rxqueues);
+ if (r < 0)
+ return r;
+ }
+
if (txqueuelen < UINT32_MAX) {
r = sd_netlink_message_append_u32(message, IFLA_TXQLEN, txqueuelen);
if (r < 0)
}
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
-int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
- uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments);
+int rtnl_set_link_properties(
+ sd_netlink **rtnl,
+ int ifindex,
+ const char *alias,
+ const struct ether_addr *mac,
+ uint32_t txqueues,
+ uint32_t rxqueues,
+ uint32_t txqueuelen,
+ uint32_t mtu,
+ uint32_t gso_max_size,
+ size_t gso_max_segments);
int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret);
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <netinet/in.h>
#include <linux/if_addrlabel.h>
return 0;
}
-int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
- struct rtmsg *rtm;
-
- assert_return(m, -EINVAL);
- assert_return(m->hdr, -EINVAL);
- assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
-
- rtm = NLMSG_DATA(m->hdr);
-
- rtm->rtm_family = family;
-
- return 0;
-}
-
int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) {
struct rtmsg *rtm;
int r;
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
- assert_return((nhmsg_type == RTM_GETNEXTHOP && nh_family == AF_UNSPEC) ||
- IN_SET(nh_family, AF_INET, AF_INET6), -EINVAL);
+ switch(nhmsg_type) {
+ case RTM_DELNEXTHOP:
+ assert_return(nh_family == AF_UNSPEC, -EINVAL);
+ _fallthrough_;
+ case RTM_GETNEXTHOP:
+ assert_return(nh_protocol == RTPROT_UNSPEC, -EINVAL);
+ break;
+ case RTM_NEWNEXTHOP:
+ assert_return(IN_SET(nh_family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL);
+ break;
+ default:
+ assert_not_reached("Invalid message type.");
+ }
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nhmsg_type);
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
- assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(m->hdr->nlmsg_type == RTM_NEWNEXTHOP, -EINVAL);
nhm = NLMSG_DATA(m->hdr);
nhm->nh_flags |= flags;
return 0;
}
-int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family) {
- struct nhmsg *nhm;
-
- assert_return(m, -EINVAL);
- assert_return(m->hdr, -EINVAL);
-
- nhm = NLMSG_DATA(m->hdr);
- nhm->nh_family = family;
-
- return 0;
-}
-
int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) {
struct nhmsg *nhm;
assert_return(m->hdr, -EINVAL);
nhm = NLMSG_DATA(m->hdr);
- *family = nhm->nh_family ;
+ *family = nhm->nh_family;
return 0;
}
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
- assert_return(change, -EINVAL);
+ assert_return(change != 0, -EINVAL);
ifi = NLMSG_DATA(m->hdr);
}
int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret,
- int index, int family) {
+ int index, int family) {
int r;
r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
#include "string-util.h"
#include "util.h"
+/* Some really high limit, to catch programming errors */
+#define REPLY_CALLBACKS_MAX UINT16_MAX
+
static int sd_netlink_new(sd_netlink **ret) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
.original_pid = getpid_cached(),
.protocol = -1,
- /* Change notification responses have sequence 0, so we must
- * start our request sequence numbers at 1, or we may confuse our
- * responses with notifications from the kernel */
- .serial = 1,
-
+ /* Kernel change notification messages have sequence number 0. We want to avoid that with our
+ * own serials, in order not to get confused when matching up kernel replies to our earlier
+ * requests.
+ *
+ * Moreover, when using netlink socket activation (i.e. where PID 1 binds an AF_NETLINK
+ * socket for us and passes it to us across execve()) and we get restarted multiple times
+ * while the socket sticks around we might get confused by replies from earlier runs coming
+ * in late — which is pretty likely if we'd start our sequence numbers always from 1. Hence,
+ * let's start with a value based on the system clock. This should make collisions much less
+ * likely (though still theoretically possible). We use a 32 bit µs counter starting at boot
+ * for this (and explicitly exclude the zero, see above). This counter will wrap around after
+ * a bit more than 1h, but that's hopefully OK as the kernel shouldn't take that long to
+ * reply to our requests.
+ *
+ * We only pick the initial start value this way. For each message we simply increase the
+ * sequence number by 1. This means we could enqueue 1 netlink message per µs without risking
+ * collisions, which should be OK.
+ *
+ * Note this means the serials will be in the range 1…UINT32_MAX here.
+ *
+ * (In an ideal world we'd attach the current serial counter to the netlink socket itself
+ * somehow, to avoid all this, but I couldn't come up with a nice way to do this) */
+ .serial = (uint32_t) (now(CLOCK_MONOTONIC) % UINT32_MAX) + 1,
};
/* We guarantee that the read buffer has at least space for
int sd_netlink_open_fd(sd_netlink **ret, int fd) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- int r;
- int protocol;
- socklen_t l;
+ int r, protocol;
assert_return(ret, -EINVAL);
assert_return(fd >= 0, -EBADF);
if (r < 0)
return r;
- l = sizeof(protocol);
- r = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &l);
+ r = getsockopt_int(fd, SOL_SOCKET, SO_PROTOCOL, &protocol);
if (r < 0)
return r;
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
+ uint32_t picked;
+
assert(rtnl);
assert(!rtnl_pid_changed(rtnl));
assert(m);
assert(m->hdr);
- /* don't use seq == 0, as that is used for broadcasts, so we
- would get confused by replies to such messages */
- m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++;
+ /* Avoid collisions with outstanding requests */
+ do {
+ picked = rtnl->serial;
- rtnl_message_seal(m);
+ /* Don't use seq == 0, as that is used for broadcasts, so we would get confused by replies to
+ such messages */
+ rtnl->serial = rtnl->serial == UINT32_MAX ? 1 : rtnl->serial + 1;
- return;
+ } while (hashmap_contains(rtnl->reply_callbacks, UINT32_TO_PTR(picked)));
+
+ m->hdr->nlmsg_seq = picked;
+ rtnl_message_seal(m);
}
int sd_netlink_send(sd_netlink *nl,
assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c);
c->timeout = 0;
- hashmap_remove(rtnl->reply_callbacks, &c->serial);
+ hashmap_remove(rtnl->reply_callbacks, UINT32_TO_PTR(c->serial));
slot = container_of(c, sd_netlink_slot, reply_callback);
static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
struct reply_callback *c;
sd_netlink_slot *slot;
- uint64_t serial;
+ uint32_t serial;
uint16_t type;
int r;
assert(m);
serial = rtnl_message_get_serial(m);
- c = hashmap_remove(rtnl->reply_callbacks, &serial);
+ c = hashmap_remove(rtnl->reply_callbacks, UINT32_TO_PTR(serial));
if (!c)
return 0;
return r;
LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) {
- if (type == c->type) {
- slot = container_of(c, sd_netlink_slot, match_callback);
+ if (type != c->type)
+ continue;
- r = c->callback(rtnl, m, slot->userdata);
- if (r != 0) {
- if (r < 0)
- log_debug_errno(r, "sd-netlink: match callback %s%s%sfailed: %m",
- slot->description ? "'" : "",
- strempty(slot->description),
- slot->description ? "' " : "");
+ slot = container_of(c, sd_netlink_slot, match_callback);
- break;
- }
- }
+ r = c->callback(rtnl, m, slot->userdata);
+ if (r < 0)
+ log_debug_errno(r, "sd-netlink: match callback %s%s%sfailed: %m",
+ slot->description ? "'" : "",
+ strempty(slot->description),
+ slot->description ? "' " : "");
+ if (r != 0)
+ break;
}
return 1;
uint64_t usec,
const char *description) {
_cleanup_free_ sd_netlink_slot *slot = NULL;
- uint32_t s;
int r, k;
assert_return(nl, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!rtnl_pid_changed(nl), -ECHILD);
- r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops);
+ if (hashmap_size(nl->reply_callbacks) >= REPLY_CALLBACKS_MAX)
+ return -ERANGE;
+
+ r = hashmap_ensure_allocated(&nl->reply_callbacks, &trivial_hash_ops);
if (r < 0)
return r;
slot->reply_callback.callback = callback;
slot->reply_callback.timeout = calc_elapse(usec);
- k = sd_netlink_send(nl, m, &s);
+ k = sd_netlink_send(nl, m, &slot->reply_callback.serial);
if (k < 0)
return k;
- slot->reply_callback.serial = s;
-
- r = hashmap_put(nl->reply_callbacks, &slot->reply_callback.serial, &slot->reply_callback);
+ r = hashmap_put(nl->reply_callbacks, UINT32_TO_PTR(slot->reply_callback.serial), &slot->reply_callback);
if (r < 0)
return r;
if (slot->reply_callback.timeout != 0) {
r = prioq_put(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
if (r < 0) {
- (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial);
+ (void) hashmap_remove(nl->reply_callbacks, UINT32_TO_PTR(slot->reply_callback.serial));
return r;
}
}
LINK_OPERSTATE_ENSLAVED,
LINK_OPERSTATE_ROUTABLE,
_LINK_OPERSTATE_MAX,
- _LINK_OPERSTATE_INVALID = -1
+ _LINK_OPERSTATE_INVALID = -EINVAL,
} LinkOperationalState;
typedef enum LinkCarrierState {
LINK_CARRIER_STATE_CARRIER = LINK_OPERSTATE_CARRIER,
LINK_CARRIER_STATE_ENSLAVED = LINK_OPERSTATE_ENSLAVED,
_LINK_CARRIER_STATE_MAX,
- _LINK_CARRIER_STATE_INVALID = -1
+ _LINK_CARRIER_STATE_INVALID = -EINVAL,
} LinkCarrierState;
typedef enum LinkAddressState {
LINK_ADDRESS_STATE_DEGRADED,
LINK_ADDRESS_STATE_ROUTABLE,
_LINK_ADDRESS_STATE_MAX,
- _LINK_ADDRESS_STATE_INVALID = -1
+ _LINK_ADDRESS_STATE_INVALID = -EINVAL,
} LinkAddressState;
const char* link_operstate_to_string(LinkOperationalState s) _const_;
return 0;
}
+_public_ int sd_network_link_get_activation_policy(int ifindex, char **policy) {
+ _cleanup_free_ char *s = NULL;
+ int r;
+
+ assert_return(policy, -EINVAL);
+
+ r = network_link_get_string(ifindex, "ACTIVATION_POLICY", &s);
+ if (r < 0) {
+ if (r != -ENODATA)
+ return r;
+
+ /* For compatibility, assuming up. */
+ s = strdup("up");
+ if (!s)
+ return -ENOMEM;
+ }
+
+ *policy = TAKE_PTR(s);
+ return 0;
+}
+
_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
return network_link_get_string(ifindex, "LLMNR", llmnr);
}
return NULL;
if (entry->list) {
- if (entry->list->unique)
+ if (entry->list->unique && entry->name)
hashmap_remove(entry->list->unique_entries, entry->name);
- else
+
+ if (!entry->list->unique || entry->list->uptodate)
LIST_REMOVE(entries, entry->list->entries, entry);
}
struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *_name, const char *_value) {
_cleanup_(udev_list_entry_freep) struct udev_list_entry *entry = NULL;
_cleanup_free_ char *name = NULL, *value = NULL;
- int r;
assert(list);
+ assert(_name);
name = strdup(_name);
if (!name)
return NULL;
*entry = (struct udev_list_entry) {
- .list = list,
.name = TAKE_PTR(name),
.value = TAKE_PTR(value),
};
if (list->unique) {
- r = hashmap_ensure_allocated(&list->unique_entries, &string_hash_ops);
- if (r < 0)
- return NULL;
-
udev_list_entry_free(hashmap_get(list->unique_entries, entry->name));
- r = hashmap_put(list->unique_entries, entry->name, entry);
- if (r < 0)
+ if (hashmap_ensure_put(&list->unique_entries, &string_hash_ops, entry->name, entry) < 0)
return NULL;
list->uptodate = false;
} else
LIST_APPEND(entries, list->entries, entry);
+ entry->list = list;
+
return TAKE_PTR(entry);
}
return;
if (list->unique) {
- hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free);
list->uptodate = false;
+ hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free);
} else
LIST_FOREACH_SAFE(entries, i, n, list->entries)
udev_list_entry_free(i);
}
static void context_free_locale(Context *c) {
- int p;
-
- for (p = 0; p < _VARIABLE_LC_MAX; p++)
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
c->locale[p] = mfree(c->locale[p]);
}
};
void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
- int p;
-
- for (p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
+ for (LocaleVariable p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p]))
locale[p] = mfree(locale[p]);
}
if (r < 0)
return r;
} else {
- int p;
-
c->locale_mtime = USEC_INFINITY;
context_free_locale(c);
/* Fill in what we got passed from systemd. */
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
const char *name;
name = locale_variable_to_string(p);
int locale_write_data(Context *c, char ***settings) {
_cleanup_strv_free_ char **l = NULL;
struct stat st;
- int r, p;
+ int r;
/* Set values will be returned as strv in *settings on success. */
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
- _cleanup_free_ char *t = NULL;
- char **u;
- const char *name;
-
- name = locale_variable_to_string(p);
- assert(name);
-
- if (isempty(c->locale[p]))
- continue;
-
- if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
- return -ENOMEM;
-
- u = strv_env_set(l, t);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
- }
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
+ if (!isempty(c->locale[p])) {
+ r = strv_env_assign(&l, locale_variable_to_string(p), c->locale[p]);
+ if (r < 0)
+ return r;
+ }
if (strv_isempty(l)) {
if (unlink("/etc/locale.conf") < 0)
if (r < 0 && r != -ENOENT)
return r;
- if (isempty(c->vc_keymap))
- l = strv_env_unset(l, "KEYMAP");
- else {
- _cleanup_free_ char *s = NULL;
- char **u;
-
- s = strjoin("KEYMAP=", c->vc_keymap);
- if (!s)
- return -ENOMEM;
-
- u = strv_env_set(l, s);
- if (!u)
- return -ENOMEM;
-
- strv_free_and_replace(l, u);
- }
-
- if (isempty(c->vc_keymap_toggle))
- l = strv_env_unset(l, "KEYMAP_TOGGLE");
- else {
- _cleanup_free_ char *s = NULL;
- char **u;
-
- s = strjoin("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
- if (!s)
- return -ENOMEM;
-
- u = strv_env_set(l, s);
- if (!u)
- return -ENOMEM;
+ r = strv_env_assign(&l, "KEYMAP", empty_to_null(c->vc_keymap));
+ if (r < 0)
+ return r;
- strv_free_and_replace(l, u);
- }
+ r = strv_env_assign(&l, "KEYMAP_TOGGLE", empty_to_null(c->vc_keymap_toggle));
+ if (r < 0)
+ return r;
if (strv_isempty(l)) {
if (unlink("/etc/vconsole.conf") < 0)
static void print_overridden_variables(void) {
_cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
bool print_warning = true;
- LocaleVariable j;
int r;
if (arg_transport != BUS_TRANSPORT_LOCAL)
return;
}
- for (j = 0; j < _VARIABLE_LC_MAX; j++)
+ for (LocaleVariable j = 0; j < _VARIABLE_LC_MAX; j++)
if (variables[j]) {
if (print_warning) {
log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" --no-convert Don't convert keyboard mappings\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
_cleanup_strv_free_ char **l_set = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- size_t c_set, c_unset;
- LocaleVariable p;
+ size_t c_set = 0, c_unset = 0;
int r;
assert(bus);
if (!l_set)
return log_oom();
- for (p = 0, c_set = 0, c_unset = 0; p < _VARIABLE_LC_MAX; p++) {
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
const char *name;
name = locale_variable_to_string(p);
Context *c = userdata;
_cleanup_strv_free_ char **l = NULL;
- int p, q, r;
+ int r;
r = locale_read_data(c, reply);
if (r < 0)
if (!l)
return -ENOMEM;
- for (p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
+ for (LocaleVariable p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
char *t;
const char *name;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-localed.service",
"Manage system locale settings and key mappings.",
/* If there's not enough space, shorten the "WHY" column, as it's little more than an explaining comment. */
(void) table_set_weight(table, TABLE_HEADER_CELL(6), 20);
+ (void) table_set_maximum_width(table, TABLE_HEADER_CELL(0), columns()/2);
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
if (r < 0)
" --why=STRING A descriptive string why is being inhibited\n"
" --mode=MODE One of block or delay\n"
" --list List active inhibitors\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
#include "main-func.h"
#include "memory-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "process-util.h"
" short-monotonic, short-unix, verbose, export,\n"
" json, json-pretty, json-sse, json-seq, cat,\n"
" with-unit)\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
arg_output = output_mode_from_string(optarg);
if (arg_output < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown output '%s'.", optarg);
+ return log_error_errno(arg_output, "Unknown output '%s'.", optarg);
if (OUTPUT_MODE_IS_JSON(arg_output))
arg_legend = false;
break;
case 's':
- if (streq(optarg, "help")) {
- DUMP_STRING_TABLE(signal, int, _NSIG);
- return 0;
- }
-
- arg_signal = signal_from_string(optarg);
- if (arg_signal < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse signal string %s.", optarg);
+ r = parse_signal_argument(optarg, &arg_signal);
+ if (r <= 0)
+ return r;
break;
case 'H':
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
HANDLE_SUSPEND_THEN_HIBERNATE,
HANDLE_LOCK,
_HANDLE_ACTION_MAX,
- _HANDLE_ACTION_INVALID = -1
+ _HANDLE_ACTION_INVALID = -EINVAL,
} HandleAction;
#include "logind-inhibit.h"
sd_event_source* child_event_source;
} BrightnessWriter;
-static void brightness_writer_free(BrightnessWriter *w) {
+static BrightnessWriter* brightness_writer_free(BrightnessWriter *w) {
if (!w)
- return;
+ return NULL;
if (w->manager && w->path)
(void) hashmap_remove_value(w->manager->brightness_writers, w->path, w);
w->child_event_source = sd_event_source_unref(w->child_event_source);
- free(w);
+ return mfree(w);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free);
return 0;
}
- r = hashmap_ensure_allocated(&m->brightness_writers, &brightness_writer_hash_ops);
- if (r < 0)
- return log_oom();
-
w = new(BrightnessWriter, 1);
if (!w)
return log_oom();
if (!w->path)
return log_oom();
- r = hashmap_put(m->brightness_writers, w->path, w);
+ r = hashmap_ensure_put(&m->brightness_writers, &brightness_writer_hash_ops, w->path, w);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to add brightness writer to hashmap: %m");
+
w->manager = m;
r = set_add_message(&w->current_messages, message);
#include "format-util.h"
#include "fs-util.h"
#include "logind-dbus.h"
+#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-user-dbus.h"
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
"Session %s not on seat %s", session_name, seat_name);
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &m->polkit_registry,
- error);
+ r = check_polkit_chvt(message, m, error);
if (r < 0)
return r;
if (r == 0)
Manager *m,
sd_bus_message *message,
InhibitWhat w,
- bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
+ uint64_t flags,
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- bool multiple_sessions, blocked;
+ bool multiple_sessions, blocked, interactive;
uid_t uid;
int r;
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ interactive = flags & SD_LOGIND_INTERACTIVE;
if (multiple_sessions && action_multiple_sessions) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
- if (blocked && action_ignore_inhibit) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ if (blocked) {
+ /* We don't check polkit for root here, because you can't be more privileged than root */
+ if (uid == 0 && (flags & SD_LOGIND_ROOT_CHECK_INHIBITORS))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
+ "Access denied to root due to active block inhibitor");
+
+ if (action_ignore_inhibit) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ }
}
if (!multiple_sessions && !blocked && action) {
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
+ bool with_flags,
sd_bus_error *error) {
- int interactive, r;
+ uint64_t flags;
+ int r;
assert(m);
assert(message);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
- r = sd_bus_message_read(message, "b", &interactive);
- if (r < 0)
- return r;
+ if (with_flags) {
+ /* New style method: with flags parameter (and interactive bool in the bus message header) */
+ r = sd_bus_message_read(message, "t", &flags);
+ if (r < 0)
+ return r;
+ if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+ } else {
+ /* Old style method: no flags parameter, but interactive bool passed as boolean in
+ * payload. Let's convert this argument to the new-style flags parameter for our internal
+ * use. */
+ int interactive;
+
+ r = sd_bus_message_read(message, "b", &interactive);
+ if (r < 0)
+ return r;
+
+ flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
+ }
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what > 0)
return r;
}
- r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
- action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, w, action, action_multiple_sessions,
+ action_ignore_inhibit, flags, error);
if (r != 0)
return r;
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
error);
}
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
error);
}
"org.freedesktop.login1.halt-multiple-sessions",
"org.freedesktop.login1.halt-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
error);
}
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
+ sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
error);
}
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
+ sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
error);
}
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
error);
}
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
error);
}
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
- r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
- action, action_multiple_sessions, action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, action, action_multiple_sessions,
+ action_ignore_inhibit, 0, error);
if (r != 0)
return r;
NULL,,
method_poweroff,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PowerOffWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_poweroff,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Reboot",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_reboot,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("RebootWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_reboot,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Halt",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_halt,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HaltWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_halt,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Suspend",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_suspend,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Hibernate",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_hibernate,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("HybridSleep",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_hybrid_sleep,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HybridSleepWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hybrid_sleep,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernate",
"b",
SD_BUS_PARAM(interactive),
NULL,,
method_suspend_then_hibernate,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend_then_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("CanPowerOff",
NULL,,
"s",
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
INHIBIT_HANDLE_LID_SWITCH = 1 << 6,
INHIBIT_HANDLE_REBOOT_KEY = 1 << 7,
_INHIBIT_WHAT_MAX = 1 << 8,
- _INHIBIT_WHAT_INVALID = -1
+ _INHIBIT_WHAT_INVALID = -EINVAL,
} InhibitWhat;
typedef enum InhibitMode {
INHIBIT_BLOCK,
INHIBIT_DELAY,
_INHIBIT_MODE_MAX,
- _INHIBIT_MODE_INVALID = -1
+ _INHIBIT_MODE_INVALID = -EINVAL,
} InhibitMode;
#include "logind.h"
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-polkit.h"
+#include "logind-polkit.h"
+#include "missing_capability.h"
+#include "user-util.h"
+
+int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error) {
+#if ENABLE_POLKIT
+ return bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.chvt",
+ NULL,
+ false,
+ UID_INVALID,
+ &manager->polkit_registry,
+ error);
+#else
+ /* Allow chvt when polkit is not present. This allows a service to start a graphical session as a
+ * non-root user when polkit is not compiled in, more closely matching the default polkit policy */
+ return 1;
+#endif
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+#include "bus-object.h"
+#include "logind.h"
+
+int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error);
#include "bus-polkit.h"
#include "bus-util.h"
#include "logind-dbus.h"
+#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-seat.h"
#include "logind-session-dbus.h"
if (session->seat != s)
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &s->manager->polkit_registry,
- error);
+ r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
if (to <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &s->manager->polkit_registry,
- error);
+ r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
assert(message);
assert(s);
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &s->manager->polkit_registry,
- error);
+ r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
assert(message);
assert(s);
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &s->manager->polkit_registry,
- error);
+ r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
#include "fd-util.h"
#include "logind-brightness.h"
#include "logind-dbus.h"
+#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-session-device.h"
assert(message);
assert(s);
- r = bus_verify_polkit_async(
- message,
- CAP_SYS_ADMIN,
- "org.freedesktop.login1.chvt",
- NULL,
- false,
- UID_INVALID,
- &s->manager->polkit_registry,
- error);
+ r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
SESSION_ACTIVE, /* Logged in and in the fg */
SESSION_CLOSING, /* Logged out, but scope is still there */
_SESSION_STATE_MAX,
- _SESSION_STATE_INVALID = -1
+ _SESSION_STATE_INVALID = -EINVAL,
} SessionState;
typedef enum SessionClass {
SESSION_LOCK_SCREEN,
SESSION_BACKGROUND,
_SESSION_CLASS_MAX,
- _SESSION_CLASS_INVALID = -1
+ _SESSION_CLASS_INVALID = -EINVAL,
} SessionClass;
typedef enum SessionType {
SESSION_MIR,
SESSION_WEB,
_SESSION_TYPE_MAX,
- _SESSION_TYPE_INVALID = -1
+ _SESSION_TYPE_INVALID = -EINVAL,
} SessionType;
#define SESSION_TYPE_IS_GRAPHICAL(type) IN_SET(type, SESSION_X11, SESSION_WAYLAND, SESSION_MIR)
KILL_LEADER,
KILL_ALL,
_KILL_WHO_MAX,
- _KILL_WHO_INVALID = -1
+ _KILL_WHO_INVALID = -EINVAL,
};
typedef enum TTYValidity {
TTY_FROM_UTMP,
TTY_UTMP_INCONSISTENT, /* may happen on ssh sessions with multiplexed TTYs */
_TTY_VALIDITY_MAX,
- _TTY_VALIDITY_INVALID = -1,
+ _TTY_VALIDITY_INVALID = -EINVAL,
} TTYValidity;
struct Session {
USER_ACTIVE, /* User logged in and has a session in the fg */
USER_CLOSING, /* User logged out, but processes still remain and lingering is not enabled */
_USER_STATE_MAX,
- _USER_STATE_INVALID = -1
+ _USER_STATE_INVALID = -EINVAL,
} UserState;
struct User {
int r;
log_set_facility(LOG_AUTH);
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-logind.service",
"Manager for user logins and devices and privileged operations.",
logind-device.h
logind-inhibit.c
logind-inhibit.h
+ logind-polkit.c
+ logind-polkit.h
logind-seat-dbus.c
logind-seat-dbus.h
logind-seat.c
#include "log.h"
#include "machine-id-setup.h"
#include "main-func.h"
+#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "util.h"
" --root=ROOT Filesystem root\n"
" --commit Commit transient ID\n"
" --print Print used machine ID\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
return version();
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
+ r = parse_path_argument(optarg, true, &arg_root);
if (r < 0)
return r;
break;
#include "bus-label.h"
#include "bus-polkit.h"
#include "copy.h"
+#include "discover-image.h"
#include "dissect-image.h"
#include "fd-util.h"
#include "fileio.h"
#include "image-dbus.h"
#include "io-util.h"
#include "loop-util.h"
-#include "machine-image.h"
#include "missing_capability.h"
#include "mount-util.h"
#include "process-util.h"
return 1;
}
- r = hashmap_ensure_allocated(&m->image_cache, &image_hash_ops);
- if (r < 0)
- return r;
-
if (!m->image_cache_defer_event) {
r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m);
if (r < 0)
image->userdata = m;
- r = hashmap_put(m->image_cache, image->name, image);
+ r = hashmap_ensure_put(&m->image_cache, &image_hash_ops, image->name, image);
if (r < 0) {
image_unref(image);
return r;
MACHINE_RUNNING, /* Machine is running */
MACHINE_CLOSING, /* Machine is terminating */
_MACHINE_STATE_MAX,
- _MACHINE_STATE_INVALID = -1
+ _MACHINE_STATE_INVALID = -EINVAL,
} MachineState;
typedef enum MachineClass {
MACHINE_VM,
MACHINE_HOST,
_MACHINE_CLASS_MAX,
- _MACHINE_CLASS_INVALID = -1
+ _MACHINE_CLASS_INVALID = -EINVAL,
} MachineClass;
enum KillWho {
KILL_LEADER,
KILL_ALL,
_KILL_WHO_MAX,
- _KILL_WHO_INVALID = -1
+ _KILL_WHO_INVALID = -EINVAL,
};
struct Machine {
#include "mkdir.h"
#include "nulstr-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
" --verify=MODE Verification mode for downloaded images (no,\n"
" checksum, signature)\n"
" --force Download image even if already exists\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
return 0;
}
- arg_output = output_mode_from_string(optarg);
- if (arg_output < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown output '%s'.", optarg);
+ r = output_mode_from_string(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Unknown output '%s'.", optarg);
+ arg_output = r;
if (OUTPUT_MODE_IS_JSON(arg_output))
arg_legend = false;
break;
case 's':
- if (streq(optarg, "help")) {
- DUMP_STRING_TABLE(signal, int, _NSIG);
- return 0;
- }
-
- arg_signal = signal_from_string(optarg);
- if (arg_signal < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse signal string %s.", optarg);
+ r = parse_signal_argument(optarg, &arg_signal);
+ if (r <= 0)
+ return r;
break;
case ARG_NO_ASK_PASSWORD:
return 0;
}
- arg_verify = import_verify_from_string(optarg);
- if (arg_verify < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse --verify= setting: %s", optarg);
+ r = import_verify_from_string(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --verify= setting: %s", optarg);
+ arg_verify = r;
break;
case ARG_FORCE:
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
#include "bus-locator.h"
#include "bus-polkit.h"
#include "cgroup-util.h"
+#include "discover-image.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "image-dbus.h"
#include "io-util.h"
#include "machine-dbus.h"
-#include "machine-image.h"
#include "machine-pool.h"
#include "machined.h"
#include "missing_capability.h"
if (m->varlink_server)
return 0;
- r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID);
+ r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");
#include "bus-polkit.h"
#include "cgroup-util.h"
#include "dirent-util.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "format-util.h"
#include "hostname-util.h"
#include "label.h"
-#include "machine-image.h"
#include "machined-varlink.h"
#include "machined.h"
#include "main-func.h"
int r;
log_set_facility(LOG_AUTH);
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-machined.service",
"Manage registrations of local VMs and containers.",
"Loads statically configured kernel modules.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
umask(0022);
" --list List mountable block devices\n"
" -u --umount Unmount mount points\n"
" -G --collect Unload unit after it stopped, even when failed\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount "
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ",
+ link);
return 0;
}
break;
case 't':
- if (free_and_strdup(&arg_mount_type, optarg) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&arg_mount_type, optarg);
+ if (r < 0)
+ return r;
break;
case 'o':
- if (free_and_strdup(&arg_mount_options, optarg) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&arg_mount_options, optarg);
+ if (r < 0)
+ return r;
break;
case ARG_OWNER: {
break;
case ARG_DESCRIPTION:
- if (free_and_strdup(&arg_description, optarg) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&arg_description, optarg);
+ if (r < 0)
+ return r;
break;
case 'p':
printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
" -h --help Show this help\n"
" --version Show package version\n"
- " --root=PATH Operate on an alternate filesystem root\n"
- , program_invocation_short_name
- );
+ " --root=PATH Operate on an alternate filesystem root\n",
+ program_invocation_short_name);
return 0;
}
t = dracut_dhcp_type_from_string(dhcp_type);
if (t < 0)
- return -EINVAL;
+ return t;
network = network_get(context, ifname);
if (!network) {
DHCP_TYPE_EITHER6,
DHCP_TYPE_IBFT,
_DHCP_TYPE_MAX,
- _DHCP_TYPE_INVALID = -1,
+ _DHCP_TYPE_INVALID = -EINVAL,
} DHCPType;
typedef struct Address Address;
BARE_UDP_PROTOCOL_MPLS_UC = ETH_P_MPLS_UC,
BARE_UDP_PROTOCOL_MPLS_MC = ETH_P_MPLS_MC,
_BARE_UDP_PROTOCOL_MAX,
- _BARE_UDP_PROTOCOL_INVALID = -1
+ _BARE_UDP_PROTOCOL_INVALID = -EINVAL,
} BareUDPProtocol;
struct BareUDP {
MULTICAST_ROUTER_PERMANENT = MDB_RTR_TYPE_PERM,
MULTICAST_ROUTER_TEMPORARY = MDB_RTR_TYPE_TEMP,
_MULTICAST_ROUTER_MAX,
- _MULTICAST_ROUTER_INVALID = -1,
+ _MULTICAST_ROUTER_INVALID = -EINVAL,
} MulticastRouter;
DEFINE_NETDEV_CAST(BRIDGE, Bridge);
NETDEV_FOO_OVER_UDP_ENCAP_DIRECT = FOU_ENCAP_DIRECT,
NETDEV_FOO_OVER_UDP_ENCAP_GUE = FOU_ENCAP_GUE,
_NETDEV_FOO_OVER_UDP_ENCAP_MAX,
- _NETDEV_FOO_OVER_UDP_ENCAP_INVALID = -1,
+ _NETDEV_FOO_OVER_UDP_ENCAP_INVALID = -EINVAL,
} FooOverUDPEncapType;
typedef struct FouTunnel {
NETDEV_GENEVE_DF_YES = GENEVE_DF_SET,
NETDEV_GENEVE_DF_INHERIT = GENEVE_DF_INHERIT,
_NETDEV_GENEVE_DF_MAX,
- _NETDEV_GENEVE_DF_INVALID = -1
+ _NETDEV_GENEVE_DF_INVALID = -EINVAL,
} GeneveDF;
struct Geneve {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
-static void l2tp_session_free(L2tpSession *s) {
+static L2tpSession* l2tp_session_free(L2tpSession *s) {
if (!s)
- return;
+ return NULL;
if (s->tunnel && s->section)
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
network_config_section_free(s->section);
-
free(s->name);
-
- free(s);
+ return mfree(s);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
spec = l2tp_l2spec_type_from_string(rvalue);
if (spec < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, spec,
"Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue);
return 0;
}
NETDEV_L2TP_L2SPECTYPE_NONE = L2TP_L2SPECTYPE_NONE,
NETDEV_L2TP_L2SPECTYPE_DEFAULT = L2TP_L2SPECTYPE_DEFAULT,
_NETDEV_L2TP_L2SPECTYPE_MAX,
- _NETDEV_L2TP_L2SPECTYPE_INVALID = -1,
+ _NETDEV_L2TP_L2SPECTYPE_INVALID = -EINVAL,
} L2tpL2specType;
typedef enum L2tpEncapType {
NETDEV_L2TP_ENCAPTYPE_UDP = L2TP_ENCAPTYPE_UDP,
NETDEV_L2TP_ENCAPTYPE_IP = L2TP_ENCAPTYPE_IP,
_NETDEV_L2TP_ENCAPTYPE_MAX,
- _NETDEV_L2TP_ENCAPTYPE_INVALID = -1,
+ _NETDEV_L2TP_ENCAPTYPE_INVALID = -EINVAL,
} L2tpEncapType;
typedef enum L2tpLocalAddressType {
NETDEV_L2TP_LOCAL_ADDRESS_STATIC,
NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC,
_NETDEV_L2TP_LOCAL_ADDRESS_MAX,
- _NETDEV_L2TP_LOCAL_ADDRESS_INVALID = -1,
+ _NETDEV_L2TP_LOCAL_ADDRESS_INVALID = -EINVAL,
} L2tpLocalAddressType;
typedef struct L2tpTunnel L2tpTunnel;
sa->use_for_encoding = -1;
}
-static void macsec_receive_association_free(ReceiveAssociation *c) {
+static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c) {
if (!c)
- return;
+ return NULL;
if (c->macsec && c->section)
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
network_config_section_free(c->section);
security_association_clear(&c->sa);
- free(c);
+ return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
return 0;
}
-static void macsec_receive_channel_free(ReceiveChannel *c) {
+static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
if (!c)
- return;
+ return NULL;
if (c->macsec) {
if (c->sci.as_uint64 > 0)
network_config_section_free(c->section);
- free(c);
+ return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
return 0;
}
-static void macsec_transmit_association_free(TransmitAssociation *a) {
+static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation *a) {
if (!a)
- return;
+ return NULL;
if (a->macsec && a->section)
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
network_config_section_free(a->section);
security_association_clear(&a->sa);
- free(a);
+ return mfree(a);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
k = netdev_kind_from_string(rvalue);
if (k < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse netdev kind, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse netdev kind, ignoring assignment: %s", rvalue);
return 0;
}
NETDEV_KIND_BAREUDP,
_NETDEV_KIND_MAX,
_NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
- _NETDEV_KIND_INVALID = -1
+ _NETDEV_KIND_INVALID = -EINVAL,
} NetDevKind;
typedef enum NetDevState {
NETDEV_STATE_READY,
NETDEV_STATE_LINGER,
_NETDEV_STATE_MAX,
- _NETDEV_STATE_INVALID = -1,
+ _NETDEV_STATE_INVALID = -EINVAL,
} NetDevState;
typedef enum NetDevCreateType {
NETDEV_CREATE_STACKED,
NETDEV_CREATE_AFTER_CONFIGURED,
_NETDEV_CREATE_MAX,
- _NETDEV_CREATE_INVALID = -1,
+ _NETDEV_CREATE_INVALID = -EINVAL,
} NetDevCreateType;
typedef struct Manager Manager;
if (r < 0) {
r = safe_atou32(rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse tunnel key ignoring assignment: %s", rvalue);
return 0;
}
} else
NETDEV_IP6_TNL_MODE_IPIP6,
NETDEV_IP6_TNL_MODE_ANYIP6,
_NETDEV_IP6_TNL_MODE_MAX,
- _NETDEV_IP6_TNL_MODE_INVALID = -1,
+ _NETDEV_IP6_TNL_MODE_INVALID = -EINVAL,
} Ip6TnlMode;
typedef enum IPv6FlowLabel {
NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
_NETDEV_IPV6_FLOWLABEL_MAX,
- _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
+ _NETDEV_IPV6_FLOWLABEL_INVALID = -EINVAL,
} IPv6FlowLabel;
typedef struct Tunnel {
NETDEV_VXLAN_DF_YES = VXLAN_DF_SET,
NETDEV_VXLAN_DF_INHERIT = VXLAN_DF_INHERIT,
_NETDEV_VXLAN_DF_MAX,
- _NETDEV_VXLAN_DF_INVALID = -1
+ _NETDEV_VXLAN_DF_INVALID = -EINVAL,
} VxLanDF;
struct VxLan {
static void resolve_endpoints(NetDev *netdev);
-static void wireguard_peer_free(WireguardPeer *peer) {
+static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
WireguardIPmask *mask;
if (!peer)
- return;
+ return NULL;
if (peer->wireguard) {
LIST_REMOVE(peers, peer->wireguard->peers, peer);
free(peer->preshared_key_file);
explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN);
- free(peer);
+ return mfree(peer);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free);
return CMP(a->ifindex, b->ifindex);
}
-static const LinkInfo* link_info_array_free(LinkInfo *array) {
+static LinkInfo* link_info_array_free(LinkInfo *array) {
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
sd_device_unref(array[i].sd_device);
free(array[i].ssid);
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL,
- *setup_state = NULL, *operational_state = NULL, *lease_file = NULL;
+ *setup_state = NULL, *operational_state = NULL, *lease_file = NULL, *activation_policy = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL,
*on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup;
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
if (r < 0)
return r;
+ r = sd_network_link_get_activation_policy(info->ifindex, &activation_policy);
+ if (r >= 0) {
+ r = table_add_many(table,
+ TABLE_EMPTY,
+ TABLE_STRING, "Activation Policy:",
+ TABLE_STRING, activation_policy);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
if (lease) {
const void *client_id;
size_t client_id_len;
" -s --stats Show detailed link statics\n"
" -l --full Do not ellipsize output\n"
" -n --lines=INTEGER Number of journal entries to show\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
static int run(int argc, char* argv[]) {
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "netlink-util.h"
#include "networkd-address-pool.h"
#include "networkd-address.h"
+#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-manager.h"
#include "networkd-network.h"
#include "parse-util.h"
}
static int address_add(Link *link, const Address *in, Address **ret) {
+ bool is_new = false;
Address *address;
int r;
r = address_add_internal(link, &link->addresses, in, &address);
if (r < 0)
return r;
+ is_new = true;
} else if (r == 0) {
/* Take over a foreign address */
r = set_ensure_put(&link->addresses, &address_hash_ops, address);
if (ret)
*ret = address;
-
- return 0;
+ return is_new;
}
static int address_update(Address *address, const Address *src) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *addr = NULL, *peer = NULL;
- char valid_buf[FORMAT_TIMESPAN_MAX];
- const char *valid_str = NULL;
+ char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
+ const char *valid_str = NULL, *preferred_str = NULL;
bool has_peer;
(void) in_addr_to_string(address->family, &address->in_addr, &addr);
address->cinfo.ifa_valid * USEC_PER_SEC,
USEC_PER_SEC);
- log_link_debug(link, "%s address: %s%s%s/%u (valid %s%s)",
+ if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
+ preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
+ address->cinfo.ifa_prefered * USEC_PER_SEC,
+ USEC_PER_SEC);
+
+ log_link_debug(link, "%s address: %s%s%s/%u (valid %s%s, preferred %s%s)",
str, strnull(addr), has_peer ? " peer " : "",
has_peer ? strnull(peer) : "", address->prefixlen,
- valid_str ? "for " : "forever", strempty(valid_str));
+ valid_str ? "for " : "forever", strempty(valid_str),
+ preferred_str ? "for " : "forever", strempty(preferred_str));
}
}
return 1;
}
+static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
+ int r;
+
+ assert(address);
+ assert(req);
+ assert(link);
+
+ r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set prefixlen: %m");
+
+ /* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all
+ * flags here unconditionally. Without setting the flag, the template addresses generated by
+ * kernel will not be removed automatically when the main address is removed. */
+ r = sd_rtnl_message_addr_set_flags(req, address->flags & 0xff);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set flags: %m");
+
+ if ((address->flags & ~0xff) != 0) {
+ r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set extended flags: %m");
+ }
+
+ r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
+
+ return 0;
+}
+
int address_remove(
const Address *address,
Link *link,
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
- r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set prefixlen: %m");
-
- r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
+ r = address_set_netlink_message(address, req, link);
if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
+ return r;
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: address_remove_handler,
const Address *address,
Link *link,
link_netlink_message_handler_t callback,
- bool update,
Address **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
Address *acquired_address, *a;
- uint32_t flags;
- int r;
+ bool update;
+ int r, k;
assert(address);
assert(IN_SET(address->family, AF_INET, AF_INET6));
if (acquired_address)
address = acquired_address;
+ update = address_get(link, address, NULL) >= 0;
+
log_address_debug(address, update ? "Updating" : "Configuring", link);
if (update)
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
- r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set prefixlen: %m");
-
- flags = address->flags | IFA_F_PERMANENT;
- r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
+ r = address_set_netlink_message(address, req, link);
if (r < 0)
- return log_link_error_errno(link, r, "Could not set flags: %m");
-
- if (flags & ~0xff) {
- r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set extended flags: %m");
- }
+ return r;
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
- r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
-
if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0)
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
- r = address_add(link, address, &a);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not add address: %m");
+ k = address_add(link, address, &a);
+ if (k < 0)
+ return log_link_error_errno(link, k, "Could not add address: %m");
r = address_set_masquerade(a, true);
if (r < 0)
if (ret)
*ret = a;
- return 1;
+ return k;
}
static int static_address_ready_callback(Address *address) {
Address *a;
Link *link;
+ int r;
assert(address);
assert(address->link);
link->addresses_ready = true;
+ r = link_set_ipv6_proxy_ndp_addresses(link);
+ if (r < 0)
+ return r;
+
return link_set_routes(link);
}
return 1;
}
-static int static_address_configure(const Address *address, Link *link, bool update) {
+static int static_address_configure(const Address *address, Link *link) {
Address *ret;
int r;
assert(address);
assert(link);
- r = address_configure(address, link, address_handler, update, &ret);
+ r = address_configure(address, link, address_handler, &ret);
if (r < 0)
return log_link_warning_errno(link, r, "Could not configure static address: %m");
}
ORDERED_HASHMAP_FOREACH(ad, link->network->addresses_by_section) {
- bool update;
-
- update = address_get(link, ad, NULL) > 0;
- r = static_address_configure(ad, link, update);
+ r = static_address_configure(ad, link);
if (r < 0)
return r;
}
return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
address->family = AF_INET6;
- r = static_address_configure(address, link, true);
+ r = static_address_configure(address, link);
if (r < 0)
return r;
}
if (link->address_messages == 0) {
link->addresses_configured = true;
link->addresses_ready = true;
+
+ r = link_set_ipv6_proxy_ndp_addresses(link);
+ if (r < 0)
+ return r;
+
r = link_set_routes(link);
if (r < 0)
return r;
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
- AddressFamily a;
int r;
assert(filename);
return 0;
}
- a = duplicate_address_detection_address_family_from_string(rvalue);
+ AddressFamily a = duplicate_address_detection_address_family_from_string(rvalue);
if (a < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL),
+ log_syntax(unit, LOG_WARNING, filename, line, a,
"Failed to parse %s=, ignoring: %s", lvalue, rvalue);
return 0;
}
-
n->duplicate_address_detection = a;
+
TAKE_PTR(n);
return 0;
}
int address_new(Address **ret);
Address *address_free(Address *address);
int address_get(Link *link, const Address *in, Address **ret);
-int address_configure(const Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret);
+int address_configure(const Address *address, Link *link, link_netlink_message_handler_t callback, Address **ret);
int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback);
bool address_equal(const Address *a1, const Address *a2);
bool address_is_ready(const Address *a);
type = duid_type_from_string(type_string);
if (type < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, type,
"Failed to parse DUID type '%s', ignoring.", type_string);
return 0;
}
/* Previously, we had a slightly different enum here,
* support its values for compatibility. */
- if (streq(rvalue, "none"))
- s = ADDRESS_FAMILY_NO;
- else if (streq(rvalue, "v4"))
- s = ADDRESS_FAMILY_IPV4;
- else if (streq(rvalue, "v6"))
- s = ADDRESS_FAMILY_IPV6;
- else if (streq(rvalue, "both"))
- s = ADDRESS_FAMILY_YES;
- else {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ s = dhcp_deprecated_address_family_from_string(rvalue);
+ if (s < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, s,
"Failed to parse DHCP option, ignoring: %s", rvalue);
return 0;
}
if (ltype == AF_INET) {
if (len > UINT8_MAX || len == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
- "%s length is not in the range 1-255, ignoring.", w);
+ "%s length is not in the range 1…255, ignoring.", w);
continue;
}
} else {
if (len > UINT16_MAX || len == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
- "%s length is not in the range 1-65535, ignoring.", w);
+ "%s length is not in the range 1…65535, ignoring.", w);
continue;
}
}
type = dhcp_option_data_type_from_string(word);
if (type < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, type,
"Invalid DHCP option data type, ignoring assignment: %s", p);
return 0;
}
DHCP_USE_DOMAINS_YES,
DHCP_USE_DOMAINS_ROUTE,
_DHCP_USE_DOMAINS_MAX,
- _DHCP_USE_DOMAINS_INVALID = -1,
+ _DHCP_USE_DOMAINS_INVALID = -EINVAL,
} DHCPUseDomains;
typedef enum DHCPOptionDataType {
log_link_debug(link, "Removing old DHCPv4 address and routes.");
- link_dirty(link);
-
SET_FOREACH(route, link->dhcp_routes_old) {
k = route_remove(route, NULL, link, NULL);
if (k < 0)
/* allow reusing an existing address and simply update its lifetime
* in case it already exists */
- r = address_configure(addr, link, dhcp4_address_handler, true, &ret);
+ r = address_configure(addr, link, dhcp4_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv4 address: %m");
* https://github.com/systemd/systemd/issues/7828 */
DHCP_CLIENT_ID_DUID_ONLY,
_DHCP_CLIENT_ID_MAX,
- _DHCP_CLIENT_ID_INVALID = -1,
+ _DHCP_CLIENT_ID_INVALID = -EINVAL,
} DHCPClientIdentifier;
int dhcp4_configure(Link *link);
#include "escape.h"
#include "hashmap.h"
+#include "hostname-setup.h"
#include "hostname-util.h"
#include "missing_network.h"
#include "networkd-address.h"
assert(link);
assert(link->manager);
- if (!force && (link->dhcp6_pd_address_messages != 0 || link->dhcp6_pd_route_configured != 0))
+ if (!force && (link->dhcp6_pd_address_messages != 0 || link->dhcp6_pd_route_messages != 0))
return 0;
if (set_isempty(link->dhcp6_pd_addresses_old) && set_isempty(link->dhcp6_pd_routes_old))
log_link_debug(link, "Removing old DHCPv6 Prefix Delegation addresses and routes.");
- link_dirty(link);
-
SET_FOREACH(route, link->dhcp6_pd_routes_old) {
k = route_remove(route, NULL, link, NULL);
if (k < 0)
log_link_debug(link, "Removing DHCPv6 Prefix Delegation addresses and routes.");
- link_dirty(link);
-
SET_FOREACH(route, link->dhcp6_pd_routes) {
k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = route_configure(route, link, dhcp6_pd_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 prefix route: %m");
+ if (r > 0)
+ link->dhcp6_pd_route_configured = false;
link->dhcp6_pd_route_messages++;
link_enter_failed(link);
return 1;
}
-
- r = link_set_routes(link);
- if (r < 0) {
- link_enter_failed(link);
- return 1;
- }
}
return 1;
address->cinfo.ifa_valid = lifetime_valid;
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
- r = address_configure(address, link, dhcp6_pd_address_handler, true, &ret);
+ r = address_configure(address, link, dhcp6_pd_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 delegated prefix address: %m");
+ if (r > 0)
+ link->dhcp6_pd_address_configured = false;
link->dhcp6_pd_address_messages++;
if (!link_dhcp6_pd_is_enabled(link))
return 0;
- link_dirty(link);
-
- link->dhcp6_pd_address_configured = false;
- link->dhcp6_pd_route_configured = false;
link->dhcp6_pd_prefixes_assigned = true;
while ((address = set_steal_first(link->dhcp6_pd_addresses))) {
if (link->dhcp6_pd_address_messages == 0) {
if (link->dhcp6_pd_prefixes_assigned)
link->dhcp6_pd_address_configured = true;
- } else {
+ } else
log_link_debug(link, "Setting DHCPv6 PD addresses");
- /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
- * called, the related flags must be cleared. Otherwise, the link becomes configured
- * state before routes are configured. */
- link->static_routes_configured = false;
- link->static_nexthops_configured = false;
- }
if (link->dhcp6_pd_route_messages == 0) {
if (link->dhcp6_pd_prefixes_assigned)
log_link_debug(link, "Removing old DHCPv6 addresses and routes.");
- link_dirty(link);
-
SET_FOREACH(route, link->dhcp6_routes_old) {
k = route_remove(route, NULL, link, NULL);
if (k < 0)
log_link_debug(link, "Removing DHCPv6 addresses and routes.");
- link_dirty(link);
-
SET_FOREACH(route, link->dhcp6_routes) {
k = route_remove(route, NULL, link, NULL);
if (k < 0)
if (r < 0)
return log_link_error_errno(link, r, "Failed to set unreachable route for DHCPv6 delegated subnet %s/%u: %m",
strna(buf), prefixlen);
+ if (r > 0)
+ link->dhcp6_route_configured = false;
link->dhcp6_route_messages++;
link_enter_failed(link);
return 1;
}
-
- r = link_set_routes(link);
- if (r < 0) {
- link_enter_failed(link);
- return 1;
- }
}
return 1;
log_dhcp6_address(link, addr, &buffer);
- r = address_configure(addr, link, dhcp6_address_handler, true, &ret);
+ r = address_configure(addr, link, dhcp6_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 address %s/%u: %m",
strnull(buffer), addr->prefixlen);
+ if (r > 0)
+ link->dhcp6_address_configured = false;
link->dhcp6_address_messages++;
return r;
}
+ if (link->network->dhcp6_use_fqdn) {
+ const char *dhcpname = NULL;
+ _cleanup_free_ char *hostname = NULL;
+ (void) sd_dhcp6_lease_get_fqdn(link->dhcp6_lease, &dhcpname);
+
+ if (dhcpname) {
+ r = shorten_overlong(dhcpname, &hostname);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
+ if (r == 1)
+ log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
+ }
+ if (hostname) {
+ r = manager_set_hostname(link->manager, hostname);
+ if (r < 0)
+ log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
+ }
+ }
+
return 0;
}
Route *rt;
int r;
- link->dhcp6_address_configured = false;
- link->dhcp6_route_configured = false;
-
- link_dirty(link);
-
while ((a = set_steal_first(link->dhcp6_addresses))) {
r = set_ensure_put(&link->dhcp6_addresses_old, &address_hash_ops, a);
if (r < 0)
if (link->dhcp6_address_messages == 0)
link->dhcp6_address_configured = true;
- else {
+ else
log_link_debug(link, "Setting DHCPv6 addresses");
- /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
- * called, the related flags must be cleared. Otherwise, the link becomes configured
- * state before routes are configured. */
- link->static_routes_configured = false;
- link->static_nexthops_configured = false;
- }
if (link->dhcp6_route_messages == 0)
link->dhcp6_route_configured = true;
DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST,
DHCP6_CLIENT_START_MODE_SOLICIT,
_DHCP6_CLIENT_START_MODE_MAX,
- _DHCP6_CLIENT_START_MODE_INVALID = -1,
+ _DHCP6_CLIENT_START_MODE_INVALID = -EINVAL,
} DHCP6ClientStartMode;
typedef struct Link Link;
_cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
Network *network = userdata;
- NeighborCacheEntryFlags f;
int r;
assert(filename);
if (r < 0)
return log_oom();
- f = fdb_ntf_flags_from_string(rvalue);
+ NeighborCacheEntryFlags f = fdb_ntf_flags_from_string(rvalue);
if (f < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL),
+ log_syntax(unit, LOG_WARNING, filename, line, f,
"FDB failed to parse AssociatedWith=, ignoring assignment: %s",
rvalue);
return 0;
NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER = NTF_MASTER,
NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER = NTF_ROUTER,
_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX,
- _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1,
+ _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -EINVAL,
} NeighborCacheEntryFlags;
typedef struct FdbEntry {
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "networkd-conf.h"
#include "networkd-manager.h"
+#include "networkd-route.h"
%}
struct ConfigPerfItem;
%null_strings
Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter)
Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec)
Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes)
+Network.RouteTable, config_parse_route_table_names, 0, 0
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid)
ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
ll_addr->scope = RT_SCOPE_LINK;
- r = address_configure(ll_addr, link, ipv4ll_address_handler, false, NULL);
+ r = address_configure(ll_addr, link, ipv4ll_address_handler, NULL);
if (r < 0)
return r;
assert(link);
r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST)
+ if (r < 0)
log_link_message_warning_errno(link, m, r, "Could not add IPv6 proxy ndp address entry, ignoring");
return 1;
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m");
- r = sd_rtnl_message_neigh_set_flags(req, NLM_F_REQUEST | NTF_PROXY);
+ r = sd_rtnl_message_neigh_set_flags(req, NTF_PROXY);
if (r < 0)
return log_link_error_errno(link, r, "Could not set neighbor flags: %m");
SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
- SD_BUS_METHOD("SetNTP", "as", NULL, bus_link_method_set_ntp_servers, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDNSEx", "a(iayqs)", NULL, bus_link_method_set_dns_servers_ex, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDefaultRoute", "b", NULL, bus_link_method_set_default_route, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RevertNTP", NULL, NULL, bus_link_method_revert_ntp, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RevertDNS", NULL, NULL, bus_link_method_revert_dns, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Renew", NULL, NULL, bus_link_method_renew, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ForceRenew", NULL, NULL, bus_link_method_force_renew, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Reconfigure", NULL, NULL, bus_link_method_reconfigure, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetNTP",
+ SD_BUS_ARGS("as", servers),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_ntp_servers,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDNS",
+ SD_BUS_ARGS("a(iay)", addresses),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_dns_servers,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDNSEx",
+ SD_BUS_ARGS("a(iayqs)", addresses),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_dns_servers_ex,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDomains",
+ SD_BUS_ARGS("a(sb)", domains),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_domains,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDefaultRoute",
+ SD_BUS_ARGS("b", enable),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_default_route,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLLMNR",
+ SD_BUS_ARGS("s", mode),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_llmnr,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetMulticastDNS",
+ SD_BUS_ARGS("s", mode),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_mdns,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDNSOverTLS",
+ SD_BUS_ARGS("s", mode),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_dns_over_tls,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDNSSEC",
+ SD_BUS_ARGS("s", mode),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_dnssec,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDNSSECNegativeTrustAnchors",
+ SD_BUS_ARGS("as", names),
+ SD_BUS_NO_RESULT,
+ bus_link_method_set_dnssec_negative_trust_anchors,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RevertNTP",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_link_method_revert_ntp,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RevertDNS",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_link_method_revert_dns,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Renew",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_link_method_renew,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ForceRenew",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_link_method_force_renew,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Reconfigure",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_link_method_reconfigure,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
#include "ethtool-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "ipvlan.h"
#include "missing_network.h"
#include "netlink-util.h"
#include "networkd-dhcp6.h"
#include "networkd-fdb.h"
#include "networkd-ipv4ll.h"
-#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-link-bus.h"
#include "networkd-link.h"
#include "networkd-lldp-tx.h"
link->state = state;
link_send_changed(link, "AdministrativeState", NULL);
+ link_dirty(link);
}
static void link_enter_unmanaged(Link *link) {
assert(link);
link_set_state(link, LINK_STATE_UNMANAGED);
-
- link_dirty(link);
}
int link_stop_engines(Link *link, bool may_keep_dhcp) {
link_set_state(link, LINK_STATE_FAILED);
(void) link_stop_engines(link, false);
-
- link_dirty(link);
}
static int link_join_netdevs_after_configured(Link *link) {
link_set_state(link, LINK_STATE_CONFIGURED);
(void) link_join_netdevs_after_configured(link);
-
- link_dirty(link);
}
void link_check_ready(Link *link) {
return 0;
}
-static int link_tx_rx_queues_hadler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(link);
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0)
- log_link_message_warning_errno(link, m, r, "Could not set transmit / receive queues for the interface");
-
- return 1;
-}
-
-static int link_set_tx_rx_queues(Link *link) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- int r;
-
- assert(link);
- assert(link->network);
- assert(link->manager);
- assert(link->manager->rtnl);
-
- if (link->network->txqueues == 0 && link->network->rxqueues == 0)
- return 0;
-
- log_link_debug(link, "Setting transmit / receive queues");
-
- r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
- if (link->network->txqueues > 0) {
- r = sd_netlink_message_append_u32(req, IFLA_NUM_TX_QUEUES, link->network->txqueues);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set link transmit queues: %m");
- }
-
- if (link->network->rxqueues > 0) {
- r = sd_netlink_message_append_u32(req, IFLA_NUM_RX_QUEUES, link->network->rxqueues);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set link receive queues: %m");
- }
-
- r = netlink_call_async(link->manager->rtnl, NULL, req, link_tx_rx_queues_hadler,
- link_netlink_destroy_callback, link);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
- link_ref(link);
-
- return 0;
-}
-
static int link_handle_bound_to_list(Link *link) {
Link *l;
int r;
if (r < 0)
return r;
+ link_dirty(link);
+
return 0;
}
Manager *m;
Link *carrier;
int r;
- bool list_updated = false;
assert(link);
assert(link->manager);
r = link_put_carrier(link, carrier, &link->bound_by_links);
if (r < 0)
return r;
-
- list_updated = true;
}
}
- if (list_updated)
- link_dirty(link);
-
HASHMAP_FOREACH(carrier, link->bound_by_links) {
r = link_put_carrier(carrier, link, &carrier->bound_to_links);
if (r < 0)
return r;
-
- link_dirty(carrier);
}
return 0;
Manager *m;
Link *carrier;
int r;
- bool list_updated = false;
assert(link);
assert(link->manager);
r = link_put_carrier(link, carrier, &link->bound_to_links);
if (r < 0)
return r;
-
- list_updated = true;
}
}
- if (list_updated)
- link_dirty(link);
-
HASHMAP_FOREACH (carrier, link->bound_to_links) {
r = link_put_carrier(carrier, link, &carrier->bound_by_links);
if (r < 0)
return r;
-
- link_dirty(carrier);
}
return 0;
}
static void link_free_bound_to_list(Link *link) {
+ bool updated = false;
Link *bound_to;
- HASHMAP_FOREACH (bound_to, link->bound_to_links) {
- hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
+ assert(link);
+
+ while ((bound_to = hashmap_steal_first(link->bound_to_links))) {
+ updated = true;
if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
link_dirty(bound_to);
}
+ if (updated)
+ link_dirty(link);
+
return;
}
static void link_free_bound_by_list(Link *link) {
+ bool updated = false;
Link *bound_by;
- HASHMAP_FOREACH (bound_by, link->bound_by_links) {
- hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
+ assert(link);
+
+ while ((bound_by = hashmap_steal_first(link->bound_by_links))) {
+ updated = true;
if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
link_dirty(bound_by);
}
}
+ if (updated)
+ link_dirty(link);
+
return;
}
static void link_free_carrier_maps(Link *link) {
- bool list_updated = false;
-
assert(link);
- if (!hashmap_isempty(link->bound_to_links)) {
- link_free_bound_to_list(link);
- list_updated = true;
- }
-
- if (!hashmap_isempty(link->bound_by_links)) {
- link_free_bound_by_list(link);
- list_updated = true;
- }
-
- if (list_updated)
- link_dirty(link);
+ link_free_bound_to_list(link);
+ link_free_bound_by_list(link);
return;
}
assert(link);
assert(link->network);
- if (!hashmap_isempty(link->bound_to_links)) {
+ switch (link->network->activation_policy) {
+ case ACTIVATION_POLICY_BOUND:
r = link_handle_bound_to_list(link);
if (r < 0)
return r;
- } else if (!(link->flags & IFF_UP)) {
+ break;
+ case ACTIVATION_POLICY_UP:
+ if (link->activated)
+ break;
+ _fallthrough_;
+ case ACTIVATION_POLICY_ALWAYS_UP:
r = link_up(link);
if (r < 0) {
link_enter_failed(link);
return r;
}
+ break;
+ case ACTIVATION_POLICY_DOWN:
+ if (link->activated)
+ break;
+ _fallthrough_;
+ case ACTIVATION_POLICY_ALWAYS_DOWN:
+ r = link_down(link, NULL);
+ if (r < 0) {
+ link_enter_failed(link);
+ return r;
+ }
+ break;
+ default:
+ break;
}
+ link->activated = true;
if (link->network->bridge) {
r = link_set_bridge(link);
link_set_state(link, LINK_STATE_CONFIGURING);
- link_dirty(link);
link->enslaving = 0;
if (link->network->bond) {
if (r < 0)
return r;
- r = link_set_ipv6_proxy_ndp_addresses(link);
- if (r < 0)
- return r;
-
r = link_set_mac(link);
if (r < 0)
return r;
if (r < 0)
return r;
- r = link_set_tx_rx_queues(link);
- if (r < 0)
- return r;
-
r = ipv4ll_configure(link);
if (r < 0)
return r;
link_unref(set_remove(link->manager->links_requesting_uuid, link));
/* Then, apply new .network file */
- r = network_apply(network, link);
- if (r < 0)
- return r;
+ link->network = network_ref(network);
+ link_dirty(link);
r = link_new_carrier_maps(link);
if (r < 0)
return r;
link_set_state(link, LINK_STATE_INITIALIZED);
- link_dirty(link);
+ link->activated = false;
/* link_configure_duid() returns 0 if it requests product UUID. In that case,
* link_configure() is called later asynchronously. */
log_link_debug(link, "Ignoring DHCP server for loopback link");
}
- r = network_apply(network, link);
- if (r < 0)
- return r;
+ link->network = network_ref(network);
+ link_dirty(link);
}
r = link_new_bound_to_list(link);
static int link_admin_state_up(Link *link) {
int r;
+ assert(link);
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN) {
+ log_link_info(link, "ActivationPolicy is \"always-off\", forcing link down");
+ return link_down(link, NULL);
+ }
+
/* We set the ipv6 mtu after the device mtu, but the kernel resets
* ipv6 mtu on NETDEV_UP, so we need to reset it. The check for
* ipv6_mtu_set prevents this from trying to set it too early before
return 0;
}
+static int link_admin_state_down(Link *link) {
+
+ assert(link);
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
+ log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up");
+ return link_up(link);
+ }
+
+ return 0;
+}
+
int link_update(Link *link, sd_netlink_message *m) {
_cleanup_strv_free_ char **s = NULL;
hw_addr_data hw_addr;
r = link_admin_state_up(link);
if (r < 0)
return r;
- } else if (link_was_admin_up && !(link->flags & IFF_UP))
+ } else if (link_was_admin_up && !(link->flags & IFF_UP)) {
log_link_info(link, "Link DOWN");
+ r = link_admin_state_down(link);
+ if (r < 0)
+ return r;
+ }
+
r = link_update_lldp(link);
if (r < 0)
return r;
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
+ fprintf(f, "ACTIVATION_POLICY=%s\n",
+ activation_policy_to_string(link->network->activation_policy));
+
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
/************************************************************/
if (r < 0)
goto fail;
- if (rename(temp_path, link->state_file) < 0) {
- r = -errno;
+ r = conservative_rename(temp_path, link->state_file);
+ if (r < 0)
goto fail;
- }
return 0;
LINK_STATE_FAILED, /* at least one configuration process failed */
LINK_STATE_LINGER, /* RTM_DELLINK for the link has been received */
_LINK_STATE_MAX,
- _LINK_STATE_INVALID = -1
+ _LINK_STATE_INVALID = -EINVAL,
} LinkState;
typedef struct Manager Manager;
bool setting_genmode:1;
bool ipv6_mtu_set:1;
bool bridge_mdb_configured:1;
+ bool activated:1;
sd_dhcp_server *dhcp_server;
LLDP_MODE_YES = 1,
LLDP_MODE_ROUTERS_ONLY = 2,
_LLDP_MODE_MAX,
- _LLDP_MODE_INVALID = -1,
+ _LLDP_MODE_INVALID = -EINVAL,
} LLDPMode;
int link_lldp_rx_configure(Link *link);
#include "parse-util.h"
#include "random-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unaligned.h"
link->lldp_emit_event_source = sd_event_source_unref(link->lldp_emit_event_source);
}
-int config_parse_lldp_emit(
- 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) {
-
- LLDPEmit *emit = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- if (isempty(rvalue))
- *emit = LLDP_EMIT_NO;
- else if (streq(rvalue, "nearest-bridge"))
- *emit = LLDP_EMIT_NEAREST_BRIDGE;
- else if (streq(rvalue, "non-tpmr-bridge"))
- *emit = LLDP_EMIT_NON_TPMR_BRIDGE;
- else if (streq(rvalue, "customer-bridge"))
- *emit = LLDP_EMIT_CUSTOMER_BRIDGE;
- else {
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse LLDP emission setting, ignoring: %s", rvalue);
- return 0;
- }
-
- *emit = r ? LLDP_EMIT_NEAREST_BRIDGE : LLDP_EMIT_NO;
- }
-
- return 0;
-}
-
int config_parse_lldp_mud(
const char *unit,
const char *filename,
return free_and_replace(n->lldp_mud, unescaped);
}
+
+static const char * const lldp_emit_table[_LLDP_EMIT_MAX] = {
+ [LLDP_EMIT_NO] = "no",
+ [LLDP_EMIT_NEAREST_BRIDGE] = "nearest-bridge",
+ [LLDP_EMIT_NON_TPMR_BRIDGE] = "non-tpmr-bridge",
+ [LLDP_EMIT_CUSTOMER_BRIDGE] = "customer-bridge",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(lldp_emit, LLDPEmit, LLDP_EMIT_NEAREST_BRIDGE);
+DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_lldp_emit, lldp_emit, LLDPEmit, LLDP_EMIT_NO, "Failed to parse LLDP emission setting");
LLDP_EMIT_NON_TPMR_BRIDGE,
LLDP_EMIT_CUSTOMER_BRIDGE,
_LLDP_EMIT_MAX,
+ _LLDP_EMIT_INVALID = -EINVAL,
} LLDPEmit;
bool link_lldp_emit_enabled(Link *link);
SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Manager, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_METHOD("ListLinks", NULL, "a(iso)", method_list_links, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetLinkByName", "s", "io", method_get_link_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetLinkByIndex", "i", "so", method_get_link_by_index, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkNTP", "ias", NULL, bus_method_set_link_ntp_servers, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDNSEx", "ia(iayqs)", NULL, bus_method_set_link_dns_servers_ex, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDefaultRoute", "ib", NULL, bus_method_set_link_default_route, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RevertLinkNTP", "i", NULL, bus_method_revert_link_ntp, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RevertLinkDNS", "i", NULL, bus_method_revert_link_dns, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RenewLink", "i", NULL, bus_method_renew_link, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ForceRenewLink", "i", NULL, bus_method_force_renew_link, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ReconfigureLink", "i", NULL, bus_method_reconfigure_link, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Reload", NULL, NULL, bus_method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ListLinks",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("a(iso)", links),
+ method_list_links,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetLinkByName",
+ SD_BUS_ARGS("s", name),
+ SD_BUS_RESULT("i", ifindex, "o", path),
+ method_get_link_by_name,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetLinkByIndex",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_RESULT("s", name, "o", path),
+ method_get_link_by_index,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkNTP",
+ SD_BUS_ARGS("i", ifindex, "as", servers),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_ntp_servers,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
+ SD_BUS_ARGS("i", ifindex, "a(iay)", addresses),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_dns_servers,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
+ SD_BUS_ARGS("i", ifindex, "a(iayqs)", addresses),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_dns_servers_ex,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
+ SD_BUS_ARGS("i", ifindex, "a(sb)", domains),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_domains,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
+ SD_BUS_ARGS("i", ifindex, "b", enable),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_default_route,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
+ SD_BUS_ARGS("i", ifindex, "s", mode),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_llmnr,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
+ SD_BUS_ARGS("i", ifindex, "s", mode),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_mdns,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
+ SD_BUS_ARGS("i", ifindex, "s", mode),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_dns_over_tls,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
+ SD_BUS_ARGS("i", ifindex, "s", mode),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_dnssec,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
+ SD_BUS_ARGS("i", ifindex, "as", names),
+ SD_BUS_NO_RESULT,
+ bus_method_set_link_dnssec_negative_trust_anchors,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RevertLinkNTP",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_NO_RESULT,
+ bus_method_revert_link_ntp,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RevertLinkDNS",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_NO_RESULT,
+ bus_method_revert_link_dns,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RenewLink",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_NO_RESULT,
+ bus_method_renew_link,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ForceRenewLink",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_NO_RESULT,
+ bus_method_force_renew_link,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ReconfigureLink",
+ SD_BUS_ARGS("i", ifindex),
+ SD_BUS_NO_RESULT,
+ bus_method_reconfigure_link,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Reload",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_method_reload,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
#include "fd-util.h"
#include "fileio.h"
#include "firewall-util.h"
+#include "fs-util.h"
#include "local-addresses.h"
#include "netlink-util.h"
#include "network-internal.h"
if (r < 0)
goto fail;
- if (rename(temp_path, m->state_file) < 0) {
- r = -errno;
+ r = conservative_rename(temp_path, m->state_file);
+ if (r < 0)
goto fail;
- }
if (m->operational_state != operstate) {
m->operational_state = operstate;
return 0;
}
-void manager_free(Manager *m) {
+Manager* manager_free(Manager *m) {
Link *link;
if (!m)
- return;
+ return NULL;
free(m->state_file);
ordered_set_free_free(m->address_pools);
+ hashmap_free(m->route_table_names_by_number);
+ hashmap_free(m->route_table_numbers_by_name);
+
/* routing_policy_rule_free() access m->rules and m->rules_foreign.
* So, it is necessary to set NULL after the sets are freed. */
m->rules = set_free(m->rules);
m->fw_ctx = fw_ctx_free(m->fw_ctx);
- free(m);
+ return mfree(m);
}
int manager_start(Manager *m) {
log_debug("Setting transient hostname: '%s'", strna(hostname));
- if (free_and_strdup(&m->dynamic_hostname, hostname) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&m->dynamic_hostname, hostname);
+ if (r < 0)
+ return r;
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
log_debug("Not connected to system bus, setting hostname later.");
assert(tz);
log_debug("Setting system timezone: '%s'", tz);
- if (free_and_strdup(&m->dynamic_timezone, tz) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&m->dynamic_timezone, tz);
+ if (r < 0)
+ return r;
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
log_debug("Not connected to system bus, setting timezone later.");
Set *routes;
Set *routes_foreign;
+ /* Route table name */
+ Hashmap *route_table_numbers_by_name;
+ Hashmap *route_table_names_by_number;
+
/* For link speed meter*/
bool use_speed_meter;
sd_event_source *speed_meter_event_source;
};
int manager_new(Manager **ret);
-void manager_free(Manager *m);
+Manager* manager_free(Manager *m);
int manager_connect_bus(Manager *m);
int manager_start(Manager *m);
NDiscDNSSL *dnssl;
NDiscRDNSS *rdnss;
int k, r = 0;
+ bool updated = false;
assert(link);
assert(router);
log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf));
}
- link_dirty(link);
-
SET_FOREACH(na, link->ndisc_addresses)
if (na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) {
k = address_remove(na->address, link, NULL);
}
SET_FOREACH(rdnss, link->ndisc_rdnss)
- if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router))
+ if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) {
free(set_remove(link->ndisc_rdnss, rdnss));
+ updated = true;
+ }
SET_FOREACH(dnssl, link->ndisc_dnssl)
- if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router))
+ if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) {
free(set_remove(link->ndisc_dnssl, dnssl));
+ updated = true;
+ }
+
+ if (updated)
+ link_dirty(link);
return r;
}
r = route_configure(route, link, ndisc_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
+ if (r > 0)
+ link->ndisc_routes_configured = false;
link->ndisc_routes_messages++;
link_enter_failed(link);
return 1;
}
-
- r = link_set_routes(link);
- if (r < 0) {
- link_enter_failed(link);
- return 1;
- }
}
return 1;
assert(link);
assert(rt);
- r = address_configure(address, link, ndisc_address_handler, true, &ret);
+ r = address_configure(address, link, ndisc_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc SLAAC address: %m");
+ if (r > 0)
+ link->ndisc_addresses_configured = false;
link->ndisc_addresses_messages++;
struct in6_addr router;
NDiscRDNSS *rdnss;
usec_t time_now;
+ bool updated = false;
int n, r;
assert(link);
if (r < 0)
return log_oom();
assert(r > 0);
+
+ updated = true;
}
+ if (updated)
+ link_dirty(link);
+
return 0;
}
uint32_t lifetime;
usec_t time_now;
NDiscDNSSL *dnssl;
+ bool updated = false;
char **j;
int r;
if (r < 0)
return log_oom();
assert(r > 0);
+
+ updated = true;
}
+ if (updated)
+ link_dirty(link);
+
return 0;
}
return 0;
}
- link->ndisc_addresses_configured = false;
- link->ndisc_routes_configured = false;
-
- link_dirty(link);
-
SET_FOREACH(na, link->ndisc_addresses)
if (IN6_ARE_ADDR_EQUAL(&na->router, &router.in6))
na->marked = true;
if (link->ndisc_addresses_messages == 0)
link->ndisc_addresses_configured = true;
- else {
+ else
log_link_debug(link, "Setting SLAAC addresses.");
- /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
- * called, the related flags must be cleared. Otherwise, the link becomes configured
- * state before routes are configured. */
- link->static_routes_configured = false;
- link->static_nexthops_configured = false;
- }
-
if (link->ndisc_routes_messages == 0)
link->ndisc_routes_configured = true;
else
NDiscRDNSS *r;
NDiscDNSSL *d;
usec_t time_now;
- bool updated = false;
assert(link);
time_now = now(clock_boottime_or_monotonic());
SET_FOREACH(r, link->ndisc_rdnss)
- if (r->valid_until < time_now) {
+ if (r->valid_until < time_now)
free(set_remove(link->ndisc_rdnss, r));
- updated = true;
- }
SET_FOREACH(d, link->ndisc_dnssl)
- if (d->valid_until < time_now) {
+ if (d->valid_until < time_now)
free(set_remove(link->ndisc_dnssl, d));
- updated = true;
- }
-
- if (updated)
- link_dirty(link);
}
void ndisc_flush(Link *link) {
token->prefix = buffer.in6;
}
- r = ordered_set_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
- if (r < 0)
+ r = ordered_set_ensure_put(&network->ipv6_tokens, &ipv6_token_hash_ops, token);
+ if (r == -ENOMEM)
return log_oom();
-
- r = ordered_set_put(network->ipv6_tokens, token);
if (r == -EEXIST)
log_syntax(unit, LOG_DEBUG, filename, line, r,
"IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
IPV6_TOKEN_ADDRESS_GENERATION_STATIC,
IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE,
_IPV6_TOKEN_ADDRESS_GENERATION_MAX,
- _IPV6_TOKEN_ADDRESS_GENERATION_INVALID = -1,
+ _IPV6_TOKEN_ADDRESS_GENERATION_INVALID = -EINVAL,
} IPv6TokenAddressGeneration;
typedef enum IPv6AcceptRAStartDHCP6Client {
IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS,
IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX,
- _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1,
+ _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -EINVAL,
} IPv6AcceptRAStartDHCP6Client;
typedef struct NDiscAddress {
};
int ipv6token_new(IPv6Token **ret);
-DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6Token *, freep);
static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));
}
static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) {
+ bool is_new = false;
Neighbor *neighbor;
int r;
r = neighbor_add_internal(link, &link->neighbors, in, &neighbor);
if (r < 0)
return r;
+ is_new = true;
} else if (r == 0) {
/* Neighbor is foreign, claim it as recognized */
r = set_ensure_put(&link->neighbors, &neighbor_hash_ops, neighbor);
set_remove(link->neighbors_foreign, neighbor);
} else if (r == 1) {
/* Neighbor already exists */
+ ;
} else
return r;
if (ret)
*ret = neighbor;
- return 0;
+ return is_new;
}
static int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) {
if (r < 0)
return log_link_error_errno(link, r, "Could not add neighbor: %m");
- return 0;
+ return r;
}
int link_set_neighbors(Link *link) {
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
Link.Group, config_parse_uint32, 0, offsetof(Network, group)
-Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(Network, txqueues)
-Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(Network, rxqueues)
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast)
Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)
Link.Promiscuous, config_parse_tristate, 0, offsetof(Network, promiscuous)
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
+Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy)
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address)
DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0
+DHCPv6.UseFQDN, config_parse_bool, 0, offsetof(Network, dhcp6_use_fqdn)
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
if (network->dhcp_use_gateway < 0)
network->dhcp_use_gateway = network->dhcp_use_routes;
- if (network->ignore_carrier_loss < 0)
- network->ignore_carrier_loss = network->configure_without_carrier;
-
if (network->dhcp_critical >= 0) {
if (network->keep_configuration >= 0)
log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
network->keep_configuration = KEEP_CONFIGURATION_NO;
}
+ if (!strv_isempty(network->bind_carrier)) {
+ if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
+ log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
+ "Setting ActivationPolicy=bound.", network->filename);
+ network->activation_policy = ACTIVATION_POLICY_BOUND;
+ } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
+ log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
+ "Ignoring ActivationPolicy=bound.", network->filename);
+ network->activation_policy = ACTIVATION_POLICY_UP;
+ }
+
+ if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
+ network->activation_policy = ACTIVATION_POLICY_UP;
+
+ if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
+ if (network->ignore_carrier_loss == false)
+ log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. "
+ "Setting IgnoreCarrierLoss=true.", network->filename);
+ network->ignore_carrier_loss = true;
+ }
+
+ if (network->ignore_carrier_loss < 0)
+ network->ignore_carrier_loss = network->configure_without_carrier;
+
if (network->keep_configuration < 0)
network->keep_configuration = KEEP_CONFIGURATION_NO;
.required_for_online = true,
.required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
+ .activation_policy = _ACTIVATION_POLICY_INVALID,
.arp = -1,
.multicast = -1,
.allmulticast = -1,
.dhcp6_use_address = true,
.dhcp6_use_dns = true,
+ .dhcp6_use_fqdn = true,
.dhcp6_use_ntp = true,
.dhcp6_rapid_commit = true,
.dhcp6_route_metric = DHCP_ROUTE_METRIC,
return -ENOENT;
}
-int network_apply(Network *network, Link *link) {
- assert(network);
- assert(link);
-
- link->network = network_ref(network);
-
- if (network->n_dns > 0 ||
- !strv_isempty(network->ntp) ||
- !ordered_set_isempty(network->search_domains) ||
- !ordered_set_isempty(network->route_domains))
- link_dirty(link);
-
- return 0;
-}
-
bool network_has_static_ipv6_configurations(Network *network) {
Address *address;
Route *route;
if (!name)
return log_oom();
- r = hashmap_ensure_allocated(h, &string_hash_ops);
- if (r < 0)
+ r = hashmap_ensure_put(h, &string_hash_ops, name, INT_TO_PTR(kind));
+ if (r == -ENOMEM)
return log_oom();
-
- r = hashmap_put(*h, name, INT_TO_PTR(kind));
if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r,
"Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
log_syntax(unit, LOG_DEBUG, filename, line, r,
"NetDev '%s' specified twice, ignoring.", name);
else
- name = NULL;
+ TAKE_PTR(name);
return 0;
}
return 0;
}
-int config_parse_rx_tx_queues(
- 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 k, *v = data;
- int r;
-
- if (isempty(rvalue)) {
- *v = 0;
- return 0;
- }
-
- r = safe_atou32(rvalue, &k);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
- return 0;
- }
- if (k == 0 || k > 4096) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
- return 0;
- }
-
- *v = k;
- return 0;
-}
-
DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
"Failed to parse KeepConfiguration= setting");
DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode");
+
+static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
+ [ACTIVATION_POLICY_UP] = "up",
+ [ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
+ [ACTIVATION_POLICY_MANUAL] = "manual",
+ [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
+ [ACTIVATION_POLICY_DOWN] = "down",
+ [ACTIVATION_POLICY_BOUND] = "bound",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");
KEEP_CONFIGURATION_STATIC = 1 << 2,
KEEP_CONFIGURATION_YES = KEEP_CONFIGURATION_DHCP | KEEP_CONFIGURATION_STATIC,
_KEEP_CONFIGURATION_MAX,
- _KEEP_CONFIGURATION_INVALID = -1,
+ _KEEP_CONFIGURATION_INVALID = -EINVAL,
} KeepConfiguration;
typedef enum IPv6LinkLocalAddressGenMode {
IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY = IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_RANDOM = IN6_ADDR_GEN_MODE_RANDOM,
_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX,
- _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID = -1
+ _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID = -EINVAL,
} IPv6LinkLocalAddressGenMode;
+typedef enum ActivationPolicy {
+ ACTIVATION_POLICY_UP,
+ ACTIVATION_POLICY_ALWAYS_UP,
+ ACTIVATION_POLICY_MANUAL,
+ ACTIVATION_POLICY_ALWAYS_DOWN,
+ ACTIVATION_POLICY_DOWN,
+ ACTIVATION_POLICY_BOUND,
+ _ACTIVATION_POLICY_MAX,
+ _ACTIVATION_POLICY_INVALID = -EINVAL,
+} ActivationPolicy;
+
typedef struct Manager Manager;
typedef struct NetworkDHCPServerEmitAddress {
struct ether_addr *mac;
uint32_t mtu;
uint32_t group;
- uint32_t txqueues;
- uint32_t rxqueues;
int arp;
int multicast;
int allmulticast;
bool unmanaged;
bool required_for_online; /* Is this network required to be considered online? */
LinkOperationalStateRange required_operstate_for_online;
+ ActivationPolicy activation_policy;
/* misc settings */
bool configure_without_carrier;
bool dhcp6_use_address;
bool dhcp6_use_dns;
bool dhcp6_use_dns_set;
+ bool dhcp6_use_fqdn;
bool dhcp6_use_ntp;
bool dhcp6_use_ntp_set;
bool dhcp6_rapid_commit;
const struct ether_addr *mac, const struct ether_addr *permanent_mac,
enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
Network **ret);
-int network_apply(Network *network, Link *link);
void network_apply_anonymize_if_set(Network *network);
bool network_has_static_ipv6_configurations(Network *network);
CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
-CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
+CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
const char* ipv6_link_local_address_gen_mode_to_string(IPv6LinkLocalAddressGenMode s) _const_;
IPv6LinkLocalAddressGenMode ipv6_link_local_address_gen_mode_from_string(const char *s) _pure_;
+
+const char* activation_policy_to_string(ActivationPolicy i) _const_;
+ActivationPolicy activation_policy_from_string(const char *s) _pure_;
}
static int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
+ bool is_new = false;
NextHop *nexthop;
int r;
r = nexthop_add_internal(link, &link->nexthops, in, &nexthop);
if (r < 0)
return r;
+ is_new = true;
} else if (r == 0) {
/* Take over a foreign nexthop */
r = set_ensure_put(&link->nexthops, &nexthop_hash_ops, nexthop);
if (ret)
*ret = nexthop;
-
- return 0;
+ return is_new;
}
static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
-
- r = sd_rtnl_message_nexthop_set_family(req, nexthop->family);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set nexthop family: %m");
}
r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,
if (r < 0)
return log_link_error_errno(link, r, "Could not add nexthop: %m");
- return 1;
+ return r;
}
int link_set_nexthop(Link *link) {
/* For backward compatibility */
val = radv_prefix_delegation_from_string(rvalue);
if (val < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, val,
"Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
RADV_PREFIX_DELEGATION_DHCP6 = 1 << 1,
RADV_PREFIX_DELEGATION_BOTH = RADV_PREFIX_DELEGATION_STATIC | RADV_PREFIX_DELEGATION_DHCP6,
_RADV_PREFIX_DELEGATION_MAX,
- _RADV_PREFIX_DELEGATION_INVALID = -1,
+ _RADV_PREFIX_DELEGATION_INVALID = -EINVAL,
} RADVPrefixDelegation;
typedef struct Prefix {
[RT_SCOPE_NOWHERE] = "nowhere",
};
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int);
-
-#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1)
-static const char *format_route_scope(int scope, char *buf, size_t size) {
- const char *s;
- char *p = buf;
-
- s = route_scope_to_string(scope);
- if (s)
- strpcpy(&p, size, s);
- else
- strpcpyf(&p, size, "%d", scope);
-
- return buf;
-}
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_scope, int);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(route_scope, int, UINT8_MAX);
static const char * const route_table_table[] = {
[RT_TABLE_DEFAULT] = "default",
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int);
-#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
-static const char *format_route_table(int table, char *buf, size_t size) {
+int manager_get_route_table_from_string(const Manager *m, const char *s, uint32_t *ret) {
+ uint32_t t;
+ int r;
+
+ assert(m);
+ assert(s);
+ assert(ret);
+
+ r = route_table_from_string(s);
+ if (r >= 0) {
+ *ret = (uint32_t) r;
+ return 0;
+ }
+
+ t = PTR_TO_UINT32(hashmap_get(m->route_table_numbers_by_name, s));
+ if (t != 0) {
+ *ret = t;
+ return 0;
+ }
+
+ r = safe_atou32(s, &t);
+ if (r < 0)
+ return r;
+
+ if (t == 0)
+ return -ERANGE;
+
+ *ret = t;
+ return 0;
+}
+
+int manager_get_route_table_to_string(const Manager *m, uint32_t table, char **ret) {
+ _cleanup_free_ char *str = NULL;
const char *s;
- char *p = buf;
+
+ assert(m);
+ assert(ret);
+
+ if (table == 0)
+ return -EINVAL;
s = route_table_to_string(table);
- if (s)
- strpcpy(&p, size, s);
- else
- strpcpyf(&p, size, "%d", table);
+ if (!s)
+ s = hashmap_get(m->route_table_names_by_number, UINT32_TO_PTR(table));
+
+ if (s) {
+ /* Currently, this is only used in debugging logs. To not confuse any bug
+ * reports, let's include the table number. */
+ if (asprintf(&str, "%s(%" PRIu32 ")", s, table) < 0)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(str);
+ return 0;
+ }
+
+ if (asprintf(&str, "%" PRIu32, table) < 0)
+ return -ENOMEM;
- return buf;
+ *ret = TAKE_PTR(str);
+ return 0;
}
static const char * const route_protocol_table[] = {
[RTPROT_STATIC] = "static",
};
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(route_protocol, int, UINT8_MAX);
static const char * const route_protocol_full_table[] = {
[RTPROT_REDIRECT] = "redirect",
[RTPROT_EIGRP] = "eigrp",
};
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int);
-
-#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1)
-static const char *format_route_protocol(int protocol, char *buf, size_t size) {
- const char *s;
- char *p = buf;
-
- s = route_protocol_full_to_string(protocol);
- if (s)
- strpcpy(&p, size, s);
- else
- strpcpyf(&p, size, "%d", protocol);
-
- return buf;
-}
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(route_protocol_full, int, UINT8_MAX);
static unsigned routes_max(void) {
static thread_local unsigned cached = 0;
static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) {
_cleanup_(route_freep) Route *tmp = NULL;
+ bool is_new = false;
Route *route;
int r;
r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, &route);
if (r < 0)
return r;
+ is_new = true;
} else if (r == 0) {
/* Take over a foreign route */
if (link) {
if (ret)
*ret = route;
-
- return 0;
+ return is_new;
}
static bool route_type_is_reject(const Route *route) {
return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW);
}
-static void log_route_debug(const Route *route, const char *str, const Link *link) {
+static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *m) {
assert(route);
assert(str);
+ assert(m);
/* link may be NULL. */
if (DEBUG_LOGGING) {
- _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
- char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
+ _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL,
+ *prefsrc = NULL, *table = NULL, *scope = NULL, *proto = NULL;
if (!in_addr_is_null(route->family, &route->dst)) {
(void) in_addr_to_string(route->family, &route->dst, &dst);
(void) in_addr_to_string(route->gw_family, &route->gw, &gw);
if (!in_addr_is_null(route->family, &route->prefsrc))
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
+ (void) route_scope_to_string_alloc(route->scope, &scope);
+ (void) manager_get_route_table_to_string(m, route->table, &table);
+ (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
log_link_debug(link,
"%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
str, strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
- format_route_scope(route->scope, scope, sizeof(scope)),
- format_route_table(route->table, table, sizeof(table)),
- format_route_protocol(route->protocol, protocol, sizeof(protocol)),
+ strna(scope), strna(table), strna(proto),
strna(route_type_to_string(route->type)));
}
}
manager = link->manager;
/* link may be NULL! */
- log_route_debug(route, "Removing", link);
+ log_route_debug(route, "Removing", link, manager);
r = sd_rtnl_message_new_route(manager->rtnl, &req,
RTM_DELROUTE, route->family,
routes = foreign ? manager->routes_foreign : manager->routes;
SET_FOREACH(route, routes) {
- /* Do not touch routes managed by the kernel */
+ /* Do not touch routes managed by the kernel. */
if (route->protocol == RTPROT_KERNEL)
continue;
- /* The route will be configured later, or already configured by a link */
+ /* The route will be configured later, or already configured by a link. */
if (links_have_route(manager, route, except))
continue;
- /* The existing links do not have the route. Let's drop this now. It may by
+ /* The existing links do not have the route. Let's drop this now. It may be
* re-configured later. */
k = route_remove(route, manager, NULL, NULL);
if (k < 0 && r >= 0)
static int route_add_and_setup_timer(Link *link, const Route *route, const MultipathRoute *m, Route **ret) {
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
Route *nr;
- int r;
+ int r, k;
assert(link);
assert(route);
if (route_type_is_reject(route))
- r = route_add(link->manager, NULL, route, NULL, &nr);
+ k = route_add(link->manager, NULL, route, NULL, &nr);
else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex)
- r = route_add(NULL, link, route, m, &nr);
+ k = route_add(NULL, link, route, m, &nr);
else {
Link *link_gw;
if (r < 0)
return log_link_error_errno(link, r, "Failed to get link with ifindex %d: %m", m->ifindex);
- r = route_add(NULL, link_gw, route, m, &nr);
+ k = route_add(NULL, link_gw, route, m, &nr);
}
- if (r < 0)
- return log_link_error_errno(link, r, "Could not add route: %m");
+ if (k < 0)
+ return log_link_error_errno(link, k, "Could not add route: %m");
/* TODO: drop expiration handling once it can be pushed into the kernel */
if (nr->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
if (ret)
*ret = nr;
- return 0;
+ return k;
}
static int append_nexthop_one(const Route *route, const MultipathRoute *m, struct rtattr **rta, size_t offset) {
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- int r;
+ int r, k = 0;
+ Route *nr;
assert(link);
assert(link->manager);
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
"Too many routes are configured, refusing: %m");
- log_route_debug(route, "Configuring", link);
+ log_route_debug(route, "Configuring", link, link->manager);
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
RTM_NEWROUTE, route->family,
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ordered_set_isempty(route->multipath_routes)) {
- Route *nr;
-
- r = route_add_and_setup_timer(link, route, NULL, &nr);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = nr;
+ k = route_add_and_setup_timer(link, route, NULL, &nr);
+ if (k < 0)
+ return k;
} else {
MultipathRoute *m;
r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0)
return r;
+ if (r > 0)
+ k = 1;
}
}
link_ref(link);
- return 0;
+ if (ret)
+ *ret = nr;
+
+ return k;
}
static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
case RTM_NEWROUTE:
if (!route) {
if (!manager->manage_foreign_routes)
- log_route_debug(tmp, "Ignoring received foreign", link);
+ log_route_debug(tmp, "Ignoring received foreign", link, manager);
else {
/* A route appeared that we did not request */
- log_route_debug(tmp, "Remembering foreign", link);
+ log_route_debug(tmp, "Remembering foreign", link, manager);
r = route_add_foreign(manager, link, tmp, NULL);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
}
}
} else
- log_route_debug(tmp, "Received remembered", link);
+ log_route_debug(tmp, "Received remembered", link, manager);
break;
case RTM_DELROUTE:
log_route_debug(tmp,
route ? "Forgetting" :
- manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received foreign", link);
+ manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received foreign",
+ link, manager);
route_free(route);
break;
r = route_scope_from_string(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route scope: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Unknown route scope: %s", rvalue);
return 0;
}
return 0;
}
- r = route_table_from_string(rvalue);
- if (r >= 0)
- n->table = r;
- else {
- r = safe_atou32(rvalue, &n->table);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
- return 0;
- }
+ r = manager_get_route_table_from_string(network->manager, rvalue, &n->table);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
}
n->table_set = true;
}
r = route_protocol_from_string(rvalue);
- if (r >= 0)
- n->protocol = r;
- else {
- r = safe_atou8(rvalue , &n->protocol);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
- return 0;
- }
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse route protocol \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
}
+ n->protocol = r;
+
TAKE_PTR(n);
return 0;
}
t = route_type_from_string(rvalue);
if (t < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
return 0;
}
+int config_parse_route_table_names(
+ 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) {
+
+ Manager *m = userdata;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(userdata);
+
+ if (isempty(rvalue)) {
+ m->route_table_names_by_number = hashmap_free(m->route_table_names_by_number);
+ m->route_table_numbers_by_name = hashmap_free(m->route_table_numbers_by_name);
+ return 0;
+ }
+
+ for (const char *p = rvalue;;) {
+ _cleanup_free_ char *name = NULL;
+ uint32_t table;
+ char *num;
+
+ r = extract_first_word(&p, &name, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid RouteTable=, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ num = strchr(name, ':');
+ if (!num) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid route table name and number pair, ignoring assignment: %s", name);
+ continue;
+ }
+
+ *num++ = '\0';
+
+ if (STR_IN_SET(name, "default", "main", "local")) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Route table name %s already predefined. Ignoring assignment: %s:%s", name, name, num);
+ continue;
+ }
+
+ r = safe_atou32(num, &table);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse route table number '%s', ignoring assignment: %s:%s", num, name, num);
+ continue;
+ }
+ if (table == 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid route table number, ignoring assignment: %s:%s", name, num);
+ continue;
+ }
+
+ r = hashmap_ensure_put(&m->route_table_numbers_by_name, &string_hash_ops_free, name, UINT32_TO_PTR(table));
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r == -EEXIST) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Specified route table name and number pair conflicts with others, ignoring assignment: %s:%s", name, num);
+ continue;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to store route table name and number pair, ignoring assignment: %s:%s", name, num);
+ continue;
+ }
+ if (r == 0)
+ /* The entry is duplicated. It should not be added to route_table_names_by_number hashmap. */
+ continue;
+
+ r = hashmap_ensure_put(&m->route_table_names_by_number, NULL, UINT32_TO_PTR(table), name);
+ if (r < 0) {
+ hashmap_remove(m->route_table_numbers_by_name, name);
+
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r == -EEXIST)
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Specified route table name and number pair conflicts with others, ignoring assignment: %s:%s", name, num);
+ else
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to store route table name and number pair, ignoring assignment: %s:%s", name, num);
+ continue;
+ }
+ assert(r > 0);
+
+ TAKE_PTR(name);
+ }
+}
+
static int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;
int network_add_default_route_on_device(Network *network);
void network_drop_invalid_routes(Network *network);
+int manager_get_route_table_from_string(const Manager *m, const char *table, uint32_t *ret);
+int manager_get_route_table_to_string(const Manager *m, uint32_t table, char **ret);
+
CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
CONFIG_PARSER_PROTOTYPE(config_parse_destination);
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_table_names);
#include "conf-parser.h"
#include "fileio.h"
#include "format-util.h"
+#include "hashmap.h"
#include "ip-protocol-list.h"
#include "netlink-util.h"
#include "networkd-manager.h"
static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
RoutingPolicyRule *existing;
+ bool is_new = false;
int r;
assert(m);
rule->manager = m;
existing = TAKE_PTR(rule);
+ is_new = true;
} else if (r == 0) {
/* Take over a foreign rule. */
r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, existing);
if (ret)
*ret = existing;
-
- return 0;
+ return is_new;
}
static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *rule) {
return 1;
}
-static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link) {
+static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link, const Manager *m) {
assert(rule);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(str);
+ assert(m);
/* link may be NULL. */
if (DEBUG_LOGGING) {
- _cleanup_free_ char *from = NULL, *to = NULL;
+ _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
(void) in_addr_to_string(family, &rule->from, &from);
(void) in_addr_to_string(family, &rule->to, &to);
+ (void) manager_get_route_table_to_string(m, rule->table, &table);
log_link_debug(link,
- "%s routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
+ "%s routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %s",
str, rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen,
- strna(rule->iif), strna(rule->oif), rule->table);
+ strna(rule->iif), strna(rule->oif), strna(table));
}
}
assert(manager->rtnl);
assert(IN_SET(rule->family, AF_INET, AF_INET6));
- log_routing_policy_rule_debug(rule, rule->family, "Removing", NULL);
+ log_routing_policy_rule_debug(rule, rule->family, "Removing", NULL, manager);
r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family);
if (r < 0)
assert(link->manager);
assert(link->manager->rtnl);
- log_routing_policy_rule_debug(rule, family, "Configuring", link);
+ log_routing_policy_rule_debug(rule, family, "Configuring", link, link->manager);
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
if (r < 0)
if (r < 0)
return log_link_error_errno(link, r, "Could not add rule: %m");
- return 1;
+ return r;
}
static int routing_policy_rule_configure(const RoutingPolicyRule *rule, Link *link) {
switch (type) {
case RTM_NEWRULE:
if (rule)
- log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL);
+ log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL, m);
else {
- log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL);
+ log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL, m);
r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp));
if (r < 0)
log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
break;
case RTM_DELRULE:
if (rule) {
- log_routing_policy_rule_debug(tmp, tmp->family, "Forgetting", NULL);
+ log_routing_policy_rule_debug(tmp, tmp->family, "Forgetting", NULL, m);
routing_policy_rule_free(rule);
} else
- log_routing_policy_rule_debug(tmp, tmp->family, "Kernel removed unknown", NULL);
+ log_routing_policy_rule_debug(tmp, tmp->family, "Kernel removed unknown", NULL, m);
break;
default:
if (r < 0)
return log_oom();
- r = safe_atou32(rvalue, &n->table);
+ r = manager_get_route_table_from_string(network->manager, rvalue, &n->table);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule table, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
a = routing_policy_rule_address_family_from_string(rvalue);
if (a < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, a,
"Invalid address family '%s', ignoring.", rvalue);
return 0;
}
t = fr_act_type_from_string(rvalue);
if (t < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, t,
"Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
SR_IOV_LINK_STATE_ENABLE = IFLA_VF_LINK_STATE_ENABLE,
SR_IOV_LINK_STATE_DISABLE = IFLA_VF_LINK_STATE_DISABLE,
_SR_IOV_LINK_STATE_MAX,
- _SR_IOV_LINK_STATE_INVALID = -1,
+ _SR_IOV_LINK_STATE_INVALID = -EINVAL,
} SRIOVLinkState;
typedef struct SRIOV {
IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
_IPV6_PRIVACY_EXTENSIONS_MAX,
- _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
+ _IPV6_PRIVACY_EXTENSIONS_INVALID = -EINVAL,
} IPv6PrivacyExtensions;
int link_set_sysctl(Link *link);
[ADDRESS_FAMILY_IPV6] = "ipv6",
};
+static const char* const dhcp_deprecated_address_family_table[_ADDRESS_FAMILY_MAX] = {
+ [ADDRESS_FAMILY_NO] = "none",
+ [ADDRESS_FAMILY_YES] = "both",
+ [ADDRESS_FAMILY_IPV4] = "v4",
+ [ADDRESS_FAMILY_IPV6] = "v6",
+};
+
static const char* const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
[SD_DHCP_LEASE_DNS] = "DNS servers",
[SD_DHCP_LEASE_NTP] = "NTP servers",
DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily);
DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
AddressFamily, "Failed to parse option");
+DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);
static AddressFamily address_family_compat_from_string(const char *s) {
return 0;
}
-void network_config_section_free(NetworkConfigSection *cs) {
- free(cs);
-}
-
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
NetworkConfigSection *cs;
unsigned n = 0;
ADDRESS_FAMILY_IPV6 = 1 << 1,
ADDRESS_FAMILY_YES = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
_ADDRESS_FAMILY_MAX,
- _ADDRESS_FAMILY_INVALID = -1,
+ _ADDRESS_FAMILY_INVALID = -EINVAL,
} AddressFamily;
typedef struct NetworkConfigSection {
const char *duplicate_address_detection_address_family_to_string(AddressFamily b) _const_;
AddressFamily duplicate_address_detection_address_family_from_string(const char *s) _pure_;
+AddressFamily dhcp_deprecated_address_family_from_string(const char *s) _pure_;
+
const char *dhcp_lease_server_type_to_string(sd_dhcp_lease_server_type t) _const_;
sd_dhcp_lease_server_type dhcp_lease_server_type_from_string(const char *s) _pure_;
int kernel_route_expiration_supported(void);
-int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
-void network_config_section_free(NetworkConfigSection *network);
+static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
+ return mfree(cs);
+}
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
+
+int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
extern const struct hash_ops network_config_hash_ops;
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
}
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
- static inline void free_func##_or_set_invalid(type *p) { \
+ static inline type* free_func##_or_set_invalid(type *p) { \
assert(p); \
\
if (p->section) \
p->section->invalid = true; \
else \
free_func(p); \
+ return NULL; \
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
int r;
- log_setup_service();
+ log_setup();
umask(0022);
+# This file is part of systemd.
+# See systemd-networkd.service(8) and polkit(8) for more information.
+
[Allow systemd-networkd to set timezone and transient hostname]
Identity=unix-user:systemd-network
Action=org.freedesktop.hostname1.set-hostname;org.freedesktop.hostname1.get-product-uuid;org.freedesktop.timedate1.set-timezone;
+// This file is part of systemd.
+// See systemd-networkd.service(8) and polkit(8) for more information.
+
// Allow systemd-networkd to set timezone, get product UUID,
// and transient hostname
polkit.addRule(function(action, subject) {
return 0;
}
-void qdisc_free(QDisc *qdisc) {
+QDisc* qdisc_free(QDisc *qdisc) {
if (!qdisc)
- return;
+ return NULL;
if (qdisc->network && qdisc->section)
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
network_config_section_free(qdisc->section);
free(qdisc->tca_kind);
- free(qdisc);
+ return mfree(qdisc);
}
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
QDISC_KIND_TBF,
QDISC_KIND_TEQL,
_QDISC_KIND_MAX,
- _QDISC_KIND_INVALID = -1,
+ _QDISC_KIND_INVALID = -EINVAL,
} QDiscKind;
typedef struct QDisc {
/* For casting the various qdisc kinds into a qdisc */
#define QDISC(q) (&(q)->meta)
-void qdisc_free(QDisc *qdisc);
+QDisc* qdisc_free(QDisc *qdisc);
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
int qdisc_configure(Link *link, QDisc *qdisc);
TC_KIND_TCLASS,
TC_KIND_FILTER,
_TC_KIND_MAX,
- _TC_KIND_INVALID = -1,
+ _TC_KIND_INVALID = -EINVAL,
} TrafficControlKind;
typedef struct TrafficControl {
return 0;
}
-void tclass_free(TClass *tclass) {
+TClass* tclass_free(TClass *tclass) {
if (!tclass)
- return;
+ return NULL;
if (tclass->network && tclass->section)
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
network_config_section_free(tclass->section);
- free(tclass);
+ return mfree(tclass);
}
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
TCLASS_KIND_HTB,
TCLASS_KIND_QFQ,
_TCLASS_KIND_MAX,
- _TCLASS_KIND_INVALID = -1,
+ _TCLASS_KIND_INVALID = -EINVAL,
} TClassKind;
typedef struct TClass {
/* For casting the various tclass kinds into a tclass */
#define TCLASS(t) (&(t)->meta)
-void tclass_free(TClass *tclass);
+TClass* tclass_free(TClass *tclass);
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
int tclass_configure(Link *link, TClass *tclass);
#include "network-internal.h"
#include "networkd-manager.h"
#include "string-util.h"
+#include "strv.h"
#include "tests.h"
static void test_deserialize_in_addr(void) {
}
}
+static void test_route_tables_one(Manager *manager, const char *name, uint32_t number) {
+ _cleanup_free_ char *str = NULL, *expected = NULL, *num_str = NULL;
+ uint32_t t;
+
+ if (!STR_IN_SET(name, "default", "main", "local")) {
+ assert_se(streq(hashmap_get(manager->route_table_names_by_number, UINT32_TO_PTR(number)), name));
+ assert_se(PTR_TO_UINT32(hashmap_get(manager->route_table_numbers_by_name, name)) == number);
+ }
+
+ assert_se(asprintf(&expected, "%s(%" PRIu32 ")", name, number) >= 0);
+ assert_se(manager_get_route_table_to_string(manager, number, &str) >= 0);
+ assert_se(streq(str, expected));
+
+ assert_se(manager_get_route_table_from_string(manager, name, &t) >= 0);
+ assert_se(t == number);
+
+ assert_se(asprintf(&num_str, "%" PRIu32, number) >= 0);
+ assert_se(manager_get_route_table_from_string(manager, num_str, &t) >= 0);
+ assert_se(t == number);
+}
+
+static void test_route_tables(Manager *manager) {
+ assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "hoge:123 foo:456 aaa:111", manager, manager) >= 0);
+ assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "bbb:11111 ccc:22222", manager, manager) >= 0);
+ assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "ddd:22222", manager, manager) >= 0);
+
+ test_route_tables_one(manager, "hoge", 123);
+ test_route_tables_one(manager, "foo", 456);
+ test_route_tables_one(manager, "aaa", 111);
+ test_route_tables_one(manager, "bbb", 11111);
+ test_route_tables_one(manager, "ccc", 22222);
+
+ assert_se(!hashmap_get(manager->route_table_numbers_by_name, "ddd"));
+
+ test_route_tables_one(manager, "default", 253);
+ test_route_tables_one(manager, "main", 254);
+ test_route_tables_one(manager, "local", 255);
+
+ assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "", manager, manager) >= 0);
+ assert_se(!manager->route_table_names_by_number);
+ assert_se(!manager->route_table_numbers_by_name);
+
+ test_route_tables_one(manager, "default", 253);
+ test_route_tables_one(manager, "main", 254);
+ test_route_tables_one(manager, "local", 255);
+}
+
static int test_load_config(Manager *manager) {
int r;
/* TODO: should_reload, is false if the config dirs do not exist, so
assert_se(manager_new(&manager) >= 0);
+ test_route_tables(manager);
+
r = test_load_config(manager);
if (r == -EPERM)
return log_tests_skipped("Cannot load configuration");
s = link_operstate_from_string(operstate);
if (s < 0)
- ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse operational state, ignoring: %m");
+ ret = log_link_debug_errno(l, s, "Failed to parse operational state, ignoring: %m");
else
l->operational_state = s;
}
return 0;
}
-void manager_free(Manager *m) {
+Manager* manager_free(Manager *m) {
if (!m)
- return;
+ return NULL;
hashmap_free_with_destructor(m->links, link_free);
hashmap_free(m->links_by_name);
sd_event_source_unref(m->network_monitor_event_source);
sd_network_monitor_unref(m->network_monitor);
-
sd_event_source_unref(m->rtnl_event_source);
sd_netlink_unref(m->rtnl);
-
sd_event_unref(m->event);
- free(m);
- return;
+ return mfree(m);
}
sd_event *event;
};
-void manager_free(Manager *m);
+Manager* manager_free(Manager *m);
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
LinkOperationalStateRange required_operstate,
bool any, usec_t timeout);
" Required operational state\n"
" --any Wait until at least one of the interfaces is online\n"
" --timeout=SECS Maximum time to wait for network connectivity\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
int r;
- log_setup_service();
+ log_setup();
umask(0022);
" --status=TEXT Set status text\n"
" --booted Check if the system was booted up with systemd\n"
" --no-block Do not wait until operation finished\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
CUSTOM_MOUNT_INACCESSIBLE,
CUSTOM_MOUNT_ARBITRARY,
_CUSTOM_MOUNT_TYPE_MAX,
- _CUSTOM_MOUNT_TYPE_INVALID = -1
+ _CUSTOM_MOUNT_TYPE_INVALID = -EINVAL,
} CustomMountType;
typedef struct CustomMount {
t = rlimit_from_string(z);
if (t < 0)
- return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
+ return json_log(v, flags, t,
"rlimit name unknown: %s", json_variant_string(v));
*type = t;
return 0;
}
- if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
- return log_oom();
-
- return 0;
+ return free_and_strdup_warn(s, empty_to_null(rvalue));
}
int config_parse_oom_score_adjust(
START_PID2, /* Use stub init process as PID 1, run parameters as command line as process 2 */
START_BOOT, /* Search for init system, pass arguments as parameters */
_START_MODE_MAX,
- _START_MODE_INVALID = -1
+ _START_MODE_INVALID = -EINVAL,
} StartMode;
typedef enum UserNamespaceMode {
USER_NAMESPACE_FIXED,
USER_NAMESPACE_PICK,
_USER_NAMESPACE_MODE_MAX,
- _USER_NAMESPACE_MODE_INVALID = -1,
+ _USER_NAMESPACE_MODE_INVALID = -EINVAL,
} UserNamespaceMode;
typedef enum ResolvConfMode {
RESOLV_CONF_DELETE,
RESOLV_CONF_AUTO,
_RESOLV_CONF_MODE_MAX,
- _RESOLV_CONF_MODE_INVALID = -1
+ _RESOLV_CONF_MODE_INVALID = -EINVAL,
} ResolvConfMode;
typedef enum LinkJournal {
LINK_HOST,
LINK_GUEST,
_LINK_JOURNAL_MAX,
- _LINK_JOURNAL_INVALID = -1
+ _LINK_JOURNAL_INVALID = -EINVAL,
} LinkJournal;
typedef enum TimezoneMode {
TIMEZONE_DELETE,
TIMEZONE_AUTO,
_TIMEZONE_MODE_MAX,
- _TIMEZONE_MODE_INVALID = -1
+ _TIMEZONE_MODE_INVALID = -EINVAL,
} TimezoneMode;
typedef enum ConsoleMode {
CONSOLE_PASSIVE,
CONSOLE_PIPE,
_CONSOLE_MODE_MAX,
- _CONSOLE_MODE_INVALID = -1,
+ _CONSOLE_MODE_INVALID = -EINVAL,
} ConsoleMode;
typedef enum SettingsMask {
#include "copy.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
+#include "discover-image.h"
#include "dissect-image.h"
#include "env-util.h"
#include "escape.h"
#include "log.h"
#include "loop-util.h"
#include "loopback-setup.h"
-#include "machine-image.h"
#include "macro.h"
#include "main-func.h"
#include "missing_sched.h"
#include "nulstr-util.h"
#include "os-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
" --load-credential=ID:PATH\n"
" Load credential to pass to container from file or\n"
" AF_UNIX stream socket.\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal()
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
return version();
case 'D':
- r = parse_path_argument_and_warn(optarg, false, &arg_directory);
+ r = parse_path_argument(optarg, false, &arg_directory);
if (r < 0)
return r;
break;
case ARG_TEMPLATE:
- r = parse_path_argument_and_warn(optarg, false, &arg_template);
+ r = parse_path_argument(optarg, false, &arg_template);
if (r < 0)
return r;
break;
case 'i':
- r = parse_path_argument_and_warn(optarg, false, &arg_image);
+ r = parse_path_argument(optarg, false, &arg_image);
if (r < 0)
return r;
break;
case ARG_OCI_BUNDLE:
- r = parse_path_argument_and_warn(optarg, false, &arg_oci_bundle);
+ r = parse_path_argument(optarg, false, &arg_oci_bundle);
if (r < 0)
return r;
break;
case ARG_NETWORK_NAMESPACE_PATH:
- r = parse_path_argument_and_warn(optarg, false, &arg_network_namespace_path);
+ r = parse_path_argument(optarg, false, &arg_network_namespace_path);
if (r < 0)
return r;
break;
case 'E': {
- char **n;
-
if (!env_assignment_is_valid(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Environment variable assignment '%s' is not valid.", optarg);
+ r = strv_env_replace_strdup(&arg_setenv, optarg);
+ if (r < 0)
+ return r;
- n = strv_env_set(arg_setenv, optarg);
- if (!n)
- return log_oom();
-
- strv_free_and_replace(arg_setenv, n);
arg_settings_mask |= SETTING_ENVIRONMENT;
break;
}
arg_kill_signal = signal_from_string(optarg);
if (arg_kill_signal < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Cannot parse signal: %s", optarg);
+ return log_error_errno(arg_kill_signal, "Cannot parse signal: %s", optarg);
arg_settings_mask |= SETTING_KILL_SIGNAL;
break;
}
case ARG_VERITY_DATA:
- r = parse_path_argument_and_warn(optarg, false, &arg_verity_settings.data_path);
+ r = parse_path_argument(optarg, false, &arg_verity_settings.data_path);
if (r < 0)
return r;
break;
rl = rlimit_from_string_harder(name);
if (rl < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown resource limit: %s", name);
+ return log_error_errno(rl, "Unknown resource limit: %s", name);
if (!arg_rlimit[rl]) {
arg_rlimit[rl] = new0(struct rlimit, 1);
arg_resolv_conf = resolv_conf_mode_from_string(optarg);
if (arg_resolv_conf < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ return log_error_errno(arg_resolv_conf,
"Failed to parse /etc/resolv.conf mode: %s", optarg);
arg_settings_mask |= SETTING_RESOLV_CONF;
arg_timezone = timezone_mode_from_string(optarg);
if (arg_timezone < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ return log_error_errno(arg_timezone,
"Failed to parse /etc/localtime mode: %s", optarg);
arg_settings_mask |= SETTING_TIMEZONE;
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (IN_SET(n, -EAGAIN, -EINTR))
return 0;
+ if (n == -EXFULL) {
+ log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
+ return 0;
+ }
if (n < 0)
return log_warning_errno(n, "Couldn't read notification socket: %m");
#include <sys/types.h>
#include <unistd.h>
+#include "env-util.h"
#include "errno-util.h"
#include "in-addr-util.h"
#include "macro.h"
static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) {
struct in6_addr in6;
- if (family != AF_INET6)
+ if (family != AF_INET6 || ifindex == 0)
return 0;
/* Some apps can't deal with the scope ID attached to non-link-local addresses. Hence, let's suppress that. */
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
t = json_variant_integer(variant);
- if (t <= 0 || t > INT_MAX)
+ if (t > INT_MAX)
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is out of bounds for an interface index.", strna(name));
*ifi = (int) t;
{}
};
+static uint64_t query_flags(void) {
+ uint64_t f = 0;
+ int r;
+
+ /* Allow callers to turn off validation, when we resolve via nss-resolve */
+
+ r = getenv_bool_secure("SYSTEMD_NSS_RESOLVE_VALIDATE");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_NSS_RESOLVE_VALIDATE value, ignoring.");
+ else if (r == 0)
+ f |= SD_RESOLVED_NO_VALIDATE;
+
+ return f;
+}
+
enum nss_status _nss_resolve_gethostbyname4_r(
const char *name,
struct gaih_addrtuple **pat,
goto fail;
r = json_build(&cparams, JSON_BUILD_OBJECT(
- JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name))));
+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)),
+ JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
if (r < 0)
goto fail;
goto fail;
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)),
- JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af))));
+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)),
+ JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
if (r < 0)
goto fail;
goto fail;
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(addr, len)),
- JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af))));
+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)),
+ JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
if (r < 0)
goto fail;
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
- "\nSee the %6$s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , ansi_underline(), ansi_normal()
- , link
- );
+ "\nSee the %6$s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
+ ansi_normal(),
+ link);
return 0;
}
#include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "memory-util.h"
#include "oomd-manager-bus.h"
#include "oomd-manager.h"
#include "path-util.h"
m = managed_oom_mode_from_string(s);
if (m < 0)
- return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), "%s is not a valid ManagedOOMMode", s);
+ return json_log(v, flags, m, "%s is not a valid ManagedOOMMode", s);
*mode = m;
return 0;
m->monitored_swap_cgroup_contexts : m->monitored_mem_pressure_cgroup_contexts;
if (reply.mode == MANAGED_OOM_AUTO) {
- (void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, reply.path));
+ (void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, empty_to_root(reply.path)));
continue;
}
limit = m->default_mem_pressure_limit;
if (streq(reply.property, "ManagedOOMMemoryPressure")) {
- if (reply.limit > 100)
+ if (reply.limit > 10000)
continue;
else if (reply.limit != 0) {
- ret = store_loadavg_fixed_point((unsigned long) reply.limit, 0, &limit);
+ ret = store_loadavg_fixed_point((unsigned long) reply.limit / 100, (unsigned long) reply.limit % 100, &limit);
if (ret < 0)
continue;
}
}
- ret = oomd_insert_cgroup_context(NULL, monitor_hm, reply.path);
+ ret = oomd_insert_cgroup_context(NULL, monitor_hm, empty_to_root(reply.path));
if (ret == -ENOMEM) {
r = ret;
goto finish;
/* Always update the limit in case it was changed. For non-memory pressure detection the value is
* ignored so always updating it here is not a problem. */
- ctx = hashmap_get(monitor_hm, reply.path);
+ ctx = hashmap_get(monitor_hm, empty_to_root(reply.path));
if (ctx)
ctx->mem_pressure_limit = limit;
}
return log_error_errno(r, "Failed to update monitored memory pressure cgroup contexts");
r = oomd_system_context_acquire("/proc/swaps", &m->system_context);
- /* If there aren't units depending on swap actions, the only error we exit on is ENOMEM */
- if (r == -ENOMEM || (r < 0 && !hashmap_isempty(m->monitored_swap_cgroup_contexts)))
+ /* If there aren't units depending on swap actions, the only error we exit on is ENOMEM.
+ * Allow ENOENT in the event that swap is disabled on the system. */
+ if (r == -ENOMEM || (r < 0 && r != -ENOENT && !hashmap_isempty(m->monitored_swap_cgroup_contexts)))
return log_error_errno(r, "Failed to acquire system context");
+ else if (r == -ENOENT)
+ zero(m->system_context);
+
+ if (oomd_memory_reclaim(m->monitored_mem_pressure_cgroup_contexts))
+ m->last_reclaim_at = usec_now;
/* If we're still recovering from a kill, don't try to kill again yet */
if (m->post_action_delay_start > 0) {
m->post_action_delay_start = 0;
}
- r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, PRESSURE_DURATION_USEC, &targets);
+ r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, m->default_mem_pressure_duration_usec, &targets);
if (r == -ENOMEM)
return log_error_errno(r, "Failed to check if memory pressure exceeded limits");
else if (r == 1) {
- /* Check if there was reclaim activity in the last interval. The concern is the following case:
+ /* Check if there was reclaim activity in the given interval. The concern is the following case:
* Pressure climbed, a lot of high-frequency pages were reclaimed, and we killed the offending
* cgroup. Even after this, well-behaved processes will fault in recently resident pages and
* this will cause pressure to remain high. Thus if there isn't any reclaim pressure, no need
* to kill something (it won't help anyways). */
- if (oomd_memory_reclaim(m->monitored_mem_pressure_cgroup_contexts)) {
+ if ((usec_now - m->last_reclaim_at) <= RECLAIM_DURATION_USEC) {
_cleanup_hashmap_free_ Hashmap *candidates = NULL;
OomdCGroupContext *t;
SET_FOREACH(t, targets) {
log_notice("Memory pressure for %s is greater than %lu for more than %"PRIu64" seconds and there was reclaim activity",
- t->path, LOAD_INT(t->mem_pressure_limit), PRESSURE_DURATION_USEC / USEC_PER_SEC);
+ t->path, LOAD_INT(t->mem_pressure_limit), m->default_mem_pressure_duration_usec / USEC_PER_SEC);
r = oomd_kill_by_pgscan(candidates, t->path, m->dry_run);
if (r == -ENOMEM)
return 0;
}
-void manager_free(Manager *m) {
+Manager* manager_free(Manager *m) {
assert(m);
varlink_close_unref(m->varlink);
hashmap_free(m->monitored_swap_cgroup_contexts);
hashmap_free(m->monitored_mem_pressure_cgroup_contexts);
- free(m);
+ return mfree(m);
}
int manager_new(Manager **ret) {
return 0;
}
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit) {
- unsigned long l;
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec) {
+ unsigned long l, f;
int r;
assert(m);
m->swap_used_limit = swap_used_limit != -1 ? swap_used_limit : DEFAULT_SWAP_USED_LIMIT;
assert(m->swap_used_limit <= 100);
- l = mem_pressure_limit != -1 ? mem_pressure_limit : DEFAULT_MEM_PRESSURE_LIMIT;
- r = store_loadavg_fixed_point(l, 0, &m->default_mem_pressure_limit);
+ if (mem_pressure_limit_permyriad != -1) {
+ assert(mem_pressure_limit_permyriad <= 10000);
+
+ l = mem_pressure_limit_permyriad / 100;
+ f = mem_pressure_limit_permyriad % 100;
+ } else {
+ l = DEFAULT_MEM_PRESSURE_LIMIT_PERCENT;
+ f = 0;
+ }
+ r = store_loadavg_fixed_point(l, f, &m->default_mem_pressure_limit);
if (r < 0)
return r;
+ m->default_mem_pressure_duration_usec = mem_pressure_usec ?: DEFAULT_MEM_PRESSURE_DURATION_USEC;
+
r = manager_connect_bus(m);
if (r < 0)
return r;
int manager_get_dump_string(Manager *m, char **ret) {
_cleanup_free_ char *dump = NULL;
_cleanup_fclose_ FILE *f = NULL;
+ char buf[FORMAT_TIMESPAN_MAX];
OomdCGroupContext *c;
size_t size;
char *key;
fprintf(f,
"Dry Run: %s\n"
"Swap Used Limit: %u%%\n"
- "Default Memory Pressure Limit: %lu%%\n"
+ "Default Memory Pressure Limit: %lu.%02lu%%\n"
+ "Default Memory Pressure Duration: %s\n"
"System Context:\n",
yes_no(m->dry_run),
m->swap_used_limit,
- LOAD_INT(m->default_mem_pressure_limit));
+ LOAD_INT(m->default_mem_pressure_limit), LOAD_FRAC(m->default_mem_pressure_limit),
+ format_timespan(buf, sizeof(buf), m->default_mem_pressure_duration_usec, USEC_PER_SEC));
oomd_dump_system_context(&m->system_context, f, "\t");
fprintf(f, "Swap Monitored CGroups:\n");
* percentage of time all tasks were delayed (i.e. unproductive).
* Generally 60 or higher might be acceptable for something like system.slice with no memory.high set; processes in
* system.slice are assumed to be less latency sensitive. */
-#define PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
-#define DEFAULT_MEM_PRESSURE_LIMIT 60
+#define DEFAULT_MEM_PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
+#define DEFAULT_MEM_PRESSURE_LIMIT_PERCENT 60
#define DEFAULT_SWAP_USED_LIMIT 90
+#define RECLAIM_DURATION_USEC (30 * USEC_PER_SEC)
#define POST_ACTION_DELAY_USEC (15 * USEC_PER_SEC)
typedef struct Manager Manager;
bool dry_run;
unsigned swap_used_limit;
loadavg_t default_mem_pressure_limit;
+ usec_t default_mem_pressure_duration_usec;
/* k: cgroup paths -> v: OomdCGroupContext
* Used to detect when to take action. */
OomdSystemContext system_context;
+ usec_t last_reclaim_at;
usec_t post_action_delay_start;
sd_event_source *cgroup_context_event_source;
Varlink *varlink;
};
-void manager_free(Manager *m);
+Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int manager_new(Manager **ret);
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit);
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec);
int manager_get_dump_string(Manager *m, char **ret);
#include <sys/xattr.h>
#include <unistd.h>
-#include "cgroup-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "oomd-util.h"
return -ENOMEM;
HASHMAP_FOREACH(item, h) {
- if (item->path && prefix && !path_startswith(item->path, prefix))
+ /* Skip over cgroups that are not valid candidates or are explicitly marked for omission */
+ if ((item->path && prefix && !path_startswith(item->path, prefix)) || item->preference == MANAGED_OOM_PREFERENCE_OMIT)
continue;
sorted[k++] = item;
if (r < 0)
return r;
- r = increment_oomd_xattr(path, "user.systemd_oomd_kill", set_size(pids_killed));
+ r = increment_oomd_xattr(path, "user.oomd_kill", set_size(pids_killed));
if (r < 0)
- log_debug_errno(r, "Failed to set user.systemd_oomd_kill on kill: %m");
+ log_debug_errno(r, "Failed to set user.oomd_kill on kill: %m");
return set_size(pids_killed) != 0;
}
assert(h);
- r = oomd_sort_cgroup_contexts(h, compare_pgscan, prefix, &sorted);
+ r = oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, prefix, &sorted);
if (r < 0)
return r;
for (int i = 0; i < r; i++) {
- if (sorted[i]->pgscan == 0)
- break;
+ /* Skip cgroups with no reclaim and memory usage; it won't alleviate pressure. */
+ /* Don't break since there might be "avoid" cgroups at the end. */
+ if (sorted[i]->pgscan == 0 && sorted[i]->current_memory_usage == 0)
+ continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r > 0 || r == -ENOMEM)
/* Try to kill cgroups with non-zero swap usage until we either succeed in
* killing or we get to a cgroup with no swap usage. */
for (int i = 0; i < r; i++) {
+ /* Skip over cgroups with no resource usage. Don't break since there might be "avoid"
+ * cgroups at the end. */
if (sorted[i]->swap_usage == 0)
- break;
+ continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r > 0 || r == -ENOMEM)
_cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
_cleanup_free_ char *p = NULL, *val = NULL;
bool is_root;
+ uid_t uid;
int r;
assert(path);
return -ENOMEM;
is_root = empty_or_root(path);
+ ctx->preference = MANAGED_OOM_PREFERENCE_NONE;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "memory.pressure", &p);
if (r < 0)
if (r < 0)
return log_debug_errno(r, "Error parsing memory pressure from %s: %m", p);
+ r = cg_get_owner(SYSTEMD_CGROUP_CONTROLLER, path, &uid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to get owner/group from %s: %m", path);
+ else if (uid == 0) {
+ /* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
+ * as an optional feature of systemd-oomd (and the system might not even support them). */
+ r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_avoid");
+ if (r == -ENOMEM)
+ return r;
+ ctx->preference = r == 1 ? MANAGED_OOM_PREFERENCE_AVOID : ctx->preference;
+
+ r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_omit");
+ if (r == -ENOMEM)
+ return r;
+ ctx->preference = r == 1 ? MANAGED_OOM_PREFERENCE_OMIT : ctx->preference;
+ }
+
if (is_root) {
r = procfs_memory_get_used(&ctx->current_memory_usage);
if (r < 0)
fprintf(f,
"%sPath: %s\n"
- "%s\tMemory Pressure Limit: %lu%%\n"
+ "%s\tMemory Pressure Limit: %lu.%02lu%%\n"
"%s\tPressure: Avg10: %lu.%02lu Avg60: %lu.%02lu Avg300: %lu.%02lu Total: %s\n"
"%s\tCurrent Memory Usage: %s\n",
strempty(prefix), ctx->path,
- strempty(prefix), LOAD_INT(ctx->mem_pressure_limit),
+ strempty(prefix), LOAD_INT(ctx->mem_pressure_limit), LOAD_FRAC(ctx->mem_pressure_limit),
strempty(prefix),
LOAD_INT(ctx->memory_pressure.avg10), LOAD_FRAC(ctx->memory_pressure.avg10),
LOAD_INT(ctx->memory_pressure.avg60), LOAD_FRAC(ctx->memory_pressure.avg60),
#include <stdbool.h>
+#include "cgroup-util.h"
#include "hashmap.h"
#include "psi-util.h"
uint64_t last_pgscan;
uint64_t pgscan;
+ ManagedOOMPreference preference;
+
/* These are only used by oomd_pressure_above for acting on high memory pressure. */
loadavg_t mem_pressure_limit;
+ usec_t mem_pressure_duration_usec;
usec_t last_hit_mem_pressure_limit;
};
/* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */
bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent);
-static inline int compare_pgscan(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
+/* The compare functions will sort from largest to smallest, putting all the contexts with "avoid" at the end
+ * (after the smallest values). */
+static inline int compare_pgscan_and_memory_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
+ int r;
+
assert(c1);
assert(c2);
- return CMP((*c2)->pgscan, (*c1)->pgscan);
+ r = CMP((*c1)->preference, (*c2)->preference);
+ if (r != 0)
+ return r;
+
+ r = CMP((*c2)->pgscan, (*c1)->pgscan);
+ if (r != 0)
+ return r;
+
+ return CMP((*c2)->current_memory_usage, (*c1)->current_memory_usage);
}
static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
+ int r;
+
assert(c1);
assert(c2);
+ r = CMP((*c1)->preference, (*c2)->preference);
+ if (r != 0)
+ return r;
+
return CMP((*c2)->swap_usage, (*c1)->swap_usage);
}
static bool arg_dry_run = false;
static int arg_swap_used_limit = -1;
-static int arg_mem_pressure_limit = -1;
+static int arg_mem_pressure_limit_permyriad = -1;
+static usec_t arg_mem_pressure_usec = 0;
static int parse_config(void) {
static const ConfigTableItem items[] = {
- { "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit },
- { "OOM", "DefaultMemoryPressureLimitPercent", config_parse_percent, 0, &arg_mem_pressure_limit },
+ { "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit },
+ { "OOM", "DefaultMemoryPressureLimit", config_parse_permyriad, 0, &arg_mem_pressure_limit_permyriad },
+ { "OOM", "DefaultMemoryPressureDurationSec", config_parse_sec, 0, &arg_mem_pressure_usec },
{}
};
" --version Show package version\n"
" --dry-run Only print destructive actions instead of doing them\n"
" --bus-introspect=PATH Write D-Bus XML introspection data\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
unsigned long long s = 0;
int r;
- log_setup_service();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
return log_error_errno(r, "Failed to get SwapTotal from /proc/meminfo: %m");
r = safe_atollu(swap, &s);
- if (r < 0)
- return log_error_errno(r, "Failed to parse SwapTotal from /proc/meminfo: %s: %m", swap);
- if (s == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Requires swap to operate");
+ if (r < 0 || s == 0)
+ log_warning("Swap is currently not detected; memory pressure usage will be degraded");
if (!is_pressure_supported())
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Pressure Stall Information (PSI) is not supported");
if (r < 0)
return log_error_errno(r, "Failed to create manager: %m");
- r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit);
+ r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit_permyriad, arg_mem_pressure_usec);
if (r < 0)
return log_error_errno(r, "Failed to start up daemon: %m");
[OOM]
#SwapUsedLimitPercent=90%
-#DefaultMemoryPressureLimitPercent=60%
+#DefaultMemoryPressureLimit=60%
+#DefaultMemoryPressureDurationSec=30s
sleep(2);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, cgroup) == true);
- assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.systemd_oomd_kill", &v) >= 0);
+ assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_kill", &v) >= 0);
assert_se(memcmp(v, i == 0 ? "2" : "4", 2) == 0);
}
}
_cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
_cleanup_free_ char *cgroup = NULL;
OomdCGroupContext *c1, *c2;
+ bool test_xattrs;
+ int r;
if (geteuid() != 0)
return (void) log_tests_skipped("not root");
assert_se(cg_pid_get_path(NULL, 0, &cgroup) >= 0);
+ /* If we don't have permissions to set xattrs we're likely in a userns or missing capabilities
+ * so skip the xattr portions of the test. */
+ r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_test", "1", 1, 0);
+ test_xattrs = !ERRNO_IS_PRIVILEGE(r) && !ERRNO_IS_NOT_SUPPORTED(r);
+
+ if (test_xattrs) {
+ assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_omit", "1", 1, 0) >= 0);
+ assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_avoid", "1", 1, 0) >= 0);
+ }
+
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
assert_se(streq(ctx->path, cgroup));
assert_se(ctx->swap_usage == 0);
assert_se(ctx->last_pgscan == 0);
assert_se(ctx->pgscan == 0);
+ /* omit takes precedence over avoid when both are set to true */
+ if (test_xattrs)
+ assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_OMIT);
+ else
+ assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
+ ctx = oomd_cgroup_context_free(ctx);
+
+ /* also check when only avoid is set to true */
+ if (test_xattrs) {
+ assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_omit", "0", 1, 0) >= 0);
+ assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_avoid", "1", 1, 0) >= 0);
+ }
+ assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
+ if (test_xattrs)
+ assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_AVOID);
ctx = oomd_cgroup_context_free(ctx);
/* Test the root cgroup */
assert_se(oomd_cgroup_context_acquire("", &ctx) == 0);
assert_se(streq(ctx->path, "/"));
assert_se(ctx->current_memory_usage > 0);
+ assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
/* Test hashmap inserts */
assert_se(h1 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
assert_se(c2->last_pgscan == 5555);
assert_se(c2->mem_pressure_limit == 6789);
assert_se(c2->last_hit_mem_pressure_limit == 42);
+
+ /* Assert that avoid/omit are not set if the cgroup is not owned by root */
+ if (test_xattrs) {
+ ctx = oomd_cgroup_context_free(ctx);
+ assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 0) >= 0);
+ assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
+ assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
+ }
}
static void test_oomd_system_context_acquire(void) {
assert_se(ctx.swap_total == 0);
assert_se(ctx.swap_used == 0);
+ assert_se(write_string_file(path, "Filename Type Size Used Priority", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(oomd_system_context_acquire(path, &ctx) == 0);
+ assert_se(ctx.swap_total == 0);
+ assert_se(ctx.swap_used == 0);
+
assert_se(write_string_file(path, "Filename Type Size Used Priority\n"
"/swapvol/swapfile file 18971644 0 -3\n"
"/dev/vda2 partition 1999868 993780 -2", WRITE_STRING_FILE_CREATE) == 0);
.swap_used = 3310136 * 1024U,
};
assert_se(oomd_swap_free_below(&ctx, 20) == false);
+
+ ctx = (OomdSystemContext) {
+ .swap_total = 0,
+ .swap_used = 0,
+ };
+ assert_se(oomd_swap_free_below(&ctx, 20) == false);
}
static void test_oomd_sort_cgroups(void) {
char **paths = STRV_MAKE("/herp.slice",
"/herp.slice/derp.scope",
"/herp.slice/derp.scope/sheep.service",
- "/zupa.slice");
+ "/zupa.slice",
+ "/omitted.slice",
+ "/avoid.slice");
- OomdCGroupContext ctx[4] = {
+ OomdCGroupContext ctx[6] = {
{ .path = paths[0],
.swap_usage = 20,
- .pgscan = 60 },
+ .pgscan = 60,
+ .current_memory_usage = 10 },
{ .path = paths[1],
.swap_usage = 60,
- .pgscan = 40 },
+ .pgscan = 40,
+ .current_memory_usage = 20 },
{ .path = paths[2],
.swap_usage = 40,
- .pgscan = 20 },
+ .pgscan = 40,
+ .current_memory_usage = 40 },
{ .path = paths[3],
.swap_usage = 10,
- .pgscan = 80 },
+ .pgscan = 80,
+ .current_memory_usage = 10 },
+ { .path = paths[4],
+ .swap_usage = 90,
+ .pgscan = 100,
+ .preference = MANAGED_OOM_PREFERENCE_OMIT },
+ { .path = paths[5],
+ .swap_usage = 99,
+ .pgscan = 200,
+ .preference = MANAGED_OOM_PREFERENCE_AVOID },
};
assert_se(h = hashmap_new(&string_hash_ops));
assert_se(hashmap_put(h, "/herp.slice/derp.scope", &ctx[1]) >= 0);
assert_se(hashmap_put(h, "/herp.slice/derp.scope/sheep.service", &ctx[2]) >= 0);
assert_se(hashmap_put(h, "/zupa.slice", &ctx[3]) >= 0);
+ assert_se(hashmap_put(h, "/omitted.slice", &ctx[4]) >= 0);
+ assert_se(hashmap_put(h, "/avoid.slice", &ctx[5]) >= 0);
- assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 4);
+ assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 5);
assert_se(sorted_cgroups[0] == &ctx[1]);
assert_se(sorted_cgroups[1] == &ctx[2]);
assert_se(sorted_cgroups[2] == &ctx[0]);
assert_se(sorted_cgroups[3] == &ctx[3]);
+ assert_se(sorted_cgroups[4] == &ctx[5]);
sorted_cgroups = mfree(sorted_cgroups);
- assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, NULL, &sorted_cgroups) == 4);
+ assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, NULL, &sorted_cgroups) == 5);
assert_se(sorted_cgroups[0] == &ctx[3]);
assert_se(sorted_cgroups[1] == &ctx[0]);
- assert_se(sorted_cgroups[2] == &ctx[1]);
- assert_se(sorted_cgroups[3] == &ctx[2]);
+ assert_se(sorted_cgroups[2] == &ctx[2]);
+ assert_se(sorted_cgroups[3] == &ctx[1]);
+ assert_se(sorted_cgroups[4] == &ctx[5]);
sorted_cgroups = mfree(sorted_cgroups);
- assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
- assert_se(sorted_cgroups[0] == &ctx[1]);
- assert_se(sorted_cgroups[1] == &ctx[2]);
+ assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
+ assert_se(sorted_cgroups[0] == &ctx[2]);
+ assert_se(sorted_cgroups[1] == &ctx[1]);
assert_se(sorted_cgroups[2] == 0);
assert_se(sorted_cgroups[3] == 0);
+ assert_se(sorted_cgroups[4] == 0);
+ assert_se(sorted_cgroups[5] == 0);
sorted_cgroups = mfree(sorted_cgroups);
}
" -h --help Show this help and exit\n"
" --version Print version string and exit\n"
" -n --dry-run Just print what would be done\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
dev_t devno;
int r;
- log_setup_service();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
struct stat st;
int r;
- log_setup_service();
+ log_setup();
if (argc != 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
#include "mkfs-util.h"
#include "mount-util.h"
#include "parse-util.h"
+#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
static uint64_t arg_size = UINT64_MAX;
static bool arg_size_auto = false;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
+static PagerFlags arg_pager_flags = 0;
+static bool arg_legend = true;
static void *arg_key = NULL;
static size_t arg_key_size = 0;
static char *arg_tpm2_device = NULL;
ENCRYPT_TPM2,
ENCRYPT_KEY_FILE_TPM2,
_ENCRYPT_MODE_MAX,
- _ENCRYPT_MODE_INVALID = -1,
+ _ENCRYPT_MODE_INVALID = -EINVAL,
} EncryptMode;
struct Partition {
return 0;
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
static int determine_current_padding(
struct fdisk_context *c,
return table_log_add_error(r);
}
- r = table_print_json(t, stdout, arg_json_format_flags);
- if (r < 0)
- return table_log_print_error(r);
-
- return 0;
+ return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
}
static void context_bar_char_process_partition(
"\n%sGrow and add partitions to partition table.%s\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not show the headers and footers\n"
" --dry-run=BOOL Whether to run dry-run operation\n"
" --empty=MODE One of refuse, allow, require, force, create; controls\n"
" how to handle empty disks lacking partition tables\n"
" them\n"
" --can-factory-reset Test whether factory reset is defined\n"
" --root=PATH Operate relative to root path\n"
- " --definitions=DIR Find partitions in specified directory\n"
+ " --definitions=DIR Find partition definitions in specified directory\n"
" --key-file=PATH Key to use when encrypting partitions\n"
" --tpm2-device=PATH Path to TPM2 device node to use\n"
" --tpm2-pcrs=PCR1,PCR2,…\n"
" --size=BYTES Grow loopback file to specified size\n"
" --json=pretty|short|off\n"
" Generate JSON output\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
enum {
ARG_VERSION = 0x100,
+ ARG_NO_PAGER,
+ ARG_NO_LEGEND,
ARG_DRY_RUN,
ARG_EMPTY,
ARG_DISCARD,
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "dry-run", required_argument, NULL, ARG_DRY_RUN },
{ "empty", required_argument, NULL, ARG_EMPTY },
{ "discard", required_argument, NULL, ARG_DISCARD },
case ARG_VERSION:
return version();
+ case ARG_NO_PAGER:
+ arg_pager_flags |= PAGER_DISABLE;
+ break;
+
+ case ARG_NO_LEGEND:
+ arg_legend = false;
+ break;
+
case ARG_DRY_RUN:
r = parse_boolean(optarg);
if (r < 0)
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, false, &arg_root);
+ r = parse_path_argument(optarg, false, &arg_root);
if (r < 0)
return r;
break;
break;
case ARG_DEFINITIONS:
- r = parse_path_argument_and_warn(optarg, false, &arg_definitions);
+ r = parse_path_argument(optarg, false, &arg_definitions);
if (r < 0)
return r;
break;
}
case ARG_JSON:
- r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags);
+ r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
[[ -f /dev/loop-control ]] || exit 77
" -h --help Show this help\n"
" --version Show package version\n"
" --suffix=SUFFIX Suffix to append to paths\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
send_interface="org.freedesktop.portable1.Manager"
send_member="DetachImage"/>
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="ReattachImage"/>
+
<allow send_destination="org.freedesktop.portable1"
send_interface="org.freedesktop.portable1.Manager"
send_member="RemoveImage"/>
send_interface="org.freedesktop.portable1.Image"
send_member="Detach"/>
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="Reattach"/>
+
<allow send_destination="org.freedesktop.portable1"
send_interface="org.freedesktop.portable1.Image"
send_member="Remove"/>
#include "copy.h"
#include "def.h"
#include "dirent-util.h"
+#include "discover-image.h"
#include "dissect-image.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
#include "locale-util.h"
#include "loop-util.h"
-#include "machine-image.h"
#include "mkdir.h"
#include "nulstr-util.h"
#include "os-util.h"
r = unit_file_exists(UNIT_FILE_SYSTEM, &paths, item->name);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
- if (r > 0)
+ if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' exists on the host already, refusing.", item->name);
r = unit_file_is_active(bus, item->name, error);
if (r < 0)
return r;
- if (r > 0)
+ if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name);
}
a = last_path_component(marker);
if (image_name_is_valid(name_or_path)) {
- const char *e;
+ const char *e, *underscore;
/* We shall match against an image name. In that case let's compare the last component, and optionally
- * allow either a suffix of ".raw" or a series of "/". */
+ * allow either a suffix of ".raw" or a series of "/".
+ * But allow matching on a different version of the same image, when a "_" is used as a separator. */
+ underscore = strchr(name_or_path, '_');
+ if (underscore)
+ return strneq(a, name_or_path, underscore - name_or_path);
e = startswith(a, name_or_path);
if (!e)
e[strspn(e, "/")] == 0 ||
streq(e, ".raw");
} else {
- const char *b;
+ const char *b, *underscore;
size_t l;
/* We shall match against a path. Let's ignore any prefix here though, as often there are many ways to
if (strcspn(b, "/") != l)
return false;
- return memcmp(a, b, l) == 0;
+ underscore = strchr(b, '_');
+ if (underscore)
+ l = underscore - b;
+
+ return strneq(a, b, l);
}
}
r = unit_file_is_active(bus, de->d_name, error);
if (r < 0)
return r;
- if (r > 0)
+ if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", de->d_name);
r = set_put_strdup(&unit_files, de->d_name);
PORTABLE_PREFER_COPY = 1 << 0,
PORTABLE_PREFER_SYMLINK = 1 << 1,
PORTABLE_RUNTIME = 1 << 2,
+ PORTABLE_REATTACH = 1 << 3,
} PortableFlags;
typedef enum PortableChangeType {
PORTABLE_RUNNING,
PORTABLE_RUNNING_RUNTIME,
_PORTABLE_STATE_MAX,
- _PORTABLE_STATE_INVALID = -1
+ _PORTABLE_STATE_INVALID = -EINVAL,
} PortableState;
typedef struct PortableChange {
#include "bus-wait-for-jobs.h"
#include "def.h"
#include "dirent-util.h"
+#include "discover-image.h"
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-table.h"
#include "fs-util.h"
#include "locale-util.h"
-#include "machine-image.h"
#include "main-func.h"
#include "pager.h"
#include "parse-util.h"
static bool arg_now = false;
static bool arg_no_block = false;
+static bool is_portable_managed(const char *unit) {
+ return ENDSWITH_SET(unit, ".service", ".target", ".socket", ".path", ".timer");
+}
+
static int determine_image(const char *image, bool permit_non_existing, char **ret) {
int r;
return 0;
}
-static int maybe_start_stop(sd_bus *bus, const char *path, bool start, BusWaitForJobs *wait) {
+static int maybe_start_stop_restart(sd_bus *bus, const char *path, const char *method, BusWaitForJobs *wait) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *name = (char *)basename(path), *job = NULL;
int r;
+ assert(STR_IN_SET(method, "StartUnit", "StopUnit", "RestartUnit"));
+
if (!arg_now)
return 0;
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- start ? "StartUnit" : "StopUnit",
+ method,
&error,
&reply,
"ss", name, "replace");
if (r < 0)
- return log_error_errno(r, "Failed to %s the portable service %s: %s",
- start ? "start" : "stop",
+ return log_error_errno(r, "Failed to call %s on the portable service %s: %s",
+ method,
path,
bus_error_message(&error, r));
return bus_log_parse_error(r);
if (!arg_quiet)
- log_info("Queued %s to %s portable service %s.", job, start ? "start" : "stop", name);
+ log_info("Queued %s to call %s on portable service %s.", job, method, name);
if (wait) {
r = bus_wait_for_jobs_add(wait, job);
if (r < 0)
- return log_error_errno(r, "Failed to watch %s job for %s %s: %m",
- job, start ? "starting" : "stopping", name);
+ return log_error_errno(r, "Failed to watch %s job to call %s on %s: %m",
+ job, method, name);
}
return 0;
if (r == 0)
break;
- if (STR_IN_SET(type, "symlink", "copy") && ENDSWITH_SET(path, ".service", ".target", ".socket")) {
+ if (STR_IN_SET(type, "symlink", "copy") && is_portable_managed(path)) {
+ (void) maybe_enable_disable(bus, path, true);
+ (void) maybe_start_stop_restart(bus, path, "StartUnit", wait);
+ }
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_block) {
+ r = bus_wait_for_jobs(wait, arg_quiet, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
+ _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL;
+ int r;
+
+ if (!arg_enable && !arg_now)
+ return 0;
+
+ if (!arg_no_block) {
+ r = bus_wait_for_jobs_new(bus, &wait);
+ if (r < 0)
+ return log_error_errno(r, "Could not watch jobs: %m");
+ }
+
+ r = sd_bus_message_rewind(reply, true);
+ if (r < 0)
+ return r;
+
+ /* First we get a list of units that were definitely removed, not just re-attached,
+ * so we can also stop them if the user asked us to. */
+ r = sd_bus_message_enter_container(reply, 'a', "(sss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ char *type, *path, *source;
+
+ r = sd_bus_message_read(reply, "(sss)", &type, &path, &source);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ if (streq(type, "unlink") && is_portable_managed(path))
+ (void) maybe_start_stop_restart(bus, path, "StopUnit", wait);
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return r;
+
+ /* Then we get a list of units that were either added or changed, so that we can
+ * enable them and/or restart them if the user asked us to. */
+ r = sd_bus_message_enter_container(reply, 'a', "(sss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ char *type, *path, *source;
+
+ r = sd_bus_message_read(reply, "(sss)", &type, &path, &source);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ if (STR_IN_SET(type, "symlink", "copy") && is_portable_managed(path)) {
(void) maybe_enable_disable(bus, path, true);
- (void) maybe_start_stop(bus, path, true, wait);
+ (void) maybe_start_stop_restart(bus, path, "RestartUnit", wait);
}
}
if (r < 0)
return bus_log_parse_error(r);
- (void) maybe_start_stop(bus, name, false, wait);
+ (void) maybe_start_stop_restart(bus, name, "StopUnit", wait);
(void) maybe_enable_disable(bus, name, false);
}
return 0;
}
-static int attach_image(int argc, char *argv[], void *userdata) {
+static int attach_reattach_image(int argc, char *argv[], const char *method) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *image = NULL;
int r;
+ assert(method);
+ assert(STR_IN_SET(method, "AttachImage", "ReattachImage"));
+
r = determine_image(argv[1], false, &image);
if (r < 0)
return r;
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- r = bus_message_new_method_call(bus, &m, bus_portable_mgr, "AttachImage");
+ r = bus_message_new_method_call(bus, &m, bus_portable_mgr, method);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0)
- return log_error_errno(r, "Failed to attach image: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "%s failed: %s", method, bus_error_message(&error, r));
(void) maybe_reload(&bus);
print_changes(reply);
- (void) maybe_enable_start(bus, reply);
+ if (streq(method, "AttachImage"))
+ (void) maybe_enable_start(bus, reply);
+ else {
+ /* ReattachImage returns 2 lists - removed units first, and changed/added second */
+ print_changes(reply);
+ (void) maybe_stop_enable_restart(bus, reply);
+ }
return 0;
}
+static int attach_image(int argc, char *argv[], void *userdata) {
+ return attach_reattach_image(argc, argv, "AttachImage");
+}
+
+static int reattach_image(int argc, char *argv[], void *userdata) {
+ return attach_reattach_image(argc, argv, "ReattachImage");
+}
+
static int detach_image(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
" Attach the specified portable service image\n"
" detach NAME|PATH [PREFIX...]\n"
" Detach the specified portable service image\n"
+ " reattach NAME|PATH [PREFIX...]\n"
+ " Reattach the specified portable service image\n"
" inspect NAME|PATH [PREFIX...]\n"
" Show details of specified portable service image\n"
" is-attached NAME|PATH Query if portable service image is attached\n"
" --now Immediately start/stop the portable service after\n"
" attach/before detach\n"
" --no-block Don't block waiting for attach --now to complete\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
{ "read-only", 2, 3, 0, read_only_image },
{ "remove", 2, VERB_ANY, 0, remove_image },
{ "set-limit", 3, 3, 0, set_limit },
+ { "reattach", 2, VERB_ANY, 0, reattach_image },
{}
};
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "alloc-util.h"
#include "btrfs-util.h"
#include "bus-common-errors.h"
+#include "bus-object.h"
#include "bus-polkit.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "io-util.h"
-#include "machine-image.h"
#include "missing_capability.h"
#include "portable.h"
#include "portabled-bus.h"
return r;
}
+static int method_reattach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_reattach);
+}
+
static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return redirect_method_to_image(userdata, message, error, bus_image_common_remove);
}
SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
SD_BUS_PROPERTY("Profiles", "as", property_get_profiles, 0, 0),
- SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListImages", NULL, "a(ssbtttso)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageMetadata", "sas", "saya{say}", method_get_image_metadata, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetImageState", "s", "s", method_get_image_state, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("AttachImage", "sassbs", "a(sss)", method_attach_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("DetachImage", "sb", "a(sss)", method_detach_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImage",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("o", object),
+ method_get_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ListImages",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("a(ssbtttso)", images),
+ method_list_images,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageOSRelease",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("a{ss}", os_release),
+ method_get_image_os_release,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageMetadata",
+ SD_BUS_ARGS("s", image,
+ "as", matches),
+ SD_BUS_RESULT("s", image,
+ "ay", os_release,
+ "a{say}", units),
+ method_get_image_metadata,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetImageState",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_RESULT("s", state),
+ method_get_image_state,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("AttachImage",
+ SD_BUS_ARGS("s", image,
+ "as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_attach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("DetachImage",
+ SD_BUS_ARGS("s", image,
+ "b", runtime),
+ SD_BUS_RESULT("a(sss)", changes),
+ method_detach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ReattachImage",
+ SD_BUS_ARGS("s", image,
+ "as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes_removed,
+ "a(sss)", changes_updated),
+ method_reattach_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RemoveImage",
+ SD_BUS_ARGS("s", image),
+ SD_BUS_NO_RESULT,
+ method_remove_image,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("MarkImageReadOnly",
+ SD_BUS_ARGS("s", image,
+ "b", read_only),
+ SD_BUS_NO_RESULT,
+ method_mark_image_read_only,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetImageLimit",
+ SD_BUS_ARGS("s", image,
+ "t", limit),
+ SD_BUS_NO_RESULT,
+ method_set_image_limit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetPoolLimit",
+ SD_BUS_ARGS("t", limit),
+ SD_BUS_NO_RESULT,
+ method_set_pool_limit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
-int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+const BusObjectImplementation manager_object = {
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ .vtables = BUS_VTABLES(manager_vtable),
+ .children = BUS_IMPLEMENTATIONS(&image_object),
+};
+
+static int reply_portable_compose_message(sd_bus_message *reply, const PortableChange *changes, size_t n_changes) {
size_t i;
int r;
- assert(m);
+ assert(reply);
assert(changes || n_changes == 0);
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
r = sd_bus_message_open_container(reply, 'a', "(sss)");
if (r < 0)
return r;
if (r < 0)
return r;
+ return 0;
+}
+
+int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ assert(m);
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = reply_portable_compose_message(reply, changes, n_changes);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
+int reply_portable_changes_pair(
+ sd_bus_message *m,
+ const PortableChange *changes_first,
+ size_t n_changes_first,
+ const PortableChange *changes_second,
+ size_t n_changes_second) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ assert(m);
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = reply_portable_compose_message(reply, changes_first, n_changes_first);
+ if (r < 0)
+ return r;
+
+ r = reply_portable_compose_message(reply, changes_second, n_changes_second);
+ if (r < 0)
+ return r;
+
return sd_bus_send(NULL, reply, NULL);
}
extern const sd_bus_vtable manager_vtable[];
int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes);
+int reply_portable_changes_pair(sd_bus_message *m, const PortableChange *changes_first, size_t n_changes_first, const PortableChange *changes_second, size_t n_changes_second);
#include "bus-common-errors.h"
#include "bus-get-properties.h"
#include "bus-label.h"
+#include "bus-object.h"
#include "bus-polkit.h"
#include "bus-util.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
-#include "machine-image.h"
#include "missing_capability.h"
#include "portable.h"
#include "portabled-bus.h"
return bus_image_common_remove(NULL, message, NULL, userdata, error);
}
+/* Given two PortableChange arrays, return a new array that has all elements of the first that are
+ * not also present in the second, comparing the basename of the path values. */
+static int normalize_portable_changes(
+ const PortableChange *changes_attached,
+ size_t n_changes_attached,
+ const PortableChange *changes_detached,
+ size_t n_changes_detached,
+ PortableChange **ret_changes,
+ size_t *ret_n_changes) {
+
+ PortableChange *changes = NULL;
+ size_t n_changes = 0;
+ int r = 0;
+
+ assert(ret_n_changes);
+ assert(ret_changes);
+
+ if (n_changes_detached == 0)
+ return 0; /* Nothing to do */
+
+ changes = new0(PortableChange, n_changes_attached + n_changes_detached);
+ if (!changes)
+ return -ENOMEM;
+
+ /* Corner case: only detached, nothing attached */
+ if (n_changes_attached == 0) {
+ memcpy(changes, changes_detached, sizeof(PortableChange) * n_changes_detached);
+ *ret_changes = TAKE_PTR(changes);
+ *ret_n_changes = n_changes_detached;
+
+ return 0;
+ }
+
+ for (size_t i = 0; i < n_changes_detached; ++i) {
+ bool found = false;
+
+ for (size_t j = 0; j < n_changes_attached; ++j)
+ if (streq(basename(changes_detached[i].path), basename(changes_attached[j].path))) {
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ _cleanup_free_ char *path = NULL, *source = NULL;
+
+ path = strdup(changes_detached[i].path);
+ if (!path) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ if (changes_detached[i].source) {
+ source = strdup(changes_detached[i].source);
+ if (!source) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ changes[n_changes++] = (PortableChange) {
+ .type = changes_detached[i].type,
+ .path = TAKE_PTR(path),
+ .source = TAKE_PTR(source),
+ };
+ }
+ }
+
+ *ret_n_changes = n_changes;
+ *ret_changes = TAKE_PTR(changes);
+
+ return 0;
+
+fail:
+ portable_changes_free(changes, n_changes);
+ return r;
+}
+
+int bus_image_common_reattach(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ PortableChange *changes_detached = NULL, *changes_attached = NULL, *changes_gone = NULL;
+ size_t n_changes_detached = 0, n_changes_attached = 0, n_changes_gone = 0;
+ _cleanup_strv_free_ char **matches = NULL;
+ PortableFlags flags = PORTABLE_REATTACH;
+ const char *profile, *copy_mode;
+ int runtime, r;
+
+ assert(message);
+ assert(name_or_path || image);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = sd_bus_message_read_strv(message, &matches);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "sbs", &profile, &runtime, ©_mode);
+ if (r < 0)
+ return r;
+
+ if (streq(copy_mode, "symlink"))
+ flags |= PORTABLE_PREFER_SYMLINK;
+ else if (streq(copy_mode, "copy"))
+ flags |= PORTABLE_PREFER_COPY;
+ else if (!isempty(copy_mode))
+ return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Unknown copy mode '%s'", copy_mode);
+
+ if (runtime)
+ flags |= PORTABLE_RUNTIME;
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_ALL,
+ "org.freedesktop.portable1.attach-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) /* Will call us back */
+ return 1;
+
+ r = portable_detach(
+ sd_bus_message_get_bus(message),
+ image->path,
+ flags,
+ &changes_detached,
+ &n_changes_detached,
+ error);
+ if (r < 0)
+ goto finish;
+
+ r = portable_attach(
+ sd_bus_message_get_bus(message),
+ image->path,
+ matches,
+ profile,
+ flags,
+ &changes_attached,
+ &n_changes_attached,
+ error);
+ if (r < 0)
+ goto finish;
+
+ /* We want to return the list of units really removed by the detach,
+ * and not added again by the attach */
+ r = normalize_portable_changes(changes_attached, n_changes_attached,
+ changes_detached, n_changes_detached,
+ &changes_gone, &n_changes_gone);
+ if (r < 0)
+ goto finish;
+
+ /* First, return the units that are gone (so that the caller can stop them)
+ * Then, return the units that are changed/added (so that the caller can
+ * start/restart/enable them) */
+ r = reply_portable_changes_pair(message,
+ changes_gone, n_changes_gone,
+ changes_attached, n_changes_attached);
+ if (r < 0)
+ goto finish;
+
+finish:
+ portable_changes_free(changes_detached, n_changes_detached);
+ portable_changes_free(changes_attached, n_changes_attached);
+ portable_changes_free(changes_gone, n_changes_gone);
+ return r;
+}
+
+static int bus_image_method_reattach(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_reattach(NULL, message, NULL, userdata, error);
+}
+
int bus_image_common_mark_read_only(
Manager *m,
sd_bus_message *message,
SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
- SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetMetadata", "as", "saya{say}", bus_image_method_get_metadata, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetState", NULL, "s", bus_image_method_get_state, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Attach", "assbs", "a(sss)", bus_image_method_attach, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Detach", "b", "a(sss)", bus_image_method_detach, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetOSRelease",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("a{ss}", os_release),
+ bus_image_method_get_os_release,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetMetadata",
+ SD_BUS_ARGS("as", matches),
+ SD_BUS_RESULT("s", image,
+ "ay", os_release,
+ "a{say}", units),
+ bus_image_method_get_metadata,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetState",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("s", state),
+ bus_image_method_get_state,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Attach",
+ SD_BUS_ARGS("as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes),
+ bus_image_method_attach,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Detach",
+ SD_BUS_ARGS("b", runtime),
+ SD_BUS_RESULT("a(sss)", changes),
+ bus_image_method_detach,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Reattach",
+ SD_BUS_ARGS("as", matches,
+ "s", profile,
+ "b", runtime,
+ "s", copy_mode),
+ SD_BUS_RESULT("a(sss)", changes_removed,
+ "a(sss)", changes_updated),
+ bus_image_method_reattach,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("Remove",
+ SD_BUS_NO_ARGS,
+ SD_BUS_NO_RESULT,
+ bus_image_method_remove,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("MarkReadOnly",
+ SD_BUS_ARGS("b", read_only),
+ SD_BUS_NO_RESULT,
+ bus_image_method_mark_read_only,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetLimit",
+ SD_BUS_ARGS("t", limit),
+ SD_BUS_NO_RESULT,
+ bus_image_method_set_limit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
return 1;
}
+
+const BusObjectImplementation image_object = {
+ "/org/freedesktop/portable1/image",
+ "org.freedesktop.portable1.Image",
+ .fallback_vtables = BUS_FALLBACK_VTABLES({image_vtable, bus_image_object_find}),
+ .node_enumerator = bus_image_node_enumerator,
+};
#include "sd-bus.h"
-#include "machine-image.h"
+#include "discover-image.h"
#include "portabled.h"
int bus_image_common_get_os_release(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
int bus_image_common_get_metadata(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
int bus_image_common_attach(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
int bus_image_common_remove(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_reattach(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
int bus_image_common_mark_read_only(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
int bus_image_common_set_limit(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
extern const sd_bus_vtable image_vtable[];
+extern const BusObjectImplementation image_object;
int bus_image_path(Image *image, char **ret);
BUS_IMAGE_AUTHENTICATE_BY_PATH, /* allow by name + polkit by path */
BUS_IMAGE_AUTHENTICATE_ALL, /* polkit by name + polkit by path */
_BUS_IMAGE_ACQUIRE_MODE_MAX,
- _BUS_IMAGE_ACQUIRE_MODE_INVALID = -1
+ _BUS_IMAGE_ACQUIRE_MODE_INVALID = -EINVAL,
} ImageAcquireMode;
int bus_image_acquire(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, ImageAcquireMode mode, const char *polkit_action, Image **ret, sd_bus_error *error);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include "discover-image.h"
#include "hashmap.h"
-#include "machine-image.h"
#include "portabled.h"
Image *manager_image_cache_get(Manager *m, const char *name_or_path);
#include "portabled-image-bus.h"
#include "portabled.h"
#include "process-util.h"
+#include "service-util.h"
#include "signal-util.h"
static Manager* manager_unref(Manager *m);
if (r < 0)
return log_error_errno(r, "Failed to connect to system bus: %m");
- r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/portable1", "org.freedesktop.portable1.Manager", manager_vtable, m);
+ r = bus_add_implementation(m->bus, &manager_object, m);
if (r < 0)
- return log_error_errno(r, "Failed to add manager object vtable: %m");
-
- r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/portable1/image", "org.freedesktop.portable1.Image", image_vtable, bus_image_object_find, m);
- if (r < 0)
- return log_error_errno(r, "Failed to add image object vtable: %m");
-
- r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/portable1/image", bus_image_node_enumerator, m);
- if (r < 0)
- return log_error_errno(r, "Failed to add image enumerator: %m");
+ return r;
r = bus_log_control_api_register(m->bus);
if (r < 0)
_cleanup_(manager_unrefp) Manager *m = NULL;
int r;
- log_setup_service();
+ log_setup();
+
+ r = service_parse_argv("systemd-portabled.service",
+ "Manage registrations of portable images.",
+ BUS_IMPLEMENTATIONS(&manager_object,
+ &log_control_object),
+ argc, argv);
+ if (r <= 0)
+ return r;
umask(0022);
#include "sd-bus.h"
#include "sd-event.h"
+#include "bus-object.h"
#include "hashmap.h"
#include "list.h"
LIST_HEAD(Operation, operations);
unsigned n_operations;
};
+
+extern const BusObjectImplementation manager_object;
[Service]
MountAPIVFS=yes
-TemporaryFileSystem=/run
-BindReadOnlyPaths=/run/systemd/notify
BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
BindReadOnlyPaths=/etc/machine-id
BindReadOnlyPaths=/etc/resolv.conf
[Service]
MountAPIVFS=yes
-TemporaryFileSystem=/run
-BindReadOnlyPaths=/run/systemd/notify
BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
BindReadOnlyPaths=/etc/machine-id
BindReadOnlyPaths=/run/dbus/system_bus_socket
[Service]
MountAPIVFS=yes
-TemporaryFileSystem=/run
-BindReadOnlyPaths=/run/systemd/notify
BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
BindReadOnlyPaths=/etc/machine-id
DynamicUser=yes
PSTORE_STORAGE_EXTERNAL,
PSTORE_STORAGE_JOURNAL,
_PSTORE_STORAGE_MAX,
- _PSTORE_STORAGE_INVALID = -1
+ _PSTORE_STORAGE_INVALID = -EINVAL,
} PStoreStorage;
static const char* const pstore_storage_table[_PSTORE_STORAGE_MAX] = {
_cleanup_(pstore_entries_reset) PStoreList list = {};
int r;
- log_setup_service();
+ log_setup();
if (argc == 3) {
arg_sourcedir = argv[1];
static int run(int argc, char *argv[]) {
int r;
- log_setup_service();
+ log_setup();
if (argc > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
ssize_t k;
int r;
- log_setup_service();
+ log_setup();
if (argc != 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
struct mntent* me;
int r;
- log_setup_service();
+ log_setup();
if (argc > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
size_t length = 0;
int r;
- log_setup_service();
+ log_setup();
if (argc != 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
DNS_TYPE_DLV,
_DNS_TYPE_MAX,
- _DNS_TYPE_INVALID = -1
+ _DNS_TYPE_INVALID = -EINVAL,
};
assert_cc(DNS_TYPE_SSHFP == 44);
DNS_CLASS_ANY = 0xFF,
_DNS_CLASS_MAX,
- _DNS_CLASS_INVALID = -1
+ _DNS_CLASS_INVALID = -EINVAL,
};
#define _DNS_CLASS_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t))
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "const char *dns_type_to_string(int type) {\n\tswitch(type) {"
}
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
-"""Generate %-from-name.gperf from %-list.txt
-"""
+"Generate %-from-name.gperf from %-list.txt"
import sys
_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"")
#endif
%}""")
-print("""\
-struct {}_name {{ const char* name; int id; }};
+print(f"""\
+struct {name}_name {{ const char* name; int id; }};
%null-strings
-%%""".format(name))
+%%""")
for line in open(input):
line = line.rstrip()
s = line.replace('_', '-')
- print("{}, {}{}".format(s, prefix, line))
+ print(f'{s}, {prefix}{line}')
+# SPDX-License-Identifier: LGPL-2.1-or-later
s/.* DNS_TYPE_(\w+).*/\1/p
resolved-mdns.h
resolved-resolv-conf.c
resolved-resolv-conf.h
+ resolved-socket-graveyard.c
+ resolved-socket-graveyard.h
resolved-varlink.c
resolved-varlink.h
resolved.c
"implementations are not supported and will cause the invocation to fail: -u,\n"
"-I, -i, -l, -R, -r, -v, -V, --enable-updates, --disable-updates,\n"
"--updates-are-enabled.\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
printf(" in %s.%s\n"
- "%s-- Data is authenticated: %s%s\n",
+ "%s-- Data is authenticated: %s; Data was acquired via local or encrypted transport: %s%s\n",
rtt_str, ansi_normal(),
- ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal());
+ ansi_grey(),
+ yes_no(flags & SD_RESOLVED_AUTHENTICATED),
+ yes_no(flags & SD_RESOLVED_CONFIDENTIAL),
+ ansi_normal());
+
+ if ((flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC)) != 0)
+ printf("%s-- Data from:%s%s%s%s%s%s\n",
+ ansi_grey(),
+ FLAGS_SET(flags, SD_RESOLVED_SYNTHETIC) ? " synthetic" : "",
+ FLAGS_SET(flags, SD_RESOLVED_FROM_CACHE) ? " cache" : "",
+ FLAGS_SET(flags, SD_RESOLVED_FROM_ZONE) ? " zone" : "",
+ FLAGS_SET(flags, SD_RESOLVED_FROM_TRUST_ANCHOR) ? " trust-anchor" : "",
+ FLAGS_SET(flags, SD_RESOLVED_FROM_NETWORK) ? " network" : "",
+ ansi_normal());
}
static void print_ifindex_comment(int printed_so_far, int ifindex) {
return 0;
}
+static int idna_candidate(const char *name, char **ret) {
+ _cleanup_free_ char *idnafied = NULL;
+ int r;
+
+ assert(name);
+ assert(ret);
+
+ r = dns_name_apply_idna(name, &idnafied);
+ if (r < 0)
+ return log_error_errno(r, "Failed to apply IDNA to name '%s': %m", name);
+ if (r > 0 && !streq(name, idnafied)) {
+ *ret = TAKE_PTR(idnafied);
+ return true;
+ }
+
+ *ret = NULL;
+ return false;
+}
+
static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *idnafied = NULL;
+ bool needs_authentication = false;
unsigned n = 0;
uint64_t flags;
- int r;
usec_t ts;
- bool needs_authentication = false;
+ int r;
assert(name);
log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(arg_ifname) ? "*" : arg_ifname);
+ if (dns_name_is_single_label(name))
+ log_notice("(Note that search domains are not appended when resolving raw record types. "
+ "Please specify fully qualified domain names when resolving raw records, or remove --type= switch from invocation in order to request regular hostname resolution.)");
+
+ r = idna_candidate(name, &idnafied);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ log_notice("(Note that IDNA translation is not applied when resolving raw record types. "
+ "Please specify translated domain names — i.e. '%s' — when resolving raw records, or remove --type= switch from invocation in order to request regular hostname resolution.",
+ idnafied);
+
r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveRecord");
if (r < 0)
return bus_log_create_error(r);
r = dns_class_from_string(t);
if (r < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown DNS class %s.", t);
+ return log_error_errno(r, "Unknown DNS class %s.", t);
class = r;
r = dns_type_from_string(t);
if (r < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown DNS type %s.", t);
+ return log_error_errno(r, "Unknown DNS type %s: %m", t);
type = r;
" --set-dnssec=MODE Set per-interface DNSSEC mode\n"
" --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
" --revert Revert per-interface configuration\n"
- "\nSee the %4$s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %4$s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
" --service-address=BOOL Resolve address for services (default: yes)\n"
" --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
" --cname=BOOL Follow CNAME redirects (default: yes)\n"
- " --search=BOOL Use search domains for single-label names\n"
- " (default: yes)\n"
+ " --validate=BOOL Allow DNSSEC validation (default: yes)\n"
+ " --synthesize=BOOL Allow synthetic response (default: yes)\n"
+ " --cache=BOOL Allow response from cache (default: yes)\n"
+ " --zone=BOOL Allow response from locally registered mDNS/LLMNR\n"
+ " records (default: yes)\n"
+ " --trust-anchor=BOOL Allow response from local trust anchor (default: yes)\n"
+ " --network=BOOL Allow response from network (default: yes)\n"
+ " --search=BOOL Use search domains for single-label names (default: yes)\n"
" --raw[=payload|packet] Dump the answer as binary data\n"
" --legend=BOOL Print headers and additional info (default: yes)\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
}
r = dns_type_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record type %s", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
+
arg_type = (uint16_t) r;
assert((int) arg_type == r);
}
r = dns_class_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record class %s", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
+
arg_class = (uint16_t) r;
assert((int) arg_class == r);
ARG_VERSION = 0x100,
ARG_LEGEND,
ARG_CNAME,
+ ARG_VALIDATE,
+ ARG_SYNTHESIZE,
+ ARG_CACHE,
+ ARG_ZONE,
+ ARG_TRUST_ANCHOR,
+ ARG_NETWORK,
ARG_SERVICE_ADDRESS,
ARG_SERVICE_TXT,
ARG_RAW,
{ "interface", required_argument, NULL, 'i' },
{ "protocol", required_argument, NULL, 'p' },
{ "cname", required_argument, NULL, ARG_CNAME },
+ { "validate", required_argument, NULL, ARG_VALIDATE },
+ { "synthesize", required_argument, NULL, ARG_SYNTHESIZE },
+ { "cache", required_argument, NULL, ARG_CACHE },
+ { "zone", required_argument, NULL, ARG_ZONE },
+ { "trust-anchor", required_argument, NULL, ARG_TRUST_ANCHOR },
+ { "network", required_argument, NULL, ARG_NETWORK },
{ "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
{ "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
{ "raw", optional_argument, NULL, ARG_RAW },
}
r = dns_type_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record type %s", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
+
arg_type = (uint16_t) r;
assert((int) arg_type == r);
}
r = dns_class_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record class %s", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
+
arg_class = (uint16_t) r;
assert((int) arg_class == r);
SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
break;
+ case ARG_VALIDATE:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --validate= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_VALIDATE, r == 0);
+ break;
+
+ case ARG_SYNTHESIZE:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --synthesize= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_SYNTHESIZE, r == 0);
+ break;
+
+ case ARG_CACHE:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --cache= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_CACHE, r == 0);
+ break;
+
+ case ARG_ZONE:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --zone= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_ZONE, r == 0);
+ break;
+
+ case ARG_TRUST_ANCHOR:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --trust-anchor= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_TRUST_ANCHOR, r == 0);
+ break;
+
+ case ARG_NETWORK:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --network= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_NETWORK, r == 0);
+ break;
+
case ARG_SERVICE_ADDRESS:
r = parse_boolean(optarg);
if (r < 0)
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
if (streq(program_invocation_short_name, "resolvconf"))
r = resolvconf_parse_argv(argc, argv);
MODE_STATUS,
MODE_SET_LINK,
MODE_REVERT_LINK,
- _MODE_INVALID = -1,
+ _MODE_INVALID = -EINVAL,
} ExecutionMode;
extern ExecutionMode arg_mode;
#include "bus-message-util.h"
#include "bus-polkit.h"
#include "dns-domain.h"
+#include "format-util.h"
#include "memory-util.h"
#include "missing_capability.h"
#include "resolved-bus.h"
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
return sd_bus_reply_method_errorf(q->bus_request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
+ case DNS_TRANSACTION_NO_SOURCE:
+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
+
+ case DNS_TRANSACTION_STUB_LOOP:
+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_STUB_LOOP, "Configured DNS server loops back to us");
+
case DNS_TRANSACTION_RCODE_FAILURE: {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
r = sd_bus_message_append(
reply, "st",
normalized,
- SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+ dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
*
* 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
*
- * 2. Only the protocols flags and the NO_CNAME flag are set, at most. Plus additional flags specific
- * to our method, passed in the "ok" parameter.
+ * 2. Only the protocols flags and a bunch of NO_XYZ flags are set, at most. Plus additional flags
+ * specific to our method, passed in the "ok" parameter.
*
* 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
* clients can simply pass 0 as flags and all will work as it should. They can also use this so
* to mean "all supported protocols".
*/
- if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
+ if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
+ SD_RESOLVED_NO_CNAME|
+ SD_RESOLVED_NO_VALIDATE|
+ SD_RESOLVED_NO_SYNTHESIZE|
+ SD_RESOLVED_NO_CACHE|
+ SD_RESOLVED_NO_ZONE|
+ SD_RESOLVED_NO_TRUST_ANCHOR|
+ SD_RESOLVED_NO_NETWORK|
+ ok))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
return r;
r = sd_bus_message_append(reply, "st", canonical,
- SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
+ SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true) |
+ SD_RESOLVED_SYNTHETIC);
if (r < 0)
return r;
return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
}
+void bus_client_log(sd_bus_message *m, const char *what) {
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ const char *comm = NULL;
+ uid_t uid = UID_INVALID;
+ pid_t pid = 0;
+ int r;
+
+ assert(m);
+ assert(what);
+
+ if (!DEBUG_LOGGING)
+ return;
+
+ r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
+ if (r < 0)
+ return (void) log_debug_errno(r, "Failed to query client credentials, ignoring: %m");
+
+ (void) sd_bus_creds_get_uid(creds, &uid);
+ (void) sd_bus_creds_get_pid(creds, &pid);
+ (void) sd_bus_creds_get_comm(creds, &comm);
+
+ log_debug("D-Bus %s request from client PID " PID_FMT " (%s) with UID " UID_FMT,
+ what, pid, strna(comm), uid);
+}
+
static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
Manager *m = userdata;
if (r < 0 && r != -EALREADY)
return r;
- r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
+ bus_client_log(message, "hostname resolution");
+
+ r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, ifindex, flags);
if (r < 0)
return r;
if (r < 0)
goto finish;
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+ r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
if (r < 0)
return r;
- r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+ bus_client_log(message, "address resolution");
+
+ r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
if (r < 0)
goto finish;
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+ r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
if (r < 0)
return r;
- r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+ bus_client_log(message, "resource record resolution");
+
+ /* Setting SD_RESOLVED_CLAMP_TTL: let's request that the TTL is fixed up for locally cached entries,
+ * after all we return it in the wire format blob. */
+ r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH|SD_RESOLVED_CLAMP_TTL);
if (r < 0)
return r;
- /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
- * blob */
- q->clamp_ttl = true;
-
q->bus_request = sd_bus_message_ref(message);
q->complete = bus_method_resolve_record_complete;
reply,
"ssst",
name, type, domain,
- SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+ dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
if (r < 0)
return r;
- r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
+ r = dns_query_new(q->manager, &aux, question, question, NULL, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
if (r < 0)
return r;
- r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+ bus_client_log(message, "service resolution");
+
+ r = dns_query_new(m, &q, question_utf8, question_idna, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
assert(message);
assert(m);
+ bus_client_log(message, "statistics reset");
+
LIST_FOREACH(scopes, s, m->dns_scopes)
s->cache.n_hit = s->cache.n_miss = 0;
assert(message);
assert(m);
+ bus_client_log(message, "cache flush");
+
manager_flush_caches(m, LOG_INFO);
return sd_bus_reply_method_return(message, NULL);
assert(message);
assert(m);
+ bus_client_log(message, "server feature reset");
+
manager_reset_server_features(m);
return sd_bus_reply_method_return(message, NULL);
int bus_property_get_resolve_support(sd_bus *bus, const char *path, const char *interface,
const char *property, sd_bus_message *reply,
void *userdata, sd_bus_error *error);
+
+void bus_client_log(sd_bus_message *m, const char *what);
/* Output: Result is authenticated */
#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
+/* Input: Don't DNSSEC validate request */
+#define SD_RESOLVED_NO_VALIDATE (UINT64_C(1) << 10)
+
+/* Input: Don't answer request from locally synthesized records (which includes /etc/hosts) */
+#define SD_RESOLVED_NO_SYNTHESIZE (UINT64_C(1) << 11)
+
+/* Input: Don't answer request from cache */
+#define SD_RESOLVED_NO_CACHE (UINT64_C(1) << 12)
+
+/* Input: Don't answer request from locally registered public LLMNR/mDNS RRs */
+#define SD_RESOLVED_NO_ZONE (UINT64_C(1) << 13)
+
+/* Input: Don't answer request from locally registered public LLMNR/mDNS RRs */
+#define SD_RESOLVED_NO_TRUST_ANCHOR (UINT64_C(1) << 14)
+
+/* Input: Don't go to network for this request */
+#define SD_RESOLVED_NO_NETWORK (UINT64_C(1) << 15)
+
+/* Input: Require that request is answered from a "primary" answer, i.e. not from RRs acquired as
+ * side-effect of a previous transaction */
+#define SD_RESOLVED_REQUIRE_PRIMARY (UINT64_C(1) << 16)
+
+/* Input: If reply is answered from cache, the TTLs will be adjusted by age of cache entry */
+#define SD_RESOLVED_CLAMP_TTL (UINT64_C(1) << 17)
+
+/* Output: Result was only sent via encrypted channels, or never left this system */
+#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
+
+/* Output: Result was (at least partially) synthesized locally */
+#define SD_RESOLVED_SYNTHETIC (UINT64_C(1) << 19)
+
+/* Output: Result was (at least partially) answered from cache */
+#define SD_RESOLVED_FROM_CACHE (UINT64_C(1) << 20)
+
+/* Output: Result was (at least partially) answered from local zone */
+#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) << 21)
+
+/* Output: Result was (at least partially) answered from trust anchor */
+#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) << 22)
+
+/* Output: Result was (at least partially) answered from network */
+#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
+
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
+#define SD_RESOLVED_FROM_MASK (SD_RESOLVED_FROM_CACHE|SD_RESOLVED_FROM_ZONE|SD_RESOLVED_FROM_TRUST_ANCHOR|SD_RESOLVED_FROM_NETWORK)
+
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
#include "alloc-util.h"
#include "dns-domain.h"
+#include "random-util.h"
#include "resolved-dns-answer.h"
#include "resolved-dns-dnssec.h"
#include "string-util.h"
a->n_ref = 1;
a->n_allocated = n;
a->set_items = TAKE_PTR(s);
-
return a;
}
static void dns_answer_flush(DnsAnswer *a) {
- DnsResourceRecord *rr;
+ DnsAnswerItem *item;
if (!a)
return;
a->set_items = set_free(a->set_items);
- DNS_ANSWER_FOREACH(rr, a)
- dns_resource_record_unref(rr);
+ DNS_ANSWER_FOREACH_ITEM(item, a) {
+ dns_resource_record_unref(item->rr);
+ dns_resource_record_unref(item->rrsig);
+ }
a->n_rrs = 0;
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free);
-static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
+static int dns_answer_add_raw(
+ DnsAnswer *a,
+ DnsResourceRecord *rr,
+ int ifindex,
+ DnsAnswerFlags flags,
+ DnsResourceRecord *rrsig) {
+
int r;
assert(rr);
.rr = rr,
.ifindex = ifindex,
.flags = flags,
+ .rrsig = dns_resource_record_ref(rrsig),
};
r = set_put(a->set_items, &a->items[a->n_rrs]);
}
static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex, r;
+ DnsAnswerItem *item;
+ int r;
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) {
- r = dns_answer_add_raw(a, rr, ifindex, flags);
+ DNS_ANSWER_FOREACH_ITEM(item, source) {
+ r = dns_answer_add_raw(
+ a,
+ item->rr,
+ item->ifindex,
+ item->flags,
+ item->rrsig);
if (r < 0)
return r;
}
return 0;
}
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
+int dns_answer_add(
+ DnsAnswer *a,
+ DnsResourceRecord *rr,
+ int ifindex,
+ DnsAnswerFlags flags,
+ DnsResourceRecord *rrsig) {
+
DnsAnswerItem tmp, *exist;
assert(rr);
if (rr->ttl > exist->rr->ttl) {
dns_resource_record_unref(exist->rr);
exist->rr = dns_resource_record_ref(rr);
+
+ /* Update RRSIG and RR at the same time */
+ if (rrsig) {
+ dns_resource_record_ref(rrsig);
+ dns_resource_record_unref(exist->rrsig);
+ exist->rrsig = rrsig;
+ }
}
exist->flags |= flags;
return 0;
}
- return dns_answer_add_raw(a, rr, ifindex, flags);
+ return dns_answer_add_raw(a, rr, ifindex, flags, rrsig);
}
static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex, r;
+ DnsAnswerItem *item;
+ int r;
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) {
- r = dns_answer_add(a, rr, ifindex, flags);
+ DNS_ANSWER_FOREACH_ITEM(item, b) {
+ r = dns_answer_add(a, item->rr, item->ifindex, item->flags, item->rrsig);
if (r < 0)
return r;
}
return 0;
}
-int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
+int dns_answer_add_extend(
+ DnsAnswer **a,
+ DnsResourceRecord *rr,
+ int ifindex,
+ DnsAnswerFlags flags,
+ DnsResourceRecord *rrsig) {
+
int r;
assert(a);
if (r < 0)
return r;
- return dns_answer_add(*a, rr, ifindex, flags);
+ return dns_answer_add(*a, rr, ifindex, flags, rrsig);
}
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) {
soa->soa.expire = 1;
soa->soa.minimum = ttl;
- return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED);
+ return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED, NULL);
}
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
DnsResourceRecord *i;
- DNS_ANSWER_FOREACH(i, a) {
+ DNS_ANSWER_FOREACH(i, a)
if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3))
return true;
- }
return false;
}
return false;
}
-int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
+int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr) {
+ DnsResourceRecord *i;
+
+ DNS_ANSWER_FOREACH(i, answer)
+ if (dns_resource_record_equal(i, rr))
+ return true;
+
+ return false;
+}
+
+int dns_answer_find_soa(
+ DnsAnswer *a,
+ const DnsResourceKey *key,
+ DnsResourceRecord **ret,
+ DnsAnswerFlags *ret_flags) {
+
DnsResourceRecord *rr, *soa = NULL;
DnsAnswerFlags rr_flags, soa_flags = 0;
int r;
/* For a SOA record we can never find a matching SOA record */
if (key->type == DNS_TYPE_SOA)
- return 0;
+ goto not_found;
DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
r = dns_resource_key_match_soa(key, rr->key);
}
if (!soa)
- return 0;
+ goto not_found;
if (ret)
*ret = soa;
- if (flags)
- *flags = soa_flags;
+ if (ret_flags)
+ *ret_flags = soa_flags;
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+ if (ret_flags)
+ *ret_flags = 0;
+
+ return 0;
}
-int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
+int dns_answer_find_cname_or_dname(
+ DnsAnswer *a,
+ const DnsResourceKey *key,
+ DnsResourceRecord **ret,
+ DnsAnswerFlags *ret_flags) {
+
DnsResourceRecord *rr;
DnsAnswerFlags rr_flags;
int r;
if (r > 0) {
if (ret)
*ret = rr;
- if (flags)
- *flags = rr_flags;
+ if (ret_flags)
+ *ret_flags = rr_flags;
return 1;
}
}
+ if (ret)
+ *ret = NULL;
+ if (ret_flags)
+ *ret_flags = 0;
+
return 0;
}
if ((*a)->n_ref > 1) {
_cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
- DnsAnswerFlags flags;
- int ifindex;
+ DnsAnswerItem *item;
copy = dns_answer_new((*a)->n_rrs);
if (!copy)
return -ENOMEM;
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
- r = dns_resource_key_equal(rr->key, key);
+ DNS_ANSWER_FOREACH_ITEM(item, *a) {
+ r = dns_resource_key_equal(item->rr->key, key);
if (r < 0)
return r;
if (r > 0)
continue;
- r = dns_answer_add_raw(copy, rr, ifindex, flags);
+ r = dns_answer_add_raw(copy, item->rr, item->ifindex, item->flags, item->rrsig);
if (r < 0)
return r;
}
/* Kill this entry */
dns_resource_record_unref((*a)->items[i].rr);
+ dns_resource_record_unref((*a)->items[i].rrsig);
+
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
(*a)->n_rrs--;
continue;
if ((*a)->n_ref > 1) {
_cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
- DnsAnswerFlags flags;
- int ifindex;
+ DnsAnswerItem *item;
copy = dns_answer_new((*a)->n_rrs);
if (!copy)
return -ENOMEM;
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
- r = dns_resource_record_equal(rr, rm);
+ DNS_ANSWER_FOREACH_ITEM(item, *a) {
+ r = dns_resource_record_equal(item->rr, rm);
if (r < 0)
return r;
if (r > 0)
continue;
- r = dns_answer_add_raw(copy, rr, ifindex, flags);
+ r = dns_answer_add_raw(copy, item->rr, item->ifindex, item->flags, item->rrsig);
if (r < 0)
return r;
}
/* Kill this entry */
dns_resource_record_unref((*a)->items[i].rr);
+ dns_resource_record_unref((*a)->items[i].rrsig);
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
(*a)->n_rrs--;
continue;
return 1;
}
-int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
- DnsResourceRecord *rr_source;
- int ifindex_source, r;
- DnsAnswerFlags flags_source;
+int dns_answer_copy_by_key(
+ DnsAnswer **a,
+ DnsAnswer *source,
+ const DnsResourceKey *key,
+ DnsAnswerFlags or_flags,
+ DnsResourceRecord *rrsig) {
+
+ DnsAnswerItem *item;
+ int r;
assert(a);
assert(key);
/* Copy all RRs matching the specified key from source into *a */
- DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) {
+ DNS_ANSWER_FOREACH_ITEM(item, source) {
- r = dns_resource_key_equal(rr_source->key, key);
+ r = dns_resource_key_equal(item->rr->key, key);
if (r < 0)
return r;
if (r == 0)
if (r < 0)
return r;
- r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags);
+ r = dns_answer_add(*a, item->rr, item->ifindex, item->flags|or_flags, item->rrsig);
if (r < 0)
return r;
}
return 0;
}
-int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
+int dns_answer_move_by_key(
+ DnsAnswer **to,
+ DnsAnswer **from,
+ const DnsResourceKey *key,
+ DnsAnswerFlags or_flags,
+ DnsResourceRecord *rrsig) {
int r;
assert(to);
assert(from);
assert(key);
- r = dns_answer_copy_by_key(to, *from, key, or_flags);
+ r = dns_answer_copy_by_key(to, *from, key, or_flags, rrsig);
if (r < 0)
return r;
items = newa(DnsAnswerItem, a->n_rrs);
for (i = 0; i < a->n_rrs; i++) {
-
- if (a->items[i].rr->key->class == DNS_CLASS_IN &&
- ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) ||
- (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local)))
+ if (dns_resource_record_is_link_local_address(a->items[i].rr) != prefer_link_local)
/* Order address records that are not preferred to the end of the array */
items[end--] = a->items[i];
else
if ((*a)->n_ref > 1)
return -EBUSY;
- ns = (*a)->n_rrs + n_free;
- if (ns > UINT16_MAX) /* Maximum number of RRs we can stick into a DNS packet section */
+ ns = (*a)->n_rrs;
+ assert(ns <= UINT16_MAX); /* Maximum number of RRs we can stick into a DNS packet section */
+
+ if (n_free > UINT16_MAX - ns) /* overflow check */
ns = UINT16_MAX;
+ else
+ ns += n_free;
if ((*a)->n_allocated >= ns)
return 0;
- /* Allocate more than we need */
- ns *= 2;
- if (ns > UINT16_MAX)
+ /* Allocate more than we need, but not more than UINT16_MAX */
+ if (ns <= UINT16_MAX/2)
+ ns *= 2;
+ else
ns = UINT16_MAX;
/* This must be done before realloc() below. Otherwise, the original DnsAnswer object
}
int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
int r;
assert(a);
- /* Tries to extend the DnsAnswer object. And if that's not
- * 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. */
+ /* Tries to extend the DnsAnswer object. And if that's not 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. */
- r = dns_answer_reserve(a, n_free);
- if (r != -EBUSY)
- return r;
+ if (*a && (*a)->n_ref > 1) {
+ _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
+ size_t ns;
- assert(*a);
+ ns = (*a)->n_rrs;
+ assert(ns <= UINT16_MAX); /* Maximum number of RRs we can stick into a DNS packet section */
- n = dns_answer_new(((*a)->n_rrs + n_free) * 2);
- if (!n)
- return -ENOMEM;
+ if (n_free > UINT16_MAX - ns) /* overflow check */
+ ns = UINT16_MAX;
+ else if (n_free > 0) { /* Increase size and double the result, just in case — except if the
+ * increase is specified as 0, in which case we just allocate the
+ * exact amount as before, under the assumption this is just a request
+ * to copy the answer. */
+ ns += n_free;
+
+ if (ns <= UINT16_MAX/2) /* overflow check */
+ ns *= 2;
+ else
+ ns = UINT16_MAX;
+ }
- r = dns_answer_add_raw_all(n, *a);
- if (r < 0)
- return r;
+ n = dns_answer_new(ns);
+ if (!n)
+ return -ENOMEM;
- dns_answer_unref(*a);
- *a = TAKE_PTR(n);
+ r = dns_answer_add_raw_all(n, *a);
+ if (r < 0)
+ return r;
+
+ dns_answer_unref(*a);
+ assert_se(*a = TAKE_PTR(n));
+ } else if (n_free > 0) {
+ r = dns_answer_reserve(a, n_free);
+ if (r < 0)
+ return r;
+ }
return 0;
}
* This function is not used in the code base, but is useful when debugging. Do not delete.
*/
void dns_answer_dump(DnsAnswer *answer, FILE *f) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex;
+ DnsAnswerItem *item;
if (!f)
f = stdout;
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
const char *t;
fputc('\t', f);
- t = dns_resource_record_to_string(rr);
+ t = dns_resource_record_to_string(item->rr);
if (!t) {
log_oom();
continue;
fputs(t, f);
- if (ifindex != 0 || flags != 0)
+ if (item->ifindex != 0 || item->rrsig || item->flags != 0)
fputs("\t;", f);
- if (ifindex != 0)
- fprintf(f, " ifindex=%i", ifindex);
- if (flags & DNS_ANSWER_AUTHENTICATED)
+ if (item->ifindex != 0)
+ fprintf(f, " ifindex=%i", item->ifindex);
+ if (item->rrsig)
+ fputs(" rrsig", f);
+ if (item->flags & DNS_ANSWER_AUTHENTICATED)
fputs(" authenticated", f);
- if (flags & DNS_ANSWER_CACHEABLE)
+ if (item->flags & DNS_ANSWER_CACHEABLE)
fputs(" cacheable", f);
- if (flags & DNS_ANSWER_SHARED_OWNER)
+ if (item->flags & DNS_ANSWER_SHARED_OWNER)
fputs(" shared-owner", f);
- if (flags & DNS_ANSWER_CACHE_FLUSH)
+ if (item->flags & DNS_ANSWER_CACHE_FLUSH)
fputs(" cache-flush", f);
- if (flags & DNS_ANSWER_GOODBYE)
+ if (item->flags & DNS_ANSWER_GOODBYE)
fputs(" goodbye", f);
+ if (item->flags & DNS_ANSWER_SECTION_ANSWER)
+ fputs(" section-answer", f);
+ if (item->flags & DNS_ANSWER_SECTION_AUTHORITY)
+ fputs(" section-authority", f);
+ if (item->flags & DNS_ANSWER_SECTION_ADDITIONAL)
+ fputs(" section-additional", f);
fputc('\n', f);
}
return 0;
}
+
+void dns_answer_randomize(DnsAnswer *a) {
+ size_t n;
+
+ /* Permutes the answer list randomly (Knuth shuffle) */
+
+ n = dns_answer_size(a);
+ if (n <= 1)
+ return;
+
+ for (size_t i = 0; i < n; i++) {
+ size_t k;
+
+ k = random_u64_range(n);
+ if (k == i)
+ continue;
+
+ SWAP_TWO(a->items[i], a->items[k]);
+ }
+}
#include "resolved-dns-rr.h"
#include "set.h"
-/* A simple array of resource records. We keep track of the
- * originating ifindex for each RR where that makes sense, so that we
- * can qualify A and AAAA RRs referring to a local link with the
- * right ifindex.
+/* A simple array of resource records. We keep track of the originating ifindex for each RR where that makes
+ * sense, so that we can qualify A and AAAA RRs referring to a local link with the right ifindex.
*
* Note that we usually encode the empty DnsAnswer object as a simple NULL. */
typedef enum DnsAnswerFlags {
- DNS_ANSWER_AUTHENTICATED = 1 << 0, /* Item has been authenticated */
- DNS_ANSWER_CACHEABLE = 1 << 1, /* Item is subject to caching */
- DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
- DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
- DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */
+ DNS_ANSWER_AUTHENTICATED = 1 << 0, /* Item has been authenticated */
+ DNS_ANSWER_CACHEABLE = 1 << 1, /* Item is subject to caching */
+ DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
+ DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
+ DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */
+ DNS_ANSWER_SECTION_ANSWER = 1 << 5, /* When parsing: RR originates from answer section */
+ DNS_ANSWER_SECTION_AUTHORITY = 1 << 6, /* When parsing: RR originates from authority section */
+ DNS_ANSWER_SECTION_ADDITIONAL = 1 << 7, /* When parsing: RR originates from additional section */
} DnsAnswerFlags;
struct DnsAnswerItem {
DnsResourceRecord *rr;
+ DnsResourceRecord *rrsig; /* Optionally, also store RRSIG RR that successfully validates this item */
int ifindex;
DnsAnswerFlags flags;
};
DnsAnswer *dns_answer_ref(DnsAnswer *a);
DnsAnswer *dns_answer_unref(DnsAnswer *a);
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
-int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
+int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig);
+int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig);
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex);
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
+int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr);
-int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
-int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
+int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags);
+int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags);
int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret);
int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key);
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr);
-int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags);
-int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags);
+int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig);
+int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig);
int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
void dns_answer_dump(DnsAnswer *answer, FILE *f);
+void dns_answer_randomize(DnsAnswer *a);
+
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define _DNS_ANSWER_FOREACH(q, kk, a) \
#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
-#define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \
+#define _DNS_ANSWER_FOREACH_ITEM(q, item, a) \
for (size_t UNIQ_T(i, q) = ({ \
- (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
- (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
- (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
+ (item) = dns_answer_isempty(a) ? NULL : (a)->items; \
0; \
}); \
- (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
+ UNIQ_T(i, q) < dns_answer_size(a); \
UNIQ_T(i, q)++, \
- (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
- (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \
- (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
+ (item) = ((UNIQ_T(i, q) < dns_answer_size(a)) ? (a)->items + UNIQ_T(i, q) : NULL))
-#define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a)
+#define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(UNIQ, item, a)
* now) */
#define CACHE_TTL_STRANGE_RCODE_USEC (10 * USEC_PER_SEC)
+#define CACHEABLE_QUERY_FLAGS (SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL)
+
typedef enum DnsCacheItemType DnsCacheItemType;
typedef struct DnsCacheItem DnsCacheItem;
struct DnsCacheItem {
DnsCacheItemType type;
- DnsResourceKey *key;
- DnsResourceRecord *rr;
+ DnsResourceKey *key; /* The key for this item, i.e. the lookup key */
+ DnsResourceRecord *rr; /* The RR for this item, i.e. the lookup value for positive queries */
+ DnsAnswer *answer; /* The full validated answer, if this is an RRset acquired via a "primary" lookup */
+ DnsPacket *full_packet; /* The full packet this information was acquired with */
int rcode;
usec_t until;
- bool authenticated:1;
bool shared_owner:1;
+ uint64_t query_flags; /* SD_RESOLVED_AUTHENTICATED and/or SD_RESOLVED_CONFIDENTIAL */
+ DnssecResult dnssec_result;
int ifindex;
int owner_family;
LIST_FIELDS(DnsCacheItem, by_key);
};
+/* Returns true if this is a cache item created as result of an explicit lookup, or created as "side-effect"
+ * of another request. "Primary" entries will carry the full answer data (with NSEC, …) that can aso prove
+ * wildcard expansion, non-existance and such, while entries that were created as "side-effect" just contain
+ * immediate RR data for the specified RR key, but nothing else. */
+#define DNS_CACHE_ITEM_IS_PRIMARY(item) (!!(item)->answer)
+
static const char *dns_cache_item_type_to_string(DnsCacheItem *item) {
assert(item);
return NULL;
}
-static void dns_cache_item_free(DnsCacheItem *i) {
+static DnsCacheItem* dns_cache_item_free(DnsCacheItem *i) {
if (!i)
- return;
+ return NULL;
dns_resource_record_unref(i->rr);
dns_resource_key_unref(i->key);
- free(i);
+ dns_answer_unref(i->answer);
+ dns_packet_unref(i->full_packet);
+ return mfree(i);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) {
DnsCache *c,
DnsCacheItem *i,
DnsResourceRecord *rr,
- bool authenticated,
+ DnsAnswer *answer,
+ DnsPacket *full_packet,
+ uint64_t query_flags,
bool shared_owner,
+ DnssecResult dnssec_result,
usec_t timestamp,
int ifindex,
int owner_family,
dns_resource_key_unref(i->key);
i->key = dns_resource_key_ref(rr->key);
- i->until = calculate_until(rr, (uint32_t) -1, timestamp, false);
- i->authenticated = authenticated;
+ dns_answer_ref(answer);
+ dns_answer_unref(i->answer);
+ i->answer = answer;
+
+ dns_packet_ref(full_packet);
+ dns_packet_unref(i->full_packet);
+ i->full_packet = full_packet;
+
+ i->until = calculate_until(rr, UINT32_MAX, timestamp, false);
+ i->query_flags = query_flags & CACHEABLE_QUERY_FLAGS;
i->shared_owner = shared_owner;
+ i->dnssec_result = dnssec_result;
i->ifindex = ifindex;
static int dns_cache_put_positive(
DnsCache *c,
DnsResourceRecord *rr,
- bool authenticated,
+ DnsAnswer *answer,
+ DnsPacket *full_packet,
+ uint64_t query_flags,
bool shared_owner,
+ DnssecResult dnssec_result,
usec_t timestamp,
int ifindex,
int owner_family,
c,
existing,
rr,
- authenticated,
+ answer,
+ full_packet,
+ query_flags,
shared_owner,
+ dnssec_result,
timestamp,
ifindex,
owner_family,
.type = DNS_CACHE_POSITIVE,
.key = dns_resource_key_ref(rr->key),
.rr = dns_resource_record_ref(rr),
+ .answer = dns_answer_ref(answer),
+ .full_packet = dns_packet_ref(full_packet),
.until = calculate_until(rr, (uint32_t) -1, timestamp, false),
- .authenticated = authenticated,
+ .query_flags = query_flags & CACHEABLE_QUERY_FLAGS,
.shared_owner = shared_owner,
+ .dnssec_result = dnssec_result,
.ifindex = ifindex,
.owner_family = owner_family,
.owner_address = *owner_address,
(void) in_addr_to_string(i->owner_family, &i->owner_address, &t);
- log_debug("Added positive %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
- i->authenticated ? "authenticated" : "unauthenticated",
+ log_debug("Added positive %s %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
+ FLAGS_SET(i->query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unauthenticated",
+ FLAGS_SET(i->query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential",
i->shared_owner ? " shared" : "",
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
(i->until - timestamp) / USEC_PER_SEC,
DnsCache *c,
DnsResourceKey *key,
int rcode,
- bool authenticated,
+ DnsAnswer *answer,
+ DnsPacket *full_packet,
+ uint64_t query_flags,
+ DnssecResult dnssec_result,
uint32_t nsec_ttl,
usec_t timestamp,
DnsResourceRecord *soa,
.type =
rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA :
rcode == DNS_RCODE_NXDOMAIN ? DNS_CACHE_NXDOMAIN : DNS_CACHE_RCODE,
- .authenticated = authenticated,
+ .query_flags = query_flags & CACHEABLE_QUERY_FLAGS,
+ .dnssec_result = dnssec_result,
.owner_family = owner_family,
.owner_address = *owner_address,
.prioq_idx = PRIOQ_IDX_NULL,
.rcode = rcode,
+ .answer = dns_answer_ref(answer),
+ .full_packet = dns_packet_ref(full_packet),
};
i->until =
DnsResourceKey *key,
int rcode,
DnsAnswer *answer,
- bool authenticated,
+ DnsPacket *full_packet,
+ uint64_t query_flags,
+ DnssecResult dnssec_result,
uint32_t nsec_ttl,
- usec_t timestamp,
int owner_family,
const union in_addr_union *owner_address) {
- DnsResourceRecord *soa = NULL, *rr;
+ DnsResourceRecord *soa = NULL;
bool weird_rcode = false;
+ DnsAnswerItem *item;
DnsAnswerFlags flags;
unsigned cache_keys;
- int r, ifindex;
+ usec_t timestamp;
+ int r;
assert(c);
assert(owner_address);
log_debug("Not caching negative entry without a SOA record: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
}
+
return 0;
}
/* Make some space for our new entries */
dns_cache_make_space(c, cache_keys);
- if (timestamp <= 0)
- timestamp = now(clock_boottime_or_monotonic());
+ timestamp = now(clock_boottime_or_monotonic());
/* Second, add in positive entries for all contained RRs */
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
- if ((flags & DNS_ANSWER_CACHEABLE) == 0 ||
- !rr_eligible(rr))
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
+ int primary = false;
+
+ if (!FLAGS_SET(item->flags, DNS_ANSWER_CACHEABLE) ||
+ !rr_eligible(item->rr))
continue;
+ if (key) {
+ /* We store the auxiliary RRs and packet data in the cache only if they were in
+ * direct response to the original query. If we cache an RR we also received, and
+ * that is just auxiliary information we can't use the data, hence don't. */
+
+ primary = dns_resource_key_match_rr(key, item->rr, NULL);
+ if (primary < 0)
+ return primary;
+ if (primary == 0) {
+ primary = dns_resource_key_match_cname_or_dname(key, item->rr->key, NULL);
+ if (primary < 0)
+ return primary;
+ }
+ }
+
+ if (!primary) {
+ DnsCacheItem *first;
+
+ /* Do not replace existing cache items for primary lookups with non-primary
+ * data. After all the primary lookup data is a lot more useful. */
+ first = hashmap_get(c->by_key, item->rr->key);
+ if (first && DNS_CACHE_ITEM_IS_PRIMARY(first))
+ return 0;
+ }
+
r = dns_cache_put_positive(
c,
- rr,
- flags & DNS_ANSWER_AUTHENTICATED,
- flags & DNS_ANSWER_SHARED_OWNER,
+ item->rr,
+ primary ? answer : NULL,
+ primary ? full_packet : NULL,
+ ((item->flags & DNS_ANSWER_AUTHENTICATED) ? SD_RESOLVED_AUTHENTICATED : 0) |
+ (query_flags & SD_RESOLVED_CONFIDENTIAL),
+ item->flags & DNS_ANSWER_SHARED_OWNER,
+ dnssec_result,
timestamp,
- ifindex,
- owner_family, owner_address);
+ item->ifindex,
+ owner_family,
+ owner_address);
if (r < 0)
goto fail;
}
if (r > 0) {
/* Refuse using the SOA data if it is unsigned, but the key is
* signed */
- if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0)
+ if (FLAGS_SET(query_flags, SD_RESOLVED_AUTHENTICATED) &&
+ (flags & DNS_ANSWER_AUTHENTICATED) == 0)
return 0;
}
c,
key,
rcode,
- authenticated,
+ answer,
+ full_packet,
+ query_flags,
+ dnssec_result,
nsec_ttl,
timestamp,
soa,
if (key)
dns_cache_remove_by_key(c, key);
- DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
- if ((flags & DNS_ANSWER_CACHEABLE) == 0)
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
+ if ((item->flags & DNS_ANSWER_CACHEABLE) == 0)
continue;
- dns_cache_remove_by_key(c, rr->key);
+ dns_cache_remove_by_key(c, item->rr->key);
}
return r;
return NULL;
}
-int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **ret, bool *authenticated) {
+static int answer_add_clamp_ttl(
+ DnsAnswer **answer,
+ DnsResourceRecord *rr,
+ int ifindex,
+ DnsAnswerFlags answer_flags,
+ DnsResourceRecord *rrsig,
+ uint64_t query_flags,
+ usec_t until,
+ usec_t current) {
+
+ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *patched = NULL, *patched_rrsig = NULL;
+ int r;
+
+ assert(answer);
+ assert(rr);
+
+ if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL)) {
+ patched = dns_resource_record_ref(rr);
+
+ r = dns_resource_record_clamp_ttl(&patched, LESS_BY(until, current) / USEC_PER_SEC);
+ if (r < 0)
+ return r;
+
+ rr = patched;
+
+ if (rrsig) {
+ patched_rrsig = dns_resource_record_ref(rrsig);
+ r = dns_resource_record_clamp_ttl(&patched_rrsig, LESS_BY(until, current) / USEC_PER_SEC);
+ if (r < 0)
+ return r;
+
+ rrsig = patched_rrsig;
+ }
+ }
+
+ r = dns_answer_add_extend(answer, rr, ifindex, answer_flags, rrsig);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int dns_cache_lookup(
+ DnsCache *c,
+ DnsResourceKey *key,
+ uint64_t query_flags,
+ int *ret_rcode,
+ DnsAnswer **ret_answer,
+ DnsPacket **ret_full_packet,
+ uint64_t *ret_query_flags,
+ DnssecResult *ret_dnssec_result) {
+
+ _cleanup_(dns_packet_unrefp) DnsPacket *full_packet = NULL;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
unsigned n = 0;
int r;
bool nxdomain = false;
DnsCacheItem *j, *first, *nsec = NULL;
- bool have_authenticated = false, have_non_authenticated = false;
+ bool have_authenticated = false, have_non_authenticated = false, have_confidential = false, have_non_confidential = false;
usec_t current;
int found_rcode = -1;
+ DnssecResult dnssec_result = -1;
+ int have_dnssec_result = -1;
assert(c);
assert(key);
- assert(rcode);
- assert(ret);
- assert(authenticated);
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
- /* If we have ANY lookups we don't use the cache, so
- * that the caller refreshes via the network. */
+ /* If we have ANY lookups we don't use the cache, so that the caller refreshes via the
+ * network. */
log_debug("Ignoring cache for ANY lookup: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
-
- c->n_miss++;
-
- *ret = NULL;
- *rcode = DNS_RCODE_SUCCESS;
- *authenticated = false;
-
- return 0;
+ goto miss;
}
first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key);
log_debug("Cache miss for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
+ goto miss;
+ }
- c->n_miss++;
+ if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL))
+ current = now(clock_boottime_or_monotonic());
- *ret = NULL;
- *rcode = DNS_RCODE_SUCCESS;
- *authenticated = false;
+ LIST_FOREACH(by_key, j, first) {
+ /* If the caller doesn't allow us to answer questions from cache data learned from
+ * "side-effect", skip this entry. */
+ if (FLAGS_SET(query_flags, SD_RESOLVED_REQUIRE_PRIMARY) &&
+ !DNS_CACHE_ITEM_IS_PRIMARY(j)) {
+ log_debug("Primary answer was requested for cache lookup for %s, which we don't have.",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
- return 0;
- }
+ goto miss;
+ }
- LIST_FOREACH(by_key, j, first) {
- if (j->rr) {
+ if (j->type == DNS_CACHE_NXDOMAIN)
+ nxdomain = true;
+ else if (j->type == DNS_CACHE_RCODE)
+ found_rcode = j->rcode;
+ else if (j->rr) {
if (j->rr->key->type == DNS_TYPE_NSEC)
nsec = j;
n++;
- } else if (j->type == DNS_CACHE_NXDOMAIN)
- nxdomain = true;
- else if (j->type == DNS_CACHE_RCODE)
- found_rcode = j->rcode;
+ }
- if (j->authenticated)
+ if (FLAGS_SET(j->query_flags, SD_RESOLVED_AUTHENTICATED))
have_authenticated = true;
else
have_non_authenticated = true;
+
+ if (FLAGS_SET(j->query_flags, SD_RESOLVED_CONFIDENTIAL))
+ have_confidential = true;
+ else
+ have_non_confidential = true;
+
+ if (j->dnssec_result < 0) {
+ have_dnssec_result = false; /* an entry without dnssec result? then invalidate things for good */
+ dnssec_result = _DNSSEC_RESULT_INVALID;
+ } else if (have_dnssec_result < 0) {
+ have_dnssec_result = true; /* So far no result seen, let's pick this one up */
+ dnssec_result = j->dnssec_result;
+ } else if (have_dnssec_result > 0 && j->dnssec_result != dnssec_result) {
+ have_dnssec_result = false; /* conflicting result seen? then invalidate for good */
+ dnssec_result = _DNSSEC_RESULT_INVALID;
+ }
+
+ /* Append the answer RRs to our answer. Ideally we have the answer object, which we
+ * preferably use. But if the cached entry was generated as "side-effect" of a reply,
+ * i.e. from validated auxiliary records rather than from the main reply, then we use the
+ * individual RRs only instead. */
+ if (j->answer) {
+
+ /* Minor optimization, if the full answer object of this and the previous RR is the
+ * same, don't bother adding it again. Typically we store a full RRset here, hence
+ * that should be the case. */
+ if (!j->by_key_prev || j->answer != j->by_key_prev->answer) {
+ DnsAnswerItem *item;
+
+ DNS_ANSWER_FOREACH_ITEM(item, j->answer) {
+ r = answer_add_clamp_ttl(&answer, item->rr, item->ifindex, item->flags, item->rrsig, query_flags, j->until, current);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ } else if (j->rr) {
+ r = answer_add_clamp_ttl(&answer,
+ j->rr,
+ j->ifindex,
+ FLAGS_SET(j->query_flags, SD_RESOLVED_AUTHENTICATED) ? DNS_ANSWER_AUTHENTICATED : 0,
+ NULL,
+ query_flags,
+ j->until,
+ current);
+ if (r < 0)
+ return r;
+ }
+
+ /* We'll return any packet we have for this. Typically all cache entries for the same key
+ * should come from the same packet anyway, hence it doesn't really matter which packet we
+ * return here, they should all resolve to the same anyway. */
+ if (!full_packet && j->full_packet)
+ full_packet = dns_packet_ref(j->full_packet);
}
if (found_rcode >= 0) {
dns_rcode_to_string(found_rcode),
dns_resource_key_to_string(key, key_str, sizeof(key_str)));
- *ret = NULL;
- *rcode = found_rcode;
- *authenticated = false;
+ if (ret_rcode)
+ *ret_rcode = found_rcode;
+ if (ret_answer)
+ *ret_answer = TAKE_PTR(answer);
+ if (ret_full_packet)
+ *ret_full_packet = TAKE_PTR(full_packet);
+ if (ret_query_flags)
+ *ret_query_flags = 0;
+ if (ret_dnssec_result)
+ *ret_dnssec_result = dnssec_result;
c->n_hit++;
return 1;
}
if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) {
- /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from
- * the lower-zone of a zone cut, but the DS RRs are on the upper zone. */
+ /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC
+ * RRs from the lower-zone of a zone cut, but the DS RRs are on the upper zone. */
log_debug("NSEC NODATA cache hit for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
- /* We only found an NSEC record that matches our name.
- * If it says the type doesn't exist report
- * NODATA. Otherwise report a cache miss. */
+ /* We only found an NSEC record that matches our name. If it says the type doesn't exist
+ * report NODATA. Otherwise report a cache miss. */
- *ret = NULL;
- *rcode = DNS_RCODE_SUCCESS;
- *authenticated = nsec->authenticated;
+ if (ret_rcode)
+ *ret_rcode = DNS_RCODE_SUCCESS;
+ if (ret_answer)
+ *ret_answer = TAKE_PTR(answer);
+ if (ret_full_packet)
+ *ret_full_packet = TAKE_PTR(full_packet);
+ if (ret_query_flags)
+ *ret_query_flags = nsec->query_flags;
+ if (ret_dnssec_result)
+ *ret_dnssec_result = nsec->dnssec_result;
if (!bitmap_isset(nsec->rr->nsec.types, key->type) &&
!bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) &&
if (n <= 0) {
c->n_hit++;
- *ret = NULL;
- *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS;
- *authenticated = have_authenticated && !have_non_authenticated;
- return 1;
- }
-
- answer = dns_answer_new(n);
- if (!answer)
- return -ENOMEM;
-
- if (clamp_ttl)
- current = now(clock_boottime_or_monotonic());
-
- LIST_FOREACH(by_key, j, first) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- if (!j->rr)
- continue;
-
- if (clamp_ttl) {
- rr = dns_resource_record_ref(j->rr);
+ if (ret_rcode)
+ *ret_rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS;
+ if (ret_answer)
+ *ret_answer = TAKE_PTR(answer);
+ if (ret_full_packet)
+ *ret_full_packet = TAKE_PTR(full_packet);
+ if (ret_query_flags)
+ *ret_query_flags =
+ ((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
+ ((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
+ if (ret_dnssec_result)
+ *ret_dnssec_result = dnssec_result;
- r = dns_resource_record_clamp_ttl(&rr, LESS_BY(j->until, current) / USEC_PER_SEC);
- if (r < 0)
- return r;
- }
-
- r = dns_answer_add(answer, rr ?: j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0);
- if (r < 0)
- return r;
+ return 1;
}
c->n_hit++;
- *ret = answer;
- *rcode = DNS_RCODE_SUCCESS;
- *authenticated = have_authenticated && !have_non_authenticated;
- answer = NULL;
+ if (ret_rcode)
+ *ret_rcode = DNS_RCODE_SUCCESS;
+ if (ret_answer)
+ *ret_answer = TAKE_PTR(answer);
+ if (ret_full_packet)
+ *ret_full_packet = TAKE_PTR(full_packet);
+ if (ret_query_flags)
+ *ret_query_flags =
+ ((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
+ ((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
+ if (ret_dnssec_result)
+ *ret_dnssec_result = dnssec_result;
return n;
+
+miss:
+ if (ret_rcode)
+ *ret_rcode = DNS_RCODE_SUCCESS;
+ if (ret_answer)
+ *ret_answer = NULL;
+ if (ret_full_packet)
+ *ret_full_packet = NULL;
+ if (ret_query_flags)
+ *ret_query_flags = 0;
+ if (ret_dnssec_result)
+ *ret_dnssec_result = _DNSSEC_RESULT_INVALID;
+
+ c->n_miss++;
+ return 0;
}
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) {
#include "list.h"
#include "prioq.h"
#include "resolve-util.h"
+#include "resolved-dns-dnssec.h"
#include "time-util.h"
typedef struct DnsCache {
void dns_cache_flush(DnsCache *c);
void dns_cache_prune(DnsCache *c);
-int dns_cache_put(DnsCache *c, DnsCacheMode cache_mode, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
-int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **answer, bool *authenticated);
+int dns_cache_put(
+ DnsCache *c,
+ DnsCacheMode cache_mode,
+ DnsResourceKey *key,
+ int rcode,
+ DnsAnswer *answer,
+ DnsPacket *full_packet,
+ uint64_t query_flags,
+ DnssecResult dnssec_result,
+ uint32_t nsec_ttl,
+ int owner_family,
+ const union in_addr_union *owner_address);
+
+int dns_cache_lookup(
+ DnsCache *c,
+ DnsResourceKey *key,
+ uint64_t query_flags,
+ int *ret_rcode,
+ DnsAnswer **ret_answer,
+ DnsPacket **ret_full_packet,
+ uint64_t *ret_query_flags,
+ DnssecResult *ret_dnssec_result);
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);
DNSSEC_INCOMPATIBLE_SERVER,
_DNSSEC_RESULT_MAX,
- _DNSSEC_RESULT_INVALID = -1
+ _DNSSEC_RESULT_INVALID = -EINVAL,
};
enum DnssecVerdict {
DNSSEC_INDETERMINATE,
_DNSSEC_VERDICT_MAX,
- _DNSSEC_VERDICT_INVALID = -1
+ _DNSSEC_VERDICT_INVALID = -EINVAL,
};
#define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2)
return 0;
}
+int dns_packet_dup(DnsPacket **ret, DnsPacket *p) {
+ DnsPacket *c;
+ int r;
+
+ assert(ret);
+ assert(p);
+
+ r = dns_packet_validate(p);
+ if (r < 0)
+ return r;
+
+ c = malloc(ALIGN(sizeof(DnsPacket)) + p->size);
+ if (!c)
+ return -ENOMEM;
+
+ *c = (DnsPacket) {
+ .n_ref = 1,
+ .protocol = p->protocol,
+ .size = p->size,
+ .rindex = DNS_PACKET_HEADER_SIZE,
+ .allocated = p->size,
+ .max_size = p->max_size,
+ .opt_start = (size_t) -1,
+ .opt_size = (size_t) -1,
+ };
+
+ memcpy(DNS_PACKET_DATA(c), DNS_PACKET_DATA(p), p->size);
+
+ *ret = c;
+ return 0;
+}
+
DnsPacket *dns_packet_ref(DnsPacket *p) {
if (!p)
return 0;
}
-int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) {
+int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed) {
DnsResourceRecord *rr;
DnsAnswerFlags flags;
int r;
r = dns_packet_append_rr(p, rr, flags, NULL, NULL);
if (r < 0)
return r;
+
+ if (completed)
+ (*completed)++;
}
return 0;
if (r < 0)
return r;
- *ret = unaligned_read_be16(d);
+ if (ret)
+ *ret = unaligned_read_be16(d);
return 0;
}
int dns_packet_read_name(
DnsPacket *p,
- char **_ret,
+ char **ret,
bool allow_compression,
- size_t *start) {
+ size_t *ret_start) {
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
size_t after_rindex = 0, jump_barrier;
- _cleanup_free_ char *ret = NULL;
+ _cleanup_free_ char *name = NULL;
size_t n = 0, allocated = 0;
bool first = true;
int r;
assert(p);
- assert(_ret);
+
INIT_REWINDER(rewinder, p);
jump_barrier = p->rindex;
if (r < 0)
return r;
- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+ if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
return -ENOMEM;
if (first)
first = false;
else
- ret[n++] = '.';
+ name[n++] = '.';
- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
if (r < 0)
return r;
return -EBADMSG;
}
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
+ if (!GREEDY_REALLOC(name, allocated, n + 1))
return -ENOMEM;
- ret[n] = 0;
+ name[n] = 0;
if (after_rindex != 0)
p->rindex= after_rindex;
- *_ret = TAKE_PTR(ret);
+ if (ret)
+ *ret = TAKE_PTR(name);
+ if (ret_start)
+ *ret_start = rewinder.saved_rindex;
- if (start)
- *start = rewinder.saved_rindex;
CANCEL_REWINDER(rewinder);
return 0;
return 0;
}
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
+int dns_packet_read_key(
+ DnsPacket *p,
+ DnsResourceKey **ret,
+ bool *ret_cache_flush,
+ size_t *ret_start) {
+
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
_cleanup_free_ char *name = NULL;
bool cache_flush = false;
uint16_t class, type;
- DnsResourceKey *key;
int r;
assert(p);
- assert(ret);
INIT_REWINDER(rewinder, p);
r = dns_packet_read_name(p, &name, true, NULL);
}
}
- key = dns_resource_key_new_consume(class, type, name);
- if (!key)
- return -ENOMEM;
+ if (ret) {
+ DnsResourceKey *key;
- name = NULL;
- *ret = key;
+ key = dns_resource_key_new_consume(class, type, name);
+ if (!key)
+ return -ENOMEM;
+
+ TAKE_PTR(name);
+ *ret = key;
+ }
if (ret_cache_flush)
*ret_cache_flush = cache_flush;
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
+ if (ret_start)
+ *ret_start = rewinder.saved_rindex;
+ CANCEL_REWINDER(rewinder);
return 0;
}
return m <= 9 && e <= 9 && (m > 0 || e == 0);
}
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
+int dns_packet_read_rr(
+ DnsPacket *p,
+ DnsResourceRecord **ret,
+ bool *ret_cache_flush,
+ size_t *ret_start) {
+
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
int r;
assert(p);
- assert(ret);
INIT_REWINDER(rewinder, p);
if (p->rindex != offset + rdlength)
return -EBADMSG;
- *ret = TAKE_PTR(rr);
-
+ if (ret)
+ *ret = TAKE_PTR(rr);
if (ret_cache_flush)
*ret_cache_flush = cache_flush;
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
+ if (ret_start)
+ *ret_start = rewinder.saved_rindex;
+ CANCEL_REWINDER(rewinder);
return 0;
}
for (i = 0; i < n; i++) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
bool cache_flush = false;
+ size_t start;
+
+ if (p->rindex == p->size) {
+ /* If we reached the end of the packet already, but there are still more RRs
+ * declared, then that's a corrupt packet. Let's accept the packet anyway, since it's
+ * apparently a common bug in routers. Let's however suppress OPT support in this
+ * case, so that we force the rest of the logic into lowest DNS baseline support. Or
+ * to say this differently: if the DNS server doesn't even get the RR counts right,
+ * it's highly unlikely it gets EDNS right. */
+ log_debug("More resource records declared in packet than included, suppressing OPT.");
+ bad_opt = true;
+ break;
+ }
- r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
+ r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
if (r < 0)
return r;
}
p->opt = dns_resource_record_ref(rr);
+ p->opt_start = start;
+ assert(p->rindex >= start);
+ p->opt_size = p->rindex - start;
} else {
- /* According to RFC 4795, section 2.9. only the RRs from the Answer section
- * shall be cached. Hence mark only those RRs as cacheable by default, but
- * not the ones from the Additional or Authority sections. */
- DnsAnswerFlags flags =
- (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
- (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0);
-
- r = dns_answer_add(answer, rr, p->ifindex, flags);
+ DnsAnswerFlags flags = 0;
+
+ if (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush)
+ flags |= DNS_ANSWER_SHARED_OWNER;
+
+ /* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be
+ * cached. Hence mark only those RRs as cacheable by default, but not the ones from
+ * the Additional or Authority sections. */
+ if (i < DNS_PACKET_ANCOUNT(p))
+ flags |= DNS_ANSWER_CACHEABLE|DNS_ANSWER_SECTION_ANSWER;
+ else if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p))
+ flags |= DNS_ANSWER_SECTION_AUTHORITY;
+ else
+ flags |= DNS_ANSWER_SECTION_ADDITIONAL;
+
+ r = dns_answer_add(answer, rr, p->ifindex, flags, NULL);
if (r < 0)
return r;
}
previous = dns_resource_record_ref(rr);
}
- if (bad_opt)
+ if (bad_opt) {
p->opt = dns_resource_record_unref(p->opt);
+ p->opt_start = p->opt_size = SIZE_MAX;
+ }
*ret_answer = TAKE_PTR(answer);
if (r < 0)
return r;
+ if (p->rindex < p->size) {
+ log_debug("Trailing garbage in packet, suppressing OPT.");
+ p->opt = dns_resource_record_unref(p->opt);
+ p->opt_start = p->opt_size = SIZE_MAX;
+ }
+
p->question = TAKE_PTR(question);
p->answer = TAKE_PTR(answer);
return dns_resource_key_equal(p->question->keys[0], key);
}
+int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size) {
+ assert(p);
+ assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
+
+ if (p->opt_start == (size_t) -1) /* No OPT section, nothing to patch */
+ return 0;
+
+ assert(p->opt_size != (size_t) -1);
+ assert(p->opt_size >= 5);
+
+ unaligned_write_be16(DNS_PACKET_DATA(p) + p->opt_start + 3, max_udp_size);
+ return 1;
+}
+
+static int patch_rr(DnsPacket *p, usec_t age) {
+ _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
+ size_t ttl_index;
+ uint32_t ttl;
+ uint16_t type, rdlength;
+ int r;
+
+ INIT_REWINDER(rewinder, p);
+
+ /* Patches the RR at the current rindex, subtracts the specified time from the TTL */
+
+ r = dns_packet_read_name(p, NULL, true, NULL);
+ if (r < 0)
+ return r;
+
+ r = dns_packet_read_uint16(p, &type, NULL);
+ if (r < 0)
+ return r;
+
+ r = dns_packet_read_uint16(p, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ r = dns_packet_read_uint32(p, &ttl, &ttl_index);
+ if (r < 0)
+ return r;
+
+ if (type != DNS_TYPE_OPT) { /* The TTL of the OPT field is not actually a TTL, skip it */
+ ttl = LESS_BY(ttl * USEC_PER_SEC, age) / USEC_PER_SEC;
+ unaligned_write_be32(DNS_PACKET_DATA(p) + ttl_index, ttl);
+ }
+
+ r = dns_packet_read_uint16(p, &rdlength, NULL);
+ if (r < 0)
+ return r;
+
+ r = dns_packet_read(p, rdlength, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ CANCEL_REWINDER(rewinder);
+ return 0;
+}
+
+int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp) {
+ _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {};
+ unsigned i, n;
+ usec_t k;
+ int r;
+
+ assert(p);
+ assert(timestamp_is_set(timestamp));
+
+ /* Adjusts all TTLs in the packet by subtracting the time difference between now and the specified timestamp */
+
+ k = now(clock_boottime_or_monotonic());
+ assert(k >= timestamp);
+ k -= timestamp;
+
+ INIT_REWINDER(rewinder, p);
+
+ dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
+
+ n = DNS_PACKET_QDCOUNT(p);
+ for (i = 0; i < n; i++) {
+ r = dns_packet_read_key(p, NULL, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ n = DNS_PACKET_RRCOUNT(p);
+ for (i = 0; i < n; i++) {
+
+ /* DNS servers suck, hence the RR count is in many servers off. If we reached the end
+ * prematurely, accept that, exit early */
+ if (p->rindex == p->size)
+ break;
+
+ r = patch_rr(p, k);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
assert(s);
DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
+bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b) {
+ return dns_packet_compare_func(a, b) == 0;
+}
+
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
[DNS_RCODE_SUCCESS] = "SUCCESS",
[DNS_RCODE_FORMERR] = "FORMERR",
DNS_PROTOCOL_MDNS,
DNS_PROTOCOL_LLMNR,
_DNS_PROTOCOL_MAX,
- _DNS_PROTOCOL_INVALID = -1
+ _DNS_PROTOCOL_INVALID = -EINVAL,
} DnsProtocol;
struct DnsPacketHeader {
bool canonical_form:1;
};
-static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
+static inline uint8_t* DNS_PACKET_DATA(const DnsPacket *p) {
if (_unlikely_(!p))
return NULL;
int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, size_t max_size);
int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled);
+int dns_packet_dup(DnsPacket **ret, DnsPacket *p);
+
void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
DnsPacket *dns_packet_ref(DnsPacket *p);
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start);
int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, bool include_rfc6975, int rcode, size_t *start);
int dns_packet_append_question(DnsPacket *p, DnsQuestion *q);
-int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a);
+int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed);
+
+int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size);
+int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp);
void dns_packet_truncate(DnsPacket *p, size_t sz);
int dns_packet_truncate_opt(DnsPacket *p);
int dns_packet_skip_question(DnsPacket *p);
int dns_packet_extract(DnsPacket *p);
+bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b);
+
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
enum {
DNS_RCODE_SUCCESS = 0,
extern const struct hash_ops dns_packet_hash_ops;
-static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
+static inline uint64_t SD_RESOLVED_FLAGS_MAKE(
+ DnsProtocol protocol,
+ int family,
+ bool authenticated,
+ bool confidential) {
uint64_t f;
/* Converts a protocol + family into a flags field as used in queries and responses */
- f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
+ f = (authenticated ? SD_RESOLVED_AUTHENTICATED : 0) |
+ (confidential ? SD_RESOLVED_CONFIDENTIAL : 0);
switch (protocol) {
case DNS_PROTOCOL_DNS:
return -ENOMEM;
*c = (DnsQueryCandidate) {
+ .n_ref = 1,
.query = q,
.scope = s,
};
}
}
-DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
-
+static DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
if (!c)
return NULL;
return mfree(c);
}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(DnsQueryCandidate, dns_query_candidate, dns_query_candidate_free);
+
static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
- DnsSearchDomain *next = NULL;
+ DnsSearchDomain *next;
assert(c);
return 1;
}
-static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
+static int dns_query_candidate_add_transaction(
+ DnsQueryCandidate *c,
+ DnsResourceKey *key,
+ DnsPacket *bypass) {
+
_cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL;
int r;
assert(c);
- assert(key);
- t = dns_scope_find_transaction(c->scope, key, true);
- if (!t) {
- r = dns_transaction_new(&t, c->scope, key);
+ if (key) {
+ /* Regular lookup with a resource key */
+ assert(!bypass);
+
+ t = dns_scope_find_transaction(c->scope, key, c->query->flags);
+ if (!t) {
+ r = dns_transaction_new(&t, c->scope, key, NULL, c->query->flags);
+ if (r < 0)
+ return r;
+ } else if (set_contains(c->transactions, t))
+ return 0;
+ } else {
+ /* "Bypass" lookup with a query packet */
+ assert(bypass);
+
+ r = dns_transaction_new(&t, c->scope, NULL, bypass, c->query->flags);
if (r < 0)
return r;
- } else if (set_contains(c->transactions, t))
- return 0;
+ }
r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
if (r < 0)
return r;
}
- t->clamp_ttl = c->query->clamp_ttl;
TAKE_PTR(t);
return 1;
}
static int dns_query_candidate_go(DnsQueryCandidate *c) {
+ _cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *keep_c = NULL;
DnsTransaction *t;
int r;
unsigned n = 0;
- bool notify = false;
assert(c);
- c->query->block_ready++;
+ /* Let's keep a reference to the query while we're operating */
+ keep_c = dns_query_candidate_ref(c);
/* Start the transactions that are not started yet */
SET_FOREACH(t, c->transactions) {
continue;
r = dns_transaction_go(t);
- if (r < 0) {
- c->query->block_ready--;
+ if (r < 0)
return r;
- }
- if (r == 0)
- /* A transaction is complete. */
- notify = true;
n++;
}
- c->query->block_ready--;
-
/* If there was nothing to start, then let's proceed immediately */
- if (n == 0 || notify)
+ if (n == 0)
dns_query_candidate_notify(c);
return 0;
dns_query_candidate_stop(c);
+ if (c->query->question_bypass) {
+ /* If this is a bypass query, then pass the original query packet along to the transaction */
+
+ assert(dns_question_size(c->query->question_bypass->question) == 1);
+
+ if (!dns_scope_good_key(c->scope, c->query->question_bypass->question->keys[0]))
+ return 0;
+
+ r = dns_query_candidate_add_transaction(c, NULL, c->query->question_bypass);
+ if (r < 0)
+ goto fail;
+
+ return 1;
+ }
+
question = dns_query_question_for_protocol(c->query, c->scope->protocol);
/* Create one transaction per question key */
if (!dns_scope_good_key(c->scope, qkey))
continue;
- r = dns_query_candidate_add_transaction(c, qkey);
+ r = dns_query_candidate_add_transaction(c, qkey, NULL);
if (r < 0)
goto fail;
dns_query_candidate_stop(c);
}
-static void dns_query_free_candidates(DnsQuery *q) {
+static void dns_query_unref_candidates(DnsQuery *q) {
assert(q);
while (q->candidates)
- dns_query_candidate_free(q->candidates);
+ dns_query_candidate_unref(q->candidates);
}
static void dns_query_reset_answer(DnsQuery *q) {
q->answer_rcode = 0;
q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
q->answer_errno = 0;
- q->answer_authenticated = false;
+ q->answer_query_flags = 0;
q->answer_protocol = _DNS_PROTOCOL_INVALID;
q->answer_family = AF_UNSPEC;
q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain);
+ q->answer_full_packet = dns_packet_unref(q->answer_full_packet);
}
DnsQuery *dns_query_free(DnsQuery *q) {
LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
}
- dns_query_free_candidates(q);
+ dns_query_unref_candidates(q);
dns_question_unref(q->question_idna);
dns_question_unref(q->question_utf8);
+ dns_packet_unref(q->question_bypass);
dns_query_reset_answer(q);
varlink_unref(q->varlink_request);
}
- dns_packet_unref(q->request_dns_packet);
- dns_packet_unref(q->reply_dns_packet);
+ if (q->request_packet)
+ hashmap_remove_value(q->stub_listener_extra ?
+ q->stub_listener_extra->queries_by_packet :
+ q->manager->stub_queries_by_packet,
+ q->request_packet,
+ q);
+
+ dns_packet_unref(q->request_packet);
+ dns_answer_unref(q->reply_answer);
+ dns_answer_unref(q->reply_authoritative);
+ dns_answer_unref(q->reply_additional);
- if (q->request_dns_stream) {
+ if (q->request_stream) {
/* Detach the stream from our query, in case something else keeps a reference to it. */
- (void) set_remove(q->request_dns_stream->queries, q);
- q->request_dns_stream = dns_stream_unref(q->request_dns_stream);
+ (void) set_remove(q->request_stream->queries, q);
+ q->request_stream = dns_stream_unref(q->request_stream);
}
free(q->request_address_string);
DnsQuery **ret,
DnsQuestion *question_utf8,
DnsQuestion *question_idna,
+ DnsPacket *question_bypass,
int ifindex,
uint64_t flags) {
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
+ char key_str[DNS_RESOURCE_KEY_STRING_MAX];
DnsResourceKey *key;
- bool good = false;
int r;
- char key_str[DNS_RESOURCE_KEY_STRING_MAX];
assert(m);
- if (dns_question_size(question_utf8) > 0) {
- r = dns_question_is_valid_for_query(question_utf8);
- if (r < 0)
- return r;
- if (r == 0)
+ if (question_bypass) {
+ /* It's either a "bypass" query, or a regular one, but can't be both. */
+ if (question_utf8 || question_idna)
return -EINVAL;
- good = true;
- }
+ } else {
+ bool good = false;
- /* If the IDNA and UTF8 questions are the same, merge their references */
- r = dns_question_is_equal(question_idna, question_utf8);
- if (r < 0)
- return r;
- if (r > 0)
- question_idna = question_utf8;
- else {
- if (dns_question_size(question_idna) > 0) {
- r = dns_question_is_valid_for_query(question_idna);
+ if (dns_question_size(question_utf8) > 0) {
+ r = dns_question_is_valid_for_query(question_utf8);
if (r < 0)
return r;
if (r == 0)
good = true;
}
- }
- if (!good) /* don't allow empty queries */
- return -EINVAL;
+ /* If the IDNA and UTF8 questions are the same, merge their references */
+ r = dns_question_is_equal(question_idna, question_utf8);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ question_idna = question_utf8;
+ else {
+ if (dns_question_size(question_idna) > 0) {
+ r = dns_question_is_valid_for_query(question_idna);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
+
+ good = true;
+ }
+ }
+
+ if (!good) /* don't allow empty queries */
+ return -EINVAL;
+ }
if (m->n_dns_queries >= QUERIES_MAX)
return -EBUSY;
*q = (DnsQuery) {
.question_utf8 = dns_question_ref(question_utf8),
.question_idna = dns_question_ref(question_idna),
+ .question_bypass = dns_packet_ref(question_bypass),
.ifindex = ifindex,
.flags = flags,
.answer_dnssec_result = _DNSSEC_RESULT_INVALID,
.answer_family = AF_UNSPEC,
};
- /* First dump UTF8 question */
- DNS_QUESTION_FOREACH(key, question_utf8)
- log_debug("Looking up RR for %s.",
- dns_resource_key_to_string(key, key_str, sizeof key_str));
-
- /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
- DNS_QUESTION_FOREACH(key, question_idna) {
- r = dns_question_contains(question_utf8, key);
- if (r < 0)
- return r;
- if (r > 0)
- continue;
+ if (question_bypass) {
+ DNS_QUESTION_FOREACH(key, question_bypass->question)
+ log_debug("Looking up bypass packet for %s.",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
+ } else {
+ /* First dump UTF8 question */
+ DNS_QUESTION_FOREACH(key, question_utf8)
+ log_debug("Looking up RR for %s.",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
+
+ /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
+ DNS_QUESTION_FOREACH(key, question_idna) {
+ r = dns_question_contains(question_utf8, key);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ continue;
- log_debug("Looking up IDNA RR for %s.",
- dns_resource_key_to_string(key, key_str, sizeof key_str));
+ log_debug("Looking up IDNA RR for %s.",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
+ }
}
LIST_PREPEND(queries, m->dns_queries, q);
if (ret)
*ret = q;
- q = NULL;
+ TAKE_PTR(q);
return 0;
}
}
static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
- _cleanup_(dns_query_candidate_freep) DnsQueryCandidate *c = NULL;
+ _cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *c = NULL;
int r;
assert(q);
DNS_TRANSACTION_NOT_FOUND))
return 0;
+ if (FLAGS_SET(q->flags, SD_RESOLVED_NO_SYNTHESIZE))
+ return 0;
+
r = dns_synthesize_answer(
q->manager,
- q->question_utf8,
+ q->question_bypass ? q->question_bypass->question : q->question_utf8,
q->ifindex,
&answer);
if (r == -ENXIO) {
q->answer_rcode = DNS_RCODE_NXDOMAIN;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
- q->answer_authenticated = true;
+ q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
*state = DNS_TRANSACTION_RCODE_FAILURE;
return 0;
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
- q->answer_authenticated = true;
+ q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
*state = DNS_TRANSACTION_SUCCESS;
assert(q);
- /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
- * data from /etc/hosts hence takes precedence over the network. */
+ /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is
+ * done. The data from /etc/hosts hence takes precedence over the network. */
+
+ if (FLAGS_SET(q->flags, SD_RESOLVED_NO_SYNTHESIZE))
+ return 0;
r = manager_etc_hosts_lookup(
q->manager,
- q->question_utf8,
+ q->question_bypass ? q->question_bypass->question : q->question_utf8,
&answer);
if (r <= 0)
return r;
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
- q->answer_authenticated = true;
+ q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
return 1;
}
static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
- bool has_authenticated = false, has_non_authenticated = false;
+ bool has_authenticated = false, has_non_authenticated = false, has_confidential = false, has_non_confidential = false;
DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
DnsTransaction *t;
int r;
q->answer = dns_answer_unref(q->answer);
q->answer_rcode = 0;
q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
- q->answer_authenticated = false;
+ q->answer_query_flags = 0;
q->answer_errno = c->error_code;
+ q->answer_full_packet = dns_packet_unref(q->answer_full_packet);
}
SET_FOREACH(t, c->transactions) {
switch (t->state) {
case DNS_TRANSACTION_SUCCESS: {
- /* We found a successfully reply, merge it into the answer */
- r = dns_answer_extend(&q->answer, t->answer);
- if (r < 0)
- goto fail;
+ /* We found a successful reply, merge it into the answer */
+
+ if (state == DNS_TRANSACTION_SUCCESS) {
+ r = dns_answer_extend(&q->answer, t->answer);
+ if (r < 0)
+ goto fail;
+
+ q->answer_query_flags |= dns_transaction_source_to_query_flags(t->answer_source);
+ } else {
+ /* Override non-successful previous answers */
+ dns_answer_unref(q->answer);
+ q->answer = dns_answer_ref(t->answer);
+
+ q->answer_query_flags = dns_transaction_source_to_query_flags(t->answer_source);
+ }
q->answer_rcode = t->answer_rcode;
q->answer_errno = 0;
- if (t->answer_authenticated) {
+ dns_packet_unref(q->answer_full_packet);
+ q->answer_full_packet = dns_packet_ref(t->received);
+
+ if (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED)) {
has_authenticated = true;
dnssec_result_authenticated = t->answer_dnssec_result;
} else {
dnssec_result_non_authenticated = t->answer_dnssec_result;
}
+ if (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
+ has_confidential = true;
+ else
+ has_non_confidential = true;
+
state = DNS_TRANSACTION_SUCCESS;
break;
}
continue;
/* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
- if (q->answer_authenticated && !t->answer_authenticated)
+ if (FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) &&
+ !FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
continue;
- q->answer = dns_answer_unref(q->answer);
+ dns_answer_unref(q->answer);
+ q->answer = dns_answer_ref(t->answer);
q->answer_rcode = t->answer_rcode;
q->answer_dnssec_result = t->answer_dnssec_result;
- q->answer_authenticated = t->answer_authenticated;
+ q->answer_query_flags = t->answer_query_flags | dns_transaction_source_to_query_flags(t->answer_source);
q->answer_errno = t->answer_errno;
+ dns_packet_unref(q->answer_full_packet);
+ q->answer_full_packet = dns_packet_ref(t->received);
state = t->state;
break;
}
if (state == DNS_TRANSACTION_SUCCESS) {
- q->answer_authenticated = has_authenticated && !has_non_authenticated;
- q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated;
+ SET_FLAG(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED, has_authenticated && !has_non_authenticated);
+ SET_FLAG(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, has_confidential && !has_non_confidential);
+ q->answer_dnssec_result = FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? dnssec_result_authenticated : dnssec_result_non_authenticated;
}
q->answer_protocol = c->scope->protocol;
dns_question_unref(q->question_utf8);
q->question_utf8 = TAKE_PTR(nq_utf8);
- dns_query_free_candidates(q);
+ dns_query_unref_candidates(q);
dns_query_reset_answer(q);
q->state = DNS_TRANSACTION_NULL;
if (q->flags & SD_RESOLVED_NO_CNAME)
return -ELOOP;
- if (!q->answer_authenticated)
+ if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
q->previous_redirect_unauthenticated = true;
+ if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
+ q->previous_redirect_non_confidential = true;
/* OK, let's actually follow the CNAME */
r = dns_query_cname_redirect(q, cname);
DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) {
assert(q);
+ if (q->question_bypass)
+ return q->question_bypass->question;
+
switch (protocol) {
case DNS_PROTOCOL_DNS:
/* Returns a somewhat useful human-readable lookup key string for this query */
+ if (q->question_bypass)
+ return dns_question_first_name(q->question_bypass->question);
+
if (q->request_address_string)
return q->request_address_string;
bool dns_query_fully_authenticated(DnsQuery *q) {
assert(q);
- return q->answer_authenticated && !q->previous_redirect_unauthenticated;
+ return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) && !q->previous_redirect_unauthenticated;
+}
+
+bool dns_query_fully_confidential(DnsQuery *q) {
+ assert(q);
+
+ return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) && !q->previous_redirect_non_confidential;
}
#include "resolved-dns-transaction.h"
struct DnsQueryCandidate {
+ unsigned n_ref;
+ int error_code;
+
DnsQuery *query;
DnsScope *scope;
DnsSearchDomain *search_domain;
- int error_code;
Set *transactions;
LIST_FIELDS(DnsQueryCandidate, candidates_by_query);
struct DnsQuery {
Manager *manager;
- /* When resolving a service, we first create a TXT+SRV query,
- * and then for the hostnames we discover auxiliary A+AAAA
- * queries. This pointer always points from the auxiliary
- * queries back to the TXT+SRV query. */
+ /* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
+ * auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
+ * TXT+SRV query. */
DnsQuery *auxiliary_for;
LIST_HEAD(DnsQuery, auxiliary_queries);
unsigned n_auxiliary_queries;
int auxiliary_result;
- /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note that even
- * on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names (in contrast to their
- * domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference between these two fields is mostly
- * relevant only for explicit *hostname* lookups as well as the domain suffixes of service lookups. */
+ /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note
+ * that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names
+ * (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference
+ * between these two fields is mostly relevant only for explicit *hostname* lookups as well as the
+ * domain suffixes of service lookups. */
DnsQuestion *question_idna;
DnsQuestion *question_utf8;
+ /* If this is not a question by ourselves, but a "bypass" request, we propagate the original packet
+ * here, and use that instead. */
+ DnsPacket *question_bypass;
+
uint64_t flags;
int ifindex;
- /* If true, the RR TTLs of the answer will be clamped by their current left validity in the cache */
- bool clamp_ttl;
-
DnsTransactionState state;
unsigned n_cname_redirects;
DnsAnswer *answer;
int answer_rcode;
DnssecResult answer_dnssec_result;
- bool answer_authenticated;
+ uint64_t answer_query_flags;
DnsProtocol answer_protocol;
int answer_family;
DnsSearchDomain *answer_search_domain;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
bool previous_redirect_unauthenticated;
+ bool previous_redirect_non_confidential;
+ DnsPacket *answer_full_packet;
/* Bus + Varlink client information */
sd_bus_message *bus_request;
char *request_address_string;
/* DNS stub information */
- DnsPacket *request_dns_packet;
- DnsStream *request_dns_stream;
- DnsPacket *reply_dns_packet;
+ DnsPacket *request_packet;
+ DnsStream *request_stream;
+ DnsAnswer *reply_answer;
+ DnsAnswer *reply_authoritative;
+ DnsAnswer *reply_additional;
DnsStubListenerExtra *stub_listener_extra;
/* Completion callback */
DNS_QUERY_RESTARTED,
};
-DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_free);
+DnsQueryCandidate* dns_query_candidate_ref(DnsQueryCandidate*);
+DnsQueryCandidate* dns_query_candidate_unref(DnsQueryCandidate*);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref);
void dns_query_candidate_notify(DnsQueryCandidate *c);
-int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags);
+int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, DnsPacket *question_bypass, int family, uint64_t flags);
DnsQuery *dns_query_free(DnsQuery *q);
int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
bool dns_query_fully_authenticated(DnsQuery *q);
+bool dns_query_fully_confidential(DnsQuery *q);
+
+static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
+ assert(q);
+
+ return SD_RESOLVED_FLAGS_MAKE(q->answer_protocol,
+ q->answer_family,
+ dns_query_fully_authenticated(q),
+ dns_query_fully_confidential(q)) |
+ (q->answer_query_flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC));
+}
return 1;
}
+bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
+
+ if (rr->key->class != DNS_CLASS_IN)
+ return false;
+
+ if (rr->key->type == DNS_TYPE_A)
+ return in4_addr_is_link_local(&rr->a.in_addr);
+
+ if (rr->key->type == DNS_TYPE_AAAA)
+ return IN6_IS_ADDR_LINKLOCAL(&rr->aaaa.in6_addr);
+
+ return false;
+}
+
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
DnsTxtItem *n;
int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl);
+bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr);
+
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i);
dns_scope_abort_transactions(s);
while (s->query_candidates)
- dns_query_candidate_free(s->query_candidates);
+ dns_query_candidate_unref(s->query_candidates);
hashmap_free(s->transactions_by_key);
return n;
}
-void dns_scope_next_dns_server(DnsScope *s) {
+void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current) {
assert(s);
if (s->protocol != DNS_PROTOCOL_DNS)
return;
+ /* Changes to the next DNS server in the list. If 'if_current' is passed will do so only if the
+ * current DNS server still matches it. */
+
if (s->link)
- link_next_dns_server(s->link);
+ link_next_dns_server(s->link, if_current);
else
- manager_next_dns_server(s->manager);
+ manager_next_dns_server(s->manager, if_current);
}
void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address);
}
-static DnsScopeMatch accept_link_local_reverse_lookups(const char *domain) {
+static DnsScopeMatch match_link_local_reverse_lookups(const char *domain) {
assert(domain);
if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0)
return _DNS_SCOPE_MATCH_INVALID;
}
+static DnsScopeMatch match_subnet_reverse_lookups(
+ DnsScope *s,
+ const char *domain,
+ bool exclude_own) {
+
+ union in_addr_union ia;
+ LinkAddress *a;
+ int f, r;
+
+ assert(s);
+ assert(domain);
+
+ /* Checks whether the specified domain is a reverse address domain (i.e. in the .in-addr.arpa or
+ * .ip6.arpa area), and if so, whether the address matches any of the local subnets of the link the
+ * scope is associated with. If so, our scope should consider itself relevant for any lookup in the
+ * domain, since it apparently refers to hosts on this link's subnet.
+ *
+ * If 'exclude_own' is true this will return DNS_SCOPE_NO for any IP addresses assigned locally. This
+ * is useful for LLMNR/mDNS as we never want to look up our own hostname on LLMNR/mDNS but always use
+ * the locally synthesized one. */
+
+ if (!s->link)
+ return _DNS_SCOPE_MATCH_INVALID; /* No link, hence no local addresses to check */
+
+ r = dns_name_address(domain, &f, &ia);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine whether '%s' is an address domain: %m", domain);
+ if (r <= 0)
+ return _DNS_SCOPE_MATCH_INVALID;
+
+ if (s->family != AF_UNSPEC && f != s->family)
+ return _DNS_SCOPE_MATCH_INVALID; /* Don't look for IPv4 addresses on LLMNR/mDNS over IPv6 and vice versa */
+
+ LIST_FOREACH(addresses, a, s->link->addresses) {
+
+ if (a->family != f)
+ continue;
+
+ /* Equals our own address? nah, let's not use this scope. The local synthesizer will pick it up for us. */
+ if (exclude_own &&
+ in_addr_equal(f, &a->in_addr, &ia) > 0)
+ return DNS_SCOPE_NO;
+
+ if (a->prefixlen == UCHAR_MAX) /* don't know subnet mask */
+ continue;
+
+ /* Check if the address is in the local subnet */
+ r = in_addr_prefix_covers(f, &a->in_addr, a->prefixlen, &ia);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine whether link address covers lookup address '%s': %m", domain);
+ if (r > 0)
+ /* Note that we only claim zero labels match. This is so that this is at the same
+ * priority a DNS scope with "." as routing domain is. */
+ return DNS_SCOPE_YES_BASE + 0;
+ }
+
+ return _DNS_SCOPE_MATCH_INVALID;
+}
+
DnsScopeMatch dns_scope_good_domain(
DnsScope *s,
int ifindex,
if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
return DNS_SCOPE_NO;
- if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
+ if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, false, false) & flags) == 0)
return DNS_SCOPE_NO;
/* Never resolve any loopback hostname or IP address via DNS, LLMNR or mDNS. Instead, always rely on
case DNS_PROTOCOL_DNS: {
bool has_search_domains = false;
+ DnsScopeMatch m;
int n_best = -1;
/* Never route things to scopes that lack DNS servers */
return DNS_SCOPE_YES_BASE + n_best;
}
- /* See if this scope is suitable as default route. */
- if (!dns_scope_is_default_route(s))
+ /* Exclude link-local IP ranges */
+ if (match_link_local_reverse_lookups(domain) >= DNS_SCOPE_YES_BASE ||
+ /* If networks use .local in their private setups, they are supposed to also add .local
+ * to their search domains, which we already checked above. Otherwise, we consider .local
+ * specific to mDNS and won't send such queries ordinary DNS servers. */
+ dns_name_endswith(domain, "local") > 0)
return DNS_SCOPE_NO;
- /* Exclude link-local IP ranges */
- if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
- dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
- dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
- dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
- dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
- /* If networks use .local in their private setups, they are supposed to also add .local to their search
- * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
- * send such queries ordinary DNS servers. */
- dns_name_endswith(domain, "local") == 0)
- return DNS_SCOPE_MAYBE;
+ /* If the IP address to look up matches the local subnet, then implicity synthesizes
+ * DNS_SCOPE_YES_BASE + 0 on this interface, i.e. preferably resolve IP addresses via the DNS
+ * server belonging to this interface. */
+ m = match_subnet_reverse_lookups(s, domain, false);
+ if (m >= 0)
+ return m;
- return DNS_SCOPE_NO;
+ /* If there was no match at all, then see if this scope is suitable as default route. */
+ if (!dns_scope_is_default_route(s))
+ return DNS_SCOPE_NO;
+
+ return DNS_SCOPE_MAYBE;
}
case DNS_PROTOCOL_MDNS: {
DnsScopeMatch m;
- m = accept_link_local_reverse_lookups(domain);
+ m = match_link_local_reverse_lookups(domain);
+ if (m >= 0)
+ return m;
+
+ m = match_subnet_reverse_lookups(s, domain, true);
if (m >= 0)
return m;
case DNS_PROTOCOL_LLMNR: {
DnsScopeMatch m;
- m = accept_link_local_reverse_lookups(domain);
+ m = match_link_local_reverse_lookups(domain);
+ if (m >= 0)
+ return m;
+
+ m = match_subnet_reverse_lookups(s, domain, true);
if (m >= 0)
return m;
assert(s);
assert(key);
- /* Check if it makes sense to resolve the specified key on
- * this scope. Note that this call assumes as fully qualified
- * name, i.e. the search suffixes already appended. */
+ /* Check if it makes sense to resolve the specified key on this scope. Note that this call assumes a
+ * fully qualified name, i.e. the search suffixes already appended. */
- if (key->class != DNS_CLASS_IN)
+ if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY))
return false;
if (s->protocol == DNS_PROTOCOL_DNS) {
return !dns_name_is_root(name);
}
- /* On mDNS and LLMNR, send A and AAAA queries only on the
- * respective scopes */
+ /* Never route DNSSEC RR queries to LLMNR/mDNS scopes */
+ if (dns_type_is_dnssec(key->type))
+ return false;
+
+ /* On mDNS and LLMNR, send A and AAAA queries only on the respective scopes */
key_family = dns_type_to_af(key->type);
if (key_family < 0)
DnsPacket **ret) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ unsigned n_answer = 0, n_soa = 0;
int r;
assert(s);
return r;
DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
- r = dns_packet_append_answer(p, answer);
+ r = dns_packet_append_answer(p, answer, &n_answer);
if (r < 0)
return r;
- DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer));
+ DNS_PACKET_HEADER(p)->ancount = htobe16(n_answer);
- r = dns_packet_append_answer(p, soa);
+ r = dns_packet_append_answer(p, soa, &n_soa);
if (r < 0)
return r;
- DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
+ DNS_PACKET_HEADER(p)->arcount = htobe16(n_soa);
*ret = TAKE_PTR(p);
}
}
-DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
- DnsTransaction *t;
+DnsTransaction *dns_scope_find_transaction(
+ DnsScope *scope,
+ DnsResourceKey *key,
+ uint64_t query_flags) {
+
+ DnsTransaction *first, *t;
assert(scope);
assert(key);
- /* Try to find an ongoing transaction that is a equal to the
- * specified question */
- t = hashmap_get(scope->transactions_by_key, key);
- if (!t)
- return NULL;
+ /* Iterate through the list of transactions with a matching key */
+ first = hashmap_get(scope->transactions_by_key, key);
+ LIST_FOREACH(transactions_by_key, t, first) {
+
+ /* These four flags must match exactly: we cannot use a validated response for a
+ * non-validating client, and we cannot use a non-validated response for a validating
+ * client. Similar, if the sources don't match things aren't usable either. */
+ if (((query_flags ^ t->query_flags) &
+ (SD_RESOLVED_NO_VALIDATE|
+ SD_RESOLVED_NO_ZONE|
+ SD_RESOLVED_NO_TRUST_ANCHOR|
+ SD_RESOLVED_NO_NETWORK)) != 0)
+ continue;
- /* Refuse reusing transactions that completed based on cached
- * data instead of a real packet, if that's requested. */
- if (!cache_ok &&
- IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
- t->answer_source != DNS_TRANSACTION_NETWORK)
- return NULL;
+ /* We can reuse a primary query if a regular one is requested, but not vice versa */
+ if ((query_flags & SD_RESOLVED_REQUIRE_PRIMARY) &&
+ !(t->query_flags & SD_RESOLVED_REQUIRE_PRIMARY))
+ continue;
+
+ /* Don't reuse a transaction that allowed caching when we got told not to use it */
+ if ((query_flags & SD_RESOLVED_NO_CACHE) &&
+ !(t->query_flags & SD_RESOLVED_NO_CACHE))
+ continue;
+
+ /* If we are are asked to clamp ttls an the existing transaction doesn't do it, we can't
+ * reuse */
+ if ((query_flags & SD_RESOLVED_CLAMP_TTL) &&
+ !(t->query_flags & SD_RESOLVED_CLAMP_TTL))
+ continue;
+
+ return t;
+ }
- return t;
+ return NULL;
}
static int dns_scope_make_conflict_packet(
return;
}
- if (manager_our_packet(scope->manager, p))
+ if (manager_packet_from_local_address(scope->manager, p))
return;
r = dns_packet_extract(p);
else
flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH;
- r = dns_answer_add(answer, i->rr, 0 , flags);
+ r = dns_answer_add(answer, i->rr, 0, flags, NULL);
if (r < 0)
return log_debug_errno(r, "Failed to add RR to announce: %m");
}
if (r < 0)
log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m");
- r = dns_answer_add(answer, rr, 0 , 0);
+ r = dns_answer_add(answer, rr, 0, 0, NULL);
if (r < 0)
return log_debug_errno(r, "Failed to add RR to announce: %m");
}
DNS_SCOPE_YES_BASE, /* Add the number of matching labels to this */
DNS_SCOPE_YES_END = DNS_SCOPE_YES_BASE + DNS_N_LABELS_MAX,
_DNS_SCOPE_MATCH_MAX,
- _DNS_SCOPE_MATCH_INVALID = -1
+ _DNS_SCOPE_MATCH_INVALID = -EINVAL,
} DnsScopeMatch;
struct DnsScope {
LIST_HEAD(DnsQueryCandidate, query_candidates);
- /* Note that we keep track of ongoing transactions in two
- * ways: once in a hashmap, indexed by the rr key, and once in
- * a linked list. We use the hashmap to quickly find
- * transactions we can reuse for a key. But note that there
- * might be multiple transactions for the same key (because
- * the zone probing can't reuse a transaction answered from
- * the zone or the cache), and the hashmap only tracks the
- * most recent entry. */
+ /* Note that we keep track of ongoing transactions in two ways: once in a hashmap, indexed by the rr
+ * key, and once in a linked list. We use the hashmap to quickly find transactions we can reuse for a
+ * key. But note that there might be multiple transactions for the same key (because the associated
+ * query flags might differ in incompatible ways: e.g. we may not reuse a non-validating transaction
+ * as validating. Hence we maintain a per-key list of transactions, which we iterate through to find
+ * one we can reuse with matching flags. */
Hashmap *transactions_by_key;
LIST_HEAD(DnsTransaction, transactions);
DnsServer *dns_scope_get_dns_server(DnsScope *s);
unsigned dns_scope_get_n_dns_servers(DnsScope *s);
-void dns_scope_next_dns_server(DnsScope *s);
+void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current);
int dns_scope_llmnr_membership(DnsScope *s, bool b);
int dns_scope_mdns_membership(DnsScope *s, bool b);
int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *answer, DnsAnswer *soa, bool tentative, DnsPacket **ret);
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p);
-DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok);
+DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, uint64_t query_flags);
int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr);
void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);
s->n_failed_tcp = 0;
s->n_failed_tls = 0;
s->packet_truncated = false;
+ s->packet_invalid = false;
s->verified_usec = 0;
/* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
- /* Even if we successfully receive a reply to a request announcing support for large packets,
- that does not mean we can necessarily receive large packets. */
+ /* Even if we successfully receive a reply to a request announcing support for large packets, that
+ * does not mean we can necessarily receive large packets. */
if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
dns_server_verified(s, level);
- /* Remember the size of the largest UDP packet we received from a server,
- we know that we can always announce support for packets with at least
- this size. */
+ /* Remember the size of the largest UDP packet we received from a server, we know that we can always
+ * announce support for packets with at least this size. */
if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size)
s->received_udp_packet_max = size;
}
assert(s);
assert(s->manager);
- if (s->possible_feature_level == level) {
- if (protocol == IPPROTO_UDP)
- s->n_failed_udp++;
- else if (protocol == IPPROTO_TCP) {
- if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level))
- s->n_failed_tls++;
- else
- s->n_failed_tcp++;
- }
+ if (s->possible_feature_level != level)
+ return;
+
+ if (protocol == IPPROTO_UDP)
+ s->n_failed_udp++;
+ else if (protocol == IPPROTO_TCP) {
+ if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level))
+ s->n_failed_tls++;
+ else
+ s->n_failed_tcp++;
}
}
log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
}
+void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
+ assert(s);
+
+ /* Invoked whenever we got a packet we couldn't parse at all */
+
+ if (s->possible_feature_level != level)
+ return;
+
+ s->packet_invalid = true;
+}
+
static bool dns_server_grace_period_expired(DnsServer *s) {
usec_t ts;
* work. Upgrade back to UDP again. */
log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
+
} else if (s->n_failed_tls > 0 &&
- DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
+ DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) &&
+ dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
/* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
* if we don't require DNS-over-TLS */
log_debug("Server doesn't support DNS-over-TLS, downgrading protocol...");
s->possible_feature_level--;
+
+ } else if (s->packet_invalid &&
+ s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
+ s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN) {
+
+ /* Downgrade from DO to EDNS0 + from EDNS0 to UDP, from TLS+DO to plain TLS. Or in
+ * other words, if we receive a packet we cannot parse jump to the next lower feature
+ * level that actually has an influence on the packet layout (and not just the
+ * transport). */
+
+ log_debug("Got invalid packet from server, downgrading protocol...");
+ s->possible_feature_level =
+ s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TLS_DO ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
+ DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_EDNS0 :
+ DNS_SERVER_FEATURE_LEVEL_UDP;
+
} else if (s->packet_bad_opt &&
- s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
+ DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(s->possible_feature_level) &&
+ dns_server_get_dnssec_mode(s) != DNSSEC_YES &&
+ dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
- /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below
- * EDNS0 levels. After all, some records generate different responses with and without OPT RR
- * in the request. Example:
- * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
+ /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to
+ * below EDNS0 levels. After all, some servers generate different responses with and
+ * without OPT RR in the request. Example:
+ *
+ * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html
+ *
+ * If we are in strict DNSSEC or DoT mode, we don't do this kind of downgrade
+ * however, as both modes imply EDNS0 to work (DNSSEC strictly requires it, and DoT
+ * only in our implementation). */
log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
log_level = LOG_NOTICE;
} else if (s->packet_rrsig_missing &&
- s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) {
+ DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
+ dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
- /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't
- * augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore,
- * after all some servers generate different replies depending if an OPT RR is in the query or
- * not. */
+ /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server
+ * doesn't augment responses with DNSSEC RRs. If so, let's better not ask the server
+ * for it anymore, after all some servers generate different replies depending if an
+ * OPT RR is in the query or not. If we are in strict DNSSEC mode, don't allow such
+ * downgrades however, since a DNSSEC feature level is a requirement for strict
+ * DNSSEC mode. */
log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
- s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
+ s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
+ DNS_SERVER_FEATURE_LEVEL_EDNS0;
} else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
- s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
+ DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
+ ((s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_DO) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
- /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
- * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
- * idea. We might downgrade all the way down to TCP this way.
+ /* We lost too many UDP packets in a row, and are on an UDP feature level. If the
+ * packets are lost, maybe the server cannot parse them, hence downgrading sounds
+ * like a good idea. We might downgrade all the way down to TCP this way.
*
* If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss
* might have many reasons, a broken DNSSEC implementation being only one reason. And if the
* user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */
log_debug("Lost too many UDP packets, downgrading feature level...");
- s->possible_feature_level--;
+ if (s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_DO) /* skip over TLS_PLAIN */
+ s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
+ else
+ s->possible_feature_level--;
} else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->packet_truncated &&
- s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
+ s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
+ DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
+ (!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
- /* We got too many TCP connection failures in a row, we had at least one truncated packet, and
- * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
- * data we hope to make the packet smaller, so that it still works via UDP given that TCP
- * appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't
- * go further down, since that's TCP, and TCP failed too often after all. */
+ /* We got too many TCP connection failures in a row, we had at least one truncated
+ * packet, and are on feature level above UDP. By downgrading things and getting rid
+ * of DNSSEC or EDNS0 data we hope to make the packet smaller, so that it still
+ * works via UDP given that TCP appears not to be a fallback. Note that if we are
+ * already at the lowest UDP level, we don't go further down, since that's TCP, and
+ * TCP failed too often after all. */
log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
- s->possible_feature_level--;
+
+ if (DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level))
+ s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; /* Go DNSSEC → EDNS0 */
+ else
+ s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; /* Go EDNS0 → UDP */
}
if (p != s->possible_feature_level) {
/* Returns whether the server supports DNSSEC according to what we know about it */
- if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
+ if (dns_server_get_dnssec_mode(server) == DNSSEC_YES) /* If strict DNSSEC mode is enabled, always assume DNSSEC mode is supported. */
+ return true;
+
+ if (!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(server->possible_feature_level))
return false;
if (server->packet_bad_opt)
return m->current_dns_server;
}
-void manager_next_dns_server(Manager *m) {
+void manager_next_dns_server(Manager *m, DnsServer *if_current) {
assert(m);
- /* If there's currently no DNS server set, then the next
- * manager_get_dns_server() will find one */
+ /* If the DNS server is already a different one than the one specified in 'if_current' don't do anything */
+ if (if_current && m->current_dns_server != if_current)
+ return;
+
+ /* If there's currently no DNS server set, then the next manager_get_dns_server() will find one */
if (!m->current_dns_server)
return;
- /* Change to the next one, but make sure to follow the linked
- * list only if the server is still linked. */
+ /* Change to the next one, but make sure to follow the linked list only if the server is still
+ * linked. */
if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
manager_set_dns_server(m, m->current_dns_server->servers_next);
return;
}
- /* If there was no next one, then start from the beginning of
- * the list */
+ /* If there was no next one, then start from the beginning of the list */
if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
manager_set_dns_server(m, m->fallback_dns_servers);
else
"\tFailed TCP attempts: %u\n"
"\tSeen truncated packet: %s\n"
"\tSeen OPT RR getting lost: %s\n"
- "\tSeen RRSIG RR missing: %s\n",
+ "\tSeen RRSIG RR missing: %s\n"
+ "\tSeen invalid packet: %s\n",
s->received_udp_packet_max,
s->n_failed_udp,
s->n_failed_tcp,
yes_no(s->packet_truncated),
yes_no(s->packet_bad_opt),
- yes_no(s->packet_rrsig_missing));
+ yes_no(s->packet_rrsig_missing),
+ yes_no(s->packet_invalid));
}
void dns_server_unref_stream(DnsServer *s) {
DNS_SERVER_FALLBACK,
DNS_SERVER_LINK,
_DNS_SERVER_TYPE_MAX,
- _DNS_SERVER_TYPE_INVALID = -1
+ _DNS_SERVER_TYPE_INVALID = -EINVAL,
} DnsServerType;
const char* dns_server_type_to_string(DnsServerType i) _const_;
DNS_SERVER_FEATURE_LEVEL_LARGE,
DNS_SERVER_FEATURE_LEVEL_TLS_DO,
_DNS_SERVER_FEATURE_LEVEL_MAX,
- _DNS_SERVER_FEATURE_LEVEL_INVALID = -1
+ _DNS_SERVER_FEATURE_LEVEL_INVALID = -EINVAL,
} DnsServerFeatureLevel;
#define DNS_SERVER_FEATURE_LEVEL_WORST 0
#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1)
+#define DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
#define DNS_SERVER_FEATURE_LEVEL_IS_TLS(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, DNS_SERVER_FEATURE_LEVEL_TLS_DO)
+#define DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_DO)
+#define DNS_SERVER_FEATURE_LEVEL_IS_UDP(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_UDP, DNS_SERVER_FEATURE_LEVEL_EDNS0, DNS_SERVER_FEATURE_LEVEL_DO, DNS_SERVER_FEATURE_LEVEL_LARGE)
const char* dns_server_feature_level_to_string(int i) _const_;
int dns_server_feature_level_from_string(const char *s) _pure_;
unsigned n_failed_tcp;
unsigned n_failed_tls;
- bool packet_truncated:1;
- bool packet_bad_opt:1;
- bool packet_rrsig_missing:1;
+ bool packet_truncated:1; /* Set when TC bit was set on reply */
+ bool packet_bad_opt:1; /* Set when OPT was missing or otherwise bad on reply */
+ bool packet_rrsig_missing:1; /* Set when RRSIG was missing */
+ bool packet_invalid:1; /* Set when we failed to parse a reply */
usec_t verified_usec;
usec_t features_grace_period_usec;
void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level);
+void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level);
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
DnsServer *manager_get_dns_server(Manager *m);
-void manager_next_dns_server(Manager *m);
+void manager_next_dns_server(Manager *m, DnsServer *if_current);
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);
DNS_STREAM_LLMNR_RECV, /* Incoming LLMNR TCP lookup */
DNS_STREAM_STUB, /* Incoming DNS stub connection */
_DNS_STREAM_TYPE_MAX,
- _DNS_STREAM_TYPE_INVALID = -1,
+ _DNS_STREAM_TYPE_INVALID = -EINVAL,
} DnsStreamType;
#define DNS_STREAM_WRITE_TLS_DATA 1
p->udp_event_source = sd_event_source_unref(p->udp_event_source);
p->tcp_event_source = sd_event_source_unref(p->tcp_event_source);
+ hashmap_free(p->queries_by_packet);
+
return mfree(p);
}
-static int dns_stub_make_reply_packet(
- DnsPacket **p,
- size_t max_size,
- DnsQuestion *q,
+uint16_t dns_stub_listener_extra_port(DnsStubListenerExtra *p) {
+ assert(p);
+
+ if (p->port > 0)
+ return p->port;
+
+ return 53;
+}
+
+static void stub_packet_hash_func(const DnsPacket *p, struct siphash *state) {
+ assert(p);
+
+ siphash24_compress(&p->protocol, sizeof(p->protocol), state);
+ siphash24_compress(&p->family, sizeof(p->family), state);
+ siphash24_compress(&p->sender, sizeof(p->sender), state);
+ siphash24_compress(&p->ipproto, sizeof(p->ipproto), state);
+ siphash24_compress(&p->sender_port, sizeof(p->sender_port), state);
+ siphash24_compress(DNS_PACKET_HEADER(p), sizeof(DnsPacketHeader), state);
+
+ /* We don't bother hashing the full packet here, just the header */
+}
+
+static int stub_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
+ int r;
+
+ r = CMP(x->protocol, y->protocol);
+ if (r != 0)
+ return r;
+
+ r = CMP(x->family, y->family);
+ if (r != 0)
+ return r;
+
+ r = memcmp(&x->sender, &y->sender, sizeof(x->sender));
+ if (r != 0)
+ return r;
+
+ r = CMP(x->ipproto, y->ipproto);
+ if (r != 0)
+ return r;
+
+ r = CMP(x->sender_port, y->sender_port);
+ if (r != 0)
+ return r;
+
+ return memcmp(DNS_PACKET_HEADER(x), DNS_PACKET_HEADER(y), sizeof(DnsPacketHeader));
+}
+
+DEFINE_HASH_OPS(stub_packet_hash_ops, DnsPacket, stub_packet_hash_func, stub_packet_compare_func);
+
+static int dns_stub_collect_answer_by_question(
+ DnsAnswer **reply,
DnsAnswer *answer,
- bool *ret_truncated) {
+ DnsQuestion *question,
+ bool with_rrsig) { /* Add RRSIG RR matching each RR */
- bool truncated = false;
- DnsResourceRecord *rr;
- unsigned c = 0;
+ DnsAnswerItem *item;
int r;
- assert(p);
+ assert(reply);
- /* Note that we don't bother with any additional RRs, as this is stub is for local lookups only, and hence
- * roundtrips aren't expensive. */
+ /* Copies all RRs from 'answer' into 'reply', if they match 'question'. */
- if (!*p) {
- r = dns_packet_new(p, DNS_PROTOCOL_DNS, 0, max_size);
- if (r < 0)
- return r;
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
+
+ if (question) {
+ bool match = false;
+
+ r = dns_question_matches_rr(question, item->rr, NULL);
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ match = true;
+ else {
+ r = dns_question_matches_cname_or_dname(question, item->rr, NULL);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ match = true;
+ }
+
+ if (!match)
+ continue;
+ }
- r = dns_packet_append_question(*p, q);
+ r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
if (r < 0)
return r;
- DNS_PACKET_HEADER(*p)->qdcount = htobe16(dns_question_size(q));
+ if (with_rrsig && item->rrsig) {
+ r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
+ if (r < 0)
+ return r;
+ }
}
- DNS_ANSWER_FOREACH(rr, answer) {
+ return 0;
+}
- r = dns_question_matches_rr(q, rr, NULL);
- if (r < 0)
- return r;
- if (r > 0)
- goto add;
+static int dns_stub_collect_answer_by_section(
+ DnsAnswer **reply,
+ DnsAnswer *answer,
+ DnsAnswerFlags section,
+ DnsAnswer *exclude1,
+ DnsAnswer *exclude2,
+ bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
- r = dns_question_matches_cname_or_dname(q, rr, NULL);
- if (r < 0)
- return r;
- if (r > 0)
- goto add;
+ DnsAnswerItem *item;
+ unsigned c = 0;
+ int r;
- continue;
- add:
- r = dns_packet_append_rr(*p, rr, 0, NULL, NULL);
- if (r == -EMSGSIZE) {
- truncated = true;
- break;
- }
+ assert(reply);
+
+ /* Copies all RRs from 'answer' into 'reply', if they originate from the specified section. Also,
+ * avoid any RRs listed in 'exclude'. */
+
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
+
+ if (dns_answer_contains(exclude1, item->rr) ||
+ dns_answer_contains(exclude2, item->rr))
+ continue;
+
+ if (!with_dnssec &&
+ dns_type_is_dnssec(item->rr->key->type))
+ continue;
+
+ if (((item->flags ^ section) & (DNS_ANSWER_SECTION_ANSWER|DNS_ANSWER_SECTION_AUTHORITY|DNS_ANSWER_SECTION_ADDITIONAL)) != 0)
+ continue;
+
+ r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
if (r < 0)
return r;
c++;
+
+ if (with_dnssec && item->rrsig) {
+ r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
+ if (r < 0)
+ return r;
+
+ c++;
+ }
}
+ return (int) c;
+}
+
+static int dns_stub_assign_sections(
+ DnsQuery *q,
+ DnsQuestion *question,
+ bool edns0_do) {
+
+ int r;
+
+ assert(q);
+ assert(question);
+
+ /* Let's assign the 'answer' and 'answer_auxiliary' RRs we collected to their respective sections in
+ * the reply datagram. We try to reproduce a section assignment similar to what the upstream DNS
+ * server responded to us. We use the DNS_ANSWER_SECTION_xyz flags to match things up, which is where
+ * the original upstream's packet section assignment is stored in the DnsAnswer object. Not all RRs
+ * in the 'answer' and 'answer_auxiliary' objects come with section information though (for example,
+ * because they were synthesized locally, and not from a DNS packet). To deal with that we extend the
+ * assignment logic a bit: anything from the 'answer' object that directly matches the original
+ * question is always put in the ANSWER section, regardless if it carries section info, or what that
+ * section info says. Then, anything from the 'answer' and 'answer_auxiliary' objects that is from
+ * the ANSWER or AUTHORITY sections, and wasn't already added to the ANSWER section is placed in the
+ * AUTHORITY section. Everything else from either object is added to the ADDITIONAL section. */
+
+ /* Include all RRs that directly answer the question in the answer section */
+ r = dns_stub_collect_answer_by_question(
+ &q->reply_answer,
+ q->answer,
+ question,
+ edns0_do);
+ if (r < 0)
+ return r;
+
+ /* Include all RRs that originate from the answer or authority sections, and aren't listed in the
+ * answer section, in the authority section */
+ r = dns_stub_collect_answer_by_section(
+ &q->reply_authoritative,
+ q->answer,
+ DNS_ANSWER_SECTION_ANSWER,
+ q->reply_answer, NULL,
+ edns0_do);
+ if (r < 0)
+ return r;
+
+ /* Include all RRs that originate from the answer or authority sections, and aren't listed in the
+ * answer section, in the authority section */
+ r = dns_stub_collect_answer_by_section(
+ &q->reply_authoritative,
+ q->answer,
+ DNS_ANSWER_SECTION_AUTHORITY,
+ q->reply_answer, NULL,
+ edns0_do);
+ if (r < 0)
+ return r;
+
+ /* Include all RRs that originate from the additional sections in the additional section (except if
+ * already listed in the other two sections). Also add all RRs with no section marking. */
+ r = dns_stub_collect_answer_by_section(
+ &q->reply_additional,
+ q->answer,
+ DNS_ANSWER_SECTION_ADDITIONAL,
+ q->reply_answer, q->reply_authoritative,
+ edns0_do);
+ if (r < 0)
+ return r;
+ r = dns_stub_collect_answer_by_section(
+ &q->reply_additional,
+ q->answer,
+ 0,
+ q->reply_answer, q->reply_authoritative,
+ edns0_do);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int dns_stub_make_reply_packet(
+ DnsPacket **ret,
+ size_t max_size,
+ DnsQuestion *q,
+ bool *ret_truncated) {
+
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ bool tc = false;
+ int r;
+
+ assert(ret);
+
+ r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, max_size);
+ if (r < 0)
+ return r;
+
+ r = dns_packet_append_question(p, q);
+ if (r == -EMSGSIZE)
+ tc = true;
+ else if (r < 0)
+ return r;
+
if (ret_truncated)
- *ret_truncated = truncated;
- else if (truncated)
+ *ret_truncated = tc;
+ else if (tc)
return -EMSGSIZE;
- DNS_PACKET_HEADER(*p)->ancount = htobe16(be16toh(DNS_PACKET_HEADER(*p)->ancount) + c);
+ DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
+ *ret = TAKE_PTR(p);
+ return 0;
+}
+
+static int dns_stub_add_reply_packet_body(
+ DnsPacket *p,
+ DnsAnswer *answer,
+ DnsAnswer *authoritative,
+ DnsAnswer *additional,
+ bool edns0_do, /* Client expects DNSSEC RRs? */
+ bool *truncated) {
+
+ unsigned n_answer = 0, n_authoritative = 0, n_additional = 0;
+ bool tc = false;
+ int r;
+
+ assert(p);
+
+ /* Add the three sections to the packet. If the answer section doesn't fit we'll signal that as
+ * truncation. If the authoritative section doesn't fit and we are in DNSSEC mode, also signal
+ * truncation. In all other cases where things don't fit don't signal truncation, as for those cases
+ * the dropped RRs should not be essential. */
+
+ r = dns_packet_append_answer(p, answer, &n_answer);
+ if (r == -EMSGSIZE)
+ tc = true;
+ else if (r < 0)
+ return r;
+ else {
+ r = dns_packet_append_answer(p, authoritative, &n_authoritative);
+ if (r == -EMSGSIZE) {
+ if (edns0_do)
+ tc = true;
+ } else if (r < 0)
+ return r;
+ else {
+ r = dns_packet_append_answer(p, additional, &n_additional);
+ if (r < 0 && r != -EMSGSIZE)
+ return r;
+ }
+ }
+
+ if (tc) {
+ if (!truncated)
+ return -EMSGSIZE;
+
+ *truncated = true;
+ }
+
+ DNS_PACKET_HEADER(p)->ancount = htobe16(n_answer);
+ DNS_PACKET_HEADER(p)->nscount = htobe16(n_authoritative);
+ DNS_PACKET_HEADER(p)->arcount = htobe16(n_additional);
return 0;
}
bool add_opt, /* add an OPT RR to this packet? */
bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */
bool ad, /* set the DNSSEC authenticated data bit? */
+ bool cd, /* set the DNSSEC checking disabled bit? */
uint16_t max_udp_size) { /* The maximum UDP datagram size to advertise to clients */
int r;
tc = true;
else if (r < 0)
return r;
-
} else {
/* If the client can't to EDNS0, don't do DO either */
edns0_do = false;
- /* If the client didn't do EDNS, clamp the rcode to 4 bit */
+ /* If we don't do EDNS, clamp the rcode to 4 bit */
if (rcode > 0xF)
rcode = DNS_RCODE_SERVFAIL;
}
- /* Don't set the AD bit unless DO is on, too */
+ /* Don't set the CD bit unless DO is on, too */
if (!edns0_do)
- ad = false;
+ cd = false;
+
+ /* Note that we allow the AD bit to be set even if client didn't signal DO, as per RFC 6840, section
+ * 5.7 */
DNS_PACKET_HEADER(p)->id = id;
1 /* rd */,
1 /* ra */,
ad /* ad */,
- 0 /* cd */,
+ cd /* cd */,
rcode));
return 0;
return 0;
}
+static int dns_stub_send_reply(
+ DnsQuery *q,
+ int rcode) {
+
+ _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
+ bool truncated, edns0_do;
+ int r;
+
+ assert(q);
+
+ /* Reply with DNSSEC DO set? Only if client supports it; and we did any DNSSEC verification
+ * ourselves, or consider the data fully authenticated because we generated it locally, or
+ * the client set cd */
+ edns0_do =
+ DNS_PACKET_DO(q->request_packet) &&
+ (q->answer_dnssec_result >= 0 || /* we did proper DNSSEC validation … */
+ dns_query_fully_authenticated(q) || /* … or we considered it authentic otherwise … */
+ DNS_PACKET_CD(q->request_packet)); /* … or client set CD */
+
+ r = dns_stub_assign_sections(
+ q,
+ q->request_packet->question,
+ edns0_do);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to assign sections: %m");
+
+ r = dns_stub_make_reply_packet(
+ &reply,
+ DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_packet),
+ q->request_packet->question,
+ &truncated);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to build reply packet: %m");
+
+ r = dns_stub_add_reply_packet_body(
+ reply,
+ q->reply_answer,
+ q->reply_authoritative,
+ q->reply_additional,
+ edns0_do,
+ &truncated);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to append reply packet body: %m");
+
+ r = dns_stub_finish_reply_packet(
+ reply,
+ DNS_PACKET_ID(q->request_packet),
+ rcode,
+ truncated,
+ !!q->request_packet->opt,
+ edns0_do,
+ DNS_PACKET_AD(q->request_packet) && dns_query_fully_authenticated(q),
+ DNS_PACKET_CD(q->request_packet),
+ q->stub_listener_extra ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to build failure packet: %m");
+
+ return dns_stub_send(q->manager, q->stub_listener_extra, q->request_stream, q->request_packet, reply);
+}
+
static int dns_stub_send_failure(
Manager *m,
DnsStubListenerExtra *l,
bool authenticated) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
+ bool truncated;
int r;
assert(m);
assert(p);
- r = dns_stub_make_reply_packet(&reply, DNS_PACKET_PAYLOAD_SIZE_MAX(p), p->question, NULL, NULL);
+ r = dns_stub_make_reply_packet(
+ &reply,
+ DNS_PACKET_PAYLOAD_SIZE_MAX(p),
+ p->question,
+ &truncated);
if (r < 0)
return log_debug_errno(r, "Failed to make failure packet: %m");
reply,
DNS_PACKET_ID(p),
rcode,
- /* truncated = */ false,
+ truncated,
!!p->opt,
DNS_PACKET_DO(p),
- authenticated,
+ DNS_PACKET_AD(p) && authenticated,
+ DNS_PACKET_CD(p),
l ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
if (r < 0)
return log_debug_errno(r, "Failed to build failure packet: %m");
return dns_stub_send(m, l, s, p, reply);
}
+static int dns_stub_patch_bypass_reply_packet(
+ DnsPacket **ret, /* Where to place the patched packet */
+ DnsPacket *original, /* The packet to patch */
+ DnsPacket *request) { /* The packet the patched packet shall look like a reply to */
+ _cleanup_(dns_packet_unrefp) DnsPacket *c = NULL;
+ int r;
+
+ assert(ret);
+ assert(original);
+ assert(request);
+
+ r = dns_packet_dup(&c, original);
+ if (r < 0)
+ return r;
+
+ /* Extract the packet, so that we know where the OPT field is */
+ r = dns_packet_extract(c);
+ if (r < 0)
+ return r;
+
+ /* Copy over the original client request ID, so that we can make the upstream query look like our own reply. */
+ DNS_PACKET_HEADER(c)->id = DNS_PACKET_HEADER(request)->id;
+
+ /* Patch in our own maximum datagram size, if EDNS0 was on */
+ r = dns_packet_patch_max_udp_size(c, ADVERTISE_DATAGRAM_SIZE_MAX);
+ if (r < 0)
+ return r;
+
+ /* Lower all TTLs by the time passed since we received the datagram. */
+ if (timestamp_is_set(original->timestamp)) {
+ r = dns_packet_patch_ttls(c, original->timestamp);
+ if (r < 0)
+ return r;
+ }
+
+ /* Our upstream connection might have supported larger DNS requests than our downstream one, hence
+ * set the TC bit if our reply is larger than what the client supports, and truncate. */
+ if (c->size > DNS_PACKET_PAYLOAD_SIZE_MAX(request)) {
+ log_debug("Artificially truncating stub response, as advertised size of client is smaller than upstream one.");
+ dns_packet_truncate(c, DNS_PACKET_PAYLOAD_SIZE_MAX(request));
+ DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) | DNS_PACKET_FLAG_TC);
+ }
+
+ *ret = TAKE_PTR(c);
+ return 0;
+}
+
static void dns_stub_query_complete(DnsQuery *q) {
int r;
assert(q);
- assert(q->request_dns_packet);
+ assert(q->request_packet);
- switch (q->state) {
+ if (q->question_bypass) {
+ /* This is a bypass reply. If so, let's propagate the upstream packet, if we have it and it
+ * is regular DNS. (We can't do this if the upstream packet is LLMNR or mDNS, since the
+ * packets are not 100% compatible.) */
- case DNS_TRANSACTION_SUCCESS: {
- bool truncated;
+ if (q->answer_full_packet &&
+ q->answer_full_packet->protocol == DNS_PROTOCOL_DNS) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
- r = dns_stub_make_reply_packet(&q->reply_dns_packet, DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_dns_packet), q->question_idna, q->answer, &truncated);
- if (r < 0) {
- log_debug_errno(r, "Failed to build reply packet: %m");
- break;
+ r = dns_stub_patch_bypass_reply_packet(&reply, q->answer_full_packet, q->request_packet);
+ if (r < 0)
+ log_debug_errno(r, "Failed to patch bypass reply packet: %m");
+ else
+ (void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_stream, q->request_packet, reply);
+
+ dns_query_free(q);
+ return;
}
+ }
- if (!truncated) {
+ switch (q->state) {
+
+ case DNS_TRANSACTION_SUCCESS:
+ /* Follow CNAMEs, and accumulate answers. Except if DNSSEC is requested, then let the client do that. */
+ if (!DNS_PACKET_DO(q->request_packet)) {
r = dns_query_process_cname(q);
- if (r == -ELOOP) {
- (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
+ if (r == -ELOOP) { /* CNAME loop */
+ (void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
break;
}
if (r < 0) {
return;
}
- r = dns_stub_finish_reply_packet(
- q->reply_dns_packet,
- DNS_PACKET_ID(q->request_dns_packet),
- q->answer_rcode,
- truncated,
- !!q->request_dns_packet->opt,
- DNS_PACKET_DO(q->request_dns_packet),
- dns_query_fully_authenticated(q),
- q->stub_listener_extra ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
- if (r < 0) {
- log_debug_errno(r, "Failed to finish reply packet: %m");
- break;
- }
-
- (void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet);
+ (void) dns_stub_send_reply(q, q->answer_rcode);
break;
- }
case DNS_TRANSACTION_RCODE_FAILURE:
- (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q));
+ (void) dns_stub_send_reply(q, q->answer_rcode);
break;
case DNS_TRANSACTION_NOT_FOUND:
- (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q));
+ (void) dns_stub_send_reply(q, DNS_RCODE_NXDOMAIN);
break;
case DNS_TRANSACTION_TIMEOUT:
case DNS_TRANSACTION_NO_TRUST_ANCHOR:
case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
case DNS_TRANSACTION_NETWORK_DOWN:
- (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
+ case DNS_TRANSACTION_NO_SOURCE:
+ case DNS_TRANSACTION_STUB_LOOP:
+ (void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
break;
case DNS_TRANSACTION_NULL:
static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStream *s, DnsPacket *p) {
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
+ Hashmap **queries_by_packet;
+ DnsQuery *existing;
int r;
assert(m);
return;
}
+ if (manager_packet_from_our_transaction(m, p)) {
+ log_debug("Got our own packet looped back, ignoring.");
+ return;
+ }
+
+ queries_by_packet = l ? &l->queries_by_packet : &m->stub_queries_by_packet;
+ existing = hashmap_get(*queries_by_packet, p);
+ if (existing && dns_packet_equal(existing->request_packet, p)) {
+ log_debug("Got repeat packet from client, ignoring.");
+ return;
+ }
+
r = dns_packet_extract(p);
if (r < 0) {
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
if (dns_type_is_obsolete(p->question->keys[0]->type)) {
log_debug("Got message with obsolete key type, refusing.");
- dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false);
return;
}
if (dns_type_is_zone_transer(p->question->keys[0]->type)) {
log_debug("Got request for zone transfer, refusing.");
- dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false);
return;
}
return;
}
- if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
- log_debug("Got request with DNSSEC CD bit set, refusing.");
- dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
+ r = hashmap_ensure_allocated(queries_by_packet, &stub_packet_hash_ops);
+ if (r < 0) {
+ log_oom();
return;
}
- r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH);
+ if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
+ log_debug("Got request with DNSSEC checking disabled, enabling bypass logic.");
+
+ r = dns_query_new(m, &q, NULL, NULL, p, 0,
+ SD_RESOLVED_PROTOCOLS_ALL|
+ SD_RESOLVED_NO_CNAME|
+ SD_RESOLVED_NO_SEARCH|
+ SD_RESOLVED_NO_VALIDATE|
+ SD_RESOLVED_REQUIRE_PRIMARY|
+ SD_RESOLVED_CLAMP_TTL);
+ } else
+ r = dns_query_new(m, &q, p->question, p->question, NULL, 0,
+ SD_RESOLVED_PROTOCOLS_ALL|
+ SD_RESOLVED_NO_SEARCH|
+ (DNS_PACKET_DO(p) ? SD_RESOLVED_NO_CNAME|SD_RESOLVED_REQUIRE_PRIMARY : 0)|
+ SD_RESOLVED_CLAMP_TTL);
if (r < 0) {
log_error_errno(r, "Failed to generate query object: %m");
dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false);
return;
}
- /* Request that the TTL is corrected by the cached time for this lookup, so that we return vaguely useful TTLs */
- q->clamp_ttl = true;
-
- q->request_dns_packet = dns_packet_ref(p);
- q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */
+ q->request_packet = dns_packet_ref(p);
+ q->request_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */
q->stub_listener_extra = l;
q->complete = dns_stub_query_complete;
assert(r > 0);
}
+ /* Add the query to the hash table we use to determine repeat packets now. We don't care about
+ * failures here, since in the worst case we'll not recognize duplicate incoming requests, which
+ * isn't particularly bad. */
+ (void) hashmap_put(*queries_by_packet, q->request_packet, q);
+
r = dns_query_go(q);
if (r < 0) {
log_error_errno(r, "Failed to start query: %m");
if (l->family == AF_INET)
sa = (union sockaddr_union) {
.in.sin_family = l->family,
- .in.sin_port = htobe16(l->port != 0 ? l->port : 53U),
+ .in.sin_port = htobe16(dns_stub_listener_extra_port(l)),
.in.sin_addr = l->address.in,
};
else
sa = (union sockaddr_union) {
.in6.sin6_family = l->family,
- .in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U),
+ .in6.sin6_port = htobe16(dns_stub_listener_extra_port(l)),
.in6.sin6_addr = l->address.in6,
};
DNS_STUB_LISTENER_TCP = 1 << 1,
DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP,
_DNS_STUB_LISTENER_MODE_MAX,
- _DNS_STUB_LISTENER_MODE_INVALID = -1
+ _DNS_STUB_LISTENER_MODE_INVALID = -EINVAL,
} DnsStubListenerMode;
#include "resolved-manager.h"
sd_event_source *udp_event_source;
sd_event_source *tcp_event_source;
+
+ Hashmap *queries_by_packet;
};
extern const struct hash_ops dns_stub_listener_extra_hash_ops;
int dns_stub_listener_extra_new(Manager *m, DnsStubListenerExtra **ret);
DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p);
+uint16_t dns_stub_listener_extra_port(DnsStubListenerExtra *p);
void manager_dns_stub_stop(Manager *m);
int manager_dns_stub_start(Manager *m);
rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
- r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
}
rr->aaaa.in6_addr = in6addr_loopback;
- r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
}
if (!rr->ptr.name)
return -ENOMEM;
- return dns_answer_add(*answer, rr, ifindex, flags);
+ return dns_answer_add(*answer, rr, ifindex, flags, NULL);
}
static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
if (r < 0)
return r;
- r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
t->answer_rcode = 0;
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
- t->answer_authenticated = false;
+ t->answer_query_flags = 0;
t->answer_nsec_ttl = (uint32_t) -1;
t->answer_errno = 0;
}
}
}
-static void dns_transaction_close_connection(DnsTransaction *t) {
+static void dns_transaction_close_connection(
+ DnsTransaction *t,
+ bool use_graveyard) { /* Set use_graveyard = false when you know the connection is already
+ * dead, for example because you got a connection error back from the
+ * kernel. In that case there's no point in keeping the fd around,
+ * hence don't. */
+ int r;
+
assert(t);
if (t->stream) {
}
t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
+
+ /* If we have an UDP socket where we sent a packet, but never received one, then add it to the socket
+ * graveyard, instead of closing it right away. That way it will stick around for a moment longer,
+ * and the reply we might still get from the server will be eaten up instead of resulting in an ICMP
+ * port unreachable error message. */
+
+ if (use_graveyard && t->dns_udp_fd >= 0 && t->sent && !t->received) {
+ r = manager_add_socket_to_graveyard(t->scope->manager, t->dns_udp_fd);
+ if (r < 0)
+ log_debug_errno(r, "Failed to add UDP socket to graveyard, closing immediately: %m");
+ else
+ TAKE_FD(t->dns_udp_fd);
+ }
+
t->dns_udp_fd = safe_close(t->dns_udp_fd);
}
log_debug("Freeing transaction %" PRIu16 ".", t->id);
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
dns_transaction_stop_timeout(t);
dns_packet_unref(t->sent);
dns_server_unref(t->server);
if (t->scope) {
- hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
- LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
+ if (t->key) {
+ DnsTransaction *first;
+
+ first = hashmap_get(t->scope->transactions_by_key, t->key);
+ LIST_REMOVE(transactions_by_key, first, t);
+ if (first)
+ hashmap_replace(t->scope->transactions_by_key, first->key, first);
+ else
+ hashmap_remove(t->scope->transactions_by_key, t->key);
+ }
- if (t->id != 0)
- hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
+ LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
}
+ if (t->id != 0)
+ hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
+
while ((c = set_steal_first(t->notify_query_candidates)))
set_remove(c->transactions, t);
set_free(t->notify_query_candidates);
dns_answer_unref(t->validated_keys);
dns_resource_key_unref(t->key);
+ dns_packet_unref(t->bypass);
return mfree(t);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
-bool dns_transaction_gc(DnsTransaction *t) {
+DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
assert(t);
+ /* Returns !NULL if we can't gc yet. */
+
if (t->block_gc > 0)
- return true;
+ return t;
if (set_isempty(t->notify_query_candidates) &&
set_isempty(t->notify_query_candidates_done) &&
set_isempty(t->notify_zone_items) &&
set_isempty(t->notify_zone_items_done) &&
set_isempty(t->notify_transactions) &&
- set_isempty(t->notify_transactions_done)) {
- dns_transaction_free(t);
- return false;
- }
+ set_isempty(t->notify_transactions_done))
+ return dns_transaction_free(t);
- return true;
+ return t;
}
static uint16_t pick_new_id(Manager *m) {
return new_id;
}
-int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
- _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
- int r;
-
- assert(ret);
- assert(s);
- assert(key);
+static int key_ok(
+ DnsScope *scope,
+ DnsResourceKey *key) {
/* Don't allow looking up invalid or pseudo RRs */
if (!dns_type_is_valid_query(key->type))
if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY))
return -EOPNOTSUPP;
+ /* Don't allows DNSSEC RRs to be looked up via LLMNR/mDNS. They don't really make sense
+ * there, and it speeds up our queries if we refuse this early */
+ if (scope->protocol != DNS_PROTOCOL_DNS &&
+ dns_type_is_dnssec(key->type))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+int dns_transaction_new(
+ DnsTransaction **ret,
+ DnsScope *s,
+ DnsResourceKey *key,
+ DnsPacket *bypass,
+ uint64_t query_flags) {
+
+ _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
+ int r;
+
+ assert(ret);
+ assert(s);
+
+ if (key) {
+ assert(!bypass);
+
+ r = key_ok(s, key);
+ if (r < 0)
+ return r;
+ } else {
+ DnsResourceKey *qk;
+ assert(bypass);
+
+ r = dns_packet_validate_query(bypass);
+ if (r < 0)
+ return r;
+
+ DNS_QUESTION_FOREACH(qk, bypass->question) {
+ r = key_ok(s, qk);
+ if (r < 0)
+ return r;
+ }
+ }
+
if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX)
return -EBUSY;
if (r < 0)
return r;
- r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
+ if (key) {
+ r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
+ if (r < 0)
+ return r;
+ }
t = new(DnsTransaction, 1);
if (!t)
.answer_dnssec_result = _DNSSEC_RESULT_INVALID,
.answer_nsec_ttl = (uint32_t) -1,
.key = dns_resource_key_ref(key),
+ .query_flags = query_flags,
+ .bypass = dns_packet_ref(bypass),
.current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID,
.clamp_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID,
.id = pick_new_id(s->manager),
return r;
}
- r = hashmap_replace(s->transactions_by_key, t->key, t);
- if (r < 0) {
- hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
- return r;
+ if (t->key) {
+ DnsTransaction *first;
+
+ first = hashmap_get(s->transactions_by_key, t->key);
+ LIST_PREPEND(transactions_by_key, first, t);
+
+ r = hashmap_replace(s->transactions_by_key, first->key, first);
+ if (r < 0) {
+ LIST_REMOVE(transactions_by_key, first, t);
+ return r;
+ }
}
LIST_PREPEND(transactions_by_scope, s->transactions, t);
if (ret)
*ret = t;
- t = NULL;
-
+ TAKE_PTR(t);
return 0;
}
assert(t);
assert(p);
+ assert(t->scope->protocol == DNS_PROTOCOL_LLMNR);
- if (manager_our_packet(t->scope->manager, p) != 0)
+ if (manager_packet_from_local_address(t->scope->manager, p) != 0)
return;
(void) in_addr_to_string(p->family, &p->sender, &pretty);
log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
t->id,
- dns_resource_key_to_string(t->key, key_str, sizeof key_str),
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
dns_protocol_to_string(t->scope->protocol),
t->scope->link ? t->scope->link->ifname : "*",
af_to_name_short(t->scope->family),
assert(!DNS_TRANSACTION_IS_LIVE(state));
if (state == DNS_TRANSACTION_DNSSEC_FAILED) {
- dns_resource_key_to_string(t->key, key_str, sizeof key_str);
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str);
log_struct(LOG_NOTICE,
"MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR,
else
st = dns_transaction_state_to_string(state);
- log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
+ log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s; %s).",
+ t->bypass ? "Bypass" : "Regular",
t->id,
- dns_resource_key_to_string(t->key, key_str, sizeof key_str),
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
dns_protocol_to_string(t->scope->protocol),
t->scope->link ? t->scope->link->ifname : "*",
af_to_name_short(t->scope->family),
st,
t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
- t->answer_authenticated ? "authenticated" : "unsigned");
+ FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) ? "not validated" :
+ (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unsigned"),
+ FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential");
t->state = state;
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
dns_transaction_stop_timeout(t);
/* Notify all queries that are interested, but make sure the
assert(t);
- log_debug("Retrying transaction %" PRIu16 ".", t->id);
+ /* Retries the transaction as it is, possibly on a different server */
+
+ if (next_server)
+ log_debug("Retrying transaction %" PRIu16 ", after switching servers.", t->id);
+ else
+ log_debug("Retrying transaction %" PRIu16 ".", t->id);
/* Before we try again, switch to a new server. */
if (next_server)
- dns_scope_next_dns_server(t->scope);
+ dns_scope_next_dns_server(t->scope, t->server);
r = dns_transaction_go(t);
if (r < 0)
dns_transaction_complete_errno(t, r);
}
+static bool dns_transaction_limited_retry(DnsTransaction *t) {
+ assert(t);
+
+ /* If we haven't tried all different servers yet, let's try again with a different server */
+
+ if (t->n_picked_servers >= dns_scope_get_n_dns_servers(t->scope))
+ return false;
+
+ dns_transaction_retry(t, /* next_server= */ true);
+ return true;
+}
+
static int dns_transaction_maybe_restart(DnsTransaction *t) {
int r;
assert(t);
- /* Returns > 0 if the transaction was restarted, 0 if not */
+ /* Restarts the transaction, under a new ID if the feature level of the server changed since we first
+ * tried, without changing DNS server. Returns > 0 if the transaction was restarted, 0 if not. */
if (!t->server)
return 0;
static void on_transaction_stream_error(DnsTransaction *t, int error) {
assert(t);
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
if (ERRNO_IS_DISCONNECT(error)) {
if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
dns_transaction_complete_errno(t, error);
}
-static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
+static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsStream *s, DnsPacket *p) {
+ bool encrypted;
+
assert(t);
+ assert(s);
assert(p);
- dns_transaction_close_connection(t);
+ encrypted = s->encrypted;
+
+ dns_transaction_close_connection(t, true);
if (dns_packet_validate_reply(p) <= 0) {
log_debug("Invalid TCP reply packet.");
dns_scope_check_conflicts(t->scope, p);
t->block_gc++;
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, encrypted);
t->block_gc--;
/* If the response wasn't useful, then complete the transition
assert(s);
/* Take ownership of packet to be able to receive new packets */
- p = dns_stream_take_read_packet(s);
- assert(p);
+ assert_se(p = dns_stream_take_read_packet(s));
t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
- if (t)
- return dns_transaction_on_stream_packet(t, p);
+ if (t && t->stream == s) /* Validate that the stream we got this on actually is the stream the
+ * transaction was using. */
+ return dns_transaction_on_stream_packet(t, s, p);
/* Ignore incorrect transaction id as an old transaction can have been canceled. */
log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p));
}
static uint16_t dns_transaction_port(DnsTransaction *t) {
+ assert(t);
+
if (t->server->port > 0)
return t->server->port;
+
return DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53;
}
int r;
assert(t);
+ assert(t->sent);
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
switch (t->scope->protocol) {
if (r < 0)
return r;
- if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
- return -EOPNOTSUPP;
+ if (manager_server_is_stub(t->scope->manager, t->server))
+ return -ELOOP;
- r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
- if (r < 0)
- return r;
+ if (!t->bypass) {
+ if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
+ return -EOPNOTSUPP;
+
+ r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
+ if (r < 0)
+ return r;
+ }
if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
s = dns_stream_ref(t->server->stream);
* the IP address, in case this is a reverse
* PTR lookup */
- r = dns_name_address(dns_resource_key_name(t->key), &family, &address);
+ r = dns_name_address(dns_resource_key_name(dns_transaction_key(t)), &family, &address);
if (r < 0)
return r;
if (r == 0)
r = dns_stream_write_packet(t->stream, t->sent);
if (r < 0) {
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, /* use_graveyard= */ false);
return r;
}
if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO)
return;
+ /* If validation is turned off for this transaction, but DNSSEC is on, then let's not cache this */
+ if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) && t->scope->dnssec_mode != DNSSEC_NO)
+ return;
+
/* Packet from localhost? */
if (!t->scope->manager->cache_from_localhost &&
in_addr_is_localhost(t->received->family, &t->received->sender) != 0)
dns_cache_put(&t->scope->cache,
t->scope->manager->enable_cache,
- t->key,
+ dns_transaction_key(t),
t->answer_rcode,
t->answer,
- t->answer_authenticated,
+ DNS_PACKET_CD(t->received) ? t->received : NULL, /* only cache full packets with CD on,
+ * since our usecase for caching them
+ * is "bypass" mode which is only
+ * enabled for CD packets. */
+ t->answer_query_flags,
+ t->answer_dnssec_result,
t->answer_nsec_ttl,
- 0,
t->received->family,
&t->received->sender);
}
/* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
* that works. */
- if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
- /* We tried fewer servers on this transaction than we know, let's try another one then */
- dns_transaction_retry(t, true);
+ if (dns_transaction_limited_retry(t))
return;
- }
/* OK, let's give up, apparently all servers we tried didn't work. */
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
/* Checks whether the answer is positive, i.e. either a direct
* answer to the question, or a CNAME/DNAME for it */
- r = dns_answer_match_key(t->answer, t->key, flags);
+ r = dns_answer_match_key(t->answer, dns_transaction_key(t), flags);
if (r != 0)
return r;
- r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
+ r = dns_answer_find_cname_or_dname(t->answer, dns_transaction_key(t), NULL, flags);
if (r != 0)
return r;
return 0;
}
-void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
+void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted) {
int r;
assert(t);
case DNS_PROTOCOL_DNS:
assert(t->server);
- if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
+ if (!t->bypass &&
+ IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
/* Request failed, immediately try again with reduced features */
* packet loss, but is not going to give us better rcodes should we actually have
* managed to get them already at UDP level. */
- if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
- /* We tried fewer servers on this transaction than we know, let's try another one then */
- dns_transaction_retry(t, true);
+ if (dns_transaction_limited_retry(t))
return;
- }
/* Give up, accept the rcode */
log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) {
/* This server refused our request? If so, try again, use a different server */
log_debug("Server returned REFUSED, switching servers, and retrying.");
- dns_transaction_retry(t, true /* pick a new server */);
- return;
+
+ if (dns_transaction_limited_retry(t))
+ return;
+
+ break;
}
if (DNS_PACKET_TC(p))
goto fail;
/* On DNS, couldn't send? Try immediately again, with a new server */
- dns_transaction_retry(t, true);
+ if (dns_transaction_limited_retry(t))
+ return;
+
+ /* No new server to try, give up */
+ dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
}
return;
/* After the superficial checks, actually parse the message. */
r = dns_packet_extract(p);
if (r < 0) {
+ if (t->server) {
+ dns_server_packet_invalid(t->server, t->current_feature_level);
+
+ r = dns_transaction_maybe_restart(t);
+ if (r < 0)
+ goto fail;
+ if (r > 0) /* Transaction got restarted... */
+ return;
+ }
+
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
return;
}
* to the request. For mDNS this check doesn't make sense, because the section 6 of RFC6762 states
* that "Multicast DNS responses MUST NOT contain any questions in the Question Section". */
if (t->scope->protocol != DNS_PROTOCOL_MDNS) {
- r = dns_packet_is_reply_for(p, t->key);
+ r = dns_packet_is_reply_for(p, dns_transaction_key(t));
if (r < 0)
goto fail;
if (r == 0) {
}
}
- /* Install the answer as answer to the transaction */
+ /* Install the answer as answer to the transaction. We ref the answer twice here: the main `answer`
+ * field is later replaced by the DNSSEC validated subset. The 'answer_auxiliary' field carries the
+ * original complete record set, including RRSIG and friends. We use this when passing data to
+ * clients that ask for DNSSEC metadata. */
dns_answer_unref(t->answer);
t->answer = dns_answer_ref(p->answer);
t->answer_rcode = DNS_PACKET_RCODE(p);
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
- t->answer_authenticated = false;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, encrypted);
r = dns_transaction_fix_rcode(t);
if (r < 0)
if (r > 0) {
/* There are DNSSEC transactions pending now. Update the state accordingly. */
t->state = DNS_TRANSACTION_VALIDATING;
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
dns_transaction_stop_timeout(t);
return;
}
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level);
- dns_transaction_retry(t, true);
+ dns_transaction_close_connection(t, /* use_graveyard = */ false);
+
+ if (dns_transaction_limited_retry(t)) /* Try a different server */
+ return 0;
+
+ dns_transaction_complete_errno(t, r);
return 0;
}
if (r < 0) {
return 0;
}
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
return 0;
}
if (r < 0)
return r;
+ if (manager_server_is_stub(t->scope->manager, t->server))
+ return -ELOOP;
+
if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
- if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
+ if (!t->bypass && !dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
return -EOPNOTSUPP;
if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
int fd;
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
+
+ /* Before we allocate a new UDP socket, let's process the graveyard a bit to free some fds */
+ manager_socket_graveyard_process(t->scope->manager);
fd = dns_scope_socket_udp(t->scope, t->server);
if (fd < 0)
t->dns_udp_fd = fd;
}
- r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
- if (r < 0)
- return r;
+ if (!t->bypass) {
+ r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
+ if (r < 0)
+ return r;
+ }
} else
- dns_transaction_close_connection(t);
+ dns_transaction_close_connection(t, true);
r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent);
if (r < 0)
log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
- dns_transaction_retry(t, true);
+ dns_transaction_retry(t, true); /* try a different server, but given this means packet loss, let's do
+ * so even if we already tried a bunch */
return 0;
}
}
}
+static void dns_transaction_randomize_answer(DnsTransaction *t) {
+ int r;
+
+ assert(t);
+
+ /* Randomizes the order of the answer array. This is done for all cached responses, so that we return
+ * a different order each time. We do this only for DNS traffic, in order to do some minimal, crappy
+ * load balancing. We don't do this for LLMNR or mDNS, since the order (preferring link-local
+ * addresses, and such like) might have meaning there, and load balancing is pointless. */
+
+ if (t->scope->protocol != DNS_PROTOCOL_DNS)
+ return;
+
+ /* No point in randomizing, if there's just one RR */
+ if (dns_answer_size(t->answer) <= 1)
+ return;
+
+ r = dns_answer_reserve_or_clone(&t->answer, 0);
+ if (r < 0) /* If this fails, just don't randomize, this is non-essential stuff after all */
+ return (void) log_debug_errno(r, "Failed to clone answer record, not randomizing RR order of answer: %m");
+
+ dns_answer_randomize(t->answer);
+}
+
static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
int r;
dns_transaction_flush_dnssec_transactions(t);
/* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
- if (t->scope->protocol == DNS_PROTOCOL_DNS) {
- r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer);
+ if (t->scope->protocol == DNS_PROTOCOL_DNS &&
+ !FLAGS_SET(t->query_flags, SD_RESOLVED_NO_TRUST_ANCHOR)) {
+ r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, dns_transaction_key(t), &t->answer);
if (r < 0)
return r;
if (r > 0) {
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
- t->answer_authenticated = true;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
return 0;
}
- if (dns_name_is_root(dns_resource_key_name(t->key)) &&
- t->key->type == DNS_TYPE_DS) {
+ if (dns_name_is_root(dns_resource_key_name(dns_transaction_key(t))) &&
+ dns_transaction_key(t)->type == DNS_TYPE_DS) {
- /* Hmm, this is a request for the root DS? A
- * DS RR doesn't exist in the root zone, and
- * if our trust anchor didn't know it either,
- * this means we cannot do any DNSSEC logic
- * anymore. */
+ /* Hmm, this is a request for the root DS? A DS RR doesn't exist in the root zone,
+ * and if our trust anchor didn't know it either, this means we cannot do any DNSSEC
+ * logic anymore. */
if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
- /* We are in downgrade mode. In this
- * case, synthesize an unsigned empty
- * response, so that the any lookup
- * depending on this one can continue
- * assuming there was no DS, and hence
- * the root zone was unsigned. */
+ /* We are in downgrade mode. In this case, synthesize an unsigned empty
+ * response, so that the any lookup depending on this one can continue
+ * assuming there was no DS, and hence the root zone was unsigned. */
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
- t->answer_authenticated = false;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
} else
- /* If we are not in downgrade mode,
- * then fail the lookup, because we
- * cannot reasonably answer it. There
- * might be DS RRs, but we don't know
- * them, and the DNS server won't tell
- * them to us (and even if it would,
- * we couldn't validate and trust them. */
+ /* If we are not in downgrade mode, then fail the lookup, because we cannot
+ * reasonably answer it. There might be DS RRs, but we don't know them, and
+ * the DNS server won't tell them to us (and even if it would, we couldn't
+ * validate and trust them. */
dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR);
return 0;
}
}
- /* Check the zone, but only if this transaction is not used
- * for probing or verifying a zone item. */
- if (set_isempty(t->notify_zone_items)) {
-
- r = dns_zone_lookup(&t->scope->zone, t->key, dns_scope_ifindex(t->scope), &t->answer, NULL, NULL);
+ /* Check the zone. */
+ if (!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_ZONE)) {
+ r = dns_zone_lookup(&t->scope->zone, dns_transaction_key(t), dns_scope_ifindex(t->scope), &t->answer, NULL, NULL);
if (r < 0)
return r;
if (r > 0) {
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_ZONE;
- t->answer_authenticated = true;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
return 0;
}
}
- /* Check the cache, but only if this transaction is not used
- * for probing or verifying a zone item. */
- if (set_isempty(t->notify_zone_items)) {
+ /* Check the cache. */
+ if (!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_CACHE)) {
- /* Before trying the cache, let's make sure we figured out a
- * server to use. Should this cause a change of server this
- * might flush the cache. */
+ /* Before trying the cache, let's make sure we figured out a server to use. Should this cause
+ * a change of server this might flush the cache. */
(void) dns_scope_get_dns_server(t->scope);
/* Let's then prune all outdated entries */
dns_cache_prune(&t->scope->cache);
- r = dns_cache_lookup(&t->scope->cache, t->key, t->clamp_ttl, &t->answer_rcode, &t->answer, &t->answer_authenticated);
+ r = dns_cache_lookup(
+ &t->scope->cache,
+ dns_transaction_key(t),
+ t->query_flags,
+ &t->answer_rcode,
+ &t->answer,
+ &t->received,
+ &t->answer_query_flags,
+ &t->answer_dnssec_result);
if (r < 0)
return r;
if (r > 0) {
- t->answer_source = DNS_TRANSACTION_CACHE;
- if (t->answer_rcode == DNS_RCODE_SUCCESS)
- dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
- else
- dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
- return 0;
+ dns_transaction_randomize_answer(t);
+
+ if (t->bypass && t->scope->protocol == DNS_PROTOCOL_DNS && !t->received)
+ /* When bypass mode is on, do not use cached data unless it came with a full
+ * packet. */
+ dns_transaction_reset_answer(t);
+ else {
+ t->answer_source = DNS_TRANSACTION_CACHE;
+ if (t->answer_rcode == DNS_RCODE_SUCCESS)
+ dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+ else
+ dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
+ return 0;
+ }
}
}
+ if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_NETWORK)) {
+ dns_transaction_complete(t, DNS_TRANSACTION_NO_SOURCE);
+ return 0;
+ }
+
return 1;
}
if (r < 0)
return r;
- r = dns_packet_append_key(p, t->key, 0, NULL);
+ r = dns_packet_append_key(p, dns_transaction_key(t), 0, NULL);
if (r < 0)
return r;
qdcount = 1;
- if (dns_key_is_shared(t->key))
+ if (dns_key_is_shared(dns_transaction_key(t)))
add_known_answers = true;
- if (t->key->type == DNS_TYPE_ANY) {
- r = set_ensure_put(&keys, &dns_resource_key_hash_ops, t->key);
+ if (dns_transaction_key(t)->type == DNS_TYPE_ANY) {
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, dns_transaction_key(t));
if (r < 0)
return r;
}
if (qdcount >= UINT16_MAX)
break;
- r = dns_packet_append_key(p, other->key, 0, NULL);
+ r = dns_packet_append_key(p, dns_transaction_key(other), 0, NULL);
/*
* If we can't stuff more questions into the packet, just give up.
qdcount++;
- if (dns_key_is_shared(other->key))
+ if (dns_key_is_shared(dns_transaction_key(other)))
add_known_answers = true;
- if (other->key->type == DNS_TYPE_ANY) {
- r = set_ensure_put(&keys, &dns_resource_key_hash_ops, other->key);
+ if (dns_transaction_key(other)->type == DNS_TYPE_ANY) {
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, dns_transaction_key(other));
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = dns_packet_append_answer(p, answer);
+ r = dns_packet_append_answer(p, answer, &nscount);
if (r < 0)
return r;
-
- nscount += dns_answer_size(answer);
}
DNS_PACKET_HEADER(p)->nscount = htobe16(nscount);
if (t->sent)
return 0;
- r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO);
- if (r < 0)
- return r;
+ if (t->bypass && t->bypass->protocol == t->scope->protocol) {
+ /* If bypass logic is enabled and the protocol if the original packet and our scope match,
+ * take the original packet, copy it, and patch in our new ID */
+ r = dns_packet_dup(&p, t->bypass);
+ if (r < 0)
+ return r;
+ } else {
+ r = dns_packet_new_query(
+ &p, t->scope->protocol,
+ /* min_alloc_dsize = */ 0,
+ /* dnssec_cd = */ !FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) &&
+ t->scope->dnssec_mode != DNSSEC_NO);
+ if (r < 0)
+ return r;
- r = dns_packet_append_key(p, t->key, 0, NULL);
- if (r < 0)
- return r;
+ r = dns_packet_append_key(p, dns_transaction_key(t), 0, NULL);
+ if (r < 0)
+ return r;
+
+ DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
+ }
- DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
DNS_PACKET_HEADER(p)->id = t->id;
t->sent = TAKE_PTR(p);
-
return 0;
}
if (r <= 0)
return r;
- log_debug("Transaction %" PRIu16 " for <%s> scope %s on %s/%s.",
+ log_debug("%s transaction %" PRIu16 " for <%s> scope %s on %s/%s (validate=%s).",
+ t->bypass ? "Bypass" : "Regular",
t->id,
- dns_resource_key_to_string(t->key, key_str, sizeof key_str),
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
dns_protocol_to_string(t->scope->protocol),
t->scope->link ? t->scope->link->ifname : "*",
- af_to_name_short(t->scope->family));
+ af_to_name_short(t->scope->family),
+ yes_no(!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE)));
if (!t->initial_jitter_scheduled &&
IN_SET(t->scope->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) {
return r;
if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
- (dns_name_endswith(dns_resource_key_name(t->key), "in-addr.arpa") > 0 ||
- dns_name_endswith(dns_resource_key_name(t->key), "ip6.arpa") > 0)) {
+ (dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), "in-addr.arpa") > 0 ||
+ dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), "ip6.arpa") > 0)) {
/* RFC 4795, Section 2.4. says reverse lookups shall
* always be made via TCP on LLMNR */
if (IN_SET(r, -EMSGSIZE, -EAGAIN))
r = dns_transaction_emit_tcp(t);
}
+ if (r == -ELOOP) {
+ if (t->scope->protocol != DNS_PROTOCOL_DNS)
+ return r;
+
+ /* One of our own stub listeners */
+ log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers.");
+
+ dns_scope_next_dns_server(t->scope, t->server);
+ if (dns_scope_get_dns_server(t->scope) == t->server) {
+ log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation.");
+ dns_transaction_complete(t, DNS_TRANSACTION_STUB_LOOP);
+ return 0;
+ }
+
+ return dns_transaction_go(t);
+ }
if (r == -ESRCH) {
/* No servers to send this to? */
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
return r;
/* Couldn't send? Try immediately again, with a new server */
- dns_scope_next_dns_server(t->scope);
+ dns_scope_next_dns_server(t->scope, t->server);
return dns_transaction_go(t);
}
assert(ret);
assert(key);
- aux = dns_scope_find_transaction(t->scope, key, true);
+ aux = dns_scope_find_transaction(t->scope, key, t->query_flags);
if (!aux) {
- r = dns_transaction_new(&aux, t->scope, key);
+ r = dns_transaction_new(&aux, t->scope, key, NULL, t->query_flags);
if (r < 0)
return r;
} else {
return log_debug_errno(SYNTHETIC_ERRNO(ELOOP),
"Potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).",
aux->id,
- dns_resource_key_to_string(t->key, s, sizeof s),
+ dns_resource_key_to_string(dns_transaction_key(t), s, sizeof s),
t->id,
- dns_resource_key_to_string(aux->key, saux, sizeof saux));
+ dns_resource_key_to_string(dns_transaction_key(aux), saux, sizeof saux));
}
}
/* Is this key explicitly listed as a negative trust anchor?
* If so, it's nothing we need to care about */
- r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key));
+ r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(dns_transaction_key(t)));
if (r < 0)
return r;
if (r > 0)
* i.e. either matches the question precisely or is a
* CNAME/DNAME for it. */
- r = dns_resource_key_match_rr(t->key, rr, NULL);
+ r = dns_resource_key_match_rr(dns_transaction_key(t), rr, NULL);
if (r != 0)
return r;
- return dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
+ return dns_resource_key_match_cname_or_dname(dns_transaction_key(t), rr->key, NULL);
}
static bool dns_transaction_dnssec_supported(DnsTransaction *t) {
* - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
*/
- if (t->scope->dnssec_mode == DNSSEC_NO)
+ if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) || t->scope->dnssec_mode == DNSSEC_NO)
return 0;
if (t->answer_source != DNS_TRANSACTION_NETWORK)
return 0; /* We only need to validate stuff from the network */
* in another transaction whose additional RRs
* point back to the original transaction, and
* we deadlock. */
- r = dns_name_endswith(dns_resource_key_name(t->key), rr->rrsig.signer);
+ r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), rr->rrsig.signer);
if (r < 0)
return r;
if (r == 0)
* up in request loops, and want to keep
* additional traffic down. */
- r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key));
+ r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), dns_resource_key_name(rr->key));
if (r < 0)
return r;
if (r == 0)
* this RR matches our original question,
* however. */
- r = dns_resource_key_match_rr(t->key, rr, NULL);
+ r = dns_resource_key_match_rr(dns_transaction_key(t), rr, NULL);
if (r < 0)
return r;
if (r == 0) {
* a negative reply, and we need the SOA RR's TTL in order to cache a negative entry?
* If so, we need to validate it, too. */
- r = dns_answer_match_key(t->answer, t->key, NULL);
+ r = dns_answer_match_key(t->answer, dns_transaction_key(t), NULL);
if (r < 0)
return r;
if (r > 0) /* positive reply, we won't need the SOA and hence don't need to validate
/* Only bother with this if the SOA/NS RR we are looking at is actually a parent of
* what we are looking for, otherwise there's no value in it for us. */
- r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key));
+ r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), dns_resource_key_name(rr->key));
if (r < 0)
return r;
if (r == 0)
const char *name;
uint16_t type = 0;
- name = dns_resource_key_name(t->key);
+ name = dns_resource_key_name(dns_transaction_key(t));
/* If this was a SOA or NS request, then check if there's a DS RR for the same domain. Note that this
* could also be used as indication that we are not at a zone apex, but in real world setups there are
* is signed, hence ask the parent SOA in that case. If this was any other RR then ask for the SOA RR,
* to see if that is signed. */
- if (t->key->type == DNS_TYPE_DS) {
+ if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
r = dns_name_parent(&name);
if (r > 0) {
type = DNS_TYPE_SOA;
log_debug("Requesting parent SOA (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty DS response).",
- name, t->id, dns_resource_key_name(t->key));
+ name, t->id, dns_resource_key_name(dns_transaction_key(t)));
} else
name = NULL;
- } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS)) {
+ } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS)) {
type = DNS_TYPE_DS;
log_debug("Requesting DS (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS response).",
if (name) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
- soa = dns_resource_key_new(t->key->class, type, name);
+ soa = dns_resource_key_new(dns_transaction_key(t)->class, type, name);
if (!soa)
return -ENOMEM;
}
static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
- DnsResourceRecord *rr;
- int ifindex, r;
+ DnsAnswerItem *item;
+ int r;
assert(t);
* RRs from the list of validated keys to the list of
* validated keys. */
- DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
+ DNS_ANSWER_FOREACH_ITEM(item, t->answer) {
- r = dnssec_verify_dnskey_by_ds_search(rr, t->validated_keys);
+ r = dnssec_verify_dnskey_by_ds_search(item->rr, t->validated_keys);
if (r < 0)
return r;
if (r == 0)
continue;
/* If so, the DNSKEY is validated too. */
- r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add_extend(&t->validated_keys, item->rr, item->ifindex, item->flags|DNS_ANSWER_AUTHENTICATED, item->rrsig);
if (r < 0)
return r;
}
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != rr->key->class)
+ if (dns_transaction_key(dt)->class != rr->key->class)
continue;
- if (dt->key->type != DNS_TYPE_DS)
+ if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
continue;
- r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key));
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
if (r < 0)
return r;
if (r == 0)
* RRs we are looking at. If it discovered signed DS
* RRs, then we need to be signed, too. */
- if (!dt->answer_authenticated)
+ if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
return false;
- return dns_answer_match_key(dt->answer, dt->key, NULL);
+ return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
}
/* We found nothing that proves this is safe to leave
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != rr->key->class)
+ if (dns_transaction_key(dt)->class != rr->key->class)
continue;
- if (dt->key->type != DNS_TYPE_SOA)
+ if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
continue;
if (!parent) {
}
}
- r = dns_name_equal(dns_resource_key_name(dt->key), parent);
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), parent);
if (r < 0)
return r;
if (r == 0)
continue;
- return t->answer_authenticated;
+ return FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
}
return true;
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != rr->key->class)
+ if (dns_transaction_key(dt)->class != rr->key->class)
continue;
- if (dt->key->type != DNS_TYPE_SOA)
+ if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
continue;
- r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key));
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
if (r < 0)
return r;
if (r == 0)
continue;
- /* We found the transaction that was supposed to find
- * the SOA RR for us. It was successful, but found no
- * RR for us. This means we are not at a zone cut. In
- * this case, we require authentication if the SOA
- * lookup was authenticated too. */
- return t->answer_authenticated;
+ /* We found the transaction that was supposed to find the SOA RR for us. It was
+ * successful, but found no RR for us. This means we are not at a zone cut. In this
+ * case, we require authentication if the SOA lookup was authenticated too. */
+ return FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
}
return true;
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != key->class)
+ if (dns_transaction_key(dt)->class != key->class)
continue;
- r = dns_name_equal(dns_resource_key_name(dt->key), tld);
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), tld);
if (r < 0)
return r;
if (r == 0)
if (t->scope->dnssec_mode == DNSSEC_NO)
return false;
- if (dns_type_is_pseudo(t->key->type))
+ if (dns_type_is_pseudo(dns_transaction_key(t)->type))
return -EINVAL;
- r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key));
+ r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(dns_transaction_key(t)));
if (r < 0)
return r;
if (r > 0)
return false;
- r = dns_transaction_in_private_tld(t, t->key);
+ r = dns_transaction_in_private_tld(t, dns_transaction_key(t));
if (r < 0)
return r;
if (r > 0) {
* that fact that we didn't get any NSEC RRs. */
log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.",
- dns_resource_key_to_string(t->key, key_str, sizeof key_str));
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
return false;
}
- name = dns_resource_key_name(t->key);
+ name = dns_resource_key_name(dns_transaction_key(t));
- if (t->key->type == DNS_TYPE_DS) {
+ if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
/* We got a negative reply for this DS lookup? DS RRs are signed when their parent zone is signed,
* hence check the parent SOA in this case. */
type = DNS_TYPE_SOA;
- } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS))
+ } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS))
/* We got a negative reply for this SOA/NS lookup? If so, check if there's a DS RR for this */
type = DNS_TYPE_DS;
else
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != t->key->class)
+ if (dns_transaction_key(dt)->class != dns_transaction_key(t)->class)
continue;
- if (dt->key->type != type)
+ if (dns_transaction_key(dt)->type != type)
continue;
- r = dns_name_equal(dns_resource_key_name(dt->key), name);
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), name);
if (r < 0)
return r;
if (r == 0)
continue;
- return dt->answer_authenticated;
+ return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
}
/* If in doubt, require NSEC/NSEC3 */
SET_FOREACH(dt, t->dnssec_transactions) {
- if (dt->key->class != rr->key->class)
+ if (dns_transaction_key(dt)->class != rr->key->class)
continue;
- if (dt->key->type == DNS_TYPE_DNSKEY) {
+ if (dns_transaction_key(dt)->type == DNS_TYPE_DNSKEY) {
- r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer);
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), rrsig->rrsig.signer);
if (r < 0)
return r;
if (r == 0)
continue;
- /* OK, we found an auxiliary DNSKEY
- * lookup. If that lookup is
- * authenticated, report this. */
+ /* OK, we found an auxiliary DNSKEY lookup. If that lookup is authenticated,
+ * report this. */
- if (dt->answer_authenticated)
+ if (FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
return true;
found = true;
- } else if (dt->key->type == DNS_TYPE_DS) {
+ } else if (dns_transaction_key(dt)->type == DNS_TYPE_DS) {
- r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer);
+ r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), rrsig->rrsig.signer);
if (r < 0)
return r;
if (r == 0)
continue;
- /* OK, we found an auxiliary DS
- * lookup. If that lookup is
- * authenticated and non-zero, we
- * won! */
+ /* OK, we found an auxiliary DS lookup. If that lookup is authenticated and
+ * non-zero, we won! */
- if (!dt->answer_authenticated)
+ if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
return false;
- return dns_answer_match_key(dt->answer, dt->key, NULL);
+ return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
}
}
}
if (DNS_TRANSACTION_IS_LIVE(dt->state))
continue;
- if (!dt->answer_authenticated)
+ if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
continue;
r = dns_answer_extend(&t->validated_keys, dt->answer);
continue;
}
- r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result, &rrsig);
+ r = dnssec_verify_rrset_search(
+ t->answer,
+ rr->key,
+ t->validated_keys,
+ USEC_INFINITY,
+ &result,
+ &rrsig);
if (r < 0)
return r;
log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
if (result == DNSSEC_VALIDATED) {
+ assert(rrsig);
if (rr->key->type == DNS_TYPE_DNSKEY) {
/* If we just validated a DNSKEY RRset, then let's add these keys to
* the set of validated keys for this transaction. */
- r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED, rrsig);
if (r < 0)
return r;
return r;
}
- /* Add the validated RRset to the new list of validated
- * RRsets, and remove it from the unvalidated RRsets.
- * We mark the RRset as authenticated and cacheable. */
- r = dns_answer_move_by_key(validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE);
+ /* Add the validated RRset to the new list of validated RRsets, and remove it from
+ * the unvalidated RRsets. We mark the RRset as authenticated and cacheable. */
+ r = dns_answer_move_by_key(validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE, rrsig);
if (r < 0)
return r;
bool authenticated = false;
const char *source;
+ assert(rrsig);
+
/* This RRset validated, but as a wildcard. This means we need
* to prove via NSEC/NSEC3 that no matching non-wildcard RR exists. */
if (r == 0)
result = DNSSEC_INVALID;
else {
- r = dns_answer_move_by_key(validated, &t->answer, rr->key,
- authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0);
+ r = dns_answer_move_by_key(
+ validated,
+ &t->answer,
+ rr->key,
+ authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0,
+ rrsig);
if (r < 0)
return r;
if (r == 0) {
/* Data does not require signing. In that case, just copy it over,
* but remember that this is by no means authenticated. */
- r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
+ r = dns_answer_move_by_key(
+ validated,
+ &t->answer,
+ rr->key,
+ 0,
+ NULL);
if (r < 0)
return r;
/* Downgrading is OK? If so, just consider the information unsigned */
- r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
+ r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
if (r < 0)
return r;
log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.",
dns_resource_key_to_string(rr->key, s, sizeof s));
- r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
+ r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
if (r < 0)
return r;
/* The DNSKEY transaction was not authenticated, this means there's
* no DS for this, which means it's OK if no keys are found for this signature. */
- r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
+ r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
if (r < 0)
return r;
assert(t);
- /* We have now collected all DS and DNSKEY RRs in
- * t->validated_keys, let's see which RRs we can now
+ /* We have now collected all DS and DNSKEY RRs in t->validated_keys, let's see which RRs we can now
* authenticate with that. */
- if (t->scope->dnssec_mode == DNSSEC_NO)
+ if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) || t->scope->dnssec_mode == DNSSEC_NO)
return 0;
/* Already validated */
/* Our own stuff needs no validation */
if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
t->answer_dnssec_result = DNSSEC_VALIDATED;
- t->answer_authenticated = true;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
return 0;
}
log_debug("Validating response from transaction %" PRIu16 " (%s).",
t->id,
- dns_resource_key_to_string(t->key, key_str, sizeof key_str));
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
/* First, see if this response contains any revoked trust
* anchors we care about */
/* The answer is fully authenticated, yay. */
t->answer_dnssec_result = DNSSEC_VALIDATED;
t->answer_rcode = DNS_RCODE_SUCCESS;
- t->answer_authenticated = true;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
} else {
/* The answer is not fully authenticated. */
t->answer_dnssec_result = DNSSEC_UNSIGNED;
- t->answer_authenticated = false;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
}
} else if (r == 0) {
bool authenticated = false;
/* Bummer! Let's check NSEC/NSEC3 */
- r = dnssec_nsec_test(t->answer, t->key, &nr, &authenticated, &t->answer_nsec_ttl);
+ r = dnssec_nsec_test(t->answer, dns_transaction_key(t), &nr, &authenticated, &t->answer_nsec_ttl);
if (r < 0)
return r;
log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
t->answer_dnssec_result = DNSSEC_VALIDATED;
t->answer_rcode = DNS_RCODE_NXDOMAIN;
- t->answer_authenticated = authenticated;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
- manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
+ manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
break;
case DNSSEC_NSEC_NODATA:
log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
t->answer_dnssec_result = DNSSEC_VALIDATED;
t->answer_rcode = DNS_RCODE_SUCCESS;
- t->answer_authenticated = authenticated;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
- manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
+ manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
break;
case DNSSEC_NSEC_OPTOUT:
/* NSEC3 says the data might not be signed */
log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
t->answer_dnssec_result = DNSSEC_UNSIGNED;
- t->answer_authenticated = false;
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
- manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
+ manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
break;
case DNSSEC_NSEC_NO_RR:
return r;
if (r > 0) {
t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
- manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
+ manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, dns_transaction_key(t));
} else {
t->answer_dnssec_result = DNSSEC_UNSIGNED;
- t->answer_authenticated = false;
- manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
+ SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
+ manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
}
break;
case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
/* We don't know the NSEC3 algorithm used? */
t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
- manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, t->key);
+ manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, dns_transaction_key(t));
break;
case DNSSEC_NSEC_FOUND:
case DNSSEC_NSEC_CNAME:
/* NSEC says it needs to be there, but we couldn't find it? Bummer! */
t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
- manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
+ manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, dns_transaction_key(t));
break;
default:
[DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported",
[DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
[DNS_TRANSACTION_NOT_FOUND] = "not-found",
+ [DNS_TRANSACTION_NO_SOURCE] = "no-source",
+ [DNS_TRANSACTION_STUB_LOOP] = "stub-loop",
};
DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
#include "in-addr-util.h"
typedef struct DnsTransaction DnsTransaction;
+typedef struct DnsTransactionFinder DnsTransactionFinder;
typedef enum DnsTransactionState DnsTransactionState;
typedef enum DnsTransactionSource DnsTransactionSource;
DNS_TRANSACTION_RR_TYPE_UNSUPPORTED,
DNS_TRANSACTION_NETWORK_DOWN,
DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */
+ DNS_TRANSACTION_NO_SOURCE, /* All suitable DnsTransactionSource turned off */
+ DNS_TRANSACTION_STUB_LOOP,
_DNS_TRANSACTION_STATE_MAX,
- _DNS_TRANSACTION_STATE_INVALID = -1
+ _DNS_TRANSACTION_STATE_INVALID = -EINVAL,
};
#define DNS_TRANSACTION_IS_LIVE(state) IN_SET((state), DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING)
DNS_TRANSACTION_ZONE,
DNS_TRANSACTION_TRUST_ANCHOR,
_DNS_TRANSACTION_SOURCE_MAX,
- _DNS_TRANSACTION_SOURCE_INVALID = -1
+ _DNS_TRANSACTION_SOURCE_INVALID = -EINVAL,
};
struct DnsTransaction {
DnsScope *scope;
- DnsResourceKey *key;
+ DnsResourceKey *key; /* For regular lookups the RR key to look for */
+ DnsPacket *bypass; /* For bypass lookups the full original request packet */
+
+ uint64_t query_flags;
DnsTransactionState state;
bool initial_jitter_scheduled:1;
bool initial_jitter_elapsed:1;
- bool clamp_ttl:1;
-
bool probing:1;
DnsPacket *sent, *received;
uint32_t answer_nsec_ttl;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
- /* Indicates whether the primary answer is authenticated,
- * i.e. whether the RRs from answer which directly match the
- * question are authenticated, or, if there are none, whether
- * the NODATA or NXDOMAIN case is. It says nothing about
- * additional RRs listed in the answer, however they have
- * their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit
- * is defined different than the AD bit in DNS packets, as
- * that covers more than just the actual primary answer. */
- bool answer_authenticated;
+ /* SD_RESOLVED_AUTHENTICATED here indicates whether the primary answer is authenticated, i.e. whether
+ * the RRs from answer which directly match the question are authenticated, or, if there are none,
+ * whether the NODATA or NXDOMAIN case is. It says nothing about additional RRs listed in the answer,
+ * however they have their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit is defined different
+ * than the AD bit in DNS packets, as that covers more than just the actual primary answer. */
+ uint64_t answer_query_flags;
/* Contains DNSKEY, DS, SOA RRs we already verified and need
* to authenticate this reply */
LIST_FIELDS(DnsTransaction, transactions_by_scope);
LIST_FIELDS(DnsTransaction, transactions_by_stream);
+ LIST_FIELDS(DnsTransaction, transactions_by_key);
};
-int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
+int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key, DnsPacket *bypass, uint64_t flags);
DnsTransaction* dns_transaction_free(DnsTransaction *t);
-bool dns_transaction_gc(DnsTransaction *t);
+DnsTransaction* dns_transaction_gc(DnsTransaction *t);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
int dns_transaction_go(DnsTransaction *t);
-void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
+void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted);
void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state);
void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
int dns_transaction_validate_dnssec(DnsTransaction *t);
int dns_transaction_request_dnssec_keys(DnsTransaction *t);
+static inline DnsResourceKey *dns_transaction_key(DnsTransaction *t) {
+ assert(t);
+
+ /* Return the lookup key of this transaction. Either takes the lookup key from the bypass packet if
+ * we are a bypass transaction. Or take the configured key for regular transactions. */
+
+ if (t->key)
+ return t->key;
+
+ assert(t->bypass);
+
+ if (dns_question_isempty(t->bypass->question))
+ return NULL;
+
+ return t->bypass->question->keys[0];
+}
+
+static inline uint64_t dns_transaction_source_to_query_flags(DnsTransactionSource s) {
+
+ switch (s) {
+
+ case DNS_TRANSACTION_NETWORK:
+ return SD_RESOLVED_FROM_NETWORK;
+
+ case DNS_TRANSACTION_CACHE:
+ return SD_RESOLVED_FROM_CACHE;
+
+ case DNS_TRANSACTION_ZONE:
+ return SD_RESOLVED_FROM_ZONE;
+
+ case DNS_TRANSACTION_TRUST_ANCHOR:
+ return SD_RESOLVED_FROM_TRUST_ANCHOR;
+
+ default:
+ return 0;
+ }
+}
+
const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;
if (!rr->ds.digest)
return -ENOMEM;
- r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
old_answer = hashmap_get(d->positive_by_key, rr->key);
answer = dns_answer_ref(old_answer);
- r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return log_error_errno(r, "Failed to add trust anchor RR: %m");
dns_transaction_gc(t);
}
-static void dns_zone_item_free(DnsZoneItem *i) {
+static DnsZoneItem* dns_zone_item_free(DnsZoneItem *i) {
if (!i)
- return;
+ return NULL;
dns_zone_item_probe_stop(i);
dns_resource_record_unref(i->rr);
- free(i);
+ return mfree(i);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free);
static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {
if (i->probe_transaction)
return 0;
- t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)), false);
+ t = dns_scope_find_transaction(
+ i->scope,
+ &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)),
+ SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (!t) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
if (!key)
return -ENOMEM;
- r = dns_transaction_new(&t, i->scope, key);
+ r = dns_transaction_new(&t, i->scope, key, NULL, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (r < 0)
return r;
}
else
flags = DNS_ANSWER_AUTHENTICATED;
- return dns_answer_add(a, i->rr, ifindex, flags);
+ return dns_answer_add(a, i->rr, ifindex, flags, NULL);
}
int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#include <stddef.h>
#include "conf-parser.h"
#include "resolved-manager.h"
#define TLS_PROTOCOL_PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
-DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gnutls_session_t, gnutls_deinit, NULL);
static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) {
int r;
if (!rr->ptr.name)
return -ENOMEM;
- r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
+ r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL);
if (r < 0)
return r;
}
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
}
}
+ bus_client_log(message, "DNS server change");
+
dns_server_mark_all(l->dns_servers);
for (size_t i = 0; i < n; i++) {
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "dns domains change");
+
dns_search_domain_mark_all(l->search_domains);
for (;;) {
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "dns default route change");
+
if (l->default_route != b) {
l->default_route = b;
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "LLMNR change");
+
l->llmnr_support = mode;
link_allocate_scopes(l);
link_add_rrs(l, false);
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "mDNS change");
+
l->mdns_support = mode;
link_allocate_scopes(l);
link_add_rrs(l, false);
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "D-o-T change");
+
link_set_dns_over_tls_mode(l, mode);
(void) link_save_user(l);
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "DNSSEC change");
+
link_set_dnssec_mode(l, mode);
(void) link_save_user(l);
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "DNSSEC NTA change");
+
set_free_free(l->dnssec_negative_trust_anchors);
l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
if (r == 0)
return 1; /* Polkit will call us back */
+ bus_client_log(message, "revert");
+
link_flush_settings(l);
link_allocate_scopes(l);
link_add_rrs(l, false);
assert(l);
+ l->llmnr_support = RESOLVE_SUPPORT_YES; /* yes, yes, we set it twice which is ugly */
+
r = sd_network_link_get_llmnr(l->ifindex, &b);
- if (r == -ENODATA) {
- r = 0;
- goto clear;
- }
+ if (r == -ENODATA)
+ return 0;
if (r < 0)
- goto clear;
+ return r;
- l->llmnr_support = resolve_support_from_string(b);
- if (l->llmnr_support < 0) {
- r = -EINVAL;
- goto clear;
- }
+ r = resolve_support_from_string(b);
+ if (r < 0)
+ return r;
+ l->llmnr_support = r;
return 0;
-
-clear:
- l->llmnr_support = RESOLVE_SUPPORT_YES;
- return r;
}
static int link_update_mdns_support(Link *l) {
assert(l);
+ l->mdns_support = RESOLVE_SUPPORT_NO;
+
r = sd_network_link_get_mdns(l->ifindex, &b);
- if (r == -ENODATA) {
- r = 0;
- goto clear;
- }
+ if (r == -ENODATA)
+ return 0;
if (r < 0)
- goto clear;
+ return r;
- l->mdns_support = resolve_support_from_string(b);
- if (l->mdns_support < 0) {
- r = -EINVAL;
- goto clear;
- }
+ r = resolve_support_from_string(b);
+ if (r < 0)
+ return r;
+ l->mdns_support = r;
return 0;
-
-clear:
- l->mdns_support = RESOLVE_SUPPORT_NO;
- return r;
}
void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
assert(l);
+ l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
+
r = sd_network_link_get_dns_over_tls(l->ifindex, &b);
- if (r == -ENODATA) {
- r = 0;
- goto clear;
- }
+ if (r == -ENODATA)
+ return 0;
if (r < 0)
- goto clear;
+ return r;
- l->dns_over_tls_mode = dns_over_tls_mode_from_string(b);
- if (l->dns_over_tls_mode < 0) {
- r = -EINVAL;
- goto clear;
- }
+ r = dns_over_tls_mode_from_string(b);
+ if (r < 0)
+ return r;
+ l->dns_over_tls_mode = r;
return 0;
-
-clear:
- l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
- return r;
}
void link_set_dnssec_mode(Link *l, DnssecMode mode) {
assert(l);
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
+
r = sd_network_link_get_dnssec(l->ifindex, &m);
- if (r == -ENODATA) {
- r = 0;
- goto clear;
- }
+ if (r == -ENODATA)
+ return 0;
if (r < 0)
- goto clear;
+ return r;
mode = dnssec_mode_from_string(m);
- if (mode < 0) {
- r = -EINVAL;
- goto clear;
- }
+ if (mode < 0)
+ return mode;
link_set_dnssec_mode(l, mode);
-
return 0;
-
-clear:
- l->dnssec_mode = _DNSSEC_MODE_INVALID;
- return r;
}
static int link_update_dnssec_negative_trust_anchors(Link *l) {
assert(l);
+ l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
+
r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
- if (r == -ENODATA) {
- r = 0;
- goto clear;
- }
+ if (r == -ENODATA)
+ return r;
if (r < 0)
- goto clear;
+ return r;
ns = set_new(&dns_name_hash_ops);
if (!ns)
if (r < 0)
return r;
- set_free_free(l->dnssec_negative_trust_anchors);
l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
-
return 0;
-
-clear:
- l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
- return r;
}
static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
return l->current_dns_server;
}
-void link_next_dns_server(Link *l) {
+void link_next_dns_server(Link *l, DnsServer *if_current) {
assert(l);
+ /* If the current server of the transaction is specified, and we already are at a different one,
+ * don't do anything */
+ if (if_current && l->current_dns_server != if_current)
+ return;
+
+ /* If currently have no DNS server, then don't do anything, we'll pick it lazily the next time a DNS
+ * server is needed. */
if (!l->current_dns_server)
return;
- /* Change to the next one, but make sure to follow the linked
- * list only if this server is actually still linked. */
+ /* Change to the next one, but make sure to follow the linked list only if this server is actually
+ * still linked. */
if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
link_set_dns_server(l, l->current_dns_server->servers_next);
return;
}
+ /* Pick the first one again, after we reached the end */
link_set_dns_server(l, l->dns_servers);
}
.family = family,
.in_addr = *in_addr,
.link = l,
+ .prefixlen = UCHAR_MAX,
};
LIST_PREPEND(addresses, l->addresses, a);
int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
int r;
+
assert(a);
assert(m);
if (r < 0)
return r;
- sd_rtnl_message_addr_get_scope(m, &a->scope);
+ (void) sd_rtnl_message_addr_get_prefixlen(m, &a->prefixlen);
+ (void) sd_rtnl_message_addr_get_scope(m, &a->scope);
link_allocate_scopes(a->link);
link_add_rrs(a->link, false);
int family;
union in_addr_union in_addr;
+ unsigned char prefixlen;
unsigned char flags, scope;
DnsServer* link_set_dns_server(Link *l, DnsServer *s);
DnsServer* link_get_dns_server(Link *l);
-void link_next_dns_server(Link *l);
+void link_next_dns_server(Link *l, DnsServer *if_current);
DnssecMode link_get_dnssec_mode(Link *l);
bool link_dnssec_supported(Link *l);
if (r <= 0)
return r;
- if (manager_our_packet(m, p))
+ if (manager_packet_from_local_address(m, p))
return 0;
scope = manager_find_scope(m, p);
t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
if (t)
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
} else if (dns_packet_validate_query(p) > 0) {
log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
while (m->dns_queries)
dns_query_free(m->dns_queries);
+ m->stub_queries_by_packet = hashmap_free(m->stub_queries_by_packet);
+
dns_scope_free(m->unicast_scope);
/* At this point only orphaned streams should remain. All others should have been freed already by their
manager_dns_stub_stop(m);
manager_varlink_done(m);
+ manager_socket_graveyard_clear(m);
+
ordered_set_free(m->dns_extra_stub_listeners);
bus_verify_polkit_async_registry_free(m->polkit_registry);
return NULL;
}
-bool manager_our_packet(Manager *m, DnsPacket *p) {
+bool manager_packet_from_local_address(Manager *m, DnsPacket *p) {
assert(m);
assert(p);
+ /* Let's see if this packet comes from an IP address we have on any local interface */
+
return !!manager_find_link_address(m, p->family, &p->sender);
}
+bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p) {
+ DnsTransaction *t;
+
+ assert(m);
+ assert(p);
+
+ /* Let's see if we have a transaction with a query message with the exact same binary contents as the
+ * one we just got. If so, it's almost definitely a packet loop of some kind. */
+
+ t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+ if (!t)
+ return false;
+
+ return t->sent && dns_packet_equal(t->sent, p);
+}
+
DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
Link *l;
return tried;
}
+
+bool manager_server_is_stub(Manager *m, DnsServer *s) {
+ DnsStubListenerExtra *l;
+
+ assert(m);
+ assert(s);
+
+ /* Safety check: we generally already skip the main stub when parsing configuration. But let's be
+ * extra careful, and check here again */
+ if (s->family == AF_INET &&
+ s->address.in.s_addr == htobe32(INADDR_DNS_STUB) &&
+ dns_server_port(s) == 53)
+ return true;
+
+ /* Main reason to call this is to check server data against the extra listeners, and filter things
+ * out. */
+ ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners)
+ if (s->family == l->family &&
+ in_addr_equal(s->family, &s->address, &l->address) &&
+ dns_server_port(s) == dns_stub_listener_extra_port(l))
+ return true;
+
+ return false;
+}
#include "resolved-dns-stub.h"
#include "resolved-dns-trust-anchor.h"
#include "resolved-link.h"
+#include "resolved-socket-graveyard.h"
#define MANAGER_SEARCH_DOMAINS_MAX 256
#define MANAGER_DNS_SERVERS_MAX 256
Hashmap *dns_transactions;
LIST_HEAD(DnsQuery, dns_queries);
unsigned n_dns_queries;
+ Hashmap *stub_queries_by_packet;
LIST_HEAD(DnsStream, dns_streams);
unsigned n_dns_streams[_DNS_STREAM_TYPE_MAX];
/* mDNS */
int mdns_ipv4_fd;
int mdns_ipv6_fd;
+ sd_event_source *mdns_ipv4_event_source;
+ sd_event_source *mdns_ipv6_event_source;
/* DNS-SD */
Hashmap *dnssd_services;
- sd_event_source *mdns_ipv4_event_source;
- sd_event_source *mdns_ipv6_event_source;
-
/* dbus */
sd_bus *bus;
VarlinkServer *varlink_server;
sd_event_source *clock_change_event_source;
+
+ LIST_HEAD(SocketGraveyard, socket_graveyard);
+ SocketGraveyard *socket_graveyard_oldest;
+ size_t n_socket_graveyard;
};
/* Manager */
void manager_refresh_rrs(Manager *m);
int manager_next_hostname(Manager *m);
-bool manager_our_packet(Manager *m, DnsPacket *p);
+bool manager_packet_from_local_address(Manager *m, DnsPacket *p);
+bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p);
+
DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
void manager_verify_all(Manager *m);
void manager_cleanup_saved_user(Manager *m);
bool manager_next_dnssd_names(Manager *m);
+
+bool manager_server_is_stub(Manager *m, DnsServer *s);
if (r <= 0)
return r;
- if (manager_our_packet(m, p))
+ if (manager_packet_from_local_address(m, p))
return 0;
scope = manager_find_scope(m, p);
rr->ttl = 1;
}
- t = dns_scope_find_transaction(scope, rr->key, false);
+ t = dns_scope_find_transaction(scope, rr->key, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
/* Also look for the various types of ANY transactions */
- t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
- t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), false);
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
- t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
- dns_transaction_process_reply(t, p);
+ dns_transaction_process_reply(t, p, false);
}
- dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
+ dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, (uint32_t) -1, p->family, &p->sender);
} else if (dns_packet_validate_query(p) > 0) {
log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
goto fail;
}
- r = conservative_rename(AT_FDCWD, temp_path_stub, AT_FDCWD, PRIVATE_STUB_RESOLV_CONF);
+ r = conservative_rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF);
if (r < 0)
log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
log_error_errno(r, "Failed to symlink %s: %m", PRIVATE_STUB_RESOLV_CONF);
}
- r = conservative_rename(AT_FDCWD, temp_path_uplink, AT_FDCWD, PRIVATE_UPLINK_RESOLV_CONF);
+ r = conservative_rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF);
if (r < 0)
log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF);
RESOLV_CONF_FOREIGN,
RESOLV_CONF_MISSING,
_RESOLV_CONF_MODE_MAX,
- _RESOLV_CONF_MODE_INVALID = -1,
+ _RESOLV_CONF_MODE_INVALID = -EINVAL,
} ResolvConfMode;
int resolv_conf_mode(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "resolved-socket-graveyard.h"
+
+#define SOCKET_GRAVEYARD_USEC (5 * USEC_PER_SEC)
+#define SOCKET_GRAVEYARD_MAX 100
+
+/* This implements a socket "graveyard" for UDP sockets. If a socket fd is added to the graveyard it is kept
+ * open for a couple of more seconds, expecting one reply. Once the reply is received the fd is closed
+ * immediately, or if none is received it is closed after the timeout. Why all this? So that if we contact a
+ * DNS server, and it doesn't reply instantly, and we lose interest in the response and thus close the fd, we
+ * don't end up sending back an ICMP error once the server responds but we aren't listening anymore. (See
+ * https://github.com/systemd/systemd/issues/17421 for further information.)
+ *
+ * Note that we don't allocate any timer event source to clear up the graveyard once the socket's timeout is
+ * reached. Instead we operate lazily: we close old entries when adding a new fd to the graveyard, or
+ * whenever any code runs manager_socket_graveyard_process() — which the DNS transaction code does right
+ * before allocating a new UDP socket. */
+
+static SocketGraveyard* socket_graveyard_free(SocketGraveyard *g) {
+ if (!g)
+ return NULL;
+
+ if (g->manager) {
+ assert(g->manager->n_socket_graveyard > 0);
+ g->manager->n_socket_graveyard--;
+
+ if (g->manager->socket_graveyard_oldest == g)
+ g->manager->socket_graveyard_oldest = g->graveyard_prev;
+
+ LIST_REMOVE(graveyard, g->manager->socket_graveyard, g);
+
+ assert((g->manager->n_socket_graveyard > 0) == !!g->manager->socket_graveyard);
+ assert((g->manager->n_socket_graveyard > 0) == !!g->manager->socket_graveyard_oldest);
+ }
+
+ if (g->io_event_source) {
+ log_debug("Closing graveyard socket fd %i", sd_event_source_get_io_fd(g->io_event_source));
+ sd_event_source_unref(g->io_event_source);
+ }
+
+ return mfree(g);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(SocketGraveyard*, socket_graveyard_free);
+
+void manager_socket_graveyard_process(Manager *m) {
+ usec_t n = USEC_INFINITY;
+
+ assert(m);
+
+ while (m->socket_graveyard_oldest) {
+ SocketGraveyard *g = m->socket_graveyard_oldest;
+
+ if (n == USEC_INFINITY)
+ assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &n) >= 0);
+
+ if (g->deadline > n)
+ break;
+
+ socket_graveyard_free(g);
+ }
+}
+
+void manager_socket_graveyard_clear(Manager *m) {
+ assert(m);
+
+ while (m->socket_graveyard)
+ socket_graveyard_free(m->socket_graveyard);
+}
+
+static int on_io_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ SocketGraveyard *g = userdata;
+
+ assert(g);
+
+ /* An IO event happened on the graveyard fd. We don't actually care which event that is, and we don't
+ * read any incoming packet off the socket. We just close the fd, that's enough to not trigger the
+ * ICMP unreachable port event */
+
+ socket_graveyard_free(g);
+ return 0;
+}
+
+static void manager_socket_graveyard_make_room(Manager *m) {
+ assert(m);
+
+ while (m->n_socket_graveyard >= SOCKET_GRAVEYARD_MAX)
+ socket_graveyard_free(m->socket_graveyard_oldest);
+}
+
+int manager_add_socket_to_graveyard(Manager *m, int fd) {
+ _cleanup_(socket_graveyard_freep) SocketGraveyard *g = NULL;
+ int r;
+
+ assert(m);
+ assert(fd >= 0);
+
+ manager_socket_graveyard_process(m);
+ manager_socket_graveyard_make_room(m);
+
+ g = new(SocketGraveyard, 1);
+ if (!g)
+ return log_oom();
+
+ *g = (SocketGraveyard) {
+ .manager = m,
+ };
+
+ LIST_PREPEND(graveyard, m->socket_graveyard, g);
+ if (!m->socket_graveyard_oldest)
+ m->socket_graveyard_oldest = g;
+
+ m->n_socket_graveyard++;
+
+ assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &g->deadline) >= 0);
+ g->deadline += SOCKET_GRAVEYARD_USEC;
+
+ r = sd_event_add_io(m->event, &g->io_event_source, fd, EPOLLIN, on_io_event, g);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create graveyard IO source: %m");
+
+ r = sd_event_source_set_io_fd_own(g->io_event_source, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable graveyard IO source fd ownership: %m");
+
+ (void) sd_event_source_set_description(g->io_event_source, "graveyard");
+
+ log_debug("Added socket %i to graveyard", fd);
+
+ TAKE_PTR(g);
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+typedef struct SocketGraveyard SocketGraveyard;
+
+#include "resolved-manager.h"
+
+struct SocketGraveyard {
+ Manager *manager;
+ usec_t deadline;
+ sd_event_source *io_event_source;
+ LIST_FIELDS(SocketGraveyard, graveyard);
+};
+
+void manager_socket_graveyard_process(Manager *m);
+void manager_socket_graveyard_clear(Manager *m);
+
+int manager_add_socket_to_graveyard(Manager *m, int fd);
case DNS_TRANSACTION_NETWORK_DOWN:
return varlink_error(q->varlink_request, "io.systemd.Resolve.NetworkDown", NULL);
+ case DNS_TRANSACTION_NO_SOURCE:
+ return varlink_error(q->varlink_request, "io.systemd.Resolve.NoSource", NULL);
+
+ case DNS_TRANSACTION_STUB_LOOP:
+ return varlink_error(q->varlink_request, "io.systemd.Resolve.StubLoop", NULL);
+
case DNS_TRANSACTION_NOT_FOUND:
/* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
/* This checks that the specified client-provided flags parameter actually makes sense, and mangles
* it slightly. Specifically:
*
- * 1. We check that only the protocol flags and the NO_CNAME flag are on at most, plus the
+ * 1. We check that only the protocol flags and a bunch of NO_XYZ flags are on at most, plus the
* method-specific flags specified in 'ok'.
*
* 2. If no protocols are enabled we automatically convert that to "all protocols are enabled".
* "everything".
*/
- if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
+ if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
+ SD_RESOLVED_NO_CNAME|
+ SD_RESOLVED_NO_VALIDATE|
+ SD_RESOLVED_NO_SYNTHESIZE|
+ SD_RESOLVED_NO_CACHE|
+ SD_RESOLVED_NO_ZONE|
+ SD_RESOLVED_NO_TRUST_ANCHOR|
+ SD_RESOLVED_NO_NETWORK|
+ ok))
return false;
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
r = json_build(&entry,
JSON_BUILD_OBJECT(
- JSON_BUILD_PAIR("ifindex", JSON_BUILD_INTEGER(ifindex)),
+ JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", JSON_BUILD_INTEGER(ifindex)),
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(family)),
JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(p, FAMILY_ADDRESS_SIZE(family)))));
if (r < 0)
JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("addresses", JSON_BUILD_VARIANT(array)),
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized)),
- JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
finish:
if (r < 0) {
log_error_errno(r, "Failed to send hostname reply: %m");
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(ff)),
JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(&parsed, FAMILY_ADDRESS_SIZE(ff)))))),
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(canonical)),
- JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true)))));
+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true, true)|
+ SD_RESOLVED_SYNTHETIC))));
}
static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
_cleanup_(lookup_parameters_destroy) LookupParameters p = {
.family = AF_UNSPEC,
};
- Manager *m = userdata;
DnsQuery *q;
+ Manager *m;
int r;
assert(link);
+
+ m = varlink_server_get_userdata(varlink_get_server(link));
assert(m);
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))
if (r < 0 && r != -EALREADY)
return r;
- r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, p.ifindex, p.flags);
+ r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, p.ifindex, p.flags);
if (r < 0)
return r;
r = json_build(&entry,
JSON_BUILD_OBJECT(
- JSON_BUILD_PAIR("ifindex", JSON_BUILD_INTEGER(ifindex)),
+ JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", JSON_BUILD_INTEGER(ifindex)),
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized))));
if (r < 0)
goto finish;
r = varlink_replyb(q->varlink_request,
JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("names", JSON_BUILD_VARIANT(array)),
- JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
finish:
if (r < 0) {
log_error_errno(r, "Failed to send address reply: %m");
_cleanup_(lookup_parameters_destroy) LookupParameters p = {
.family = AF_UNSPEC,
};
- Manager *m = userdata;
DnsQuery *q;
+ Manager *m;
int r;
assert(link);
+
+ m = varlink_server_get_userdata(varlink_get_server(link));
assert(m);
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))
if (r < 0)
return r;
- r = dns_query_new(m, &q, question, question, p.ifindex, p.flags|SD_RESOLVED_NO_SEARCH);
+ r = dns_query_new(m, &q, question, question, NULL, p.ifindex, p.flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-resolved.service",
"Provide name resolution with caching using DNS, mDNS, LLMNR.",
answer = dns_answer_new(1);
assert_se(answer);
- assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+ assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey,
rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0);
answer = dns_answer_new(1);
assert_se(answer);
- assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+ assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey,
rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0);
answer = dns_answer_new(1);
assert_se(answer);
- assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+ assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
/* Validate the RR as it if was 2015-12-2 today */
assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0);
answer = dns_answer_new(1);
assert_se(answer);
- assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+ assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
/* Validate the RR as it if was 2015-12-11 today */
assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0);
answer = dns_answer_new(4);
assert_se(answer);
- assert_se(dns_answer_add(answer, mx1, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
- assert_se(dns_answer_add(answer, mx2, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
- assert_se(dns_answer_add(answer, mx3, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
- assert_se(dns_answer_add(answer, mx4, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
+ assert_se(dns_answer_add(answer, mx1, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
+ assert_se(dns_answer_add(answer, mx2, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
+ assert_se(dns_answer_add(answer, mx3, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
+ assert_se(dns_answer_add(answer, mx4, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0);
/* Validate the RR as it if was 2020-02-24 today */
assert_se(dnssec_verify_rrset(answer, mx1->key, rrsig, dnskey, 1582534685*USEC_PER_SEC, &result) >= 0);
if (argc > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires no arguments.");
- log_setup_service();
+ log_setup();
umask(0022);
%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \
if [ $1 -ge 1 ] && [ -x @bindir@/systemctl ]; then \
# Package upgrade, not uninstall \
- @bindir@/systemctl try-restart %{?*} || : \
+ for unit in %{?*}; do \
+ @bindir@/systemctl set-property $unit Markers=+needs-restart || : \
+ done \
fi \
%{nil}
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+configure_file(
+ input : 'macros.systemd.in',
+ output : 'macros.systemd',
+ configuration : substs,
+ install_dir : rpmmacrosdir == 'no' ? '' : rpmmacrosdir)
+
+# Those doesn't get installed anywhere, one of them needs to included in the
+# rpm spec file definition.
+configure_file(
+ input : 'triggers.systemd.in',
+ output : 'triggers.systemd',
+ configuration : substs)
+configure_file(
+ input : 'triggers.systemd.sh.in',
+ output : 'triggers.systemd.sh',
+ configuration : substs)
# The contents of this are an example to be copied into systemd.spec.
#
-# Minimum rpm version supported: 4.13.0
+# Minimum rpm version supported: 4.14.0
%transfiletriggerin -P 900900 -p <lua> -- @systemunitdir@ /etc/systemd/system
-- This script will run after any package is initially installed or
-- upgraded. We care about the case where a package is initially
-- installed, because other cases are covered by the *un scriptlets,
-- so sometimes we will reload needlessly.
-
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
elseif pid > 0 then
posix.wait(pid)
end
+
+ pid = posix.fork()
+ if pid == 0 then
+ assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked"))
+ elseif pid > 0 then
+ posix.wait(pid)
+ end
end
-%transfiletriggerun -p <lua> -- @systemunitdir@ /etc/systemd/system
+%transfiletriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system
-- On removal, we need to run daemon-reload after any units have been
--- removed. %transfiletriggerpostun would be ideal, but it does not get
--- executed for some reason.
+-- removed.
-- On upgrade, we need to run daemon-reload after any new unit files
-- have been installed, but before %postun scripts in packages get
--- executed. %transfiletriggerun gets the right list of files
--- but it is invoked too early (before changes happen).
--- %filetriggerpostun happens at the right time, but it fires for
--- every package.
--- To execute the reload at the right time, we create a state
--- file in %transfiletriggerun and execute the daemon-reload in
--- the first %filetriggerpostun.
-
+-- executed.
if posix.access("/run/systemd/system") then
- posix.mkdir("%{_localstatedir}/lib")
- posix.mkdir("%{_localstatedir}/lib/rpm-state")
- posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd")
- io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w")
-end
-
-%filetriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system
-if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then
- posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload")
- posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd")
pid = posix.fork()
if pid == 0 then
assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
end
end
-%transfiletriggerin -P 100700 -p <lua> -- @sysusersdir@
--- This script will process files installed in @sysusersdir@ to create
--- specified users automatically. The priority is set such that it
--- will run before the tmpfiles file trigger.
+%transfiletriggerpostun -P 10000 -p <lua> -- @systemunitdir@ /etc/systemd/system
+-- We restart remaining services that should be restarted here.
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
- assert(posix.exec("%{_bindir}/systemd-sysusers"))
+ assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked"))
elseif pid > 0 then
posix.wait(pid)
end
end
-%transfiletriggerin -P 100500 -p <lua> -- @tmpfilesdir@
--- This script will process files installed in @tmpfilesdir@ to create
--- tmpfiles automatically. The priority is set such that it will run
--- after the sysusers file trigger, but before any other triggers.
+%transfiletriggerin -P 100700 -p <lua> -- @sysusersdir@
+-- This script will process files installed in @sysusersdir@ to create
+-- specified users automatically. The priority is set such that it
+-- will run before the tmpfiles file trigger.
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
- assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create"))
+ assert(posix.exec("%{_bindir}/systemd-sysusers"))
elseif pid > 0 then
posix.wait(pid)
end
end
-%transfiletriggerin -p <lua> -- @udevhwdbdir@
+%transfiletriggerin -P 1000700 udev -p <lua> -- @udevhwdbdir@
-- This script will automatically invoke hwdb update if files have been
-- installed or updated in @udevhwdbdir@.
if posix.access("/run/systemd/system") then
end
end
-%transfiletriggerin -p <lua> -- @catalogdir@
+%transfiletriggerin -P 1000700 -p <lua> -- @catalogdir@
-- This script will automatically invoke journal catalog update if files
-- have been installed or updated in @catalogdir@.
if posix.access("/run/systemd/system") then
end
end
-%transfiletriggerin -p <lua> -- @udevrulesdir@
--- This script will automatically update udev with new rules if files
--- have been installed or updated in @udevrulesdir@.
+%transfiletriggerin -P 1000700 -p <lua> -- @binfmtdir@
+-- This script will automatically apply binfmt rules if files have been
+-- installed or updated in @binfmtdir@.
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
- assert(posix.exec("%{_bindir}/udevadm", "control", "--reload"))
+ assert(posix.exec("@rootlibexecdir@/systemd-binfmt"))
elseif pid > 0 then
posix.wait(pid)
end
end
-%transfiletriggerin -p <lua> -- @sysctldir@
--- This script will automatically apply sysctl rules if files have been
--- installed or updated in @sysctldir@.
+%transfiletriggerin -P 1000600 -p <lua> -- @tmpfilesdir@
+-- This script will process files installed in @tmpfilesdir@ to create
+-- tmpfiles automatically. The priority is set such that it will run
+-- after the sysusers file trigger, but before any other triggers.
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
- assert(posix.exec("@rootlibexecdir@/systemd-sysctl"))
+ assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create"))
elseif pid > 0 then
posix.wait(pid)
end
end
-%transfiletriggerin -p <lua> -- @binfmtdir@
--- This script will automatically apply binfmt rules if files have been
--- installed or updated in @binfmtdir@.
+%transfiletriggerin -P 1000600 udev -p <lua> -- @udevrulesdir@
+-- This script will automatically update udev with new rules if files
+-- have been installed or updated in @udevrulesdir@.
if posix.access("/run/systemd/system") then
pid = posix.fork()
if pid == 0 then
- assert(posix.exec("@rootlibexecdir@/systemd-binfmt"))
+ assert(posix.exec("%{_bindir}/udevadm", "control", "--reload"))
+ elseif pid > 0 then
+ posix.wait(pid)
+ end
+end
+
+%transfiletriggerin -P 1000500 -p <lua> -- @sysctldir@
+-- This script will automatically apply sysctl rules if files have been
+-- installed or updated in @sysctldir@.
+if posix.access("/run/systemd/system") then
+ pid = posix.fork()
+ if pid == 0 then
+ assert(posix.exec("@rootlibexecdir@/systemd-sysctl"))
elseif pid > 0 then
posix.wait(pid)
end
--- /dev/null
+# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# Copyright 2018 Neal Gompa
+
+# The contents of this are an example to be copied into systemd.spec.
+#
+# Minimum rpm version supported: 4.14.0
+
+%transfiletriggerin -P 900900 -- @systemunitdir@ /etc/systemd/system
+# This script will run after any package is initially installed or
+# upgraded. We care about the case where a package is initially
+# installed, because other cases are covered by the *un scriptlets,
+# so sometimes we will reload needlessly.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemctl daemon-reload || :
+ %{_bindir}/systemctl reload-or-restart --marked || :
+fi
+
+%transfiletriggerpostun -P 1000100 -- @systemunitdir@ /etc/systemd/system
+# On removal, we need to run daemon-reload after any units have been
+# removed.
+# On upgrade, we need to run daemon-reload after any new unit files
+# have been installed, but before %postun scripts in packages get
+# executed.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemctl daemon-reload || :
+fi
+
+%transfiletriggerpostun -P 10000 -- @systemunitdir@ /etc/systemd/system
+# We restart remaining services that should be restarted here.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemctl reload-or-restart --marked || :
+fi
+
+%transfiletriggerin -P 1000700 -- @sysusersdir@
+# This script will process files installed in @sysusersdir@ to create
+# specified users automatically. The priority is set such that it
+# will run before the tmpfiles file trigger.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemd-sysusers || :
+fi
+
+%transfiletriggerin -P 1000700 udev -- @udevhwdbdir@
+# This script will automatically invoke hwdb update if files have been
+# installed or updated in @udevhwdbdir@.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemd-hwdb update || :
+fi
+
+%transfiletriggerin -P 1000700 -- @catalogdir@
+# This script will automatically invoke journal catalog update if files
+# have been installed or updated in @catalogdir@.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/journalctl --update-catalog || :
+fi
+
+%transfiletriggerin -P 1000700 -- @binfmtdir@
+# This script will automatically apply binfmt rules if files have been
+# installed or updated in @binfmtdir@.
+if test -d "/run/systemd/system"; then
+ # systemd-binfmt might fail if binfmt_misc kernel module is not loaded
+ # during install
+ @rootlibexecdir@/systemd-binfmt || :
+fi
+
+%transfiletriggerin -P 1000600 -- @tmpfilesdir@
+# This script will process files installed in @tmpfilesdir@ to create
+# tmpfiles automatically. The priority is set such that it will run
+# after the sysusers file trigger, but before any other triggers.
+if test -d "/run/systemd/system"; then
+ %{_bindir}/systemd-tmpfiles --create || :
+fi
+
+%transfiletriggerin -P 1000600 udev -- @udevrulesdir@
+# This script will automatically update udev with new rules if files
+# have been installed or updated in @udevrulesdir@.
+if test -e /run/udev/control; then
+ %{_bindir}/udevadm control --reload || :
+fi
+
+%transfiletriggerin -P 1000500 -- @sysctldir@
+# This script will automatically apply sysctl rules if files have been
+# installed or updated in @sysctldir@.
+if test -d "/run/systemd/system"; then
+ @rootlibexecdir@/systemd-sysctl || :
+fi
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_success_action, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_success_action, value);
} else if (proc_cmdline_key_streq(key, "systemd.run_failure_action")) {
if (proc_cmdline_value_missing(key, value))
return 0;
- if (free_and_strdup(&arg_failure_action, value) < 0)
- return log_oom();
+ return free_and_strdup_warn(&arg_failure_action, value);
}
return 0;
#include "fd-util.h"
#include "format-util.h"
#include "main-func.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
" --on-timezone-change Run when the timezone changes\n"
" --on-clock-change Run when the realtime clock jumps\n"
" --timer-property=NAME=VALUE Set timer unit property\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
break;
case ARG_WORKING_DIRECTORY:
- r = parse_path_argument_and_warn(optarg, true, &arg_working_directory);
+ r = parse_path_argument(optarg, true, &arg_working_directory);
if (r < 0)
return r;
/* acl_free takes multiple argument types.
* Multiple cleanup functions are necessary. */
-DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(acl_t, acl_free, NULL);
#define acl_free_charp acl_free
-DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, acl_free_charp, NULL);
#define acl_free_uid_tp acl_free
-DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(uid_t*, acl_free_uid_tp, NULL);
#define acl_free_gid_tp acl_free
-DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gid_t*, acl_free_gid_tp, NULL);
#else
#define ACL_READ 0x04
n = recvmsg_safe(socket_fd, &msghdr, 0);
if (IN_SET(n, -EAGAIN, -EINTR))
continue;
+ if (n == -EXFULL) {
+ log_debug("Got message with truncated control data, ignoring.");
+ continue;
+ }
if (n < 0) {
r = (int) n;
goto finish;
*
* If @b is NULL, this is a no-op.
*/
-void barrier_destroy(Barrier *b) {
+Barrier* barrier_destroy(Barrier *b) {
if (!b)
- return;
+ return NULL;
b->me = safe_close(b->me);
b->them = safe_close(b->them);
safe_close_pair(b->pipe);
b->barriers = 0;
+ return NULL;
}
/**
#define BARRIER_NULL {-1, -1, {-1, -1}, 0}
int barrier_create(Barrier *obj);
-void barrier_destroy(Barrier *b);
+Barrier* barrier_destroy(Barrier *b);
DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy);
#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
-Bitmap *bitmap_new(void) {
+Bitmap* bitmap_new(void) {
return new0(Bitmap, 1);
}
-Bitmap *bitmap_copy(Bitmap *b) {
+Bitmap* bitmap_copy(Bitmap *b) {
Bitmap *ret;
ret = bitmap_new();
return ret;
}
-void bitmap_free(Bitmap *b) {
+Bitmap* bitmap_free(Bitmap *b) {
if (!b)
- return;
+ return NULL;
free(b->bitmaps);
- free(b);
+ return mfree(b);
}
int bitmap_ensure_allocated(Bitmap **b) {
size_t bitmaps_allocated;
} Bitmap;
-Bitmap *bitmap_new(void);
-Bitmap *bitmap_copy(Bitmap *b);
+Bitmap* bitmap_new(void);
+Bitmap* bitmap_copy(Bitmap *b);
int bitmap_ensure_allocated(Bitmap **b);
-void bitmap_free(Bitmap *b);
+Bitmap* bitmap_free(Bitmap *b);
int bitmap_set(Bitmap *b, unsigned n);
void bitmap_unset(Bitmap *b, unsigned n);
# include "macro.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(blkid_probe, blkid_free_probe, NULL);
#endif
NETDEV_BOND_MODE_BALANCE_TLB = BOND_MODE_TLB,
NETDEV_BOND_MODE_BALANCE_ALB = BOND_MODE_ALB,
_NETDEV_BOND_MODE_MAX,
- _NETDEV_BOND_MODE_INVALID = -1
+ _NETDEV_BOND_MODE_INVALID = -EINVAL,
} BondMode;
typedef enum BondXmitHashPolicy {
NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23 = BOND_XMIT_POLICY_ENCAP23,
NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34 = BOND_XMIT_POLICY_ENCAP34,
_NETDEV_BOND_XMIT_HASH_POLICY_MAX,
- _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1
+ _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -EINVAL,
} BondXmitHashPolicy;
typedef enum BondLacpRate {
NETDEV_BOND_LACP_RATE_SLOW,
NETDEV_BOND_LACP_RATE_FAST,
_NETDEV_BOND_LACP_RATE_MAX,
- _NETDEV_BOND_LACP_RATE_INVALID = -1,
+ _NETDEV_BOND_LACP_RATE_INVALID = -EINVAL,
} BondLacpRate;
typedef enum BondAdSelect {
NETDEV_BOND_AD_SELECT_BANDWIDTH,
NETDEV_BOND_AD_SELECT_COUNT,
_NETDEV_BOND_AD_SELECT_MAX,
- _NETDEV_BOND_AD_SELECT_INVALID = -1,
+ _NETDEV_BOND_AD_SELECT_INVALID = -EINVAL,
} BondAdSelect;
typedef enum BondFailOverMac {
NETDEV_BOND_FAIL_OVER_MAC_ACTIVE,
NETDEV_BOND_FAIL_OVER_MAC_FOLLOW,
_NETDEV_BOND_FAIL_OVER_MAC_MAX,
- _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1,
+ _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -EINVAL,
} BondFailOverMac;
typedef enum BondArpValidate {
NETDEV_BOND_ARP_VALIDATE_BACKUP,
NETDEV_BOND_ARP_VALIDATE_ALL,
_NETDEV_BOND_ARP_VALIDATE_MAX,
- _NETDEV_BOND_ARP_VALIDATE_INVALID = -1,
+ _NETDEV_BOND_ARP_VALIDATE_INVALID = -EINVAL,
} BondArpValidate;
typedef enum BondArpAllTargets {
NETDEV_BOND_ARP_ALL_TARGETS_ANY,
NETDEV_BOND_ARP_ALL_TARGETS_ALL,
_NETDEV_BOND_ARP_ALL_TARGETS_MAX,
- _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1,
+ _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -EINVAL,
} BondArpAllTargets;
typedef enum BondPrimaryReselect {
NETDEV_BOND_PRIMARY_RESELECT_BETTER,
NETDEV_BOND_PRIMARY_RESELECT_FAILURE,
_NETDEV_BOND_PRIMARY_RESELECT_MAX,
- _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1,
+ _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -EINVAL,
} BondPrimaryReselect;
const char *bond_mode_to_string(BondMode d) _const_;
}
static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
- return str_verscmp(a->id, b->id);
+ return strverscmp_improved(a->id, b->id);
}
static int boot_entries_find(
BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
_BOOT_ENTRY_MAX,
- _BOOT_ENTRY_INVALID = -1,
+ _BOOT_ENTRY_INVALID = -EINVAL,
} BootEntryType;
typedef struct BootEntry {
return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
}
-int bus_property_get_percent(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- char pstr[DECIMAL_STR_MAX(int) + 2];
- int p = *(int*) userdata;
-
- xsprintf(pstr, "%d%%", p);
-
- return sd_bus_message_append_basic(reply, 's', pstr);
-}
-
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
-int bus_property_get_percent(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
"Slice",
"ManagedOOMSwap",
"ManagedOOMMemoryPressure",
- "ManagedOOMMemoryPressureLimitPercent"))
+ "ManagedOOMPreference"))
return bus_append_string(m, field, eq);
+ if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {
+ char *n;
+
+ r = parse_permyriad(eq);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+
+ n = strjoina(field, "Permyriad");
+
+ r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) r);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
+
if (STR_IN_SET(field, "CPUAccounting",
"MemoryAccounting",
"IOAccounting",
"ReadWritePaths",
"ReadOnlyPaths",
"InaccessiblePaths",
+ "ExecPaths",
+ "NoExecPaths",
"RuntimeDirectory",
"StateDirectory",
"CacheDirectory",
if (unit_dependency_from_string(field) >= 0 ||
STR_IN_SET(field, "Documentation",
- "RequiresMountsFor"))
+ "RequiresMountsFor",
+ "Markers"))
return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
t = condition_type_from_string(field);
BUS_TRANSPORT_REMOTE,
BUS_TRANSPORT_MACHINE,
_BUS_TRANSPORT_MAX,
- _BUS_TRANSPORT_INVALID = -1
+ _BUS_TRANSPORT_INVALID = -EINVAL,
} BusTransport;
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name);
return 0;
}
-void bus_wait_for_jobs_free(BusWaitForJobs *d) {
+BusWaitForJobs* bus_wait_for_jobs_free(BusWaitForJobs *d) {
if (!d)
- return;
+ return NULL;
set_free(d->jobs);
free(d->name);
free(d->result);
- free(d);
+ return mfree(d);
}
int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
typedef struct BusWaitForJobs BusWaitForJobs;
int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret);
-void bus_wait_for_jobs_free(BusWaitForJobs *d);
+BusWaitForJobs* bus_wait_for_jobs_free(BusWaitForJobs *d);
int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path);
int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args);
int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
BUS_WAIT_FAILURE, /* dito, but something failed */
BUS_WAIT_RUNNING, /* Still something to wait for */
_BUS_WAIT_FOR_UNITS_STATE_MAX,
- _BUS_WAIT_FOR_UNITS_STATE_INVALID = -1,
+ _BUS_WAIT_FOR_UNITS_STATE_INVALID = -EINVAL,
} BusWaitForUnitsState;
typedef enum BusWaitForUnitsFlags {
/* Let's make sure that the microsecond component is safe to be stored in an 'int' */
assert_cc(INT_MAX >= USEC_PER_SEC);
-static void chain_free(CalendarComponent *c) {
- CalendarComponent *n;
-
+static CalendarComponent* chain_free(CalendarComponent *c) {
while (c) {
- n = c->next;
+ CalendarComponent *n = c->next;
free(c);
c = n;
}
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(CalendarComponent*, chain_free);
return false;
}
-int clock_set_timezone(int *min) {
- const struct timeval *tv_null = NULL;
+int clock_set_timezone(int *ret_minutesdelta) {
struct timespec ts;
struct tm tm;
int minutesdelta;
assert_se(localtime_r(&ts.tv_sec, &tm));
minutesdelta = tm.tm_gmtoff / 60;
- tz.tz_minuteswest = -minutesdelta;
- tz.tz_dsttime = 0; /* DST_NONE */
+ tz = (struct timezone) {
+ .tz_minuteswest = -minutesdelta,
+ .tz_dsttime = 0, /* DST_NONE */
+ };
- /*
- * If the RTC does not run in UTC but in local time, the very first
- * call to settimeofday() will set the kernel's timezone and will warp the
- * system clock, so that it runs in UTC instead of the local time we
- * have read from the RTC.
- */
- if (settimeofday(tv_null, &tz) < 0)
- return negative_errno();
+ /* If the RTC does not run in UTC but in local time, the very first call to settimeofday() will set
+ * the kernel's timezone and will warp the system clock, so that it runs in UTC instead of the local
+ * time we have read from the RTC. */
+ if (settimeofday(NULL, &tz) < 0)
+ return -errno;
+
+ if (ret_minutesdelta)
+ *ret_minutesdelta = minutesdelta;
- if (min)
- *min = minutesdelta;
return 0;
}
int clock_reset_timewarp(void) {
- const struct timeval *tv_null = NULL;
- struct timezone tz;
-
- tz.tz_minuteswest = 0;
- tz.tz_dsttime = 0; /* DST_NONE */
-
- /*
- * The very first call to settimeofday() does time warp magic. Do a
- * dummy call here, so the time warping is sealed and all later calls
- * behave as expected.
- */
- if (settimeofday(tv_null, &tz) < 0)
+ static const struct timezone tz = {
+ .tz_minuteswest = 0,
+ .tz_dsttime = 0, /* DST_NONE */
+ };
+
+ /* The very first call to settimeofday() does time warp magic. Do a dummy call here, so the time
+ * warping is sealed and all later calls behave as expected. */
+ if (settimeofday(NULL, &tz) < 0)
return -errno;
return 0;
ORDER_EQUAL,
ORDER_UNEQUAL,
_ORDER_MAX,
- _ORDER_INVALID = -1
+ _ORDER_INVALID = -EINVAL,
} OrderOperator;
static OrderOperator parse_order(const char **s) {
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected end of expression: %s", p);
}
- r = test_order(str_verscmp(u.release, s), order);
+ r = test_order(strverscmp_improved(u.release, s), order);
} else
/* No prefix? Then treat as glob string */
r = fnmatch(s, u.release, 0) == 0;
* class device */
r = dir_is_empty("/sys/class/tpmrm");
+ if (r == 0)
+ return true; /* nice! we have a device */
+
+ /* Hmm, so Linux doesn't know of the TPM2 device (or we couldn't check for it), most likely because
+ * the driver wasn't loaded yet. Let's see if the firmware knows about a TPM2 device, in this
+ * case. This way we can answer the TPM2 question already during early boot (where we most likely
+ * need it) */
+ if (efi_has_tpm2())
+ return true;
+
+ /* OK, this didn't work either, in this case propagate the original errors */
if (r == -ENOENT)
return false;
if (r < 0)
CONDITION_CONTROL_GROUP_CONTROLLER,
_CONDITION_TYPE_MAX,
- _CONDITION_TYPE_INVALID = -1
+ _CONDITION_TYPE_INVALID = -EINVAL,
} ConditionType;
typedef enum ConditionResult {
CONDITION_FAILED,
CONDITION_ERROR,
_CONDITION_RESULT_MAX,
- _CONDITION_RESULT_INVALID = -1
+ _CONDITION_RESULT_INVALID = -EINVAL,
} ConditionResult;
typedef struct Condition {
assert(rvalue);
assert(data);
- if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
- return log_oom();
-
- return 0;
+ return free_and_strdup_warn(s, empty_to_null(rvalue));
}
int config_parse_path(
x = log_facility_unshifted_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, x, "Failed to parse log facility, ignoring: %s", rvalue);
return 0;
}
x = log_level_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, x, "Failed to parse log level, ignoring: %s", rvalue);
return 0;
}
r = signal_from_string(rvalue);
if (r <= 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse signal name, ignoring: %s", rvalue);
return 0;
}
}
DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");
+DEFINE_CONFIG_PARSE(config_parse_permyriad, parse_permyriad, "Failed to parse permyriad value");
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
+CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
typedef enum Disabled {
DISABLED_CONFIGURATION,
\
x = from_string(rvalue); \
if (x < 0) { \
- log_syntax(unit, LOG_WARNING, filename, line, 0, \
+ log_syntax(unit, LOG_WARNING, filename, line, x, \
msg ", ignoring: %s", rvalue); \
return 0; \
} \
\
x = name##_from_string(rvalue); \
if (x < 0) { \
- log_syntax(unit, LOG_WARNING, filename, line, 0, \
+ log_syntax(unit, LOG_WARNING, filename, line, x, \
msg ", ignoring: %s", rvalue); \
return 0; \
} \
r = extract_first_word(&p, &en, NULL, 0); \
if (r == -ENOMEM) \
return log_oom(); \
- if (r < 0) \
- return log_syntax(unit, LOG_ERR, filename, line, 0, \
- msg ": %s", en); \
+ if (r < 0) { \
+ log_syntax(unit, LOG_WARNING, filename, line, r, \
+ msg ", ignoring: %s", en); \
+ return 0; \
+ } \
if (r == 0) \
break; \
\
- if ((x = name##_from_string(en)) < 0) { \
- log_syntax(unit, LOG_WARNING, filename, line, 0, \
+ x = name##_from_string(en); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_WARNING, filename, line, x, \
msg ", ignoring: %s", en); \
continue; \
} \
COREDUMP_FILTER_PRIVATE_DAX,
COREDUMP_FILTER_SHARED_DAX,
_COREDUMP_FILTER_MAX,
- _COREDUMP_FILTER_INVALID = -1,
+ _COREDUMP_FILTER_INVALID = -EINVAL,
} CoredumpFilter;
#define COREDUMP_FILTER_MASK_DEFAULT (1u << COREDUMP_FILTER_PRIVATE_ANONYMOUS | \
int dlopen_cryptsetup(void);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, crypt_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, sym_crypt_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct crypt_device *, crypt_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct crypt_device *, sym_crypt_free, NULL);
void cryptsetup_enable_logging(struct crypt_device *cd);
#include "chattr-util.h"
#include "copy.h"
#include "dirent-util.h"
+#include "discover-image.h"
#include "dissect-image.h"
#include "env-file.h"
#include "env-util.h"
#include "lockfile-util.h"
#include "log.h"
#include "loop-util.h"
-#include "machine-image.h"
#include "macro.h"
#include "mkdir.h"
#include "nulstr-util.h"
r = asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino);
else
return -ENOTTY;
-
if (r < 0)
return -ENOMEM;
}
}
int image_name_lock(const char *name, int operation, LockFile *ret) {
+ const char *p;
+
assert(name);
assert(ret);
/* Locks an image name, regardless of the precise path used. */
+ if (streq(name, ".host"))
+ return -EBUSY;
+
if (!image_name_is_valid(name))
return -EINVAL;
return 0;
}
- if (streq(name, ".host"))
- return -EBUSY;
-
- const char *p = strjoina("/run/systemd/nspawn/locks/name-", name);
(void) mkdir_p("/run/systemd/nspawn/locks", 0700);
+
+ p = strjoina("/run/systemd/nspawn/locks/name-", name);
return make_lock_file(p, operation, ret);
}
IMAGE_PORTABLE,
IMAGE_EXTENSION,
_IMAGE_CLASS_MAX,
- _IMAGE_CLASS_INVALID = -1
+ _IMAGE_CLASS_INVALID = -EINVAL,
} ImageClass;
typedef enum ImageType {
IMAGE_RAW,
IMAGE_BLOCK,
_IMAGE_TYPE_MAX,
- _IMAGE_TYPE_INVALID = -1
+ _IMAGE_TYPE_INVALID = -EINVAL,
} ImageType;
typedef struct Image {
return 0;
}
-static inline void dm_deferred_remove_clean(char *name) {
+static inline char* dm_deferred_remove_clean(char *name) {
if (!name)
- return;
+ return NULL;
(void) sym_crypt_deactivate_by_name(NULL, name, CRYPT_DEACTIVATE_DEFERRED);
- free(name);
+ return mfree(name);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char *, dm_deferred_remove_clean);
[META_HOSTNAME] = "/etc/hostname\0",
[META_MACHINE_ID] = "/etc/machine-id\0",
[META_MACHINE_INFO] = "/etc/machine-info\0",
- [META_OS_RELEASE] = "/etc/os-release\0"
- "/usr/lib/os-release\0",
+ [META_OS_RELEASE] = ("/etc/os-release\0"
+ "/usr/lib/os-release\0"),
};
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL;
[PARTITION_VAR] = "var",
};
+int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options) {
+ _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
+ _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
+ _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
+ DissectImageFlags dissect_image_flags;
+ int r;
+
+ assert(src);
+ assert(dest);
+
+ r = verity_settings_load(&verity, src, NULL, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to load root hash: %m");
+
+ dissect_image_flags = verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
+
+ r = loop_device_make_by_path(
+ src,
+ -1,
+ verity.data_path ? 0 : LO_FLAGS_PARTSCAN,
+ &loop_device);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to create loop device for image: %m");
+
+ r = dissect_image(
+ loop_device->fd,
+ &verity,
+ options,
+ dissect_image_flags,
+ &dissected_image);
+ /* No partition table? Might be a single-filesystem image, try again */
+ if (!verity.data_path && r == -ENOPKG)
+ r = dissect_image(
+ loop_device->fd,
+ &verity,
+ options,
+ dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
+ &dissected_image);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to dissect image: %m");
+
+ r = dissected_image_decrypt(
+ dissected_image,
+ NULL,
+ &verity,
+ dissect_image_flags,
+ &decrypted_image);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to decrypt dissected image: %m");
+
+ r = mkdir_p_label(dest, 0755);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to create destination directory %s: %m", dest);
+ r = umount_recursive(dest, 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to umount under destination directory %s: %m", dest);
+
+ r = dissected_image_mount(dissected_image, dest, UID_INVALID, dissect_image_flags);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to mount image: %m");
+
+ if (decrypted_image) {
+ r = decrypted_image_relinquish(decrypted_image);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to relinquish decrypted image: %m");
+ }
+
+ loop_device_relinquish(loop_device);
+
+ return 0;
+}
+
DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);
PARTITION_TMP,
PARTITION_VAR,
_PARTITION_DESIGNATOR_MAX,
- _PARTITION_DESIGNATOR_INVALID = -1
+ _PARTITION_DESIGNATOR_INVALID = -EINVAL,
} PartitionDesignator;
static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) {
bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator d);
int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image);
+
+int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options);
+++ /dev/null
-../boot/efi/loader-features.h
\ No newline at end of file
return 0;
}
+bool efi_has_tpm2(void) {
+ static int cache = -1;
+
+ /* Returns whether the system has a TPM2 chip which is known to the EFI firmware. */
+
+ if (cache < 0) {
+
+ /* First, check if we are on an EFI boot at all. */
+ if (!is_efi_boot())
+ cache = false;
+ else {
+ /* Then, check if the ACPI table "TPM2" exists, which is the TPM2 event log table, see:
+ * https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpecification_v1.20_r8.pdf
+ * This table exists whenever the firmware is hooked up to TPM2. */
+ cache = access("/sys/firmware/acpi/tables/TPM2", F_OK) >= 0;
+ if (!cache && errno != ENOENT)
+ log_debug_errno(errno, "Unable to test whether /sys/firmware/acpi/tables/TPM2 exists, assuming it doesn't: %m");
+ }
+ }
+
+ return cache;
+}
+
#endif
bool efi_loader_entry_name_valid(const char *s) {
int efi_loader_get_config_timeout_one_shot(usec_t *ret);
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat);
+bool efi_has_tpm2(void);
+
#else
static inline int efi_reboot_to_firmware_supported(void) {
return -EOPNOTSUPP;
}
+static inline bool efi_has_tpm2(void) {
+ return false;
+}
+
#endif
bool efi_loader_entry_name_valid(const char *s);
/* We reuse the kernel provided enum which does not contain negative value. So, the cast
* below is mandatory. Otherwise, the check below always passes and access an invalid address. */
if ((int) mode < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, mode,
"Failed to parse advertise mode, ignoring: %s", w);
continue;
}
DUP_HALF = DUPLEX_HALF,
DUP_FULL = DUPLEX_FULL,
_DUP_MAX,
- _DUP_INVALID = -1
+ _DUP_INVALID = -EINVAL,
} Duplex;
typedef enum WakeOnLan {
WOL_MAGICSECURE,
WOL_OFF,
_WOL_MAX,
- _WOL_INVALID = -1
+ _WOL_INVALID = -EINVAL,
} WakeOnLan;
typedef enum NetDevFeature {
NET_DEV_FEAT_TSO,
NET_DEV_FEAT_TSO6,
_NET_DEV_FEAT_MAX,
- _NET_DEV_FEAT_INVALID = -1
+ _NET_DEV_FEAT_INVALID = -EINVAL,
} NetDevFeature;
typedef enum NetDevPort {
NET_DEV_PORT_NONE = PORT_NONE,
NET_DEV_PORT_OTHER = PORT_OTHER,
_NET_DEV_PORT_MAX,
- _NET_DEV_PORT_INVALID = -1
+ _NET_DEV_PORT_INVALID = -EINVAL,
} NetDevPort;
#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX)
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
-static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
+static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid, bool set_systemd_exec_pid) {
pid_t _pid;
int r;
(void) rlimit_nofile_safe();
+ if (set_systemd_exec_pid) {
+ r = setenv_systemd_exec_pid(false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to set $SYSTEMD_EXEC_PID, ignoring: %m");
+ }
+
if (!argv) {
_argv[0] = (char*) path;
_argv[1] = NULL;
return log_error_errno(fd, "Failed to open serialization file: %m");
}
- r = do_spawn(t, argv, fd, &pid);
+ r = do_spawn(t, argv, fd, &pid, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID));
if (r <= 0)
continue;
return r;
STRV_FOREACH_PAIR(x, y, new) {
- char *p;
-
if (!env_name_is_valid(*x)) {
log_warning("Invalid variable assignment \"%s=...\", ignoring.", *x);
continue;
}
- p = strjoin(*x, "=", *y);
- if (!p)
- return -ENOMEM;
-
- r = strv_env_replace(env, p);
+ r = strv_env_assign(env, *x, *y);
if (r < 0)
return r;
return -errno;
}
- return r;
+ return 0;
}
static int gather_environment_collect(int fd, void *arg) {
};
typedef enum {
- EXEC_DIR_NONE = 0, /* No execdir flags */
- EXEC_DIR_PARALLEL = 1 << 0, /* Execute scripts in parallel, if possible */
- EXEC_DIR_IGNORE_ERRORS = 1 << 1, /* Ignore non-zero exit status of scripts */
+ EXEC_DIR_NONE = 0, /* No execdir flags */
+ EXEC_DIR_PARALLEL = 1 << 0, /* Execute scripts in parallel, if possible */
+ EXEC_DIR_IGNORE_ERRORS = 1 << 1, /* Ignore non-zero exit status of scripts */
+ EXEC_DIR_SET_SYSTEMD_EXEC_PID = 1 << 2, /* Set $SYSTEMD_EXEC_PID environment variable */
} ExecDirFlags;
typedef enum ExecCommandFlags {
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
/* Temporary work-around for broken glibc vs. linux kernel header definitions
* This is already fixed upstream, remove this when distributions have updated.
#include "macro.h"
#include "socket-util.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct xtc_handle*, iptc_free, NULL);
static int entry_fill_basics(
struct ipt_entry *entry,
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <arpa/inet.h>
#include <endian.h>
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
+#include "process-util.h"
+#include "signal-util.h"
#include "sort-util.h"
#include "string-util.h"
#include "strxcpyx.h"
#include "terminal-util.h"
#include "time-util.h"
+#include "user-util.h"
#include "utf8.h"
#include "util.h"
int ifindex;
union in_addr_union address;
sd_id128_t id128;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
/* … add more here as we start supporting more cell data types … */
};
} TableData;
case TABLE_UINT:
case TABLE_PERCENT:
case TABLE_IFINDEX:
+ case TABLE_SIGNAL:
return sizeof(int);
case TABLE_IN_ADDR:
case TABLE_ID128:
return sizeof(sd_id128_t);
+ case TABLE_UID:
+ return sizeof(uid_t);
+ case TABLE_GID:
+ return sizeof(gid_t);
+ case TABLE_PID:
+ return sizeof(pid_t);
+
default:
assert_not_reached("Uh? Unexpected cell type");
}
bool b;
union in_addr_union address;
sd_id128_t id128;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
} buffer;
switch (type) {
break;
case TABLE_INT:
+ case TABLE_SIGNAL:
buffer.int_val = va_arg(ap, int);
data = &buffer.int_val;
break;
data = &buffer.id128;
break;
+ case TABLE_UID:
+ buffer.uid = va_arg(ap, uid_t);
+ data = &buffer.uid;
+ break;
+
+ case TABLE_GID:
+ buffer.gid = va_arg(ap, gid_t);
+ data = &buffer.gid;
+ break;
+
+ case TABLE_PID:
+ buffer.pid = va_arg(ap, pid_t);
+ data = &buffer.pid;
+ break;
+
case TABLE_SET_MINIMUM_WIDTH: {
size_t w = va_arg(ap, size_t);
return CMP(a->size, b->size);
case TABLE_INT:
+ case TABLE_SIGNAL:
return CMP(a->int_val, b->int_val);
case TABLE_INT8:
case TABLE_ID128:
return memcmp(&a->id128, &b->id128, sizeof(sd_id128_t));
+ case TABLE_UID:
+ return CMP(a->uid, b->uid);
+
+ case TABLE_GID:
+ return CMP(a->gid, b->gid);
+
+ case TABLE_PID:
+ return CMP(a->pid, b->pid);
+
default:
;
}
break;
}
+ case TABLE_UID: {
+ _cleanup_free_ char *p = NULL;
+
+ if (!uid_is_valid(d->uid))
+ return "n/a";
+
+ p = new(char, DECIMAL_STR_WIDTH(d->uid) + 1);
+ if (!p)
+ return NULL;
+
+ sprintf(p, UID_FMT, d->uid);
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_GID: {
+ _cleanup_free_ char *p = NULL;
+
+ if (!gid_is_valid(d->gid))
+ return "n/a";
+
+ p = new(char, DECIMAL_STR_WIDTH(d->gid) + 1);
+ if (!p)
+ return NULL;
+
+ sprintf(p, GID_FMT, d->gid);
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_PID: {
+ _cleanup_free_ char *p = NULL;
+
+ if (!pid_is_valid(d->pid))
+ return "n/a";
+
+ p = new(char, DECIMAL_STR_WIDTH(d->pid) + 1);
+ if (!p)
+ return NULL;
+
+ sprintf(p, PID_FMT, d->pid);
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_SIGNAL: {
+ _cleanup_free_ char *p = NULL;
+ const char *suffix;
+
+ suffix = signal_to_string(d->int_val);
+ if (!suffix)
+ return "n/a";
+
+ p = strjoin("SIG", suffix);
+ if (!p)
+ return NULL;
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
default:
assert_not_reached("Unexpected type?");
}
if (width[j] < minimum_width[j])
width[j] = minimum_width[j];
- assert(width[j] >= requested_width[j]);
- delta = width[j] - requested_width[j];
+ delta = LESS_BY(width[j], requested_width[j]);
/* Subtract what we just added from the rest */
if (extra > delta)
return json_variant_new_integer(ret, d->percent);
case TABLE_IFINDEX:
+ if (d->ifindex <= 0)
+ return json_variant_new_null(ret);
+
return json_variant_new_integer(ret, d->ifindex);
case TABLE_IN_ADDR:
return json_variant_new_string(ret, id128_to_uuid_string(d->id128, buf));
}
+ case TABLE_UID:
+ if (!uid_is_valid(d->uid))
+ return json_variant_new_null(ret);
+
+ return json_variant_new_integer(ret, d->uid);
+
+ case TABLE_GID:
+ if (!gid_is_valid(d->gid))
+ return json_variant_new_null(ret);
+
+ return json_variant_new_integer(ret, d->gid);
+
+ case TABLE_PID:
+ if (!pid_is_valid(d->pid))
+ return json_variant_new_null(ret);
+
+ return json_variant_new_integer(ret, d->pid);
+
+ case TABLE_SIGNAL:
+ if (!SIGNAL_VALID(d->int_val))
+ return json_variant_new_null(ret);
+
+ return json_variant_new_integer(ret, d->int_val);
+
default:
return -EINVAL;
}
return fflush_and_check(f);
}
+
+int table_print_with_pager(
+ Table *t,
+ JsonFormatFlags json_format_flags,
+ PagerFlags pager_flags,
+ bool show_header) {
+
+ bool saved_header;
+ int r;
+
+ assert(t);
+
+ /* A all-in-one solution for showing tables, and turning on a pager first. Also optionally suppresses
+ * the table header and logs about any error. */
+
+ if (json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
+ (void) pager_open(pager_flags);
+
+ saved_header = t->header;
+ t->header = show_header;
+ r = table_print_json(t, stdout, json_format_flags);
+ t->header = saved_header;
+ if (r < 0)
+ return table_log_print_error(r);
+
+ return 0;
+}
#include "json.h"
#include "macro.h"
+#include "pager.h"
typedef enum TableDataType {
TABLE_EMPTY,
TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */
TABLE_ID128,
TABLE_UUID,
+ TABLE_UID,
+ TABLE_GID,
+ TABLE_PID,
+ TABLE_SIGNAL,
_TABLE_DATA_TYPE_MAX,
/* The following are not really data types, but commands for table_add_cell_many() to make changes to
TABLE_SET_URL,
TABLE_SET_UPPERCASE,
- _TABLE_DATA_TYPE_INVALID = -1,
+ _TABLE_DATA_TYPE_INVALID = -EINVAL,
} TableDataType;
-/* PIDs are just 32bit signed integers on Linux */
-#define TABLE_PID TABLE_INT32
-assert_cc(sizeof(pid_t) == sizeof(int32_t));
-
-/* UIDs/GIDs are just 32bit unsigned integers on Linux */
-#define TABLE_UID TABLE_UINT32
-#define TABLE_GID TABLE_UINT32
-assert_cc(sizeof(uid_t) == sizeof(uint32_t));
-assert_cc(sizeof(gid_t) == sizeof(uint32_t));
-
typedef struct Table Table;
typedef struct TableCell TableCell;
int table_to_json(Table *t, JsonVariant **ret);
int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags);
+int table_print_with_pager(Table *t, JsonFormatFlags json_format_flags, PagerFlags pager_flags, bool show_header);
+
#define table_log_add_error(r) \
log_error_errno(r, "Failed to add cell(s) to table: %m")
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
set -eu
$1 -dM -include netinet/in.h - </dev/null | \
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
import sys
import os
const char *roothash,
const char *options) {
- _cleanup_free_ char *name_escaped = NULL, *data_what_escaped = NULL, *hash_what_escaped,
+ _cleanup_free_ char *name_escaped = NULL, *data_what_escaped = NULL, *hash_what_escaped = NULL,
*roothash_escaped = NULL, *options_escaped = NULL;
assert(f);
NETDEV_GENEVE_DF_SET = GENEVE_DF_SET,
NETDEV_GENEVE_DF_INHERIT = GENEVE_DF_INHERIT,
_NETDEV_GENEVE_DF_MAX,
- _NETDEV_GENEVE_DF_INVALID = -1,
+ _NETDEV_GENEVE_DF_INVALID = -EINVAL,
} GeneveDF;
const char *geneve_df_to_string(GeneveDF d) _const_;
[HOSTNAME_FALLBACK] = "fallback",
};
-DEFINE_STRING_TABLE_LOOKUP_TO_STRING(hostname_source, HostnameSource);
+DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);
HOSTNAME_STATIC, /* from /etc/hostname */
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
- _HOSTNAME_INVALID = -1,
+ _HOSTNAME_INVALID = -EINVAL,
} HostnameSource;
-const char* hostname_source_to_string(HostnameSource source);
+const char* hostname_source_to_string(HostnameSource source) _const_;
+HostnameSource hostname_source_from_string(const char *str) _pure_;
+
int sethostname_idempotent(const char *s);
int shorten_overlong(const char *s, char **ret);
ID128_PRINT_UUID,
ID128_PRINT_PRETTY,
_ID128_PRETTY_PRINT_MODE_MAX,
- _ID128_PRETTY_PRINT_MODE_INVALID = -1
+ _ID128_PRETTY_PRINT_MODE_INVALID = -EINVAL,
} Id128PrettyPrintMode;
int id128_pretty_print_sample(const char *name, sd_id128_t id);
int import_assign_pool_quota_and_warn(const char *path) {
int r;
- r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true);
- if (r == -ENOTTY) {
- log_debug_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, as directory is not on btrfs or not a subvolume. Ignoring.");
- return 0;
- }
- if (r < 0)
- return log_error_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines: %m");
- if (r > 0)
- log_info("Set up default quota hierarchy for /var/lib/machines.");
+ assert(path);
r = btrfs_subvol_auto_qgroup(path, 0, true);
if (r == -ENOTTY) {
IMPORT_VERIFY_CHECKSUM,
IMPORT_VERIFY_SIGNATURE,
_IMPORT_VERIFY_MAX,
- _IMPORT_VERIFY_INVALID = -1,
+ _IMPORT_VERIFY_INVALID = -EINVAL,
} ImportVerify;
int import_url_last_component(const char *url, char **ret);
return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
}
-static void unit_file_list_free_one(UnitFileList *f) {
+static UnitFileList* unit_file_list_free_one(UnitFileList *f) {
if (!f)
- return;
+ return NULL;
free(f->path);
- free(f);
+ return mfree(f);
}
Hashmap* unit_file_list_free(Hashmap *h) {
UNIT_FILE_PRESET_ENABLE_ONLY,
UNIT_FILE_PRESET_DISABLE_ONLY,
_UNIT_FILE_PRESET_MAX,
- _UNIT_FILE_PRESET_INVALID = -1
+ _UNIT_FILE_PRESET_INVALID = -EINVAL,
};
enum UnitFileChangeType {
UNIT_FILE_TYPE_SYMLINK,
UNIT_FILE_TYPE_MASKED,
_UNIT_FILE_TYPE_MAX,
- _UNIT_FILE_TYPE_INVALID = -1,
+ _UNIT_FILE_TYPE_INVALID = -EINVAL,
};
struct UnitFileInstallInfo {
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
BEGIN{
print "static const char* const ip_protocol_names[] = { "
}
NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3,
NETDEV_IPVLAN_MODE_L3S = IPVLAN_MODE_L3S,
_NETDEV_IPVLAN_MODE_MAX,
- _NETDEV_IPVLAN_MODE_INVALID = -1
+ _NETDEV_IPVLAN_MODE_INVALID = -EINVAL,
} IPVlanMode;
typedef enum IPVlanFlags {
NETDEV_IPVLAN_FLAGS_PRIVATE = IPVLAN_F_PRIVATE,
NETDEV_IPVLAN_FLAGS_VEPA = IPVLAN_F_VEPA,
_NETDEV_IPVLAN_FLAGS_MAX,
- _NETDEV_IPVLAN_FLAGS_INVALID = -1
+ _NETDEV_IPVLAN_FLAGS_INVALID = -EINVAL,
} IPVlanFlags;
const char *ipvlan_mode_to_string(IPVlanMode d) _const_;
JSON_TOKEN_BOOLEAN,
JSON_TOKEN_NULL,
_JSON_TOKEN_MAX,
- _JSON_TOKEN_INVALID = -1,
+ _JSON_TOKEN_INVALID = -EINVAL,
};
int json_tokenize(const char **p, char **ret_string, JsonValue *ret_value, unsigned *ret_line, unsigned *ret_column, void **state, unsigned *line, unsigned *column);
JsonSource *source;
unsigned line, column;
- JsonVariantType type:5;
+ /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
+ uint16_t depth;
+
+ JsonVariantType type:8;
/* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above
* is valid. If false, the 'n_ref' field above is valid instead. */
/* If in addition to this object all objects referenced by it are also ordered strictly by name */
bool normalized:1;
- /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
- uint16_t depth;
-
union {
/* For simple types we store the value in-line. */
JsonValue value;
if (source && source_line > 0 && source_column > 0)
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
NULL);
else if (source_line > 0 && source_column > 0)
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
NULL);
else
return log_struct_internal(
- LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+ level,
error,
file, line, func,
"MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
return unhexmem(json_variant_string(v), (size_t) -1, ret, ret_size);
}
-int json_parse_cmdline_parameter_and_warn(const char *s, JsonFormatFlags *ret) {
- assert(s);
- assert(ret);
-
- if (streq(s, "pretty"))
- *ret = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO;
- else if (streq(s, "short"))
- *ret = JSON_FORMAT_NEWLINE;
- else if (streq(s, "off"))
- *ret = JSON_FORMAT_OFF;
- else if (streq(s, "help")) {
- puts("pretty\n"
- "short\n"
- "off");
- return 0; /* 0 means → we showed a brief help, exit now */
- } else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json= switch: %s", s);
-
- return 1; /* 1 means → properly parsed */
-}
-
static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = {
[JSON_VARIANT_STRING] = "string",
[JSON_VARIANT_INTEGER] = "integer",
JSON_VARIANT_OBJECT,
JSON_VARIANT_NULL,
_JSON_VARIANT_TYPE_MAX,
- _JSON_VARIANT_TYPE_INVALID = -1
+ _JSON_VARIANT_TYPE_INVALID = -EINVAL,
} JsonVariantType;
int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size);
int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size);
-int json_parse_cmdline_parameter_and_warn(const char *s, JsonFormatFlags *ret);
-
const char *json_variant_type_to_string(JsonVariantType t);
JsonVariantType json_variant_type_from_string(const char *s);
#include "macro.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_table*, mnt_free_table, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_iter*, mnt_free_iter, NULL);
static inline int libmount_parse(
const char *path,
else
prefix = "--";
- if (colors_enabled())
- newline = strjoina(ANSI_NORMAL "\n", ansi_grey(), prefix, ANSI_NORMAL " ", ansi_green());
- else
- newline = strjoina("\n", prefix, " ");
+ newline = strjoina(ansi_normal(), "\n", ansi_grey(), prefix, ansi_normal(), " ", ansi_green());
z = strreplace(strstrip(t), "\n", newline);
if (!z)
return log_oom();
- if (colors_enabled())
- fprintf(f, "%s%s %s%s", ansi_grey(), prefix, ANSI_NORMAL, ansi_green());
- else
- fprintf(f, "%s ", prefix);
+ fprintf(f, "%s%s %s%s", ansi_grey(), prefix, ansi_normal(), ansi_green());
fputs(z, f);
- if (colors_enabled())
- fputs(ANSI_NORMAL "\n", f);
- else
- fputc('\n', f);
+ fprintf(f, "%s\n", ansi_normal());
return 1;
}
if (line == 0 && noaccess)
fprintf(f, "Warning: some journal files were not opened due to insufficient permissions.");
else if (!noaccess)
- fprintf(f, "Warning: journal has been rotated since unit was started, output may be incomplete.\n");
+ fprintf(f, "Notice: journal has been rotated since unit was started, output may be incomplete.\n");
else
fprintf(f, "Warning: journal has been rotated since unit was started and some journal "
"files were not opened due to insufficient permissions, output may be incomplete.\n");
NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU,
NETDEV_MACVLAN_MODE_SOURCE = MACVLAN_MODE_SOURCE,
_NETDEV_MACVLAN_MODE_MAX,
- _NETDEV_MACVLAN_MODE_INVALID = -1
+ _NETDEV_MACVLAN_MODE_INVALID = -EINVAL,
} MacVlanMode;
const char *macvlan_mode_to_string(MacVlanMode d) _const_;
dev-setup.c
dev-setup.h
devnode-acl.h
+ discover-image.c
+ discover-image.h
dissect-image.c
dissect-image.h
dm-util.c
dns-domain.h
dropin.c
dropin.h
- efi-loader-features.h
efi-loader.c
efi-loader.h
enable-mempool.c
loopback-setup.h
machine-id-setup.c
machine-id-setup.h
- machine-image.c
- machine-image.h
machine-pool.c
machine-pool.h
macvlan-util.c
output-mode.h
pager.c
pager.h
+ parse-argument.c
+ parse-argument.h
pe-header.h
pkcs11-util.c
pkcs11-util.h
fname = 'syscall-list.h'
syscall_list_h = custom_target(
fname,
- input : syscall_names_text,
+ input : syscall_list_txt,
output : fname,
command : [generate_syscall_list,
'@INPUT@'],
DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_ctx*, kmod_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_module*, kmod_module_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_list*, kmod_module_unref_list);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct kmod_list*, kmod_module_unref_list, NULL);
int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
+#include <linux/loop.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "dissect-image.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "string-util.h"
#include "strv.h"
#include "tmpfile-util.h"
+#include "user-util.h"
int mount_fd(const char *source,
int target_fd,
assert(prefix);
assert(proc_self_mountinfo);
- /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already
- * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
- * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to
- * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each
- * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We
- * do not have any effect on future submounts that might get propagated, they might be writable. This includes
- * future submounts that have been triggered via autofs.
+ /* Recursively remount a directory (and all its submounts) with desired flags (MS_READONLY,
+ * MS_NOSUID, MS_NOEXEC). If the directory is already mounted, we reuse the mount and simply mark it
+ * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write operation), ditto for other flags. If it
+ * isn't we first make it one. Afterwards we apply (or remove) the flags to all submounts we can
+ * access, too. When mounts are stacked on the same mount point we only care for each individual
+ * "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We do
+ * not have any effect on future submounts that might get propagated, they might be writable
+ * etc. This includes future submounts that have been triggered via autofs.
*
* If the "deny_list" parameter is specified it may contain a list of subtrees to exclude from the
* remount operation. Note that we'll ignore the deny list for the top-level path. */
return 0;
}
-int bind_mount_in_namespace(
+static int mount_in_namespace(
pid_t target,
const char *propagate_path,
const char *incoming_path,
const char *src,
const char *dest,
bool read_only,
- bool make_file_or_directory) {
+ bool make_file_or_directory,
+ const MountOptions *options,
+ bool is_image) {
_cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
_cleanup_close_ int self_mntns_fd = -1, mntns_fd = -1, root_fd = -1, pidns_fd = -1, chased_src_fd = -1;
assert(incoming_path);
assert(src);
assert(dest);
+ assert(!options || is_image);
r = namespace_open(target, &pidns_fd, &mntns_fd, NULL, NULL, &root_fd);
if (r < 0)
/* Second, we mount the source file or directory to a directory inside of our MS_SLAVE playground. */
mount_tmp = strjoina(mount_slave, "/mount");
- r = make_mount_point_inode_from_stat(&st, mount_tmp, 0700);
+ if (is_image)
+ r = mkdir_p(mount_tmp, 0700);
+ else
+ r = make_mount_point_inode_from_stat(&st, mount_tmp, 0700);
if (r < 0) {
log_debug_errno(r, "Failed to create temporary mount point %s: %m", mount_tmp);
goto finish;
mount_tmp_created = true;
- r = mount_follow_verbose(LOG_DEBUG, chased_src, mount_tmp, NULL, MS_BIND, NULL);
+ if (is_image)
+ r = verity_dissect_and_mount(chased_src, mount_tmp, options);
+ else
+ r = mount_follow_verbose(LOG_DEBUG, chased_src, mount_tmp, NULL, MS_BIND, NULL);
if (r < 0)
goto finish;
* right-away. */
mount_outside = strjoina(propagate_path, "/XXXXXX");
- if (S_ISDIR(st.st_mode))
+ if (is_image || S_ISDIR(st.st_mode))
r = mkdtemp(mount_outside) ? 0 : -errno;
else {
r = mkostemp_safe(mount_outside);
mount_outside_mounted = true;
mount_tmp_mounted = false;
- if (S_ISDIR(st.st_mode))
+ if (is_image || S_ISDIR(st.st_mode))
(void) rmdir(mount_tmp);
else
(void) unlink(mount_tmp);
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
if (make_file_or_directory) {
- (void) mkdir_parents(dest, 0755);
- (void) make_mount_point_inode_from_stat(&st, dest, 0700);
+ if (!is_image) {
+ (void) mkdir_parents(dest, 0755);
+ (void) make_mount_point_inode_from_stat(&st, dest, 0700);
+ } else
+ (void) mkdir_p(dest, 0755);
}
/* Fifth, move the mount to the right place inside */
if (mount_outside_mounted)
(void) umount_verbose(LOG_DEBUG, mount_outside, UMOUNT_NOFOLLOW);
if (mount_outside_created) {
- if (S_ISDIR(st.st_mode))
+ if (is_image || S_ISDIR(st.st_mode))
(void) rmdir(mount_outside);
else
(void) unlink(mount_outside);
if (mount_tmp_mounted)
(void) umount_verbose(LOG_DEBUG, mount_tmp, UMOUNT_NOFOLLOW);
if (mount_tmp_created) {
- if (S_ISDIR(st.st_mode))
+ if (is_image || S_ISDIR(st.st_mode))
(void) rmdir(mount_tmp);
else
(void) unlink(mount_tmp);
return r;
}
+
+int bind_mount_in_namespace(
+ pid_t target,
+ const char *propagate_path,
+ const char *incoming_path,
+ const char *src,
+ const char *dest,
+ bool read_only,
+ bool make_file_or_directory) {
+
+ return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, NULL, false);
+}
+
+int mount_image_in_namespace(
+ pid_t target,
+ const char *propagate_path,
+ const char *incoming_path,
+ const char *src,
+ const char *dest,
+ bool read_only,
+ bool make_file_or_directory,
+ const MountOptions *options) {
+
+ return mount_in_namespace(target, propagate_path, incoming_path, src, dest, read_only, make_file_or_directory, options, true);
+}
#include <unistd.h>
#include "alloc-util.h"
+#include "dissect-image.h"
#include "errno-util.h"
#include "macro.h"
int mount_move_root(const char *path);
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, endmntent, NULL);
#define _cleanup_endmntent_ _cleanup_(endmntentp)
int mount_verbose_full(
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);
int bind_mount_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory);
+int mount_image_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory, const MountOptions *options);
NAMING_V245 = NAMING_V243 | NAMING_NSPAWN_LONG_HASH,
NAMING_V247 = NAMING_V245 | NAMING_BRIDGE_NO_SLOT,
- _NAMING_SCHEME_FLAGS_INVALID = -1,
+ _NAMING_SCHEME_FLAGS_INVALID = -EINVAL,
} NamingSchemeFlags;
typedef struct NamingScheme {
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
#include "openssl-util.h"
#include "alloc-util.h"
#if HAVE_OPENSSL
# include <openssl/pem.h>
-DEFINE_TRIVIAL_CLEANUP_FUNC(X509*, X509_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(X509_NAME*, X509_NAME_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL);
int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
+#include "discover-image.h"
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "macro.h"
-#include "machine-image.h"
#include "os-util.h"
#include "string-util.h"
#include "strv.h"
OUTPUT_CAT,
OUTPUT_WITH_UNIT,
_OUTPUT_MODE_MAX,
- _OUTPUT_MODE_INVALID = -1
+ _OUTPUT_MODE_INVALID = -EINVAL,
} OutputMode;
static inline bool OUTPUT_MODE_IS_JSON(OutputMode m) {
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "format-table.h"
+#include "parse-argument.h"
+#include "path-util.h"
+#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
+#include "string-util.h"
+
+/* All functions in this file emit warnigs. */
+
+int parse_json_argument(const char *s, JsonFormatFlags *ret) {
+ assert(s);
+ assert(ret);
+
+ if (streq(s, "pretty"))
+ *ret = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO;
+ else if (streq(s, "short"))
+ *ret = JSON_FORMAT_NEWLINE;
+ else if (streq(s, "off"))
+ *ret = JSON_FORMAT_OFF;
+ else if (streq(s, "help")) {
+ puts("pretty\n"
+ "short\n"
+ "off");
+ return 0; /* 0 means → we showed a brief help, exit now */
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json= switch: %s", s);
+
+ return 1; /* 1 means → properly parsed */
+}
+
+int parse_path_argument(const char *path, bool suppress_root, char **arg) {
+ char *p;
+ int r;
+
+ /*
+ * This function is intended to be used in command line parsers, to handle paths that are passed
+ * in. It makes the path absolute, and reduces it to NULL if omitted or root (the latter optionally).
+ *
+ * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON SUCCESS!
+ * Hence, do not pass in uninitialized pointers.
+ */
+
+ if (isempty(path)) {
+ *arg = mfree(*arg);
+ return 0;
+ }
+
+ r = path_make_absolute_cwd(path, &p);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
+
+ path_simplify(p, false);
+ if (suppress_root && empty_or_root(p))
+ p = mfree(p);
+
+ return free_and_replace(*arg, p);
+}
+
+int parse_signal_argument(const char *s, int *ret) {
+ int r;
+
+ assert(s);
+ assert(ret);
+
+ if (streq(s, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ if (streq(s, "list")) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+
+ table = table_new("signal", "name");
+ if (!table)
+ return log_oom();
+
+ for (int i = 1; i < _NSIG; i++) {
+ r = table_add_many(
+ table,
+ TABLE_INT, i,
+ TABLE_SIGNAL, i);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return table_log_print_error(r);
+
+ return 0;
+ }
+
+ r = signal_from_string(s);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse signal string \"%s\".", s);
+
+ *ret = r;
+ return 1; /* work to do */
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "json.h"
+
+int parse_json_argument(const char *s, JsonFormatFlags *ret);
+int parse_path_argument(const char *path, bool suppress_root, char **arg);
+int parse_signal_argument(const char *s, int *ret);
P11KitUri *uri_from_slot_info(const CK_SLOT_INFO *slot_info);
P11KitUri *uri_from_token_info(const CK_TOKEN_INFO *token_info);
-DEFINE_TRIVIAL_CLEANUP_FUNC(P11KitUri*, p11_kit_uri_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(CK_FUNCTION_LIST**, p11_kit_modules_finalize_and_release);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(P11KitUri*, p11_kit_uri_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CK_FUNCTION_LIST**, p11_kit_modules_finalize_and_release, NULL);
CK_RV pkcs11_get_slot_list_malloc(CK_FUNCTION_LIST *m, CK_SLOT_ID **ret_slotids, CK_ULONG *ret_n_slotids);
int dlopen_pwquality(void);
-DEFINE_TRIVIAL_CLEANUP_FUNC(pwquality_settings_t*, sym_pwquality_free_settings);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pwquality_settings_t*, sym_pwquality_free_settings, NULL);
void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq);
int pwq_allocate_context(pwquality_settings_t **ret);
RESOLVE_SUPPORT_YES,
RESOLVE_SUPPORT_RESOLVE,
_RESOLVE_SUPPORT_MAX,
- _RESOLVE_SUPPORT_INVALID = -1
+ _RESOLVE_SUPPORT_INVALID = -EINVAL,
};
enum DnssecMode {
DNSSEC_YES,
_DNSSEC_MODE_MAX,
- _DNSSEC_MODE_INVALID = -1
+ _DNSSEC_MODE_INVALID = -EINVAL,
};
enum DnsOverTlsMode {
DNS_OVER_TLS_YES,
_DNS_OVER_TLS_MODE_MAX,
- _DNS_OVER_TLS_MODE_INVALID = -1
+ _DNS_OVER_TLS_MODE_INVALID = -EINVAL,
};
CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support);
/* The new openat2() system call can't be filtered sensibly, since it moves the flags parameter into
* an indirect structure. Let's block it entirely for now. That should be a reasonably OK thing to do
* for now, since openat2() is very new and code generally needs fallback logic anyway to be
- * compatible with kernels that are not absolutely recent. */
+ * compatible with kernels that are not absolutely recent. We would normally return EPERM for a
+ * policy check, but this isn't strictly a policy check. Instead, we return ENOSYS to force programs
+ * to call open() or openat() instead. We can properly enforce policy for those functions. */
r = seccomp_rule_add_exact(
seccomp,
- SCMP_ACT_ERRNO(EPERM),
+ SCMP_ACT_ERRNO(ENOSYS),
SCMP_SYS(openat2),
0);
if (r < 0)
#define ERRNO_IS_SECCOMP_FATAL(r) \
IN_SET(abs(r), EPERM, EACCES, ENOMEM, EFAULT)
-DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(scmp_filter_ctx, seccomp_release, NULL);
int parse_syscall_archs(char **l, Set **ret_archs);
}
int deserialize_environment(const char *value, char ***list) {
- _cleanup_free_ char *unescaped = NULL;
+ char *unescaped;
int r;
assert(value);
if (r < 0)
return log_error_errno(r, "Failed to unescape: %m");
- r = strv_env_replace(list, unescaped);
+ r = strv_env_replace_consume(list, unescaped);
if (r < 0)
return log_error_errno(r, "Failed to append environment variable: %m");
-
- unescaped = NULL; /* now part of 'list' */
return 0;
}
}
if (boring < 1 || i == size)
- printf("%s: %d → %s → %d\n", name, i, val, rev);
+ printf("%s: %d → %s → %d\n", name, i, strnull(val), rev);
else if (boring == 1)
printf("%*s ...\n", (int) strlen(name), "");
- assert_se(!(i >= 0 && i < size ?
- sparse ? rev != i && rev != -1 : val == NULL || rev != i :
- val != NULL || rev != -1));
+ if (i >= 0 && i < size) {
+ if (sparse)
+ assert_se(rev == i || rev == -EINVAL);
+ else
+ assert_se(val != NULL && rev == i);
+ } else
+ assert_se(val == NULL && rev == -EINVAL);
}
}
/* we set the udev log level here explicitly, this is supposed
* to regulate the code in libudev/ and udev/. */
- r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log);
+ r = log_set_max_level_from_string(log);
if (r < 0)
log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r,
"failed to set udev log level '%s', ignoring: %m", log);
RESOLVE_NAME_LATE,
RESOLVE_NAME_EARLY,
_RESOLVE_NAME_TIMING_MAX,
- _RESOLVE_NAME_TIMING_INVALID = -1,
+ _RESOLVE_NAME_TIMING_INVALID = -EINVAL,
} ResolveNameTiming;
ResolveNameTiming resolve_name_timing_from_string(const char *s) _pure_;
p = startswith(key, "RLIMIT_");
if (!p)
- l = -1;
+ l = -SYNTHETIC_ERRNO(EINVAL);
else
l = rlimit_from_string(p);
if (l < 0)
- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Resource limit '%s' not known.", key);
+ return json_log(variant, flags, l, "Resource limit '%s' not known.", key);
if (!json_variant_is_object(value))
return json_log(value, flags, SYNTHETIC_ERRNO(EINVAL), "Resource limit '%s' has invalid value.", key);
static int json_dispatch_environment(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
_cleanup_strv_free_ char **n = NULL;
char ***l = userdata;
- size_t i;
int r;
if (json_variant_is_null(variant)) {
if (!json_variant_is_array(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name));
- for (i = 0; i < json_variant_elements(variant); i++) {
- _cleanup_free_ char *c = NULL;
+ for (size_t i = 0; i < json_variant_elements(variant); i++) {
JsonVariant *e;
const char *a;
if (!env_assignment_is_valid(a))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array of environment variables.", strna(name));
- c = strdup(a);
- if (!c)
- return json_log_oom(variant, flags);
-
- r = strv_env_replace(&n, c);
+ r = strv_env_replace_strdup(&n, a);
if (r < 0)
return json_log_oom(variant, flags);
-
- c = NULL;
}
- strv_free_and_replace(*l, n);
- return 0;
+ return strv_free_and_replace(*l, n);
}
int json_dispatch_user_disposition(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
k = user_disposition_from_string(json_variant_string(variant));
if (k < 0)
- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Disposition type '%s' not known.", json_variant_string(variant));
+ return json_log(variant, flags, k, "Disposition type '%s' not known.", json_variant_string(variant));
*disposition = k;
return 0;
k = user_storage_from_string(json_variant_string(variant));
if (k < 0)
- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Storage type '%s' not known.", json_variant_string(variant));
+ return json_log(variant, flags, k, "Storage type '%s' not known.", json_variant_string(variant));
*storage = k;
return 0;
JsonDispatchFlags json_flags = USER_RECORD_LOAD_FLAGS_TO_JSON_DISPATCH_FLAGS(load_flags);
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
JsonVariant *array[ELEMENTSOF(mask_field) * 2];
- size_t n_retain = 0, i;
+ size_t n_retain = 0;
UserRecordMask m = 0;
int r;
return json_log(v, json_flags, SYNTHETIC_ERRNO(EINVAL), "Stripping everything from record, refusing.");
/* Check if we have the special sections and if they match our flags set */
- for (i = 0; i < ELEMENTSOF(mask_field); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(mask_field); i++) {
JsonVariant *e, *k;
if (FLAGS_SET(USER_RECORD_STRIP_MASK(load_flags), mask_field[i].mask)) {
r = json_variant_new_object(&w, array, n_retain);
if (r < 0)
return json_log(v, json_flags, r, "Failed to allocate new object: %m");
- } else {
+ } else
/* And now check if there's anything else in the record */
- for (i = 0; i < json_variant_elements(v); i += 2) {
+ for (size_t i = 0; i < json_variant_elements(v); i += 2) {
const char *f;
bool special = false;
- size_t j;
assert_se(f = json_variant_string(json_variant_by_index(v, i)));
- for (j = 0; j < ELEMENTSOF(mask_field); j++)
+ for (size_t j = 0; j < ELEMENTSOF(mask_field); j++)
if (streq(f, mask_field[j].name)) { /* already covered in the loop above */
special = true;
continue;
break;
}
}
- }
if (FLAGS_SET(load_flags, USER_RECORD_REQUIRE_REGULAR) && !FLAGS_SET(m, USER_RECORD_REGULAR))
return json_log(v, json_flags, SYNTHETIC_ERRNO(EBADMSG), "Record lacks basic identity fields, which are required.");
USER_CONTAINER, /* UID ranges allocated for container uses */
USER_RESERVED, /* Range above 2^31 */
_USER_DISPOSITION_MAX,
- _USER_DISPOSITION_INVALID = -1,
+ _USER_DISPOSITION_INVALID = -EINVAL,
} UserDisposition;
typedef enum UserHomeStorage {
USER_FSCRYPT,
USER_CIFS,
_USER_STORAGE_MAX,
- _USER_STORAGE_INVALID = -1
+ _USER_STORAGE_INVALID = -EINVAL,
} UserStorage;
typedef enum UserRecordMask {
* very new and not apply to the current script being executed. */
e = getenv("RUNLEVEL");
- if (e && e[0] > 0) {
+ if (!isempty(e)) {
*runlevel = e[0];
-
- if (previous) {
- /* $PREVLEVEL seems to be an Upstart thing */
-
- e = getenv("PREVLEVEL");
- if (e && e[0] > 0)
- *previous = e[0];
- else
- *previous = 0;
- }
+ if (previous)
+ *previous = 0;
return 0;
}
VARLINK_DISCONNECTED,
_VARLINK_STATE_MAX,
- _VARLINK_STATE_INVALID = -1
+ _VARLINK_STATE_INVALID = -EINVAL,
} VarlinkState;
/* Tests whether we are not yet disconnected. Note that this is true during all states where the connection
return r;
v->fd = fd;
- v->userdata = server->userdata;
+ if (server->flags & VARLINK_SERVER_INHERIT_USERDATA)
+ v->userdata = server->userdata;
+
if (ucred_acquired) {
v->ucred = ucred;
v->ucred_acquired = true;
} VarlinkMethodFlags;
typedef enum VarlinkServerFlags {
- VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */
- VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
- VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
+ VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */
+ VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
+ VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
+ VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */
- _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1,
+ _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1,
} VarlinkServerFlags;
typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
m = volatile_mode_from_string(mode);
if (m < 0)
- return -EINVAL;
+ return m;
*ret = m;
} else
VOLATILE_STATE,
VOLATILE_OVERLAY,
_VOLATILE_MODE_MAX,
- _VOLATILE_MODE_INVALID = -1
+ _VOLATILE_MODE_INVALID = -EINVAL,
} VolatileMode;
VolatileMode volatile_mode_from_string(const char *s);
" hybrid-sleep Both hibernate and suspend the system\n"
" suspend-then-hibernate Initially suspend and then hibernate\n"
" the system after a fixed period of time\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
int r;
- log_setup_service();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
" the %3$s for time span format\n"
" -h --help Show this help\n"
" --version Show package version\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , time_link
- );
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ time_link);
return 0;
}
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
- log_setup_service();
+ log_setup();
print_mode(argc > 1 ? argv[1] : "");
" --cat-config Show configuration files\n"
" --prefix=PATH Only apply rules with the specified prefix\n"
" --no-pager Do not pipe output into a pager\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
umask(0022);
#include <unistd.h>
#include "capability-util.h"
+#include "discover-image.h"
#include "dissect-image.h"
#include "escape.h"
#include "fd-util.h"
#include "fs-util.h"
#include "hashmap.h"
#include "log.h"
-#include "machine-image.h"
#include "main-func.h"
#include "missing_magic.h"
#include "mkdir.h"
#include "mountpoint-util.h"
#include "os-util.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "stat-util.h"
#include "terminal-util.h"
#include "user-util.h"
+#include "verbs.h"
-static enum {
- ACTION_STATUS,
- ACTION_MERGE,
- ACTION_UNMERGE,
- ACTION_REFRESH,
- ACTION_LIST,
-} arg_action = ACTION_STATUS;
static char **arg_hierarchies = NULL; /* "/usr" + "/opt" by default */
static char *arg_root = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
+static bool arg_legend = true;
+static bool arg_force = false;
STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
return ret;
}
-static int status(void) {
+static int verb_unmerge(int argc, char **argv, void *userdata) {
+
+ if (!have_effective_cap(CAP_SYS_ADMIN))
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
+
+ return unmerge();
+}
+
+static int verb_status(int argc, char **argv, void *userdata) {
_cleanup_(table_unrefp) Table *t = NULL;
int r, ret = 0;
char **p;
(void) table_set_sort(t, (size_t) 0, (size_t) -1);
- if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
- (void) pager_open(arg_pager_flags);
-
- r = table_print_json(t, stdout, arg_json_format_flags);
+ r = table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
if (r < 0)
- return table_log_add_error(r);
+ return r;
return ret;
}
return 1;
}
-static int strverscmpp(char *const* a, char *const* b) {
- /* usable in qsort() for sorting a string array with strverscmp() */
- return strverscmp(*a, *b);
+static int strverscmp_improvedp(char *const* a, char *const* b) {
+ /* usable in qsort() for sorting a string array with strverscmp_improved() */
+ return strverscmp_improved(*a, *b);
+}
+
+static int validate_version(
+ const char *root,
+ const char *name,
+ const char *host_os_release_id,
+ const char *host_os_release_version_id,
+ const char *host_os_release_sysext_level) {
+
+ _cleanup_free_ char *extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
+ int r;
+
+ assert(root);
+ assert(name);
+
+ if (arg_force) {
+ log_debug("Force mode enabled, skipping version validation.");
+ return 1;
+ }
+
+ /* Insist that extension images do not overwrite the underlying OS release file (it's fine if
+ * they place one in /etc/os-release, i.e. where things don't matter, as they aren't
+ * merged.) */
+ r = chase_symlinks("/usr/lib/os-release", root, CHASE_PREFIX_ROOT, NULL, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
+
+ /* Now that we can look into the extension image, let's see if the OS version is compatible */
+ r = parse_extension_release(
+ root,
+ name,
+ "ID", &extension_release_id,
+ "VERSION_ID", &extension_release_version_id,
+ "SYSEXT_LEVEL", &extension_release_sysext_level,
+ NULL);
+ if (r == -ENOENT) {
+ log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", name);
+ return 0;
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", name);
+
+ if (!streq_ptr(host_os_release_id, extension_release_id)) {
+ log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
+ name, strna(extension_release_id), strna(host_os_release_id));
+ return 0;
+ }
+
+ /* If the extension has a sysext API level declared, then it must match the host API
+ * level. Otherwise, compare OS version as a whole */
+ if (extension_release_sysext_level) {
+ if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
+ log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
+ name, extension_release_sysext_level, strna(host_os_release_sysext_level));
+ return 0;
+ }
+ } else {
+ if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
+ log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
+ name, extension_release_version_id, strna(host_os_release_version_id));
+ return 0;
+ }
+ }
+
+ log_debug("Version info of extension '%s' matches host.", name);
+ return 1;
}
static int merge_subprocess(Hashmap *images, const char *workspace) {
/* Let's now mount all images */
HASHMAP_FOREACH(img, images) {
- _cleanup_free_ char *p = NULL,
- *extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
+ _cleanup_free_ char *p = NULL;
p = path_join(workspace, "extensions", img->name);
if (!p)
assert_not_reached("Unsupported image type");
}
- /* Insist that extension images do not overwrite the underlying OS release file (it's fine if
- * they place one in /etc/os-release, i.e. where things don't matter, as they aren't
- * merged.) */
- r = chase_symlinks("/usr/lib/os-release", p, CHASE_PREFIX_ROOT, NULL, NULL);
- if (r < 0) {
- if (r != -ENOENT)
- return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
- } else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
-
- /* Now that we can look into the extension image, let's see if the OS version is compatible */
- r = parse_extension_release(
+ r = validate_version(
p,
img->name,
- "ID", &extension_release_id,
- "VERSION_ID", &extension_release_version_id,
- "SYSEXT_LEVEL", &extension_release_sysext_level,
- NULL);
- if (r == -ENOENT) {
- log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name);
+ host_os_release_id,
+ host_os_release_version_id,
+ host_os_release_sysext_level);
+ if (r < 0)
+ return r;
+ if (r == 0) {
n_ignored++;
continue;
- } else if (r < 0)
- return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", img->name);
- else {
- if (!streq_ptr(host_os_release_id, extension_release_id)) {
- log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
- img->name, strna(extension_release_id), strna(host_os_release_id));
- n_ignored++;
- continue;
- }
-
- /* If the extension has a sysext API level declared, then it must match the host API level. Otherwise, compare OS version as a whole */
- if (extension_release_sysext_level) {
- if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
- log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
- img->name, extension_release_sysext_level, strna(host_os_release_sysext_level));
- n_ignored++;
- continue;
- }
- } else {
- if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
- log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
- img->name, extension_release_version_id, strna(host_os_release_version_id));
- n_ignored++;
- continue;
- }
- }
-
- log_debug("Version info of extension '%s' matches host.", img->name);
}
/* Noice! This one is an extension we want. */
return 0;
}
- /* Order by version sort (i.e. libc strverscmp()) */
- typesafe_qsort(extensions, n_extensions, strverscmpp);
+ /* Order by version sort with strverscmp_improved() */
+ typesafe_qsort(extensions, n_extensions, strverscmp_improvedp);
buf = strv_join(extensions, "', '");
if (!buf)
return r != 123; /* exit code 123 means: didn't do anything */
}
-static int help(void) {
+static int verb_merge(int argc, char **argv, void *userdata) {
+ _cleanup_(hashmap_freep) Hashmap *images = NULL;
+ char **p;
+ int r;
+
+ if (!have_effective_cap(CAP_SYS_ADMIN))
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
+
+ images = hashmap_new(&image_hash_ops);
+ if (!images)
+ return log_oom();
+
+ r = image_discover(IMAGE_EXTENSION, arg_root, images);
+ if (r < 0)
+ return log_error_errno(r, "Failed to discover extension images: %m");
+
+ /* In merge mode fail if things are already merged. (In --refresh mode below we'll unmerge if we find
+ * things are already merged...) */
+ STRV_FOREACH(p, arg_hierarchies) {
+ _cleanup_free_ char *resolved = NULL;
+
+ r = chase_symlinks(*p, arg_root, CHASE_PREFIX_ROOT, &resolved, NULL);
+ if (r == -ENOENT) {
+ log_debug_errno(r, "Hierarchy '%s%s' does not exist, ignoring.", strempty(arg_root), *p);
+ continue;
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to resolve path to hierarchy '%s%s': %m", strempty(arg_root), *p);
+
+ r = is_our_mount_point(resolved);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
+ "Hierarchy '%s' is already merged.", *p);
+ }
+
+ return merge(images);
+}
+
+static int verb_refresh(int argc, char **argv, void *userdata) {
+ _cleanup_(hashmap_freep) Hashmap *images = NULL;
+ int r;
+
+ if (!have_effective_cap(CAP_SYS_ADMIN))
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
+
+ images = hashmap_new(&image_hash_ops);
+ if (!images)
+ return log_oom();
+
+ r = image_discover(IMAGE_EXTENSION, arg_root, images);
+ if (r < 0)
+ return log_error_errno(r, "Failed to discover extension images: %m");
+
+ r = merge(images); /* Returns > 0 if it did something, i.e. a new overlayfs is mounted now. When it
+ * does so it implicitly unmounts any overlayfs placed there before. Returns == 0
+ * if it did nothing, i.e. no extension images found. In this case the old
+ * overlayfs remains in place if there was one. */
+ if (r < 0)
+ return r;
+ if (r == 0) /* No images found? Then unmerge. The goal of --refresh is after all that after having
+ * called there's a guarantee that the merge status matches the installed extensions. */
+ r = unmerge();
+
+ /* Net result here is that:
+ *
+ * 1. If an overlayfs was mounted before and no extensions exist anymore, we'll have unmerged things.
+ *
+ * 2. If an overlayfs was mounted before, and there are still extensions installed' we'll have
+ * unmerged and then merged things again.
+ *
+ * 3. If an overlayfs so far wasn't mounted, and there are extensions installed, we'll have it
+ * mounted now.
+ *
+ * 4. If there was no overlayfs mount so far, and no extensions installed, we implement a NOP.
+ */
+
+ return 0;
+}
+
+static int verb_list(int argc, char **argv, void *userdata) {
+ _cleanup_(hashmap_freep) Hashmap *images = NULL;
+ _cleanup_(table_unrefp) Table *t = NULL;
+ Image *img;
+ int r;
+
+ images = hashmap_new(&image_hash_ops);
+ if (!images)
+ return log_oom();
+
+ r = image_discover(IMAGE_EXTENSION, arg_root, images);
+ if (r < 0)
+ return log_error_errno(r, "Failed to discover extension images: %m");
+
+ if ((arg_json_format_flags & JSON_FORMAT_OFF) && hashmap_isempty(images)) {
+ log_info("No OS extensions found.");
+ return 0;
+ }
+
+ t = table_new("name", "type", "path", "time");
+ if (!t)
+ return log_oom();
+
+ HASHMAP_FOREACH(img, images) {
+ r = table_add_many(
+ t,
+ TABLE_STRING, img->name,
+ TABLE_STRING, image_type_to_string(img->type),
+ TABLE_PATH, img->path,
+ TABLE_TIMESTAMP, img->mtime != 0 ? img->mtime : img->crtime);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ (void) table_set_sort(t, (size_t) 0, (size_t) -1);
+
+ return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
_cleanup_free_ char *link = NULL;
int r;
printf("%1$s [OPTIONS...] [DEVICE]\n"
"\n%5$sMerge extension images into /usr/ and /opt/ hierarchies.%6$s\n"
"\n%3$sCommands:%4$s\n"
+ " status Show current merge status (default)\n"
+ " merge Merge extensions into /usr/ and /opt/\n"
+ " unmerge Unmerge extensions from /usr/ and /opt/\n"
+ " refresh Unmerge/merge extensions again\n"
+ " list List installed extensions\n"
" -h --help Show this help\n"
" --version Show package version\n"
- " -m --merge Merge extensions into /usr/ and /opt/\n"
- " -u --unmerge Unmerge extensions from /usr/ and /opt/\n"
- " -R --refresh Unmerge/merge extensions again\n"
- " -l --list List all OS images\n"
"\n%3$sOptions:%4$s\n"
" --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not show the headers and footers\n"
" --root=PATH Operate relative to root path\n"
" --json=pretty|short|off\n"
" Generate JSON output\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal()
- );
+ " --force Ignore version incompatibilities\n"
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
- ARG_MERGE,
- ARG_UNMERGE,
- ARG_REFRESH,
- ARG_LIST,
+ ARG_NO_LEGEND,
ARG_ROOT,
ARG_JSON,
+ ARG_FORCE,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "root", required_argument, NULL, ARG_ROOT },
- { "merge", no_argument, NULL, 'm' },
- { "unmerge", no_argument, NULL, 'u' },
- { "refresh", no_argument, NULL, 'R' },
- { "list", no_argument, NULL, 'l' },
- { "json", required_argument, NULL, ARG_JSON },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "json", required_argument, NULL, ARG_JSON },
+ { "force", no_argument, NULL, ARG_FORCE },
{}
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hmuRl", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
switch (c) {
case 'h':
- return help();
+ return verb_help(argc, argv, NULL);
case ARG_VERSION:
return version();
arg_pager_flags |= PAGER_DISABLE;
break;
- case 'm':
- arg_action = ACTION_MERGE;
- break;
-
- case 'u':
- arg_action = ACTION_UNMERGE;
- break;
-
- case 'R':
- arg_action = ACTION_REFRESH;
- break;
-
- case 'l':
- arg_action = ACTION_LIST;
+ case ARG_NO_LEGEND:
+ arg_legend = false;
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, false, &arg_root);
+ r = parse_path_argument(optarg, false, &arg_root);
if (r < 0)
return r;
break;
case ARG_JSON:
- r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags);
+ r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
+ case ARG_FORCE:
+ arg_force = true;
+ break;
+
case '?':
return -EINVAL;
assert_not_reached("Unhandled option");
}
- if (argc - optind > 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unexpected argument.");
-
return 1;
}
return 0;
}
+static int sysext_main(int argc, char *argv[]) {
+
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
+ { "merge", VERB_ANY, 1, 0, verb_merge },
+ { "unmerge", VERB_ANY, 1, 0, verb_unmerge },
+ { "refresh", VERB_ANY, 1, 0, verb_refresh },
+ { "list", VERB_ANY, 1, 0, verb_list },
+ { "help", VERB_ANY, 1, 0, verb_help },
+ {}
+ };
+
+ return dispatch_verb(argc, argv, verbs, NULL);
+}
+
static int run(int argc, char *argv[]) {
- _cleanup_(hashmap_freep) Hashmap *images = NULL;
int r;
- log_show_color(true);
- log_parse_environment();
- log_open();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
return log_oom();
}
- /* Given that things deep down in the child process will fail, let's catch the no-privilege issue
- * early on */
- if (!IN_SET(arg_action, ACTION_STATUS, ACTION_LIST) && !have_effective_cap(CAP_SYS_ADMIN))
- return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be privileged.");
-
- if (arg_action == ACTION_STATUS)
- return status();
-
- if (arg_action == ACTION_UNMERGE)
- return unmerge();
-
- images = hashmap_new(&image_hash_ops);
- if (!images)
- return log_oom();
-
- r = image_discover(IMAGE_EXTENSION, arg_root, images);
- if (r < 0)
- return log_error_errno(r, "Failed to discover extension images: %m");
-
- switch (arg_action) {
-
- case ACTION_LIST: {
- _cleanup_(table_unrefp) Table *t = NULL;
- Image *img;
-
- if ((arg_json_format_flags & JSON_FORMAT_OFF) && hashmap_isempty(images)) {
- log_info("No OS extensions found.");
- return 0;
- }
-
- t = table_new("name", "type", "path", "time");
- if (!t)
- return log_oom();
-
- HASHMAP_FOREACH(img, images) {
- r = table_add_many(
- t,
- TABLE_STRING, img->name,
- TABLE_STRING, image_type_to_string(img->type),
- TABLE_PATH, img->path,
- TABLE_TIMESTAMP, img->mtime != 0 ? img->mtime : img->crtime);
- if (r < 0)
- return table_log_add_error(r);
- }
-
- (void) table_set_sort(t, (size_t) 0, (size_t) -1);
-
- if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
- (void) pager_open(arg_pager_flags);
-
- r = table_print_json(t, stdout, arg_json_format_flags);
- if (r < 0)
- return table_log_print_error(r);
-
- r = 0;
- break;
- }
-
- case ACTION_MERGE: {
- char **p;
-
- /* In merge mode fail if things are already merged. (In --refresh mode below we'll unmerge if
- * we find things are already merged...) */
- STRV_FOREACH(p, arg_hierarchies) {
- _cleanup_free_ char *resolved = NULL;
-
- r = chase_symlinks(*p, arg_root, CHASE_PREFIX_ROOT, &resolved, NULL);
- if (r == -ENOENT) {
- log_debug_errno(r, "Hierarchy '%s%s' does not exist, ignoring.", strempty(arg_root), *p);
- continue;
- }
- if (r < 0)
- return log_error_errno(r, "Failed to resolve path to hierarchy '%s%s': %m", strempty(arg_root), *p);
-
- r = is_our_mount_point(resolved);
- if (r < 0)
- return r;
- if (r > 0)
- return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
- "Hierarchy '%s' is already merged.", *p);
- }
-
- r = merge(images);
- break;
- }
-
- case ACTION_REFRESH:
- r = merge(images); /* Returns > 0 if it did something, i.e. a new overlayfs is mounted
- * now. When it does so it implicitly unmounts any overlayfs placed there
- * before. Returns == 0 if it did nothing, i.e. no extension images
- * found. In this case the old overlayfs remains in place if there was
- * one. */
- if (r < 0)
- return r;
- if (r == 0) /* No images found? Then unmerge. The goal of --refresh is after all that after
- * having called there's a guarantee that the merge status matches the installed
- * extensions. */
- r = unmerge();
-
- /* Net result here is that:
- *
- * 1. If an overlayfs was mounted before and no extensions exist anymore, we'll have unmerged
- * things.
- *
- * 2. If an overlayfs was mounted before, and there are still extensions installed' we'll
- * have unmerged and then merged things again.
- *
- * 3. If an overlayfs so far wasn't mounted, and there are extensions installed, we'll have
- * it mounted now.
- *
- * 4. If there was no overlayfs mount so far, and no extensions installed, we implement a
- * NOP.
- */
- break;
-
- default:
- assert_not_reached("Uneexpected action");
- }
-
- return r;
+ return sysext_main(argc, argv);
}
DEFINE_MAIN_FUNCTION(run);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "env-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "selinux-util.h"
+#include "static-destruct.h"
+#include "stdio-util.h"
+#include "strv.h"
+#include "systemctl.h"
+#include "systemctl-util.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_strv_free_ char **argv = NULL;
+ _cleanup_close_ int orig_stdout_fd = -1;
+ int r;
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ arg_pager_flags = PAGER_DISABLE; /* We shouldn't execute the pager */
+
+ argv = strv_parse_nulstr((const char *)data, size);
+ if (!argv)
+ return log_oom();
+
+ if (!argv[0])
+ return 0; /* argv[0] should always be present, but may be zero-length. */
+
+ if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
+ orig_stdout_fd = fcntl(fileno(stdout), F_DUPFD_CLOEXEC, 3);
+ if (orig_stdout_fd < 0)
+ log_warning_errno(orig_stdout_fd, "Failed to duplicate fd 1: %m");
+ else
+ assert_se(freopen("/dev/null", "w", stdout));
+
+ opterr = 0; /* do not print errors */
+ }
+
+ optind = 0; /* this tells the getopt machinery to reinitialize */
+
+ r = systemctl_dispatch_parse_argv(strv_length(argv), argv);
+ if (r < 0)
+ log_error_errno(r, "Failed to parse args: %m");
+ else
+ log_info(r == 0 ? "Done!" : "Action!");
+
+ if (orig_stdout_fd >= 0) {
+ char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ xsprintf(path, "/proc/self/fd/%d", orig_stdout_fd);
+ assert_se(freopen(path, "w", stdout));
+ }
+
+ release_busses(); /* We open the bus for communication with logind.
+ * It needs to be closed to avoid apparent leaks. */
+
+ mac_selinux_finish();
+
+ /* Call static destructors to do global state cleanup. We do it here, and not in fuzz-main.c so that
+ * any global state is destoyed between fuzzer runs. */
+ static_destruct();
+
+ return 0;
+}
libshared_static,
libbasic_gcrypt]
endif
+
+fuzzers += [
+ [['src/systemctl/fuzz-systemctl-parse-argv.c',
+ systemctl_sources],
+ systemctl_link_with,
+ [], [], ['-DFUZZ_SYSTEMCTL_PARSE_ARGV']]]
" -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
" -d --no-wtmp Don't write wtmp record\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , arg_action == ACTION_REBOOT ? " [ARG]" : ""
- , ansi_highlight()
- , arg_action == ACTION_REBOOT ? "Reboot" :
- arg_action == ACTION_POWEROFF ? "Power off" :
- "Halt"
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ arg_action == ACTION_REBOOT ? " [ARG]" : "",
+ ansi_highlight(),
+ arg_action == ACTION_REBOOT ? "Reboot" :
+ arg_action == ACTION_POWEROFF ? "Power off" :
+ "Halt",
+ ansi_normal(),
+ link);
return 0;
}
"\n%sPrints the previous and current runlevel of the init system.%s\n"
"\nOptions:\n"
" --help Show this help\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
" -k Don't halt/power-off/reboot, just send warnings\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
" -c Cancel a pending shutdown\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
wall = argv + optind + 1;
if (wall) {
- arg_wall = strv_copy(wall);
- if (!arg_wall)
+ char **copy = strv_copy(wall);
+ if (!copy)
return log_oom();
+ strv_free_and_replace(arg_wall, copy);
}
optind = argc;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <getopt.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "pretty-print.h"
+#include "rlimit-util.h"
#include "systemctl-compat-telinit.h"
#include "systemctl-daemon-reload.h"
#include "systemctl-start-unit.h"
"\nOptions:\n"
" --help Show this help\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
return 0;
}
+
+int exec_telinit(char *argv[]) {
+ (void) rlimit_nofile_safe();
+ execv(TELINIT, argv);
+
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Couldn't find an alternative telinit implementation to spawn.");
+}
int telinit_parse_argv(int argc, char *argv[]);
int start_with_fallback(void);
int reload_with_fallback(void);
+int exec_telinit(char *argv[]);
UnitActiveState active_state;
sd_bus *bus;
char **name;
- int r, i;
+ int r;
bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
if (!arg_quiet)
puts(unit_active_state_to_string(active_state));
- for (i = 0; i < nb_states; ++i)
+ for (int i = 0; i < nb_states; ++i)
if (good_states[i] == active_state)
found = true;
}
static int show_installation_targets_client_side(const char *name) {
UnitFileChange *changes = NULL;
- size_t n_changes = 0, i;
+ size_t n_changes = 0;
UnitFileFlags flags;
char **p;
int r;
if (r < 0)
return log_error_errno(r, "Failed to get file links for %s: %m", name);
- for (i = 0; i < n_changes; i++)
+ for (size_t i = 0; i < n_changes; i++)
if (changes[i].type == UNIT_FILE_UNLINK)
printf(" %s\n", changes[i].path);
_cleanup_free_ char *n = NULL;
size_t max_len = MAX(columns(),20u);
size_t len = 0;
- int i;
if (!arg_plain) {
- for (i = level - 1; i >= 0; i--) {
+ for (int i = level - 1; i >= 0; i--) {
len += 2;
if (len > max_len - 3 && !arg_full) {
printf("%s...\n",max_len % 2 ? "" : " ");
break;
}
- printf("%s%s%s ", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), ansi_normal());
+ printf("%s%s%s ", on, special_glyph(unit_active_state_to_glyph(active_state)), ansi_normal());
}
r = list_dependencies_print(*c, level, branches, c[1] == NULL);
static int output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned n, bool skipped) {
_cleanup_(table_unrefp) Table *table = NULL;
- const struct job_info *j;
const char *on, *off;
int r;
(void) table_set_empty_string(table, "-");
- for (j = jobs; j < jobs + n; j++) {
+ for (const struct job_info *j = jobs; j < jobs + n; j++) {
if (streq(j->state, "running"))
on = ansi_highlight();
else
}
static void free_machines_list(struct machine_info *machine_infos, int n) {
- int i;
-
if (!machine_infos)
return;
- for (i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
machine_info_clear(&machine_infos[i]);
free(machine_infos);
static int output_machines_list(struct machine_info *machine_infos, unsigned n) {
_cleanup_(table_unrefp) Table *table = NULL;
- struct machine_info *m;
bool state_missing = false;
int r;
(void) table_set_empty_string(table, "-");
- for (m = machine_infos; m < machine_infos + n; m++) {
+ for (struct machine_info *m = machine_infos; m < machine_infos + n; m++) {
_cleanup_free_ char *mname = NULL;
const char *on_state = "", *on_failed = "";
bool circle = false;
int list_unit_files(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ UnitFileList *units = NULL;
- UnitFileList *unit;
size_t size = 0;
unsigned c = 0;
const char *state;
return r;
if (install_client_side())
- for (unit = units; unit < units + c; unit++)
+ for (UnitFileList *unit = units; unit < units + c; unit++)
free(unit->path);
if (c == 0)
static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
_cleanup_(table_unrefp) Table *table = NULL;
- struct socket_info *s;
const char *on, *off;
int r;
(void) table_set_empty_string(table, "-");
if (cs) {
- for (s = socket_infos; s < socket_infos + cs; s++) {
+ for (struct socket_info *s = socket_infos; s < socket_infos + cs; s++) {
_cleanup_free_ char *j = NULL;
const char *path;
_cleanup_strv_free_ char **sockets_with_suffix = NULL;
_cleanup_free_ UnitInfo *unit_infos = NULL;
_cleanup_free_ struct socket_info *socket_infos = NULL;
- const UnitInfo *u;
- struct socket_info *s;
unsigned cs = 0;
size_t size = 0;
int r, n;
if (n < 0)
return n;
- for (u = unit_infos; u < unit_infos + n; u++) {
+ for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
_cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
- int i, c;
+ int c;
if (!endswith(u->id, ".socket"))
continue;
goto cleanup;
}
- for (i = 0; i < c; i++)
+ for (int i = 0; i < c; i++)
socket_infos[cs + i] = (struct socket_info) {
.machine = u->machine,
.id = u->id,
cleanup:
assert(cs == 0 || socket_infos);
- for (s = socket_infos; s < socket_infos + cs; s++) {
+ for (struct socket_info *s = socket_infos; s < socket_infos + cs; s++) {
free(s->type);
free(s->path);
if (s->own_triggered)
static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
_cleanup_(table_unrefp) Table *table = NULL;
- struct timer_info *t;
const char *on, *off;
int r;
(void) table_set_empty_string(table, "-");
- if (n > 0) {
- for (t = timer_infos; t < timer_infos + n; t++) {
- _cleanup_free_ char *j = NULL, *activates = NULL;
- const char *unit;
-
- if (t->machine) {
- j = strjoin(t->machine, ":", t->id);
- if (!j)
- return log_oom();
- unit = j;
- } else
- unit = t->id;
+ for (struct timer_info *t = timer_infos; t < timer_infos + n; t++) {
+ _cleanup_free_ char *j = NULL, *activates = NULL;
+ const char *unit;
- activates = strv_join(t->triggered, ", ");
- if (!activates)
+ if (t->machine) {
+ j = strjoin(t->machine, ":", t->id);
+ if (!j)
return log_oom();
+ unit = j;
+ } else
+ unit = t->id;
- r = table_add_many(table,
- TABLE_TIMESTAMP, t->next_elapse,
- TABLE_TIMESTAMP_RELATIVE, t->next_elapse,
- TABLE_TIMESTAMP, t->last_trigger,
- TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
- TABLE_STRING, unit,
- TABLE_STRING, activates);
- if (r < 0)
- return table_log_add_error(r);
- }
+ activates = strv_join(t->triggered, ", ");
+ if (!activates)
+ return log_oom();
+ r = table_add_many(table,
+ TABLE_TIMESTAMP, t->next_elapse,
+ TABLE_TIMESTAMP_RELATIVE, t->next_elapse,
+ TABLE_TIMESTAMP, t->last_trigger,
+ TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
+ TABLE_STRING, unit,
+ TABLE_STRING, activates);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ if (n > 0) {
on = ansi_highlight();
off = ansi_normal();
} else {
_cleanup_strv_free_ char **timers_with_suffix = NULL;
_cleanup_free_ struct timer_info *timer_infos = NULL;
_cleanup_free_ UnitInfo *unit_infos = NULL;
- struct timer_info *t;
- const UnitInfo *u;
size_t size = 0;
int n, c = 0;
dual_timestamp nw;
dual_timestamp_get(&nw);
- for (u = unit_infos; u < unit_infos + n; u++) {
+ for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
_cleanup_strv_free_ char **triggered = NULL;
dual_timestamp next = DUAL_TIMESTAMP_NULL;
usec_t m, last = 0;
output_timers_list(timer_infos, c);
cleanup:
- for (t = timer_infos; t < timer_infos + c; t++)
+ for (struct timer_info *t = timer_infos; t < timer_infos + c; t++)
strv_free(t->triggered);
return r;
if (value) {
if (level) {
- if (log_level_from_string(value) < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "\"%s\" is not a valid log level.", value);
+ r = log_level_from_string(value);
+ if (r < 0)
+ return log_error_errno(r, "\"%s\" is not a valid log level.", value);
}
r = bus_set_property(bus, bloc,
#include "bus-error.h"
#include "bus-locator.h"
+#include "login-util.h"
#include "process-util.h"
#include "systemctl-logind.h"
#include "systemctl-start-unit.h"
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *method_with_flags;
+ uint64_t flags = 0;
sd_bus *bus;
int r;
if (arg_dry_run)
return 0;
+ SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
+
+ method_with_flags = strjoina(actions[a].method, "WithFlags");
+
+ r = bus_call_method(bus, bus_login_mgr, method_with_flags, &error, NULL, "t", flags);
+ if (r >= 0)
+ return 0;
+ if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
+ return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
+
+ /* Fallback to original methods in case there is older version of systemd-logind */
+ log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a].method);
+ sd_bus_error_free(&error);
+
r = bus_call_method(bus, bus_login_mgr, actions[a].method, &error, NULL, "b", arg_ask_password);
if (r < 0)
return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "bus-error.h"
#include "bus-locator.h"
+#include "dissect-image.h"
#include "systemctl-mount.h"
#include "systemctl-util.h"
#include "systemctl.h"
return 0;
}
+
+int mount_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *unit = argv[1], *src = argv[2], *dest = argv[3];
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_free_ char *n = NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = unit_name_mangle(unit, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ r = bus_message_new_method_call(
+ bus,
+ &m,
+ bus_systemd_mgr,
+ "MountImageUnit");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sssbb",
+ n,
+ src,
+ dest,
+ arg_read_only,
+ arg_mkdir);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'a', "(ss)");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (argc > 4) {
+ _cleanup_free_ char *partition = NULL, *mount_options = NULL;
+ const char *options = argv[4];
+
+ r = extract_many_words(&options, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
+ if (r < 0)
+ return r;
+ /* Single set of options, applying to the root partition/single filesystem */
+ if (r == 1) {
+ r = sd_bus_message_append(m, "(ss)", "root", partition);
+ if (r < 0)
+ return bus_log_create_error(r);
+ } else if (r > 1) {
+ if (partition_designator_from_string(partition) < 0)
+ return bus_log_create_error(-EINVAL);
+
+ r = sd_bus_message_append(m, "(ss)", partition, mount_options);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, -1, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mount image: %s", bus_error_message(&error, r));
+
+ return 0;
+}
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int mount_bind(int argc, char *argv[], void *userdata);
+int mount_image(int argc, char *argv[], void *userdata);
LIST_FIELDS(struct UnitCondition, conditions);
} UnitCondition;
-static void unit_condition_free(UnitCondition *c) {
+static UnitCondition* unit_condition_free(UnitCondition *c) {
if (!c)
- return;
+ return NULL;
free(c->name);
free(c->param);
- free(c);
+ return mfree(c);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
typedef struct UnitStatusInfo {
format_active_state(i->active_state, &active_on, &active_off);
- printf("%s%s%s %s", active_on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), active_off, strna(i->id));
+ const SpecialGlyph glyph = unit_active_state_to_glyph(unit_active_state_from_string(i->active_state));
+
+ printf("%s%s%s %s", active_on, special_glyph(glyph), active_off, strna(i->id));
if (i->description && !streq_ptr(i->id, i->description))
printf(" - %s", i->description);
printf("%s %s%s%s %s\n",
t == i->triggered_by ? "TriggeredBy:" : " ",
- on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
+ on, special_glyph(unit_active_state_to_glyph(state)), off,
*t);
}
} else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
const int32_t *status, *signal;
- size_t n_status, n_signal, i;
+ size_t n_status, n_signal;
r = sd_bus_message_enter_container(m, 'r', "aiai");
if (r < 0)
fputc('=', stdout);
}
- for (i = 0; i < n_status; i++) {
+ for (size_t i = 0; i < n_status; i++) {
if (first)
first = false;
else
printf("%"PRIi32, status[i]);
}
- for (i = 0; i < n_signal; i++) {
+ for (size_t i = 0; i < n_signal; i++) {
const char *str;
str = signal_to_string((int) signal[i]);
SYSTEMCTL_SHOW_STATUS,
SYSTEMCTL_SHOW_HELP,
_SYSTEMCTL_SHOW_MODE_MAX,
- _SYSTEMCTL_SHOW_MODE_INVALID = -1,
+ _SYSTEMCTL_SHOW_MODE_INVALID = -EINVAL,
} SystemctlShowMode;
static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ UnitInfo *unit_infos = NULL;
- const UnitInfo *u;
unsigned c;
int r, ret = 0;
typesafe_qsort(unit_infos, c, unit_info_compare);
- for (u = unit_infos; u < unit_infos + c; u++) {
+ for (const UnitInfo *u = unit_infos; u < unit_infos + c; u++) {
_cleanup_free_ char *p = NULL;
p = unit_dbus_path_from_name(u->id);
show_mode = systemctl_show_mode_from_string(argv[0]);
if (show_mode < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid argument.");
+ return log_error_errno(show_mode, "Invalid argument.");
if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
};
static const char *verb_to_method(const char *verb) {
- size_t i;
-
- for (i = 0; i < ELEMENTSOF(unit_actions); i++)
+ for (size_t i = 0; i < ELEMENTSOF(unit_actions); i++)
if (streq_ptr(unit_actions[i].verb, verb))
return unit_actions[i].method;
}
static const char *verb_to_job_type(const char *verb) {
- size_t i;
-
- for (i = 0; i < ELEMENTSOF(unit_actions); i++)
+ for (size_t i = 0; i < ELEMENTSOF(unit_actions); i++)
if (streq_ptr(unit_actions[i].verb, verb))
return unit_actions[i].job_type;
return r;
}
+static int enqueue_marked_jobs(
+ sd_bus *bus,
+ BusWaitForJobs *w) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ log_debug("%s dbus call org.freedesktop.systemd1.Manager EnqueueMarkedJobs()",
+ arg_dry_run ? "Would execute" : "Executing");
+
+ if (arg_dry_run)
+ return 0;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "EnqueueMarkedJobs", &error, &reply, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start jobs: %s", bus_error_message(&error, r));
+
+ _cleanup_strv_free_ char **paths = NULL;
+ r = sd_bus_message_read_strv(reply, &paths);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (w) {
+ char **path;
+
+ STRV_FOREACH(path, paths) {
+ log_debug("Adding %s to the set", *path);
+ r = bus_wait_for_jobs_add(w, *path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch job %s: %m", *path);
+ }
+ }
+
+ return 0;
+}
+
const struct action_metadata action_table[_ACTION_MAX] = {
[ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
[ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
};
enum action verb_to_action(const char *verb) {
- enum action i;
-
- for (i = 0; i < _ACTION_MAX; i++)
+ for (enum action i = 0; i < _ACTION_MAX; i++)
if (streq_ptr(action_table[i].verb, verb))
return i;
job_type = "start";
mode = "isolate";
suffix = ".target";
- } else {
+ } else if (!arg_marked) {
/* A command in style of "systemctl start <unit1> <unit2> …", "sysemctl stop <unit1> <unit2> …" and so on */
method = verb_to_method(argv[0]);
job_type = verb_to_job_type(argv[0]);
names = strv_new(one_name);
if (!names)
return log_oom();
- } else {
+ } else if (!arg_marked) {
bool expanded;
r = expand_unit_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
return log_error_errno(r, "Failed to allocate unit watch context: %m");
}
- STRV_FOREACH(name, names) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ if (arg_marked)
+ ret = enqueue_marked_jobs(bus, w);
- r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
- if (ret == EXIT_SUCCESS && r < 0)
- ret = translate_bus_error_to_exit_status(r, &error);
+ else
+ STRV_FOREACH(name, names) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- if (r >= 0 && streq(method, "StopUnit")) {
- r = strv_push(&stopped_units, *name);
- if (r < 0)
- return log_oom();
+ r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
+ if (ret == EXIT_SUCCESS && r < 0)
+ ret = translate_bus_error_to_exit_status(r, &error);
+
+ if (r >= 0 && streq(method, "StopUnit")) {
+ r = strv_push(&stopped_units, *name);
+ if (r < 0)
+ return log_oom();
+ }
}
- }
if (!arg_no_block) {
const char* extra_args[4];
}
void release_busses(void) {
- BusFocus w;
-
- for (w = 0; w < _BUS_FOCUS_MAX; w++)
+ for (BusFocus w = 0; w < _BUS_FOCUS_MAX; w++)
buses[w] = sd_bus_flush_close_unref(buses[w]);
}
state = unit_active_state_from_string(buf);
if (state < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit state '%s' for: %s", buf, unit);
+ return log_error_errno(state, "Invalid unit state '%s' for: %s", buf, unit);
*ret_active_state = state;
return 0;
int expand_unit_names(sd_bus *bus, char **names, const char* suffix, char ***ret, bool *ret_expanded) {
_cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
char **name;
- int r, i;
+ int r;
assert(bus);
assert(ret);
n = strv_length(mangled);
allocated = n + 1;
- for (i = 0; i < r; i++) {
+ for (int i = 0; i < r; i++) {
if (!GREEDY_REALLOC(mangled, allocated, n+2))
return log_oom();
#include "main-func.h"
#include "output-mode.h"
#include "pager.h"
+#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "rlimit-util.h"
TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
bool arg_read_only = false;
bool arg_mkdir = false;
+bool arg_marked = false;
STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
" set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n"
" bind UNIT PATH [PATH] Bind-mount a path from the host into a\n"
" unit's namespace\n"
+ " mount-image UNIT PATH [PATH [OPTS]] Mount an image from the host into a\n"
+ " unit's namespace\n"
" service-log-level SERVICE [LEVEL] Get/set logging threshold for service\n"
" service-log-target SERVICE [TARGET] Get/set logging target for service\n"
" reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
" 'utc': 'Day YYYY-MM-DD HH:MM:SS UTC\n"
" 'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n"
" --read-only Create read-only bind mount\n"
- " --mkdir Create directory before bind-mounting, if missing\n"
- "\nSee the %2$s for details.\n"
- , program_invocation_short_name
- , link
- , ansi_underline(), ansi_normal()
- , ansi_highlight(), ansi_normal()
- );
+ " --mkdir Create directory before mounting, if missing\n"
+ " --marked Restart/reload previously marked units\n"
+ "\nSee the %2$s for details.\n",
+ program_invocation_short_name,
+ link,
+ ansi_underline(),
+ ansi_normal(),
+ ansi_highlight(),
+ ansi_normal());
return 0;
}
ARG_TIMESTAMP_STYLE,
ARG_READ_ONLY,
ARG_MKDIR,
+ ARG_MARKED,
};
static const struct option options[] = {
{ "after", no_argument, NULL, ARG_AFTER },
{ "before", no_argument, NULL, ARG_BEFORE },
{ "show-types", no_argument, NULL, ARG_SHOW_TYPES },
- { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
+ { "failed", no_argument, NULL, ARG_FAILED },
{ "full", no_argument, NULL, 'l' },
{ "job-mode", required_argument, NULL, ARG_JOB_MODE },
{ "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP_STYLE },
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "mkdir", no_argument, NULL, ARG_MKDIR },
+ { "marked", no_argument, NULL, ARG_MARKED },
{}
};
case ARG_VERSION:
return version();
- case 't': {
- const char *p;
-
+ case 't':
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--type= requires arguments.");
- for (p = optarg;;) {
+ for (const char *p = optarg;;) {
_cleanup_free_ char *type = NULL;
r = extract_first_word(&p, &type, ",", 0);
}
break;
- }
case 'P':
arg_value = true;
arg_properties = new0(char*, 1);
if (!arg_properties)
return log_oom();
- } else {
- const char *p;
-
- for (p = optarg;;) {
+ } else
+ for (const char *p = optarg;;) {
_cleanup_free_ char *prop = NULL;
r = extract_first_word(&p, &prop, ",", 0);
if (strv_consume(&arg_properties, TAKE_PTR(prop)) < 0)
return log_oom();
}
- }
/* If the user asked for a particular property, show it, even if it is empty. */
arg_all = true;
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, false, &arg_root);
+ r = parse_path_argument(optarg, false, &arg_root);
if (r < 0)
return r;
break;
break;
case 's':
- if (streq(optarg, "help")) {
- DUMP_STRING_TABLE(signal, int, _NSIG);
- return 0;
- }
-
- arg_signal = signal_from_string(optarg);
- if (arg_signal < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse signal string %s.",
- optarg);
+ r = parse_signal_argument(optarg, &arg_signal);
+ if (r <= 0)
+ return r;
break;
case ARG_NO_ASK_PASSWORD:
arg_boot_loader_entry = empty_to_null(optarg);
break;
- case ARG_STATE: {
- const char *p;
-
+ case ARG_STATE:
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--state= requires arguments.");
- for (p = optarg;;) {
+ for (const char *p = optarg;;) {
_cleanup_free_ char *s = NULL;
r = extract_first_word(&p, &s, ",", 0);
return log_oom();
}
break;
- }
case 'r':
if (geteuid() != 0)
arg_with_dependencies = true;
break;
- case ARG_WHAT: {
- const char *p;
-
+ case ARG_WHAT:
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments.");
- for (p = optarg;;) {
+ for (const char *p = optarg;;) {
_cleanup_free_ char *k = NULL;
r = extract_first_word(&p, &k, ",", 0);
}
break;
- }
case ARG_REBOOT_ARG:
arg_reboot_argument = optarg;
arg_mkdir = true;
break;
+ case ARG_MARKED:
+ arg_marked = true;
+ break;
+
case '.':
/* Output an error mimicking getopt, and print a hint afterwards */
log_error("%s: invalid option -- '.'", program_invocation_name);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--wait may not be combined with --no-block.");
+ bool do_reload_or_restart = streq_ptr(argv[optind], "reload-or-restart");
+ if (arg_marked) {
+ if (!do_reload_or_restart)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--marked may only be used with 'reload-or-restart'.");
+ if (optind + 1 < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No additional arguments allowed with 'reload-or-restart --marked'.");
+ if (arg_wait)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--marked --wait is not supported.");
+ if (arg_show_transaction)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--marked --show-transaction is not supported.");
+
+ } else if (do_reload_or_restart) {
+ if (optind + 1 >= argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "List of units to restart/reload is required.");
+ }
+
return 1;
}
-static int parse_argv(int argc, char *argv[]) {
+int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- if (program_invocation_short_name) {
-
- if (strstr(program_invocation_short_name, "halt")) {
- arg_action = ACTION_HALT;
- return halt_parse_argv(argc, argv);
-
- } else if (strstr(program_invocation_short_name, "poweroff")) {
- arg_action = ACTION_POWEROFF;
- return halt_parse_argv(argc, argv);
-
- } else if (strstr(program_invocation_short_name, "reboot")) {
- if (kexec_loaded())
- arg_action = ACTION_KEXEC;
- else
- arg_action = ACTION_REBOOT;
- return halt_parse_argv(argc, argv);
-
- } else if (strstr(program_invocation_short_name, "shutdown")) {
- arg_action = ACTION_POWEROFF;
- return shutdown_parse_argv(argc, argv);
-
- } else if (strstr(program_invocation_short_name, "init")) {
-
- /* Matches invocations as "init" as well as "telinit", which are synonymous when run
- * as PID != 1 on SysV.
- *
- * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
- * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
- * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
- * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
- * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
- * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
- * quick way to match both.
- *
- * Also see redirect_telinit() in src/core/main.c. */
-
- if (sd_booted() > 0) {
- arg_action = _ACTION_INVALID;
- return telinit_parse_argv(argc, argv);
- } else {
- /* Hmm, so some other init system is running, we need to forward this request to
- * it. For now we simply guess that it is Upstart. */
-
- (void) rlimit_nofile_safe();
- execv(TELINIT, argv);
-
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Couldn't find an alternative telinit implementation to spawn.");
- }
-
- } else if (strstr(program_invocation_short_name, "runlevel")) {
- arg_action = ACTION_RUNLEVEL;
- return runlevel_parse_argv(argc, argv);
+ if (strstr_ptr(argv[0], "halt")) {
+ arg_action = ACTION_HALT;
+ return halt_parse_argv(argc, argv);
+
+ } else if (strstr_ptr(argv[0], "poweroff")) {
+ arg_action = ACTION_POWEROFF;
+ return halt_parse_argv(argc, argv);
+
+ } else if (strstr_ptr(argv[0], "reboot")) {
+ if (kexec_loaded())
+ arg_action = ACTION_KEXEC;
+ else
+ arg_action = ACTION_REBOOT;
+ return halt_parse_argv(argc, argv);
+
+ } else if (strstr_ptr(argv[0], "shutdown")) {
+ arg_action = ACTION_POWEROFF;
+ return shutdown_parse_argv(argc, argv);
+
+ } else if (strstr_ptr(argv[0], "init")) {
+
+ /* Matches invocations as "init" as well as "telinit", which are synonymous when run
+ * as PID != 1 on SysV.
+ *
+ * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
+ * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
+ * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
+ * for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
+ * immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
+ * get "systemctl". In both cases we shall do the same thing, which is why we do
+ * strstr_ptr(argv[0], "init") here, as a quick way to match both.
+ *
+ * Also see redirect_telinit() in src/core/main.c. */
+
+ if (sd_booted() > 0) {
+ arg_action = _ACTION_INVALID;
+ return telinit_parse_argv(argc, argv);
+ } else {
+ /* Hmm, so some other init system is running, we need to forward this request to it.
+ */
+ arg_action = ACTION_TELINIT;
+ return 1;
}
+
+ } else if (strstr_ptr(argv[0], "runlevel")) {
+ arg_action = ACTION_RUNLEVEL;
+ return runlevel_parse_argv(argc, argv);
}
arg_action = ACTION_SYSTEMCTL;
return systemctl_parse_argv(argc, argv);
}
+#ifndef FUZZ_SYSTEMCTL_PARSE_ARGV
static int systemctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units },
{ "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
- { "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
+ { "reload-or-restart", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */
{ "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit },
{ "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */
{ "add-requires", 3, VERB_ANY, 0, add_dependency },
{ "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit },
{ "bind", 3, 4, VERB_ONLINE_ONLY, mount_bind },
+ { "mount-image", 4, 5, VERB_ONLINE_ONLY, mount_image },
{}
};
int r;
setlocale(LC_ALL, "");
- log_parse_environment_cli();
+ log_parse_environment();
log_open();
/* The journal merging logic potentially needs a lot of fds. */
sigbus_install();
- r = parse_argv(argc, argv);
+ r = systemctl_dispatch_parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = runlevel_main();
break;
+ case ACTION_TELINIT:
+ r = exec_telinit(argv);
+ break;
+
case ACTION_EXIT:
case ACTION_SUSPEND:
case ACTION_HIBERNATE:
case ACTION_SUSPEND_THEN_HIBERNATE:
case ACTION_EMERGENCY:
case ACTION_DEFAULT:
- /* systemctl verbs with no equivalent in the legacy commands. These cannot appear in
- * arg_action. Fall through. */
+ /* systemctl verbs with no equivalent in the legacy commands. These cannot appear in
+ * arg_action. Fall through. */
case _ACTION_INVALID:
default:
}
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
+#endif
ACTION_RELOAD,
ACTION_REEXEC,
ACTION_RUNLEVEL,
+ ACTION_TELINIT,
ACTION_CANCEL_SHUTDOWN,
_ACTION_MAX,
- _ACTION_INVALID = -1
+ _ACTION_INVALID = -EINVAL,
};
enum dependency {
extern TimestampStyle arg_timestamp_style;
extern bool arg_read_only;
extern bool arg_mkdir;
+extern bool arg_marked;
+
+int systemctl_dispatch_parse_argv(int argc, char *argv[]);
#!/bin/sh
+# SPDX-License-Identifier: CC0-1.0
+#
# This script is called by "systemctl enable/disable" when the given unit is a
# SysV init.d script. It needs to call the distribution's mechanism for
# enabling/disabling those, such as chkconfig, update-rc.d, or similar. This
int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie);
int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply);
int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec);
+int sd_bus_reply(const sd_bus_message *call, sd_bus_message *reply);
int sd_bus_get_fd(sd_bus *bus);
int sd_bus_get_events(sd_bus *bus);
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <inttypes.h>
#include <net/ethernet.h>
#include <netinet/in.h>
SD_DHCP_LEASE_SMTP,
SD_DHCP_LEASE_LPR,
_SD_DHCP_LEASE_SERVER_TYPE_MAX,
- _SD_DHCP_LEASE_SERVER_TYPE_INVALID = -1,
+ _SD_DHCP_LEASE_SERVER_TYPE_INVALID = -EINVAL,
} sd_dhcp_lease_server_type;
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <inttypes.h>
#include <net/ethernet.h>
#include <sys/types.h>
SD_LLDP_EVENT_UPDATED,
SD_LLDP_EVENT_REFRESHED,
_SD_LLDP_EVENT_MAX,
- _SD_LLDP_EVENT_INVALID = -1,
+ _SD_LLDP_EVENT_INVALID = -EINVAL,
} sd_lldp_event;
typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
#include <inttypes.h>
#include <net/ethernet.h>
#include <netinet/in.h>
SD_NDISC_EVENT_TIMEOUT,
SD_NDISC_EVENT_ROUTER,
_SD_NDISC_EVENT_MAX,
- _SD_NDISC_EVENT_INVALID = -1,
+ _SD_NDISC_EVENT_INVALID = -EINVAL,
} sd_ndisc_event;
typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata);
int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info);
int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data);
int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data);
+int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type);
int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type);
int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type);
int sd_netlink_message_exit_container(sd_netlink_message *m);
int sd_netlink_message_is_broadcast(const sd_netlink_message *m);
/* rtnl */
-
-int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index);
-int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family);
-int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family);
-int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol);
-int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
-
int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family);
+int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family);
+int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family);
int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags);
int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags);
int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex);
+int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index);
int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change);
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_flags(const sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type);
+int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol);
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);
int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type);
int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family);
-int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family);
int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol);
int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope);
int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, unsigned char *tos);
int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type);
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol);
-
int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags);
-int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family);
int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family);
+int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family);
-int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *family);
+int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *index);
int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state);
int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags);
*/
int sd_network_link_get_required_for_online(int ifindex);
+/* Get activation policy for ifindex.
+ * Possible values are as specified for ActivationPolicy=
+ */
+int sd_network_link_get_activation_policy(int ifindex, char **policy);
+
/* Get path to .network file applied to link */
int sd_network_link_get_network_file(int ifindex, char **filename);
#include "hashmap.h"
#include "main-func.h"
#include "mount-util.h"
+#include "nscd-flush.h"
#include "pager.h"
+#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "selinux-util.h"
return r;
group_tmp = mfree(group_tmp);
+
+ if (!arg_root && !arg_image)
+ (void) nscd_flush_cache(STRV_MAKE("group"));
}
if (gshadow) {
r = rename_and_apply_smack_floor_label(gshadow_tmp, gshadow_path);
return r;
passwd_tmp = mfree(passwd_tmp);
+
+ if (!arg_root && !arg_image)
+ (void) nscd_flush_cache(STRV_MAKE("passwd"));
}
if (shadow) {
r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path);
" --replace=PATH Treat arguments as replacement for PATH\n"
" --inline Treat arguments as configuration lines\n"
" --no-pager Do not pipe output into a pager\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_root);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
if (r < 0)
return r;
break;
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"This systemd-sysusers version is compiled without support for --image=.");
#else
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
if (r < 0)
return r;
break;
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
if (arg_cat_config)
return cat_config();
bool loaded;
} SysvStub;
-static void free_sysvstub(SysvStub *s) {
+static SysvStub* free_sysvstub(SysvStub *s) {
if (!s)
- return;
+ return NULL;
free(s->name);
free(s->path);
strv_free(s->after);
strv_free(s->wants);
strv_free(s->wanted_by);
- free(s);
+ return mfree(s);
}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub);
static void free_sysvstub_hashmapp(Hashmap **h) {
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
import sys, re
print('#include <stdio.h>')
if match:
s = match.group(1)
if s == 'sd_bus_object_vtable_format':
- print(' &{},'.format(s))
+ print(f' &{s},')
else:
- print(' {},'.format(s))
+ print(f' {s},')
print('''};
int main(void) {
- unsigned i;
- for (i = 0; i < sizeof(symbols)/sizeof(void*); i++)
+ for (size_t i = 0; i < sizeof(symbols)/sizeof(void*); i++)
printf("%p\\n", symbols[i]);
return 0;
}''')
[['src/test/test-extract-word.c']],
+ [['src/test/test-parse-argument.c']],
+
[['src/test/test-parse-util.c'],
[],
[libseccomp]],
libkmod,
libacl,
libselinux],
- udev_includes, '', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'],
+ udev_includes, '', 'manual'],
[['src/test/test-udev-util.c']],
#include "rm-rf.h"
#include "service.h"
#include "tests.h"
-#include "unit.h"
+#include "unit-serialize.h"
#include "virt.h"
int main(int argc, char *argv[]) {
static int run(int argc, char **argv) {
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "parse-util.h"
+#include "process-util.h"
#include "serialize.h"
#include "string-util.h"
#include "strv.h"
+#include "tests.h"
#include "util.h"
static void test_strv_env_delete(void) {
assert_se(strv_length(l) == 2);
}
-static void test_strv_env_set(void) {
- log_info("/* %s */", __func__);
-
- _cleanup_strv_free_ char **l = NULL, **r = NULL;
-
- l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
- assert_se(l);
-
- r = strv_env_set(l, "WALDO=WALDO");
- assert_se(r);
-
- assert_se(streq(r[0], "PIEP"));
- assert_se(streq(r[1], "SCHLUMPF=SMURFF"));
- assert_se(streq(r[2], "NANANANA=YES"));
- assert_se(streq(r[3], "WALDO=WALDO"));
- assert_se(strv_length(r) == 4);
-}
-
static void test_strv_env_merge(void) {
log_info("/* %s */", __func__);
assert_se(strv_length(r) == 5);
}
+static void test_strv_env_replace_strdup(void) {
+ log_info("/* %s */", __func__);
+
+ _cleanup_strv_free_ char **a = NULL;
+
+ assert_se(strv_env_replace_strdup(&a, "a=a") == 1);
+ assert_se(strv_env_replace_strdup(&a, "b=b") == 1);
+ assert_se(strv_env_replace_strdup(&a, "a=A") == 0);
+
+ assert_se(strv_length(a) == 2);
+ strv_sort(a);
+ assert_se(streq(a[0], "a=A"));
+ assert_se(streq(a[1], "b=b"));
+}
+
+static void test_strv_env_assign(void) {
+ log_info("/* %s */", __func__);
+
+ _cleanup_strv_free_ char **a = NULL;
+
+ assert_se(strv_env_assign(&a, "a", "a") == 1);
+ assert_se(strv_env_assign(&a, "b", "b") == 1);
+ assert_se(strv_env_assign(&a, "a", "A") == 0);
+ assert_se(strv_env_assign(&a, "b", NULL) == 0);
+
+ assert_se(strv_env_assign(&a, "a=", "B") == -EINVAL);
+
+ assert_se(strv_length(a) == 1);
+ assert_se(streq(a[0], "a=A"));
+}
+
static void test_env_strv_get_n(void) {
log_info("/* %s */", __func__);
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
}
+static void test_setenv_systemd_exec_pid(void) {
+ _cleanup_free_ char *saved = NULL;
+ const char *e;
+ pid_t p;
+
+ log_info("/* %s */", __func__);
+
+ e = getenv("SYSTEMD_EXEC_PID");
+ if (e)
+ assert_se(saved = strdup(e));
+
+ assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
+ assert_se(setenv_systemd_exec_pid(true) == 0);
+ assert_se(!getenv("SYSTEMD_EXEC_PID"));
+
+ assert_se(setenv("SYSTEMD_EXEC_PID", "*", 1) >= 0);
+ assert_se(setenv_systemd_exec_pid(true) == 0);
+ assert_se(e = getenv("SYSTEMD_EXEC_PID"));
+ assert_se(streq(e, "*"));
+
+ assert_se(setenv("SYSTEMD_EXEC_PID", "123abc", 1) >= 0);
+ assert_se(setenv_systemd_exec_pid(true) == 1);
+ assert_se(e = getenv("SYSTEMD_EXEC_PID"));
+ assert_se(parse_pid(e, &p) >= 0);
+ assert_se(p == getpid_cached());
+
+ assert_se(unsetenv("SYSTEMD_EXEC_PID") >= 0);
+ assert_se(setenv_systemd_exec_pid(false) == 1);
+ assert_se(e = getenv("SYSTEMD_EXEC_PID"));
+ assert_se(parse_pid(e, &p) >= 0);
+ assert_se(p == getpid_cached());
+
+ assert_se(set_unset_env("SYSTEMD_EXEC_PID", saved, 1) >= 0);
+}
+
int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
test_strv_env_delete();
test_strv_env_get();
test_strv_env_unset();
- test_strv_env_set();
test_strv_env_merge();
+ test_strv_env_replace_strdup();
+ test_strv_env_assign();
test_env_strv_get_n();
test_replace_env(false);
test_replace_env(true);
test_env_name_is_valid();
test_env_value_is_valid();
test_env_assignment_is_valid();
+ test_setenv_systemd_exec_pid();
return 0;
}
test(m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
+static void test_exec_noexecpaths(Manager *m) {
+
+ test(m, "exec-noexecpaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
+}
+
static void test_exec_temporaryfilesystem(Manager *m) {
test(m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
entry(test_exec_ignoresigpipe),
entry(test_exec_inaccessiblepaths),
entry(test_exec_ioschedulingclass),
+ entry(test_exec_noexecpaths),
entry(test_exec_oomscoreadjust),
entry(test_exec_passenvironment),
entry(test_exec_personality),
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
+#include "random-util.h"
#include "rm-rf.h"
#include "stdio-util.h"
#include "string-util.h"
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
}
+static void create_binary_file(const char *p, const void *data, size_t l) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open(p, O_CREAT|O_WRONLY|O_EXCL|O_CLOEXEC, 0600);
+ assert_se(fd >= 0);
+ assert_se(write(fd, data, l) == (ssize_t) l);
+}
+
static void test_conservative_rename(void) {
_cleanup_(unlink_and_freep) char *p = NULL;
_cleanup_free_ char *q = NULL;
+ size_t l = 16*1024 + random_u64() % (32 * 1024); /* some randomly sized buffer 16k…48k */
+ uint8_t buffer[l+1];
+
+ random_bytes(buffer, l);
assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
- assert_se(write_string_file(p, "this is a test", WRITE_STRING_FILE_CREATE) >= 0);
+ create_binary_file(p, buffer, l);
assert_se(tempfn_random_child(NULL, NULL, &q) >= 0);
/* Check that the hardlinked "copy" is detected */
assert_se(link(p, q) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Check that a manual copy is detected */
assert_se(copy_file(p, q, 0, (mode_t) -1, 0, 0, COPY_REFLINK) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Check that a manual new writeout is also detected */
- assert_se(write_string_file(q, "this is a test", WRITE_STRING_FILE_CREATE) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
+ create_binary_file(q, buffer, l);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Check that a minimally changed version is detected */
- assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
+ buffer[47] = ~buffer[47];
+ create_binary_file(q, buffer, l);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Check that this really is new updated version */
- assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0);
+ create_binary_file(q, buffer, l);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Make sure we detect extended files */
- assert_se(write_string_file(q, "this is a_testx", WRITE_STRING_FILE_CREATE) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
+ buffer[l++] = 47;
+ create_binary_file(q, buffer, l);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
/* Make sure we detect truncated files */
- assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0);
- assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0);
+ l--;
+ create_binary_file(q, buffer, l);
+ assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0);
assert_se(access(q, F_OK) < 0 && errno == ENOENT);
}
+# SPDX-License-Identifier: LGPL-2.1-or-later
BEGIN {
print "/* GENERATED FILE */";
print "#define ORDERED"
dump_glyph(SPECIAL_GLYPH_TREE_SPACE);
dump_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET);
dump_glyph(SPECIAL_GLYPH_BLACK_CIRCLE);
+ dump_glyph(SPECIAL_GLYPH_WHITE_CIRCLE);
+ dump_glyph(SPECIAL_GLYPH_MULTIPLICATION_SIGN);
+ dump_glyph(SPECIAL_GLYPH_CIRCLE_ARROW);
dump_glyph(SPECIAL_GLYPH_BULLET);
dump_glyph(SPECIAL_GLYPH_ARROW);
dump_glyph(SPECIAL_GLYPH_ELLIPSIS);
#include "string-util.h"
#include "util.h"
-assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
- == LOG_REALM_SYSTEMD);
-assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_LOCAL7 | LOG_DEBUG))
- == LOG_REALM_UDEV);
-assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG_FACMASK)
- == LOG_LOCAL3);
-assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK)
- == LOG_INFO);
-
assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(EINVAL)));
assert_cc(!IS_SYNTHETIC_ERRNO(EINVAL));
assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(0)));
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL, 0,
NULL, 0,
NULL, 0,
NULL,
NULL,
NULL,
+ NULL,
0,
NULL);
assert_se(r == 0);
NULL
};
+ const char * const exec[] = {
+ "/lib",
+ "/usr",
+ "-/lib64",
+ "-/usr/lib64",
+ NULL
+ };
+
+ const char * const no_exec[] = {
+ "/var",
+ NULL
+ };
+
const char *inaccessible[] = {
"/home/lennart/projects",
NULL
(char **) writable,
(char **) readonly,
(char **) inaccessible,
+ (char **) exec,
+ (char **) no_exec,
NULL,
&(BindMount) { .source = (char*) "/usr/bin", .destination = (char*) "/etc/systemd", .read_only = true }, 1,
&(TemporaryFileSystem) { .path = (char*) "/var", .options = (char*) "ro" }, 1,
NULL,
NULL,
NULL,
+ NULL,
0,
NULL);
if (r < 0) {
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "parse-argument.h"
+#include "stdio-util.h"
+#include "tests.h"
+
+static void test_parse_json_argument(void) {
+ log_info("/* %s */", __func__);
+
+ JsonFormatFlags flags = JSON_FORMAT_PRETTY;
+
+ assert_se(parse_json_argument("help", &flags) == 0);
+ assert_se(flags == JSON_FORMAT_PRETTY);
+
+ assert_se(parse_json_argument("off", &flags) == 1);
+ assert_se(flags == JSON_FORMAT_OFF);
+}
+
+static void test_parse_path_argument(void) {
+ log_info("/* %s */", __func__);
+
+ _cleanup_free_ char *path = NULL;
+
+ assert_se(parse_path_argument("help", false, &path) == 0);
+ assert_se(streq(basename(path), "help"));
+
+ assert_se(parse_path_argument("/", false, &path) == 0);
+ assert_se(streq(path, "/"));
+
+ assert_se(parse_path_argument("/", true, &path) == 0);
+ assert_se(path == NULL);
+}
+
+static void test_parse_signal_argument(void) {
+ log_info("/* %s */", __func__);
+
+ int signal = -1;
+
+ assert_se(parse_signal_argument("help", &signal) == 0);
+ assert_se(signal == -1);
+
+ assert_se(parse_signal_argument("list", &signal) == 0);
+ assert_se(signal == -1);
+
+ assert_se(parse_signal_argument("SIGABRT", &signal) == 1);
+ assert_se(signal == SIGABRT);
+
+ assert_se(parse_signal_argument("ABRT", &signal) == 1);
+ assert_se(signal == SIGABRT);
+
+ char buf[DECIMAL_STR_MAX(int)];
+ xsprintf(buf, "%d", SIGABRT);
+ assert_se(parse_signal_argument(buf, &signal) == 1);
+ assert_se(signal == SIGABRT);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ test_parse_json_argument();
+ test_parse_path_argument();
+ test_parse_signal_argument();
+}
assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
}
+static void test_parse_permyriad(void) {
+ assert_se(parse_permyriad("") == -EINVAL);
+ assert_se(parse_permyriad("foo") == -EINVAL);
+ assert_se(parse_permyriad("0") == -EINVAL);
+ assert_se(parse_permyriad("50") == -EINVAL);
+ assert_se(parse_permyriad("100") == -EINVAL);
+ assert_se(parse_permyriad("-1") == -EINVAL);
+
+ assert_se(parse_permyriad("0‱") == 0);
+ assert_se(parse_permyriad("555‱") == 555);
+ assert_se(parse_permyriad("1000‱") == 1000);
+ assert_se(parse_permyriad("-7‱") == -ERANGE);
+ assert_se(parse_permyriad("10007‱") == -ERANGE);
+ assert_se(parse_permyriad("‱") == -EINVAL);
+ assert_se(parse_permyriad("‱‱") == -EINVAL);
+ assert_se(parse_permyriad("‱1") == -EINVAL);
+ assert_se(parse_permyriad("1‱‱") == -EINVAL);
+ assert_se(parse_permyriad("3.2‱") == -EINVAL);
+
+ assert_se(parse_permyriad("0‰") == 0);
+ assert_se(parse_permyriad("555.5‰") == 5555);
+ assert_se(parse_permyriad("1000.0‰") == 10000);
+ assert_se(parse_permyriad("-7‰") == -ERANGE);
+ assert_se(parse_permyriad("1007‰") == -ERANGE);
+ assert_se(parse_permyriad("‰") == -EINVAL);
+ assert_se(parse_permyriad("‰‰") == -EINVAL);
+ assert_se(parse_permyriad("‰1") == -EINVAL);
+ assert_se(parse_permyriad("1‰‰") == -EINVAL);
+ assert_se(parse_permyriad("3.22‰") == -EINVAL);
+
+ assert_se(parse_permyriad("0%") == 0);
+ assert_se(parse_permyriad("55%") == 5500);
+ assert_se(parse_permyriad("55.53%") == 5553);
+ assert_se(parse_permyriad("100%") == 10000);
+ assert_se(parse_permyriad("-7%") == -ERANGE);
+ assert_se(parse_permyriad("107%") == -ERANGE);
+ assert_se(parse_permyriad("%") == -EINVAL);
+ assert_se(parse_permyriad("%%") == -EINVAL);
+ assert_se(parse_permyriad("%1") == -EINVAL);
+ assert_se(parse_permyriad("1%%") == -EINVAL);
+ assert_se(parse_permyriad("3.212%") == -EINVAL);
+}
+
+static void test_parse_permyriad_unbounded(void) {
+ assert_se(parse_permyriad_unbounded("1001‱") == 1001);
+ assert_se(parse_permyriad_unbounded("4000‱") == 4000);
+ assert_se(parse_permyriad_unbounded("2147483647‱") == 2147483647);
+ assert_se(parse_permyriad_unbounded("2147483648‱") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("4294967295‱") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("4294967296‱") == -ERANGE);
+
+ assert_se(parse_permyriad_unbounded("101‰") == 1010);
+ assert_se(parse_permyriad_unbounded("400‰") == 4000);
+ assert_se(parse_permyriad_unbounded("214748364.7‰") == 2147483647);
+ assert_se(parse_permyriad_unbounded("214748364.8‰") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("429496729.5‰") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("429496729.6‰") == -ERANGE);
+
+ assert_se(parse_permyriad_unbounded("99%") == 9900);
+ assert_se(parse_permyriad_unbounded("40%") == 4000);
+ assert_se(parse_permyriad_unbounded("21474836.47%") == 2147483647);
+ assert_se(parse_permyriad_unbounded("21474836.48%") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("42949672.95%") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("42949672.96%") == -ERANGE);
+}
+
static void test_parse_nice(void) {
int n;
test_parse_percent_unbounded();
test_parse_permille();
test_parse_permille_unbounded();
+ test_parse_permyriad();
+ test_parse_permyriad_unbounded();
test_parse_nice();
test_parse_dev();
test_parse_errno();
test_path_extract_filename_one(NULL, NULL, -EINVAL);
test_path_extract_filename_one("a/b/c", "c", 0);
test_path_extract_filename_one("a/b/c/", "c", 0);
- test_path_extract_filename_one("/", NULL, -EINVAL);
- test_path_extract_filename_one("//", NULL, -EINVAL);
- test_path_extract_filename_one("///", NULL, -EINVAL);
+ test_path_extract_filename_one("/", NULL, -EADDRNOTAVAIL);
+ test_path_extract_filename_one("//", NULL, -EADDRNOTAVAIL);
+ test_path_extract_filename_one("///", NULL, -EADDRNOTAVAIL);
test_path_extract_filename_one(".", NULL, -EINVAL);
test_path_extract_filename_one("./.", NULL, -EINVAL);
test_path_extract_filename_one("././", NULL, -EINVAL);
}
static void test_filename_is_valid(void) {
- char foo[FILENAME_MAX+2];
- int i;
+ char foo[NAME_MAX+2];
log_info("/* %s */", __func__);
assert_se(!filename_is_valid("bar/foo/"));
assert_se(!filename_is_valid("bar//"));
- for (i=0; i<FILENAME_MAX+1; i++)
- foo[i] = 'a';
- foo[FILENAME_MAX+1] = '\0';
+ memset(foo, 'a', sizeof(foo) - 1);
+ char_array_0(foo);
assert_se(!filename_is_valid(foo));
assert_se(filename_is_valid("o.o"));
}
+static void test_path_is_valid(void) {
+ char foo[PATH_MAX+2];
+ const char *c;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(!path_is_valid(""));
+ assert_se(path_is_valid("/bar/foo"));
+ assert_se(path_is_valid("/bar/foo/"));
+ assert_se(path_is_valid("/bar/foo/"));
+ assert_se(path_is_valid("//bar//foo//"));
+ assert_se(path_is_valid("/"));
+ assert_se(path_is_valid("/////"));
+ assert_se(path_is_valid("/////.///.////...///..//."));
+ assert_se(path_is_valid("."));
+ assert_se(path_is_valid(".."));
+ assert_se(path_is_valid("bar/foo"));
+ assert_se(path_is_valid("bar/foo/"));
+ assert_se(path_is_valid("bar//"));
+
+ memset(foo, 'a', sizeof(foo) -1);
+ char_array_0(foo);
+
+ assert_se(!path_is_valid(foo));
+
+ c = strjoina("/xxx/", foo, "/yyy");
+ assert_se(!path_is_valid(c));
+
+ assert_se(path_is_valid("foo_bar-333"));
+ assert_se(path_is_valid("o.o"));
+}
+
static void test_hidden_or_backup_file(void) {
log_info("/* %s */", __func__);
test_last_path_component();
test_path_extract_filename();
test_filename_is_valid();
+ test_path_is_valid();
test_hidden_or_backup_file();
test_skip_dev_prefix();
test_empty_or_root();
test_ioprio_class_from_to_string_one("1", 1);
test_ioprio_class_from_to_string_one("7", 7);
test_ioprio_class_from_to_string_one("8", 8);
- test_ioprio_class_from_to_string_one("9", -1);
- test_ioprio_class_from_to_string_one("-1", -1);
+ test_ioprio_class_from_to_string_one("9", -EINVAL);
+ test_ioprio_class_from_to_string_one("-1", -EINVAL);
}
static void test_setpriority_closest(void) {
assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0);
assert_se(rlimit_from_string("NOFILE") == RLIMIT_NOFILE);
- assert_se(rlimit_from_string("LimitNOFILE") == -1);
- assert_se(rlimit_from_string("RLIMIT_NOFILE") == -1);
- assert_se(rlimit_from_string("xxxNOFILE") == -1);
- assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1);
+ assert_se(rlimit_from_string("LimitNOFILE") == -EINVAL);
+ assert_se(rlimit_from_string("RLIMIT_NOFILE") == -EINVAL);
+ assert_se(rlimit_from_string("xxxNOFILE") == -EINVAL);
+ assert_se(rlimit_from_string("DefaultLimitNOFILE") == -EINVAL);
assert_se(rlimit_from_string_harder("NOFILE") == RLIMIT_NOFILE);
assert_se(rlimit_from_string_harder("LimitNOFILE") == RLIMIT_NOFILE);
assert_se(rlimit_from_string_harder("RLIMIT_NOFILE") == RLIMIT_NOFILE);
- assert_se(rlimit_from_string_harder("xxxNOFILE") == -1);
- assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -1);
+ assert_se(rlimit_from_string_harder("xxxNOFILE") == -EINVAL);
+ assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -EINVAL);
for (i = 0; i < _RLIMIT_MAX; i++) {
_cleanup_free_ char *prefixed = NULL;
}
static void test_strbuf(void) {
- _cleanup_(strbuf_cleanupp) struct strbuf *sb;
+ _cleanup_(strbuf_freep) struct strbuf *sb;
_cleanup_strv_free_ char **l;
ssize_t a, b, c, d, e, f, g, h;
assert_se(!string_contains_word("a:b:cc", ":#", ":cc"));
}
+static void test_strverscmp_improved_one(const char *newer, const char *older) {
+ log_info("/* %s(%s, %s) */", __func__, strnull(newer), strnull(older));
+
+ assert_se(strverscmp_improved(newer, newer) == 0);
+ assert_se(strverscmp_improved(newer, older) > 0);
+ assert_se(strverscmp_improved(older, newer) < 0);
+ assert_se(strverscmp_improved(older, older) == 0);
+}
+
+static void test_strverscmp_improved(void) {
+ static const char * const versions[] = {
+ "",
+ "~1",
+ "ab",
+ "abb",
+ "abc",
+ "0001",
+ "002",
+ "12",
+ "122",
+ "122.9",
+ "123~rc1",
+ "123",
+ "123-a",
+ "123-a.1",
+ "123-a1",
+ "123-a1.1",
+ "123-3",
+ "123-3.1",
+ "123^patch1",
+ "123^1",
+ "123.a-1",
+ "123.1-1",
+ "123a-1",
+ "124",
+ NULL,
+ };
+ const char * const *p, * const *q;
+
+ STRV_FOREACH(p, versions)
+ STRV_FOREACH(q, p + 1)
+ test_strverscmp_improved_one(*q, *p);
+
+ test_strverscmp_improved_one("123.45-67.89", "123.45-67.88");
+ test_strverscmp_improved_one("123.45-67.89a", "123.45-67.89");
+ test_strverscmp_improved_one("123.45-67.89", "123.45-67.ab");
+ test_strverscmp_improved_one("123.45-67.89", "123.45-67.9");
+ test_strverscmp_improved_one("123.45-67.89", "123.45-67");
+ test_strverscmp_improved_one("123.45-67.89", "123.45-66.89");
+ test_strverscmp_improved_one("123.45-67.89", "123.45-9.99");
+ test_strverscmp_improved_one("123.45-67.89", "123.42-99.99");
+ test_strverscmp_improved_one("123.45-67.89", "123-99.99");
+
+ /* '~' : pre-releases */
+ test_strverscmp_improved_one("123.45-67.89", "123~rc1-99.99");
+ test_strverscmp_improved_one("123-45.67.89", "123~rc1-99.99");
+ test_strverscmp_improved_one("123~rc2-67.89", "123~rc1-99.99");
+ test_strverscmp_improved_one("123^aa2-67.89", "123~rc1-99.99");
+ test_strverscmp_improved_one("123aa2-67.89", "123~rc1-99.99");
+
+ /* '-' : separator between version and release. */
+ test_strverscmp_improved_one("123.45-67.89", "123-99.99");
+ test_strverscmp_improved_one("123^aa2-67.89", "123-99.99");
+ test_strverscmp_improved_one("123aa2-67.89", "123-99.99");
+
+ /* '^' : patch releases */
+ test_strverscmp_improved_one("123.45-67.89", "123^45-67.89");
+ test_strverscmp_improved_one("123^aa2-67.89", "123^aa1-99.99");
+ test_strverscmp_improved_one("123aa2-67.89", "123^aa2-67.89");
+
+ /* '.' : point release */
+ test_strverscmp_improved_one("123aa2-67.89", "123.aa2-67.89");
+ test_strverscmp_improved_one("123.ab2-67.89", "123.aa2-67.89");
+
+ /* invalid characters */
+ assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_string_extract_line();
test_string_contains_word_strv();
test_string_contains_word();
+ test_strverscmp_improved();
return 0;
}
#include "condition.h"
#include "device-private.h"
#include "device.h"
+#include "discover-image.h"
#include "execute.h"
#include "import-util.h"
#include "install.h"
#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
-#include "machine-image.h"
#include "mount.h"
#include "path.h"
#include "process-util.h"
test_table(log_target, LOG_TARGET);
test_table(mac_address_policy, MAC_ADDRESS_POLICY);
test_table(managed_oom_mode, MANAGED_OOM_MODE);
+ test_table(managed_oom_preference, MANAGED_OOM_PREFERENCE);
test_table(manager_state, MANAGER_STATE);
test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
" -p --property=NAME Show only properties by this name\n"
" -a --all Show all properties, including empty ones\n"
" --value When showing properties, only print the value\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
int r;
setlocale(LC_ALL, "");
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
- log_setup_service();
+ log_setup();
r = service_parse_argv("systemd-timedated.service",
"Manage the system clock and timezone and NTP enablement.",
+# This file is part of systemd.
+# See systemd-timedated.service(8) for more information.
+
systemd-timesyncd.service
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
server_name_free(m->fallback_servers);
}
-void manager_free(Manager *m) {
+Manager* manager_free(Manager *m) {
if (!m)
- return;
+ return NULL;
manager_disconnect(m);
manager_flush_server_names(m, SERVER_SYSTEM);
sd_bus_flush_close_unref(m->bus);
- free(m);
+ return mfree(m);
}
static int manager_network_read_link_servers(Manager *m) {
};
int manager_new(Manager **ret);
-void manager_free(Manager *m);
+Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int r;
log_set_facility(LOG_CRON);
- log_setup_service();
+ log_setup();
umask(0022);
#include "def.h"
#include "dirent-util.h"
#include "dissect-image.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "mountpoint-util.h"
#include "offline-passwd.h"
#include "pager.h"
+#include "parse-argument.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
CREATION_EXISTING,
CREATION_FORCE,
_CREATION_MODE_MAX,
- _CREATION_MODE_INVALID = -1
+ _CREATION_MODE_INVALID = -EINVAL,
} CreationMode;
static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = {
return pfd;
if (subvol) {
- if (btrfs_is_subvol(empty_to_root(arg_root)) <= 0)
-
+ r = getenv_bool("SYSTEMD_TMPFILES_FORCE_SUBVOL");
+ if (r < 0) {
+ if (r != -ENXIO) /* env var is unset */
+ log_warning_errno(r, "Cannot parse value of $SYSTEMD_TMPFILES_FORCE_SUBVOL, ignoring.");
+ r = btrfs_is_subvol(empty_to_root(arg_root)) > 0;
+ }
+ if (!r)
/* Don't create a subvolume unless the root directory is
* one, too. We do this under the assumption that if the
* root directory is just a plain directory (i.e. very
" --image=PATH Operate on disk image as filesystem root\n"
" --replace=PATH Treat arguments as replacement for PATH\n"
" --no-pager Do not pipe output into a pager\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
break;
case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_root);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
if (r < 0)
return r;
break;
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"This systemd-tmpfiles version is compiled without support for --image=.");
#else
- r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image);
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
if (r < 0)
return r;
#endif
if (r <= 0)
return r;
- log_setup_service();
+ log_setup();
+
+ /* We require /proc/ for a lot of our operations, i.e. for adjusting access modes, for anything
+ * SELinux related, for recursive operation, for xattr, acl and chattr handling, for btrfs stuff and
+ * a lot more. It's probably the majority of invocations where /proc/ is required. Since people
+ * apparently invoke it without anyway and are surprised about the failures, let's catch this early
+ * and output a nice and friendly warning. */
+ if (proc_mounted() == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "/proc/ is not mounted, but required for successful operation of systemd-tmpfiles. "
+ "Please mount /proc/. Alternatively, consider using the --root= or --image= switches.");
/* Descending down file system trees might take a lot of fds */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
" --wall Continuously forward password requests to wall\n"
" --plymouth Ask question with Plymouth instead of on TTY\n"
" --console Ask question on /dev/console instead of current TTY\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
static int run(int argc, char *argv[]) {
int r;
- log_setup_service();
+ log_setup();
umask(0022);
+++ /dev/null
-" 'set exrc' in ~/.vimrc will read .vimrc from the current directory
-set tabstop=8
-set shiftwidth=8
-set expandtab
#include <unistd.h>
#include "fd-util.h"
+#include "main-func.h"
#include "memory-util.h"
#include "random-util.h"
#include "sort-util.h"
FEATURE_MRW_W,
_FEATURE_MAX,
- _FEATURE_INVALID = -1,
+ _FEATURE_INVALID = -EINVAL,
} Feature;
typedef enum MediaState {
MEDIA_STATE_COMPLETE = 2,
MEDIA_STATE_OTHER = 3,
_MEDIA_STATE_MAX,
- _MEDIA_STATE_INVALID = -1,
+ _MEDIA_STATE_INVALID = -EINVAL,
} MediaState;
typedef struct Context {
_cleanup_(context_clear) Context c;
int r;
+ log_set_target(LOG_TARGET_AUTO);
+ udev_parse_config();
+ log_parse_environment();
+ log_open();
+
context_init(&c);
r = parse_argv(argc, argv);
return 0;
}
-int main(int argc, char *argv[]) {
- int r;
-
- log_set_target(LOG_TARGET_AUTO);
- udev_parse_config();
- log_parse_environment();
- log_open();
-
- r = run(argc, argv);
-
- log_close();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
+DEFINE_MAIN_FUNCTION(run);
_cleanup_(unlink_tempfilep) char filename[] = "/tmp/fuzz-udev-rules.XXXXXX";
int r;
- if (!getenv("SYSTEMD_LOG_LEVEL")) {
- log_set_max_level_realm(LOG_REALM_UDEV, LOG_CRIT);
- log_set_max_level_realm(LOG_REALM_SYSTEMD, LOG_CRIT);
- }
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
assert_se(fmkostemp_safe(filename, "r+", &f) == 0);
if (size != 0)
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
awk '
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
$1 -dM -include linux/input.h - </dev/null | awk '
link_config_gperf_c,
keyboard_keys_from_name_h,
include_directories : udev_includes,
- c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
link_with : udev_link_with,
dependencies : [libblkid, libkmod])
udev_id_progs = [['ata_id/ata_id.c'],
- ['cdrom_id/cdrom_id.c'],
- ['fido_id/fido_id.c',
- 'fido_id/fido_id_desc.c',
- 'fido_id/fido_id_desc.h'],
- ['scsi_id/scsi_id.c',
- 'scsi_id/scsi_id.h',
- 'scsi_id/scsi_serial.c',
- 'scsi_id/scsi.h'],
- ['v4l_id/v4l_id.c'],
- ['mtd_probe/mtd_probe.c',
- 'mtd_probe/mtd_probe.h',
- 'mtd_probe/probe_smartmedia.c']]
+ ['cdrom_id/cdrom_id.c'],
+ ['fido_id/fido_id.c',
+ 'fido_id/fido_id_desc.c',
+ 'fido_id/fido_id_desc.h'],
+ ['scsi_id/scsi_id.c',
+ 'scsi_id/scsi_id.h',
+ 'scsi_id/scsi_serial.c',
+ 'scsi_id/scsi.h'],
+ ['v4l_id/v4l_id.c'],
+ ['mtd_probe/mtd_probe.c',
+ 'mtd_probe/mtd_probe.h',
+ 'mtd_probe/probe_smartmedia.c']]
dmi_arches = ['x86', 'x86_64', 'aarch64', 'arm', 'ia64', 'mips']
if dmi_arches.contains(host_machine.cpu_family())
name,
prog,
include_directories : includes,
- c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
dependencies : [versiondep],
link_with : udev_link_with,
install_rpath : udev_rpath,
]
tests += [
+ [['src/udev/test-udev-event.c'],
+ [libudevd_core,
+ libshared],
+ [threads,
+ libacl]],
+
+ [['src/udev/test-udev-builtin.c'],
+ [libudevd_core,
+ libshared],
+ [threads,
+ libacl]],
+
[['src/udev/fido_id/test-fido-id-desc.c',
'src/udev/fido_id/fido_id_desc.c']],
]
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
%{
#if __GNUC__ >= 7
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names)
Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
-Link.TxQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
+Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(link_config, txqueues)
+Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(link_config, rxqueues)
+Link.TransmitQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
usec_t network_dirs_ts_usec;
};
-static void link_config_free(link_config *link) {
+static link_config* link_config_free(link_config *link) {
if (!link)
- return;
+ return NULL;
free(link->filename);
free(link->alternative_names_policy);
free(link->alias);
- free(link);
+ return mfree(link);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
link_config_free(link);
}
-void link_config_ctx_free(link_config_ctx *ctx) {
+link_config_ctx* link_config_ctx_free(link_config_ctx *ctx) {
if (!ctx)
- return;
+ return NULL;
safe_close(ctx->ethtool_fd);
-
sd_netlink_unref(ctx->rtnl);
-
link_configs_free(ctx);
-
- free(ctx);
-
- return;
+ return mfree(ctx);
}
int link_config_ctx_new(link_config_ctx **ret) {
} else
mac = config->mac;
- r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->txqueuelen, config->mtu,
- config->gso_max_size, config->gso_max_segments);
+ r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac,
+ config->txqueues, config->rxqueues, config->txqueuelen,
+ config->mtu, config->gso_max_size, config->gso_max_segments);
if (r < 0)
- log_device_warning_errno(device, r, "Could not set Alias=, MACAddress=, TxQueueLength=, MTU=, "
- "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, ignoring: %m");
+ log_device_warning_errno(device, r,
+ "Could not set Alias=, MACAddress=, "
+ "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTU=, "
+ "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
+ "ignoring: %m");
return 0;
}
return 0;
}
- if (free_and_strdup(s, rvalue) < 0)
- return log_oom();
+ return free_and_strdup_warn(s, rvalue);
+}
+
+int config_parse_rx_tx_queues(
+ 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 k, *v = data;
+ int r;
+
+ if (isempty(rvalue)) {
+ *v = 0;
+ return 0;
+ }
+
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
+ return 0;
+ }
+ if (k == 0 || k > 4096) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
+ return 0;
+ }
+
+ *v = k;
return 0;
}
MAC_ADDRESS_POLICY_RANDOM,
MAC_ADDRESS_POLICY_NONE,
_MAC_ADDRESS_POLICY_MAX,
- _MAC_ADDRESS_POLICY_INVALID = -1
+ _MAC_ADDRESS_POLICY_INVALID = -EINVAL,
} MACAddressPolicy;
typedef enum NamePolicy {
NAMEPOLICY_PATH,
NAMEPOLICY_MAC,
_NAMEPOLICY_MAX,
- _NAMEPOLICY_INVALID = -1
+ _NAMEPOLICY_INVALID = -EINVAL,
} NamePolicy;
struct link_config {
char *name;
char **alternative_names;
char *alias;
+ uint32_t txqueues;
+ uint32_t rxqueues;
uint32_t txqueuelen;
uint32_t mtu;
uint32_t gso_max_segments;
};
int link_config_ctx_new(link_config_ctx **ret);
-void link_config_ctx_free(link_config_ctx *ctx);
+link_config_ctx* link_config_ctx_free(link_config_ctx *ctx);
DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
int link_load_one(link_config_ctx *ctx, const char *filename);
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
+CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen);
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
" -g --whitelisted Treat device as whitelisted\n"
" -u --replace-whitespace Replace all whitespace by underscores\n"
" -v --verbose Verbose logging\n"
- " -x --export Print values as environment keys\n"
- , program_invocation_short_name);
-
+ " -x --export Print values as environment keys\n",
+ program_invocation_short_name);
}
static int set_options(int argc, char **argv,
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "tests.h"
+#include "udev-builtin.h"
+
+static void test_udev_builtin_cmd_to_ptr(void) {
+ log_info("/* %s */", __func__);
+
+ /* Those could have been static asserts, but ({}) is not allowed there. */
+#if HAVE_BLKID
+ assert_se(UDEV_BUILTIN_CMD_TO_PTR(UDEV_BUILTIN_BLKID));
+ assert_se(PTR_TO_UDEV_BUILTIN_CMD(UDEV_BUILTIN_CMD_TO_PTR(UDEV_BUILTIN_BLKID)) == UDEV_BUILTIN_BLKID);
+#endif
+ assert_se(UDEV_BUILTIN_CMD_TO_PTR(UDEV_BUILTIN_BTRFS));
+ assert_se(PTR_TO_UDEV_BUILTIN_CMD(UDEV_BUILTIN_CMD_TO_PTR(UDEV_BUILTIN_BTRFS)) == UDEV_BUILTIN_BTRFS);
+ assert_se(PTR_TO_UDEV_BUILTIN_CMD(UDEV_BUILTIN_CMD_TO_PTR(_UDEV_BUILTIN_INVALID)) == _UDEV_BUILTIN_INVALID);
+
+ assert_se(PTR_TO_UDEV_BUILTIN_CMD(NULL) == _UDEV_BUILTIN_INVALID);
+ assert_se(PTR_TO_UDEV_BUILTIN_CMD((void*) 10000) == _UDEV_BUILTIN_INVALID);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_udev_builtin_cmd_to_ptr();
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "path-util.h"
+#include "signal-util.h"
+#include "strv.h"
+#include "tests.h"
+#include "udev-event.h"
+#include "util.h"
+
+#define BUF_SIZE 1024
+
+static void test_event_spawn_core(bool with_pidfd, const char *cmd, char result_buf[BUF_SIZE]) {
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ _cleanup_(udev_event_freep) UdevEvent *event = NULL;
+
+ assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
+
+ assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0);
+ assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG));
+ assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, BUF_SIZE) == 0);
+
+ assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
+}
+
+static void test_event_spawn_cat(bool with_pidfd) {
+ _cleanup_strv_free_ char **lines = NULL;
+ _cleanup_free_ char *cmd = NULL;
+ char result_buf[BUF_SIZE];
+
+ log_debug("/* %s(%s) */", __func__, yes_no(with_pidfd));
+
+ assert_se(find_executable("cat", &cmd) >= 0);
+ assert_se(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent"));
+
+ test_event_spawn_core(with_pidfd, cmd, result_buf);
+
+ assert_se(lines = strv_split_newlines(result_buf));
+ strv_print(lines);
+
+ assert_se(strv_contains(lines, "INTERFACE=lo"));
+ assert_se(strv_contains(lines, "IFINDEX=1"));
+}
+
+static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) {
+ _cleanup_strv_free_ char **lines = NULL;
+ _cleanup_free_ char *cmd = NULL;
+ char result_buf[BUF_SIZE];
+
+ log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
+
+ assert_se(cmd = strjoin(self, " ", arg));
+
+ test_event_spawn_core(with_pidfd, cmd, result_buf);
+
+ assert_se(lines = strv_split_newlines(result_buf));
+ strv_print(lines);
+
+ assert_se(strv_contains(lines, "aaa"));
+ assert_se(strv_contains(lines, "bbb"));
+}
+
+static void test1(void) {
+ fprintf(stdout, "aaa\nbbb");
+ fprintf(stderr, "ccc\nddd");
+}
+
+static void test2(void) {
+ char buf[16384];
+
+ fprintf(stdout, "aaa\nbbb");
+
+ memset(buf, 'a', sizeof(buf) - 1);
+ char_array_0(buf);
+ fputs(buf, stderr);
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_free_ char *self = NULL;
+
+ if (argc > 1) {
+ if (streq(argv[1], "test1"))
+ test1();
+ else if (streq(argv[1], "test2"))
+ test2();
+ else
+ assert_not_reached("unknown command.");
+
+ return 0;
+ }
+
+ test_setup_logging(LOG_DEBUG);
+
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+
+ test_event_spawn_cat(true);
+ test_event_spawn_cat(false);
+
+ assert_se(path_make_absolute_cwd(argv[0], &self) >= 0);
+ path_simplify(self, true);
+
+ test_event_spawn_self(self, "test1", true);
+ test_event_spawn_self(self, "test1", false);
+
+ test_event_spawn_self(self, "test2", true);
+ test_event_spawn_self(self, "test2", false);
+
+ return 0;
+}
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include "device-util.h"
#include "alloc-util.h"
+#include "device-util.h"
+#include "errno-util.h"
#include "link-config.h"
#include "log.h"
#include "string-util.h"
r = link_get_driver(ctx, dev, &driver);
if (r < 0)
- log_device_full_errno(dev, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING,
+ log_device_full_errno(dev, ERRNO_IS_NOT_SUPPORTED(r) || r == -ENODEV ? LOG_DEBUG : LOG_WARNING,
r, "Failed to query device driver: %m");
else
udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver);
if (r < 0) {
if (r == -ENOENT)
return log_device_debug_errno(dev, r, "No matching link configuration found.");
+ if (r == -ENODEV)
+ return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it.");
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
r = link_config_apply(ctx, link, dev, &name);
- if (r < 0)
- log_device_warning_errno(dev, r, "Could not apply link config, ignoring: %m");
+ if (r == -ENODEV)
+ log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
+ else if (r < 0)
+ log_device_warning_errno(dev, r, "Could not apply link configuration, ignoring: %m");
udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename);
UDEV_BUILTIN_UACCESS,
#endif
_UDEV_BUILTIN_MAX,
- _UDEV_BUILTIN_INVALID = -1,
+ _UDEV_BUILTIN_INVALID = -EINVAL,
} UdevBuiltinCommand;
typedef struct UdevBuiltin {
bool run_once;
} UdevBuiltin;
-#define PTR_TO_UDEV_BUILTIN_CMD(p) ((UdevBuiltinCommand) ((intptr_t) (p)-1))
-#define UDEV_BUILTIN_CMD_TO_PTR(u) ((void *) ((intptr_t) (u)+1))
+#define UDEV_BUILTIN_CMD_TO_PTR(u) \
+ ({ \
+ UdevBuiltinCommand _u = (u); \
+ _u < 0 ? NULL : (void*)(intptr_t) (_u + 1); \
+ })
+
+#define PTR_TO_UDEV_BUILTIN_CMD(p) \
+ ({ \
+ void *_p = (p); \
+ _p && (intptr_t)(_p) <= _UDEV_BUILTIN_MAX ? \
+ (UdevBuiltinCommand)((intptr_t)_p - 1) : _UDEV_BUILTIN_INVALID; \
+ })
#if HAVE_BLKID
extern const UdevBuiltin udev_builtin_blkid;
udev_ctrl_disconnect(uctrl);
udev_ctrl_unref(uctrl);
(void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON);
+ /* We don't return NULL here because uctrl is not freed */
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl *, udev_ctrl_disconnect_and_listen_again);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct udev_ctrl*, udev_ctrl_disconnect_and_listen_again, NULL);
static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL;
FORMAT_SUBST_ROOT,
FORMAT_SUBST_SYS,
_FORMAT_SUBST_TYPE_MAX,
- _FORMAT_SUBST_TYPE_INVALID = -1
+ _FORMAT_SUBST_TYPE_INVALID = -EINVAL,
} FormatSubstitutionType;
struct subst_map_entry {
v = strv_split_newlines(p);
if (!v)
- return 0;
+ log_oom_debug();
STRV_FOREACH(q, v)
log_device_debug(spawn->device, "'%s'(%s) '%s'", spawn->cmd,
fd == spawn->fd_stdout ? "out" : "err", *q);
}
-
if (l == 0)
return 0;
- /* Re-enable the event source if we did not encounter EOF */
reenable:
+ /* Re-enable the event source if we did not encounter EOF */
+
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
if (r < 0)
log_device_error_errno(spawn->device, r,
r = sd_event_new(&e);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to allocate sd-event object: %m");
if (spawn->timeout_usec > 0) {
usec_t usec, age_usec;
usec + spawn->timeout_warn_usec, USEC_PER_SEC,
on_spawn_timeout_warning, spawn);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to create timeout warning event source: %m");
}
spawn->timeout_usec -= age_usec;
r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
usec + spawn->timeout_usec, USEC_PER_SEC, on_spawn_timeout, spawn);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to create timeout event source: %m");
}
}
if (spawn->fd_stdout >= 0) {
r = sd_event_add_io(e, &stdout_source, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to create stdio event source: %m");
r = sd_event_source_set_enabled(stdout_source, SD_EVENT_ONESHOT);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to enable stdio event source: %m");
}
if (spawn->fd_stderr >= 0) {
r = sd_event_add_io(e, &stderr_source, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to create stderr event source: %m");
r = sd_event_source_set_enabled(stderr_source, SD_EVENT_ONESHOT);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to enable stderr event source: %m");
}
r = sd_event_add_child(e, &sigchld_source, spawn->pid, WEXITED, on_spawn_sigchld, spawn);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to create sigchild event source: %m");
/* SIGCHLD should be processed after IO is complete */
r = sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1);
if (r < 0)
- return r;
+ return log_device_debug_errno(spawn->device, r, "Failed to set priority to sigchild event source: %m");
return sd_event_loop(e);
}
OP_ASSIGN, /* = */
OP_ASSIGN_FINAL, /* := */
_OP_TYPE_MAX,
- _OP_TYPE_INVALID = -1
+ _OP_TYPE_INVALID = -EINVAL,
} UdevRuleOperatorType;
typedef enum {
MATCH_TYPE_GLOB_WITH_EMPTY, /* shell globs ?,*,[] with empty string, e.g., "|foo*" */
MATCH_TYPE_SUBSYSTEM, /* "subsystem", "bus", or "class" */
_MATCH_TYPE_MAX,
- _MATCH_TYPE_INVALID = -1
+ _MATCH_TYPE_INVALID = -EINVAL,
} UdevRuleMatchType;
typedef enum {
SUBST_TYPE_FORMAT, /* % or $ */
SUBST_TYPE_SUBSYS, /* "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
_SUBST_TYPE_MAX,
- _SUBST_TYPE_INVALID = -1
+ _SUBST_TYPE_INVALID = -EINVAL,
} UdevRuleSubstituteType;
typedef enum {
TK_A_RUN_PROGRAM, /* string */
_TK_TYPE_MAX,
- _TK_TYPE_INVALID = -1,
+ _TK_TYPE_INVALID = -EINVAL,
} UdevRuleTokenType;
typedef enum {
rule_line->tokens = NULL;
}
-static void udev_rule_line_free(UdevRuleLine *rule_line) {
+static UdevRuleLine* udev_rule_line_free(UdevRuleLine *rule_line) {
if (!rule_line)
- return;
+ return NULL;
udev_rule_line_clear_tokens(rule_line);
}
free(rule_line->line);
- free(rule_line);
+ return mfree(rule_line);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRuleLine*, udev_rule_line_free);
return token->op == OP_MATCH;
}
case TK_M_IMPORT_PROGRAM: {
- char result[UDEV_LINE_SIZE], *line, *pos;
+ _cleanup_strv_free_ char **lines = NULL;
+ char result[UDEV_LINE_SIZE], **line;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf);
return token->op == OP_NOMATCH;
}
- for (line = result; !isempty(line); line = pos) {
- char *key, *value;
+ lines = strv_split_newlines(result);
+ if (!lines)
+ return log_oom();
- pos = strchr(line, '\n');
- if (pos)
- *pos++ = '\0';
+ STRV_FOREACH(line, lines) {
+ char *key, *value;
- r = get_property_from_string(line, &key, &value);
+ r = get_property_from_string(*line, &key, &value);
if (r < 0) {
log_rule_debug_errno(dev, rules, r,
"Failed to parse key and value from '%s', ignoring: %m",
- line);
+ *line);
continue;
}
if (r == 0)
}
case TK_M_IMPORT_BUILTIN: {
UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data);
+ assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
unsigned mask = 1U << (int) cmd;
if (udev_builtin_run_once(cmd)) {
if (level < 0)
level = event->default_log_level;
- log_set_max_level_all_realms(level);
+ log_set_max_level(level);
if (level == LOG_DEBUG && !event->log_level_was_debug) {
/* The log level becomes LOG_DEBUG at first time. Let's log basic information. */
token->value);
break;
}
- if (free_and_strdup(&event->name, buf) < 0)
- return log_oom();
+ r = free_and_strdup_warn(&event->name, buf);
+ if (r < 0)
+ return r;
log_rule_debug(dev, rules, "NAME '%s'", event->name);
break;
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
ordered_hashmap_clear_free_key(event->run_list);
- r = ordered_hashmap_ensure_allocated(&event->run_list, NULL);
- if (r < 0)
- return log_oom();
-
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
cmd = strdup(buf);
if (!cmd)
return log_oom();
- r = ordered_hashmap_put(event->run_list, cmd, token->data);
- if (r < 0)
+ r = ordered_hashmap_ensure_put(&event->run_list, NULL, cmd, token->data);
+ if (r == -ENOMEM)
return log_oom();
+ if (r < 0)
+ return log_rule_error_errno(dev, rules, r, "Failed to store command '%s': %m", cmd);
TAKE_PTR(cmd);
ESCAPE_NONE, /* OPTIONS="string_escape=none" */
ESCAPE_REPLACE, /* OPTIONS="string_escape=replace" */
_ESCAPE_TYPE_MAX,
- _ESCAPE_TYPE_INVALID = -1
+ _ESCAPE_TYPE_INVALID = -EINVAL,
} UdevRuleEscapeType;
int udev_rules_parse_file(UdevRules *rules, const char *filename);
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# 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.
+
Name: udev
Description: udev
Version: @PROJECT_VERSION@
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
" --ping Wait for udev to respond to a ping message\n"
- " -t --timeout=SECONDS Maximum time to block for a reply\n"
- , program_invocation_short_name);
+ " -t --timeout=SECONDS Maximum time to block for a reply\n",
+ program_invocation_short_name);
return 0;
}
" -r --root=PATH Alternative root path in the filesystem\n\n"
"NOTE:\n"
"The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n"
- "Please use systemd-hwdb instead.\n"
- , program_invocation_short_name);
+ "Please use systemd-hwdb instead.\n",
+ program_invocation_short_name);
return 0;
}
" -e --export-db Export the content of the udev database\n"
" -c --cleanup-db Clean up the udev database\n"
" -w --wait-for-initialization[=SECONDS]\n"
- " Wait for device to be initialized\n"
- , program_invocation_short_name);
+ " Wait for device to be initialized\n",
+ program_invocation_short_name);
return 0;
}
" -k --kernel Print kernel uevents\n"
" -u --udev Print udev events\n"
" -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
- " -t --tag-match=TAG Filter events by tag\n"
- , program_invocation_short_name);
+ " -t --tag-match=TAG Filter events by tag\n",
+ program_invocation_short_name);
return 0;
}
" -h --help Show this help\n"
" -V --version Show package version\n"
" -t --timeout=SEC Maximum time to wait for events\n"
- " -E --exit-if-exists=FILE Stop waiting if file exists\n"
- , program_invocation_short_name);
+ " -E --exit-if-exists=FILE Stop waiting if file exists\n",
+ program_invocation_short_name);
return 0;
}
"Test a built-in command.\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n\n"
- "Commands:\n"
- , program_invocation_short_name);
+ "Commands:\n",
+ program_invocation_short_name);
udev_builtin_list();
" -h --help Show this help\n"
" -V --version Show package version\n"
" -a --action=ACTION|help Set action string\n"
- " -N --resolve-names=early|late|never When to resolve names\n"
- , program_invocation_short_name);
+ " -N --resolve-names=early|late|never When to resolve names\n",
+ program_invocation_short_name);
return 0;
}
" -b --parent-match=NAME Trigger devices with that parent device\n"
" -w --settle Wait for the triggered events to complete\n"
" --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
- " before triggering uevents\n"
- , program_invocation_short_name);
+ " before triggering uevents\n",
+ program_invocation_short_name);
return 0;
}
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
break;
- case 'c':
+ case 'c': {
+ DeviceAction a;
+
if (streq(optarg, "help")) {
dump_device_action_table();
return 0;
}
- if (device_action_from_string(optarg) < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
+
+ a = device_action_from_string(optarg);
+ if (a < 0)
+ return log_error_errno(a, "Unknown action '%s'", optarg);
action = optarg;
break;
+ }
case 's':
r = sd_device_enumerator_add_match_subsystem(e, optarg, true);
if (r < 0)
printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n"
"Send control commands or test the device manager.\n\n"
- "Commands:\n"
- , program_invocation_short_name);
+ "Commands:\n",
+ program_invocation_short_name);
for (i = 0; i < ELEMENTSOF(short_descriptions); i++)
printf(" %-12s %s\n", short_descriptions[i][0], short_descriptions[i][1]);
if (r <= 0)
return r;
- log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
-
r = mac_selinux_init();
if (r < 0)
return r;
free(event);
}
-static void worker_free(struct worker *worker) {
+static struct worker* worker_free(struct worker *worker) {
if (!worker)
- return;
+ return NULL;
assert(worker->manager);
sd_device_monitor_unref(worker->monitor);
event_free(worker->event);
- free(worker);
+ return mfree(worker);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct worker *, worker_free);
manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]);
}
-static void manager_free(Manager *manager) {
+static Manager* manager_free(Manager *manager) {
if (!manager)
- return;
+ return NULL;
udev_builtin_exit();
safe_close(manager->fd_inotify);
safe_close_pair(manager->worker_watch);
- free(manager);
+ return mfree(manager);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
log_device_warning_errno(dev, r, "Failed to send signal to main daemon, ignoring: %m");
/* Reset the log level, as it might be changed by "OPTIONS=log_level=". */
- log_set_max_level_all_realms(manager->log_level);
+ log_set_max_level(manager->log_level);
return 1;
}
switch (type) {
case UDEV_CTRL_SET_LOG_LEVEL:
log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
- log_set_max_level_all_realms(value->intval);
+ log_set_max_level(value->intval);
manager->log_level = value->intval;
manager_kill_workers(manager);
break;
" -t --event-timeout=SECONDS Seconds to wait before terminating an event\n"
" -N --resolve-names=early|late|never\n"
" When to resolve users and groups\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ link);
return 0;
}
log_set_max_level(LOG_DEBUG);
}
- log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
-
r = must_be_root();
if (r < 0)
return r;
case 'h':
printf("%s [-h,--help] <device file>\n\n"
"Video4Linux device identification.\n\n"
- " -h Print this message\n"
- , program_invocation_short_name);
+ " -h Print this message\n",
+ program_invocation_short_name);
return 0;
case '?':
return -EINVAL;
struct stat st;
int r, q = 0;
- log_setup_service();
+ log_setup();
if (stat("/usr", &st) < 0) {
log_error_errno(errno, "Failed to stat /usr: %m");
static int run(int argc, char *argv[]) {
_cleanup_(context_clear) Context c = {
#if HAVE_AUDIT
- .audit_fd = -1
+ .audit_fd = -1,
#endif
};
int r;
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program requires one argument.");
- log_setup_service();
+ log_setup();
umask(0022);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program requires one argument.");
- log_setup_service();
+ log_setup();
umask(0022);
OUTPUT_TABLE,
OUTPUT_FRIENDLY,
OUTPUT_JSON,
- _OUTPUT_INVALID = -1
+ _OUTPUT_INVALID = -EINVAL,
} arg_output = _OUTPUT_INVALID;
static PagerFlags arg_pager_flags = 0;
" -N Do not synthesize or include glibc NSS data\n"
" (Same as --synthesize=no --with-nss=no)\n"
" --synthesize=BOOL Synthesize root/nobody user\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , ansi_highlight(), ansi_normal()
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ link);
return 0;
}
int r;
- log_setup_cli();
+ log_setup();
r = parse_argv(argc, argv);
if (r <= 0)
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
- log_setup_service();
+ log_setup();
umask(0022);
unsigned n_iterations = 0;
int m, listen_fd, r;
- log_setup_service();
+ log_setup();
m = sd_listen_fds(false);
if (m < 0)
unsigned idx = 0;
int r;
- log_setup_service();
+ log_setup();
umask(0022);
printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH [OPTIONS]\n"
"%s detach VOLUME\n\n"
"Attaches or detaches an integrity protected block device.\n"
- "\nSee the %s for details.\n"
- , program_invocation_short_name
- , program_invocation_short_name
- , link
- );
+ "\nSee the %s for details.\n",
+ program_invocation_short_name,
+ program_invocation_short_name,
+ link);
return 0;
}
if (argc < 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments.");
- log_setup_service();
+ log_setup();
umask(0022);
-/* Detailed project version that includes git commit when not built from a release.
+/* SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Detailed project version that includes git commit when not built from a release.
* Use this in preference to PROJECT_VERSION, with the following exceptions:
* - where a simplified form is expected for compatibility, for example
* 'udevadm version',
dev_t devt;
int r;
- log_setup_service();
+ log_setup();
if (argc > 3)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
/* The kernel command line always wins. However if nothing was set there, the argument passed here wins instead. */
m = volatile_mode_from_string(argv[1]);
if (m < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Couldn't parse volatile mode: %s", argv[1]);
+ return log_error_errno(m, "Couldn't parse volatile mode: %s", argv[1]);
}
if (argc < 3)
#include "alloc-util.h"
#include "fd-util.h"
#include "fs-util.h"
+#include "fuzz.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
-#include "fuzz.h"
#include "xdg-autostart-service.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_free_ char *t;
assert_se(t = xdg_autostart_service_translate_name("a-b.blub.desktop"));
- assert_se(streq(t, "app-a\\x2db.blub-autostart.service"));
+ assert_se(streq(t, "app-a\\x2db.blub@autostart.service"));
}
static void test_xdg_format_exec_start_one(const char *exec, const char *expected) {
}
static const char* const xdg_desktop_file[] = {
- "[Desktop Entry]\n"
- "Exec\t =\t /bin/sleep 100\n" /* Whitespace Before/After = must be ignored */
- "OnlyShowIn = A;B;\n"
- "NotShowIn=C;;D\\\\\\;;E\n", /* "C", "", "D\;", "E" */
+ ("[Desktop Entry]\n"
+ "Exec\t =\t /bin/sleep 100\n" /* Whitespace Before/After = must be ignored */
+ "OnlyShowIn = A;B;\n"
+ "NotShowIn=C;;D\\\\\\;;E\n"), /* "C", "", "D\;", "E" */
- "[Desktop Entry]\n"
- "Exec=a\n"
- "Exec=b\n",
+ ("[Desktop Entry]\n"
+ "Exec=a\n"
+ "Exec=b\n"),
- "[Desktop Entry]\n"
- "Hidden=\t true\n",
+ ("[Desktop Entry]\n"
+ "Hidden=\t true\n"),
};
static void test_xdg_desktop_parse(unsigned i, const char *s) {
if (!escaped)
return NULL;
- return strjoin("app-", escaped, "-autostart.service");
+ return strjoin("app-", escaped, "@autostart.service");
}
static int xdg_config_parse_bool(
ninja: Entering directory `/home/zbyszek/src/systemd/build'
ninja: no work to do.
--x-- Running TEST-01-BASIC --x--
-+ make -C TEST-01-BASIC BUILD_DIR=/home/zbyszek/src/systemd/build clean setup run
++ make -C TEST-01-BASIC clean setup run
make: Entering directory '/home/zbyszek/src/systemd/test/TEST-01-BASIC'
TEST-01-BASIC CLEANUP: Basic systemd setup
TEST-01-BASIC SETUP: Basic systemd setup
make: Leaving directory '/home/zbyszek/src/systemd/test/TEST-01-BASIC'
--x-- Result of TEST-01-BASIC: 0 --x--
--x-- Running TEST-02-CRYPTSETUP --x--
-+ make -C TEST-02-CRYPTSETUP BUILD_DIR=/home/zbyszek/src/systemd/build clean setup run
++ make -C TEST-02-CRYPTSETUP clean setup run
If one of the tests fails, then $subdir/test.log contains the log file of
the test.
Note that in the second case, the path is relative to the test case directory.
An absolute path may also be used in both cases.
+Testing installed binaries instead of built
+===========================================
+
+To run the extended testsuite using the systemd installed on the system instead
+of the systemd from a build, use the NO_BUILD=1:
+
+$ sudo NO_BUILD=1 test/run-integration-tests
+
Configuration variables
=======================
To add new dependencies or new binaries to the packages used during the tests,
a merge request can be sent to: https://salsa.debian.org/systemd-team/systemd
targeting the 'upstream-ci' branch.
+
+The cloud-side infrastructure, that is hooked into the Github interface, is
+located at:
+
+https://git.launchpad.net/autopkgtest-cloud/
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
-
all setup run clean clean-again:
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
+ @TEST_BASE_DIR=../ ./test.sh --$@
.PHONY: all setup run clean clean-again
. $TEST_BASE_DIR/test-functions
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
- (
- LOG_LEVEL=5
- setup_basic_environment
- mask_supporting_services
-
- # install tests manually so the test is functional even when -Dinstall-tests=false
- mkdir -p $initdir/usr/lib/systemd/tests/testdata/units/
- cp -v $(dirname $0)/../units/{testsuite-01,end}.service $initdir/usr/lib/systemd/tests/testdata/units/
- )
+test_append_files() {
+ # install tests manually so the test is functional even when -Dinstall-tests=false
+ local dst="$1/usr/lib/systemd/tests/testdata/units/"
+ mkdir -p "$dst"
+ cp -v $TEST_UNITS_DIR/{testsuite-01,end}.service $TEST_UNITS_DIR/testsuite.target "$dst"
}
do_test "$@" 01
--- /dev/null
+/usr/lib/systemd/tests/testdata/testsuite-06\.units(/.*)? system_u:object_r:systemd_unit_file_t:s0
SETUP_SELINUX=yes
KERNEL_APPEND="$KERNEL_APPEND selinux=1 security=selinux"
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
+test_append_files() {
(
- LOG_LEVEL=5
-
- setup_basic_environment
- mask_supporting_services
-
+ setup_selinux
local _modules_dir=/var/lib/selinux
- rm -rf $initdir/$_modules_dir
- if ! cp -ar $_modules_dir $initdir/$_modules_dir; then
+ rm -rf $1/$_modules_dir
+ if ! cp -ar $_modules_dir $1/$_modules_dir; then
dfatal "Failed to copy $_modules_dir"
exit 1
fi
local _policy_headers_dir=/usr/share/selinux/devel
- rm -rf $initdir/$_policy_headers_dir
+ rm -rf $1/$_policy_headers_dir
inst_dir /usr/share/selinux
- if ! cp -ar $_policy_headers_dir $initdir/$_policy_headers_dir; then
+ if ! cp -ar $_policy_headers_dir $1/$_policy_headers_dir; then
dfatal "Failed to copy $_policy_headers_dir"
exit 1
fi
- mkdir $initdir/systemd-test-module
- cp systemd_test.te $initdir/systemd-test-module
- cp systemd_test.if $initdir/systemd-test-module
+ mkdir $1/systemd-test-module
+ cp systemd_test.te $1/systemd-test-module
+ cp systemd_test.if $1/systemd-test-module
+ cp systemd_test.fc $1/systemd-test-module
dracut_install -o sesearch
dracut_install runcon
dracut_install checkmodule semodule semodule_package m4 make load_policy sefcontext_compile
. $TEST_BASE_DIR/test-functions
QEMU_TIMEOUT=300
FSTYPE=ext4
-
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
- (
- LOG_LEVEL=5
- setup_basic_environment
- )
- mask_supporting_services
-}
+TEST_FORCE_NEWIMAGE=1
do_test "$@" 08
. $TEST_BASE_DIR/test-functions
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
+test_append_files() {
(
- LOG_LEVEL=5
- setup_basic_environment
- mask_supporting_services
-
- ../create-busybox-container $initdir/testsuite-13.nc-container
- initdir="$initdir/testsuite-13.nc-container" dracut_install nc ip md5sum
+ ../create-busybox-container $1/testsuite-13.nc-container
+ initdir="$1/testsuite-13.nc-container" dracut_install nc ip md5sum
)
}
. $TEST_BASE_DIR/test-functions
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
- (
- LOG_LEVEL=5
- setup_basic_environment
- mask_supporting_services
- printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >$initdir/etc/machine-id
- )
+test_append_files() {
+ printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >$1/etc/machine-id
}
do_test "$@" 14
TEST_DESCRIPTION="cryptsetup systemd setup"
IMAGE_NAME="cryptsetup"
TEST_NO_NSPAWN=1
+TEST_FORCE_NEWIMAGE=1
. $TEST_BASE_DIR/test-functions
. $TEST_BASE_DIR/test-functions
QEMU_TIMEOUT=300
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
+test_append_files() {
(
- LOG_LEVEL=5
- setup_basic_environment
- mask_supporting_services
-
instmods dummy
generate_module_dependencies
)
TEST_DESCRIPTION="test systemd-dissect"
IMAGE_NAME="dissect"
TEST_NO_NSPAWN=1
+TEST_INSTALL_VERITY_MINIMAL=1
. $TEST_BASE_DIR/test-functions
-command -v mksquashfs >/dev/null 2>&1 || exit 0
-command -v veritysetup >/dev/null 2>&1 || exit 0
command -v sfdisk >/dev/null 2>&1 || exit 0
# Need loop devices for systemd-dissect
-test_create_image() {
- create_empty_image_rootdir
-
- # Create what will eventually be our root filesystem onto an overlay
- # If some pieces are missing from the host, skip rather than fail
+test_append_files() {
(
- LOG_LEVEL=5
- setup_basic_environment
- mask_supporting_services
-
instmods loop =block
instmods squashfs =squashfs
instmods dm_verity =md
install_dmevent
generate_module_dependencies
inst_binary losetup
-
- BASICTOOLS=(
- bash
- cat
- mount
- )
- oldinitdir=$initdir
- export initdir=$TESTDIR/minimal
- mkdir -p $initdir/usr/lib $initdir/etc
- setup_basic_dirs
- install_basic_tools
- cp $os_release $initdir/usr/lib/os-release
- ln -s ../usr/lib/os-release $initdir/etc/os-release
- echo MARKER=1 >> $initdir/usr/lib/os-release
- mksquashfs $initdir $oldinitdir/usr/share/minimal.raw
- veritysetup format $oldinitdir/usr/share/minimal.raw $oldinitdir/usr/share/minimal.verity | grep '^Root hash:' | cut -f2 | tr -d '\n' > $oldinitdir/usr/share/minimal.roothash
- export initdir=$oldinitdir
+ install_verity_minimal
)
}
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
-
all setup run clean clean-again:
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
+ @TEST_BASE_DIR=../ ./test.sh --$@
# finish option is used to run checks that can only be run outside of
# the test execution. Example case, honor first shutdown, proof is obtained
# the test will loop and will be terminated via a command timeout.
# This just provides concrete confirmation.
finish:
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./fini.sh --$@
+ @TEST_BASE_DIR=../ ./fini.sh --$@
.PHONY: all setup run clean clean-again finish
--- /dev/null
+../TEST-01-BASIC/Makefile
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -e
+TEST_DESCRIPTION="test systemd-portabled"
+IMAGE_NAME="portabled"
+TEST_NO_NSPAWN=1
+TEST_INSTALL_VERITY_MINIMAL=1
+
+. $TEST_BASE_DIR/test-functions
+
+# Need loop devices for mounting images
+test_append_files() {
+ (
+ instmods loop =block
+ instmods squashfs =squashfs
+ instmods dm_verity =md
+ install_dmevent
+ generate_module_dependencies
+ inst_binary losetup
+ inst_binary mksquashfs
+ inst_binary unsquashfs
+ install_verity_minimal
+ )
+}
+
+do_test "$@" 58
AlternativeNamesPolicy=
AlternativeName=
Alias=
-TxQueueLength=
+TransmitQueues=
+ReceiveQueues=
+TransmitQueueLength=
MTUBytes=
BitsPerSecond=
Duplex=
MACAddress=
PermanentMACAddress=
[Link]
+ActivationPolicy=
RequiredForOnline=
ARP=
AllMulticast=
MACAddress=
Group=
Promiscuous=
-TransmitQueues=
-ReceiveQueues=
[SR-IOV]
VirtualFunction=
MACSpoofCheck=
UseAddress=
UseNTP=
UseDNS=
+UseFQDN=
RapidCommit=
ForceDHCPv6PDOtherInformation=
PrefixDelegationHint=
DirectoryNotEmpty=
Documentation=
DynamicUser=
+ExecPaths=
ExecReload=
ExecCondition=
ExecStart=
Mark=
MaxConnections=
MaxConnectionsPerSource=
+ManagedOOMSwap=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimitPercent=
+ManagedOOMPreference=
MemoryAccounting=
MemoryHigh=
MemoryLimit=
MessageQueueMessageSize=
MountAPIVFS=
NoDelay=
+NoExecPaths=
NoNewPrivileges=
NonBlocking=
NotifyAccess=
#!/usr/bin/env bash
set -e
-BUILD_DIR="$($(dirname "$0")/../tools/find-build-dir.sh)"
+if [ "$NO_BUILD" ]; then
+ BUILD_DIR=""
+elif BUILD_DIR="$($(dirname "$0")/../tools/find-build-dir.sh)"; then
+ ninja -C "$BUILD_DIR"
+else
+ echo "No build found, please set BUILD_DIR or NO_BUILD" >&2
+ exit 1
+fi
+
if [ $# -gt 0 ]; then
- args="$@"
+ args="$*"
else
args="setup run clean-again"
fi
-args_no_clean=$(sed -r 's/\bclean.*\b//g' <<<$args)
-do_clean=$( [ "$args" = "$args_no_clean" ]; echo $? )
+
+VALID_TARGETS="all setup run clean clean-again"
+
+is_valid_target() {
+ for target in $VALID_TARGETS; do
+ [ "$1" = "$target" ] && return 0
+ done
+ return 1
+}
+
+# reject invalid make targets in $args
+for arg in $args; do
+ if ! is_valid_target "$arg"; then
+ echo "Invalid target: $arg" >&2
+ exit 1
+ fi
+done
+
+CLEAN=0
+CLEANAGAIN=0
+
+# separate 'clean' and 'clean-again' operations
+[[ "$args" =~ "clean-again" ]] && CLEANAGAIN=1
+args=${args/clean-again}
+[[ "$args" =~ "clean" ]] && CLEAN=1
+args=${args/clean}
declare -A results
declare -A times
cd "$(dirname "$0")"
-# Let's always do the cleaning operation first, because it destroys the image
-# cache.
-if [ $do_clean = 1 ]; then
- for TEST in TEST-??-* ; do
- ( set -x ; make -C "$TEST" "BUILD_DIR=$BUILD_DIR" clean )
- done
-
- [ -n "$args_no_clean" ] || exit 0
-fi
-
pass_deny_list() {
for marker in $DENY_LIST_MARKERS $BLACKLIST_MARKERS; do
if [ -f "$1/$marker" ]; then
return 0
}
-for TEST in TEST-??-* ; do
- COUNT=$(($COUNT+1))
+# Let's always do the cleaning operation first, because it destroys the image
+# cache.
+if [ $CLEAN = 1 ]; then
+ for TEST in TEST-??-* ; do
+ ( set -x ; make -C "$TEST" clean )
+ done
+fi
+
+# Run actual tests (if requested)
+if [[ $args =~ [a-z] ]]; then
+ for TEST in TEST-??-* ; do
+ COUNT=$(($COUNT+1))
- pass_deny_list $TEST || continue
- start=$(date +%s)
+ pass_deny_list $TEST || continue
+ start=$(date +%s)
- echo -e "\n--x-- Running $TEST --x--"
- set +e
- ( set -x ; make -C "$TEST" "BUILD_DIR=$BUILD_DIR" $args_no_clean )
- RESULT=$?
- set -e
- echo "--x-- Result of $TEST: $RESULT --x--"
+ echo -e "\n--x-- Running $TEST --x--"
+ set +e
+ ( set -x ; make -C "$TEST" $args )
+ RESULT=$?
+ set -e
+ echo "--x-- Result of $TEST: $RESULT --x--"
- results["$TEST"]="$RESULT"
- times["$TEST"]=$(( $(date +%s) - $start ))
+ results["$TEST"]="$RESULT"
+ times["$TEST"]=$(( $(date +%s) - $start ))
- [ "$RESULT" -ne "0" ] && FAILURES=$(($FAILURES+1))
-done
+ [ "$RESULT" -ne "0" ] && FAILURES=$(($FAILURES+1))
+ done
+fi
-if [ $FAILURES -eq 0 -a $do_clean = 1 ]; then
+# Run clean-again, if requested, and if no tests failed
+if [ $FAILURES -eq 0 -a $CLEANAGAIN = 1 ]; then
for TEST in ${!results[@]}; do
- ( set -x ; make -C "$TEST" "BUILD_DIR=$BUILD_DIR" clean-again )
+ ( set -x ; make -C "$TEST" clean-again )
done
fi
--- /dev/null
+[Unit]
+Description=Test for NoExecPaths=
+
+[Service]
+Type=oneshot
+# This should work, as we explicitly disable the effect of NoExecPaths=
+ExecStart=+/bin/sh -c '/bin/cat /dev/null'
+# This should also work, as we do not disable the effect of NoExecPaths= but invert the exit code
+ExecStart=/bin/sh -x -c '! /bin/cat /dev/null'
+NoExecPaths=/bin/cat
UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}"
EFI_MOUNT="${EFI_MOUNT:-$(bootctl -x 2>/dev/null || echo /boot)}"
QEMU_MEM="${QEMU_MEM:-512M}"
+# Note that defining a different IMAGE_NAME in a test setup script will only result
+# in default.img being copied and renamed. It can then be extended by defining
+# a test_append_files() function. The $1 parameter will be the root directory.
+# To force creating a new image from scratch (eg: to encrypt it), also define
+# TEST_FORCE_NEWIMAGE=1 in the test setup script.
IMAGE_NAME=${IMAGE_NAME:-default}
TEST_REQUIRE_INSTALL_TESTS="${TEST_REQUIRE_INSTALL_TESTS:-1}"
TEST_PARALLELIZE="${TEST_PARALLELIZE:-0}"
ROOTLIBDIR=/usr/lib/systemd
fi
+# The calling test.sh scripts have TEST_BASE_DIR set via their Makefile, but we don't need them to provide it
+TEST_BASE_DIR=${TEST_BASE_DIR:-$(realpath $(dirname "$BASH_SOURCE"))}
+TEST_UNITS_DIR="$TEST_BASE_DIR/units"
+SOURCE_DIR=$(realpath "$TEST_BASE_DIR/..")
+TOOLS_DIR="$SOURCE_DIR/tools"
+
+# note that find-build-dir.sh will return $BUILD_DIR if provided, else it will try to find it
+if ! BUILD_DIR=$($TOOLS_DIR/find-build-dir.sh); then
+ if [ "$NO_BUILD" ]; then
+ BUILD_DIR=$SOURCE_DIR
+ else
+ echo "ERROR: no build found, please set BUILD_DIR or use NO_BUILD" >&2
+ exit 1
+ fi
+fi
+
PATH_TO_INIT=$ROOTLIBDIR/systemd
[ "$SYSTEMD_JOURNALD" ] || SYSTEMD_JOURNALD=$(which -a $BUILD_DIR/systemd-journald $ROOTLIBDIR/systemd-journald 2>/dev/null | grep '^/' -m1)
[ "$SYSTEMD_JOURNAL_REMOTE" ] || SYSTEMD_JOURNAL_REMOTE=$(which -a $BUILD_DIR/systemd-journal-remote $ROOTLIBDIR/systemd-journal-remote 2>/dev/null | grep '^/' -m1)
[ "$SYSTEMD_NSPAWN" ] || SYSTEMD_NSPAWN=$(which -a $BUILD_DIR/systemd-nspawn systemd-nspawn 2>/dev/null | grep '^/' -m1)
[ "$JOURNALCTL" ] || JOURNALCTL=$(which -a $BUILD_DIR/journalctl journalctl 2>/dev/null | grep '^/' -m1)
+TESTFILE=${BASH_SOURCE[1]}
+if [ -z "$TESTFILE" ]; then
+ echo "ERROR: test-functions must be sourced from one of the TEST-*/test.sh scripts" >&2
+ exit 1
+fi
+TESTNAME=$(basename $(dirname $(realpath $TESTFILE)))
+STATEDIR="$BUILD_DIR/test/$TESTNAME"
+STATEFILE="$STATEDIR/.testdir"
+IMAGESTATEDIR="$STATEDIR/.."
+TESTLOG="$STATEDIR/test.log"
+
BASICTOOLS=(
awk
basename
rmdir
sed
seq
+ setfattr
setfont
setsid
sfdisk
vi
)
-STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
-STATEFILE="$STATEDIR/.testdir"
-IMAGESTATEDIR="$STATEDIR/.."
-TESTLOG="$STATEDIR/test.log"
-
is_built_with_asan() {
if ! type -P objdump >/dev/null; then
ddebug "Failed to find objdump. Assuming systemd hasn't been built with ASAN."
fi
# Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182
- local _asan_calls=$(objdump -dC $SYSTEMD_JOURNALD | egrep "callq\s+[0-9a-f]+\s+<__asan" -c)
+ local _asan_calls=$(objdump -dC $SYSTEMD_JOURNALD | egrep "callq?\s+[0-9a-f]+\s+<__asan" -c)
if (( $_asan_calls < 1000 )); then
return 1
else
return 0
}
+# Build two very minimal root images, with two units, one is the same and one is different across them
+install_verity_minimal() {
+ if [ -e $initdir/usr/share/minimal.raw ]; then
+ return
+ fi
+ if ! command -v mksquashfs >/dev/null 2>&1; then
+ dfatal "mksquashfs not found"
+ exit 1
+ fi
+ if ! command -v veritysetup >/dev/null 2>&1; then
+ dfatal "veritysetup not found"
+ exit 1
+ fi
+ (
+ BASICTOOLS=(
+ bash
+ cat
+ mount
+ sleep
+ )
+ oldinitdir=$initdir
+ rm -rfv $TESTDIR/minimal
+ export initdir=$TESTDIR/minimal
+ mkdir -p $initdir/usr/lib/systemd/system $initdir/etc
+ setup_basic_dirs
+ install_basic_tools
+ cp $os_release $initdir/usr/lib/os-release
+ ln -s ../usr/lib/os-release $initdir/etc/os-release
+ touch $initdir/etc/machine-id $initdir/etc/resolv.conf
+ echo MARKER=1 >> $initdir/usr/lib/os-release
+ echo -e "[Service]\nExecStartPre=cat /usr/lib/os-release\nExecStart=sleep 120" > $initdir/usr/lib/systemd/system/app0.service
+ cp $initdir/usr/lib/systemd/system/app0.service $initdir/usr/lib/systemd/system/app0-foo.service
+
+ mksquashfs $initdir $oldinitdir/usr/share/minimal_0.raw
+ veritysetup format $oldinitdir/usr/share/minimal_0.raw $oldinitdir/usr/share/minimal_0.verity | \
+ grep '^Root hash:' | cut -f2 | tr -d '\n' > $oldinitdir/usr/share/minimal_0.roothash
+
+ sed -i "s/MARKER=1/MARKER=2/g" $initdir/usr/lib/os-release
+ rm $initdir/usr/lib/systemd/system/app0-foo.service
+ cp $initdir/usr/lib/systemd/system/app0.service $initdir/usr/lib/systemd/system/app0-bar.service
+
+ mksquashfs $initdir $oldinitdir/usr/share/minimal_1.raw
+ veritysetup format $oldinitdir/usr/share/minimal_1.raw $oldinitdir/usr/share/minimal_1.verity | \
+ grep '^Root hash:' | cut -f2 | tr -d '\n' > $oldinitdir/usr/share/minimal_1.roothash
+ )
+}
+
setup_basic_environment() {
# create the basic filesystem layout
setup_basic_dirs
if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
create_asan_wrapper
fi
+ if [ -n "$TEST_INSTALL_VERITY_MINIMAL" ]; then
+ install_verity_minimal
+ fi
}
setup_selinux() {
fi
}
-install_systemd() {
+install_compiled_systemd() {
ddebug "Install compiled systemd"
local _ninja_bin=$(type -P ninja || type -P ninja-build)
exit 1
fi
(set -x; DESTDIR=$initdir "$_ninja_bin" -C $BUILD_DIR install)
+}
+
+install_debian_systemd() {
+ ddebug "Install debian systemd"
+
+ local _systemd_pkgs=$(grep -E '^Package:' ${SOURCE_DIR}/debian/control | cut -d ':' -f 2)
+ local _files=""
+ for deb in $_systemd_pkgs; do
+ _files=$(dpkg-query -L $deb 2>/dev/null) || continue
+ ddebug "Install debian files from package $deb"
+ for file in $_files; do
+ [ -e "$file" ] || continue
+ [ -d "$file" ] && continue
+ inst $file
+ done
+ done
+}
+
+install_distro_systemd() {
+ ddebug "Install distro systemd"
+
+ if [ "$LOOKS_LIKE_DEBIAN" ]; then
+ install_debian_systemd
+ else
+ dfatal "NO_BUILD not supported for this distro"
+ exit 1
+ fi
+}
+
+install_systemd() {
+ if [ "$NO_BUILD" ]; then
+ install_distro_systemd
+ else
+ install_compiled_systemd
+ fi
+
# remove unneeded documentation
rm -fr $initdir/usr/share/{man,doc}
install_missing_libraries() {
# install possible missing libraries
for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
- LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i):$(get_ldpath $i)/src/udev" inst_libs $i
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i
done
# A number of dependencies is now optional via dlopen, so the install
# we want an empty environment
> $initdir/etc/environment
> $initdir/etc/machine-id
+ > $initdir/etc/resolv.conf
# set the hostname
echo systemd-testsuite > $initdir/etc/hostname
mkdir -p $initdir/etc/systemd/system
mkdir -p $initdir/var/log/journal
- for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log dev proc sys sysroot root run run/lock run/initramfs; do
+ for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log var/tmp dev proc sys sysroot root run run/lock run/initramfs; do
if [ -L "/$d" ]; then
inst_symlink "/$d"
else
set +e
_umount_dir $initdir
rm -vf "$IMAGE_PUBLIC"
+ # If multiple setups/cleans are ran in parallel, this can cause a race
+ if [ ${TEST_PARALLELIZE} -ne 1 ]; then
+ rm -vf "${IMAGESTATEDIR}/default.img"
+ fi
rm -vfr "$TESTDIR"
rm -vf "$STATEFILE"
) || :
mount_initdir
else
if [ ! -e "$IMAGE_PUBLIC" ]; then
- # Create the backing public image, but then completely unmount
- # it and drop the loopback device responsible for it, since we're
- # going to symlink/copy the image and mount it again from
- # elsewhere.
- test_create_image
- test_setup_cleanup
- umount_loopback
- cleanup_loopdev
+ # default.img is the base that every test uses and optionally appends to
+ if [ ! -e "${IMAGESTATEDIR}/default.img" ] || [ -n "${TEST_FORCE_NEWIMAGE}" ]; then
+ # Create the backing public image, but then completely unmount
+ # it and drop the loopback device responsible for it, since we're
+ # going to symlink/copy the image and mount it again from
+ # elsewhere.
+ local image_old=${IMAGE_PUBLIC}
+ if [ -z "${TEST_FORCE_NEWIMAGE}" ]; then
+ IMAGE_PUBLIC="${IMAGESTATEDIR}/default.img"
+ fi
+ test_create_image
+ test_setup_cleanup
+ umount_loopback
+ cleanup_loopdev
+ IMAGE_PUBLIC="${image_old}"
+ fi
+ if [ "${IMAGE_NAME}" != "default" ] && [ -z "${TEST_FORCE_NEWIMAGE}" ]; then
+ cp -v "$(realpath "${IMAGESTATEDIR}/default.img")" "$IMAGE_PUBLIC"
+ fi
+ fi
+
+ local hook_defined=1
+ if declare -f -F test_append_files > /dev/null; then
+ hook_defined=$?
fi
echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)"
- if [ ${TEST_PARALLELIZE} -ne 0 ]; then
+ if [ ${TEST_PARALLELIZE} -ne 0 ] || [ ${hook_defined} -eq 0 ]; then
cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
else
ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
fi
mount_initdir
+ if [ ${hook_defined} -eq 0 ]; then
+ test_append_files "$initdir"
+ fi
fi
setup_nspawn_root
--- /dev/null
+[Match]
+Name=test1
+
+[Network]
+Address=192.168.10.30/24
+Gateway=192.168.10.1
--- /dev/null
+[Link]
+ActivationPolicy=always-down
--- /dev/null
+[Link]
+ActivationPolicy=always-up
--- /dev/null
+[Link]
+ActivationPolicy=down
--- /dev/null
+[Link]
+ActivationPolicy=manual
--- /dev/null
+[Link]
+ActivationPolicy=up
+++ /dev/null
-[Match]
-Name=dummy98
-
-[Network]
-IPv6AcceptRA=no
-
-# these lines are ignored
-Address=hogehoge
-Address=foofoo
-
-[Route]
-Gateway=20.20.20.1
-
-[Address]
-Address=10.2.3.4/16
-PreferredLifetime=0
-Scope=link
-
-[Address]
-Address=2001:0db8:0:f101::1/64
-
-[Address]
-Address=20.20.20.100/24
-
-[Address]
-# this section must be ignored
-Peer=hoge
-Address=10.10.0.1/16
-Label=30
-
-[Address]
-# this section must be ignored
-Label=30
-Peer=hoge
-Address=10.10.0.2/16
[Address]
Address=::/64
+[Address]
+Address=10.7.8.9/16
+PreferredLifetime=0
+Scope=link
+
+[Address]
+Address=2001:0db8:1:f101::1/64
+PreferredLifetime=0
+
# test for ENOBUFS issue #17012
[Network]
Address=10.3.3.1/16
--- /dev/null
+[Match]
+Name=dummy98
+
+[Network]
+IPv6ProxyNDPAddress=2607:5300:203:5215:5::1
+IPv6ProxyNDPAddress=2607:5300:203:5215:4::1
+IPv6ProxyNDPAddress=2607:5300:203:5215:3::1
+IPv6ProxyNDPAddress=2607:5300:203:5215:2::1
+IPv6ProxyNDPAddress=2607:5300:203:5215:1::1
+IPv6AcceptRA=no
+IPForward=yes
+Address=66.70.129.136/32
+Address=66.70.129.142/32
+Address=66.70.129.143/32
+
+[Address]
+Address=2607:5300:203:5215::1/64
+
+[Route]
+Destination=2607:5300:203:52ff:ff:ff:ff:ff
+
+[Route]
+Gateway=2607:5300:203:52ff:ff:ff:ff:ff
+Destination=::/0
Name=veth-peer
[Network]
+IPv6AcceptRA=no
IPv6SendRA=yes
[IPv6SendRA]
'25-address-dad-veth99.network',
'25-address-link-section.network',
'25-address-peer-ipv4.network',
- '25-address-preferred-lifetime-zero.network',
'25-address-static.network',
+ '25-activation-policy.network',
'25-bind-carrier.network',
'25-bond-active-backup-slave.netdev',
'25-fibrule-invert.network',
'25-gre-tunnel-remote-any.netdev',
'25-ip6gre-tunnel-remote-any.netdev',
'25-ipv6-address-label-section.network',
+ '25-ipv6-proxy-ndp.network',
'25-link-local-addressing-no.network',
'25-link-local-addressing-yes.network',
'25-link-section-unmanaged.network',
output = check_output('ip -4 address show dev dummy98')
print(output)
- self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
- self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
- self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
+ self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
+ self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
+ self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
+ self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
# test for ENOBUFS issue #17012
for i in range(1,254):
- self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
+ self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
# invalid sections
- self.assertNotRegex(output, '10.10.0.1/16')
- self.assertNotRegex(output, '10.10.0.2/16')
+ self.assertNotIn('10.10.0.1/16', output)
+ self.assertNotIn('10.10.0.2/16', output)
output = check_output('ip -4 address show dev dummy98 label 32')
- self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
+ self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
output = check_output('ip -4 address show dev dummy98 label 33')
- self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
+ self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
output = check_output('ip -4 address show dev dummy98 label 34')
- self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
+ self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
output = check_output('ip -4 address show dev dummy98 label 35')
- self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
+ self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
output = check_output('ip -6 address show dev dummy98')
print(output)
- self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
- self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
- self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
- self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
- self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
- self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
+ self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
+ self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
+ self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
+ self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
+ self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
+ self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
+ self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
restart_networkd()
self.wait_online(['dummy98:routable'])
# test for ENOBUFS issue #17012
output = check_output('ip -4 address show dev dummy98')
for i in range(1,254):
- self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
-
- def test_address_preferred_lifetime_zero_ipv6(self):
- copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
- start_networkd(5)
-
- self.wait_online(['dummy98:routable'])
-
- output = check_output('ip address show dummy98')
- print(output)
- self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
- self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
-
- output = check_output('ip route show dev dummy98')
- print(output)
- self.assertRegex(output, 'default via 20.20.20.1 proto static')
+ self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
def test_address_dad(self):
copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
- self.assertRegex(output, 'ff00::/8 metric 256 pref medium')
+ self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
print()
self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
- self.assertRegex(output, 'ff00::/8 metric 256 pref medium')
+ self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
def test_configure_without_carrier(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev')
print(output)
self.assertRegex(output, '2004:da8:1::/64')
+ def test_ipv6_proxy_ndp(self):
+ copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
+ start_networkd()
+
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('ip neighbor show proxy dev dummy98')
+ print(output)
+ for i in range(1,5):
+ self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
+
def test_neighbor_section(self):
copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
start_networkd()
self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
self.wait_operstate('test1', 'routable')
+ def _test_activation_policy(self, test):
+ self.setUp()
+ conffile = '25-activation-policy.network'
+ if test:
+ conffile = f'{conffile}.d/{test}.conf'
+ copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
+ start_networkd()
+
+ always = test.startswith('always')
+ if test == 'manual':
+ initial_up = 'UP' in check_output('ip link show test1')
+ else:
+ initial_up = not test.endswith('down') # note: default is up
+ expect_up = initial_up
+ next_up = not expect_up
+
+ # if initial expected state is down, must wait for setup_state to reach configuring
+ # so systemd-networkd considers it 'activated'
+ setup_state = None if initial_up else 'configuring'
+
+ for iteration in range(4):
+ with self.subTest(iteration=iteration, expect_up=expect_up):
+ operstate = 'routable' if expect_up else 'off'
+ self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
+ setup_state = None
+
+ if expect_up:
+ self.assertIn('UP', check_output('ip link show test1'))
+ self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
+ self.assertIn('default via 192.168.10.1', check_output('ip route show'))
+ else:
+ self.assertIn('DOWN', check_output('ip link show test1'))
+
+ if next_up:
+ check_output('ip link set dev test1 up')
+ else:
+ check_output('ip link set dev test1 down')
+ expect_up = initial_up if always else next_up
+ next_up = not next_up
+
+ self.tearDown()
+
+ def test_activation_policy(self):
+ for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
+ with self.subTest(test=test):
+ self._test_activation_policy(test)
+
def test_domain(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
start_networkd()
self.assertRegex(data, r'OPER_STATE=routable')
self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
+ self.assertRegex(data, r'ACTIVATION_POLICY=up')
self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com')
self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
print('### ip -6 route list table all dev bridge99')
output = check_output('ip -6 route list table all dev bridge99')
print(output)
- self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
+ self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
self.assertEqual(call('ip link del test1'), 0)
print('### ip -6 route list table all dev bridge99')
output = check_output('ip -6 route list table all dev bridge99')
print(output)
- self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
+ self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
def test_bridge_configure_without_carrier(self):
copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
start_networkd()
self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
- output = check_output(*networkctl_cmd, 'lldp', env=env)
- print(output)
- self.assertRegex(output, 'veth-peer')
- self.assertRegex(output, 'veth99')
+ for trial in range(10):
+ if trial > 0:
+ time.sleep(1)
+
+ output = check_output(*networkctl_cmd, 'lldp', env=env)
+ print(output)
+ if re.search(r'veth99 .* veth-peer', output):
+ break
+ else:
+ self.fail()
class NetworkdRATests(unittest.TestCase, Utilities):
links = ['veth99']
ConditionSecurity=selinux
[Service]
-ExecStart=sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile load'
+ExecStart=sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile clean load'
Type=oneshot
TimeoutSec=0
RemainAfterExit=yes
clear_services test15-a test15-b test15-c
}
+test_linked_units () {
+ echo "Testing linked units..."
+ echo "*** test linked unit (same basename)"
+
+ create_service test15-a
+ mv /etc/systemd/system/test15-a.service /
+ ln -s /test15-a.service /etc/systemd/system/
+ ln -s test15-a.service /etc/systemd/system/test15-b.service
+
+ check_ok test15-a Names test15-a.service
+ check_ok test15-a Names test15-b.service
+
+ echo "*** test linked unit (cross basename)"
+
+ mv /test15-a.service /test15-a@.scope
+ ln -fs /test15-a@.scope /etc/systemd/system/test15-a.service
+ systemctl daemon-reload
+
+ check_ok test15-a Names test15-a.service
+ check_ok test15-a Names test15-b.service
+ check_ko test15-a Names test15-b@
+
+ rm /test15-a@.scope
+ clear_services test15-a test15-b
+}
+
test_hierarchical_dropins () {
echo "Testing hierarchical dropins..."
echo "*** test service.d/ top level drop-in"
}
test_basic_dropins
+test_linked_units
test_hierarchical_dropins
test_template_dropins
test_alias_dropins
trap cleanup EXIT
-cp /usr/share/minimal.* "${image_dir}/"
-image="${image_dir}/minimal"
+cp /usr/share/minimal* "${image_dir}/"
+image="${image_dir}/minimal_0"
roothash="$(cat ${image}.roothash)"
os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)
grep -F "squashfs" ${image_dir}/result/c | grep -q -F "noatime"
grep -F "squashfs" ${image_dir}/result/c | grep -q -F -v "nosuid"
+# Adding a new mounts at runtime works if the unit is in the active state,
+# so use Type=notify to make sure there's no race condition in the test
+cat > /run/systemd/system/testservice-50d.service <<EOF
+[Service]
+RuntimeMaxSec=300
+Type=notify
+RemainAfterExit=yes
+MountAPIVFS=yes
+PrivateTmp=yes
+ExecStart=/bin/sh -c 'systemd-notify --ready; while ! grep -q -F MARKER /tmp/img/usr/lib/os-release; do sleep 0.1; done; mount | grep -F "/tmp/img" | grep -q -F "nosuid"'
+EOF
+systemctl start testservice-50d.service
+
+systemctl mount-image --mkdir testservice-50d.service ${image}.raw /tmp/img root:nosuid
+
+while systemctl show -P SubState testservice-50d.service | grep -q running
+do
+ sleep 0.1
+done
+
+systemctl is-active testservice-50d.service
+
echo OK >/testok
exit 0
--- /dev/null
+[Unit]
+Description=Create some memory pressure
+
+[Service]
+MemoryHigh=2M
+Slice=testsuite-56-workload.slice
+ExecStart=/usr/lib/systemd/tests/testdata/units/testsuite-56-slowgrowth.sh
IOAccounting=true
TasksAccounting=true
ManagedOOMMemoryPressure=kill
-ManagedOOMMemoryPressureLimitPercent=1%
+ManagedOOMMemoryPressureLimit=1%
systemd-analyze log-target console
# Loose checks to ensure the environment has the necessary features for systemd-oomd
-[[ "$( awk '/SwapTotal/ { print $2 }' /proc/meminfo )" != "0" ]] || echo "no swap" >> /skipped
[[ -e /proc/pressure ]] || echo "no PSI" >> /skipped
cgroup_type=$(stat -fc %T /sys/fs/cgroup/)
if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]; then
fi
[[ -e /skipped ]] && exit 0 || true
-systemctl start testsuite-56-testbloat.service
+rm -rf /etc/systemd/system/testsuite-56-testbloat.service.d
+
+echo "DefaultMemoryPressureDurationSec=5s" >> /etc/systemd/oomd.conf
+
systemctl start testsuite-56-testchill.service
+systemctl start testsuite-56-testbloat.service
# Verify systemd-oomd is monitoring the expected units
oomctl | grep "/testsuite-56-workload.slice"
-oomctl | grep "1%"
+oomctl | grep "1.00%"
+oomctl | grep "Default Memory Pressure Duration: 5s"
-# systemd-oomd watches for elevated pressure for 30 seconds before acting.
-# It can take time to build up pressure so either wait 5 minutes or for the service to fail.
-timeout=$(date -ud "5 minutes" +%s)
+# systemd-oomd watches for elevated pressure for 5 seconds before acting.
+# It can take time to build up pressure so either wait 2 minutes or for the service to fail.
+timeout=$(date -ud "2 minutes" +%s)
while [[ $(date -u +%s) -le $timeout ]]; do
if ! systemctl status testsuite-56-testbloat.service; then
break
fi
- sleep 15
+ sleep 5
done
# testbloat should be killed and testchill should be fine
if systemctl status testsuite-56-testbloat.service; then exit 42; fi
if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
+# only run this portion of the test if we can set xattrs
+if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
+ sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
+
+ mkdir -p /etc/systemd/system/testsuite-56-testbloat.service.d/
+ echo "[Service]" > /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
+ echo "ManagedOOMPreference=avoid" >> /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
+
+ systemctl daemon-reload
+ systemctl start testsuite-56-testchill.service
+ systemctl start testsuite-56-testmunch.service
+ systemctl start testsuite-56-testbloat.service
+
+ timeout=$(date -ud "2 minutes" +%s)
+ while [[ $(date -u +%s) -le $timeout ]]; do
+ if ! systemctl status testsuite-56-testmunch.service; then
+ break
+ fi
+ sleep 5
+ done
+
+ # testmunch should be killed since testbloat had the avoid xattr on it
+ if ! systemctl status testsuite-56-testbloat.service; then exit 25; fi
+ if systemctl status testsuite-56-testmunch.service; then exit 43; fi
+ if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
+fi
+
systemd-analyze log-level info
echo OK > /testok
--- /dev/null
+[Unit]
+Description=TEST-58-PORTABLE
+
+[Service]
+ExecStartPre=rm -f /failed /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
--- /dev/null
+#!/usr/bin/env bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -ex
+set -o pipefail
+
+export SYSTEMD_LOG_LEVEL=debug
+
+portablectl attach --now --runtime /usr/share/minimal_0.raw app0
+
+systemctl is-active app0.service
+systemctl is-active app0-foo.service
+set +o pipefail
+set +e
+systemctl is-active app0-bar.service && exit 1
+set -e
+set -o pipefail
+
+portablectl reattach --now --runtime /usr/share/minimal_1.raw app0
+
+systemctl is-active app0.service
+systemctl is-active app0-bar.service
+set +o pipefail
+set +e
+systemctl is-active app0-foo.service && exit 1
+set -e
+set -o pipefail
+
+portablectl list | grep -q -F "minimal_1"
+
+portablectl detach --now --runtime /usr/share/minimal_1.raw app0
+
+portablectl list | grep -q -F "No images."
+
+# portablectl also works with directory paths rather than images
+
+unsquashfs -dest /tmp/minimal_0 /usr/share/minimal_0.raw
+unsquashfs -dest /tmp/minimal_1 /usr/share/minimal_1.raw
+
+portablectl attach --copy=symlink --now --runtime /tmp/minimal_0 app0
+
+systemctl is-active app0.service
+systemctl is-active app0-foo.service
+set +o pipefail
+set +e
+systemctl is-active app0-bar.service && exit 1
+set -e
+set -o pipefail
+
+portablectl reattach --now --enable --runtime /tmp/minimal_1 app0
+
+systemctl is-active app0.service
+systemctl is-active app0-bar.service
+set +o pipefail
+set +e
+systemctl is-active app0-foo.service && exit 1
+set -e
+set -o pipefail
+
+portablectl list | grep -q -F "minimal_1"
+
+portablectl detach --now --enable --runtime /tmp/minimal_1 app0
+
+portablectl list | grep -q -F "No images."
+
+echo OK > /testok
+
+exit 0
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
cd "$MESON_SOURCE_ROOT"
+++ /dev/null
-#!/bin/sh
-set -eu
-
-cd "$1"
-
-(curl --fail -L 'https://chromium.googlesource.com/chromiumos/platform2/+/master/power_manager/udev/gen_autosuspend_rules.py?format=TEXT'; echo) \
- | base64 -d > gen_autosuspend_rules.py
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
sd_good=0
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
"$@" '-' -o/dev/null </dev/null
#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
which perl &>/dev/null || exit 77
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
export SYSTEMD_LOG_LEVEL=info
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
# Fedora uses C.utf8 but Debian uses C.UTF-8
#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
# The official unmodified version of the script can be found at
# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
# Try to guess the build directory:
#!/bin/bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
# Download and extract coverity tool
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
git shortlog -s `git describe --abbrev=0 --match 'v[0-9][0-9][0-9]'`.. | \
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
CONFIG=$1
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
src="$1"
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
if [ "${MESON_INSTALL_QUIET:-0}" = 1 ] ; then
#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
set -o pipefail
fi
fi
-meson $build -D$fuzzflag -Db_lundef=false
+if ! meson $build -D$fuzzflag -Db_lundef=false; then
+ cat $build/meson-logs/meson-log.txt
+ exit 1
+fi
+
ninja -v -C $build fuzzers
# The seed corpus is a separate flat archive for each fuzzer,
+++ /dev/null
-#!/bin/sh
-set -eu
-
-cd "$1" && shift
-
-curl --fail -L -o syscall-names.text 'https://raw.githubusercontent.com/hrw/syscalls-table/master/syscall-names.text'
-
-for arch in "$@"; do
- curl --fail -L -o syscalls-$arch "https://raw.githubusercontent.com/hrw/syscalls-table/master/tables/syscalls-$arch"
-done
except ImportError as e:
shlex_join = e
+try:
+ from shlex import quote as shlex_quote
+except ImportError as e:
+ shlex_quote = e
+
class NoCommand(Exception):
pass
'org.freedesktop.DBus.Introspectable',
'org.freedesktop.DBus.Properties',
]
+RED = '\x1b[31m'
+GREEN = '\x1b[32m'
+YELLOW = '\x1b[33m'
+RESET = '\x1b[39m'
def xml_parser():
return etree.XMLParser(no_network=True,
interface = programlisting.get('interface')
argv = [f'{opts.build_dir}/{executable}', f'--bus-introspect={interface}']
- print(f'COMMAND: {shlex_join(argv)}')
+ if isinstance(shlex_join, Exception):
+ print(f'COMMAND: {" ".join(shlex_quote(arg) for arg in argv)}')
+ else:
+ print(f'COMMAND: {shlex_join(argv)}')
try:
- out = subprocess.check_output(argv, text=True)
+ out = subprocess.check_output(argv, universal_newlines=True)
except FileNotFoundError:
print(f'{executable} not found, ignoring', file=sys.stderr)
return
with open(page, 'w') as out:
out.write(out_text)
- return dict(stats=stats, outdated=(out_text != src))
+ return dict(stats=stats, modified=(out_text != src))
def parse_args():
p = argparse.ArgumentParser()
if __name__ == '__main__':
opts = parse_args()
- for item in (etree, shlex_join):
+ for item in (etree, shlex_quote):
if isinstance(item, Exception):
print(item, file=sys.stderr)
exit(77 if opts.test else 1)
# Let's print all statistics at the end
mlen = max(len(page) for page in stats)
- total = sum((item['stats'] for item in stats.values()), start=collections.Counter())
- total = 'total', dict(stats=total, outdated=False)
- outdated = []
+ total = sum((item['stats'] for item in stats.values()), collections.Counter())
+ total = 'total', dict(stats=total, modified=False)
+ modified = []
+ classification = 'OUTDATED' if opts.test else 'MODIFIED'
for page, info in sorted(stats.items()) + [total]:
m = info['stats']['missing']
t = info['stats']['total']
p = page + ':'
- c = 'OUTDATED' if info['outdated'] else ''
+ c = classification if info['modified'] else ''
if c:
- outdated.append(page)
- print(f'{p:{mlen + 1}} {t - m}/{t} {c}')
+ modified.append(page)
+ color = RED if m > t/2 else (YELLOW if m else GREEN)
+ print(f'{color}{p:{mlen + 1}} {t - m}/{t} {c}{RESET}')
- if opts.test and outdated:
- exit(f'Outdated pages: {", ".join(outdated)}\n'
- f'Hint: ninja -C {opts.build_dir} man/update-dbus-docs')
+ if opts.test and modified:
+ exit(f'Outdated pages: {", ".join(modified)}\n'
+ f'Hint: ninja -C {opts.build_dir} update-dbus-docs')
--- /dev/null
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eu
+
+cd "$1"
+
+(curl --fail -L 'https://chromium.googlesource.com/chromiumos/platform2/+/master/power_manager/udev/gen_autosuspend_rules.py?format=TEXT'; echo) \
+ | base64 -d > tools/chromiumos/gen_autosuspend_rules.py
+
+(cat <<%EOF
+# This file is part of systemd.
+#
+# Rules to autosuspend known fingerprint readers (pulled from libfprint).
+#
+%EOF
+curl --fail -L 'https://gitlab.freedesktop.org/libfprint/libfprint/-/raw/master/data/autosuspend.hwdb') \
+ > hwdb.d/60-autosuspend-fingerprint-reader.hwdb
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
cd "$1"
# Do not edit. Generated by update-man-rules.py.
# Update with:
-# ninja -C build man/update-man-rules
+# ninja -C build update-man-rules
manpages = ['''
MESON_FOOTER = '''\
--- /dev/null
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eu
+
+cd "$1" && shift
+
+curl --fail -L -o syscall-list.txt 'https://raw.githubusercontent.com/hrw/syscalls-table/master/syscall-names.text'
+
+for arch in "$@"; do
+ curl --fail -L -o syscalls-$arch.txt "https://raw.githubusercontent.com/hrw/syscalls-table/master/tables/syscalls-$arch"
+done
#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
set -eu
i=1
['systemd-poweroff.service', ''],
['systemd-reboot.service', ''],
['systemd-rfkill.socket', 'ENABLE_RFKILL'],
+ ['systemd-sysext.service', 'ENABLE_SYSEXT'],
['systemd-sysusers.service', 'ENABLE_SYSUSERS',
'sysinit.target.wants/'],
['systemd-tmpfiles-clean.service', 'ENABLE_TMPFILES'],
['systemd-oomd.service', 'ENABLE_OOMD'],
['systemd-portabled.service', 'ENABLE_PORTABLED',
'dbus-org.freedesktop.portable1.service'],
- ['systemd-sysext.service', 'ENABLE_SYSEXT'],
['systemd-userdbd.service', 'ENABLE_USERDB'],
['systemd-homed.service', 'ENABLE_HOMED'],
['systemd-quotacheck.service', 'ENABLE_QUOTACHECK'],
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=@rootlibexecdir@/systemd-sysext --merge
-ExecStop=@rootlibexecdir@/systemd-sysext --unmerge
+ExecStart=systemd-sysext merge
+ExecStop=systemd-sysext unmerge
[Install]
WantedBy=sysinit.target
AmbientCapabilities=CAP_SYS_TIME
BusName=org.freedesktop.timesync1
CapabilityBoundingSet=CAP_SYS_TIME
+# Turn off DNSSEC validation for hostname look-ups, since those need the
+# correct time to work, but we likely won't acquire that without NTP. Let's
+# break this chicken-and-egg cycle here.
+Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0
ExecStart=!!@rootlibexecdir@/systemd-timesyncd
LockPersonality=yes
MemoryDenyWriteExecute=yes