---
**systemd version the issue has been seen with**
-> ...
+ > …
<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released (non-rc) systemd versions upstream! -->
<!-- See https://github.com/systemd/systemd/releases for the list of most recent releases. -->
**Used distribution**
> …
+**Linux kernel version used** (`uname -a`)
+ > …
+
+**CPU architecture issue was seen on**
+ > …
+
**Expected behaviour you didn't see**
> …
> …
**Steps to reproduce the problem**
+ > …
jobs:
build:
- runs-on: ubuntu-18.04
+ runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
env:
- { COMPILER: "gcc", COMPILER_VERSION: "10" }
- { COMPILER: "clang", COMPILER_VERSION: "10" }
+ - { COMPILER: "clang", COMPILER_VERSION: "11" }
env: ${{ matrix.env }}
steps:
- name: Repository checkout
expect
fdisk
gettext
- iptables-dev
iputils-ping
isc-dhcp-client
itstool
libcap-dev
libcurl4-gnutls-dev
libfdisk-dev
+ libfido2-dev
libgpg-error-dev
liblz4-dev
liblzma-dev
libqrencode-dev
libssl-dev
libxkbcommon-dev
+ libxtables-dev
libzstd-dev
mount
net-tools
CHANGES WITH 247 in spe:
- * KERNEL API INCOMPATIBILTY: Linux 4.12 introduced two new uevents
+ * KERNEL API INCOMPATIBILITY: Linux 4.12 introduced two new uevents
"bind" and "unbind" to the Linux device model. When this kernel
change was made, systemd-udevd was only minimally updated to handle
and propagate these new event types. The introduction of these new
uevents (which are typically generated for USB devices and devices
needing a firmware upload before being functional) resulted in a
- number of software issues, we so far didn't address (mostly because
- there was hope the kernel maintainers would themeselves address these
- issues in some form – which did not happen). To handle them properly,
- many (if not most) udev rules files shipped in various packages need
- updating, and so do many programs that monitor or enumerate devices
- with libudev or sd-device, or otherwise process uevents. Please note
- that this incompatibility is not fault of systemd or udev, but caused
- by an incompatible kernel change that happened back in Linux 4.12.
+ number of issues which we so far didn't address. We hoped the kernel
+ maintainers would themselves address these issues in some form, but
+ that did not happen. To handle them properly, many (if not most) udev
+ rules files shipped in various packages need updating, and so do many
+ programs that monitor or enumerate devices with libudev or sd-device,
+ or otherwise process uevents. Please note that this incompatibility
+ is not fault of systemd or udev, but caused by an incompatible kernel
+ change that happened back in Linux 4.12, but is becoming more and
+ more visible as the new uevents are generated by more kernel drivers.
To minimize issues resulting from this kernel change (but not avoid
them entirely) starting with systemd-udevd 247 the udev "tags"
device. To accommodate for this a new automatic property CURRENT_TAGS
has been added that works similar to the existing TAGS property but
only lists tags set by the most recent uevent/database
- update. Similar, the libudev/sd-device API has been updated with new
- functions to enumerate these 'current' tags, in addition to the
+ update. Similarly, the libudev/sd-device API has been updated with
+ new functions to enumerate these 'current' tags, in addition to the
existing APIs that now enumerate the 'sticky' ones.
To properly handle "bind"/"unbind" on Linux 4.12 and newer it is
ACTION=="remove",GOTO="xyz_end" instead, so that the
properties/tags they add are also applied whenever "bind" (or
"unbind") is seen. (This is most important for all physical device
- types — as that's for which "bind" and "unbind" are currently
- usually generated, for all other device types this change is still
+ types — those for which "bind" and "unbind" are currently
+ generated, for all other device types this change is still
recommended but not as important — but certainly prepares for
future kernel uevent type additions).
- • Similar, all code monitoring devices that contains an 'if' branch
+ • Similarly, all code monitoring devices that contains an 'if' branch
discerning the "add" + "change" uevent actions from all other
uevents actions (i.e. considering devices only relevant after "add"
or "change", and irrelevant on all other events) should be reworked
• Any code that uses device tags for deciding whether a device is
relevant or not most likely needs to be updated to use the new
udev_device_has_current_tag() API (or sd_device_has_current_tag()
- in case sd-device is used), to check whether the tag is set
- at the moment an uevent is seen (as opposed to the existing
+ in case sd-device is used), to check whether the tag is set at the
+ moment an uevent is seen (as opposed to the existing
udev_device_has_tag() API which checks if the tag ever existed on
the device, following the API concept redefinition explained
above).
this is not caused by systemd/udev changes, but result of a kernel
behaviour change.
+ * The MountAPIVFS= service file setting now defaults to on if
+ RootImage= and RootDirectory= are used, which means that with those
+ two settings /proc/, /sys/ and /dev/ are automatically properly set
+ up for services. Previous behaviour may be restored by explicitly
+ setting MountAPIVFS=off.
+
* Since PAM 1.2.0 (2015) configuration snippets may be placed in
/usr/lib/pam.d/ in addition to /etc/pam.d/. If a file exists in the
latter it takes precedence over the former, similar to how most of
packages' vendor versions of their PAM stack definitions from
/etc/pam.d/ to /usr/lib/pam.d/, but if such OS-wide migration is not
desired the location to which systemd installs its PAM stack
- configuration file may be changed via the "pamconfdir" meson variable
- at build time, optionally undoing this change of default paths
- introduced with systemd 247.
+ configuration may be changed via the -Dpamconfdir Meson option.
+
+ * The runtime dependencies on libqrencode, libpcre2, libidn/libidn2,
+ libpwquality and libcryptsetup have been changed to be based on
+ dlopen(): instead of regular dynamic library dependencies declared in
+ the binary ELF headers, these libraries are now loaded on demand
+ only, if they are available. If the libraries cannot be found the
+ relevant operations will fail gracefully, or a suitable fallback
+ logic is chosen. This is supposed to be useful for general purpose
+ distributions, as it allows minimizing the list of dependencies the
+ systemd packages pull in, permitting building of more minimal OS
+ images, while still making use of these "weak" dependencies should
+ they be installed. Since many package managers automatically
+ synthesize package dependencies from ELF shared library dependencies,
+ some additional manual packaging work has to be done now to replace
+ those (slightly downgraded from "required" to "recommended" or
+ whatever is conceptually suitable for the package manager). Note that
+ this change does not alter build-time behaviour: as before the
+ build-time dependencies have to be installed during build, even if
+ they now are optional during runtime.
+
+ * sd-event.h gained a new call sd_event_add_time_relative() for
+ installing timers relative to the current time. This is mostly a
+ convenience wrapper around the pre-existing sd_event_add_time() call
+ which installs absolute timers.
+
+ * sd-event event sources may now be placed in a new "exit-on-failure"
+ mode, which may be controlled via the new
+ sd_event_source_get_exit_on_failure() and
+ sd_event_source_set_exit_on_failure() functions. If enabled, any
+ failure returned by the event source handler functions will result in
+ exiting the event loop (unlike the default behaviour of just
+ disabling the event source but continuing with the event loop). This
+ feature is useful to set for all event sources that define "primary"
+ program behaviour (where failure should be fatal) in contrast to
+ "auxiliary" behaviour (where failure should remain local).
+
+ * Most event source types sd-event supports now accept a NULL handler
+ function, in which case the event loop is exited once the event
+ source is to be dispatched, using the userdata pointer — converted to
+ a signed integer — as exit code of the event loop. Previously this
+ was supported for IO and signal event sources already. Exit event
+ sources still do not support this (simply because it makes little
+ sense there, as the event loop is already exiting when they are
+ dispatched).
+
+ * A new per-unit setting RootImageOptions= has been added which allows
+ tweaking the mount options for any file system mounted as effect of
+ the RootImage= setting.
+
+ * Another new per-unit setting MountImages= has been added, that allows
+ mounting additional disk images into the file system tree accessible
+ to the service.
+
+ * systemd-repart now generates JSON output when requested with the new
+ --json= switch.
+
+ * systemd-machined's OpenMachineShell() bus call will now pass
+ additional policy metadata data fields to the PolicyKit
+ authentication request.
+
+ * systemd-tmpfiles gained a new -E switch, which is equivalent to
+ --exclude-prefix=/dev --exclude-prefix=/proc --exclude=/run
+ --exclude=/sys. It's particularly useful in combination with --root=,
+ when operating on OS trees that do not have any of these four runtime
+ directories mounted, as this means no files below these subtrees are
+ created or modified, since those mount points should probably remain
+ empty.
+
+ * systemd-tmpfiles gained a new --image= switch which is like --root=,
+ but takes a disk image instead of a directory as argument. The
+ specified disk image is mounted inside a temporary mount namespace
+ and the tmpfiles.d/ drop-ins stored in the image are executed and
+ applied to the image. systemd-sysusers similarly gained a new
+ --image= switch, that allows the sysusers.d/ drop-ins stored in the
+ image to be applied onto the image.
+
+ * Similarly, the journalctl command also gained an --image= switch,
+ which is a quick one-step solution to look at the log data included
+ in OS disk images.
+
+ * journalctl's --output=cat option (which outputs the log content
+ without any metadata, just the pure text messages) will now make use
+ of terminal colors when run on a suitable terminal, similarly to the
+ other output modes.
+
+ * JSON group records now support a "description" string that may be
+ used to add a human-readable textual description to such groups. This
+ is supposed to match the user's GECOS field which traditionally
+ didn't have a counterpart for group records.
+
+ * The "systemd-dissect" tool that may be used to inspect OS disk images
+ and that was previously installed to /usr/lib/systemd/ has now been
+ moved to /usr/bin/, reflecting its updated status of an officially
+ supported tool with a stable interface. It gained support for a new
+ --mkdir switch which when combined with --mount has the effect of
+ creating the directory to mount the image to if it is missing
+ first. It also gained two new commands --copy-from and --copy-to for
+ copying files and directories in and out of an OS image without the
+ need to manually mount it. It also acquired support for a new option
+ --json= to generate JSON output when inspecting an OS image.
+
+ * The cgroup2 file system is now mounted with the
+ "memory_recursiveprot" mount option, supported since kernel 5.7. This
+ means that the MemoryLow= and MemoryMin= unit file settings now apply
+ recursively to whole subtrees.
+
+ * systemd-homed now defaults to using the btrfs file system — if
+ available — when creating home directories in LUKS volumes. This may
+ be changed with the DefaultFileSystemType= setting in homed.conf.
+ It's now the default file system in various major distributions and
+ has the major benefit for homed that it can be grown and shrunk while
+ mounted, unlike the other contenders ext4 and xfs, which can both be
+ grown online, but not shrunk (in fact xfs is the technically most
+ limited option here, as it cannot be shrunk at all).
+
+ * JSON user records managed by systemd-homed gained support for
+ "recovery keys". These are basically secondary passphrases that can
+ unlock user accounts/home directories. They are computer-generated
+ rather than user-chosen, and typically have greater entropy.
+ homectl's --recovery-key= option may be used to add a recovery key to
+ a user account. The generated recovery key is displayed as a QR code,
+ so that it can be scanned to be kept in a safe place. This feature is
+ particularly useful in combination with systemd-homed's support for
+ FIDO2 or PKCS#11 authentication, as a secure fallback in case the
+ security tokens are lost. Recovery keys may be entered wherever the
+ system asks for a password.
+
+ * systemd-homed now maintains a "dirty" flag for each LUKS encrypted
+ home directory which indicates that a home directory has not been
+ deactivated cleanly when offline. This flag is useful to identify
+ home directories for which the offline discard logic did not run when
+ offlining, and where it would be a good idea to log in again to catch
+ up.
+
+ * systemctl gained a new parameter --timestamp= which may be used to
+ change the style in which timestamps are output, i.e. whether to show
+ them in local timezone or UTC, or whether to show µs granularity.
+
+ * Alibaba's "pouch" container manager is now detected by
+ systemd-detect-virt, ConditionVirtualization= and similar
+ constructs. Similar, they now also recognize IBM PowerVM machine
+ virtualization.
+
+ * systemd-nspawn has been reworked to use the /run/host/incoming/ as
+ place to use for propagating external mounts into the
+ container. Similarly /run/host/notify is now used as the socket path
+ for container payloads to communicate with the container manager
+ using sd_notify(). The container manager now uses the
+ /run/host/inaccessible/ directory to place "inaccessible" file nodes
+ of all relevant types which may be used by the container payload as
+ bind mount source to over-mount inodes to make them inaccessible.
+ /run/host/container-manager will now be initialized with the same
+ string as the $container environment variable passed to the
+ container's PID 1. /run/host/container-uuid will be initialized with
+ the same string as $container_uuid. This means the /run/host/
+ hierarchy is now the primary way to make host resources available to
+ the container. The Container Interface documents these new files and
+ directories:
+
+ https://systemd.io/CONTAINER_INTERFACE
+
+ * Support for the "ConditionNull=" unit file condition has been
+ deprecated and undocumented for 6 years. systemd started to warn
+ about its use 1.5 years ago. It has now been removed entirely.
+
+ * sd-bus.h gained a new API call sd_bus_error_has_names(), which takes
+ a sd_bus_error struct and a list of error names, and checks if the
+ error matches one of these names. It's a convenience wrapper that is
+ useful in cases where multiple errors shall be handled the same way.
+
+ * A new system call filter list "@known" has been added, that contains
+ all system calls known at the time systemd was built.
+
+ * Behaviour of system call filter allow lists has changed slightly:
+ system calls that are contained in @known will result in a EPERM by
+ default, while those not contained in it result in ENOSYS. This
+ should improve compatibility because known system calls will thus be
+ communicated as prohibited, while unknown (and thus newer ones) will
+ be communicated as not implemented, which hopefully has the greatest
+ chance of triggering the right fallback code paths in client
+ applications.
+
+ * "systemd-analyze syscall-filter" will now show two separate sections
+ at the bottom of the output: system calls known during systemd build
+ time but not included in any of the filter groups shown above, and
+ system calls defined on the local kernel but known during systemd
+ build time.
+
+ * If the $SYSTEMD_LOG_SECCOMP=1 environment variable is set for
+ systemd-nspawn all system call filter violations will be logged by
+ the kernel (audit). This is useful for tracking down system calls
+ invoked by container payloads that are prohibited by the container's
+ system call filter policy.
+
+ * Two new unit file settings ProtectProc= and ProcSubset= have been
+ added that expose the hidepid= and subset= mount options of procfs.
+ All processes of the unit will only see processes in /proc that are
+ are owned by the unit's user. This is an important new sandboxing
+ option that is recommended to be set on all system services. All
+ long-running system services that are included in systemd itself set
+ this option now. This option is only supported on kernel 5.8 and
+ above, since the hidepid= option supported on older kernels was not a
+ per-mount option but actually applied to the whole PID namespace.
+
+ * Socket units gained a new boolean setting FlushPending=. If enabled
+ all pending socket data/connections are flushed whenever the socket
+ unit enters the "listening" state, i.e. after the associated service
+ exited.
+
+ * The unit file setting NUMAMask= gained a new "all" value: when used,
+ all existing NUMA nodes are added to the NUMA mask.
+
+ * A new "credentials" logic has been added to system services. This is
+ a simple mechanism to pass privileged data to services in a safe and
+ secure way. It's supposed to be used to pass per-service secret data
+ such as passwords or cryptographic keys but also associated less
+ private information such as user names, certificates, and similar to
+ system services. Each credential is identified by a short user-chosen
+ name and may contain arbitrary binary data. Two new unit file
+ settings have been added: SetCredential= and LoadCredential=. The
+ former allows setting a credential to a literal string, the latter
+ sets a credential to the contents of a file (or data read from a
+ user-chosen AF_UNIX stream socket). Credentials are passed to the
+ service via a special credentials directory, one file for each
+ credential. The path to the credentials directory is passed in a new
+ $CREDENTIALS_DIRECTORY environment variable. Since the credentials
+ are passed in the file system they may be easily referenced in
+ ExecStart= command lines too, thus no explicit support for the
+ credentials logic in daemons is required (though ideally daemons
+ would look for the bits they need in $CREDENTIALS_DIRECTORY
+ themselves automatically, if set). The $CREDENTIALS_DIRECTORY is
+ backed by unswappable memory if privileges allow it, immutable if
+ privileges allow it, is accessible only to the service's UID, and is
+ automatically destroyed when the service stops.
+
+ * systemd-nspawn supports the same credentials logic. It can both
+ consume credentials passed to it via the aforementioned
+ $CREDENTIALS_DIRECTORY protocol as well as pass these credentials on
+ to its payload. The service manager/PID 1 has been updated to match
+ this: it can also accept credentials from the container manager that
+ invokes it (in fact: any process that invokes it), and passes them on
+ to its services. Thus, credentials can be propagated recursively down
+ the tree: from a system's service manager to a systemd-nspawn
+ service, to the service manager that runs as container payload and to
+ the service it runs below. Credentials may also be added on the
+ systemd-nspawn command line, using new --set-credential= and
+ --load-credential= command line switches that match the
+ aforementioned service settings.
+
+ * systemd-repart gained new settings Format=, Encrypt=, CopyFiles= in
+ the partition drop-ins which may be used to format/LUKS
+ encrypt/populate any created partitions. The partitions are
+ encrypted/formatted/populated before they are registered in the
+ partition table, so that they appear atomically: either the
+ partitions do not exist yet or they exist fully encrypted, formatted,
+ and populated — there is no time window where they are
+ "half-initialized". Thus the system is robust to abrupt shutdown: if
+ the tool is terminated half-way during its operations on next boot it
+ will start from the beginning.
+
+ * systemd-repart's --size= operation gained a new "auto" value. If
+ specified, and operating on a loopback file it is automatically sized
+ to the minimal size the size constraints permit. This is useful to
+ use "systemd-repart" as an image builder for minimally sized images.
+
+ * systemd-resolved now gained a third IPC interface for requesting name
+ resolution: besides D-Bus and local DNS to 127.0.0.53 a Varlink
+ interface is now supported. The nss-resolve NSS module has been
+ modified to use this new interface instead of D-Bus. Using Varlink
+ has a major benefit over D-Bus: it works without a broker service,
+ and thus already during earliest boot, before the dbus daemon has
+ been started. This means name resolution via systemd-resolved now
+ works at the same time systemd-networkd operates: from earliest boot
+ on, including in the initrd.
+
+ * systemd-resolved gained support for a new DNSStubListenerExtra=
+ configuration file setting which may be used to specify additional IP
+ addresses the built-in DNS stub shall listen on, in addition to the
+ main one on 127.0.0.53:53.
+
+ * Name lookups issued via systemd-resolved's D-Bus and Varlink
+ interfaces (and thus also via glibc NSS if nss-resolve is used) will
+ now honour a trailing dot in the hostname: if specified the search
+ path logic is turned off. Thus "resolvectl query foo." is now
+ equivalent to "resolvectl query --search=off foo.".
+
+ * systemd-resolved gained a new D-Bus property "ResolvConfMode" that
+ exposes how /etc/resolv.conf is currently managed: by resolved (and
+ in which mode if so) or another subsystem. "resolvctl" will display
+ this property in its status output.
+
+ * The resolv.conf snippets systemd-resolved provides will now set "."
+ as the search domain if no other search domain is known. This turns
+ off the derivation of an implicit search domain by nss-dns for the
+ hostname, when the hostname is set to an FQDN. This change is done to
+ make nss-dns using resolv.conf provided by systemd-resolved behave
+ more similarly to nss-resolve.
+
+ * systemd-tmpfiles' file "aging" logic (i.e. the automatic clean-up of
+ /tmp/ and /var/tmp/ based on file timestamps) now looks at the
+ "birth" time (btime) of a file in addition to the atime, mtime, and
+ ctime.
+
+ * systemd-analyze gained a new verb "capability" that lists all known
+ capabilities by the systemd build and by the kernel.
+
+ * If a file /usr/lib/clock-epoch exists, PID 1 will read its mtime and
+ advance the system clock to it at boot if it is noticed to be before
+ that time. Previously, PID 1 would only advance the time to an epoch
+ time that is set during build-time. With this new file OS builders
+ can change this epoch timestamp on individual OS images without
+ having to rebuild systemd.
+
+ * systemd-logind will now listen to the KEY_RESTART key from the Linux
+ input layer and reboot the system if it is pressed, similarly to how
+ it already handles KEY_POWER, KEY_SUSPEND or KEY_SLEEP. KEY_RESTART
+ was originally defined in the Multimedia context (to restart playback
+ of a song or film), but is now primarily used in various embedded
+ devices for "Reboot" buttons. Accordingly, systemd-logind will now
+ honour it as such. This may configured in more detail via the new
+ HandleRebootKey= and RebootKeyIgnoreInhibited=.
+
+ * systemd-nspawn/systemd-machined will now reconstruct hardlinks when
+ copying OS trees, for example in "systemd-nspawn --ephemeral",
+ "systemd-nspawn --template=", "machinectl clone" and similar. This is
+ useful when operating with OSTree images, which use hardlinks heavily
+ throughout, and where such copies previously resulting in "exploding"
+ hardlinks.
+
+ * systemd-nspawn's --console= setting gained support for a new
+ "autopipe" value, which is identical to "interactive" when invoked on
+ a TTY, and "pipe" otherwise.
+
+ * systemd-networkd's .network files gained support for explicitly
+ configuring the multicast membership entries of bridge devices in the
+ [BridgeMDB] section. It also gained support for the PIE queuing
+ discipline in the [FlowQueuePIE] sections.
+
+ * systemd-networkd's .netdev files may now be used to create "BareUDP"
+ tunnels, configured in the new [BareUDP] setting. VXLAN tunnels may
+ now be marked to be independent of any underlying network interface
+ via the new Independent= boolean setting.
+
+ * systemd-networkd's Gateway= setting in .network files now accepts the
+ special values _dhcp4 and _ipv6ra to configure additional, locally
+ defined, explicit routes to the gateway acquired via DHCP or IPv6
+ Router Advertisements.
+
+ * systemctl gained support for two new verbs: "service-log-level" and
+ "service-log-target" may be used on services that implement the
+ generic org.freedesktop.LogControl1 D-Bus interface to dynamically
+ adjust the log level and target. All of systemd's long-running
+ services support this now, but ideally all system services would
+ implement this interface to make the system more uniformly
+ debuggable.
+
+ * The SystemCallErrorNumber= unit file setting now accepts the new
+ "kill" and "log" actions, in addition to arbitrary error number
+ specifications as before. If "kill" the the processes are killed on
+ the event, if "log" the offending system call is audit logged.
+
+ * A new SystemCallLog= unit file setting has been added that accepts a
+ list of system calls that shall be logged about (audit).
+
+ * The OS image dissection logic (as used by RootImage= in unit files or
+ systemd-nspawn's --image= switch) has gained support for identifying
+ and mounting explicit /usr/ partitions, which are now defined in the
+ discoverable partition specification. This should be useful for
+ environments where the root file system is
+ generated/formatted/populated dynamically on first boot and combined
+ with an immutable /usr/ tree that is supplied by the vendor.
+
+ * In the final phase of shutdown, within the systemd-shutdown binary
+ we'll now try to detach MD devices (i.e software RAID) in addition to
+ loopback block devices and DM devices as before. This is supposed to
+ be a safety net only, in order to increase robustness if things go
+ wrong. Storage subsystems are expected to properly detach their
+ storage volumes during regular shutdown already (or in case of
+ storage backing the root file system: in the initrd hook we return to
+ later).
+
+ * If the SYSTEMD_LOG_TID environment variable is set all systemd tools
+ will now log the thread ID in their log output. This is useful when
+ working with heavily threaded programs.
+
+ * If the SYSTEMD_RDRAND environment variable is set to "0", systemd will
+ not use the RDRAND CPU instruction. This is useful in environments
+ such as replay debuggers where non-deterministic behaviour is not
+ desirable.
+
+ * The autopaging logic in systemd's various tools (such as systemctl)
+ has been updated to turn on "secure" mode in "less"
+ (i.e. $LESSECURE=1) if execution in a "sudo" environment is
+ detected. This disables invoking external programs from the pager,
+ via the pipe logic. This behaviour may be overridden via the new
+ $SYSTEMD_PAGERSECURE environment variable.
+
+ * Units which have resource limits (.service, .mount, .swap, .slice,
+ .socket, and .slice) gained new configuration settings
+ ManagedOOMSwap=, ManagedOOMMemoryPressure=, and
+ ManagedOOMMemoryPressureLimitPercent= that specify resource pressure
+ limits and optional action taken by systemd-oomd.
+
+ * A new service systemd-oomd has been added. It monitors resource
+ contention for selected parts of the unit hierarchy using the PSI
+ information reported by the kernel, and kills processes when memory
+ or swap pressure is above configured limits. This service is only
+ enabled in developer mode (see below) and should be considered a
+ preview in this release. Behaviour details and option names are
+ subject to change without the usual backwards-compatibility promises.
+
+ * A new helper oomctl has been added to introspect systemd-oomd state.
+ If also is only available in developer mode and should be considered
+ a preview without the usual backwards-compatibility promises.
+
+ * New meson option -Dcompat-mutable-uid-boundaries= has been added. If
+ enabled, systemd reads the system UID boundaries from /etc/login.defs
+ at runtime, instead of using the built-in values selected during
+ build. This is an option to improve compatibility for upgrades from
+ old systems. It's strongly recommended not to make use of this
+ functionality on new systems (or even enable it during build), as it
+ makes something runtime-configurable that is mostly an implementation
+ detail of the OS, and permits avoidable differences in deployments
+ that create all kinds of problems in the long run.
+
+ * New meson option '-Dmode=developer|release' has been added. When
+ 'developer', additional checks and features are enabled that are
+ relevant during upstream development, e.g. verification that
+ semi-automatically-generated documentation has been properly updated
+ following API changes. Those checks are considered hints for
+ developers and are not actionable in downstream builds. In addition,
+ extra features that are not ready for general consumption may be
+ enabled in developer mode. It is thus recommended to set
+ '-Dmode=release' in end-user and distro builds.
+
+ * systemd-cryptsetup gained support for processing detached LUKS
+ headers specified on the kernel command line via the header=
+ parameter of the luks.options= kernel command line option. The same
+ device/path syntax as for key files is supported for header files
+ like this.
+
+ * The "net_id" built-in of udev has been updated to ignore ACPI _SUN
+ slot index data for devices that are connected through a PCI bridge
+ where the _SUN index is associated with the bridge instead of the
+ network device itself. Previously this would create ambiguous device
+ naming if multiple network interfaces were connected to the same PCI
+ bridge. Since this is a naming scheme incompatibility on systems that
+ possess hardware like this it has been introduced as new naming
+ scheme "v247". The previous scheme can be selected via the
+ "net.naming-scheme=v245" kernel command line parameter.
+
+ * ConditionFirstBoot= semantics have been modified to be safe towards
+ abnormal system power-off during first boot. Specifically, the
+ "systemd-machine-id-commit.service" service now acts as boot
+ milestone indicating when the first boot process is sufficiently
+ complete in order to not consider the next following boot also a
+ first boot. If the system is reset before this unit is reached the
+ first time, the next boot will still be considered a first boot; once
+ it has been reached, no further boots will be considered a first
+ boot. The "first-boot-complete.target" unit now acts as official hook
+ point to order against this. If a service shall be run on every boot
+ until the first boot fully succeeds it may thus be ordered before
+ this target unit (and pull it in) and carry ConditionFirstBoot=
+ appropriately.
+
+ * bootctl's set-default and set-oneshot commands now accept the three
+ special strings "@default", "@oneshot", "@current" in place of a boot
+ entry id. These strings are resolved to the current default and
+ oneshot boot loader entry, as well as the currently booted one. Thus
+ a command "bootctl set-default @current" may be used to make the
+ currently boot menu item the new default for all subsequent boots.
+
+ * A new generic target unit "initrd-cryptsetup.target" has been added
+ that is supposed to pull in all encrypted volumes that shall be set
+ up during the initrd phase. It takes the place of "cryptsetup.target"
+ and "remote-cryptsetup.target" that exist during the host boot
+ phase. In other words, the new "initrd-cryptsetup.target" is supposed
+ to take the role for "initrd-fs.target", but for encrypted volumes.
+
+ * "systemctl edit" has been updated to show the original effective unit
+ contents in commented form in the text editor.
CHANGES WITH 246:
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
-[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)<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/>
[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master)<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>
[![Packaging status](https://repology.org/badge/tiny-repos/systemd.svg)](https://repology.org/project/systemd/versions)
Features:
+* systemd-analyze netif that explains predictable interface (or networkctl)
+
+* port selinux code from mallinfo() to mallinfo2() once added to glibc
+
+* Add service setting to run a service within the specified VRF. i.e. do the
+ equivalent of "ip vrf exec".
+
+* export action of device object on sd-device, so that monitor becomes useful
+
* add root=tmpfs that mounts a tmpfs to /sysroot (to be used in combination
with usr=…, for a similar effect as systemd.volatile=yes but without the
"hide-out" effect). Also, add root=gpt-auto-late support or so, that is like
* make us use dynamically fewer deps for containers in general purpose distros:
o turn into dlopen() deps:
- - libidn2 (always)
- elfutils (always)
- p11-kit-trust (always)
- kmod-libs (only when called from PID 1)
* systemctl: if some operation fails, show log output?
-* systemctl edit: use equivalent of cat() to insert existing config as a comment, prepended with #.
- Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc.
-
* exponential backoff in timesyncd when we cannot reach a server
* timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM
Subject: Новая сесія № @SESSION_ID@ створана для карыстальніка @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Новая сесія з № @SESSION_ID@ створана для карыстальніка @USER_ID@.
Subject: Сесія № @SESSION_ID@ спынена
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Сесія № @SESSION_ID@ спынена.
Subject: Даступна новае працоўнае месца № @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Новае працоўнае месца № @SEAT_ID@ наладжана і даступна для выкарыстання.
Subject: Працоўнае месца № @SEAT_ID@ выдалена
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Працоўнае месца № @SEAT_ID@ выдалена і больш не даступна.
Subject: Novaja siesija № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Novaja siesija z № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@.
Subject: Siesija № @SESSION_ID@ spyniena
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Siesija № @SESSION_ID@ spyniena.
Subject: Dastupna novaje pracoŭnaje miesca № @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Novaje pracoŭnaje miesca № @SEAT_ID@ naladžana i dastupna dlia
vykarystannia.
Subject: Pracoŭnaje miesca № @SEAT_ID@ vydaliena
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Pracoŭnaje miesca № @SEAT_ID@ vydaliena i boĺš nie dastupna.
Subject: Създадена е нова сесия № @SESSION_ID@ за потребителя „@USER_ID@“
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
За потребителя „@USER_ID@“ е създадена нова сесия № @SESSION_ID@.
Subject: Сесия № @SESSION_ID@ приключи
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Сесия № @SESSION_ID@ приключи работа.
Subject: Налично е ново работно място № @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Новото работно място № @SEAT_ID@ е настроено и готово за работа.
Subject: Работното място № @SEAT_ID@ е премахнато
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Работното място № @SEAT_ID@ вече не е налично.
Subject: A new session @SESSION_ID@ has been created for user @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A new session with the ID @SESSION_ID@ has been created for the user @USER_ID@.
Subject: Session @SESSION_ID@ has been terminated
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A session with the ID @SESSION_ID@ has been terminated.
Subject: A new seat @SEAT_ID@ is now available
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A new seat @SEAT_ID@ has been configured and is now available.
Subject: Seat @SEAT_ID@ has now been removed
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A seat @SEAT_ID@ has been removed and is no longer available.
Subject: En ny session @SESSION_ID@ er blevet lavet for bruger @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
En ny session med ID @SESSION_ID@ er blevet lavet for brugeren @USER_ID@.
Subject: Session @SESSION_ID@ er blevet lukket ned
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
En session med ID @SESSION_ID@ er blevet lukket ned.
Subject: En ny arbejdsstation $SEAT_ID@ er nu tilgængelig
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
En ny arbejdsstation @SEAT_ID@ er blevet konfigureret og er nu tilgængelig.
Subject: Arbejdsstation @SEAT_ID@ er nu blevet fjernet
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
En arbejdsstation @SEAT_ID@ er blevet fjernet og er ikke længere tilgængelig.
Subject: Une nouvelle session @SESSION_ID@ a été créée pour l'utilisateur @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Une nouvelle session a été créée pour l'utilisateur @USER_ID@ avec
l'identifiant (ID) @SESSION_ID@.
Subject: La session @SESSION_ID@ s'est terminée
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
La session d'identifiant (ID) @SESSION_ID@ s'est terminée.
Subject: Un nouveau poste (seat) @SEAT_ID@ est disponible
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Un nouveau poste (seat) @SEAT_ID@ a été configuré et est maintenant
disponible.
Subject: Le poste (seat) @SEAT_ID@ a été retiré
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Le poste (seat) @SEAT_ID@ a été retiré et n'est plus disponible.
Subject: Nova sesija @SESSION_ID@ je stvorena za korisnika @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Nova sesija sa ID @SESSION_ID@ je stvorena za korisnika @USER_ID@.
Subject: Sesija @SESSION_ID@ je prekinuta
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Sesija sa ID @SESSION_ID@ je prekinuta.
Subject: Novo sjedište @SEAT_ID@ je sada dostupno
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Novo sjedište @SEAT_ID@ je podešeno i sada je dostupno.
Subject: Sjedište @SEAT_ID@ je sada uklonjeno
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Sjedište @SEAT_ID@ je uklonjeno i više nije dostupno.
Subject: Új munkamenet (@SESSION_ID@) létrehozva, felhasználója: @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Létrejött egy új munkamenet @SESSION_ID@ azonosítóval ezen felhasználóhoz:
@USER_ID@.
Subject: Munkamenet (@SESSION_ID@) befejezve
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A következő azonosítójú munkamenet befejeződött: @SESSION_ID@.
Subject: Elérhető egy új munkaállomás: @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Beállításra kerül és használható egy új munkaállomás: @SEAT_ID@.
Subject: A munkaállomás eltávolítva: @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
A munkaállomás el lett távolítva, és már nem érhető el: @SEAT_ID@
Subject: La nuova sessione @SESSION_ID@ è stata creata per l'utente @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Una nuova sessione con ID @SESSION_ID@ è stata creata per l'utente @USER_ID@.
Subject: La sessione @SESSION_ID@ è terminata
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
La sessione con ID @SESSION_ID@ è terminata.
Subject: La nuova postazione @SEAT_ID@ è ora disponibile
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
La nuova postazione @SEAT_ID@ è stata configurata ed è ora disponibile.
Subject: La postazione @SEAT_ID@ è stata rimossa
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
La postazione @SEAT_ID@ è stata rimossa e non è più disponibile.
Subject: @USER_ID@ 사용자의 새 @SESSION_ID@ 세션 만듦
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
@USER_ID@ 사용자의 새 @SESSION_ID@ 세션을 만들었습니다.
Subject: @SESSION_ID@ 세션 마침
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
@SESSION_ID@ 세션을 끝냈습니다.
Subject: 새 @SEAT_ID@ 시트 사용할 수 있음
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
새 @SEAT_ID@ 시트를 설정했고 사용할 수 있습니다.
Subject: @SEAT_ID@ 시트 제거함
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
@SEAT_ID@ 시트를 제거했으며 더이상 사용할 수 없습니다.
Subject: Utworzono nową sesję @SESSION_ID@ dla użytkownika @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika
@USER_ID@.
Subject: Zakończono sesję @SESSION_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Sesja o identyfikatorze @SESSION_ID@ została zakończona.
Subject: Dostępne jest nowe stanowisko @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne.
Subject: Usunięto stanowisko @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne.
Subject: A nova sessão @SESSION_ID@ foi criada para usuário o @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Uma nova sessão com o ID @SESSION_ID@ foi criada para o usuário @USER_ID@.
Subject: Sessão @SESSION_ID@ foi terminada
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Um sessão com o ID @SESSION_ID@ foi terminada.
Subject: Um novo seat @SEAT_ID@ está disponível
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Um novo seat @SEAT_ID@ foi configurado e está disponível.
Subject: Seat @SEAT_ID@ foi removido agora
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Um seat @SEAT_ID@ foi removido e não está mais disponível.
Subject: Для пользователя @USER_ID@ создан новый сеанс @SESSION_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Для пользователя @USER_ID@ создан новый сеанс с идентификатором @SESSION_ID@.
Subject: Сеанс @SESSION_ID@ завершен
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Сеанс с идентификатором @SESSION_ID@ завершился.
Subject: Добавлено новое рабочее место @SEAT_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Новое рабочее место (seat) @SEAT_ID@ полностью настроено и готово к
использованию.
Subject: Рабочее место @SEAT_ID@ отключено
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Рабочее место (seat) @SEAT_ID@ было отключено.
Subject: Нова сесија @SESSION_ID@ је направљена за корисника @USER_ID@
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Нова сесија са ИБ-ом @SESSION_ID@ је направљена за корисника @USER_ID@.
Subject: Сесија @SESSION_ID@ је окончана
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Сесија са ИБ-ом @SESSION_ID@ је окончана.
Subject: Ново седиште @SEAT_ID@ је сада доступно
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Ново седиште @SEAT_ID@ је исподешавано и сада је доступно.
Subject: Седиште @SEAT_ID@ је сада уклоњено
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Седиште @SEAT_ID@ је сада уклоњено и више није доступно.
Subject: 一个新会话 @SESSION_ID@ 已为用户 @USER_ID@ 建立
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一个 ID 为 @SESSION_ID@ 的新会话已为用户 @USER_ID@ 建立。
Subject: 会话 @SESSION_ID@ 已终止
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一个 ID 为 @SESSION_ID@ 的会话已终止。
Subject: 一个新的座位 @SEAT_ID@ 可用
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一个新的座位 @SEAT_ID@ 已被配置并已可用。
Subject: 座位 @SEAT_ID@ 已被移除
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
座位 @SEAT_ID@ 已被移除并不再可用。
Subject: 新的工作階段 @SESSION_ID@ 已為使用者 @USER_ID@ 建立
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一個新的工作階段,ID @SESSION_ID@ 已為使用者 @USER_ID@ 建立。
Subject: 工作階段 @SESSION_ID@ 已結束
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一個工作階段,ID @SESSION_ID@ 已結束。
Subject: 新的座位 @SEAT_ID@ 可用
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
一個新的座位 @SEAT_ID@ 已被設定且現在可用。
Subject: 座位 @SEAT_ID@ 已被移除
Defined-By: systemd
Support: %SUPPORT_URL%
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
座位 @SEAT_ID@ 已被移除且不再可用。
@@
- (empty_or_root(s) ? "/" : s)
+ empty_to_root(s)
+@@
+expression s;
+@@
+- (s ? s : "/")
++ empty_to_root(s)
expression e;
statement s;
@@
-- if (e == NULL)
-+ if (!e)
-s
+if (
+(
+!e
+|
+- e == NULL
++ !e
+)
+ )
+ {...}
+else s
+
@@
expression e;
statement s;
@@
-- if (e != NULL)
-+ if (e)
-s
+if (
+(
+e
+|
+- e != NULL
++ e
+)
+ )
+ {...}
+else s
--- /dev/null
+@@
+constant c;
+@@
+(
+- errno == -c
++ errno == c
+|
+- errno != -c
++ errno != c
+)
@@
-/* Disable this transformation for the securebits-util.h, as it makes
- * the expression there confusing. */
-position p : script:python() { p[0].file != "src/shared/securebits-util.h" };
+/* Disable this transformation in cases where it doesn't make sense or
+ * where it makes the resulting expression more confusing
+ */
+position p : script:python() {
+ not (p[0].file == "src/shared/securebits-util.h" or
+ p[0].file == "src/core/manager.h" or
+ p[0].current_element == "log_set_max_level_realm" or
+ p[0].current_element == "unichar_is_valid")
+ };
expression x, y;
@@
(
+/* Limit the number of expressions to 6 for performance reasons */
@@
expression e;
/* Exclude JsonVariant * from the transformation, as it can't work with the
* current version of the IN_SET macro */
typedef JsonVariant;
type T != JsonVariant*;
-constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
+constant T n0, n1, n2, n3, n4, n5;
@@
-
(
-- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8 || e == n9
-+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
-|
-- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8
-+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
-|
-- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7
-+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
-|
-- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6
-+ IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
-|
- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5
+ IN_SET(e, n0, n1, n2, n3, n4, n5)
|
--- /dev/null
+/* Collected macros from our systemd codebase to make the cocci semantic
+ * parser happy. Inspired by the original cocci macros file
+ * /usr/lib64/coccinelle/standard.h (including the YACFE_* symbols)
+ */
+
+// General
+#define PTR_TO_PID(x)
+
+// src/basic/macro.h
+#define _printf_(a, b) __attribute__((__format__(printf, a, b)))
+#define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__)))
+#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 _weak_ __attribute__((__weak__))
+#define _likely_(x) (__builtin_expect(!!(x), 1))
+#define _unlikely_(x) (__builtin_expect(!!(x), 0))
+#define _public_ __attribute__((__visibility__("default")))
+#define _hidden_ __attribute__((__visibility__("hidden")))
+#define _weakref_(x) __attribute__((__weakref__(#x)))
+#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)))
+#define _fallthrough_
+#define _noreturn_ __attribute__((__noreturn__))
+#define thread_local __thread
+
+#define ELEMENTSOF(x) \
+ (__builtin_choose_expr( \
+ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
+ sizeof(x)/sizeof((x)[0]), \
+ VOID_0))
+
+// src/basic/umask-util.h
+#define _cleanup_umask_
+#define RUN_WITH_UMASK(mask) \
+ for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
+ FLAGS_SET(_saved_umask_, S_IFMT); \
+ _saved_umask_ &= 0777)
+
+// src/basic/hashmap.h
+#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
+#define HASHMAP_FOREACH(e, h) YACFE_ITERATOR
+#define ORDERED_HASHMAP_FOREACH(e, h) YACFE_ITERATOR
+#define HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR
+#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR
+
+// src/basic/list.h
+#define LIST_HEAD(t,name) \
+ t *name
+#define LIST_FIELDS(t,name) \
+ t *name##_next, *name##_prev
+#define LIST_HEAD_INIT(head) \
+ do { \
+ (head) = NULL; \
+ } while (false)
+#define LIST_INIT(name,item) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ assert(_item); \
+ _item->name##_prev = _item->name##_next = NULL; \
+ } while (false)
+#define LIST_PREPEND(name,head,item) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if ((_item->name##_next = *_head)) \
+ _item->name##_next->name##_prev = _item; \
+ _item->name##_prev = NULL; \
+ *_head = _item; \
+ } while (false)
+#define LIST_APPEND(name,head,item) \
+ do { \
+ typeof(*(head)) **_hhead = &(head), *_tail; \
+ LIST_FIND_TAIL(name, *_hhead, _tail); \
+ LIST_INSERT_AFTER(name, *_hhead, _tail, item); \
+ } while (false)
+#define LIST_REMOVE(name,head,item) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if (_item->name##_next) \
+ _item->name##_next->name##_prev = _item->name##_prev; \
+ if (_item->name##_prev) \
+ _item->name##_prev->name##_next = _item->name##_next; \
+ else { \
+ assert(*_head == _item); \
+ *_head = _item->name##_next; \
+ } \
+ _item->name##_next = _item->name##_prev = NULL; \
+ } while (false)
+#define LIST_FIND_HEAD(name,item,head) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ if (!_item) \
+ (head) = NULL; \
+ else { \
+ while (_item->name##_prev) \
+ _item = _item->name##_prev; \
+ (head) = _item; \
+ } \
+ } while (false)
+#define LIST_FIND_TAIL(name,item,tail) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ if (!_item) \
+ (tail) = NULL; \
+ else { \
+ while (_item->name##_next) \
+ _item = _item->name##_next; \
+ (tail) = _item; \
+ } \
+ } while (false)
+#define LIST_INSERT_AFTER(name,head,a,b) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
+ assert(_b); \
+ if (!_a) { \
+ if ((_b->name##_next = *_head)) \
+ _b->name##_next->name##_prev = _b; \
+ _b->name##_prev = NULL; \
+ *_head = _b; \
+ } else { \
+ if ((_b->name##_next = _a->name##_next)) \
+ _b->name##_next->name##_prev = _b; \
+ _b->name##_prev = _a; \
+ _a->name##_next = _b; \
+ } \
+ } while (false)
+#define LIST_INSERT_BEFORE(name,head,a,b) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
+ assert(_b); \
+ if (!_a) { \
+ if (!*_head) { \
+ _b->name##_next = NULL; \
+ _b->name##_prev = NULL; \
+ *_head = _b; \
+ } else { \
+ typeof(*(head)) *_tail = (head); \
+ while (_tail->name##_next) \
+ _tail = _tail->name##_next; \
+ _b->name##_next = NULL; \
+ _b->name##_prev = _tail; \
+ _tail->name##_next = _b; \
+ } \
+ } else { \
+ if ((_b->name##_prev = _a->name##_prev)) \
+ _b->name##_prev->name##_next = _b; \
+ else \
+ *_head = _b; \
+ _b->name##_next = _a; \
+ _a->name##_prev = _b; \
+ } \
+ } while (false)
+
+#define LIST_JUST_US(name,item) \
+ (!(item)->name##_prev && !(item)->name##_next) \
+#define LIST_FOREACH(name,i,head) \
+ for ((i) = (head); (i); (i) = (i)->name##_next)
+#define LIST_FOREACH_SAFE(name,i,n,head) \
+ for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
+#define LIST_FOREACH_BEFORE(name,i,p) \
+ for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
+#define LIST_FOREACH_AFTER(name,i,p) \
+ for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
+#define LIST_FOREACH_OTHERS(name,i,p) \
+ for (({ \
+ (i) = (p); \
+ while ((i) && (i)->name##_prev) \
+ (i) = (i)->name##_prev; \
+ if ((i) == (p)) \
+ (i) = (p)->name##_next; \
+ }); \
+ (i); \
+ (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
+#define LIST_LOOP_BUT_ONE(name,i,head,p) \
+ for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
+ (i) != (p); \
+ (i) = (i)->name##_next ? (i)->name##_next : (head))
+
+#define LIST_IS_EMPTY(head) \
+ (!(head))
+#define LIST_JOIN(name,a,b) \
+ do { \
+ assert(b); \
+ if (!(a)) \
+ (a) = (b); \
+ else { \
+ typeof(*(a)) *_head = (b), *_tail; \
+ LIST_FIND_TAIL(name, (a), _tail); \
+ _tail->name##_next = _head; \
+ _head->name##_prev = _tail; \
+ } \
+ (b) = NULL; \
+ } while (false)
+
+// src/basic/strv.h
+#define STRV_FOREACH(s, l) YACFE_ITERATOR
+#define STRV_FOREACH_BACKWARDS(s, l) YACFE_ITERATOR
+#define STRV_FOREACH_PAIR(x, y, l) YACFE_ITERATOR
+
+// src/basic/socket-util.h
+#define CMSG_BUFFER_TYPE(size) \
+ union { \
+ struct cmsghdr cmsghdr; \
+ uint8_t buf[size]; \
+ uint8_t align_check[(size) >= CMSG_SPACE(0) && \
+ (size) == CMSG_ALIGN(size) ? 1 : -1]; \
+ }
+
+// src/libsystemd/sd-device/device-util.h
+#define FOREACH_DEVICE_PROPERTY(device, key, value) YACFE_ITERATOR
+#define FOREACH_DEVICE_TAG(device, tag) YACFE_ITERATOR
+#define FOREACH_DEVICE_CURRENT_TAG(device, tag) YACFE_ITERATOR
+#define FOREACH_DEVICE_SYSATTR(device, attr) YACFE_ITERATOR
+#define FOREACH_DEVICE_DEVLINK(device, devlink) YACFE_ITERATOR
+#define FOREACH_DEVICE(enumerator, device) YACFE_ITERATOR
+#define FOREACH_SUBSYSTEM(enumerator, device) YACFE_ITERATOR
+
+// src/basic/dirent-util.h
+#define FOREACH_DIRENT(de, d, on_error) YACFE_ITERATOR
+#define FOREACH_DIRENT_ALL(de, d, on_error) YACFE_ITERATOR
+/* Limit the number of expressions to 6 for performance reasons */
@@
expression e;
typedef JsonVariant;
type T != JsonVariant*;
-constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
+constant T n0, n1, n2, n3, n4, n5;
@@
(
-- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9
-+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
-|
-- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8
-+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
-|
-- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7
-+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
-|
-- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6
-+ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
-|
- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5
+ !IN_SET(e, n0, n1, n2, n3, n4, n5)
|
)
top="$(git rev-parse --show-toplevel)"
-iso_defs="$top/coccinelle/systemd-definitions.iso"
args=
# Create an array from files tracked by git...
exit 1
fi
-for SCRIPT in ${@-$top/coccinelle/*.cocci} ; do
+for SCRIPT in ${@-$top/coccinelle/*.cocci}; do
echo "--x-- Processing $SCRIPT --x--"
TMPFILE=`mktemp`
echo "+ spatch --sp-file $SCRIPT $args ..."
parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \
- spatch --iso-file $iso_defs --sp-file $SCRIPT $args ::: "${files[@]}" \
+ spatch --macro-file="$top/coccinelle/macros.h" --sp-file $SCRIPT $args ::: "${files[@]}" \
2>"$TMPFILE" || cat "$TMPFILE"
echo -e "--x-- Processed $SCRIPT --x--\n"
done
@@
-expression list args;
-@@
-- strjoin(args, NULL);
-+ strjoin(args);
-@@
+position p : script:python() { p[0].current_element != "test_strjoin" };
expression t;
expression list args;
@@
-- t = strjoin(args, NULL);
+(
+- strjoin@p(args, NULL);
++ strjoin(args);
+|
+- t = strjoin@p(args, NULL);
+ t = strjoin(args);
-@@
-expression list args;
-@@
-- return strjoin(args, NULL);
+|
+- return strjoin@p(args, NULL);
+ return strjoin(args);
+)
+++ /dev/null
-/* Statement isomorphisms - replace explicit checks against NULL with a
- * shorter variant, which relies on C's downgrade-to-bool feature.
- * The expression metavariables should be declared as pointers, however,
- * that doesn't work well with complex expressions like:
- * if (UNIT(p)->default_dependencies != NULL)
- */
-
-Statement
-@@
-expression X;
-statement S;
-@@
-if (X == NULL) S => if (!X) S
-
-Statement
-@@
-expression X;
-statement S;
-@@
-if (X != NULL) S => if (X) S
@@
+position p : script:python() { not p[0].file.startswith("man/") };
expression e, fmt;
expression list vaargs;
@@
-- snprintf(e, sizeof(e), fmt, vaargs);
+- snprintf@p(e, sizeof(e), fmt, vaargs);
+ xsprintf(e, fmt, vaargs);
--- /dev/null
+@@
+position p : script:python() { p[0].file != "src/journal/lookup3.c" };
+identifier id;
+expression e;
+@@
+if (...)
+- {
+(
+ id@p(...);
+|
+ e@p;
+)
+- }
+
+@@
+position p : script:python() { p[0].file != "src/journal/lookup3.c" };
+identifier id;
+expression e;
+@@
+if (...)
+- {
+(
+ return id@p(...);
+|
+ return e@p;
+)
+- }
the lock it is kept for the entire time the device is processed.
Note that `systemd-udevd` also watches all block device nodes it manages for
-`inotify()` `IN_CLOSE` events: whenever such an event is seen, this is used as
-trigger to re-run the rule-set for the device.
+`inotify()` `IN_CLOSE_WRITE` events: whenever such an event is seen, this is
+used as trigger to re-run the rule-set for the device.
These two concepts allow tools such as disk partitioners or file system
formatting tools to safely and easily take exclusive ownership of a block
device while operating: before starting work on the block device, they should
take an `LOCK_EX` lock on it. This has two effects: first of all, in case
`systemd-udevd` is still processing the device the tool will wait for it to
-finish. Second, after the lock is taken, it can be sure that
-`systemd-udevd` will refrain from processing the block device, and thus all
-other client applications subscribed to it won't get device notifications from
-potentially half-written data either. After the operation is complete the
+finish. Second, after the lock is taken, it can be sure that `systemd-udevd`
+will refrain from processing the block device, and thus all other client
+applications subscribed to it won't get device notifications from potentially
+half-written data either. After the operation is complete the
partitioner/formatter can simply close the device node. This has two effects:
it implicitly releases the lock, so that `systemd-udevd` can process events on
-the device node again. Secondly, it results an `IN_CLOSE` event, which causes
-`systemd-udevd` to immediately re-process the device — seeing all changes the
-tool made — and notify subscribed clients about it.
+the device node again. Secondly, it results an `IN_CLOSE_WRITE` event, which
+causes `systemd-udevd` to immediately re-process the device — seeing all
+changes the tool made — and notify subscribed clients about it.
+
+Ideally, `systemd-udevd` would explicitly watch block devices for `LOCK_EX`
+locks being released. Such monitoring is not supported on Linux however, which
+is why it watches for `IN_CLOSE_WRITE` instead, i.e. for `close()` calls to
+writable file descriptors referring to the block device. In almost all cases,
+the difference between these two events does not matter much, as any locks
+taken are implicitly released by `close()`. However, it should be noted that if
+an application unlocks a device after completing its work without closing it,
+i.e. while keeping the file descriptor open for further, longer time, then
+`systemd-udevd` will not notice this and not retrigger and thus reprobe the
+device.
Besides synchronizing block device access between `systemd-udevd` and such
tools this scheme may also be used to synchronize access between those tools
**Note:** _In all cases the `/loader/` directory should be located directly in the root of the file system. Specifically, if `$BOOT` is the ESP, then `/loader/` directory should be located directly in the root directory of the ESP, and not in the `/EFI/` subdirectory._
-Inside the `$BOOT/loader/entries/` directory each OS vendor may drop one or more configuration snippets with the suffix ".conf", one for each boot menu item. The file name of the file is used for identification of the boot item but shall never be presented to the user in the UI. The file name may be chosen freely but should be unique enough to avoid clashes between OS installations. More specifically it is suggested to include the machine ID (`/etc/machine-id` or the D-Bus machine ID for OSes that lack `/etc/machine-id`), the kernel version (as returned by `uname -r`) and an OS identifier (The ID field of `/etc/os-release`). Example: `$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf`.
+Inside the `$BOOT/loader/entries/` directory each OS vendor may drop one or
+more configuration snippets with the suffix ".conf", one for each boot menu
+item. The file name of the file is used for identification of the boot item but
+shall never be presented to the user in the UI. The file name may be chosen
+freely but should be unique enough to avoid clashes between OS
+installations. More specifically it is suggested to include the machine ID
+(`/etc/machine-id` or the D-Bus machine ID for OSes that lack
+`/etc/machine-id`), the kernel version (as returned by `uname -r`) and an OS
+identifier (The ID field of `/etc/os-release`). Example:
+`$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf`.
+
+In order to maximize compatibility with file system implementations and
+restricted boot loader environments, and to minimize conflicting character use
+with other progams, file names shall be chosen from a restricted character set:
+ASCII upper and lower case characters, digits, "+", "-", "_" and ".". Also, the
+file names should have a length of at least one and at most 255 characters
+(including file name suffix).
These configuration snippets shall be Unix-style text files (i.e. line separation with a single newline character), in the UTF-8 encoding. The configuration snippets are loosely inspired on Grub1's configuration syntax. Lines beginning with '#' shall be ignored and used for commenting. The first word of a line is used as key and shall be separated by one or more spaces from its value. The following keys are known:
systems with EFI firmware. Ignore this section if you work on systems not
supporting EFI.
+Type #2 file names should be chosen from the same restricted character set as
+Type #1 described above (but use a different file name suffix of `.efi` instead
+of `.conf`).
+
Images of this type have the advantage that all metadata and payload that makes
up the boot entry is monopolized in a single PE file that can be signed
cryptographically as one for the purpose of EFI SecureBoot.
int a, b, c;
```
+ (i.e. use double indentation — 16 spaces — for the parameter list.)
+
- Try to write this:
```c
- Do not write functions that clobber call-by-reference variables on
failure. Use temporary variables for these cases and change the passed in
- variables only on success.
+ variables only on success. The rule is: never clobber return parameters on
+ failure, always initialize return parameters on success.
+
+- Typically, function parameters fit into three categories: input parameters,
+ mutable objects, and call-by-reference return parameters. Input parameters
+ should always carry suitable "const" declarators if they are pointers, to
+ indicate they are input-only and not changed by the function. Return
+ parameters are best prefixed with "ret_", to clarify they are return
+ parameters. (Conversely, please do not prefix parameters that aren't
+ output-only with "ret_", in particular not mutable parameters that are both
+ input as well as output). Example:
+
+ ```c
+ static int foobar_frobnicate(
+ Foobar* object, /* the associated mutable object */
+ const char *input, /* immutable input parameter */
+ char **ret_frobnicated) { /* return parameter */
+ …
+ return 0;
+ }
+ ```
- The order in which header files are included doesn't matter too
much. systemd-internal headers must not rely on an include order, so it is
## Logging
- For every function you add, think about whether it is a "logging" function or
- a "non-logging" function. "Logging" functions do logging on their own,
- "non-logging" function never log on their own and expect their callers to
- log. All functions in "library" code, i.e. in `src/shared/` and suchlike must
- be "non-logging". Every time a "logging" function calls a "non-logging"
- function, it should log about the resulting errors. If a "logging" function
- calls another "logging" function, then it should not generate log messages,
- so that log messages are not generated twice for the same errors.
+ a "non-logging" function. "Logging" functions do (non-debug) logging on their
+ own, "non-logging" function never log on their own (except at debug level)
+ and expect their callers to log. All functions in "library" code, i.e. in
+ `src/shared/` and suchlike must be "non-logging". Every time a "logging"
+ function calls a "non-logging" function, it should log about the resulting
+ errors. If a "logging" function calls another "logging" function, then it
+ should not generate log messages, so that log messages are not generated
+ twice for the same errors. (Note that debug level logging — at syslog level
+ `LOG_DEBUG` — is not considered logging in this context, debug logging is
+ generally always fine and welcome.)
- If possible, do a combined log & return operation:
| [hostnamed](https://www.freedesktop.org/wiki/Software/systemd/hostnamed) | D-Bus | yes | yes | GNOME | yes | [Ubuntu](https://launchpad.net/ubuntu/+source/ubuntu-system-service), [Gentoo](http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml), [BSD](http://uglyman.kremlin.cc/gitweb/gitweb.cgi?p=systembsd.git;a=summary) | partially |
| [localed](https://www.freedesktop.org/wiki/Software/systemd/localed) | D-Bus | yes | yes | GNOME | yes | [Ubuntu](https://launchpad.net/ubuntu/+source/ubuntu-system-service), [Gentoo](http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml), [BSD](http://uglyman.kremlin.cc/gitweb/gitweb.cgi?p=systembsd.git;a=summary) | partially |
| [timedated](https://www.freedesktop.org/wiki/Software/systemd/timedated) | D-Bus | yes | yes | GNOME | yes | [Gentoo](http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml), [BSD](http://uglyman.kremlin.cc/gitweb/gitweb.cgi?p=systembsd.git;a=summary) | partially |
-| [initrd interface](https://www.freedesktop.org/wiki/Software/systemd/InitrdInterface) | Environment, flag files | yes | yes | dracut, ArchLinux | yes | ArchLinux | no |
+| [initrd interface](https://systemd.io/INITRD_INTERFACE/) | Environment, flag files | yes | yes | dracut, ArchLinux | yes | ArchLinux | no |
| [Container interface](https://systemd.io/CONTAINER_INTERFACE) | Environment, Mounts | yes | yes | libvirt/LXC | yes | - | no |
| [Boot Loader interface](https://systemd.io/BOOT_LOADER_INTERFACE) | EFI variables | yes | yes | gummiboot | yes | - | no |
| [Service bus API](https://www.freedesktop.org/wiki/Software/systemd/dbus) | D-Bus | yes | yes | system-config-services | no | - | no |
| [$XDG_RUNTIME_DIR](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) | Environment | yes | yes | glib, GNOME | yes | - | no |
| [$LISTEN_FDS $LISTEN_PID FD Passing](https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html) | Environment | yes | yes | numerous (via sd-daemon.h) | yes | - | no |
| [$NOTIFY_SOCKET Daemon Notifications](https://www.freedesktop.org/software/systemd/man/sd_notify.html) | Environment | yes | yes | a few, including udev | yes | - | no |
-| [argv[0][0]='@' Logic](https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons) | `/proc` marking | yes | yes | mdadm | yes | - | no |
+| [argv[0][0]='@' Logic](https://systemd.io/ROOT_STORAGE_DAEMONS/) | `/proc` marking | yes | yes | mdadm | yes | - | no |
| [Unit file format](https://www.freedesktop.org/software/systemd/man/systemd.unit.html) | File format | yes | yes | numerous | no | - | no |
| [Network](https://www.freedesktop.org/software/systemd/man/systemd.network.html) & [Netdev file format](https://www.freedesktop.org/software/systemd/man/systemd.netdev.html) | File format | yes | yes | no | no | - | no |
| [Link file format](https://www.freedesktop.org/software/systemd/man/systemd.link.html) | File format | yes | yes | no | no | - | no |
| [Journal File Format](https://systemd.io/JOURNAL_FILE_FORMAT) | File format | yes | yes | - | maybe | - | no |
| [Journal Export Format](https://www.freedesktop.org/wiki/Software/systemd/export) | File format | yes | yes | - | yes | - | no |
| [Cooperation in cgroup tree](https://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups) | Treaty | yes | yes | libvirt | yes | libvirt | no |
-| [Password Agents](https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents) | Socket+Files | yes | yes | - | yes | - | no |
-| [udev multi-seat properties](https://www.freedesktop.org/wiki/Software/systemd/multiseat) | udev Property | yes | yes | X11, gdm | no | - | no |
+| [Password Agents](https://systemd.io/PASSWORD_AGENTS/) | Socket+Files | yes | yes | - | yes | - | no |
+| [udev multi-seat properties](https://www.freedesktop.org/software/systemd/man/sd-login.html) | udev Property | yes | yes | X11, gdm | no | - | no |
| udev session switch ACL properties | udev Property | no | no | - | no | - | no |
| [CLI of systemctl,...](https://www.freedesktop.org/software/systemd/man/systemctl.html) | CLI | yes | yes | numerous | no | - | no |
| [tmpfiles.d](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html) | File format | yes | yes | numerous | yes | ArchLinux | partially |
The recommended way to distinguish between run-from-initrd and run-from-rootfs
for a daemon is to check for `/etc/initrd-release` (which exists on all modern
initrd implementations, see the [initrd
-Interface](http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface)
-for details) which when exists results in `argv[0][0]` being set to `@`, and
-otherwise doesn't. Something like this:
+Interface](https://systemd.io/INITRD_INTERFACE/) for details) which when exists
+results in `argv[0][0]` being set to `@`, and otherwise doesn't. Something like
+this:
```c
#include <unistd.h>
---
-title: Using /tmp/ And /var/tmp/ Safely
+title: Using /tmp/ and /var/tmp/ Safely
category: Interfaces
layout: default
---
-# Using `/tmp/` And `/var/tmp/` Safely
+# Using `/tmp/` and `/var/tmp/` Safely
`/tmp/` and `/var/tmp/` are two world-writable directories Linux systems
provide for temporary files. The former is typically on `tmpfs` and thus
✓ IPAccounting=
✓ IPAddressAllow=
✓ IPAddressDeny=
+✓ ManagedOOMSwap=
+✓ ManagedOOMMemoryPressure=
+✓ ManagedOOMMemoryPressureLimitPercent=
```
## Process Killing Settings
allocation logic, the maximum UID used for this range is hence
1878982656+65535=1879048191.)
-Note that systemd does not make any of these values runtime-configurable. All
-these boundaries are chosen during build time. That said, the system UID/GID
-boundary is traditionally configured in /etc/login.defs, though systemd won't
-look there during runtime.
+Systemd has compile-time default for these boundaries. Using those defaults is
+recommended. It will nevertheless query `/etc/login.defs` at runtime, when
+compiled with `-Dcompat-mutable-uid-boundaries=true` and that file is present.
+Support for this is considered only a compatibility feature and should not be
+used except when upgrading systems which were creating with different defaults.
## Considerations for container managers
ID_OUI_FROM_DATABASE=Data Track Technology PLC
OUI:0002C7*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0002C8*
ID_OUI_FROM_DATABASE=Technocom Communications Technology (pte) Ltd
ID_OUI_FROM_DATABASE=Digitel Co., Ltd.
OUI:000334*
- ID_OUI_FROM_DATABASE=Newport Electronics
+ ID_OUI_FROM_DATABASE=Omega Engineering Inc.
OUI:000335*
ID_OUI_FROM_DATABASE=Mirae Technology
ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc.
OUI:0006F5*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0006F6*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:0006F7*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0006F8*
ID_OUI_FROM_DATABASE=The Boeing Company
ID_OUI_FROM_DATABASE=CSEE Transport
OUI:000704*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:000705*
ID_OUI_FROM_DATABASE=Endress & Hauser GmbH & Co
ID_OUI_FROM_DATABASE=Emuzed
OUI:000B4E*
- ID_OUI_FROM_DATABASE=VertexRSI, General Dynamics SatCOM Technologies, Inc.
+ ID_OUI_FROM_DATABASE=Communications & Power Industries
OUI:000B4F*
ID_OUI_FROM_DATABASE=Verifone
ID_OUI_FROM_DATABASE=Moram Co., Ltd.
OUI:00145A*
- ID_OUI_FROM_DATABASE=Neratec Solutions AG
+ ID_OUI_FROM_DATABASE=Westermo Neratec AG
OUI:00145B*
ID_OUI_FROM_DATABASE=SeekerNet Inc.
ID_OUI_FROM_DATABASE=YVES TECHNOLOGY CO., LTD.
OUI:00163B*
- ID_OUI_FROM_DATABASE=VertexRSI/General Dynamics
+ ID_OUI_FROM_DATABASE=Communications & Power Industries
OUI:00163C*
ID_OUI_FROM_DATABASE=Rebox B.V.
ID_OUI_FROM_DATABASE=Jaty Electronics
OUI:0016FE*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0016FF*
ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0019C1*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0019C2*
ID_OUI_FROM_DATABASE=Equustek Solutions, Inc.
ID_OUI_FROM_DATABASE=G.i.N. mbH
OUI:001BFB*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:001BFC*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
ID_OUI_FROM_DATABASE=Lyngbox Media AB
OUI:001E3D*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:001E3E*
ID_OUI_FROM_DATABASE=KMW Inc.
ID_OUI_FROM_DATABASE=GS Yuasa Power Supply Ltd.
OUI:00214F*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:002150*
ID_OUI_FROM_DATABASE=EYEVIEW ELECTRONICS
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:002306*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:002307*
ID_OUI_FROM_DATABASE=FUTURE INNOVATION TECH CO.,LTD
ID_OUI_FROM_DATABASE=ANTIPODE
OUI:002386*
- ID_OUI_FROM_DATABASE=Tour & Andersson AB
+ ID_OUI_FROM_DATABASE=IMI Hydronic Engineering international SA
OUI:002387*
ID_OUI_FROM_DATABASE=ThinkFlood, Inc.
ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD
OUI:002433*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:002434*
ID_OUI_FROM_DATABASE=Lectrosonics, Inc.
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002643*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:002644*
ID_OUI_FROM_DATABASE=Thomson Telecom Belgium
ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
OUI:00264E*
- ID_OUI_FROM_DATABASE=Rail & Road Protec GmbH
+ ID_OUI_FROM_DATABASE=r2p GmbH
OUI:00264F*
ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH
OUI:003146*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:003192*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:003217*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:00336C*
ID_OUI_FROM_DATABASE=SynapSense Corporation
+OUI:0034A1*
+ ID_OUI_FROM_DATABASE=RF-LAMBDA USA INC.
+
OUI:0034DA*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
OUI:0054BD*
ID_OUI_FROM_DATABASE=Swelaser AB
+OUI:0055B1*
+ ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd.
+
OUI:0055DA0*
ID_OUI_FROM_DATABASE=Shinko Technos co.,ltd.
ID_OUI_FROM_DATABASE=NETCOMM LIMITED
OUI:006065*
- ID_OUI_FROM_DATABASE=BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH
+ ID_OUI_FROM_DATABASE=B&R Industrial Automation GmbH
OUI:006066*
ID_OUI_FROM_DATABASE=LACROIX Trafic
OUI:006DFB*
ID_OUI_FROM_DATABASE=Vutrix Technologies Ltd
+OUI:006E02*
+ ID_OUI_FROM_DATABASE=Xovis AG
+
OUI:006F64*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:0088BA*
ID_OUI_FROM_DATABASE=NC&C
+OUI:008A55*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:008A96*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
ID_OUI_FROM_DATABASE=LEICHU ENTERPRISE CO., LTD.
OUI:0090D2*
- ID_OUI_FROM_DATABASE=ARTEL VIDEO SYSTEMS
+ ID_OUI_FROM_DATABASE=Artel Video Systems
OUI:0090D3*
ID_OUI_FROM_DATABASE=GIESECKE & DEVRIENT GmbH
OUI:00B810*
ID_OUI_FROM_DATABASE=Yichip Microelectronics (Hangzhou) Co.,Ltd
+OUI:00B881*
+ ID_OUI_FROM_DATABASE=New platforms LLC
+
OUI:00B8B3*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:00C2C6*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:00C343*
+ ID_OUI_FROM_DATABASE=E-T-A Circuit Breakers Ltd
+
OUI:00C3F4*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:00C52C*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:00C5DB*
ID_OUI_FROM_DATABASE=Datatech Sistemas Digitales Avanzados SL
OUI:00E8AB*
ID_OUI_FROM_DATABASE=Meggitt Training Systems, Inc.
+OUI:00E93A*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
OUI:00EABD*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:0404EA*
ID_OUI_FROM_DATABASE=Valens Semiconductor Ltd.
+OUI:0405DD*
+ ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co., Ltd
+
OUI:04072E*
ID_OUI_FROM_DATABASE=VTech Electronics Ltd.
ID_OUI_FROM_DATABASE=CSST
OUI:04766E*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0476B0*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
ID_OUI_FROM_DATABASE=Lartech telecom LLC
OUI:0498F3*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:0499E6*
ID_OUI_FROM_DATABASE=Shenzhen Yoostar Technology Co., Ltd
OUI:04E676*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+OUI:04E77E*
+ ID_OUI_FROM_DATABASE=We Corporation Inc.
+
OUI:04E795*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:04F17D*
ID_OUI_FROM_DATABASE=Tarana Wireless
+OUI:04F352*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:04F4BC*
ID_OUI_FROM_DATABASE=Xena Networks
OUI:0838A5*
ID_OUI_FROM_DATABASE=Funkwerk plettac electronic GmbH
+OUI:0838E6*
+ ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+
OUI:083A2F*
ID_OUI_FROM_DATABASE=Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd
OUI:0854BB*
ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+OUI:085531*
+ ID_OUI_FROM_DATABASE=Routerboard.com
+
OUI:085700*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:0858A5*
+ ID_OUI_FROM_DATABASE=Beijing Vrv Software Corpoaration Limited.
+
OUI:085AE0*
ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd.
OUI:086361*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0865F0*
+ ID_OUI_FROM_DATABASE=JM Zengge Co., Ltd
+
OUI:08661F*
ID_OUI_FROM_DATABASE=Palo Alto Networks
OUI:087BAA*
ID_OUI_FROM_DATABASE=SVYAZKOMPLEKTSERVICE, LLC
+OUI:087C39*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:087CBE*
ID_OUI_FROM_DATABASE=Quintic Corp.
OUI:0890BA*
ID_OUI_FROM_DATABASE=Danlaw Inc
+OUI:089356*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:0894EF*
ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation
OUI:08CA45*
ID_OUI_FROM_DATABASE=Toyou Feiji Electronics Co., Ltd.
+OUI:08CBE5*
+ ID_OUI_FROM_DATABASE=R3 - Reliable Realtime Radio Communications GmbH
+
OUI:08CC27*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
OUI:0C15C5*
ID_OUI_FROM_DATABASE=SDTEC Co., Ltd.
+OUI:0C1773*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:0C17F1*
ID_OUI_FROM_DATABASE=TELECSYS
OUI:0C31DC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0C354F*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:0C35FE*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:0C3956*
ID_OUI_FROM_DATABASE=Observator instruments
+OUI:0C3AFA*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:0C3B50*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:0CB771*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:0CB789*
+ ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
+
OUI:0CB912*
ID_OUI_FROM_DATABASE=JM-DATA GmbH
OUI:0CEC84*
ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:0CEC8D*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
OUI:0CEE99*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:102C83*
ID_OUI_FROM_DATABASE=XIMEA
+OUI:102D31*
+ ID_OUI_FROM_DATABASE=Shenzhen Americas Trading Company LLC
+
OUI:102D96*
ID_OUI_FROM_DATABASE=Looxcie Inc.
OUI:103DEA*
ID_OUI_FROM_DATABASE=HFC Technology (Beijing) Ltd. Co.
+OUI:103F44*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:1040F3*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:1070FD*
ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc.
+OUI:107100*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:1071F9*
ID_OUI_FROM_DATABASE=Cloud Telecomputers, LLC
OUI:10954B*
ID_OUI_FROM_DATABASE=Megabyte Ltd.
+OUI:109693*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:109836*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:109C70*
ID_OUI_FROM_DATABASE=Prusa Research s.r.o.
+OUI:109D7A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:109E3A*
ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
OUI:10D542*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:10D7B0*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:10DA43*
ID_OUI_FROM_DATABASE=NETGEAR
OUI:141330*
ID_OUI_FROM_DATABASE=Anakreon UK LLP
+OUI:141333*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
OUI:141346*
ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
OUI:141AA3*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:141B30*
+ ID_OUI_FROM_DATABASE=Shenzhen Yipingfang Network Technology Co., Ltd.
+
OUI:141BBD*
ID_OUI_FROM_DATABASE=Volex Inc.
OUI:145412*
ID_OUI_FROM_DATABASE=Entis Co., Ltd.
+OUI:14563A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:145645*
ID_OUI_FROM_DATABASE=Savitech Corp.
OUI:146B72*
ID_OUI_FROM_DATABASE=Shenzhen Fortune Ship Technology Co., Ltd.
+OUI:146B9A*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:146B9C*
ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
OUI:14876A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:1488E6*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:14893E*
ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED
OUI:14A9E3*
ID_OUI_FROM_DATABASE=MST CORPORATION
+OUI:14AB02*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:14AB56*
ID_OUI_FROM_DATABASE=WUXI FUNIDE DIGITAL CO.,LTD
OUI:18104E*
ID_OUI_FROM_DATABASE=CEDINT-UPM
+OUI:181171*
+ ID_OUI_FROM_DATABASE=Guangzhou Doctorpai Education & Technology Co.,Ltd
+
OUI:181212*
ID_OUI_FROM_DATABASE=Cepton Technologies
OUI:1835D1*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:183672*
+ ID_OUI_FROM_DATABASE=Shaoxing ShunChuang Technology CO.,LTD
+
OUI:1836FC*
ID_OUI_FROM_DATABASE=Elecsys International Corporation
OUI:1844E6*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:184516*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:184593*
ID_OUI_FROM_DATABASE=Taicang T&W Electronics
OUI:184F32*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:184F5D*
+ ID_OUI_FROM_DATABASE=JRC Mobility Inc.
+
OUI:18502A*
ID_OUI_FROM_DATABASE=SOARNEX
OUI:185AE8*
ID_OUI_FROM_DATABASE=Zenotech.Co.,Ltd
+OUI:185BB3*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:185D9A*
ID_OUI_FROM_DATABASE=BobjGear LLC
OUI:1886AC*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:188740*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:188796*
ID_OUI_FROM_DATABASE=HTC Corporation
OUI:18B591*
ID_OUI_FROM_DATABASE=I-Storm
+OUI:18B6CC*
+ ID_OUI_FROM_DATABASE=We Corporation Inc.
+
OUI:18B6F7*
ID_OUI_FROM_DATABASE=NEW POS TECHNOLOGY LIMITED
OUI:18C8E7*
ID_OUI_FROM_DATABASE=Shenzhen Hualistone Technology Co.,Ltd
+OUI:18CC18*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:18CC23*
ID_OUI_FROM_DATABASE=Philio Technology Corporation
OUI:18EE69*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:18EE86*
+ ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc.
+
OUI:18EF63*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:1C2E1B*
ID_OUI_FROM_DATABASE=Suzhou Tremenet Communication Technology Co., Ltd.
+OUI:1C3008*
+ ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+
OUI:1C330E*
ID_OUI_FROM_DATABASE=PernixData
OUI:1C4593*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:1C45C2*
+ ID_OUI_FROM_DATABASE=Huizhou City Sunsin lntelligent Technology Co.,Ltd
+
OUI:1C4840*
ID_OUI_FROM_DATABASE=IMS Messsysteme GmbH
OUI:1C4BD6*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+OUI:1C4C48*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:1C4D66*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:1C8F8A*
ID_OUI_FROM_DATABASE=Phase Motion Control SpA
+OUI:1C90BE*
+ ID_OUI_FROM_DATABASE=Ericsson AB
+
OUI:1C9148*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:1C9ECB*
ID_OUI_FROM_DATABASE=Beijing Nari Smartchip Microelectronics Company Limited
+OUI:1C9F4E*
+ ID_OUI_FROM_DATABASE=COOSEA GROUP (HK) COMPANY LIMITED
+
OUI:1CA0B8*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd.
OUI:1CA770*
ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+OUI:1CA852*
+ ID_OUI_FROM_DATABASE=SENSAIO PTE LTD
+
OUI:1CAA07*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:1CE2CC*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:1CE57F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:1CE61D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:1CEA1B*
ID_OUI_FROM_DATABASE=Nokia
+OUI:1CEC72*
+ ID_OUI_FROM_DATABASE=Allradio Co., Ltd
+
OUI:1CEEC9*
ID_OUI_FROM_DATABASE=Elo touch solutions
OUI:201A06*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+OUI:201B88*
+ ID_OUI_FROM_DATABASE=Dongguan Liesheng Electronic Co., Ltd.
+
OUI:201BC9*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:204E7F*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:204EF6*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
OUI:2050E7*
ID_OUI_FROM_DATABASE=AMPAK Technology,Inc.
ID_OUI_FROM_DATABASE=AASSET SECURITY
OUI:2085939*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Mastodon Design
OUI:208593A*
ID_OUI_FROM_DATABASE=H3 Industries, Inc.
OUI:20AB48*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:20AC9C*
+ ID_OUI_FROM_DATABASE=China Telecom Corporation Limited
+
OUI:20AD56*
ID_OUI_FROM_DATABASE=Continental Automotive Systems Inc.
OUI:20CD39*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:20CD6E*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:20CEC4*
ID_OUI_FROM_DATABASE=Peraso Technologies
OUI:20DCE6*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:20DCFD*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:20DE88*
ID_OUI_FROM_DATABASE=IC Realtime LLC
OUI:2400FA*
ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd
+OUI:24016F*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:2401C7*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:2405F5*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+OUI:2406AA*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:240917*
ID_OUI_FROM_DATABASE=Devlin Electronics Limited
OUI:241125*
ID_OUI_FROM_DATABASE=Hutek Co., Ltd.
+OUI:241145*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:241148*
ID_OUI_FROM_DATABASE=Entropix, LLC
ID_OUI_FROM_DATABASE=SuZhou A-rack Information Technology Co.,Ltd
OUI:2415108*
- ID_OUI_FROM_DATABASE=Medicomp, Inc
+ ID_OUI_FROM_DATABASE=Private
OUI:2415109*
ID_OUI_FROM_DATABASE=Topgolf Sweden AB
OUI:242FFA*
ID_OUI_FROM_DATABASE=Toshiba Global Commerce Solutions
+OUI:2430F8*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:243154*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:2462CE*
ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+OUI:24649F*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:2464EF*
ID_OUI_FROM_DATABASE=CYG SUNRI CO.,LTD.
OUI:2474F7*
ID_OUI_FROM_DATABASE=GoPro
+OUI:247625*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:247656*
ID_OUI_FROM_DATABASE=Shanghai Net Miles Fiber Optics Technology Co., LTD.
OUI:249442*
ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
+OUI:249493*
+ ID_OUI_FROM_DATABASE=FibRSol Global Network Limited
+
+OUI:249494*
+ ID_OUI_FROM_DATABASE=Hong Kong Bouffalo Lab Limited
+
+OUI:2494CB*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:249504*
ID_OUI_FROM_DATABASE=SFR
OUI:249EAB*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:249F89*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:24A074*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:24A43C*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+OUI:24A487*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:24A495*
ID_OUI_FROM_DATABASE=Thales Canada Inc.
OUI:280E8B*
ID_OUI_FROM_DATABASE=Beijing Spirit Technology Development Co., Ltd.
+OUI:280FC5*
+ ID_OUI_FROM_DATABASE=Beijing Leadsec Technology Co., Ltd.
+
OUI:28101B*
ID_OUI_FROM_DATABASE=MagnaCom
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:28A183*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:28A186*
ID_OUI_FROM_DATABASE=enblink
OUI:28AC9E*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:28AD18*
+ ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+
OUI:28AD3E*
ID_OUI_FROM_DATABASE=Shenzhen TONG BO WEI Technology CO.,LTD
OUI:28CFE9*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:28D044*
+ ID_OUI_FROM_DATABASE=Shenzhen Xinyin technology company
+
OUI:28D0CB*
ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd
OUI:28DB81*
ID_OUI_FROM_DATABASE=Shanghai Guao Electronic Technology Co., Ltd
+OUI:28DE65*
+ ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+
OUI:28DEE5*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:28E476*
ID_OUI_FROM_DATABASE=Pi-Coral
+OUI:28E5B0*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:28E608*
ID_OUI_FROM_DATABASE=Tokheim
OUI:2C073C*
ID_OUI_FROM_DATABASE=DEVLINE LIMITED
+OUI:2C0786*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:2C081C*
ID_OUI_FROM_DATABASE=OVH
OUI:2C4835E*
ID_OUI_FROM_DATABASE=IROOTECH TECHNOLOGY CO.,LTD
+OUI:2C4A11*
+ ID_OUI_FROM_DATABASE=Ciena Corporation
+
OUI:2C4CC6*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:302478*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:3024A9*
+ ID_OUI_FROM_DATABASE=HP Inc.
+
OUI:3027CF*
ID_OUI_FROM_DATABASE=Private
OUI:30317D*
ID_OUI_FROM_DATABASE=Hosiden Corporation
+OUI:303235*
+ ID_OUI_FROM_DATABASE=Qingdao Intelligent&Precise Electronics Co.,Ltd.
+
OUI:303294*
ID_OUI_FROM_DATABASE=W-IE-NE-R Plein & Baus GmbH
OUI:3055ED*
ID_OUI_FROM_DATABASE=Trex Network LLC
+OUI:305684*
+ ID_OUI_FROM_DATABASE=SHENZHEN YUNJI INTELLIGENT TECHNOLOGY CO.,LTD
+
OUI:305714*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:309C23*
ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD.
+OUI:309E1D*
+ ID_OUI_FROM_DATABASE=OHSUNG
+
OUI:309FFB*
ID_OUI_FROM_DATABASE=Ardomus Networks Corporation
+OUI:30A023*
+ ID_OUI_FROM_DATABASE=ROCK PATH S.R.L
+
OUI:30A1FA*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:30AEF6*
ID_OUI_FROM_DATABASE=Radio Mobile Access
+OUI:30AFCE*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:30B164*
ID_OUI_FROM_DATABASE=Power Electronics International Inc.
OUI:30B216*
- ID_OUI_FROM_DATABASE=ABB Power Grids Germany AG – Grid Automation
+ ID_OUI_FROM_DATABASE=Hitachi ABB Power Grids – Grid Automation
OUI:30B237*
ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd.
OUI:30B9B0*
ID_OUI_FROM_DATABASE=Intracom Asia Co., Ltd
+OUI:30BE3B*
+ ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation
+
OUI:30C01B*
ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
OUI:30C3D9*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:30C507*
ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
OUI:30CDA7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:30D042*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:30D16B*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
OUI:30D6C9*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:30D941*
+ ID_OUI_FROM_DATABASE=Raydium Semiconductor Corp.
+
OUI:30D9D9*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:30E171*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:30E283*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:30E37A*
ID_OUI_FROM_DATABASE=Intel Corporate
ID_OUI_FROM_DATABASE=Eclipse Information Technologies
OUI:34049E9*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Church & Dwight Co., Inc.
OUI:34049EA*
ID_OUI_FROM_DATABASE=i3 International Inc.
ID_OUI_FROM_DATABASE=Eginity, Inc.
OUI:34049EC*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=ClearCaptions LLC
OUI:34049ED*
ID_OUI_FROM_DATABASE=uikismart
OUI:341B22*
ID_OUI_FROM_DATABASE=Grandbeing Technology Co., Ltd
+OUI:341CF0*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:341E6B*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:342AF1*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:342B70*
+ ID_OUI_FROM_DATABASE=Arris
+
OUI:342CC4*
ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc.
ID_OUI_FROM_DATABASE=Enecsys Ltd
OUI:34C731*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:34C803*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:34D2C4*
ID_OUI_FROM_DATABASE=RENA GmbH Print Systeme
+OUI:34D693*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:34D712*
ID_OUI_FROM_DATABASE=Smartisan Digital Co., Ltd
OUI:387862*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
+OUI:387A3C*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:387B47*
ID_OUI_FROM_DATABASE=AKELA, Inc.
OUI:389592*
ID_OUI_FROM_DATABASE=Beijing Tendyron Corporation
+OUI:3897A4*
+ ID_OUI_FROM_DATABASE=ELECOM CO.,LTD.
+
OUI:3897D6*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
OUI:3898D8*
ID_OUI_FROM_DATABASE=MERITECH CO.,LTD
+OUI:3898E9*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:389AF6*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications
OUI:38C096*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:38C2BA*
ID_OUI_FROM_DATABASE=CCTV NEOTECH
OUI:38C9A9*
ID_OUI_FROM_DATABASE=SMART High Reliability Solutions, Inc.
+OUI:38CA73*
+ ID_OUI_FROM_DATABASE=Shenzhen MiaoMing Intelligent Technology Co.,Ltd
+
OUI:38CA97*
ID_OUI_FROM_DATABASE=Contour Design LLC
OUI:38FB14*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:38FC98*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:38FDFE0*
ID_OUI_FROM_DATABASE=Edge I&D Co., Ltd.
OUI:3C6104*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:3C6105*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:3C6200*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:3CA348*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:3CA37E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:3CA581*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
OUI:3CBD3E*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd.
+OUI:3CBDC5*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:3CBDD8*
ID_OUI_FROM_DATABASE=LG ELECTRONICS INC
OUI:3CD16E*
ID_OUI_FROM_DATABASE=Telepower Communication Co., Ltd
+OUI:3CD2E5*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:3CD4D6*
ID_OUI_FROM_DATABASE=WirelessWERX, Inc
OUI:3CDFBD*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:3CE038*
+ ID_OUI_FROM_DATABASE=Plumeria Networks, Inc.
+
OUI:3CE072*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:4013D9*
ID_OUI_FROM_DATABASE=Global ES
+OUI:4014AD*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:401597*
ID_OUI_FROM_DATABASE=Protect America, Inc.
OUI:401B5F*
ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
+OUI:401C83*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:401D59*
ID_OUI_FROM_DATABASE=Biometric Associates, LP
OUI:408BF6*
ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co., Ltd
+OUI:408C4C*
+ ID_OUI_FROM_DATABASE=Shenzhen MiaoMing Intelligent Technology Co.,Ltd
+
OUI:408D5C*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:40A93F*
ID_OUI_FROM_DATABASE=Pivotal Commware, Inc.
+OUI:40A9CF*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:40AA56*
ID_OUI_FROM_DATABASE=China Dragon Technology Limited
OUI:40B4F0*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:40B5C1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:40B688*
ID_OUI_FROM_DATABASE=LEGIC Identsystems AG
OUI:40D40E*
ID_OUI_FROM_DATABASE=Biodata Ltd
+OUI:40D4BD*
+ ID_OUI_FROM_DATABASE=SK Networks Service CO., LTD.
+
OUI:40D559*
ID_OUI_FROM_DATABASE=MICRO S.E.R.I.
OUI:4439C4*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
+OUI:443B32*
+ ID_OUI_FROM_DATABASE=Intelbras
+
OUI:443C88*
ID_OUI_FROM_DATABASE=FICOSA MAROC INTERNATIONAL
OUI:44CD0E*
ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+OUI:44CE3A*
+ ID_OUI_FROM_DATABASE=Jiangsu Huacun Electronic Technology Co., Ltd.
+
OUI:44CE7D*
ID_OUI_FROM_DATABASE=SFR
OUI:44E8A5*
ID_OUI_FROM_DATABASE=Myreka Technologies Sdn. Bhd.
+OUI:44E968*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:44E9DD*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:44F034*
ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD.
+OUI:44F21B*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:44F436*
ID_OUI_FROM_DATABASE=zte corporation
OUI:482335*
ID_OUI_FROM_DATABASE=Dialog Semiconductor Hellas SA
+OUI:482567*
+ ID_OUI_FROM_DATABASE=Poly
+
OUI:48262C*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:486FD2*
ID_OUI_FROM_DATABASE=StorSimple Inc
+OUI:48701E*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:487119*
ID_OUI_FROM_DATABASE=SGB GROUP LTD.
OUI:488AD2*
ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+OUI:488B0A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:488D36*
ID_OUI_FROM_DATABASE=Arcadyan Corporation
OUI:48A493*
ID_OUI_FROM_DATABASE=TAIYO YUDEN CO.,LTD
+OUI:48A516*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:48A5E7*
ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
OUI:48D875*
ID_OUI_FROM_DATABASE=China TransInfo Technology Co., Ltd
+OUI:48D890*
+ ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+
OUI:48D8FE*
ID_OUI_FROM_DATABASE=ClarIDy Solutions, Inc.
OUI:48EE86*
ID_OUI_FROM_DATABASE=UTStarcom (China) Co.,Ltd
+OUI:48EF61*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:48F027*
ID_OUI_FROM_DATABASE=Chengdu newifi Co.,Ltd
OUI:48F07B*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:48F17F*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:4C0143*
ID_OUI_FROM_DATABASE=eero inc.
+OUI:4C0220*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:4C022E*
ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD
OUI:4C1FCC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:4C20B8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:4C2113*
ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd.
OUI:4C3B74*
ID_OUI_FROM_DATABASE=VOGTEC(H.K.) Co., Ltd
+OUI:4C3BDF*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
OUI:4C3C16*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:4C5262*
ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH
+OUI:4C52EC*
+ ID_OUI_FROM_DATABASE=SOLARWATT GmbH
+
OUI:4C5427*
ID_OUI_FROM_DATABASE=Linepro Sp. z o.o.
OUI:4C6C13*
ID_OUI_FROM_DATABASE=IoT Company Solucoes Tecnologicas Ltda
+OUI:4C6D58*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:4C6E6E*
ID_OUI_FROM_DATABASE=Comnect Technology CO.,LTD
OUI:4CEEB0*
ID_OUI_FROM_DATABASE=SHC Netzwerktechnik GmbH
+OUI:4CEF56*
+ ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited
+
OUI:4CEFC0*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:4CFB45*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:4CFBF4*
+ ID_OUI_FROM_DATABASE=Optimal Audio Ltd
+
OUI:4CFBFE*
ID_OUI_FROM_DATABASE=Sercomm Japan Corporation
OUI:502ECE*
ID_OUI_FROM_DATABASE=Asahi Electronics Co.,Ltd
+OUI:502F9B*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:502FA8*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:508D6F*
ID_OUI_FROM_DATABASE=CHAHOO Limited
+OUI:508E49*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:508F4C*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:50A4D0E*
ID_OUI_FROM_DATABASE=Sagetech Corporation
+OUI:50A5DC*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:50A67F*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:549FAE*
ID_OUI_FROM_DATABASE=iBASE Gaming Inc
+OUI:549FC6*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:54A04F*
ID_OUI_FROM_DATABASE=t-mac Technologies Ltd
ID_OUI_FROM_DATABASE=Avaya Inc
OUI:5816D7*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:58170C*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:582059*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:58208A0*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:58208A2*
+ ID_OUI_FROM_DATABASE=MARS DIGI TECH CO .,LTD
+
+OUI:58208A3*
+ ID_OUI_FROM_DATABASE=Aggregate Co.,Ltd.
+
OUI:58208A4*
ID_OUI_FROM_DATABASE=TRING
+OUI:58208A5*
+ ID_OUI_FROM_DATABASE=JIA HUANG JHAN YE CO.,LTD
+
+OUI:58208A6*
+ ID_OUI_FROM_DATABASE=Shangyin Intelligence Technology Shandong Co.,Ltd
+
+OUI:58208A7*
+ ID_OUI_FROM_DATABASE=pureLiFi Ltd
+
OUI:58208A8*
ID_OUI_FROM_DATABASE=SAMIL CTS Co., Ltd.
OUI:58208A9*
ID_OUI_FROM_DATABASE=Suzhou Ruilisi Technology Ltd.
+OUI:58208AA*
+ ID_OUI_FROM_DATABASE=Conductix-Wampfler
+
+OUI:58208AB*
+ ID_OUI_FROM_DATABASE=Infodev Electronic Designers Intl.
+
+OUI:58208AD*
+ ID_OUI_FROM_DATABASE=SAMBO HITECH
+
+OUI:58208AE*
+ ID_OUI_FROM_DATABASE=UPM Technology, Inc
+
OUI:5820B1*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:58238C*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+OUI:582429*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:582575*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:58605F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:5860D8*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:586163*
ID_OUI_FROM_DATABASE=Quantum Networks (SG) Pte. Ltd.
OUI:5885E9*
ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd
+OUI:588694*
+ ID_OUI_FROM_DATABASE=EFM Networks
+
OUI:58874C*
ID_OUI_FROM_DATABASE=LITE-ON CLEAN ENERGY TECHNOLOGY CORP.
OUI:5894CF*
ID_OUI_FROM_DATABASE=Vertex Standard LMR, Inc.
+OUI:5895D80*
+ ID_OUI_FROM_DATABASE=Shenzhen DOOGEE Hengtong Technology CO.,LTD
+
+OUI:5895D81*
+ ID_OUI_FROM_DATABASE=shenzhen UDD Technologies,co.,Ltd
+
+OUI:5895D82*
+ ID_OUI_FROM_DATABASE=Sercomm Corporation.
+
+OUI:5895D83*
+ ID_OUI_FROM_DATABASE=Tonnet Telecommunication International Co., Ltd.
+
+OUI:5895D84*
+ ID_OUI_FROM_DATABASE=Unity Surveillance, Inc.
+
+OUI:5895D85*
+ ID_OUI_FROM_DATABASE=elgris UG
+
+OUI:5895D86*
+ ID_OUI_FROM_DATABASE=Norgren Manufacturing Co., Ltd.
+
+OUI:5895D87*
+ ID_OUI_FROM_DATABASE=Epiphan Systems Inc
+
+OUI:5895D88*
+ ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd.
+
+OUI:5895D89*
+ ID_OUI_FROM_DATABASE=Loftie
+
+OUI:5895D8A*
+ ID_OUI_FROM_DATABASE=Peak Communications Limited
+
+OUI:5895D8B*
+ ID_OUI_FROM_DATABASE=SuZhou Ruishengwei Intelligent Technology Co.,Ltd
+
+OUI:5895D8C*
+ ID_OUI_FROM_DATABASE=LOCTEK ERGONOMIC TECHNOLOGY CORP.
+
+OUI:5895D8D*
+ ID_OUI_FROM_DATABASE=Alunos AG
+
+OUI:5895D8E*
+ ID_OUI_FROM_DATABASE=Gmv sistemas SAU
+
OUI:58961D*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:58D08F*
ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group
+OUI:58D349*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:58D50A*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
ID_OUI_FROM_DATABASE=HANGZHOU DANGBEI NETWORK TECH.Co.,Ltd
OUI:58E8760*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Zhuhai Raysharp Technology Co.,Ltd
OUI:58E8761*
ID_OUI_FROM_DATABASE=Beijing Perabytes IS Technology Co., Ltd
OUI:5C0FFB*
ID_OUI_FROM_DATABASE=Amino Communications Ltd
+OUI:5C10C5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:5C1193*
ID_OUI_FROM_DATABASE=Seal One AG
ID_OUI_FROM_DATABASE=Alpha Networks Inc.
OUI:5C3400*
- ID_OUI_FROM_DATABASE=HISENSE VISUAL TECHNOLOGY CO.,LTD
+ ID_OUI_FROM_DATABASE=Hisense Electric Co.,Ltd
OUI:5C353B*
ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc.
OUI:5C5F67*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:5C6199*
+ ID_OUI_FROM_DATABASE=CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.
+
OUI:5C63BF*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:5C86C1*
ID_OUI_FROM_DATABASE=DONGGUAN SOLUM ELECTRONICS CO.,LTD
+OUI:5C8730*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:5C8778*
ID_OUI_FROM_DATABASE=Cybertelbridge co.,ltd
OUI:5CBD9E*
ID_OUI_FROM_DATABASE=HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED
+OUI:5CC0A0*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:5CC1D7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:5CEB68*
ID_OUI_FROM_DATABASE=Cheerstar Technology Co., Ltd
+OUI:5CED8C*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
OUI:5CEE79*
ID_OUI_FROM_DATABASE=Global Digitech Co LTD
OUI:5CF9F0*
ID_OUI_FROM_DATABASE=Atomos Engineering P/L
+OUI:5CF9FD*
+ ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+
OUI:5CFAFB*
ID_OUI_FROM_DATABASE=Acubit
+OUI:5CFB3A*
+ ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+
OUI:5CFB7C*
ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
OUI:603553*
ID_OUI_FROM_DATABASE=Buwon Technology
+OUI:603573*
+ ID_OUI_FROM_DATABASE=Earda Technologies co Ltd
+
OUI:6035C0*
ID_OUI_FROM_DATABASE=SFR
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:60380E*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:6038E0*
ID_OUI_FROM_DATABASE=Belkin International Inc.
OUI:603A7C*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:603CEE*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
OUI:603D26*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
OUI:606ED0*
ID_OUI_FROM_DATABASE=SEAL AG
+OUI:607072*
+ ID_OUI_FROM_DATABASE=SHENZHEN HONGDE SMART LINK TECHNOLOGY CO., LTD
+
OUI:6070C0*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:6077E2*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:607EA4*
+ ID_OUI_FROM_DATABASE=Shanghai Imilab Technology Co.Ltd
+
OUI:607EC9*
ID_OUI_FROM_DATABASE=Apple, Inc.
ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
OUI:60812B*
- ID_OUI_FROM_DATABASE=Custom Control Concepts
+ ID_OUI_FROM_DATABASE=Astronics Custom Control Concepts
OUI:6081F9*
ID_OUI_FROM_DATABASE=Helium Systems, Inc
OUI:60BEB5*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:60BEC4*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:60C0BF*
ID_OUI_FROM_DATABASE=ON Semiconductor
OUI:60DB2A*
ID_OUI_FROM_DATABASE=HNS
+OUI:60DB98*
+ ID_OUI_FROM_DATABASE=Calix Inc.
+
OUI:60DE35*
ID_OUI_FROM_DATABASE=GITSN, Inc.
OUI:6402CB*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:64037F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:6405BE*
ID_OUI_FROM_DATABASE=NEW LIGHT LED
OUI:64209F*
ID_OUI_FROM_DATABASE=Tilgin AB
+OUI:6420E0*
+ ID_OUI_FROM_DATABASE=T3 Technology Co., Ltd.
+
OUI:642184*
ID_OUI_FROM_DATABASE=Nippon Denki Kagaku Co.,LTD
OUI:647791*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:647924*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:6479A7*
ID_OUI_FROM_DATABASE=Phison Electronics Corp.
OUI:64A0E7*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:64A200*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:64A232*
ID_OUI_FROM_DATABASE=OOO Samlight
+OUI:64A28A*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:64A2F9*
ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:64D4BD*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:64D4DA*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:683E02*
ID_OUI_FROM_DATABASE=SIEMENS AG, Digital Factory, Motion Control System
+OUI:683E26*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:683E34*
ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd.
OUI:6843D7*
ID_OUI_FROM_DATABASE=Agilecom Photonics Solutions Guangdong Limited
+OUI:684571*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:6845F1*
ID_OUI_FROM_DATABASE=TOSHIBA CLIENT SOLUTIONS CO., LTD.
OUI:687251*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+OUI:6872C3*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:6872DC*
ID_OUI_FROM_DATABASE=CETORY.TV Company Limited
OUI:68784C*
ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:6879120*
+ ID_OUI_FROM_DATABASE=PCTEL, Inc.
+
+OUI:6879121*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:6879122*
+ ID_OUI_FROM_DATABASE=CNDI CO.,LTD
+
+OUI:6879123*
+ ID_OUI_FROM_DATABASE=Stephan Electronics SARL
+
+OUI:6879124*
+ ID_OUI_FROM_DATABASE=McDonald's Corporation
+
+OUI:6879125*
+ ID_OUI_FROM_DATABASE=Copper Labs, Inc.
+
+OUI:6879126*
+ ID_OUI_FROM_DATABASE=APPOTRONICS CO., LTD
+
+OUI:6879127*
+ ID_OUI_FROM_DATABASE=Babbit and Friends, SIA
+
+OUI:6879128*
+ ID_OUI_FROM_DATABASE=ShangHai Aigentoo Information Technology Co., Ltd
+
+OUI:6879129*
+ ID_OUI_FROM_DATABASE=LEAPS s.r.o.
+
+OUI:687912A*
+ ID_OUI_FROM_DATABASE=Wingtech Mobile Communications Co., Ltd.
+
+OUI:687912B*
+ ID_OUI_FROM_DATABASE=Swisscom Broadcast Ltd
+
+OUI:687912C*
+ ID_OUI_FROM_DATABASE=Globus Infocom Limited
+
+OUI:687912D*
+ ID_OUI_FROM_DATABASE=Neurolab
+
+OUI:687912E*
+ ID_OUI_FROM_DATABASE=Ametek Solidstate Controls
+
OUI:687924*
ID_OUI_FROM_DATABASE=ELS-GmbH & Co. KG
OUI:68D482*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+OUI:68D48B*
+ ID_OUI_FROM_DATABASE=Hailo Technologies Ltd.
+
OUI:68D6ED*
ID_OUI_FROM_DATABASE=GooWi Wireless Technology Co., Limited
OUI:6C090A*
ID_OUI_FROM_DATABASE=GEMATICA SRL
+OUI:6C09BF*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:6C09D6*
ID_OUI_FROM_DATABASE=Digiquest Electronics LTD
OUI:6C0D34*
ID_OUI_FROM_DATABASE=Nokia
+OUI:6C0DC4*
+ ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd.
+
OUI:6C0E0D*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:6C0F6A*
ID_OUI_FROM_DATABASE=JDC Tech Co., Ltd.
+OUI:6C1414*
+ ID_OUI_FROM_DATABASE=BUJEON ELECTRONICS Co,.Ltd
+
+OUI:6C146E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:6C14F7*
ID_OUI_FROM_DATABASE=Erhardt+Leimer GmbH
OUI:6C19C0*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:6C1A75*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:6C1C71*
ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
OUI:6C1E90*
ID_OUI_FROM_DATABASE=Hansol Technics Co., Ltd.
+OUI:6C1ED7*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:6C2056*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:6C2CDC*
ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
+OUI:6C2D24*
+ ID_OUI_FROM_DATABASE=Zhen Shi Information Technology (Shanghai) Co., Ltd.
+
OUI:6C2E33*
ID_OUI_FROM_DATABASE=Accelink Technologies Co.,Ltd.
OUI:6C750D*
ID_OUI_FROM_DATABASE=WiFiSONG
+OUI:6C7637*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:6C7660*
ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
OUI:6C9E7C*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:6CA0B4*
+ ID_OUI_FROM_DATABASE=BSkyB Ltd
+
OUI:6CA100*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:6CAD3F*
ID_OUI_FROM_DATABASE=Hubbell Building Automation, Inc.
+OUI:6CADAD*
+ ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+
OUI:6CADEF*
ID_OUI_FROM_DATABASE=KZ Broadband Technologies, Ltd.
OUI:6CB7F4*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:6CB881*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:6CB9C5*
ID_OUI_FROM_DATABASE=Delta Networks, Inc.
OUI:6CE873*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:6CE874*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:6CE8C6*
ID_OUI_FROM_DATABASE=Earda Technologies co Ltd
OUI:703A0E*
ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+OUI:703A2D*
+ ID_OUI_FROM_DATABASE=Shenzhen V-Link Technology CO., LTD.
+
OUI:703A51*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:703EAC*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:7040FF*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:7041B7*
ID_OUI_FROM_DATABASE=Edwards Lifesciences LLC
OUI:708F47*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:7090B7*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:70918F*
ID_OUI_FROM_DATABASE=Weber-Stephen Products LLC
OUI:70B08C*
ID_OUI_FROM_DATABASE=Shenou Communication Equipment Co.,Ltd
+OUI:70B13D*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:70B14E*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:70B3D5017*
ID_OUI_FROM_DATABASE=FTG Corporation
+OUI:70B3D5018*
+ ID_OUI_FROM_DATABASE=DELITECH GROUP
+
OUI:70B3D5019*
ID_OUI_FROM_DATABASE=Transit Solutions, LLC.
OUI:70B3D509B*
ID_OUI_FROM_DATABASE=Jacarta Ltd
+OUI:70B3D509C*
+ ID_OUI_FROM_DATABASE=Cardinal Kinetic
+
OUI:70B3D509D*
ID_OUI_FROM_DATABASE=PuS GmbH und Co. KG
OUI:70B3D50F4*
ID_OUI_FROM_DATABASE=Visual Robotics
+OUI:70B3D50F5*
+ ID_OUI_FROM_DATABASE=Season Electronics Ltd
+
OUI:70B3D50F6*
ID_OUI_FROM_DATABASE=KSE GmbH
OUI:70B3D510A*
ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY
+OUI:70B3D510B*
+ ID_OUI_FROM_DATABASE=SECUREAN CO.,Ltd
+
OUI:70B3D510C*
ID_OUI_FROM_DATABASE=Vocality International Ltd
OUI:70B3D5115*
ID_OUI_FROM_DATABASE=Welltec Corp.
+OUI:70B3D5116*
+ ID_OUI_FROM_DATABASE=Momentum Data Systems
+
OUI:70B3D5117*
ID_OUI_FROM_DATABASE=SysCom Automationstechnik GmbH
+OUI:70B3D5118*
+ ID_OUI_FROM_DATABASE=Macromatic Industrial Controls, Inc.
+
OUI:70B3D5119*
ID_OUI_FROM_DATABASE=Private
OUI:70B3D5155*
ID_OUI_FROM_DATABASE=Sanwa New Tec Co.,Ltd
+OUI:70B3D5156*
+ ID_OUI_FROM_DATABASE=Rivercity Innovations Ltd.
+
OUI:70B3D5157*
ID_OUI_FROM_DATABASE=Shanghai Jupper Technology Co.Ltd
OUI:70B3D5175*
ID_OUI_FROM_DATABASE=Akribis Systems
+OUI:70B3D5176*
+ ID_OUI_FROM_DATABASE=Larraioz Elektronika
+
OUI:70B3D5177*
ID_OUI_FROM_DATABASE=Wired Broadcast Ltd
OUI:70B3D5194*
ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J.
+OUI:70B3D5195*
+ ID_OUI_FROM_DATABASE=Ci4Rail
+
OUI:70B3D5197*
ID_OUI_FROM_DATABASE=Lattech Systems Pty Ltd
OUI:70B3D51A1*
ID_OUI_FROM_DATABASE=HMicro Inc
+OUI:70B3D51A2*
+ ID_OUI_FROM_DATABASE=Xirgo Technologies LLC
+
OUI:70B3D51A3*
ID_OUI_FROM_DATABASE=Telairity Semiconductor
OUI:70B3D51B9*
ID_OUI_FROM_DATABASE=RELISTE Ges.m.b.H.
+OUI:70B3D51BA*
+ ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
+
OUI:70B3D51BB*
ID_OUI_FROM_DATABASE=EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA
OUI:70B3D523C*
ID_OUI_FROM_DATABASE=Quasonix, LLC
+OUI:70B3D523D*
+ ID_OUI_FROM_DATABASE=Circle Consult ApS
+
OUI:70B3D523E*
ID_OUI_FROM_DATABASE=Tornado Modular Systems
OUI:70B3D5246*
ID_OUI_FROM_DATABASE=Saline Lectronics, Inc.
+OUI:70B3D5247*
+ ID_OUI_FROM_DATABASE=Satsky Communication Equipment Co.,Ltd.
+
OUI:70B3D5248*
ID_OUI_FROM_DATABASE=GL TECH CO.,LTD
OUI:70B3D525D*
ID_OUI_FROM_DATABASE=Mimo Networks
+OUI:70B3D525E*
+ ID_OUI_FROM_DATABASE=RFHIC
+
OUI:70B3D525F*
ID_OUI_FROM_DATABASE=COPPERNIC SAS
OUI:70B3D527A*
ID_OUI_FROM_DATABASE=TD ECOPHISIKA
+OUI:70B3D527B*
+ ID_OUI_FROM_DATABASE=DAVE SRL
+
OUI:70B3D527C*
ID_OUI_FROM_DATABASE=MOTION LIB,Inc.
OUI:70B3D52DE*
ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+OUI:70B3D52DF*
+ ID_OUI_FROM_DATABASE=EASTERN SCIENCE & TECHNOLOGY CO., LTD
+
OUI:70B3D52E0*
ID_OUI_FROM_DATABASE=Peter Huber
OUI:70B3D5321*
ID_OUI_FROM_DATABASE=Yite technology
+OUI:70B3D5322*
+ ID_OUI_FROM_DATABASE=PuS GmbH und Co. KG
+
OUI:70B3D5323*
ID_OUI_FROM_DATABASE=TATTILE SRL
OUI:70B3D535A*
ID_OUI_FROM_DATABASE=Applied Radar, Inc.
+OUI:70B3D535B*
+ ID_OUI_FROM_DATABASE=Nuance Hearing Ltd.
+
OUI:70B3D535C*
ID_OUI_FROM_DATABASE=ACS electronics srl
ID_OUI_FROM_DATABASE=Adel System srl
OUI:70B3D5376*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Magenta Labs, Inc.
OUI:70B3D5377*
ID_OUI_FROM_DATABASE=Monnit Corporation
OUI:70B3D537F*
ID_OUI_FROM_DATABASE=IDS Innomic GmbH
+OUI:70B3D5380*
+ ID_OUI_FROM_DATABASE=SeaTech Intelligent Technology (Shanghai) Co., LTD
+
OUI:70B3D5381*
ID_OUI_FROM_DATABASE=CRDE
OUI:70B3D5394*
ID_OUI_FROM_DATABASE=Romteck Australia
+OUI:70B3D5395*
+ ID_OUI_FROM_DATABASE=ICsec S.A.
+
OUI:70B3D5396*
ID_OUI_FROM_DATABASE=CTG sp. z o. o.
OUI:70B3D53A1*
ID_OUI_FROM_DATABASE=Reckeen HDP Media sp. z o.o. sp. k.
+OUI:70B3D53A2*
+ ID_OUI_FROM_DATABASE=Daifuku CO., Ltd.
+
OUI:70B3D53A3*
ID_OUI_FROM_DATABASE=CDS Institute of Management Strategy, Inc.
OUI:70B3D53A5*
ID_OUI_FROM_DATABASE=KMtronic ltd
+OUI:70B3D53A6*
+ ID_OUI_FROM_DATABASE=myenergi Ltd
+
OUI:70B3D53A7*
ID_OUI_FROM_DATABASE=Varikorea
OUI:70B3D53AA*
ID_OUI_FROM_DATABASE=RCATSONE
+OUI:70B3D53AB*
+ ID_OUI_FROM_DATABASE=Camozzi Automation SpA
+
OUI:70B3D53AC*
ID_OUI_FROM_DATABASE=RF-Tuote Oy
OUI:70B3D53C7*
ID_OUI_FROM_DATABASE=SOFTCREATE CORP.
+OUI:70B3D53C8*
+ ID_OUI_FROM_DATABASE=ABC Electric Co.
+
OUI:70B3D53C9*
ID_OUI_FROM_DATABASE=Duerkopp-Adler
OUI:70B3D53D0*
ID_OUI_FROM_DATABASE=ORtek Technology, Inc.
+OUI:70B3D53D1*
+ ID_OUI_FROM_DATABASE=Imenco Ltd
+
OUI:70B3D53D2*
ID_OUI_FROM_DATABASE=Imagine Inc.
OUI:70B3D53ED*
ID_OUI_FROM_DATABASE=Ultra Electronics Sonar System Division
+OUI:70B3D53EE*
+ ID_OUI_FROM_DATABASE=Laser Imagineering Vertriebs GmbH
+
OUI:70B3D53EF*
ID_OUI_FROM_DATABASE=Vtron Pty Ltd
OUI:70B3D540B*
ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L.
+OUI:70B3D540C*
+ ID_OUI_FROM_DATABASE=Tornado Modular Systems
+
OUI:70B3D540D*
ID_OUI_FROM_DATABASE=Grupo Epelsa S.L.
OUI:70B3D5422*
ID_OUI_FROM_DATABASE=SUS Corporation
+OUI:70B3D5423*
+ ID_OUI_FROM_DATABASE=Harman Connected Services Corporation India Pvt. Ltd.
+
OUI:70B3D5424*
ID_OUI_FROM_DATABASE=Underground Systems, Inc.
OUI:70B3D544E*
ID_OUI_FROM_DATABASE=Solace Systems Inc.
+OUI:70B3D544F*
+ ID_OUI_FROM_DATABASE=Velvac Incorporated
+
+OUI:70B3D5453*
+ ID_OUI_FROM_DATABASE=Foerster-Technik GmbH
+
OUI:70B3D5454*
ID_OUI_FROM_DATABASE=Golding Audio Ltd
OUI:70B3D547C*
ID_OUI_FROM_DATABASE=Par-Tech, Inc.
+OUI:70B3D547D*
+ ID_OUI_FROM_DATABASE=Shenyang TECHE Technology Co.,Ltd
+
OUI:70B3D547E*
ID_OUI_FROM_DATABASE=Fiber Optika Technologies Pvt. Ltd.
OUI:70B3D5482*
ID_OUI_FROM_DATABASE=Aeryon Labs Inc
+OUI:70B3D5483*
+ ID_OUI_FROM_DATABASE=LITUM BILGI TEKNOLOJILERI SAN. VE TIC. A.S.
+
OUI:70B3D5484*
ID_OUI_FROM_DATABASE=Hermann Sewerin GmbH
+OUI:70B3D5485*
+ ID_OUI_FROM_DATABASE=CLARESYS LIMITED
+
OUI:70B3D5486*
ID_OUI_FROM_DATABASE=ChongQing JianTao Technology Co., Ltd.
OUI:70B3D549B*
ID_OUI_FROM_DATABASE=Algodue Elettronica Srl
+OUI:70B3D549C*
+ ID_OUI_FROM_DATABASE=AC Power Corp.
+
OUI:70B3D549D*
ID_OUI_FROM_DATABASE=Shenzhen Chanslink Network Technology Co., Ltd
OUI:70B3D54C2*
ID_OUI_FROM_DATABASE=hera Laborsysteme GmbH
+OUI:70B3D54C3*
+ ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG
+
OUI:70B3D54C4*
ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies
OUI:70B3D54D6*
ID_OUI_FROM_DATABASE=Operational Technology Solutions
+OUI:70B3D54D7*
+ ID_OUI_FROM_DATABASE=Technological Ray GmbH
+
OUI:70B3D54D8*
ID_OUI_FROM_DATABASE=Versilis Inc.
OUI:70B3D54E1*
ID_OUI_FROM_DATABASE=Grupo Epelsa S.L.
+OUI:70B3D54E2*
+ ID_OUI_FROM_DATABASE=Transit Solutions, LLC.
+
OUI:70B3D54E3*
ID_OUI_FROM_DATABASE=adnexo GmbH
OUI:70B3D5551*
ID_OUI_FROM_DATABASE=infrachip
+OUI:70B3D5552*
+ ID_OUI_FROM_DATABASE=ALTIT.CO.,Ltd.
+
OUI:70B3D5553*
ID_OUI_FROM_DATABASE=TAALEX Systemtechnik GmbH
OUI:70B3D555F*
ID_OUI_FROM_DATABASE=Deep BV
+OUI:70B3D5561*
+ ID_OUI_FROM_DATABASE=Liberator Pty Ltd
+
+OUI:70B3D5562*
+ ID_OUI_FROM_DATABASE=JD Squared, Inc.
+
OUI:70B3D5563*
ID_OUI_FROM_DATABASE=Zhejiang Hao Teng Electronic Technology Co., Ltd.
OUI:70B3D5572*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5573*
+ ID_OUI_FROM_DATABASE=GEGA ELECTRONIQUE
+
OUI:70B3D5574*
ID_OUI_FROM_DATABASE=Cloud Intelligence Pty Ltd
OUI:70B3D558A*
ID_OUI_FROM_DATABASE=ITK Dr. Kassen GmbH
+OUI:70B3D558B*
+ ID_OUI_FROM_DATABASE=Williams Sound LLC
+
OUI:70B3D558C*
ID_OUI_FROM_DATABASE=OPTSYS
OUI:70B3D55D6*
ID_OUI_FROM_DATABASE=BMT Messtechnik Gmbh
+OUI:70B3D55D7*
+ ID_OUI_FROM_DATABASE=Clockwork Dog
+
OUI:70B3D55D8*
ID_OUI_FROM_DATABASE=LYNX Technik AG
OUI:70B3D55F4*
ID_OUI_FROM_DATABASE=FDSTiming
+OUI:70B3D55F5*
+ ID_OUI_FROM_DATABASE=Microvision
+
OUI:70B3D55F6*
ID_OUI_FROM_DATABASE=FreeFlight Systems
OUI:70B3D5618*
ID_OUI_FROM_DATABASE=Motec Pty Ltd
+OUI:70B3D5619*
+ ID_OUI_FROM_DATABASE=ZAO ZEO
+
OUI:70B3D561A*
ID_OUI_FROM_DATABASE=Rocket Lab Ltd.
OUI:70B3D5620*
ID_OUI_FROM_DATABASE=Orlaco Products B.V.
+OUI:70B3D5621*
+ ID_OUI_FROM_DATABASE=SERTEC SRL
+
+OUI:70B3D5622*
+ ID_OUI_FROM_DATABASE=PCS Inc.
+
OUI:70B3D5623*
ID_OUI_FROM_DATABASE=Beijing HuaLian Technology Co, Ltd.
+OUI:70B3D5624*
+ ID_OUI_FROM_DATABASE=EBE Mobility & Green Energy GmbH
+
OUI:70B3D5625*
ID_OUI_FROM_DATABASE=VX Instruments GmbH
OUI:70B3D5645*
ID_OUI_FROM_DATABASE=Project Decibel, Inc.
+OUI:70B3D5646*
+ ID_OUI_FROM_DATABASE=Xirgo Technologies LLC
+
OUI:70B3D5647*
ID_OUI_FROM_DATABASE=KZTA
OUI:70B3D5662*
ID_OUI_FROM_DATABASE=Icon Industrial Engineering
+OUI:70B3D5663*
+ ID_OUI_FROM_DATABASE=Intrinsic Group Limited
+
OUI:70B3D5664*
ID_OUI_FROM_DATABASE=Sankyo Intec co.,ltd
OUI:70B3D5667*
ID_OUI_FROM_DATABASE=CT Company
+OUI:70B3D5668*
+ ID_OUI_FROM_DATABASE=Öresundskraft AB
+
OUI:70B3D5669*
ID_OUI_FROM_DATABASE=Panoramic Power
OUI:70B3D56C3*
ID_OUI_FROM_DATABASE=BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD
+OUI:70B3D56C4*
+ ID_OUI_FROM_DATABASE=Veo Robotics, Inc.
+
OUI:70B3D56C5*
ID_OUI_FROM_DATABASE=CJSC «Russian telecom equipment company» (CJSC RTEC)
OUI:70B3D56C7*
ID_OUI_FROM_DATABASE=Becton Dickinson
+OUI:70B3D56C8*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
OUI:70B3D56C9*
ID_OUI_FROM_DATABASE=Redstone Sunshine(Beijing)Technology Co.,Ltd.
OUI:70B3D56E1*
ID_OUI_FROM_DATABASE=Shanghai Holystar Information Technology Co.,Ltd
+OUI:70B3D56E2*
+ ID_OUI_FROM_DATABASE=E-Controls
+
OUI:70B3D56E3*
ID_OUI_FROM_DATABASE=SHEN ZHEN QLS ELECTRONIC TECHNOLOGY CO.,LTD.
OUI:70B3D56EE*
ID_OUI_FROM_DATABASE=HANKOOK CTEC CO,. LTD.
+OUI:70B3D56EF*
+ ID_OUI_FROM_DATABASE=Beringar
+
OUI:70B3D56F0*
ID_OUI_FROM_DATABASE=iTelaSoft Pvt Ltd
OUI:70B3D571C*
ID_OUI_FROM_DATABASE=Konzept Informationssysteme GmbH
+OUI:70B3D571D*
+ ID_OUI_FROM_DATABASE=Connido Limited
+
OUI:70B3D571E*
ID_OUI_FROM_DATABASE=Motec Pty Ltd
ID_OUI_FROM_DATABASE=SD Biosensor
OUI:70B3D5738*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=GRYPHON SECURE INC
OUI:70B3D5739*
ID_OUI_FROM_DATABASE=Zigencorp, Inc
OUI:70B3D579B*
ID_OUI_FROM_DATABASE=Soniclean Pty Ltd
+OUI:70B3D579C*
+ ID_OUI_FROM_DATABASE=ADDE
+
OUI:70B3D579D*
ID_OUI_FROM_DATABASE=Editech Co., Ltd
OUI:70B3D57B0*
ID_OUI_FROM_DATABASE=Medisafe International
+OUI:70B3D57B1*
+ ID_OUI_FROM_DATABASE=Panamera
+
OUI:70B3D57B2*
ID_OUI_FROM_DATABASE=Rail Power Systems GmbH
OUI:70B3D57B4*
ID_OUI_FROM_DATABASE=Zumbach Electronic AG
+OUI:70B3D57B5*
+ ID_OUI_FROM_DATABASE=VOCAL Technologies Ltd.
+
OUI:70B3D57B6*
ID_OUI_FROM_DATABASE=Amada Miyachi America Inc.
OUI:70B3D57BC*
ID_OUI_FROM_DATABASE=FIRST RF Corporation
+OUI:70B3D57BD*
+ ID_OUI_FROM_DATABASE=TableConnect GmbH
+
OUI:70B3D57BE*
ID_OUI_FROM_DATABASE=Phytron GmbH
OUI:70B3D57D7*
ID_OUI_FROM_DATABASE=Gedomo GmbH
+OUI:70B3D57D8*
+ ID_OUI_FROM_DATABASE=Nuand LLC
+
OUI:70B3D57D9*
ID_OUI_FROM_DATABASE=ATOM GIKEN Co.,Ltd.
ID_OUI_FROM_DATABASE=Xerox International Partners
OUI:70B3D57EC*
- ID_OUI_FROM_DATABASE=GRIDSMART Technologies
+ ID_OUI_FROM_DATABASE=Cubic ITS, Inc. dba GRIDSMART Technologies
OUI:70B3D57ED*
ID_OUI_FROM_DATABASE=The Things Network Foundation
ID_OUI_FROM_DATABASE=CRAVIS CO., LIMITED
OUI:70B3D57F0*
- ID_OUI_FROM_DATABASE=Yokogawa Denshikiki Co.,Ltd
+ ID_OUI_FROM_DATABASE=YDK Technologies Co.,Ltd
OUI:70B3D57F1*
ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc.
OUI:70B3D5805*
ID_OUI_FROM_DATABASE=Eurotronik Kranj d.o.o.
+OUI:70B3D5806*
+ ID_OUI_FROM_DATABASE=International Super Computer Co., Ltd.
+
OUI:70B3D5807*
ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak
OUI:70B3D583C*
ID_OUI_FROM_DATABASE=Sinoembed
+OUI:70B3D583D*
+ ID_OUI_FROM_DATABASE=Gentec
+
OUI:70B3D583E*
ID_OUI_FROM_DATABASE=The Dini Group, La Jolla inc.
OUI:70B3D5858*
ID_OUI_FROM_DATABASE=Hubbell Power Systems
+OUI:70B3D5859*
+ ID_OUI_FROM_DATABASE=HAN CHANG
+
OUI:70B3D585A*
ID_OUI_FROM_DATABASE=BRUSHIES
OUI:70B3D5882*
ID_OUI_FROM_DATABASE=SIMON TECH, S.L.
+OUI:70B3D5883*
+ ID_OUI_FROM_DATABASE=Contec Americas Inc.
+
OUI:70B3D5884*
ID_OUI_FROM_DATABASE=LG Electronics
OUI:70B3D58B4*
ID_OUI_FROM_DATABASE=Scenario Automation
+OUI:70B3D58B5*
+ ID_OUI_FROM_DATABASE=xTom GmbH
+
+OUI:70B3D58B6*
+ ID_OUI_FROM_DATABASE=Eldes Ltd
+
OUI:70B3D58B7*
ID_OUI_FROM_DATABASE=Contec Americas Inc.
OUI:70B3D58D3*
ID_OUI_FROM_DATABASE=PERFORMANCE CONTROLS, INC.
+OUI:70B3D58D4*
+ ID_OUI_FROM_DATABASE=Guangdong Transtek Medical Electronics Co., Ltd.
+
OUI:70B3D58D5*
ID_OUI_FROM_DATABASE=Guangzhou Wanglu
OUI:70B3D58F8*
ID_OUI_FROM_DATABASE=Wi6labs
+OUI:70B3D58F9*
+ ID_OUI_FROM_DATABASE=IWS Global Pty Ltd
+
OUI:70B3D58FA*
ID_OUI_FROM_DATABASE=DEA SYSTEM SPA
+OUI:70B3D58FB*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
OUI:70B3D58FC*
ID_OUI_FROM_DATABASE=Mianjie Technology
OUI:70B3D5908*
ID_OUI_FROM_DATABASE=Accusonic
+OUI:70B3D5909*
+ ID_OUI_FROM_DATABASE=tetronik GmbH AEN
+
OUI:70B3D590A*
ID_OUI_FROM_DATABASE=Hangzhou SunTown Intelligent Science & Technology Co.,Ltd.
OUI:70B3D5920*
ID_OUI_FROM_DATABASE=SLAT
+OUI:70B3D5921*
+ ID_OUI_FROM_DATABASE=QDevil
+
OUI:70B3D5922*
ID_OUI_FROM_DATABASE=Adcole Space
OUI:70B3D593B*
ID_OUI_FROM_DATABASE=Changchun FAW Yanfeng Visteon Automotive Electronics.,Ltd.
+OUI:70B3D593D*
+ ID_OUI_FROM_DATABASE=Elmeasure India Pvt Ltd
+
OUI:70B3D593E*
ID_OUI_FROM_DATABASE=Systems With Intelligence Inc.
OUI:70B3D5961*
ID_OUI_FROM_DATABASE=TASK SISTEMAS DE COMPUTACAO LTDA
+OUI:70B3D5962*
+ ID_OUI_FROM_DATABASE=Senquire Pte. Ltd
+
OUI:70B3D5963*
ID_OUI_FROM_DATABASE=Triax A/S
OUI:70B3D5987*
ID_OUI_FROM_DATABASE=AXIS CORPORATION
+OUI:70B3D5988*
+ ID_OUI_FROM_DATABASE=Arris
+
OUI:70B3D5989*
ID_OUI_FROM_DATABASE=DCNS
OUI:70B3D59A2*
ID_OUI_FROM_DATABASE=O-Net Communications(Shenzhen)Limited
+OUI:70B3D59A3*
+ ID_OUI_FROM_DATABASE=Shanghai Hourui Technology Co., Ltd.
+
OUI:70B3D59A4*
ID_OUI_FROM_DATABASE=Nordmann International GmbH
OUI:70B3D59A5*
ID_OUI_FROM_DATABASE=Softel
+OUI:70B3D59A6*
+ ID_OUI_FROM_DATABASE=QUNU LABS PRIVATE LIMITED
+
OUI:70B3D59A7*
ID_OUI_FROM_DATABASE=Honeywell
OUI:70B3D59BA*
ID_OUI_FROM_DATABASE=ATIM Radiocommunication
+OUI:70B3D59BB*
+ ID_OUI_FROM_DATABASE=Jinga-hi, Inc.
+
OUI:70B3D59BD*
ID_OUI_FROM_DATABASE=Signal Processing Devices Sweden AB
ID_OUI_FROM_DATABASE=FeldTech GmbH
OUI:70B3D5A03*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Proemion GmbH
OUI:70B3D5A04*
ID_OUI_FROM_DATABASE=Galea Electric S.L.
OUI:70B3D5A30*
ID_OUI_FROM_DATABASE=SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD
+OUI:70B3D5A31*
+ ID_OUI_FROM_DATABASE=Private
+
OUI:70B3D5A32*
ID_OUI_FROM_DATABASE=Toughdog Security Systems
OUI:70B3D5A3D*
ID_OUI_FROM_DATABASE=SMART IN OVATION GmbH
+OUI:70B3D5A3E*
+ ID_OUI_FROM_DATABASE=Vigorcloud Co., Ltd.
+
OUI:70B3D5A3F*
ID_OUI_FROM_DATABASE=PHPower Srl
OUI:70B3D5A60*
ID_OUI_FROM_DATABASE=Pneumax S.p.A.
+OUI:70B3D5A61*
+ ID_OUI_FROM_DATABASE=Omsk Manufacturing Association named after A.S. Popov
+
OUI:70B3D5A62*
ID_OUI_FROM_DATABASE=Environexus
OUI:70B3D5AB0*
ID_OUI_FROM_DATABASE=OSR R&D ISRAEL LTD
+OUI:70B3D5AB1*
+ ID_OUI_FROM_DATABASE=ISRV Zrt.
+
OUI:70B3D5AB2*
ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L.
OUI:70B3D5B0C*
ID_OUI_FROM_DATABASE=Vigilate srl
+OUI:70B3D5B0E*
+ ID_OUI_FROM_DATABASE=Servotronix Motion Control
+
OUI:70B3D5B0F*
ID_OUI_FROM_DATABASE=merkur Funksysteme AG
OUI:70B3D5B13*
ID_OUI_FROM_DATABASE=Omwave
+OUI:70B3D5B14*
+ ID_OUI_FROM_DATABASE=Pantherun Technologies Pvt Ltd
+
OUI:70B3D5B15*
ID_OUI_FROM_DATABASE=Eta Beta Srl
OUI:70B3D5B1B*
ID_OUI_FROM_DATABASE=Technology Link Corporation
+OUI:70B3D5B1C*
+ ID_OUI_FROM_DATABASE=Serveron / Qualitrol
+
OUI:70B3D5B1D*
ID_OUI_FROM_DATABASE=Safelet BV
OUI:70B3D5B21*
ID_OUI_FROM_DATABASE=TATTILE SRL
+OUI:70B3D5B22*
+ ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+
OUI:70B3D5B23*
ID_OUI_FROM_DATABASE=Supervision Test et Pilotage
OUI:70B3D5B44*
ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD.
+OUI:70B3D5B45*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision IND.CO.,LTD
+
OUI:70B3D5B46*
ID_OUI_FROM_DATABASE=FAS Electronics (Fujian) Co.,LTD.
OUI:70B3D5B60*
ID_OUI_FROM_DATABASE=ZAO ZEO
+OUI:70B3D5B61*
+ ID_OUI_FROM_DATABASE=WuXi anktech Co., Ltd
+
OUI:70B3D5B62*
ID_OUI_FROM_DATABASE=Sakura Seiki Co.,Ltd.
OUI:70B3D5B68*
ID_OUI_FROM_DATABASE=S-Rain Control A/S
+OUI:70B3D5B69*
+ ID_OUI_FROM_DATABASE=Daatrics LTD
+
OUI:70B3D5B6A*
ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
ID_OUI_FROM_DATABASE=Integra Metering SAS
OUI:70B3D5B71*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Optiver Pty Ltd
OUI:70B3D5B72*
ID_OUI_FROM_DATABASE=UB330.net d.o.o.
OUI:70B3D5B82*
ID_OUI_FROM_DATABASE=Lookout Portable Security
+OUI:70B3D5B83*
+ ID_OUI_FROM_DATABASE=Matrix Telematics Limited
+
OUI:70B3D5B84*
ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies
ID_OUI_FROM_DATABASE=Fenotech Inc.
OUI:70B3D5B86*
- ID_OUI_FROM_DATABASE=Cubitech
+ ID_OUI_FROM_DATABASE=Hilo
OUI:70B3D5B87*
ID_OUI_FROM_DATABASE=CAITRON GmbH
OUI:70B3D5BBB*
ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+OUI:70B3D5BBC*
+ ID_OUI_FROM_DATABASE=Boundary Technologies Ltd
+
OUI:70B3D5BBD*
ID_OUI_FROM_DATABASE=Providius Corp
OUI:70B3D5BDD*
ID_OUI_FROM_DATABASE=CDR SRL
+OUI:70B3D5BDE*
+ ID_OUI_FROM_DATABASE=CAST Group of Companies Inc.
+
OUI:70B3D5BDF*
ID_OUI_FROM_DATABASE=H2O-YUG LLC
OUI:70B3D5BE1*
ID_OUI_FROM_DATABASE=FeCon GmbH
+OUI:70B3D5BE2*
+ ID_OUI_FROM_DATABASE=Nocix, LLC
+
OUI:70B3D5BE3*
ID_OUI_FROM_DATABASE=Saratov Electrounit Production Plant named after Sergo Ordzhonikidze, OJSC
OUI:70B3D5BEA*
ID_OUI_FROM_DATABASE=Virtuosys Ltd
+OUI:70B3D5BEB*
+ ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+
OUI:70B3D5BEC*
ID_OUI_FROM_DATABASE=Tokyo Communication Equipment MFG Co.,ltd.
OUI:70B3D5BF3*
ID_OUI_FROM_DATABASE=CG-WIRELESS
+OUI:70B3D5BF4*
+ ID_OUI_FROM_DATABASE=CreevX
+
OUI:70B3D5BF5*
ID_OUI_FROM_DATABASE=Acacia Research
OUI:70B3D5C45*
ID_OUI_FROM_DATABASE=Stiebel Eltron GmbH
+OUI:70B3D5C46*
+ ID_OUI_FROM_DATABASE=eumig industrie-TV GmbH.
+
OUI:70B3D5C48*
ID_OUI_FROM_DATABASE=Weltek Technologies Co. Ltd.
OUI:70B3D5C56*
ID_OUI_FROM_DATABASE=TELETASK
+OUI:70B3D5C57*
+ ID_OUI_FROM_DATABASE=eBZ GmbH
+
OUI:70B3D5C58*
ID_OUI_FROM_DATABASE=RMI Laser LLC
OUI:70B3D5CBE*
ID_OUI_FROM_DATABASE=Ensura Solutions BV
+OUI:70B3D5CBF*
+ ID_OUI_FROM_DATABASE=Cubic ITS, Inc. dba GRIDSMART Technologies
+
OUI:70B3D5CC1*
ID_OUI_FROM_DATABASE=BEEcube Inc.
OUI:70B3D5CDC*
ID_OUI_FROM_DATABASE=Dat-Con d.o.o.
+OUI:70B3D5CDD*
+ ID_OUI_FROM_DATABASE=Teneo IoT B.V.
+
OUI:70B3D5CDE*
ID_OUI_FROM_DATABASE=Multipure International
OUI:70B3D5CEA*
ID_OUI_FROM_DATABASE=Computerwise, Inc.
+OUI:70B3D5CEC*
+ ID_OUI_FROM_DATABASE=Deltronic Security AB
+
OUI:70B3D5CED*
ID_OUI_FROM_DATABASE=Advanced Products Corporation Pte Ltd
OUI:70B3D5D16*
ID_OUI_FROM_DATABASE=Monnit Corporation
+OUI:70B3D5D17*
+ ID_OUI_FROM_DATABASE=Power Element
+
OUI:70B3D5D18*
ID_OUI_FROM_DATABASE=MetCom Solutions GmbH
ID_OUI_FROM_DATABASE=C-COM Satellite Systems Inc.
OUI:70B3D5D50*
- ID_OUI_FROM_DATABASE=GRIDSMART Technologies
+ ID_OUI_FROM_DATABASE=Cubic ITS, Inc. dba GRIDSMART Technologies
OUI:70B3D5D51*
ID_OUI_FROM_DATABASE=Azcom Technology S.r.l.
OUI:70B3D5D5C*
ID_OUI_FROM_DATABASE=Critical Link LLC
+OUI:70B3D5D5E*
+ ID_OUI_FROM_DATABASE=Barcelona Smart Technologies
+
OUI:70B3D5D5F*
ID_OUI_FROM_DATABASE=Core Balance Co., Ltd.
OUI:70B3D5D81*
ID_OUI_FROM_DATABASE=PDD Group Ltd
+OUI:70B3D5D82*
+ ID_OUI_FROM_DATABASE=SUN ELECTRONICS CO.,LTD.
+
OUI:70B3D5D84*
ID_OUI_FROM_DATABASE=Sentry360
+OUI:70B3D5D85*
+ ID_OUI_FROM_DATABASE=BTG Instruments AB
+
OUI:70B3D5D86*
ID_OUI_FROM_DATABASE=WPGSYS Pte Ltd
OUI:70B3D5DC6*
ID_OUI_FROM_DATABASE=IDEM INC.
+OUI:70B3D5DC7*
+ ID_OUI_FROM_DATABASE=NUBURU Inc.
+
OUI:70B3D5DC8*
ID_OUI_FROM_DATABASE=Enertex Bayern GmbH
ID_OUI_FROM_DATABASE=Eutron SPA
OUI:70B3D5DCD*
- ID_OUI_FROM_DATABASE=C Tech Bilişim Teknolojileri San. ve Tic. AŞ
+ ID_OUI_FROM_DATABASE=C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.
OUI:70B3D5DCE*
ID_OUI_FROM_DATABASE=Stahl GmbH
OUI:70B3D5DDD*
ID_OUI_FROM_DATABASE=BIO RAD LABORATORIES
+OUI:70B3D5DDE*
+ ID_OUI_FROM_DATABASE=Abbott Diagnostics Technologies AS
+
OUI:70B3D5DDF*
ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc.
ID_OUI_FROM_DATABASE=Nation-E Ltd.
OUI:70B3D5DE9*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=EkspertStroyProekt LLC
OUI:70B3D5DEA*
ID_OUI_FROM_DATABASE=Advanced Ventilation Applications, Inc.
OUI:70B3D5E1C*
ID_OUI_FROM_DATABASE=RoomMate AS
+OUI:70B3D5E1D*
+ ID_OUI_FROM_DATABASE=Galaxy Next Generation, Inc.
+
OUI:70B3D5E1E*
ID_OUI_FROM_DATABASE=Umano Medical Inc.
ID_OUI_FROM_DATABASE=LLVISION TECHNOLOGY CO.,LTD
OUI:70B3D5E22*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Federated Wireless, Inc.
OUI:70B3D5E23*
ID_OUI_FROM_DATABASE=Smith Meter, Inc.
OUI:70B3D5E43*
ID_OUI_FROM_DATABASE=SL Audio A/S
+OUI:70B3D5E44*
+ ID_OUI_FROM_DATABASE=BrainboxAI Inc
+
OUI:70B3D5E45*
ID_OUI_FROM_DATABASE=Momentum Data Systems
OUI:70B3D5E64*
ID_OUI_FROM_DATABASE=HONG JIANG ELECTRONICS CO., LTD.
+OUI:70B3D5E65*
+ ID_OUI_FROM_DATABASE=BIRTECH TECHNOLOGY
+
OUI:70B3D5E67*
ID_OUI_FROM_DATABASE=APPLIED PROCESSING
+OUI:70B3D5E68*
+ ID_OUI_FROM_DATABASE=Transit Solutions, LLC.
+
OUI:70B3D5E69*
ID_OUI_FROM_DATABASE=Fire4 Systems UK Ltd
OUI:70B3D5E86*
ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+OUI:70B3D5E87*
+ ID_OUI_FROM_DATABASE=STACKFORCE GmbH
+
OUI:70B3D5E88*
ID_OUI_FROM_DATABASE=Breas Medical AB
OUI:70B3D5E9E*
ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH
+OUI:70B3D5E9F*
+ ID_OUI_FROM_DATABASE=Gigaband IP LLC
+
OUI:70B3D5EA0*
ID_OUI_FROM_DATABASE=PARK24
OUI:70B3D5EC8*
ID_OUI_FROM_DATABASE=Viko Elektrik-Elektronik A.Ş.
+OUI:70B3D5EC9*
+ ID_OUI_FROM_DATABASE=Qlinx Technologies
+
OUI:70B3D5ECA*
ID_OUI_FROM_DATABASE=Transtronic AB
ID_OUI_FROM_DATABASE=Przemyslowy Instytut Automatyki i Pomiarow
OUI:70B3D5ED2*
- ID_OUI_FROM_DATABASE=PCTEL
+ ID_OUI_FROM_DATABASE=PCTEL, Inc.
OUI:70B3D5ED3*
ID_OUI_FROM_DATABASE=Beijing Lihong Create Co., Ltd.
+OUI:70B3D5ED4*
+ ID_OUI_FROM_DATABASE=WILMORE ELECTRONICS COMPANY
+
OUI:70B3D5ED5*
ID_OUI_FROM_DATABASE=hangzhou battle link technology Co.,Ltd
OUI:70B3D5F3F*
ID_OUI_FROM_DATABASE=comtac AG
+OUI:70B3D5F41*
+ ID_OUI_FROM_DATABASE=DUEVI SRL
+
OUI:70B3D5F42*
ID_OUI_FROM_DATABASE=Matsuhisa Corporation
OUI:70B3D5F6A*
ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
+OUI:70B3D5F6B*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
OUI:70B3D5F6C*
ID_OUI_FROM_DATABASE=VisioGreen
OUI:70B3D5F7E*
ID_OUI_FROM_DATABASE=Alpha Elettronica s.r.l.
+OUI:70B3D5F7F*
+ ID_OUI_FROM_DATABASE=ABL Space Systems
+
OUI:70B3D5F80*
ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
OUI:70B3D5F8F*
ID_OUI_FROM_DATABASE=DIMASTEC GESTAO DE PONTO E ACESSO EIRELI-ME
+OUI:70B3D5F90*
+ ID_OUI_FROM_DATABASE=Atman Tecnologia Ltda
+
OUI:70B3D5F91*
ID_OUI_FROM_DATABASE=Solid State Disks Ltd
OUI:70B3D5FAB*
ID_OUI_FROM_DATABASE=Open System Solutions Limited
+OUI:70B3D5FAC*
+ ID_OUI_FROM_DATABASE=Integrated Protein Technologies, Inc.
+
OUI:70B3D5FAD*
ID_OUI_FROM_DATABASE=ARC Technology Solutions, LLC
OUI:7463DF*
ID_OUI_FROM_DATABASE=VTS GmbH
+OUI:74650C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:7465D1*
ID_OUI_FROM_DATABASE=Atlinks
OUI:7472F2*
ID_OUI_FROM_DATABASE=Chipsip Technology Co., Ltd.
+OUI:74731D*
+ ID_OUI_FROM_DATABASE=ifm electronic gmbh
+
OUI:747336*
ID_OUI_FROM_DATABASE=MICRODIGTAL Inc
OUI:747818*
ID_OUI_FROM_DATABASE=Jurumani Solutions
+OUI:747827*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:747A90*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:748F4D*
ID_OUI_FROM_DATABASE=MEN Mikro Elektronik GmbH
+OUI:74901F*
+ ID_OUI_FROM_DATABASE=Ragile Networks Inc.
+
OUI:749050*
ID_OUI_FROM_DATABASE=Renesas Electronics Corporation
ID_OUI_FROM_DATABASE=AgJunction
OUI:7495EC*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:749637*
ID_OUI_FROM_DATABASE=Todaair Electronic Co., Ltd
OUI:74B6B6*
ID_OUI_FROM_DATABASE=eero inc.
+OUI:74B7B3*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
OUI:74B91E*
ID_OUI_FROM_DATABASE=Nanjing Bestway Automation System Co., Ltd
OUI:74D675*
ID_OUI_FROM_DATABASE=WYMA Tecnologia
+OUI:74D6CB*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:74D6EA*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:74EC42*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:74ECB2*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:74ECF1*
ID_OUI_FROM_DATABASE=Acumen
OUI:78055F*
ID_OUI_FROM_DATABASE=Shenzhen WYC Technology Co., Ltd.
+OUI:78058C*
+ ID_OUI_FROM_DATABASE=mMax Communications, Inc.
+
OUI:780738*
ID_OUI_FROM_DATABASE=Z.U.K. Elzab S.A.
OUI:781DFD*
ID_OUI_FROM_DATABASE=Jabil Inc
+OUI:781F11*
+ ID_OUI_FROM_DATABASE=RAB Lighting
+
OUI:781FDB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:782D7E*
ID_OUI_FROM_DATABASE=TRENDnet, Inc.
+OUI:782E56*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
OUI:782EEF*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:784561*
ID_OUI_FROM_DATABASE=CyberTAN Technology Inc.
+OUI:7845B3*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:7845C4*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:7869D4*
ID_OUI_FROM_DATABASE=Shenyang Vibrotech Instruments Inc.
+OUI:786A1F*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:786A89*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:787D53*
ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+OUI:787DF3*
+ ID_OUI_FROM_DATABASE=Sterlite Technologies Limited
+
OUI:787E61*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:788E33*
ID_OUI_FROM_DATABASE=Jiangsu SEUIC Technology Co.,Ltd
+OUI:7891E9*
+ ID_OUI_FROM_DATABASE=Raisecom Technology CO.,LTD
+
OUI:78923E*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:7894E8*
ID_OUI_FROM_DATABASE=Radio Bridge
+OUI:7895EB*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:789682*
ID_OUI_FROM_DATABASE=zte corporation
OUI:7897C3*
ID_OUI_FROM_DATABASE=DINGXIN INFORMATION TECHNOLOGY CO.,LTD
+OUI:7898E8*
+ ID_OUI_FROM_DATABASE=D-Link International
+
OUI:7898FD*
ID_OUI_FROM_DATABASE=Q9 Networks Inc.
OUI:78C881*
ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc.
+OUI:78C95E*
+ ID_OUI_FROM_DATABASE=Midmark RTLS
+
OUI:78CA04*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:78CA83E*
ID_OUI_FROM_DATABASE=Konecranes
+OUI:78CB2C*
+ ID_OUI_FROM_DATABASE=Join Digital, Inc.
+
OUI:78CB33*
ID_OUI_FROM_DATABASE=DHC Software Co.,Ltd
OUI:78EF4C*
ID_OUI_FROM_DATABASE=Unetconvergence Co., Ltd.
+OUI:78F09B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:78F29E*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
OUI:7C4CA5*
ID_OUI_FROM_DATABASE=BSkyB Ltd
+OUI:7C4E09*
+ ID_OUI_FROM_DATABASE=Shenzhen Skyworth Wireless Technology Co.,Ltd
+
OUI:7C4F7D*
ID_OUI_FROM_DATABASE=Sawwave
OUI:7C738B*
ID_OUI_FROM_DATABASE=Cocoon Alarm Ltd
+OUI:7C73EB*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:7C7630*
ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
OUI:7C787E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:7C78B2*
+ ID_OUI_FROM_DATABASE=Wyze Labs Inc
+
OUI:7C79E8*
ID_OUI_FROM_DATABASE=PayRange Inc.
OUI:7C8EE4*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:7C8FDE*
+ ID_OUI_FROM_DATABASE=DWnet Technologies(Suzhou) Corporation
+
OUI:7C9122*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:7CBFB1*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:7CC294*
+ ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd
+
OUI:7CC385*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:8002DF*
ID_OUI_FROM_DATABASE=ORA Inc.
+OUI:800384*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:800588*
ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD
OUI:807459*
ID_OUI_FROM_DATABASE=K's Co.,Ltd.
+OUI:807484*
+ ID_OUI_FROM_DATABASE=ALL Winner (Hong Kong) Limited
+
OUI:80751F*
ID_OUI_FROM_DATABASE=BSkyB Ltd
OUI:808F1D*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:808FE8*
+ ID_OUI_FROM_DATABASE=Intelbras
+
OUI:80912A*
ID_OUI_FROM_DATABASE=Lih Rong electronic Enterprise Co., Ltd.
OUI:809FAB*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:809FF5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:80A036*
ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd.
OUI:80C862*
ID_OUI_FROM_DATABASE=Openpeak, Inc
+OUI:80C955*
+ ID_OUI_FROM_DATABASE=Redpine Signals, Inc.
+
OUI:80CA4B*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LTD
OUI:80F593*
ID_OUI_FROM_DATABASE=IRCO Sistemas de Telecomunicación S.A.
+OUI:80F5B5*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:80F62E*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
OUI:84119E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:8411C20*
+ ID_OUI_FROM_DATABASE=Kazdream Technologies LLP
+
+OUI:8411C21*
+ ID_OUI_FROM_DATABASE=Beijing Dayu Technology Co., Ltd.
+
+OUI:8411C22*
+ ID_OUI_FROM_DATABASE=Futurecom Systems Group
+
+OUI:8411C23*
+ ID_OUI_FROM_DATABASE=Hitachi,Ltd.
+
+OUI:8411C24*
+ ID_OUI_FROM_DATABASE=LLC STC MZTA
+
+OUI:8411C25*
+ ID_OUI_FROM_DATABASE=AIBIoT GmbH
+
+OUI:8411C26*
+ ID_OUI_FROM_DATABASE=KESSEL AG
+
+OUI:8411C27*
+ ID_OUI_FROM_DATABASE=Ei3 Corporation
+
+OUI:8411C28*
+ ID_OUI_FROM_DATABASE=Leybold GmbH
+
+OUI:8411C29*
+ ID_OUI_FROM_DATABASE=C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.
+
+OUI:8411C2A*
+ ID_OUI_FROM_DATABASE=igus GmbH
+
+OUI:8411C2B*
+ ID_OUI_FROM_DATABASE=Guangdong Creator&Flyaudio Electronic Technology Co.,LTD
+
+OUI:8411C2C*
+ ID_OUI_FROM_DATABASE=Provision-ISR
+
+OUI:8411C2D*
+ ID_OUI_FROM_DATABASE=Goldmund Switzerland
+
+OUI:8411C2E*
+ ID_OUI_FROM_DATABASE=Dangerous Music Group, LLC
+
OUI:84139F*
ID_OUI_FROM_DATABASE=zte corporation
OUI:841B5E*
ID_OUI_FROM_DATABASE=NETGEAR
+OUI:841B77*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:841C70*
ID_OUI_FROM_DATABASE=zte corporation
OUI:842F75*
ID_OUI_FROM_DATABASE=Innokas Group
+OUI:843095*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision IND.CO.,LTD
+
OUI:8430E5*
ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC
OUI:845181*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:8454DF*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:8455A5*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:845DD7*
ID_OUI_FROM_DATABASE=Shenzhen Netcom Electronics Co.,Ltd
+OUI:846082*
+ ID_OUI_FROM_DATABASE=Private
+
OUI:8461A0*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:846FCE*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:847127*
+ ID_OUI_FROM_DATABASE=Silicon Laboratories
+
OUI:847207*
ID_OUI_FROM_DATABASE=I&C Technology
OUI:84930C*
ID_OUI_FROM_DATABASE=InCoax Networks Europe AB
+OUI:8493A0*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:84948C*
ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
OUI:849D64*
ID_OUI_FROM_DATABASE=SMC Corporation
+OUI:849DC2*
+ ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd.
+
OUI:849DC5*
ID_OUI_FROM_DATABASE=Centera Photonics Inc.
OUI:84C9C6*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+OUI:84CC63*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:84CCA8*
ID_OUI_FROM_DATABASE=Espressif Inc.
OUI:84E327*
ID_OUI_FROM_DATABASE=TAILYN TECHNOLOGIES INC
+OUI:84E342*
+ ID_OUI_FROM_DATABASE=Tuya?HK?Limietd
+
OUI:84E4D9*
ID_OUI_FROM_DATABASE=Shenzhen NEED technology Ltd.
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
OUI:84EA97*
- ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor Co., Ltd.
+ ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
OUI:84EA99*
ID_OUI_FROM_DATABASE=Vieworks
OUI:84F129*
ID_OUI_FROM_DATABASE=Metrascale Inc.
+OUI:84F147*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:84F3EB*
ID_OUI_FROM_DATABASE=Espressif Inc.
OUI:881544*
ID_OUI_FROM_DATABASE=Cisco Meraki
+OUI:8815C5*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:8817A3*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
OUI:888914*
ID_OUI_FROM_DATABASE=All Components Incorporated
+OUI:88892F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:888964*
ID_OUI_FROM_DATABASE=GSI Electronics Inc.
OUI:888C19*
ID_OUI_FROM_DATABASE=Brady Corp Asia Pacific Ltd
+OUI:888E68*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:88908D*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:8C3357*
ID_OUI_FROM_DATABASE=HiteVision Digital Media Technology Co.,Ltd.
+OUI:8C3401*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:8C34FD*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:8C4500*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:8C476E0*
+ ID_OUI_FROM_DATABASE=Chipsafer Pte. Ltd.
+
+OUI:8C476E1*
+ ID_OUI_FROM_DATABASE=TelWare Corporation
+
+OUI:8C476E2*
+ ID_OUI_FROM_DATABASE=HuiZhou MIKI Communication Equipment Co.,LTD
+
+OUI:8C476E3*
+ ID_OUI_FROM_DATABASE=Shanghai Satellite Communication Technology Co.,Ltd
+
+OUI:8C476E4*
+ ID_OUI_FROM_DATABASE=Shenzhen Juding Electronics Co., Ltd.
+
+OUI:8C476E5*
+ ID_OUI_FROM_DATABASE=Square Inc.
+
+OUI:8C476E6*
+ ID_OUI_FROM_DATABASE=Oxford Nanopore Technologies Ltd.
+
+OUI:8C476E7*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:8C476E8*
+ ID_OUI_FROM_DATABASE=IntelliVIX Co. Ltd.
+
+OUI:8C476E9*
+ ID_OUI_FROM_DATABASE=Xertified AB
+
+OUI:8C476EA*
+ ID_OUI_FROM_DATABASE=AU Optronics Corporation
+
+OUI:8C476EB*
+ ID_OUI_FROM_DATABASE=Faravid Communication&Data Analysis
+
+OUI:8C476EC*
+ ID_OUI_FROM_DATABASE=Edge Networks Inc
+
+OUI:8C476ED*
+ ID_OUI_FROM_DATABASE=innolectric AG
+
+OUI:8C476EE*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
OUI:8C47BE*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:8C541D*
ID_OUI_FROM_DATABASE=LGE
+OUI:8C554A*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:8C55BB*
+ ID_OUI_FROM_DATABASE=Songwoo Information & Technology Co., Ltd
+
OUI:8C569D*
ID_OUI_FROM_DATABASE=Imaging Solutions Group
OUI:8C79F5*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:8C7A15*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:8C7B9D*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:8CAB8E*
ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd.
+OUI:8CAE496*
+ ID_OUI_FROM_DATABASE=Chengdu BillDTE Technology Co., Ltd
+
+OUI:8CAE49A*
+ ID_OUI_FROM_DATABASE=Gigawave
+
OUI:8CAE4C*
ID_OUI_FROM_DATABASE=Plugable Technologies
OUI:8CCDE8*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:8CCE4E*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:8CCEFD*
ID_OUI_FROM_DATABASE=Shenzhen zhouhai technology co.,LTD
OUI:8CFD18*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:8CFDDE*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:8CFDF0*
ID_OUI_FROM_DATABASE=Qualcomm Inc.
OUI:907F61*
ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd.
+OUI:90808F*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:90812A*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:909916*
ID_OUI_FROM_DATABASE=ELVEES NeoTek OJSC
+OUI:909A4A*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:909A77*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:90B21F*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:90B4DD*
+ ID_OUI_FROM_DATABASE=Private
+
OUI:90B686*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:90DD5D*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:90DE80*
+ ID_OUI_FROM_DATABASE=Shenzhen Century Xinyang Technology Co., Ltd
+
OUI:90DFB7*
ID_OUI_FROM_DATABASE=s.m.s smart microwave sensors GmbH
OUI:90FF79*
ID_OUI_FROM_DATABASE=Metro Ethernet Forum
+OUI:90FFD6*
+ ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
+
OUI:940006*
ID_OUI_FROM_DATABASE=jinyoung
OUI:940937*
ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:9409D3*
+ ID_OUI_FROM_DATABASE=shenzhen maxtopic technology co.,ltd
+
OUI:940B19*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:9454DF*
ID_OUI_FROM_DATABASE=YST CORP.
+OUI:945641*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
OUI:9457A5*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:945B7E*
ID_OUI_FROM_DATABASE=TRILOBIT LTDA.
+OUI:945F34*
+ ID_OUI_FROM_DATABASE=Renesas Electronics (Penang) Sdn. Bhd.
+
OUI:94611E*
ID_OUI_FROM_DATABASE=Wata Electronics Co.,Ltd.
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:947BBE*
- ID_OUI_FROM_DATABASE=Ubicquia
+ ID_OUI_FROM_DATABASE=Ubicquia LLC
OUI:947BE7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:94A40C*
ID_OUI_FROM_DATABASE=Diehl Metering GmbH
+OUI:94A67E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
OUI:94A7B7*
ID_OUI_FROM_DATABASE=zte corporation
OUI:94B10A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:94B271*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:94B2CC*
ID_OUI_FROM_DATABASE=PIONEER CORPORATION
OUI:94B8C5*
ID_OUI_FROM_DATABASE=RuggedCom Inc.
+OUI:94B97E*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:94B9B4*
ID_OUI_FROM_DATABASE=Aptos Technology
OUI:94F278*
ID_OUI_FROM_DATABASE=Elma Electronic
+OUI:94F2BB*
+ ID_OUI_FROM_DATABASE=Valeo Vision Systems
+
OUI:94F551*
ID_OUI_FROM_DATABASE=Cadi Scientific Pte Ltd
OUI:980637E*
ID_OUI_FROM_DATABASE=Shanghai Jinnian information technology Co. Ltd
+OUI:98063A*
+ ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd
+
OUI:98063C*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:983B8F*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:983F60*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:983F9F*
ID_OUI_FROM_DATABASE=China SSJ (Suzhou) Network Technology Inc.
OUI:9897D1*
ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
+OUI:989AB9*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:989BCB*
ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
OUI:98C97C*
- ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO,LTD
+ ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
OUI:98CA33*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:98F170*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:98F181*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:98F199*
ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
OUI:9C1E95*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+OUI:9C1EA4*
+ ID_OUI_FROM_DATABASE=Renesas Electronics (Penang) Sdn. Bhd.
+
OUI:9C1FDD*
ID_OUI_FROM_DATABASE=Accupix Inc.
OUI:9C2840*
ID_OUI_FROM_DATABASE=Discovery Technology,LTD..
+OUI:9C28B3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:9C28BF*
ID_OUI_FROM_DATABASE=Continental Automotive Czech Republic s.r.o.
OUI:9C5F5A*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:9C5FB0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:9C611D*
ID_OUI_FROM_DATABASE=Panasonic Corporation of North America
OUI:9C713A*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:9C7370*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:9C741A*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
ID_OUI_FROM_DATABASE=INTEG process group inc
OUI:9C8D7C*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:9C8DD3*
ID_OUI_FROM_DATABASE=Leonton Technologies
OUI:9C8E99*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:9C8E9C*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:9C8ECD*
ID_OUI_FROM_DATABASE=Amcrest Technologies
OUI:9C99CD*
ID_OUI_FROM_DATABASE=Voippartners
+OUI:9C9AC0*
+ ID_OUI_FROM_DATABASE=LEGO System A/S
+
OUI:9C9C1D*
ID_OUI_FROM_DATABASE=Starkey Labs Inc.
OUI:9CB2B2*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:9CB2E8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:9CB654*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:A0687E*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:A06974*
+ ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
+
OUI:A06986*
ID_OUI_FROM_DATABASE=Wellav Technologies Ltd
OUI:A0764E*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:A07751*
+ ID_OUI_FROM_DATABASE=ASMedia Technology Inc.
+
OUI:A07771*
ID_OUI_FROM_DATABASE=Vialis BV
+OUI:A07817*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:A078BA*
ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
OUI:A09E1A*
ID_OUI_FROM_DATABASE=Polar Electro Oy
+OUI:A09F10*
+ ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+
OUI:A0A130*
ID_OUI_FROM_DATABASE=DLI Taiwan Branch office
OUI:A41731*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:A4178B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A41791*
ID_OUI_FROM_DATABASE=Shenzhen Decnta Technology Co.,LTD.
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:A468BC*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Oakley Inc.
OUI:A46C2A*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:A46CF1*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:A46DA4*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A46E79*
ID_OUI_FROM_DATABASE=DFT System Co.Ltd
OUI:A47CC9*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:A47D9F*
+ ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
+
OUI:A47E39*
ID_OUI_FROM_DATABASE=zte corporation
OUI:A49426*
ID_OUI_FROM_DATABASE=Elgama-Elektronika Ltd.
+OUI:A49733*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
OUI:A4975C*
ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd.
OUI:A4A80F*
ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd.
+OUI:A4AAFE*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:A4AC0F*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:A4CC32*
ID_OUI_FROM_DATABASE=Inficomm Co., Ltd
+OUI:A4CCB9*
+ ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd.
+
OUI:A4CD23*
ID_OUI_FROM_DATABASE=Shenzhenshi Xinzhongxin Co., Ltd
OUI:A4F7D0*
ID_OUI_FROM_DATABASE=LAN Accessories Co., Ltd.
+OUI:A4F9E4*
+ ID_OUI_FROM_DATABASE=AirVine Scientific, Inc.
+
OUI:A4FA76*
ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
OUI:A82BD6*
ID_OUI_FROM_DATABASE=Shina System Co., Ltd
+OUI:A8301C*
+ ID_OUI_FROM_DATABASE=Qingdao Intelligent&Precise Electronics Co.,Ltd.
+
OUI:A830AD*
ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
OUI:A84041*
ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited
+OUI:A8407D*
+ ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd.
+
OUI:A84122*
ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co.,Ltd.
OUI:A86DAA*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:A86E4E*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:A8705D*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:A8741D*
ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH
+OUI:A87484*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:A875D6*
ID_OUI_FROM_DATABASE=FreeTek International Co., Ltd.
OUI:A88038*
ID_OUI_FROM_DATABASE=ShenZhen MovingComm Technology Co., Limited
+OUI:A8817E*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:A88195*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:A89A93*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:A89AD7*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:A89B10*
ID_OUI_FROM_DATABASE=inMotion Ltd.
OUI:A8AD3D*
ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+OUI:A8B088*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:A8B0AE*
ID_OUI_FROM_DATABASE=LEONI
OUI:A8DA01*
ID_OUI_FROM_DATABASE=Shenzhen NUOLIJIA Digital Technology Co.,Ltd
+OUI:A8DA0C*
+ ID_OUI_FROM_DATABASE=SERVERCOM (INDIA) PRIVATE LIMITED
+
OUI:A8DB03*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
OUI:AC1203*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:AC122F*
+ ID_OUI_FROM_DATABASE=Fantasia Trading LLC
+
OUI:AC1461*
ID_OUI_FROM_DATABASE=ATAW Co., Ltd.
OUI:AC319D*
ID_OUI_FROM_DATABASE=Shenzhen TG-NET Botone Technology Co.,Ltd.
+OUI:AC3328*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:AC34CB*
ID_OUI_FROM_DATABASE=Shanhai GBCOM Communication Technology Co. Ltd
OUI:AC3651*
ID_OUI_FROM_DATABASE=Jiangsu Hengtong Terahertz Technology Co., Ltd.
+OUI:AC3728*
+ ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+
OUI:AC3743*
ID_OUI_FROM_DATABASE=HTC Corporation
OUI:AC44F2*
ID_OUI_FROM_DATABASE=YAMAHA CORPORATION
+OUI:AC471B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:AC4723*
ID_OUI_FROM_DATABASE=Genelec
OUI:AC676F*
ID_OUI_FROM_DATABASE=Electrocompaniet A.S.
+OUI:AC6784*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:AC67B2*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:AC6AA3*
+ ID_OUI_FROM_DATABASE=Shenzhen Kertong Technology Co.,Ltd
+
OUI:AC6B0F*
ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS INC
ID_OUI_FROM_DATABASE=iConnectivity
OUI:AC7A4D*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:AC7A56*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:ACDBDA*
ID_OUI_FROM_DATABASE=Shenzhen Geniatech Inc, Ltd
+OUI:ACDCCA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:ACDCE5*
ID_OUI_FROM_DATABASE=Procter & Gamble Company
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:ACF85C*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Chengdu Higon Integrated Circuit Design Co,. Ltd.
OUI:ACF8CC*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:ACF97E*
ID_OUI_FROM_DATABASE=ELESYS INC.
+OUI:ACFAA5*
+ ID_OUI_FROM_DATABASE=digitron
+
OUI:ACFD93*
ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
OUI:B04519*
ID_OUI_FROM_DATABASE=TCT mobile ltd
+OUI:B04530*
+ ID_OUI_FROM_DATABASE=BSkyB Ltd
+
OUI:B04545*
ID_OUI_FROM_DATABASE=YACOUB Automation GmbH
OUI:B0495F*
ID_OUI_FROM_DATABASE=OMRON HEALTHCARE Co., Ltd.
+OUI:B04A39*
+ ID_OUI_FROM_DATABASE=Beijing Roborock Technology Co., Ltd.
+
OUI:B04BBF*
ID_OUI_FROM_DATABASE=PT HAN SUNG ELECTORONICS INDONESIA
OUI:B08BCF*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B08C75*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B08E1A*
ID_OUI_FROM_DATABASE=URadio Systems Co., Ltd
OUI:B0989F*
ID_OUI_FROM_DATABASE=LG CNS
+OUI:B098BC*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:B09928*
ID_OUI_FROM_DATABASE=FUJITSU LIMITED
OUI:B0A460*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:B0A651*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B0A6F5*
ID_OUI_FROM_DATABASE=Xaptum, Inc.
OUI:B0BB8B*
ID_OUI_FROM_DATABASE=WAVETEL TECHNOLOGY LIMITED
+OUI:B0BBE5*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:B0BD6D*
ID_OUI_FROM_DATABASE=Echostreams Innovative Solutions
OUI:B0C4E7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:B0C53C*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B0C554*
ID_OUI_FROM_DATABASE=D-Link International
OUI:B0EC8F*
ID_OUI_FROM_DATABASE=GMX SAS
+OUI:B0ECDD*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B0ECE1*
ID_OUI_FROM_DATABASE=Private
OUI:B40EDC*
ID_OUI_FROM_DATABASE=LG-Ericsson Co.,Ltd.
+OUI:B40EDE*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:B40F3B*
ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch
OUI:B41A1D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:B41BB0*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B41C30*
ID_OUI_FROM_DATABASE=zte corporation
OUI:B456B9*
ID_OUI_FROM_DATABASE=Teraspek Technologies Co.,Ltd
+OUI:B456E3*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:B45861*
ID_OUI_FROM_DATABASE=CRemote, LLC
OUI:B49CDF*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:B49D02*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:B49D0B*
ID_OUI_FROM_DATABASE=BQ
OUI:B4B88D*
ID_OUI_FROM_DATABASE=Thuh Company
+OUI:B4BA12*
+ ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co.,Ltd.
+
OUI:B4BC7C*
ID_OUI_FROM_DATABASE=Texas Instruments
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:B4EC02*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:B4ECF2*
ID_OUI_FROM_DATABASE=Shanghai Listent Medical Tech Co., Ltd.
OUI:B4F949*
ID_OUI_FROM_DATABASE=optilink networks pvt ltd
+OUI:B4FBE3*
+ ID_OUI_FROM_DATABASE=AltoBeam (China) Inc.
+
OUI:B4FBE4*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
OUI:B4FE8C*
ID_OUI_FROM_DATABASE=Centro Sicurezza Italia SpA
+OUI:B4FF98*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B80018*
ID_OUI_FROM_DATABASE=Htel
OUI:B810D4*
ID_OUI_FROM_DATABASE=Masimo Corporation
+OUI:B8114B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B813E9*
ID_OUI_FROM_DATABASE=Trace Live Network
OUI:B82CA0*
ID_OUI_FROM_DATABASE=Resideo
+OUI:B82D28*
+ ID_OUI_FROM_DATABASE=AMPAK Technology,Inc.
+
OUI:B82FCB*
ID_OUI_FROM_DATABASE=CMS Electracom
OUI:B844D9*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:B8477A*
+ ID_OUI_FROM_DATABASE=Dasan Electron Co., Ltd.
+
OUI:B847C6*
ID_OUI_FROM_DATABASE=SanJet Technology Corp.
OUI:B85F98*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+OUI:B85FB0*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:B86091*
ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC
OUI:B8871E*
ID_OUI_FROM_DATABASE=Good Mind Industries Co., Ltd.
+OUI:B8876E*
+ ID_OUI_FROM_DATABASE=Yandex Services AG
+
OUI:B887A8*
ID_OUI_FROM_DATABASE=Step Ahead Innovations Inc.
OUI:B8AD3E*
ID_OUI_FROM_DATABASE=BLUECOM
+OUI:B8AE1C*
+ ID_OUI_FROM_DATABASE=Smart Cube., Ltd
+
OUI:B8AE6E*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
OUI:BC428C*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:BC4377*
ID_OUI_FROM_DATABASE=Hang Zhou Huite Technology Co.,ltd.
OUI:BC5A56*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:BC5BD5*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:BC5C4C*
ID_OUI_FROM_DATABASE=ELECOM CO.,LTD.
OUI:BC629F*
ID_OUI_FROM_DATABASE=Telenet Systems P. Ltd.
+OUI:BC62CE*
+ ID_OUI_FROM_DATABASE=SHENZHEN NETIS TECHNOLOGY CO.,LTD
+
OUI:BC62D2*
ID_OUI_FROM_DATABASE=Genexis International B.V.
OUI:BC6784*
ID_OUI_FROM_DATABASE=Environics Oy
+OUI:BC69CB*
+ ID_OUI_FROM_DATABASE=Panasonic Life Solutions Networks Co., Ltd.
+
OUI:BC6A16*
ID_OUI_FROM_DATABASE=tdvine
ID_OUI_FROM_DATABASE=HangZhou JuRu Technology CO.,LTD
OUI:BC7536*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:BC7574*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:BC9740E*
ID_OUI_FROM_DATABASE=B4ComTechnologies LLC
+OUI:BC9789*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:BC97E1*
ID_OUI_FROM_DATABASE=Broadcom Limited
OUI:BC9911*
ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+OUI:BC9930*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:BC99BC*
ID_OUI_FROM_DATABASE=FonSee Technology Inc.
OUI:C02506*
ID_OUI_FROM_DATABASE=AVM GmbH
+OUI:C0252F*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+
OUI:C0255C*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:C0335E*
ID_OUI_FROM_DATABASE=Microsoft
+OUI:C033DA*
+ ID_OUI_FROM_DATABASE=Shenzhen JRUN Technologies CO., LTD
+
OUI:C034B4*
ID_OUI_FROM_DATABASE=Gigastone Corporation
OUI:C03B8F*
ID_OUI_FROM_DATABASE=Minicom Digital Signage
+OUI:C03C59*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:C03D03*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:C03FD5*
ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+OUI:C03FDD*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C04004*
ID_OUI_FROM_DATABASE=Medicaroid Corporation
OUI:C074AD*
ID_OUI_FROM_DATABASE=Grandstream Networks, Inc.
+OUI:C07831*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C07878*
ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
OUI:C09134*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:C09435*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:C094AD*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:C095DA*
ID_OUI_FROM_DATABASE=NXP India Private Limited
OUI:C0C976*
ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+OUI:C0C9E3*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:C0CB38*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:C40ACB*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:C40B31*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:C40BCB*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:C417FE*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:C418E9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:C4198B*
ID_OUI_FROM_DATABASE=Dominion Voting Systems Corporation
OUI:C419EC*
ID_OUI_FROM_DATABASE=Qualisys AB
+OUI:C41C9C*
+ ID_OUI_FROM_DATABASE=JiQiDao
+
OUI:C41CFF*
ID_OUI_FROM_DATABASE=Vizio, Inc
OUI:C42628*
ID_OUI_FROM_DATABASE=Airo Wireless
+OUI:C4278C*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C42795*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
OUI:C436DA*
ID_OUI_FROM_DATABASE=Rusteletech Ltd.
+OUI:C43772*
+ ID_OUI_FROM_DATABASE=Virtuozzo International GmbH
+
OUI:C438D3*
ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD
OUI:C43C3C*
ID_OUI_FROM_DATABASE=CYBELEC SA
+OUI:C43CEA*
+ ID_OUI_FROM_DATABASE=BUFFALO.INC
+
OUI:C43DC7*
ID_OUI_FROM_DATABASE=NETGEAR
OUI:C44044*
ID_OUI_FROM_DATABASE=RackTop Systems Inc.
+OUI:C440F6*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:C4411E*
ID_OUI_FROM_DATABASE=Belkin International Inc.
+OUI:C44137*
+ ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd.
+
OUI:C44202*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:C45976*
ID_OUI_FROM_DATABASE=Fugoo Coorporation
+OUI:C45A86*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C45BF7*
ID_OUI_FROM_DATABASE=ants
OUI:C4693E*
ID_OUI_FROM_DATABASE=Turbulence Design Inc.
+OUI:C469F0*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C46AB7*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:C4A402*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:C4A72B*
+ ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+
OUI:C4A81D*
ID_OUI_FROM_DATABASE=D-Link International
OUI:C4CAD9*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:C4CB54*
+ ID_OUI_FROM_DATABASE=Fibocom Auto Inc.
+
OUI:C4CB6B*
ID_OUI_FROM_DATABASE=Airista Flow, Inc.
OUI:C4DD57*
ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:C4DE7B*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:C4E032*
ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group
OUI:C4F839*
ID_OUI_FROM_DATABASE=Actia Automotive
+OUI:C4FBAA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C4FCE4*
ID_OUI_FROM_DATABASE=DishTV NZ Ltd
OUI:C8B5B7*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C8B6D3*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C8BA94*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
OUI:CC3ADF*
ID_OUI_FROM_DATABASE=Private
+OUI:CC3B27*
+ ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+
OUI:CC3B3E*
ID_OUI_FROM_DATABASE=Lester Electrical
OUI:CC4EEC*
ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+OUI:CC4F5C1*
+ ID_OUI_FROM_DATABASE=lesswire GmbH
+
+OUI:CC4F5C2*
+ ID_OUI_FROM_DATABASE=MatchX GmbH
+
+OUI:CC4F5C3*
+ ID_OUI_FROM_DATABASE=Shanghai Zenchant Electornics Co.,LTD
+
+OUI:CC4F5C4*
+ ID_OUI_FROM_DATABASE=Spark Biomedical
+
+OUI:CC4F5C5*
+ ID_OUI_FROM_DATABASE=Kymati GmbH
+
+OUI:CC4F5C6*
+ ID_OUI_FROM_DATABASE=Watertech S.p.A.
+
+OUI:CC4F5C7*
+ ID_OUI_FROM_DATABASE=Smiths US Innovation LLC
+
+OUI:CC4F5C8*
+ ID_OUI_FROM_DATABASE=Feelmore Labs
+
+OUI:CC4F5C9*
+ ID_OUI_FROM_DATABASE=Dtrovision
+
+OUI:CC4F5CA*
+ ID_OUI_FROM_DATABASE=AZ-TECHNOLOGY SDN BHD
+
+OUI:CC4F5CB*
+ ID_OUI_FROM_DATABASE=Ontex BV
+
+OUI:CC4F5CC*
+ ID_OUI_FROM_DATABASE=Beijing Cotytech Technology Co.,LTD.
+
+OUI:CC4F5CD*
+ ID_OUI_FROM_DATABASE=Beijing Neutron Technology CO.,LTD.
+
+OUI:CC4F5CE*
+ ID_OUI_FROM_DATABASE=Buttons (Beijing) Technology Limited
+
OUI:CC500A*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:CCE0C3*
ID_OUI_FROM_DATABASE=EXTEN Technologies, Inc.
+OUI:CCE0DA*
+ ID_OUI_FROM_DATABASE=Baidu Online Network Technology (Beijing) Co., Ltd
+
OUI:CCE17F*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:CCF538*
ID_OUI_FROM_DATABASE=3isysnetworks
+OUI:CCF55F*
+ ID_OUI_FROM_DATABASE=E FOCUS INSTRUMENTS INDIA PRIVATE LIMITED
+
OUI:CCF67A*
ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
OUI:D01CBB*
ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd.
+OUI:D021AC*
+ ID_OUI_FROM_DATABASE=Yo Labs LLC
+
OUI:D021F9*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
OUI:D02DB3*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:D02EAB*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:D03110*
ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd
OUI:D0542D*
ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
+OUI:D05509*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
OUI:D055B2*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
OUI:D058FC*
ID_OUI_FROM_DATABASE=BSkyB Ltd
+OUI:D05919*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:D05995*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:D0BB80*
ID_OUI_FROM_DATABASE=SHL Telemedicine International Ltd.
+OUI:D0BCC1*
+ ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
+
OUI:D0BD01*
ID_OUI_FROM_DATABASE=DS International
OUI:D0C282*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:D0C31E*
+ ID_OUI_FROM_DATABASE=JUNGJIN Electronics Co.,Ltd
+
OUI:D0C42F*
ID_OUI_FROM_DATABASE=Tamagawa Seiki Co.,Ltd.
OUI:D41AC8*
ID_OUI_FROM_DATABASE=Nippon Printer Engineering
+OUI:D41B81*
+ ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
+
OUI:D41C1C*
ID_OUI_FROM_DATABASE=RCF S.P.A.
OUI:D44DA4*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:D44F67*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D44F68*
ID_OUI_FROM_DATABASE=Eidetic Communications Inc
OUI:D4741B*
ID_OUI_FROM_DATABASE=Beijing HuaDa ZhiBao Electronic System Co.,Ltd.
+OUI:D476A0*
+ ID_OUI_FROM_DATABASE=Fortinet, Inc.
+
OUI:D476EA*
ID_OUI_FROM_DATABASE=zte corporation
OUI:D47DFC*
ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+OUI:D47EE4*
+ ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited
+
OUI:D481CA*
ID_OUI_FROM_DATABASE=iDevices, LLC
OUI:D490E0*
ID_OUI_FROM_DATABASE=Topcon Electronics GmbH & Co. KG
+OUI:D4910F*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:D491AF*
ID_OUI_FROM_DATABASE=Electroacustica General Iberica, S.A.
OUI:D80F99*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:D810CB*
+ ID_OUI_FROM_DATABASE=Andrea Informatique
+
OUI:D81265*
ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD.
OUI:D834EE*
ID_OUI_FROM_DATABASE=Stem Audio
+OUI:D8373B*
+ ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
+
OUI:D837BE*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
OUI:D8CB8A*
ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD.
+OUI:D8CC98*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:D8CE3A*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:D8F2CA*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:D8F3BC*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:D8F3DB*
ID_OUI_FROM_DATABASE=Post CH AG
OUI:DC4A3E*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:DC4A9E0*
+ ID_OUI_FROM_DATABASE=Dongguan Huili electroacoustic Industrial Co.,ltd
+
+OUI:DC4A9E1*
+ ID_OUI_FROM_DATABASE=Advanced Electronics Ltd
+
+OUI:DC4A9E2*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:DC4A9E3*
+ ID_OUI_FROM_DATABASE=LEACH INTERNATIONAL EUROPE
+
+OUI:DC4A9E4*
+ ID_OUI_FROM_DATABASE=ADIAL
+
+OUI:DC4A9E5*
+ ID_OUI_FROM_DATABASE=Nuove Tecnologie srl
+
+OUI:DC4A9E6*
+ ID_OUI_FROM_DATABASE=TATTILE SRL
+
+OUI:DC4A9E7*
+ ID_OUI_FROM_DATABASE=Astrogate Inc.
+
+OUI:DC4A9E8*
+ ID_OUI_FROM_DATABASE=Methodex Systems Pvt. Ltd.
+
+OUI:DC4A9E9*
+ ID_OUI_FROM_DATABASE=AiSight GmbH
+
+OUI:DC4A9EA*
+ ID_OUI_FROM_DATABASE=LongSung Technology (Shanghai) Co.,Ltd.
+
+OUI:DC4A9EB*
+ ID_OUI_FROM_DATABASE=Maxvision Technology Corp.
+
+OUI:DC4A9EC*
+ ID_OUI_FROM_DATABASE=HEFEI DATANG STORAGE TECHNOLOGY CO.,LTD
+
+OUI:DC4A9ED*
+ ID_OUI_FROM_DATABASE=HAPPIEST BABY INC.
+
+OUI:DC4A9EE*
+ ID_OUI_FROM_DATABASE=SES-imagotag Deutschland GmbH
+
OUI:DC4BDD*
ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd.
OUI:DC60A1*
ID_OUI_FROM_DATABASE=Teledyne DALSA Professional Imaging
+OUI:DC6373*
+ ID_OUI_FROM_DATABASE=OBARA KOREA
+
OUI:DC647C*
ID_OUI_FROM_DATABASE=C.R.S. iiMotion GmbH
OUI:DC8B28*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:DC8C1B*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:DC8C37*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:DC9B9C*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:DC9BD6*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
OUI:DC9C52*
ID_OUI_FROM_DATABASE=Sapphire Technology Limited.
OUI:DCB4C4*
ID_OUI_FROM_DATABASE=Microsoft XCG
+OUI:DCB72E*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:DCB7FC*
+ ID_OUI_FROM_DATABASE=Alps Electric (Ireland) Ltd
+
OUI:DCB808*
ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
OUI:DCE838*
ID_OUI_FROM_DATABASE=CK Telecom (Shenzhen) Limited
+OUI:DCE994*
+ ID_OUI_FROM_DATABASE=CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.
+
OUI:DCEB53*
ID_OUI_FROM_DATABASE=Wuhan QianXiao Elecronic Technology CO.,LTD
OUI:E01CEE*
ID_OUI_FROM_DATABASE=Bravo Tech, Inc.
+OUI:E01CFC*
+ ID_OUI_FROM_DATABASE=D-Link International
+
OUI:E01D38*
ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd
OUI:E01F88*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:E01FED*
+ ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd.
+
OUI:E02202*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:E02B96*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:E02BE9*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:E02CB2*
ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited
OUI:E04B45*
ID_OUI_FROM_DATABASE=Hi-P Electronics Pte Ltd
+OUI:E04BA6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E04F43*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
OUI:E06CA6*
ID_OUI_FROM_DATABASE=Creotech Instruments S.A.
+OUI:E06D17*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:E0735F*
ID_OUI_FROM_DATABASE=NUCOM
OUI:E0750A*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:E0757D*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
OUI:E076D0*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+OUI:E07726*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E078A3*
ID_OUI_FROM_DATABASE=Shanghai Winner Information Technology Co.,Inc
OUI:E08FEC*
ID_OUI_FROM_DATABASE=REPOTEC CO., LTD.
+OUI:E0913C*
+ ID_OUI_FROM_DATABASE=Kyeungin CNS Co., Ltd.
+
OUI:E09153*
ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:E0AE5E*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:E0AEB2*
ID_OUI_FROM_DATABASE=Bender GmbH & Co.KG
OUI:E0C2B7*
ID_OUI_FROM_DATABASE=Masimo Corporation
+OUI:E0C377*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E0C3F3*
ID_OUI_FROM_DATABASE=zte corporation
OUI:E0DDC0*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:E0E0C2*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
OUI:E0E0FC*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+OUI:E0E1A9*
+ ID_OUI_FROM_DATABASE=Shenzhen Four Seas Global Link Network Technology Co., Ltd.
+
+OUI:E0E2E6*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:E0E5CF*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:E432CB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:E433AE*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:E43493*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:E44790*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:E44791*
+ ID_OUI_FROM_DATABASE=Iris ID Systems, Inc.
+
OUI:E447B3*
ID_OUI_FROM_DATABASE=zte corporation
OUI:E48D8C*
ID_OUI_FROM_DATABASE=Routerboard.com
+OUI:E48F1D*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E48F34*
ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A.
OUI:E4C2D1*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:E4C32A*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:E4C483*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
OUI:E4DB6D*
ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd.
+OUI:E4DC43*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E4DD79*
ID_OUI_FROM_DATABASE=En-Vision America, Inc.
OUI:E4F14C*
ID_OUI_FROM_DATABASE=Private
+OUI:E4F1D4*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:E4F327*
ID_OUI_FROM_DATABASE=ATOL LLC
OUI:E80959*
ID_OUI_FROM_DATABASE=Guoguang Electric Co.,Ltd
+OUI:E80AEC*
+ ID_OUI_FROM_DATABASE=Jiangsu Hengtong Optic-Electric Co., LTD
+
OUI:E80B13*
ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC
OUI:E81DA8*
ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:E81E92*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:E820E2*
ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
OUI:E8481F*
ID_OUI_FROM_DATABASE=Advanced Automotive Antennas
+OUI:E848B8*
+ ID_OUI_FROM_DATABASE=TP-Link Corporation Limited
+
OUI:E84943*
ID_OUI_FROM_DATABASE=YUGE Information technology Co. Ltd
OUI:E84ECE*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:E84F4B*
+ ID_OUI_FROM_DATABASE=Shenzhen Delos Electronic Co., Ltd
+
OUI:E8508B*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
OUI:E86819*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:E868E7*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:E86A64*
ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd
OUI:E87AF3*
ID_OUI_FROM_DATABASE=S5 Tech S.r.l.
+OUI:E87F6B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E87F95*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:E8825B*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:E884A5*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:E884C6*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:E8C229*
ID_OUI_FROM_DATABASE=H-Displays (MSC) Bhd
+OUI:E8C2DD*
+ ID_OUI_FROM_DATABASE=Infinix mobility limited
+
OUI:E8C320*
- ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
+ ID_OUI_FROM_DATABASE=Austco Marketing & Service (USA) ltd.
OUI:E8C417*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:E8DAAA*
ID_OUI_FROM_DATABASE=VideoHome Technology Corp.
+OUI:E8DB84*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:E8DE00*
ID_OUI_FROM_DATABASE=ChongQing GuanFang Technology Co.,LTD
OUI:E8EB1B*
ID_OUI_FROM_DATABASE=Microchip Technology Inc.
+OUI:E8EB34*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:E8ECA3*
ID_OUI_FROM_DATABASE=Dongguan Liesheng Electronic Co.Ltd
OUI:EC0D9A*
ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc.
+OUI:EC0DE4*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:EC0EC4*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:EC63ED*
ID_OUI_FROM_DATABASE=Hyundai Autoever Corp.
+OUI:EC6488*
+ ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
+
OUI:EC64E7*
ID_OUI_FROM_DATABASE=MOCACARE Corporation
OUI:EC7D9D*
ID_OUI_FROM_DATABASE=CPI
+OUI:EC7E91*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:EC7FC6*
ID_OUI_FROM_DATABASE=ECCEL CORPORATION SAS
OUI:EC9F0DE*
ID_OUI_FROM_DATABASE=MAX Technologies
+OUI:ECA1D1*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:ECA29B*
ID_OUI_FROM_DATABASE=Kemppi Oy
OUI:ECC06A*
ID_OUI_FROM_DATABASE=PowerChord Group Limited
+OUI:ECC302*
+ ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
+
OUI:ECC38A*
ID_OUI_FROM_DATABASE=Accuenergy (CANADA) Inc
OUI:ECC882*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:ECC89C*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
+
OUI:ECCB30*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:ECCD6D*
ID_OUI_FROM_DATABASE=Allied Telesis, Inc.
+OUI:ECCE13*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:ECCED7*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:F010AB*
ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd.
+OUI:F013C1*
+ ID_OUI_FROM_DATABASE=Hannto Technology Co., Ltd
+
OUI:F013C3*
ID_OUI_FROM_DATABASE=SHENZHEN FENDA TECHNOLOGY CO., LTD
OUI:F01C2D*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:F01D2D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:F01DBC*
ID_OUI_FROM_DATABASE=Microsoft Corporation
OUI:F02329*
ID_OUI_FROM_DATABASE=SHOWA DENKI CO.,LTD.
+OUI:F023AE*
+ ID_OUI_FROM_DATABASE=AMPAK Technology,Inc.
+
OUI:F023B90*
ID_OUI_FROM_DATABASE=Aquametro AG
OUI:F02E51*
ID_OUI_FROM_DATABASE=Casa Systems
+OUI:F02F74*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
OUI:F02FA7*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:F04F7C*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:F05136*
ID_OUI_FROM_DATABASE=TCT mobile ltd
OUI:F063F9*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:F06426*
+ ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+
OUI:F065C2*
ID_OUI_FROM_DATABASE=Yanfeng Visteon Electronics Technology (Shanghai) Co.,Ltd.
ID_OUI_FROM_DATABASE=SHARP Corporation
OUI:F0A225*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:F0A35A*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:F0A968*
ID_OUI_FROM_DATABASE=Antailiye Technology Co.,Ltd
+OUI:F0AA0B*
+ ID_OUI_FROM_DATABASE=Arra Networks/ Spectramesh
+
OUI:F0AB54*
ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
OUI:F0B31E*
ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
+OUI:F0B3EC*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F0B429*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:F0F7B3*
ID_OUI_FROM_DATABASE=Phorm
+OUI:F0F7E7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F0F842*
ID_OUI_FROM_DATABASE=KEEBOX, Inc.
OUI:F40B93*
ID_OUI_FROM_DATABASE=BlackBerry RTS
+OUI:F40B9F*
+ ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD
+
OUI:F40E01*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:F43328*
ID_OUI_FROM_DATABASE=CIMCON Lighting Inc.
+OUI:F434F0*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F436E1*
ID_OUI_FROM_DATABASE=Abilis Systems SARL
OUI:F44EFD*
ID_OUI_FROM_DATABASE=Actions Semiconductor Co.,Ltd.(Cayman Islands)
+OUI:F44FD3*
+ ID_OUI_FROM_DATABASE=shenzhen hemuwei technology co.,ltd
+
OUI:F450EB*
ID_OUI_FROM_DATABASE=Telechips Inc
OUI:F4645D*
ID_OUI_FROM_DATABASE=Toshiba
+OUI:F465A6*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F4672D*
ID_OUI_FROM_DATABASE=ShenZhen Topstar Technology Company
OUI:F46F4E*
ID_OUI_FROM_DATABASE=Echowell
+OUI:F46FED*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:F470AB*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
OUI:F80D60*
ID_OUI_FROM_DATABASE=CANON INC.
+OUI:F80DAC*
+ ID_OUI_FROM_DATABASE=HP Inc.
+
OUI:F80DEA*
ID_OUI_FROM_DATABASE=ZyCast Technology Inc.
OUI:F83880*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F83B1D*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:F83B7E*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:F83CBF*
ID_OUI_FROM_DATABASE=BOTATO ELECTRONICS SDN BHD
OUI:F852DF*
ID_OUI_FROM_DATABASE=VNL Europe AB
+OUI:F85329*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F854AF*
ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
OUI:F85E3C*
ID_OUI_FROM_DATABASE=SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD
+OUI:F85E42*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:F85EA0*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:F85F2A*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:F86601*
ID_OUI_FROM_DATABASE=Suzhou Chi-tek information technology Co., Ltd
+OUI:F8665A*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F866D1*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:F86CE1*
ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+OUI:F86D73*
+ ID_OUI_FROM_DATABASE=Zengge Co., Limited
+
OUI:F86ECF*
ID_OUI_FROM_DATABASE=Arcx Inc
OUI:F877B8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F87A41*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:F87AEF*
ID_OUI_FROM_DATABASE=Rosonix Technology, Inc.
OUI:F88C1C*
ID_OUI_FROM_DATABASE=KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING
+OUI:F88C21*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:F88DEF*
ID_OUI_FROM_DATABASE=Tenebraex
OUI:F8A5C5*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F8A73A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:F8A763*
ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
OUI:F8B156*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:F8B1DD*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F8B2F3*
ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD
OUI:F8B7E2*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:F8B95A*
+ ID_OUI_FROM_DATABASE=LG Innotek
+
OUI:F8BBBF*
ID_OUI_FROM_DATABASE=eero inc.
OUI:F8E079*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:F8E43B*
+ ID_OUI_FROM_DATABASE=ASIX Electronics Corporation
+
OUI:F8E44E*
ID_OUI_FROM_DATABASE=MCOT INC.
OUI:FC1910*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:FC1928*
+ ID_OUI_FROM_DATABASE=Actions Microelectronics Co., Ltd
+
OUI:FC1999*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
OUI:FC4596*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+OUI:FC45C3*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:FC48EF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:FC4B1C*
ID_OUI_FROM_DATABASE=INTERSENSOR S.R.L.
+OUI:FC4B57*
+ ID_OUI_FROM_DATABASE=Peerless Instrument Division of Curtiss-Wright
+
OUI:FC4BBC*
ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd.
ID_OUI_FROM_DATABASE=Beijing MDC Telecom
OUI:FC62B9*
- ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD.
+ ID_OUI_FROM_DATABASE=ALPSALPINE CO,.LTD
OUI:FC643A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:FC64BA*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:FC65B3*
+ ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
+
OUI:FC65DE*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:FC6947*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:FC698C*
+ ID_OUI_FROM_DATABASE=ANDREAS STIHL AG & Co. KG
+
OUI:FC6BF0*
ID_OUI_FROM_DATABASE=TOPWELL INTERNATIONAL HOLDINDS LIMITED
OUI:FC6DC0*
ID_OUI_FROM_DATABASE=BME CORPORATION
+OUI:FC6DD1*
+ ID_OUI_FROM_DATABASE=APRESIA Systems, Ltd.
+
OUI:FC6FB7*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:FC7F56*
ID_OUI_FROM_DATABASE=CoSyst Control Systems GmbH
+OUI:FC7FF1*
+ ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company
+
OUI:FC8329*
ID_OUI_FROM_DATABASE=Trei technics
OUI:FC8B97*
ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+OUI:FC8D3D*
+ ID_OUI_FROM_DATABASE=Leapfive Tech. Ltd.
+
OUI:FC8E5B*
ID_OUI_FROM_DATABASE=China Mobile Iot Limited company
OUI:FC956A*
ID_OUI_FROM_DATABASE=OCTAGON SYSTEMS CORP.
+OUI:FC9643*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:FC9947*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:FCB698*
ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
+OUI:FCB69D*
+ ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
+
OUI:FCB6D8*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:FCCCE4*
ID_OUI_FROM_DATABASE=Ascon Ltd.
+OUI:FCCD2F0*
+ ID_OUI_FROM_DATABASE=Ningbo Bull Digital Technology Co., LTD
+
+OUI:FCCD2F1*
+ ID_OUI_FROM_DATABASE=Siren Care(Shanghai) information and technology company
+
+OUI:FCCD2F2*
+ ID_OUI_FROM_DATABASE=Loupedeck Oy
+
+OUI:FCCD2F3*
+ ID_OUI_FROM_DATABASE=Xmitech Technology Co., Limited
+
+OUI:FCCD2F4*
+ ID_OUI_FROM_DATABASE=Genitek Engineering sprl
+
+OUI:FCCD2F5*
+ ID_OUI_FROM_DATABASE=QCTEK CO.,LTD.
+
+OUI:FCCD2F6*
+ ID_OUI_FROM_DATABASE=Annapurna labs
+
+OUI:FCCD2F7*
+ ID_OUI_FROM_DATABASE=Suzhou lehui display co.,ltd
+
+OUI:FCCD2F8*
+ ID_OUI_FROM_DATABASE=Asesorias y Servicios Innovaxxion SPA
+
+OUI:FCCD2F9*
+ ID_OUI_FROM_DATABASE=Aroma Retail
+
+OUI:FCCD2FA*
+ ID_OUI_FROM_DATABASE=SCOPUS INTERNATIONAL-BELGIUM
+
+OUI:FCCD2FB*
+ ID_OUI_FROM_DATABASE=HEAD-DIRECT (KUNSHAN) Co. Ltd
+
+OUI:FCCD2FC*
+ ID_OUI_FROM_DATABASE=Spedos ADS a.s.
+
+OUI:FCCD2FD*
+ ID_OUI_FROM_DATABASE=Shenzhen Smartbyte Technology Co., Ltd.
+
+OUI:FCCD2FE*
+ ID_OUI_FROM_DATABASE=Eltek brojila d.o.o.
+
OUI:FCCF43*
ID_OUI_FROM_DATABASE=HUIZHOU CITY HUIYANG DISTRICT MEISIQI INDUSTRY DEVELOPMENT CO,.LTD
OUI:FCD2B6E*
ID_OUI_FROM_DATABASE=Univer S.p.A.
+OUI:FCD436*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
OUI:FCD4F2*
ID_OUI_FROM_DATABASE=The Coca Cola Company
acpi:LNUX*:
ID_VENDOR_FROM_DATABASE=The Linux Foundation
+acpi:LOON*:
+ ID_VENDOR_FROM_DATABASE=Loongson Technology Corporation Limited
+
acpi:MCHP*:
ID_VENDOR_FROM_DATABASE=Microchip Technology Inc
acpi:PHYT*:
ID_VENDOR_FROM_DATABASE=Phytium Technology Co. Ltd.
+acpi:PIXA*:
+ ID_VENDOR_FROM_DATABASE=PixArt imaging inc.
+
acpi:QCOM*:
ID_VENDOR_FROM_DATABASE=Qualcomm Inc
ID_VENDOR_FROM_DATABASE=Teracue AG
acpi:TOSB*:
- ID_VENDOR_FROM_DATABASE=Toshiba Corporation
+ ID_VENDOR_FROM_DATABASE=Dynabook Inc.
acpi:TXNW*:
ID_VENDOR_FROM_DATABASE=Texas Instruments
acpi:CFG*:
ID_VENDOR_FROM_DATABASE=Atlantis
+acpi:CFR*:
+ ID_VENDOR_FROM_DATABASE=Meta View, Inc.
+
acpi:CGA*:
ID_VENDOR_FROM_DATABASE=Chunghwa Picture Tubes, LTD
acpi:CMI*:
ID_VENDOR_FROM_DATABASE=C-Media Electronics
+acpi:CMK*:
+ ID_VENDOR_FROM_DATABASE=Comark LLC
+
acpi:CMM*:
ID_VENDOR_FROM_DATABASE=Comtime GmbH
acpi:MKV*:
ID_VENDOR_FROM_DATABASE=Trtheim Technology
+acpi:MLC*:
+ ID_VENDOR_FROM_DATABASE=MILCOTS
+
acpi:MLD*:
ID_VENDOR_FROM_DATABASE=Deep Video Imaging Ltd
acpi:MPS*:
ID_VENDOR_FROM_DATABASE=mps Software GmbH
+acpi:MPV*:
+ ID_VENDOR_FROM_DATABASE=Megapixel Visual Realty
+
acpi:MPX*:
ID_VENDOR_FROM_DATABASE=Micropix Technologies, Ltd.
acpi:NXS*:
ID_VENDOR_FROM_DATABASE=Technology Nexus Secure Open Systems AB
+acpi:NXT*:
+ ID_VENDOR_FROM_DATABASE=NZXT (PNP same EDID)_
+
acpi:NYC*:
ID_VENDOR_FROM_DATABASE=Nakayo Relecommunications, Inc.
acpi:SKT*:
ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Company Ltd
+acpi:SKW*:
+ ID_VENDOR_FROM_DATABASE=Skyworth
+
acpi:SKY*:
ID_VENDOR_FROM_DATABASE=SKYDATA S.P.A.
ID_VENDOR_FROM_DATABASE=Orion Communications Co., Ltd.
acpi:TOS*:
- ID_VENDOR_FROM_DATABASE=Toshiba Corporation
+ ID_VENDOR_FROM_DATABASE=Dynabook Inc.
acpi:TOU*:
ID_VENDOR_FROM_DATABASE=Touchstone Technology
---- 20-acpi-vendor.hwdb.base 2020-07-23 17:21:29.955652649 +0200
-+++ 20-acpi-vendor.hwdb 2020-07-23 17:21:29.974652774 +0200
+--- 20-acpi-vendor.hwdb.base 2020-10-13 09:40:27.449819401 +0200
++++ 20-acpi-vendor.hwdb 2020-10-13 09:40:27.464819680 +0200
@@ -3,6 +3,8 @@
# Data imported from:
# https://uefi.org/uefi-pnp-export
acpi:AMDI*:
ID_VENDOR_FROM_DATABASE=AMD
-@@ -289,6 +288,9 @@
+@@ -295,6 +294,9 @@
acpi:AAA*:
ID_VENDOR_FROM_DATABASE=Avolites Ltd
acpi:AAE*:
ID_VENDOR_FROM_DATABASE=Anatek Electronics Inc.
-@@ -316,6 +318,9 @@
+@@ -322,6 +324,9 @@
acpi:ABO*:
ID_VENDOR_FROM_DATABASE=D-Link Systems Inc
acpi:ABS*:
ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc.
-@@ -361,7 +366,7 @@
+@@ -367,7 +372,7 @@
acpi:ACO*:
ID_VENDOR_FROM_DATABASE=Allion Computer Inc.
ID_VENDOR_FROM_DATABASE=Aspen Tech Inc
acpi:ACR*:
-@@ -634,6 +639,9 @@
+@@ -640,6 +645,9 @@
acpi:AMT*:
ID_VENDOR_FROM_DATABASE=AMT International Industry
acpi:AMX*:
ID_VENDOR_FROM_DATABASE=AMX LLC
-@@ -682,6 +690,9 @@
+@@ -688,6 +696,9 @@
acpi:AOA*:
ID_VENDOR_FROM_DATABASE=AOpen Inc.
acpi:AOE*:
ID_VENDOR_FROM_DATABASE=Advanced Optics Electronics, Inc.
-@@ -691,6 +702,9 @@
+@@ -697,6 +708,9 @@
acpi:AOT*:
ID_VENDOR_FROM_DATABASE=Alcatel
acpi:APC*:
ID_VENDOR_FROM_DATABASE=American Power Conversion
-@@ -866,7 +880,7 @@
+@@ -872,7 +886,7 @@
ID_VENDOR_FROM_DATABASE=Alps Electric Inc
acpi:AUO*:
acpi:AUR*:
ID_VENDOR_FROM_DATABASE=Aureal Semiconductor
-@@ -946,6 +960,9 @@
+@@ -952,6 +966,9 @@
acpi:AXE*:
ID_VENDOR_FROM_DATABASE=Axell Corporation
acpi:AXI*:
ID_VENDOR_FROM_DATABASE=American Magnetics
-@@ -1096,6 +1113,9 @@
+@@ -1102,6 +1119,9 @@
acpi:BML*:
ID_VENDOR_FROM_DATABASE=BIOMED Lab
acpi:BMS*:
ID_VENDOR_FROM_DATABASE=BIOMEDISYS
-@@ -1108,6 +1128,9 @@
+@@ -1114,6 +1134,9 @@
acpi:BNO*:
ID_VENDOR_FROM_DATABASE=Bang & Olufsen
acpi:BNS*:
ID_VENDOR_FROM_DATABASE=Boulder Nonlinear Systems
-@@ -1348,6 +1371,9 @@
+@@ -1357,6 +1380,9 @@
acpi:CHA*:
ID_VENDOR_FROM_DATABASE=Chase Research PLC
acpi:CHD*:
ID_VENDOR_FROM_DATABASE=ChangHong Electric Co.,Ltd
-@@ -1501,6 +1527,9 @@
+@@ -1513,6 +1539,9 @@
acpi:COD*:
ID_VENDOR_FROM_DATABASE=CODAN Pty. Ltd.
acpi:COI*:
ID_VENDOR_FROM_DATABASE=Codec Inc.
-@@ -1907,7 +1936,7 @@
+@@ -1919,7 +1948,7 @@
ID_VENDOR_FROM_DATABASE=Dragon Information Technology
acpi:DJE*:
acpi:DJP*:
ID_VENDOR_FROM_DATABASE=Maygay Machines, Ltd
-@@ -2239,6 +2268,9 @@
+@@ -2251,6 +2280,9 @@
acpi:EIN*:
ID_VENDOR_FROM_DATABASE=Elegant Invention
acpi:EKA*:
ID_VENDOR_FROM_DATABASE=MagTek Inc.
-@@ -2500,6 +2532,9 @@
+@@ -2512,6 +2544,9 @@
acpi:FCG*:
ID_VENDOR_FROM_DATABASE=First International Computer Ltd
acpi:FCS*:
ID_VENDOR_FROM_DATABASE=Focus Enhancements, Inc.
-@@ -2873,7 +2908,7 @@
+@@ -2885,7 +2920,7 @@
ID_VENDOR_FROM_DATABASE=General Standards Corporation
acpi:GSM*:
acpi:GSN*:
ID_VENDOR_FROM_DATABASE=Grandstream Networks, Inc.
-@@ -2974,6 +3009,9 @@
+@@ -2986,6 +3021,9 @@
acpi:HEC*:
ID_VENDOR_FROM_DATABASE=Hisense Electric Co., Ltd.
acpi:HEL*:
ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems Europe Ltd
-@@ -3103,6 +3141,9 @@
+@@ -3115,6 +3153,9 @@
acpi:HSD*:
ID_VENDOR_FROM_DATABASE=HannStar Display Corp
acpi:HSM*:
ID_VENDOR_FROM_DATABASE=AT&T Microelectronics
-@@ -3226,6 +3267,9 @@
+@@ -3238,6 +3279,9 @@
acpi:ICI*:
ID_VENDOR_FROM_DATABASE=Infotek Communication Inc
acpi:ICM*:
ID_VENDOR_FROM_DATABASE=Intracom SA
-@@ -3322,6 +3366,9 @@
+@@ -3334,6 +3378,9 @@
acpi:IKE*:
ID_VENDOR_FROM_DATABASE=Ikegami Tsushinki Co. Ltd.
acpi:IKS*:
ID_VENDOR_FROM_DATABASE=Ikos Systems Inc
-@@ -3367,6 +3414,9 @@
+@@ -3379,6 +3426,9 @@
acpi:IMT*:
ID_VENDOR_FROM_DATABASE=Inmax Technology Corporation
acpi:INA*:
ID_VENDOR_FROM_DATABASE=Inventec Corporation
-@@ -3874,6 +3924,9 @@
+@@ -3886,6 +3936,9 @@
acpi:LAN*:
ID_VENDOR_FROM_DATABASE=Sodeman Lancom Inc
acpi:LAS*:
ID_VENDOR_FROM_DATABASE=LASAT Comm. A/S
-@@ -3919,6 +3972,9 @@
+@@ -3931,6 +3984,9 @@
acpi:LED*:
ID_VENDOR_FROM_DATABASE=Long Engineering Design Inc
acpi:LEG*:
ID_VENDOR_FROM_DATABASE=Legerity, Inc
-@@ -3934,6 +3990,9 @@
+@@ -3946,6 +4002,9 @@
acpi:LGC*:
ID_VENDOR_FROM_DATABASE=Logic Ltd
acpi:LGI*:
ID_VENDOR_FROM_DATABASE=Logitech Inc
-@@ -3988,6 +4047,9 @@
+@@ -4000,6 +4059,9 @@
acpi:LND*:
ID_VENDOR_FROM_DATABASE=Land Computer Company Ltd
acpi:LNK*:
ID_VENDOR_FROM_DATABASE=Link Tech Inc
-@@ -4022,7 +4084,7 @@
+@@ -4034,7 +4096,7 @@
ID_VENDOR_FROM_DATABASE=Design Technology
acpi:LPL*:
acpi:LSC*:
ID_VENDOR_FROM_DATABASE=LifeSize Communications
-@@ -4198,6 +4260,9 @@
+@@ -4210,6 +4272,9 @@
acpi:MCX*:
ID_VENDOR_FROM_DATABASE=Millson Custom Solutions Inc.
acpi:MDA*:
ID_VENDOR_FROM_DATABASE=Media4 Inc
-@@ -4435,6 +4500,9 @@
+@@ -4450,6 +4515,9 @@
acpi:MOM*:
ID_VENDOR_FROM_DATABASE=Momentum Data Systems
acpi:MOS*:
ID_VENDOR_FROM_DATABASE=Moses Corporation
-@@ -4660,6 +4728,9 @@
+@@ -4678,6 +4746,9 @@
acpi:NAL*:
ID_VENDOR_FROM_DATABASE=Network Alchemy
acpi:NAT*:
ID_VENDOR_FROM_DATABASE=NaturalPoint Inc.
-@@ -5164,6 +5235,9 @@
+@@ -5185,6 +5256,9 @@
acpi:PCX*:
ID_VENDOR_FROM_DATABASE=PC Xperten
acpi:PDM*:
ID_VENDOR_FROM_DATABASE=Psion Dacom Plc.
-@@ -5227,9 +5301,6 @@
+@@ -5248,9 +5322,6 @@
acpi:PHE*:
ID_VENDOR_FROM_DATABASE=Philips Medical Systems Boeblingen GmbH
acpi:PHL*:
ID_VENDOR_FROM_DATABASE=Philips Consumer Electronics Company
-@@ -5317,9 +5388,6 @@
+@@ -5338,9 +5409,6 @@
acpi:PNL*:
ID_VENDOR_FROM_DATABASE=Panelview, Inc.
acpi:PNR*:
ID_VENDOR_FROM_DATABASE=Planar Systems, Inc.
-@@ -5455,15 +5523,9 @@
+@@ -5476,15 +5544,9 @@
acpi:PTS*:
ID_VENDOR_FROM_DATABASE=Plain Tree Systems Inc
acpi:PVG*:
ID_VENDOR_FROM_DATABASE=Proview Global Co., Ltd
-@@ -5779,9 +5841,6 @@
+@@ -5800,9 +5862,6 @@
acpi:RTI*:
ID_VENDOR_FROM_DATABASE=Rancho Tech Inc
acpi:RTL*:
ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Company Ltd
-@@ -5947,9 +6006,6 @@
+@@ -5968,9 +6027,6 @@
acpi:SEE*:
ID_VENDOR_FROM_DATABASE=SeeColor Corporation
acpi:SEI*:
ID_VENDOR_FROM_DATABASE=Seitz & Associates Inc
-@@ -6406,6 +6462,9 @@
+@@ -6430,6 +6486,9 @@
acpi:SVD*:
ID_VENDOR_FROM_DATABASE=SVD Computer
acpi:SVI*:
ID_VENDOR_FROM_DATABASE=Sun Microsystems
-@@ -6490,6 +6549,9 @@
+@@ -6514,6 +6573,9 @@
acpi:SZM*:
ID_VENDOR_FROM_DATABASE=Shenzhen MTC Co., Ltd
acpi:TAA*:
ID_VENDOR_FROM_DATABASE=Tandberg
-@@ -6580,6 +6642,9 @@
+@@ -6604,6 +6666,9 @@
acpi:TDG*:
ID_VENDOR_FROM_DATABASE=Six15 Technologies
acpi:TDM*:
ID_VENDOR_FROM_DATABASE=Tandem Computer Europe Inc
-@@ -6622,6 +6687,9 @@
+@@ -6646,6 +6711,9 @@
acpi:TEV*:
ID_VENDOR_FROM_DATABASE=Televés, S.A.
acpi:TEZ*:
ID_VENDOR_FROM_DATABASE=Tech Source Inc.
-@@ -6736,9 +6804,6 @@
+@@ -6760,9 +6828,6 @@
acpi:TNC*:
ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd
acpi:TNM*:
ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA
-@@ -7045,14 +7110,14 @@
+@@ -7069,14 +7134,14 @@
acpi:UNC*:
ID_VENDOR_FROM_DATABASE=Unisys Corporation
acpi:UNI*:
ID_VENDOR_FROM_DATABASE=Uniform Industry Corp.
-@@ -7087,6 +7152,9 @@
+@@ -7111,6 +7176,9 @@
acpi:USA*:
ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG
acpi:USD*:
ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation
-@@ -7330,9 +7398,6 @@
+@@ -7354,9 +7422,6 @@
acpi:WAL*:
ID_VENDOR_FROM_DATABASE=Wave Access
acpi:WAV*:
ID_VENDOR_FROM_DATABASE=Wavephore
-@@ -7457,7 +7522,7 @@
+@@ -7481,7 +7546,7 @@
ID_VENDOR_FROM_DATABASE=WyreStorm Technologies LLC
acpi:WYS*:
acpi:WYT*:
ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd.
-@@ -7471,9 +7536,6 @@
+@@ -7495,9 +7560,6 @@
acpi:XDM*:
ID_VENDOR_FROM_DATABASE=XDM Ltd.
acpi:XES*:
ID_VENDOR_FROM_DATABASE=Extreme Engineering Solutions, Inc.
-@@ -7504,9 +7566,6 @@
+@@ -7528,9 +7590,6 @@
acpi:XNT*:
ID_VENDOR_FROM_DATABASE=XN Technologies, Inc.
acpi:XQU*:
ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD
-@@ -7573,6 +7632,9 @@
+@@ -7597,6 +7656,9 @@
acpi:ZBX*:
ID_VENDOR_FROM_DATABASE=Zebax Technologies
pci:v*d*sv*sd*bc00sc01*
ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible unclassified device
+pci:v*d*sv*sd*bc00sc05*
+ ID_PCI_SUBCLASS_FROM_DATABASE=Image coprocessor
+
pci:v*d*sv*sd*bc01*
ID_PCI_CLASS_FROM_DATABASE=Mass storage controller
pci:v00001000d0000005Dsv00001000sd0000936A*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9364-8i)
+pci:v00001000d0000005Dsv00001000sd00009380*
+ ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9380-8e)
+
pci:v00001000d0000005Dsv00001028sd00001F41*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H830 Adapter)
ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355e Adapter)
pci:v00001000d000000E6sv00001028sd0000200E*
- ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355i MX)
+ ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA350i MX)
pci:v00001000d000000E6sv00001D49sd00000205*
ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA)
ID_MODEL_FROM_DATABASE=Navi 10 XL Downstream Port of PCI Express Switch
pci:v00001002d0000154C*
- ID_MODEL_FROM_DATABASE=Kryptos
+ ID_MODEL_FROM_DATABASE=Kryptos [Radeon RX 350]
pci:v00001002d0000154E*
ID_MODEL_FROM_DATABASE=Garfield
ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] (Secondary)
pci:v00001002d00003E50*
- ID_MODEL_FROM_DATABASE=RV380 [Radeon X600]
+ ID_MODEL_FROM_DATABASE=RV380 [Radeon X550/X600]
pci:v00001002d00003E54*
ID_MODEL_FROM_DATABASE=RV380 GL [FireGL V3200]
pci:v00001002d00003E70*
- ID_MODEL_FROM_DATABASE=RV380 [Radeon X600] (Secondary)
+ ID_MODEL_FROM_DATABASE=RV380 [Radeon X550/X600] (Secondary)
pci:v00001002d00004136*
ID_MODEL_FROM_DATABASE=RS100 [Mobility IGP 320M]
ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW)
pci:v00001002d00005046*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS]
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X]
pci:v00001002d00005046sv00001002sd00000004*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00000008*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury Pro/Xpert 2000 Pro)
pci:v00001002d00005046sv00001002sd00000014*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00000018*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury Pro/Xpert 2000 Pro)
pci:v00001002d00005046sv00001002sd00000028*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage 128 Pro AIW AGP)
pci:v00001002d00005046sv00001002sd0000002A*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage 128 Pro AIW AGP)
pci:v00001002d00005046sv00001002sd00000048*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00002000*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (VGA device))
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury MAXX AGP 4x (TMDS) (VGA device))
pci:v00001002d00005046sv00001002sd00002001*
- ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!))
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X] (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!))
pci:v00001002d00005050*
- ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI]
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO PCI / Xpert 128 PCI]
pci:v00001002d00005050sv00001002sd00000008*
- ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI] (Xpert 128)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO PCI / Xpert 128 PCI] (Xpert 128)
pci:v00001002d00005052*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4X TMDS
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X]
pci:v00001002d00005144*
ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon]
pci:v00001002d0000524Csv00001002sd00000088*
ID_MODEL_FROM_DATABASE=Rage 128 VR AGP (Xpert 99)
-pci:v00001002d00005346*
- ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x
-
-pci:v00001002d00005346sv00001002sd00000048*
- ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x (RAGE 128 16MB VGA TVOUT AMC PAL)
-
pci:v00001002d0000534D*
ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x
ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT/SE] (Radeon X800 SE)
pci:v00001002d0000554D*
- ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL]
+ ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO2/XL]
pci:v00001002d0000554Dsv00001002sd00000322*
- ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (All-In-Wonder X800 XL)
+ ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO2/XL] (All-In-Wonder X800 XL)
pci:v00001002d0000554Dsv00001458sd00002124*
- ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (GV-R80L256V-B (AGP))
+ ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO2/XL] (GV-R80L256V-B (AGP))
pci:v00001002d0000554E*
ID_MODEL_FROM_DATABASE=R430 [All-In-Wonder X800 GT]
ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT] (Secondary)
pci:v00001002d0000556D*
- ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary)
+ ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO2/XL] (Secondary)
pci:v00001002d0000556Dsv00001458sd00002125*
- ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary) (GV-R80L256V-B (AGP))
+ ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO2/XL] (Secondary) (GV-R80L256V-B (AGP))
pci:v00001002d0000556F*
ID_MODEL_FROM_DATABASE=R430 [Radeon X800] (Secondary)
ID_MODEL_FROM_DATABASE=RD780 Host Bridge
pci:v00001002d00005960*
- ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO]
+ ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO / 9250]
pci:v00001002d00005960sv000017AFsd00002020*
- ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Excalibur Radeon 9250)
+ ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO / 9250] (Excalibur Radeon 9250)
pci:v00001002d00005961*
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200]
ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350)
pci:v00001002d00006611*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM]
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM]
pci:v00001002d00006611sv00001028sd0000210B*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon R5 240 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon R5 240 OEM)
pci:v00001002d00006611sv00001642sd00001869*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon 520 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon 520 OEM)
pci:v00001002d00006611sv0000174Bsd00004248*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
pci:v00001002d00006611sv0000174Bsd0000A240*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
pci:v00001002d00006611sv0000174Bsd0000D340*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon R7 340 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon R7 340 OEM)
pci:v00001002d00006611sv00001B0Asd000090D3*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM] (Radeon R7 240 OEM)
pci:v00001002d00006613*
ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340]
pci:v00001002d000067D0*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro V7300X / V7350x2]
+pci:v00001002d000067D7*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 5100 / Barco MXRT-6700]
+
pci:v00001002d000067DF*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]
pci:v00001002d000067DFsv00001682sd0000C570*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570)
+pci:v00001002d000067DFsv00001682sd0000C580*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580)
+
pci:v00001002d000067DFsv0000174Bsd0000E347*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470/480)
pci:v00001002d000067EFsv0000103Csd00003421*
ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon RX 460)
+pci:v00001002d000067EFsv00001043sd00000561*
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (AREZ Radeon RX 560)
+
pci:v00001002d000067EFsv0000106Bsd00000160*
ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 460)
pci:v00001002d0000687Fsv00001002sd00006B76*
ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (RX Vega64)
+pci:v00001002d0000687Fsv00001458sd0000230C*
+ ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (Radeon RX VEGA 56 GAMING OC 8G)
+
pci:v00001002d00006880*
ID_MODEL_FROM_DATABASE=Lexington [Radeon HD 6550M]
pci:v00001002d00006939sv0000174Bsd0000E308*
ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380 Nitro 4G D5)
+pci:v00001002d0000693B*
+ ID_MODEL_FROM_DATABASE=Tonga PRO GL [FirePro W7100 / Barco MXRT-7600]
+
pci:v00001002d0000694C*
ID_MODEL_FROM_DATABASE=Polaris 22 XT [Radeon RX Vega M GH]
ID_MODEL_FROM_DATABASE=R520/M58 [Mobility Radeon X1800]
pci:v00001002d00007104*
- ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200]
+ ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200 / Barco MXTR-5100]
pci:v00001002d00007104sv000013CCsd00003D0A*
- ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] (MXRT-5100)
+ ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200 / Barco MXTR-5100] (MXRT-5100)
pci:v00001002d00007109*
ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL]
pci:v00001002d00009614*
ID_MODEL_FROM_DATABASE=RS780D [Radeon HD 3300]
+pci:v00001002d00009615*
+ ID_MODEL_FROM_DATABASE=RS780E [Radeon HD 3200]
+
pci:v00001002d00009616*
ID_MODEL_FROM_DATABASE=RS780L [Radeon 3000]
ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G]
pci:v00001002d0000991E*
- ID_MODEL_FROM_DATABASE=Bishop
+ ID_MODEL_FROM_DATABASE=Bishop [Xbox One S APU]
pci:v00001002d00009920*
ID_MODEL_FROM_DATABASE=Liverpool [Playstation 4 APU]
pci:v00001022d00001468*
ID_MODEL_FROM_DATABASE=Zeppelin Cryptographic Coprocessor NTBCCP
+pci:v00001022d00001470*
+ ID_MODEL_FROM_DATABASE=Vega 10 PCIe Bridge
+
+pci:v00001022d00001471*
+ ID_MODEL_FROM_DATABASE=Vega 10 PCIe Bridge
+
pci:v00001022d00001480*
ID_MODEL_FROM_DATABASE=Starship/Matisse Root Complex
ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 8Mb H-VRAM)
pci:v0000105Dd00002339sv000011A4sd0000000A*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000000*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000004*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000005*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000006*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000008*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd00000009*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd0000000A*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd00002339sv000013CCsd0000000C*
- ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel)
+ ID_MODEL_FROM_DATABASE=Imagine 128-II (Metheus 5 Megapixel)
pci:v0000105Dd0000493D*
ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride]
pci:v0000105Dd0000493Dsv000011A4sd0000000A*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000011A4sd0000000B*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd00000002*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 4 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 4 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd00000003*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd00000007*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd00000008*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd00000009*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd0000493Dsv000013CCsd0000000A*
- ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head)
+ ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Metheus 5 Megapixel, Dual Head)
pci:v0000105Dd00005348*
ID_MODEL_FROM_DATABASE=Revolution 4
ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 LE]
pci:v000010DEd000000F5*
- ID_MODEL_FROM_DATABASE=G71 [GeForce 7800 GS]
+ ID_MODEL_FROM_DATABASE=G71 [GeForce 7800 GS AGP]
pci:v000010DEd000000F6*
ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT]
ID_MODEL_FROM_DATABASE=MCPX Memory Controller
pci:v000010DEd000002E0*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT]
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT AGP]
pci:v000010DEd000002E0sv000002E0sd00002249*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (GF 7600GT 560M 256MB DDR3 DUAL DVI TV)
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT AGP] (GF 7600GT 560M 256MB DDR3 DUAL DVI TV)
pci:v000010DEd000002E1*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS]
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS AGP]
pci:v000010DEd000002E1sv00001682sd0000222B*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (PV-T73K-UAL3 (256MB))
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS AGP] (PV-T73K-UAL3 (256MB))
pci:v000010DEd000002E1sv00001682sd00002247*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (GF 7600GS 512MB DDR2)
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS AGP] (GF 7600GS 512MB DDR2)
pci:v000010DEd000002E2*
- ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT]
+ ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT AGP]
pci:v000010DEd000002E3*
- ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS]
+ ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS AGP]
pci:v000010DEd000002E4*
- ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT]
+ ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT AGP]
pci:v000010DEd000002E4sv00001682sd00002271*
- ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (PV-T71A-YDF7 (512MB))
+ ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT AGP] (PV-T71A-YDF7 (512MB))
+
+pci:v000010DEd000002E5*
+ ID_MODEL_FROM_DATABASE=G71 [GeForce 7600 GS AGP]
pci:v000010DEd000002F0*
ID_MODEL_FROM_DATABASE=C51 Host Bridge
ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti Rev. A] (RTX 2080 Ti GAMING X TRIO)
pci:v000010DEd00001E2D*
- ID_MODEL_FROM_DATABASE=TU102B
+ ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti Engineering Sample]
pci:v000010DEd00001E2E*
- ID_MODEL_FROM_DATABASE=TU102B
+ ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti 12GB Engineering Sample]
pci:v000010DEd00001E30*
ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000]
ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] (Quadro RTX 6000)
pci:v000010DEd00001E36*
- ID_MODEL_FROM_DATABASE=TU102GL
+ ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000]
pci:v000010DEd00001E37*
ID_MODEL_FROM_DATABASE=TU102GL [GRID RTX T10-4/T10-8/T10-16]
pci:v000010DEd00001F55*
ID_MODEL_FROM_DATABASE=TU106BM [GeForce RTX 2060 Mobile]
+pci:v000010DEd00001F76*
+ ID_MODEL_FROM_DATABASE=TU106GLM [Quadro RTX 3000 Mobile Refresh]
+
pci:v000010DEd00001F81*
ID_MODEL_FROM_DATABASE=TU117
pci:v000010DEd00001F97*
ID_MODEL_FROM_DATABASE=TU117M [GeForce MX450]
+pci:v000010DEd00001F98*
+ ID_MODEL_FROM_DATABASE=TU117M [GeForce MX450]
+
pci:v000010DEd00001F99*
ID_MODEL_FROM_DATABASE=TU117M
+pci:v000010DEd00001F9C*
+ ID_MODEL_FROM_DATABASE=TU117M [GeForce MX450]
+
pci:v000010DEd00001FAE*
ID_MODEL_FROM_DATABASE=TU117GL
pci:v000010DEd000021D1*
ID_MODEL_FROM_DATABASE=TU116BM [GeForce GTX 1660 Ti Mobile]
+pci:v000010DEd00002204*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3090]
+
+pci:v000010DEd00002206*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080 10GB / 20GB]
+
+pci:v000010DEd00002206sv000010DEsd0000146D*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080 10GB / 20GB] (GA102 [GeForce RTX 3080 20GB])
+
+pci:v000010DEd00002206sv00001462sd00003892*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080 10GB / 20GB] (RTX 3080 10GB GAMING X TRIO)
+
+pci:v000010DEd0000222B*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3090 Engineering Sample]
+
+pci:v000010DEd0000222F*
+ ID_MODEL_FROM_DATABASE=GA102 [GeForce RTX 3080 11GB / 12GB Engineering Sample]
+
+pci:v000010DEd00002230*
+ ID_MODEL_FROM_DATABASE=GA102GL [RTX A6000]
+
+pci:v000010DEd0000223F*
+ ID_MODEL_FROM_DATABASE=GA102GL
+
+pci:v000010DEd00002482*
+ ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Ti]
+
+pci:v000010DEd00002484*
+ ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070]
+
+pci:v000010DEd00002486*
+ ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3060 Ti]
+
+pci:v000010DEd0000249C*
+ ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile]
+
+pci:v000010DEd0000249D*
+ ID_MODEL_FROM_DATABASE=GA104M [GeForce RTX 3070 Mobile / Max-Q]
+
+pci:v000010DEd000024AF*
+ ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Engineering Sample]
+
+pci:v000010DEd000024BF*
+ ID_MODEL_FROM_DATABASE=GA104 [GeForce RTX 3070 Engineering Sample]
+
+pci:v000010DEd0000252F*
+ ID_MODEL_FROM_DATABASE=GA106 [GeForce RTX 3060 Engineering Sample]
+
pci:v000010DF*
ID_VENDOR_FROM_DATABASE=Emulex Corporation
pci:v000010ECd0000C822*
ID_MODEL_FROM_DATABASE=RTL8822CE 802.11ac PCIe Wireless Network Adapter
+pci:v000010ECd0000C82F*
+ ID_MODEL_FROM_DATABASE=RTL8822CE 802.11ac PCIe Wireless Network Adapter
+
pci:v000010ECd0000D723*
ID_MODEL_FROM_DATABASE=RTL8723DE 802.11b/g/n PCIe Adapter
pci:v0000117Cd00000094sv0000117Csd000000AC*
ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-324E)
+pci:v0000117Cd000000BB*
+ ID_MODEL_FROM_DATABASE=Celerity FC 32/64Gb/s Gen 7 Fibre Channel HBA
+
+pci:v0000117Cd000000BBsv0000117Csd000000BC*
+ ID_MODEL_FROM_DATABASE=Celerity FC 32/64Gb/s Gen 7 Fibre Channel HBA (Celerity FC-321P)
+
+pci:v0000117Cd000000BBsv0000117Csd000000BD*
+ ID_MODEL_FROM_DATABASE=Celerity FC 32/64Gb/s Gen 7 Fibre Channel HBA (Celerity FC-322P)
+
+pci:v0000117Cd000000BBsv0000117Csd000000BE*
+ ID_MODEL_FROM_DATABASE=Celerity FC 32/64Gb/s Gen 7 Fibre Channel HBA (Celerity FC-324P)
+
+pci:v0000117Cd000000E6*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA
+
+pci:v0000117Cd000000E6sv0000117Csd000000C0*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA (ExpressSAS H1280 GT)
+
+pci:v0000117Cd000000E6sv0000117Csd000000C1*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA (ExpressSAS H1208 GT)
+
+pci:v0000117Cd000000E6sv0000117Csd000000C2*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA (ExpressSAS H1244 GT)
+
+pci:v0000117Cd000000E6sv0000117Csd000000C3*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA (ExpressSAS H12F0 GT)
+
+pci:v0000117Cd000000E6sv0000117Csd000000C4*
+ ID_MODEL_FROM_DATABASE=ExpressSAS GT 12Gb/s SAS/SATA HBA (ExpressSAS H120F GT)
+
pci:v0000117Cd00008013*
ID_MODEL_FROM_DATABASE=ExpressPCI UL4D
pci:v0000118Dd00000344*
ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber
+pci:v0000118Dd0000B04E*
+ ID_MODEL_FROM_DATABASE=Claxon CXP4 CoaXPress frame grabber
+
pci:v0000118E*
ID_VENDOR_FROM_DATABASE=Hermstedt GmbH
pci:v0000126Fd00000910*
ID_MODEL_FROM_DATABASE=SM910
+pci:v0000126Fd00002262*
+ ID_MODEL_FROM_DATABASE=SM2262/SM2262EN SSD Controller
+
pci:v00001270*
ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd.
ID_VENDOR_FROM_DATABASE=Yano Electric Co Ltd
pci:v000013CC*
- ID_VENDOR_FROM_DATABASE=Metheus Corporation
+ ID_VENDOR_FROM_DATABASE=BARCO
pci:v000013CD*
ID_VENDOR_FROM_DATABASE=Compatible Systems Corporation
pci:v0000144Dd00001600*
ID_MODEL_FROM_DATABASE=Apple PCIe SSD
+pci:v0000144Dd0000A544*
+ ID_MODEL_FROM_DATABASE=Exynos 8890 PCIe Root Complex
+
pci:v0000144Dd0000A800*
ID_MODEL_FROM_DATABASE=XP941 PCIe SSD
pci:v0000144Dd0000A824sv00001028sd00002099*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller PM173X (EMC PowerEdge Express Flash Ent NVMe AGN SED RI U.2 Gen4 7.68TB)
+pci:v0000144Dd0000ECEC*
+ ID_MODEL_FROM_DATABASE=Exynos 8895 PCIe Root Complex
+
pci:v0000144E*
ID_VENDOR_FROM_DATABASE=OLITEC
pci:v000014E4d000016D6sv000014E4sd00004120*
ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller (NetXtreme E-Series Advanced Dual-port 10Gb SFP+ Ethernet Network Daughter Card)
+pci:v000014E4d000016D6sv000014E4sd00004126*
+ ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller (NetXtreme-E Dual-port 10G SFP+ Ethernet OCP 3.0 Adapter (BCM957412N4120C))
+
pci:v000014E4d000016D6sv0000152Dsd00008B20*
ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller
pci:v000014E4d000016D7sv000014E4sd00004140*
ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (NetXtreme E-Series Advanced Dual-port 25Gb SFP28 Network Daughter Card)
+pci:v000014E4d000016D7sv000014E4sd00004146*
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (NetXtreme-E Dual-port 25G SFP28 Ethernet OCP 3.0 Adapter (BCM957414N4140C))
+
pci:v000014E4d000016D7sv00001590sd0000020E*
ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631SFP28 Adapter)
ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (NetXtreme-E 10Gb SFP+ Adapter)
pci:v000014E4d000016D8sv000014E4sd00004163*
- ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (BCM957416M4163C OCP 2x10GBT Type1 wRoCE)
+ ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (NetXtreme-E Dual-port 10GBASE-T Ethernet OCP 2.0 Adapter (BCM957416M4163C))
+
+pci:v000014E4d000016D8sv000014E4sd00004166*
+ ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (NetXtreme-E Dual-port 10GBASE-T Ethernet OCP 3.0 Adapter (BCM957416N4160C))
pci:v000014E4d000016D8sv00001590sd0000020C*
ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (Ethernet 10Gb 2-port 535T Adapter)
pci:v000014E4d000016E9*
ID_MODEL_FROM_DATABASE=BCM57407 NetXtreme-E 25Gb Ethernet Controller
+pci:v000014E4d000016EB*
+ ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E RDMA Partition
+
pci:v000014E4d000016EC*
ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Partition
pci:v000014E4d00001750*
ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet
+pci:v000014E4d00001750sv000014E4sd00002100*
+ ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (NetXtreme-E Dual-port 100G QSFP56 Ethernet PCIe4.0 x16 Adapter (BCM957508-P2100G))
+
+pci:v000014E4d00001750sv000014E4sd00005208*
+ ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (NetXtreme-E Dual-port 100G QSFP56 Ethernet OCP 3.0 Adapter (BCM957508-N2100G))
+
pci:v000014E4d00001751*
ID_MODEL_FROM_DATABASE=BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet
pci:v000014E4d00001752*
ID_MODEL_FROM_DATABASE=BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet
+pci:v000014E4d00001800*
+ ID_MODEL_FROM_DATABASE=BCM57502 NetXtreme-E Ethernet Partition
+
+pci:v000014E4d00001801*
+ ID_MODEL_FROM_DATABASE=BCM57504 NetXtreme-E Ethernet Partition
+
+pci:v000014E4d00001802*
+ ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E Ethernet Partition
+
+pci:v000014E4d00001803*
+ ID_MODEL_FROM_DATABASE=BCM57502 NetXtreme-E RDMA Partition
+
+pci:v000014E4d00001804*
+ ID_MODEL_FROM_DATABASE=BCM57504 NetXtreme-E RDMA Partition
+
+pci:v000014E4d00001805*
+ ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E RDMA Partition
+
pci:v000014E4d00001806*
ID_MODEL_FROM_DATABASE=BCM5750X NetXtreme-E Ethernet Virtual Function
pci:v000014E4d00004412*
ID_MODEL_FROM_DATABASE=BCM4412 10/100BaseT
+pci:v000014E4d0000441F*
+ ID_MODEL_FROM_DATABASE=BCM4361 802.11ac Dual-Band Wireless Network Controller
+
+pci:v000014E4d00004420*
+ ID_MODEL_FROM_DATABASE=BCM4361 802.11ac 2.4 GHz Wireless Network Controller
+
+pci:v000014E4d00004421*
+ ID_MODEL_FROM_DATABASE=BCM4361 802.11ac 5 GHz Wireless Network Controller
+
pci:v000014E4d00004430*
ID_MODEL_FROM_DATABASE=BCM44xx CardBus iLine32 HomePNA 2.0
ID_VENDOR_FROM_DATABASE=ACKSYS
pci:v00001529*
- ID_VENDOR_FROM_DATABASE=AMERICAN MICROSystems Inc
+ ID_VENDOR_FROM_DATABASE=ON Semiconductor
pci:v0000152A*
ID_VENDOR_FROM_DATABASE=QUICKTURN DESIGN Systems
pci:v00001556d00001110*
ID_MODEL_FROM_DATABASE=XpressRich Reference Design
+pci:v00001556d00001111*
+ ID_MODEL_FROM_DATABASE=XpressRich-AXI Ref Design
+
+pci:v00001556d00001112*
+ ID_MODEL_FROM_DATABASE=QuickPCIe
+
pci:v00001556d00001113*
ID_MODEL_FROM_DATABASE=XpressSwitch
+pci:v00001556d00001114*
+ ID_MODEL_FROM_DATABASE=Inspector
+
+pci:v00001556d00001115*
+ ID_MODEL_FROM_DATABASE=XpressLINK Ref Design
+
+pci:v00001556d00001116*
+ ID_MODEL_FROM_DATABASE=XpressLINK-SOC Ref Design
+
pci:v00001556d0000BE00*
ID_MODEL_FROM_DATABASE=PCI Express Bridge
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:v000015B3d00001017sv000015B3sd00000125*
- ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (Tencent ConnectX-5 EN Ex network interface card for OCP 3.0, with host management, 50GbE Dual-port QSFP28, PCIe4.0 x16, Thumbscrew (pull-tab) bracket)
-
pci:v000015B3d00001018*
ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5 Virtual Function]
pci:v000015B3d00001019sv000015B3sd00000008*
ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex] (ConnectX-5 Ex EN network interface card, 100GbE dual-port QSFP28, PCIe4.0 x16, tall bracket; MCX516A-CDAT)
+pci:v000015B3d00001019sv000015B3sd00000125*
+ ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex] (Tencent ConnectX-5 EN Ex network interface card for OCP 3.0, with host management, 50GbE Dual-port QSFP28, PCIe4.0 x16, Thumbscrew (pull-tab) bracket)
+
pci:v000015B3d0000101A*
ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex Virtual Function]
pci:v0000168Cd00000042sv000011ADsd000008A6*
ID_MODEL_FROM_DATABASE=QCA9377 802.11ac Wireless Network Adapter (Qualcomm Atheros QCA9377 802.11ac Wireless Network Adapter)
+pci:v0000168Cd00000042sv000017AAsd00000901*
+ ID_MODEL_FROM_DATABASE=QCA9377 802.11ac Wireless Network Adapter (Qualcomm Atheros QCA9377 Wireless Network Adapter)
+
pci:v0000168Cd00000046*
ID_MODEL_FROM_DATABASE=QCA9984 802.11ac Wave 2 Wireless Network Adapter
pci:v00001760d00000144*
ID_MODEL_FROM_DATABASE=PCA7408AS - Analog Inputs/Outputs
+pci:v00001760d00000145*
+ ID_MODEL_FROM_DATABASE=PCA-7228AL Multifunction PCI IO card
+
+pci:v00001760d00000146*
+ ID_MODEL_FROM_DATABASE=PCA-7228AS Multifunction PCI IO card
+
+pci:v00001760d00000147*
+ ID_MODEL_FROM_DATABASE=PCA7428AL Multifunction PCI IO card
+
+pci:v00001760d00000148*
+ ID_MODEL_FROM_DATABASE=PCA7428AS Multifunction PCI IO card
+
+pci:v00001760d00000149*
+ ID_MODEL_FROM_DATABASE=PCA7228EL Multifunction PCI IO card with isolated analog inputs
+
+pci:v00001760d00000150*
+ ID_MODEL_FROM_DATABASE=PCA7428EL Multifunction PCI IO card with isolated analog inputs
+
+pci:v00001760d00000151*
+ ID_MODEL_FROM_DATABASE=PCA7628AL - PCI card with analog inputs, counters and DIO
+
+pci:v00001760d00000152*
+ ID_MODEL_FROM_DATABASE=PCA7628AS PCI card with analog inputs, outputs, counters and DIO
+
+pci:v00001760d00000161*
+ ID_MODEL_FROM_DATABASE=PCA7288A PCI card with analog outputs, counters and DIO
+
+pci:v00001760d00000180*
+ ID_MODEL_FROM_DATABASE=PCI1052 Communication card for MicroUnit network
+
pci:v00001760d00000214*
ID_MODEL_FROM_DATABASE=PCT-7424C (F0) PC card with standard counters
pci:v000017A0d00009750*
ID_MODEL_FROM_DATABASE=GL9750 SD Host Controller
+pci:v000017A0d0000E763*
+ ID_MODEL_FROM_DATABASE=GL9763E eMMC Controller
+
pci:v000017AA*
ID_VENDOR_FROM_DATABASE=Lenovo
pci:v000017CBd00000002sv00001737sd00000054*
ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400)
+pci:v000017CBd00000105*
+ ID_MODEL_FROM_DATABASE=MSM8998 PCIe Root Complex
+
+pci:v000017CBd00000108*
+ ID_MODEL_FROM_DATABASE=SM8150/SA8195P PCIe Root Complex
+
+pci:v000017CBd00000300*
+ ID_MODEL_FROM_DATABASE=MDM9x35 LTE Modem
+
+pci:v000017CBd00000301*
+ ID_MODEL_FROM_DATABASE=MDM9640 PCIe Root Complex
+
+pci:v000017CBd00000302*
+ ID_MODEL_FROM_DATABASE=MDM9x55 LTE Modem [Snapdragon X12]
+
pci:v000017CBd00000400*
ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2432 PCI Express Root Port
pci:v000017CBd00000401*
ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2400 PCI Express Root Port
+pci:v000017CBd00001000*
+ ID_MODEL_FROM_DATABASE=QCS405 PCIe Root Complex
+
pci:v000017CC*
ID_VENDOR_FROM_DATABASE=NetChip Technology, Inc
ID_MODEL_FROM_DATABASE=MPC8314E
pci:v00001957d000000B6sv00001A56sd00001101*
- ID_MODEL_FROM_DATABASE=MPC8314E (Killer Xeno Pro Gigabit Ethernet Controller)
+ ID_MODEL_FROM_DATABASE=MPC8314E (Bigfoot Killer Xeno Pro Gigabit Ethernet Controller)
pci:v00001957d000000C2*
ID_MODEL_FROM_DATABASE=MPC8379E
ID_MODEL_FROM_DATABASE=MPC8308
pci:v00001957d0000C006sv00001A56sd00001201*
- ID_MODEL_FROM_DATABASE=MPC8308 (Killer E2100 Gigabit Ethernet Controller)
+ ID_MODEL_FROM_DATABASE=MPC8308 (Bigfoot Killer E2100 Gigabit Ethernet Controller)
pci:v00001957d0000FC02*
ID_MODEL_FROM_DATABASE=RedStone
pci:v00001966d00001977*
ID_MODEL_FROM_DATABASE=DVG128 family
+pci:v00001966d00001979*
+ ID_MODEL_FROM_DATABASE=3DVG/UHD3
+
+pci:v00001966d00001980*
+ ID_MODEL_FROM_DATABASE=HDV2/UHD2
+
+pci:v00001966d00001980sv00001234sd00003160*
+ ID_MODEL_FROM_DATABASE=HDV2/UHD2 (UHD2LC)
+
+pci:v00001966d00001980sv00001234sd00003300*
+ ID_MODEL_FROM_DATABASE=HDV2/UHD2 (Legacy UHD2)
+
+pci:v00001966d00001980sv00001234sd00003410*
+ ID_MODEL_FROM_DATABASE=HDV2/UHD2 (UHD2)
+
pci:v00001969*
ID_VENDOR_FROM_DATABASE=Qualcomm Atheros
pci:v00001A08d00000000*
ID_MODEL_FROM_DATABASE=SC15064
+pci:v00001A0D*
+ ID_VENDOR_FROM_DATABASE=SEAKR Engineering
+
pci:v00001A0E*
ID_VENDOR_FROM_DATABASE=DekTec Digital Video B.V.
ID_MODEL_FROM_DATABASE=CinePlay
pci:v00001A56*
- ID_VENDOR_FROM_DATABASE=Bigfoot Networks, Inc.
+ ID_VENDOR_FROM_DATABASE=Rivet Networks
pci:v00001A57*
ID_VENDOR_FROM_DATABASE=Highly Reliable Systems
pci:v00001AE0d00000042*
ID_MODEL_FROM_DATABASE=Compute Engine Virtual Ethernet [gVNIC]
+pci:v00001AE0d0000ABCD*
+ ID_MODEL_FROM_DATABASE=Airbrush Combined Paintbox IPU/Oscar Edge TPU [Pixel Neural Core]
+
pci:v00001AE3*
ID_VENDOR_FROM_DATABASE=SANBlaze Technology, Inc.
pci:v00001AE8*
ID_VENDOR_FROM_DATABASE=Silicon Software GmbH
+pci:v00001AE8d00000751*
+ ID_MODEL_FROM_DATABASE=mE5 marathon VCL
+
+pci:v00001AE8d00000752*
+ ID_MODEL_FROM_DATABASE=mE5 marathon AF2
+
+pci:v00001AE8d00000753*
+ ID_MODEL_FROM_DATABASE=mE5 marathon ACX QP
+
+pci:v00001AE8d00000754*
+ ID_MODEL_FROM_DATABASE=mE5 marathon ACL
+
+pci:v00001AE8d00000755*
+ ID_MODEL_FROM_DATABASE=mE5 marathon ACX SP
+
+pci:v00001AE8d00000756*
+ ID_MODEL_FROM_DATABASE=mE5 marathon ACX DP
+
+pci:v00001AE8d00000757*
+ ID_MODEL_FROM_DATABASE=mE5 marathon VCX QP
+
+pci:v00001AE8d00000758*
+ ID_MODEL_FROM_DATABASE=mE5 marathon VF2
+
+pci:v00001AE8d00000759*
+ ID_MODEL_FROM_DATABASE=mE5 marathon VCLx
+
pci:v00001AE8d00000A40*
- ID_MODEL_FROM_DATABASE=microEnable IV-BASE x1
+ ID_MODEL_FROM_DATABASE=microEnable IV AD1-CL
pci:v00001AE8d00000A41*
- ID_MODEL_FROM_DATABASE=microEnable IV-FULL x1
+ ID_MODEL_FROM_DATABASE=microEnable IV VD1-CL
+
+pci:v00001AE8d00000A42*
+ ID_MODEL_FROM_DATABASE=microEnable IV AD4-CL
pci:v00001AE8d00000A44*
- ID_MODEL_FROM_DATABASE=microEnable IV-FULL x4
+ ID_MODEL_FROM_DATABASE=microEnable IV VD4-CL
+
+pci:v00001AE8d00000A45*
+ ID_MODEL_FROM_DATABASE=microEnable IV AS1-CL
+
+pci:v00001AE8d00000A53*
+ ID_MODEL_FROM_DATABASE=microEnable 5 AQ8-CXP6B
+
+pci:v00001AE8d00000A54*
+ ID_MODEL_FROM_DATABASE=microEnable 5 VQ8-CXP6B
+
+pci:v00001AE8d00000A56*
+ ID_MODEL_FROM_DATABASE=microEnable 5 VQ8-CXP6D
+
+pci:v00001AE8d00000A57*
+ ID_MODEL_FROM_DATABASE=microEnable 5 AQ8-CXP6D
+
+pci:v00001AE8d00000A58*
+ ID_MODEL_FROM_DATABASE=microEnable 5 VD8-CL
+
+pci:v00001AE8d00000A5A*
+ ID_MODEL_FROM_DATABASE=microEnable 5 AD8-CL
+
+pci:v00001AE8d00000B52*
+ ID_MODEL_FROM_DATABASE=mE5 Abacus 4G Base
+
+pci:v00001AE8d00000B53*
+ ID_MODEL_FROM_DATABASE=mE5 Abacus 4G Base II
+
+pci:v00001AE8d00000B61*
+ ID_MODEL_FROM_DATABASE=mE6 Abacus 4TG
+
+pci:v00001AE8d00000B63*
+ ID_MODEL_FROM_DATABASE=CXP-12 Interface Card 1C
+
+pci:v00001AE8d00000E42*
+ ID_MODEL_FROM_DATABASE=microEnable IV AQ4-GE
pci:v00001AE8d00000E44*
- ID_MODEL_FROM_DATABASE=microEnable IV-GigE x4
+ ID_MODEL_FROM_DATABASE=microEnable IV VQ4-GE
pci:v00001AE9*
ID_VENDOR_FROM_DATABASE=Wilocity Ltd.
pci:v00001B21d00001042*
ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller
+pci:v00001B21d00001042sv00001043sd00001059*
+ ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (K53SM motherboard)
+
pci:v00001B21d00001042sv00001043sd00008488*
ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (P8B WS Motherboard)
pci:v00001B21d00002142*
ID_MODEL_FROM_DATABASE=ASM2142 USB 3.1 Host Controller
+pci:v00001B21d00003242*
+ ID_MODEL_FROM_DATABASE=ASM3242 USB 3.2 Host Controller
+
pci:v00001B26*
ID_VENDOR_FROM_DATABASE=Netcope Technologies, a.s.
pci:v00001B4Bd00000640*
ID_MODEL_FROM_DATABASE=88SE9128 SATA III 6Gb/s RAID Controller
+pci:v00001B4Bd00002241*
+ ID_MODEL_FROM_DATABASE=88NR2241 Non-Volatile memory controller
+
+pci:v00001B4Bd00002241sv00001D49sd00000306*
+ ID_MODEL_FROM_DATABASE=88NR2241 Non-Volatile memory controller (ThinkSystem M.2 NVMe 2-Bay RAID Enablement Kit)
+
+pci:v00001B4Bd00002241sv00001D49sd00000307*
+ ID_MODEL_FROM_DATABASE=88NR2241 Non-Volatile memory controller (ThinkSystem 7mm NVMe 2-Bay Rear RAID Enablement Kit)
+
pci:v00001B4Bd00009120*
ID_MODEL_FROM_DATABASE=88SE9120 SATA 6Gb/s Controller
pci:v00001B4Bd00009230sv00001D49sd00000300*
ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s 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)
+
+pci:v00001B4Bd00009230sv00001D49sd00000302*
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s 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)
+
+pci:v00001B4Bd00009230sv00001D49sd00000304*
+ ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s 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)
+
pci:v00001B4Bd00009235*
ID_MODEL_FROM_DATABASE=88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller
pci:v00001B4Bd00009485*
ID_MODEL_FROM_DATABASE=88SE9485 SAS/SATA 6Gb/s controller
+pci:v00001B4C*
+ ID_VENDOR_FROM_DATABASE=GALAX
+
pci:v00001B55*
ID_VENDOR_FROM_DATABASE=NetUP Inc.
pci:v00001C5Cd00001504*
ID_MODEL_FROM_DATABASE=SC300 512GB M.2 2280 SATA Solid State Drive
+pci:v00001C5Cd00002839*
+ ID_MODEL_FROM_DATABASE=PE8000 Series NVMe Solid State Drive
+
+pci:v00001C5Cd00002839sv00000100sd00001C5C*
+ ID_MODEL_FROM_DATABASE=PE8000 Series NVMe Solid State Drive
+
pci:v00001C5F*
ID_VENDOR_FROM_DATABASE=Beijing Memblaze Technology Co. Ltd.
pci:v00001CB0d0000D000*
ID_MODEL_FROM_DATABASE=Venice NVMe SSD
+pci:v00001CB0d0000D000sv00001CB0sd00002010*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series OCS U.2)
+
+pci:v00001CB0d0000D000sv00001CB0sd00002011*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series OCS U.2)
+
+pci:v00001CB0d0000D000sv00001CB0sd00002012*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series OCS U.2)
+
pci:v00001CB0d0000D000sv00001CB0sd00002F10*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series U.2 SSD)
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series NVMe U.2)
pci:v00001CB0d0000D000sv00001CB0sd00002F11*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series U.2 SSD)
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series NVMe U.2)
pci:v00001CB0d0000D000sv00001CB0sd00002F12*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series U.2 SSD)
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series NVMe U.2)
-pci:v00001CB0d0000D000sv00001CB0sd0000AF10*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series AIC SSD)
+pci:v00001CB0d0000D000sv00001CB0sd0000A010*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series OCS AIC)
-pci:v00001CB0d0000D000sv00001CB0sd0000AF11*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series AIC SSD)
+pci:v00001CB0d0000D000sv00001CB0sd0000A012*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series OCS AIC)
+
+pci:v00001CB0d0000D000sv00001CB0sd0000AF10*
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series NVMe AIC)
pci:v00001CB0d0000D000sv00001CB0sd0000AF12*
- ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series AIC SSD)
+ ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series NVMe AIC)
pci:v00001CB1*
ID_VENDOR_FROM_DATABASE=Collion UG & Co.KG
pci:v00001D78d00001512*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller
-pci:v00001D78d00001512sv00001D78sd00002003*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 1.6TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002004*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 HHHL 2TB NVMe SSD)
-pci:v00001D78d00001512sv00001D78sd00002005*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 3.2TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002006*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 HHHL 4TB NVMe SSD)
-pci:v00001D78d00001512sv00001D78sd00002007*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 6.4TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002008*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 HHHL 8TB NVMe SSD)
-pci:v00001D78d00001512sv00001D78sd00002103*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 1.6TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002104*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 U.2 2TB NVMe SSD)
-pci:v00001D78d00001512sv00001D78sd00002105*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 3.2TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002106*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 U.2 4TB NVMe SSD)
-pci:v00001D78d00001512sv00001D78sd00002107*
- ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 6.4TB NVMe SSD)
-
pci:v00001D78d00001512sv00001D78sd00002108*
ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5437 U.2 8TB NVMe SSD)
+pci:v00001D78d00001512sv00001D78sd00003003*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 1.6TB NVMe SSD)
+
+pci:v00001D78d00001512sv00001D78sd00003005*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 3.2TB NVMe SSD)
+
+pci:v00001D78d00001512sv00001D78sd00003007*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 HHHL 6.4TB NVMe SSD)
+
+pci:v00001D78d00001512sv00001D78sd00003103*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 1.6TB NVMe SSD)
+
+pci:v00001D78d00001512sv00001D78sd00003105*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 3.2TB NVMe SSD)
+
+pci:v00001D78d00001512sv00001D78sd00003107*
+ ID_MODEL_FROM_DATABASE=TAI NVMe Controller (D5457 U.2 6.4TB NVMe SSD)
+
pci:v00001D7C*
ID_VENDOR_FROM_DATABASE=Aerotech, Inc.
ID_VENDOR_FROM_DATABASE=Liqid Inc.
pci:v00001DD8*
- ID_VENDOR_FROM_DATABASE=Pensando Systems Inc
+ ID_VENDOR_FROM_DATABASE=Pensando Systems
pci:v00001DD8d00001000*
ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port
pci:v00001DD8d00001000sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001000sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001000sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001000sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DD8d00001001*
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port
pci:v00001DD8d00001001sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001001sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001001sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001001sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DD8d00001002*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller
pci:v00001DD8d00001002sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001002sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001002sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001002sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DD8d00001003*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF
pci:v00001DD8d00001003sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001003sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001003sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001003sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DD8d00001004*
ID_MODEL_FROM_DATABASE=DSC Management Controller
pci:v00001DD8d00001004sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001004sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001004sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Management Controller (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001004sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DD8d00001007*
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator
pci:v00001DD8d00001007sv00001DD8sd00004002*
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)
+
pci:v00001DD8d00001007sv00001DD8sd00004008*
ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-25 10/25G 2-port SFP28 x8 4GB RAM 8GB eMMC)
+pci:v00001DD8d00001007sv00001DD8sd0000400A*
+ ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (DSC-100 40/100G 2-port 8G RAM 16G eMMC G1 Services Card)
+
+pci:v00001DD8d00001007sv00001DD8sd0000400C*
+ 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)
+
pci:v00001DE0*
ID_VENDOR_FROM_DATABASE=Groq
pci:v00001DE5d00002000*
ID_MODEL_FROM_DATABASE=NoLoad Hardware Development Kit
+pci:v00001DE5d00003000*
+ ID_MODEL_FROM_DATABASE=eBPF-based PCIe Accelerator
+
pci:v00001DEE*
ID_VENDOR_FROM_DATABASE=Biwin Storage Technology Co., Ltd.
pci:v00001DF3d00000204sv00001DF3sd00000002*
ID_MODEL_FROM_DATABASE=ACE-NIC-NID Programmable Network Accelerator (ENA1020ZS)
+pci:v00001DF3d00000205*
+ ID_MODEL_FROM_DATABASE=ACE-NIC250 Programmable Network Accelerator
+
+pci:v00001DF3d00000205sv00001DF3sd00000000*
+ ID_MODEL_FROM_DATABASE=ACE-NIC250 Programmable Network Accelerator (Maintenance Mode)
+
+pci:v00001DF3d00000205sv00001DF3sd00000001*
+ ID_MODEL_FROM_DATABASE=ACE-NIC250 Programmable Network Accelerator (ENA2250F)
+
+pci:v00001DF3d00000206*
+ ID_MODEL_FROM_DATABASE=ACE-NIC200 Programmable Network Accelerator
+
+pci:v00001DF3d00000206sv00001DF3sd00000000*
+ ID_MODEL_FROM_DATABASE=ACE-NIC200 Programmable Network Accelerator (Maintenance Mode)
+
+pci:v00001DF3d00000206sv00001DF3sd00000001*
+ ID_MODEL_FROM_DATABASE=ACE-NIC200 Programmable Network Accelerator (ENA2200F)
+
pci:v00001DF7*
ID_VENDOR_FROM_DATABASE=opencpi.org
pci:v00001E0Fd00000007*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6
+pci:v00001E0Fd00000007sv00001028sd00002078*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (DC NVMe CD6 RI 960GB)
+
+pci:v00001E0Fd00000007sv00001028sd00002079*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (DC NVMe CD6 RI 1.92TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000207A*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (DC NVMe CD6 RI 3.84TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000207B*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (DC NVMe CD6 RI 7.68TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000207C*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (DC NVMe CD6 RI 15.36TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000207E*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 RI 1.92TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000207F*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 RI 3.84TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002080*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 RI 7.68TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002081*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 RI 15.36TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002084*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 MU 1.6TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002085*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 MU 3.2TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002086*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe CM6 MU 6.4TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210A*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 RI 1.92TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210B*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 RI 3.84TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210C*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 RI 7.68TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210D*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 RI15.36TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210E*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 MU 1.6TB)
+
+pci:v00001E0Fd00000007sv00001028sd0000210F*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 MU 3.2TB)
+
+pci:v00001E0Fd00000007sv00001028sd00002110*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Dell Ent NVMe FIPS CM6 MU 6.4TB)
+
+pci:v00001E0Fd00000007sv00001E0Fsd00000001*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx6 (Generic NVMe CM6 RI 3.84TB)
+
pci:v00001E17*
ID_VENDOR_FROM_DATABASE=Arnold & Richter Cine Technik GmbH & Co. Betriebs KG
pci:v00001E38*
ID_VENDOR_FROM_DATABASE=Blaize, Inc
+pci:v00001E38d00000102*
+ ID_MODEL_FROM_DATABASE=Xplorer X1600
+
pci:v00001E3D*
ID_VENDOR_FROM_DATABASE=Burlywood, Inc
pci:v00001E6B*
ID_VENDOR_FROM_DATABASE=Axiado Corp.
+pci:v00001E7C*
+ ID_VENDOR_FROM_DATABASE=Brainchip Inc
+
+pci:v00001E7Cd0000BCA1*
+ ID_MODEL_FROM_DATABASE=AKD1000 Neural Network Coprocessor [Akida]
+
pci:v00001E85*
ID_VENDOR_FROM_DATABASE=Heitec AG
pci:v00001E95*
ID_VENDOR_FROM_DATABASE=Solid State Storage Technology Corporation
+pci:v00001EB1*
+ ID_VENDOR_FROM_DATABASE=VeriSilicon Inc
+
+pci:v00001EB1d00001001*
+ ID_MODEL_FROM_DATABASE=Video Accelerator
+
pci:v00001FC0*
ID_VENDOR_FROM_DATABASE=Ascom (Finland) Oy
pci:v00002646*
ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc.
+pci:v00002646d00002263*
+ ID_MODEL_FROM_DATABASE=A2000, M.2, 500GB
+
pci:v0000270B*
ID_VENDOR_FROM_DATABASE=Xantel Corporation
ID_MODEL_FROM_DATABASE=AS-i 3.0 PCI Master
pci:v00003475*
- ID_VENDOR_FROM_DATABASE=Arastra Inc.
+ ID_VENDOR_FROM_DATABASE=Arista Networks, Inc.
pci:v00003513*
ID_VENDOR_FROM_DATABASE=ARCOM Control Systems Ltd
pci:v00003D3Dd000007A2*
ID_MODEL_FROM_DATABASE=Sun XVR-500 Graphics Accelerator
+pci:v00003D3Dd000007A2sv00003D3Dsd00001047*
+ ID_MODEL_FROM_DATABASE=Sun XVR-500 Graphics Accelerator (Sun XVR-600 Graphics Accelerator)
+
pci:v00003D3Dd000007A3*
ID_MODEL_FROM_DATABASE=Wildcat IV 7210
pci:v00008086d00000176*
ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller
+pci:v00008086d00000284*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP LPC Premium Controller/eSPI Controller
+
+pci:v00008086d000002A3*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP SMBus Host Controller
+
pci:v00008086d000002A4*
ID_MODEL_FROM_DATABASE=Comet Lake SPI (flash) Controller
pci:v00008086d000002A6*
ID_MODEL_FROM_DATABASE=Comet Lake North Peak
+pci:v00008086d000002C8*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP cAVS
+
pci:v00008086d000002D3*
ID_MODEL_FROM_DATABASE=Comet Lake SATA AHCI Controller
pci:v00008086d000002E9*
ID_MODEL_FROM_DATABASE=Comet Lake Serial IO I2C Host Controller
+pci:v00008086d000002ED*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP USB 3.1 xHCI Host Controller
+
+pci:v00008086d000002EF*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP Shared SRAM
+
pci:v00008086d000002F0*
- ID_MODEL_FROM_DATABASE=Wireless-AC 9462
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP CNVi WiFi
+
+pci:v00008086d000002F0sv00008086sd00000034*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP CNVi WiFi (Wireless-AC 9560 160MHz)
pci:v00008086d000002F0sv00008086sd00000070*
- ID_MODEL_FROM_DATABASE=Wireless-AC 9462 (Intel(R) Wi-Fi 6 AX201 160MHz)
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP CNVi WiFi (Wi-Fi 6 AX201 160MHz)
+
+pci:v00008086d000002F0sv00008086sd00000074*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP CNVi WiFi (Wi-Fi 6 AX201 160MHz)
+
+pci:v00008086d000002F5*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-LP SCS3
pci:v00008086d000002F9*
ID_MODEL_FROM_DATABASE=Comet Lake Thermal Subsytem
pci:v00008086d00000412*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller
+pci:v00008086d00000412sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (EliteDesk 800 G1)
+
pci:v00008086d00000412sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (ThinkCentre M83)
ID_MODEL_FROM_DATABASE=Comet Lake PCH Shared SRAM
pci:v00008086d000006F0*
- ID_MODEL_FROM_DATABASE=Wi-Fi 6 AX201
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH CNVi WiFi
+
+pci:v00008086d000006F0sv00008086sd00000034*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH CNVi WiFi (Wireless-AC 9560)
+
+pci:v00008086d000006F0sv00008086sd00000074*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH CNVi WiFi (Wi-Fi 6 AX201 160MHz)
+
+pci:v00008086d000006F0sv00008086sd000002A4*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH CNVi WiFi (Wireless-AC 9462)
pci:v00008086d000006F9*
ID_MODEL_FROM_DATABASE=Comet Lake PCH Thermal Controller
ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem U.2 P4610 NVMe SSD)
pci:v00008086d00000A54sv00008086sd00004308*
- ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Intel SSD D5-P4320 and D5-P4326)
+ ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (SSD D5-P4320 and D5-P4326)
pci:v00008086d00000A54sv00008086sd00004702*
ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4500))
pci:v00008086d00000C00*
ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller
+pci:v00008086d00000C00sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (EliteDesk 800 G1)
+
pci:v00008086d00000C00sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (ThinkCentre M83)
pci:v00008086d00000C0C*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller
+pci:v00008086d00000C0Csv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (EliteDesk 800 G1)
+
pci:v00008086d00000C0Csv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (ThinkPad T440p)
pci:v00008086d0000153Asv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ZBook 15)
+pci:v00008086d0000153Asv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (EliteDesk 800 G1)
+
pci:v00008086d0000153Asv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ThinkPad T440p)
pci:v00008086d00001592sv00008086sd0000000B*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet 100G 2P E810-C Adapter)
+pci:v00008086d00001592sv00008086sd0000000C*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet 100G 2P E810-C OCP)
+
pci:v00008086d00001593*
ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP
ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2
pci:v00008086d000015D5sv00008086sd00000001*
- ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2 (Intel(R) Ethernet SDI Adapter FM10420-25GbE-DA2)
+ ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2
pci:v00008086d000015D6*
ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-V
ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 USB Controller [Titan Ridge DD 2018]
pci:v00008086d000015F2*
- ID_MODEL_FROM_DATABASE=Intel(R) Ethernet Controller I225-LM
+ ID_MODEL_FROM_DATABASE=Ethernet Controller I225-LM
+
+pci:v00008086d000015F2sv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller I225-LM (Ethernet Network Adapter I225-T1)
+
+pci:v00008086d000015F2sv00008086sd00000002*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller I225-LM (Ethernet Network Adapter I225-T1)
pci:v00008086d000015F3*
- ID_MODEL_FROM_DATABASE=Intel(R) Ethernet Controller I225-V
+ ID_MODEL_FROM_DATABASE=Ethernet Controller I225-V
pci:v00008086d000015F4*
ID_MODEL_FROM_DATABASE=Ethernet Connection (15) I219-LM
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=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16)
+ ID_MODEL_FROM_DATABASE=6th-9th Gen Core Processor PCIe Controller (x16)
pci:v00008086d00001902*
ID_MODEL_FROM_DATABASE=HD Graphics 510
pci:v00008086d000027E2sv00001775sd000011CC*
ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 (CC11/CL11)
-pci:v00008086d0000280B*
- ID_MODEL_FROM_DATABASE=Intel(R) Display Audio
-
pci:v00008086d00002810*
ID_MODEL_FROM_DATABASE=82801HB/HR (ICH8/R) LPC Interface Controller
pci:v00008086d00002FFE*
ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers
+pci:v00008086d00003140*
+ ID_MODEL_FROM_DATABASE=Easel/Monette Hill Image Processor [Pixel Visual Core]
+
pci:v00008086d00003165*
ID_MODEL_FROM_DATABASE=Wireless 3165
pci:v00008086d0000318E*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor NorthPeak
+pci:v00008086d00003190*
+ ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Gaussian Mixture Model
+
pci:v00008086d00003192*
ID_MODEL_FROM_DATABASE=Gemini Lake P2SB
pci:v00008086d000031DB*
ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port
+pci:v00008086d000031DC*
+ ID_MODEL_FROM_DATABASE=AC 1550i Wireless
+
pci:v00008086d000031EE*
ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller
pci:v00008086d000037C8*
ID_MODEL_FROM_DATABASE=C62x Chipset QuickAssist Technology
+pci:v00008086d000037C8sv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=C62x Chipset QuickAssist Technology (QuickAssist Adapter 8960)
+
+pci:v00008086d000037C8sv00008086sd00000002*
+ ID_MODEL_FROM_DATABASE=C62x Chipset QuickAssist Technology (QuickAssist Adapter 8970)
+
pci:v00008086d000037CC*
ID_MODEL_FROM_DATABASE=Ethernet Connection X722
ID_MODEL_FROM_DATABASE=8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] (Z370 AORUS Gaming K3-CF)
pci:v00008086d00003E30*
- ID_MODEL_FROM_DATABASE=8th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S]
+ ID_MODEL_FROM_DATABASE=8th/9th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S]
pci:v00008086d00003E33*
ID_MODEL_FROM_DATABASE=8th/9th Gen Core Processor Host Bridge/DRAM Registers [Coffee Lake]
ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #3
pci:v00008086d00008A51*
- ID_MODEL_FROM_DATABASE=Intel Iris Plus Graphics G7 (Ice Lake)
+ ID_MODEL_FROM_DATABASE=Iris Plus Graphics G7 (Ice Lake)
pci:v00008086d00008A52*
ID_MODEL_FROM_DATABASE=Iris Plus Graphics G7
ID_MODEL_FROM_DATABASE=Iris Plus Graphics G4 (Ice Lake)
pci:v00008086d00008A5C*
- ID_MODEL_FROM_DATABASE=Intel Iris Plus Graphics G4 (Ice Lake)
+ ID_MODEL_FROM_DATABASE=Iris Plus Graphics G4 (Ice Lake)
pci:v00008086d00008C00*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode]
pci:v00008086d00008C02*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
+pci:v00008086d00008C02sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (EliteDesk 800 G1)
+
pci:v00008086d00008C02sv000017AAsd0000309F*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkCentre M83)
pci:v00008086d00008C10*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1
+pci:v00008086d00008C10sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (EliteDesk 800 G1)
+
pci:v00008086d00008C10sv00001043sd00008534*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (ASUS H81I-PLUS)
pci:v00008086d00008C12*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2
+pci:v00008086d00008C12sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 (EliteDesk 800 G1)
+
pci:v00008086d00008C12sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 (ThinkPad T440p)
pci:v00008086d00008C20sv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ZBook 15)
+pci:v00008086d00008C20sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (EliteDesk 800 G1)
+
pci:v00008086d00008C20sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ThinkPad T440p)
pci:v00008086d00008C22sv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ZBook 15)
+pci:v00008086d00008C22sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (EliteDesk 800 G1)
+
pci:v00008086d00008C22sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkPad T440p)
pci:v00008086d00008C26sv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ZBook 15)
+pci:v00008086d00008C26sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (EliteDesk 800 G1)
+
pci:v00008086d00008C26sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T440p)
pci:v00008086d00008C2Dsv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ZBook 15)
+pci:v00008086d00008C2Dsv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (EliteDesk 800 G1)
+
pci:v00008086d00008C2Dsv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkPad T440p)
pci:v00008086d00008C31sv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ZBook 15)
+pci:v00008086d00008C31sv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (EliteDesk 800 G1)
+
pci:v00008086d00008C31sv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkPad T440p)
pci:v00008086d00008C3Asv0000103Csd00001909*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ZBook 15)
+pci:v00008086d00008C3Asv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (EliteDesk 800 G1)
+
pci:v00008086d00008C3Asv000017AAsd0000220E*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkPad T440p)
pci:v00008086d00008C3D*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family KT Controller
+pci:v00008086d00008C3Dsv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family KT Controller (EliteDesk 800 G1)
+
pci:v00008086d00008C40*
ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C4E*
ID_MODEL_FROM_DATABASE=Q87 Express LPC Controller
+pci:v00008086d00008C4Esv0000103Csd00001998*
+ ID_MODEL_FROM_DATABASE=Q87 Express LPC Controller (EliteDesk 800 G1)
+
pci:v00008086d00008C4F*
ID_MODEL_FROM_DATABASE=QM87 Express LPC 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:v00008086d00009B64*
ID_MODEL_FROM_DATABASE=10th Gen Core Processor Host Bridge/DRAM Registers
pci:v00008086d00009BC4*
ID_MODEL_FROM_DATABASE=UHD Graphics
+pci:v00008086d00009BC8*
+ ID_MODEL_FROM_DATABASE=UHD Graphics 630
+
pci:v00008086d00009C00*
ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode]
pci:v00008086d0000A379sv00001028sd00000869*
ID_MODEL_FROM_DATABASE=Cannon Lake PCH Thermal Controller (Vostro 3470)
+pci:v00008086d0000A382*
+ ID_MODEL_FROM_DATABASE=400 Series Chipset Family SATA AHCI Controller
+
+pci:v00008086d0000A3A3*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-V SMBus Host Controller
+
+pci:v00008086d0000A3B1*
+ ID_MODEL_FROM_DATABASE=Comet Lake PCH-V Thermal Subsystem
+
pci:v00008086d0000A620*
ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB)
ID_MODEL_FROM_DATABASE=SSD Pro 7600p/760p/E 6100p Series
pci:v00008086d0000F1A6sv00008086sd0000390B*
- ID_MODEL_FROM_DATABASE=SSD Pro 7600p/760p/E 6100p Series (Intel Corporation SSD Pro 7600p/760p/E 6100p Series [NVM Express])
+ ID_MODEL_FROM_DATABASE=SSD Pro 7600p/760p/E 6100p Series ([NVM Express])
pci:v00008086d0000F1A8*
ID_MODEL_FROM_DATABASE=SSD 660P Series
ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0)
pci:v00009005d0000028F*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS
pci:v00009005d0000028Fsv0000103Csd00000600*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-p SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P408i-p SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000601*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-p SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P408e-p SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000602*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-a SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P408i-a SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000603*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-c SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P408i-c SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000650*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-p SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array E208i-p SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000651*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208e-p SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array E208e-p SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000652*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-c SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array E208i-c SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000654*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-a SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array E208i-a SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000655*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-m SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P408e-m SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000700*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-c SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P204i-c SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00000701*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-b SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P204i-b SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00001100*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P816i-a SR Gen10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P816i-a SR Gen10)
pci:v00009005d0000028Fsv0000103Csd00001101*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P416ie-m SR G10)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (Smart Array P416ie-m SR G10)
pci:v00009005d0000028Fsv0000105Bsd00001211*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 8238-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 8238-16i)
pci:v00009005d0000028Fsv0000105Bsd00001321*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 8242-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 8242-24i)
pci:v00009005d0000028Fsv000013FEsd00008312*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SKY-9200 MIC-8312BridgeB)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SKY-9200 MIC-8312BridgeB)
pci:v00009005d0000028Fsv0000152Dsd00008A22*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8204-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (QS-8204-8i)
pci:v00009005d0000028Fsv0000152Dsd00008A23*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8238-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (QS-8238-16i)
pci:v00009005d0000028Fsv0000152Dsd00008A24*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8236-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (QS-8236-16i)
pci:v00009005d0000028Fsv0000152Dsd00008A36*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8240-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (QS-8240-24i)
pci:v00009005d0000028Fsv0000152Dsd00008A37*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8242-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (QS-8242-24i)
pci:v00009005d0000028Fsv0000193Dsd00008460*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA H460-M1)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA H460-M1)
pci:v00009005d0000028Fsv0000193Dsd00008461*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA H460-B1)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA H460-B1)
pci:v00009005d0000028Fsv0000193Dsd0000C460*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-M2)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID P460-M2)
pci:v00009005d0000028Fsv0000193Dsd0000C461*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-B2)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID P460-B2)
pci:v00009005d0000028Fsv0000193Dsd0000F460*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-M4)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID P460-M4)
pci:v00009005d0000028Fsv0000193Dsd0000F461*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-B4)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID P460-B4)
pci:v00009005d0000028Fsv000019E5sd0000D227*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC-HD SR465C-M 4G)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartROC-HD SR465C-M 4G)
pci:v00009005d0000028Fsv000019E5sd0000D228*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC SR455C-M 2G)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartROC SR455C-M 2G)
pci:v00009005d0000028Fsv000019E5sd0000D229*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartIOC SR155-M)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartIOC SR155-M)
pci:v00009005d0000028Fsv000019E5sd0000D22A*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartIOC-HD SR765-M)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartIOC-HD SR765-M)
pci:v00009005d0000028Fsv000019E5sd0000D22B*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC-e SR455C-ME 4G)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartROC-e SR455C-ME 4G)
pci:v00009005d0000028Fsv000019E5sd0000D22C*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC SR455C-M 4G)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartROC SR455C-M 4G)
pci:v00009005d0000028Fsv00001BD4sd00000045*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SMART-HBA 8242-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SMART-HBA 8242-24i)
pci:v00009005d0000028Fsv00001BD4sd00000046*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID 8236-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID 8236-16i)
pci:v00009005d0000028Fsv00001BD4sd00000047*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID 8240-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID 8240-24i)
pci:v00009005d0000028Fsv00001BD4sd00000048*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SMART-HBA 8238-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SMART-HBA 8238-16i)
pci:v00009005d0000028Fsv00001BD4sd0000004A*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (PM8222-SHBA)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (PM8222-SHBA)
pci:v00009005d0000028Fsv00001BD4sd0000004B*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID PM8204-2GB)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID PM8204-2GB)
pci:v00009005d0000028Fsv00001BD4sd0000004C*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID PM8204-4GB)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (RAID PM8204-4GB)
pci:v00009005d0000028Fsv00001BD4sd0000004F*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (PM8222-HBA)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (PM8222-HBA)
pci:v00009005d0000028Fsv00009005sd00000608*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3162-8i /e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3162-8i /e)
pci:v00009005d0000028Fsv00009005sd00000800*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-8i)
pci:v00009005d0000028Fsv00009005sd00000801*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3152-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3152-8i)
pci:v00009005d0000028Fsv00009005sd00000802*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3151-4i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3151-4i)
pci:v00009005d0000028Fsv00009005sd00000803*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3101-4i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3101-4i)
pci:v00009005d0000028Fsv00009005sd00000804*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-8e)
pci:v00009005d0000028Fsv00009005sd00000805*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3102-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3102-8i)
pci:v00009005d0000028Fsv00009005sd00000806*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3100)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3100)
pci:v00009005d0000028Fsv00009005sd00000807*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3162-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3162-8i)
pci:v00009005d0000028Fsv00009005sd00000900*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-8i)
pci:v00009005d0000028Fsv00009005sd00000901*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-4i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-4i)
pci:v00009005d0000028Fsv00009005sd00000902*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-8i)
pci:v00009005d0000028Fsv00009005sd00000903*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-4i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-4i)
pci:v00009005d0000028Fsv00009005sd00000904*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-8e)
pci:v00009005d0000028Fsv00009005sd00000905*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-8e)
pci:v00009005d0000028Fsv00009005sd00000906*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-4i4e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-4i4e)
pci:v00009005d0000028Fsv00009005sd00000907*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100)
pci:v00009005d0000028Fsv00009005sd00000908*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100)
pci:v00009005d0000028Fsv00009005sd0000090A*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100A-8i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100A-8i)
pci:v00009005d0000028Fsv00009005sd00001200*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-24i)
pci:v00009005d0000028Fsv00009005sd00001201*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i16e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-8i16e)
pci:v00009005d0000028Fsv00009005sd00001202*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-8i8e)
pci:v00009005d0000028Fsv00009005sd00001280*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-16i)
pci:v00009005d0000028Fsv00009005sd00001281*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-16e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-16e)
pci:v00009005d0000028Fsv00009005sd00001300*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8i8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-8i8e)
pci:v00009005d0000028Fsv00009005sd00001301*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (HBA 1100-24i)
pci:v00009005d0000028Fsv00009005sd00001302*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8i8e)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-8i8e)
pci:v00009005d0000028Fsv00009005sd00001303*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-24i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartHBA 2100-24i)
pci:v00009005d0000028Fsv00009005sd00001380*
- ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-16i)
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI SAS (SmartRAID 3154-16i)
pci:v00009005d00000410*
ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID)
usb:v03F0p311D*
ID_MODEL_FROM_DATABASE=Atheros AR9285 Malbec Bluetooth Adapter
+usb:v03F0p312A*
+ ID_MODEL_FROM_DATABASE=LaserJet Pro M701n
+
usb:v03F0p3202*
ID_MODEL_FROM_DATABASE=PhotoSmart 1215
usb:v041Ep3237*
ID_MODEL_FROM_DATABASE=SB X-Fi Surround 5.1 Pro
+usb:v041Ep3263*
+ ID_MODEL_FROM_DATABASE=SB X-Fi Surround 5.1 Pro
+
usb:v041Ep3F00*
ID_MODEL_FROM_DATABASE=E-Mu Xboard 25 MIDI Controller
usb:v046DpC231*
ID_MODEL_FROM_DATABASE=G13 Virtual Mouse
+usb:v046DpC232*
+ ID_MODEL_FROM_DATABASE=Gaming Virtual Keyboard
+
usb:v046DpC245*
ID_MODEL_FROM_DATABASE=G400 Optical Mouse
usb:v047FpC03B*
ID_MODEL_FROM_DATABASE=HD1
+usb:v047FpDA60*
+ ID_MODEL_FROM_DATABASE=DA60
+
usb:v0480*
ID_VENDOR_FROM_DATABASE=Toshiba America Inc
ID_MODEL_FROM_DATABASE=Flash Drive
usb:v048Dp1234*
- ID_MODEL_FROM_DATABASE=Mass storage
+ ID_MODEL_FROM_DATABASE=Chipsbank CBM2199 Flash Drive
usb:v048Dp1336*
ID_MODEL_FROM_DATABASE=SD/MMC Cardreader
usb:v04D9pA055*
ID_MODEL_FROM_DATABASE=Keyboard
+usb:v04D9pA075*
+ ID_MODEL_FROM_DATABASE=Optical Gaming Mouse
+
usb:v04D9pA096*
ID_MODEL_FROM_DATABASE=Keyboard
ID_MODEL_FROM_DATABASE=GT-I9100 / GT-C3350 Phones (USB Debugging mode)
usb:v04E8p6860*
- ID_MODEL_FROM_DATABASE=Galaxy series, misc. (MTP mode)
+ ID_MODEL_FROM_DATABASE=Galaxy A5 (MTP)
usb:v04E8p6863*
ID_MODEL_FROM_DATABASE=Galaxy series, misc. (tethering mode)
ID_MODEL_FROM_DATABASE=File-backed Storage Gadget
usb:v0525p3424*
- ID_MODEL_FROM_DATABASE=Lumidigm Venus fingerprint sensor
+ ID_MODEL_FROM_DATABASE=V30x/V4xx fingerprint sensor [Lumidigm]
usb:v0525pA0F0*
ID_MODEL_FROM_DATABASE=Cambridge Electronic Devices Power1401 mk 2
ID_MODEL_FROM_DATABASE=Linux-USB user-mode bulk source/sink
usb:v0525pA4A5*
- ID_MODEL_FROM_DATABASE=Pocketbook Pro 903 / Mobius 2 Action Cam / xDuoo X3
+ ID_MODEL_FROM_DATABASE=Pocketbook Pro 903 / Mobius 2 Action Cam / xDuoo X3 / PocketBook Pro 602
usb:v0525pA4A6*
ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget
usb:v054Cp035F*
ID_MODEL_FROM_DATABASE=UP-DR200 Photo Printer
+usb:v054Cp0360*
+ ID_MODEL_FROM_DATABASE=M2 Card Reader
+
usb:v054Cp0382*
ID_MODEL_FROM_DATABASE=Memory Stick PRO-HG Duo Adaptor (MSAC-UAH1)
usb:v059Fp1094*
ID_MODEL_FROM_DATABASE=Rugged THB
+usb:v059Fp1095*
+ ID_MODEL_FROM_DATABASE=Rugged
+
usb:v059FpA601*
ID_MODEL_FROM_DATABASE=HardDrive
usb:v05A7p4003*
ID_MODEL_FROM_DATABASE=Bluetooth Headset Series 2 in DFU mode
+usb:v05A7p400D*
+ ID_MODEL_FROM_DATABASE=SoundLink Color II speaker in DFU mode
+
+usb:v05A7p40FE*
+ ID_MODEL_FROM_DATABASE=SoundLink Color II speaker
+
usb:v05A7pBC50*
ID_MODEL_FROM_DATABASE=SoundLink Wireless Mobile speaker
usb:v05C8p0374*
ID_MODEL_FROM_DATABASE=HP EliteBook integrated HD Webcam
+usb:v05C8p038E*
+ ID_MODEL_FROM_DATABASE=HP Wide Vision HD integrated webcam
+
usb:v05C8p03A1*
ID_MODEL_FROM_DATABASE=XiaoMi Webcam
ID_MODEL_FROM_DATABASE=Orico SATA External Hard Disk Drive Lay-Flat Docking Station with USB 3.0 & eSATA interfaces.
usb:v067Bp2303*
- ID_MODEL_FROM_DATABASE=PL2303 Serial Port
+ ID_MODEL_FROM_DATABASE=PL2303 Serial Port / Mobile Action MA-8910P
usb:v067Bp2305*
ID_MODEL_FROM_DATABASE=PL2305 Parallel Port
usb:v06BCp02BB*
ID_MODEL_FROM_DATABASE=OKI PT390 POS Printer
+usb:v06BCp0383*
+ ID_MODEL_FROM_DATABASE=MC563 Multifunction Printer
+
usb:v06BCp0A91*
ID_MODEL_FROM_DATABASE=B2500MFP (printer+scanner)
usb:v0781pB6BA*
ID_MODEL_FROM_DATABASE=CF SDDR-289
+usb:v0781pCFC9*
+ ID_MODEL_FROM_DATABASE=SDDR-489 ImageMate Pro Reader
+
usb:v0782*
ID_VENDOR_FROM_DATABASE=Trackerball
usb:v096Ep0005*
ID_MODEL_FROM_DATABASE=ePass2000
+usb:v096Ep0006*
+ ID_MODEL_FROM_DATABASE=HID Dongle (for OEMs - manufacturer string is "OEM")
+
usb:v096Ep0120*
ID_MODEL_FROM_DATABASE=Microcosm Ltd Dinkey
usb:v0A5Fp0050*
ID_MODEL_FROM_DATABASE=P120i / WM120i
+usb:v0A5Fp0080*
+ ID_MODEL_FROM_DATABASE=GK420d Label Printer
+
usb:v0A5Fp0081*
ID_MODEL_FROM_DATABASE=GK420t Label Printer
usb:v0A82p4600*
ID_MODEL_FROM_DATABASE=TravelScan 460/464
+usb:v0A82p6605*
+ ID_MODEL_FROM_DATABASE=ScanShell 800N
+
usb:v0A83*
ID_VENDOR_FROM_DATABASE=NextComm, Inc.
usb:v0BDApB812*
ID_MODEL_FROM_DATABASE=RTL88x2bu [AC1200 Techkey]
+usb:v0BDApF179*
+ ID_MODEL_FROM_DATABASE=RTL8188FTV 802.11b/g/n 1T1R 2.4G WLAN Adapter
+
usb:v0BDB*
ID_VENDOR_FROM_DATABASE=Ericsson Business Mobile Networks BV
usb:v0C3E*
ID_VENDOR_FROM_DATABASE=Nextcell, Inc.
+usb:v0C40*
+ ID_VENDOR_FROM_DATABASE=ELMCU
+
+usb:v0C40p8000*
+ ID_MODEL_FROM_DATABASE=2.4GHz receiver
+
usb:v0C44*
ID_VENDOR_FROM_DATABASE=Motorola iDEN
usb:v0C45p1A90*
ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera (with capture button) [Andonstar V160]
+usb:v0C45p5004*
+ ID_MODEL_FROM_DATABASE=Redragon Mitra RGB Keyboard
+
usb:v0C45p5101*
ID_MODEL_FROM_DATABASE=2.4G Wireless Device [Rii MX3]
ID_VENDOR_FROM_DATABASE=INTELLIGENT SYSTEMS
usb:v0F6Ep0100*
- ID_MODEL_FROM_DATABASE=GameBoy Color Emulator
+ ID_MODEL_FROM_DATABASE=IS-CGB-EMULATOR
usb:v0F6Ep0201*
ID_MODEL_FROM_DATABASE=GameBoy Advance Flash Gang Writer
usb:v0F6Ep0202*
- ID_MODEL_FROM_DATABASE=GameBoy Advance Capture
+ ID_MODEL_FROM_DATABASE=IS-AGB-CAPTURE
usb:v0F6Ep0300*
- ID_MODEL_FROM_DATABASE=Gamecube DOL Viewer
+ ID_MODEL_FROM_DATABASE=IS-DOL-VIEWER
usb:v0F6Ep0400*
- ID_MODEL_FROM_DATABASE=NDS Emulator
+ ID_MODEL_FROM_DATABASE=IS-NITRO-EMULATOR
usb:v0F6Ep0401*
- ID_MODEL_FROM_DATABASE=NDS UIC
+ ID_MODEL_FROM_DATABASE=IS-NITRO-UIC
usb:v0F6Ep0402*
- ID_MODEL_FROM_DATABASE=NDS Writer
+ ID_MODEL_FROM_DATABASE=IS-NITRO-WRITER
usb:v0F6Ep0403*
- ID_MODEL_FROM_DATABASE=NDS Capture
+ ID_MODEL_FROM_DATABASE=IS-NITRO-CAPTURE
usb:v0F6Ep0404*
- ID_MODEL_FROM_DATABASE=NDS Emulator (Lite)
+ ID_MODEL_FROM_DATABASE=IS-NITRO-EMULATOR (DS Lite)
+
+usb:v0F6Ep0500*
+ ID_MODEL_FROM_DATABASE=IS-TWL-DEBUGGER
+
+usb:v0F6Ep0501*
+ ID_MODEL_FROM_DATABASE=IS-TWL-CAPTURE
usb:v0F73*
ID_VENDOR_FROM_DATABASE=DFI
usb:v1504p001F*
ID_MODEL_FROM_DATABASE=SRP-350II Thermal Receipt Printer
+usb:v1508*
+ ID_VENDOR_FROM_DATABASE=Fibocom
+
usb:v1509*
ID_VENDOR_FROM_DATABASE=First International Computer, Inc.
usb:v1532p004D*
ID_MODEL_FROM_DATABASE=DeathAdder 2000 (Cynosa Pro Bundle)
+usb:v1532p004F*
+ ID_MODEL_FROM_DATABASE=RZ01-0145, Gaming Mouse [DeathAdder 2000 (Alternate)]
+
usb:v1532p0050*
ID_MODEL_FROM_DATABASE=Naga Hex V2
usb:v1532p007E*
ID_MODEL_FROM_DATABASE=RC30-030502 Mouse Dock
+usb:v1532p0083*
+ ID_MODEL_FROM_DATABASE=RC30-0315, Gaming Mouse [Basilisk X HyperSpeed]
+
usb:v1532p0084*
ID_MODEL_FROM_DATABASE=RZ01-0321 Gaming Mouse [DeathAdder V2]
usb:v1532p0085*
ID_MODEL_FROM_DATABASE=RZ01-0316 Gaming Mouse [Basilisk V2]
+usb:v1532p0086*
+ ID_MODEL_FROM_DATABASE=Gaming Mouse [Basilisk Ultimate, Wired]
+
usb:v1532p0088*
- ID_MODEL_FROM_DATABASE=Razer Basilisk Ultimate Dongle
+ ID_MODEL_FROM_DATABASE=Gaming Mouse [Basilisk Ultimate, Wireless, Receiver]
+
+usb:v1532p008A*
+ ID_MODEL_FROM_DATABASE=RZ01-0325, Gaming Mouse [Viper Mini]
usb:v1532p0101*
ID_MODEL_FROM_DATABASE=Copperhead Mouse
usb:v1532p0255*
ID_MODEL_FROM_DATABASE=RZ09-0328, Gaming Laptop [Blade 15 Base Model (2020)]
+usb:v1532p0256*
+ ID_MODEL_FROM_DATABASE=RZ09--0329, Gaming Laptop [Blade Pro 17 Full HD (2020)]
+
+usb:v1532p025D*
+ ID_MODEL_FROM_DATABASE=RZ03-0338, Gaming Keyboard [Ornata V2]
+
usb:v1532p0300*
ID_MODEL_FROM_DATABASE=RZ06-0063 Motion Sensing Controllers [Hydra]
usb:v1532p051D*
ID_MODEL_FROM_DATABASE=Nari (Wired)
+usb:v1532p051E*
+ ID_MODEL_FROM_DATABASE=RC30-026902, Gaming Headset [Nari Essential, Wireless, Receiver]
+
+usb:v1532p051F*
+ ID_MODEL_FROM_DATABASE=RC30-026901, Gaming Headset [Nari Essential, Wired]
+
usb:v1532p0520*
ID_MODEL_FROM_DATABASE=Kraken Tournament Edition
usb:v1532p0A03*
ID_MODEL_FROM_DATABASE=Wildcat
+usb:v1532p0A15*
+ ID_MODEL_FROM_DATABASE=RZ06-0199, Gaming Controller [Wolverine Tournament Edition]
+
usb:v1532p0C00*
ID_MODEL_FROM_DATABASE=RZ02-0135 Hard Gaming Mouse Mat [Firefly]
usb:v1605p0001*
ID_MODEL_FROM_DATABASE=DIO-32 (No Firmware Yet)
+usb:v1605p0002*
+ ID_MODEL_FROM_DATABASE=USB-DIO-48 (No Firmware Yet)
+
+usb:v1605p0003*
+ ID_MODEL_FROM_DATABASE=USB-DIO-96 (No Firmware Yet)
+
+usb:v1605p0004*
+ ID_MODEL_FROM_DATABASE=USB-DIO-32I (No Firmware Yet)
+
+usb:v1605p0005*
+ ID_MODEL_FROM_DATABASE=USB-DIO24 (based on -CTR6) (No Firmware Yet)
+
+usb:v1605p0006*
+ ID_MODEL_FROM_DATABASE=USB-DIO24-CTR6 (No Firmware Yet)
+
usb:v1606*
ID_VENDOR_FROM_DATABASE=Umax
# Match string formats:
# <subsystem>:<modalias>
#
-# pci:v<vendor>d<device>
-# usb:v<vendor>p<product>
+# pci:v<vendor>d<device>:
+# usb:v<vendor>p<product>:
#
# To add local entries, create a new file
# /etc/udev/hwdb.d/61-autosuspend-local.hwdb
#
# Allowed properties are:
# ID_AUTOSUSPEND=1
-
#
+# All matches should end in ':*' to allow future expansions of the match key.
+
# Sort by brand, model
#########################################
#########################################
# AU9540 Smartcard Reader
-usb:v058Fp9540*
+usb:v058Fp9540:*
+ ID_AUTOSUSPEND=1
+
+#########################################
+# Lenovo
+#########################################
+
+# X1C8 Touchscreen
+usb:v04F3p2B7C:*
+# T14 Gen 1 Touchscreen
+usb:v04F3p2ACC:*
ID_AUTOSUSPEND=1
#########################################
#########################################
# Emulated USB HID devices
-usb:v0627p0001:*QEMU USB Keyboard*
-usb:v0627p0001:*QEMU USB Mouse*
-usb:v0627p0001:*QEMU USB Tablet*
+usb:v0627p0001:*QEMU USB Keyboard*:*
+usb:v0627p0001:*QEMU USB Mouse*:*
+usb:v0627p0001:*QEMU USB Tablet*:*
ID_AUTOSUSPEND=1
#########################################
# Wacom
#########################################
-usb:v056Ap51A0*
+usb:v056Ap51A0:*
ID_AUTOSUSPEND=1
# The lookup keys are composed in:
# 60-evdev.rules
#
-# Note: The format of the "evdev:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
+# Note: The format of the "evdev:" prefix match key is a contract between the
+# rules file and the hardware data, it might change in later revisions to
+# support more or better matches, it is not necessarily expected to be a stable
+# ABI.
#
# Match string formats:
# evdev:<modalias>
# and add your rules there. To load the new rules execute (as root):
# systemd-hwdb update
# udevadm trigger /dev/input/eventXX
-# where /dev/input/eventXX is the device in question. If in
-# doubt, simply use /dev/input/event* to reload all input rules.
+# where /dev/input/eventXX is the device in question. If in doubt, simply use
+# /dev/input/event* to reload all input rules.
#
# If your changes are generally applicable, preferably send them as a pull
# request to
# Allowed properties are:
# EVDEV_ABS_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
#
-# where <axis> is the hexadecimal EV_ABS code as listed in linux/input.h
-# and min, max, res, fuzz, flat are the decimal values to the respective
-# fields of the struct input_absinfo as listed in linux/input.h.
-# If a field is missing the field will be left as-is. Not all fields need to
-# be present. e.g. ::45 sets the resolution to 45 units/mm.
-
+# where <axis> is the hexadecimal EV_ABS code as listed in linux/input.h and
+# min, max, res, fuzz, flat are the decimal values to the respective fields of
+# the struct input_absinfo as listed in linux/input.h. If a field is missing
+# the field will be left as-is. Not all fields need to be present. e.g. ::45
+# sets the resolution to 45 units/mm.
#
+# All matches should end in ':*' to allow future expansions of the match key.
+
# Sort by brand, model
#########################################
#########################################
# Hyperpen 12000U
-evdev:input:b0003v08CAp0010*
+evdev:input:b0003v08CAp0010:*
+# Hyperpen 6000U
+evdev:input:b0003v08CAp0020:*
EVDEV_ABS_00=::20
EVDEV_ABS_01=::20
#########################################
# Macbook2,1 (late 2006), single-button touchpad
-evdev:input:b0003v05ACp021B*
+evdev:input:b0003v05ACp021B:*
# Macbook4,1
-evdev:input:b0003v05ACp0229*
-evdev:input:b0003v05ACp022A*
+evdev:input:b0003v05ACp0229:*
+evdev:input:b0003v05ACp022A:*
EVDEV_ABS_00=256:1471:12
EVDEV_ABS_01=256:831:12
# Macbook5,1 (unibody), aka wellspring3
-evdev:input:b0003v05ACp0236*
-evdev:input:b0003v05ACp0237*
-evdev:input:b0003v05ACp0238*
+evdev:input:b0003v05ACp0236:*
+evdev:input:b0003v05ACp0237:*
+evdev:input:b0003v05ACp0238:*
EVDEV_ABS_00=::92
EVDEV_ABS_01=::90
EVDEV_ABS_35=::92
EVDEV_ABS_36=::90
# Macbook8 (unibody, March 2011)
-evdev:input:b0003v05ACp0245*
-evdev:input:b0003v05ACp0246*
-evdev:input:b0003v05ACp0247*
+evdev:input:b0003v05ACp0245:*
+evdev:input:b0003v05ACp0246:*
+evdev:input:b0003v05ACp0247:*
EVDEV_ABS_00=::92
EVDEV_ABS_01=::91
EVDEV_ABS_35=::92
EVDEV_ABS_36=::91
# Macbook8,2 (unibody)
-evdev:input:b0003v05ACp0252*
-evdev:input:b0003v05ACp0253*
-evdev:input:b0003v05ACp0254*
+evdev:input:b0003v05ACp0252:*
+evdev:input:b0003v05ACp0253:*
+evdev:input:b0003v05ACp0254:*
EVDEV_ABS_00=::94
EVDEV_ABS_01=::92
EVDEV_ABS_35=::94
EVDEV_ABS_36=::92
# MacbookPro10,1 (unibody, June 2012)
-evdev:input:b0003v05ACp0262*
-evdev:input:b0003v05ACp0263*
-evdev:input:b0003v05ACp0264*
+evdev:input:b0003v05ACp0262:*
+evdev:input:b0003v05ACp0263:*
+evdev:input:b0003v05ACp0264:*
# MacbookPro10,2 (unibody, October 2012)
-evdev:input:b0003v05ACp0259*
-evdev:input:b0003v05ACp025A*
-evdev:input:b0003v05ACp025B*
+evdev:input:b0003v05ACp0259:*
+evdev:input:b0003v05ACp025A:*
+evdev:input:b0003v05ACp025B:*
EVDEV_ABS_00=::94
EVDEV_ABS_01=::92
EVDEV_ABS_35=::94
#########################################
# Asus N53SV
-evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnASUSTeKComputerInc.:pnN53SV*
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnASUSTeKComputerInc.:pnN53SV:*
EVDEV_ABS_00=0:1152:14
EVDEV_ABS_01=0:576:10
EVDEV_ABS_35=0:1152:14
EVDEV_ABS_01=1103:5856:61
# Asus VivoBook E402SA
-evdev:name:Elan Touchpad:dmi:*svnASUSTeKCOMPUTERINC.:pnE402SA*
+evdev:name:Elan Touchpad:dmi:*svnASUSTeKCOMPUTERINC.:pnE402SA:*
EVDEV_ABS_00=::29
EVDEV_ABS_01=::29
EVDEV_ABS_35=::29
#########################################
# Dell Vostro 1510
-evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510*
+evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510:*
EVDEV_ABS_00=::14
EVDEV_ABS_01=::18
# Dell Inspiron 3537 - PS/2
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnDellInc.:pnInspiron3537*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnDellInc.:pnInspiron3537:*
EVDEV_ABS_00=1268:5675:41
EVDEV_ABS_01=1101:4792:61
EVDEV_ABS_35=1268:5675:41
EVDEV_ABS_36=1101:4792:61
# Dell Inspiron 3537 - RMI4
-evdev:name:Synaptics TM2382-001:dmi:*svnDellInc.:pnInspiron3537*
+evdev:name:Synaptics TM2382-001:dmi:*svnDellInc.:pnInspiron3537:*
EVDEV_ABS_00=::24
EVDEV_ABS_01=::34
EVDEV_ABS_35=::24
EVDEV_ABS_36=::34
# Dell Inspiron N5040
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInspironN5040*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInspironN5040:*
EVDEV_ABS_00=25:2000:22
EVDEV_ABS_01=0:1351:28
EVDEV_ABS_35=25:2000:22
EVDEV_ABS_01=687:5176:107
# Dell Latitude E6220
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220:*
EVDEV_ABS_00=76:1815:22
EVDEV_ABS_01=131:1330:30
EVDEV_ABS_35=76:1815:22
EVDEV_ABS_36=131:1330:30
# Dell Latitude E6320
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320:*
EVDEV_ABS_00=79:1841:22
EVDEV_ABS_01=140:1325:29
EVDEV_ABS_35=79:1841:22
EVDEV_ABS_36=140:1325:29
# Dell Latitude E7250
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7250*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7250:*
EVDEV_ABS_00=179:3903:38
EVDEV_ABS_01=277:1916:32
EVDEV_ABS_35=179:3903:38
EVDEV_ABS_36=277:1916:32
# Dell Latitude E7470
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470:*
EVDEV_ABS_00=29:2930:30
EVDEV_ABS_01=26:1533:29
EVDEV_ABS_35=29:2930:30
EVDEV_ABS_36=26:1533:29
# Dell Precision 5510
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510:*
EVDEV_ABS_00=::42
EVDEV_ABS_01=::43
EVDEV_ABS_35=::42
EVDEV_ABS_36=::43
# Dell Precision M4700
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnDellInc.:pnPrecisionM4700*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnDellInc.:pnPrecisionM4700:*
EVDEV_ABS_00=0:1960:24
EVDEV_ABS_01=113:1436:30
EVDEV_ABS_35=0:1960:24
EVDEV_ABS_36=::60
# Dell XPS15 9550
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPS159550*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPS159550:*
EVDEV_ABS_00=::41
EVDEV_ABS_01=::43
EVDEV_ABS_35=::41
EVDEV_ABS_36=::43
# Dell XPS M1530
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530:*
EVDEV_ABS_00=85:947:15
EVDEV_ABS_01=154:726:18
#####
# Fujitsu Component - USB Touch Panel
-evdev:input:b0003v0430p0530*
+evdev:input:b0003v0430p0530:*
EVDEV_ABS_00=0:4096:16
EVDEV_ABS_01=0:4096:16
#########################################
# Chromebook Pixel (2015) - Samus
-evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus*
+evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus:*
EVDEV_ABS_00=::10
EVDEV_ABS_01=::10
EVDEV_ABS_35=::10
#########################################
# HP Chromebook 14 (Falco)
-evdev:name:Cypress APA Trackpad ?cyapa?:dmi:*:svnHewlett-Packard*:pnFalco*:
+evdev:name:Cypress APA Trackpad ?cyapa?:dmi:*:svnHewlett-Packard*:pnFalco*:*
EVDEV_ABS_00=:::8
EVDEV_ABS_01=:::8
EVDEV_ABS_35=:::8
EVDEV_ABS_36=:::8
# HP Pavilion dm4
-evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4*
+evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4:*
EVDEV_ABS_00=1360:5563:47
EVDEV_ABS_01=1269:4618:61
EVDEV_ABS_35=1360:5563:47
EVDEV_ABS_36=1269:4618:61
# HP Pavilion g6
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvnHewlett-Packard:*svnHewlett-Packard:pnHPPaviliong6*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvnHewlett-Packard:*svnHewlett-Packard:pnHPPaviliong6:*
EVDEV_ABS_00=1255:5728:50
EVDEV_ABS_01=1215:4761:71
EVDEV_ABS_35=1255:5728:50
EVDEV_ABS_36=1215:4761:71
# HP Pavilion dv7
-evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondv7*
+evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondv7:*
EVDEV_ABS_00=1068:5805:44
EVDEV_ABS_01=1197:4890:57
EVDEV_ABS_35=1068:5805:44
EVDEV_ABS_36=1029:4916:78
# HP Spectre
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPSpectreNotebook*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPSpectreNotebook:*
EVDEV_ABS_00=1205:5691:47
EVDEV_ABS_01=1083:4808:65
EVDEV_ABS_35=1205:5691:47
EVDEV_ABS_36=1083:4808:65
# HP Envy x360
-evdev:name:SynPS/2 Synaptics TouchPad:*svnHP:pnHPENVYx360Convertible15m-cn0xxx*
+evdev:name:SynPS/2 Synaptics TouchPad:*svnHP:pnHPENVYx360Convertible15m-cn0xxx:*
EVDEV_ABS_00=1302:5640:36
EVDEV_ABS_01=1119:4741:61
EVDEV_ABS_35=1302:5640:36
#########################################
# Lenovo B590
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrLenovoB590*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrLenovoB590:*
EVDEV_ABS_00=1243:5759:48
EVDEV_ABS_01=1130:4832:65
EVDEV_ABS_35=1243:5759:48
EVDEV_ABS_36=1130:4832:65
# Lenovo E530
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:pn*ThinkPadEdgeE530*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:pn*ThinkPadEdgeE530:*
EVDEV_ABS_00=1241:5703:49
EVDEV_ABS_01=1105:4820:68
EVDEV_ABS_35=1241:5703:49
EVDEV_ABS_36=1105:4820:68
# Lenovo L430
-evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnLENOVO*:pvrThinkPadL430*
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnLENOVO*:pvrThinkPadL430:*
EVDEV_ABS_00=19:2197:29
EVDEV_ABS_01=12:1151:25
EVDEV_ABS_35=19:2197:29
EVDEV_ABS_36=12:1151:25
# Lenovo P50
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50:*
EVDEV_ABS_00=::44
EVDEV_ABS_01=::67
EVDEV_ABS_35=::44
EVDEV_ABS_36=1159:4700:53
# Lenovo ThinkPad X140e
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX140e*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX140e:*
EVDEV_ABS_00=1176:5767:62
EVDEV_ABS_01=416:5534:160
EVDEV_ABS_35=1176:5767:62
EVDEV_ABS_36=416:5534:160
# Lenovo ThinkPad T430
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadT430*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadT430:*
EVDEV_ABS_00=1250:5631:58
EVDEV_ABS_01=1309:4826:78
EVDEV_ABS_35=1250:5631:58
EVDEV_ABS_36=1309:4826:78
# Lenovo Thinkpad Carbon X1 4th gen. and X1 Yoga 1st gen.
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon4th*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon4th:*
EVDEV_ABS_00=1262:5679:44
EVDEV_ABS_01=1101:4824:65
EVDEV_ABS_35=1262:5679:44
EVDEV_ABS_36=1101:4824:65
# Lenovo Thinkpad Carbon X1 5th gen.
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th:*
EVDEV_ABS_00=::44
EVDEV_ABS_01=::65
EVDEV_ABS_35=::44
EVDEV_ABS_36=::65
# Lenovo Thinkpad Carbon X1 5th gen. (rmi4)
-evdev:name:Synaptics TM3289-002:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
+evdev:name:Synaptics TM3289-002:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th:*
EVDEV_ABS_00=::19
EVDEV_ABS_01=::19
EVDEV_ABS_35=::19
EVDEV_ABS_36=::19
# Lenovo Thinkpad X1 Tablet Gen3
-evdev:input:b0003v17EFp60B5*
+evdev:input:b0003v17EFp60B5:*
EVDEV_ABS_00=::12
EVDEV_ABS_01=::11
EVDEV_ABS_35=::12
EVDEV_ABS_36=::11
# Lenovo T460
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460:*
EVDEV_ABS_00=1266:5677:44
EVDEV_ABS_01=1093:4832:65
EVDEV_ABS_35=1266:5677:44
EVDEV_ABS_36=1093:4832:65
# Lenovo T510
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510:*
EVDEV_ABS_00=778:6239:72
EVDEV_ABS_01=841:5330:100
EVDEV_ABS_35=778:6239:72
EVDEV_ABS_36=841:5330:100
# Lenovo V360
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrLenovoV360*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrLenovoV360:*
EVDEV_ABS_00=1243:5927:60
EVDEV_ABS_01=902:5330:108
# Lenovo W530
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadW530*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadW530:*
EVDEV_ABS_00=1250:5631:59
EVDEV_ABS_01=1205:4834:81
EVDEV_ABS_35=1250:5631:59
EVDEV_ABS_36=1205:4834:81
# Lenovo X220 series
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadX220*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadX220:*
EVDEV_ABS_00=1316:5627:58
EVDEV_ABS_01=1355:4826:81
EVDEV_ABS_35=1316:5627:58
EVDEV_ABS_36=1355:4826:81
# Lenovo X230 series
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230:*
EVDEV_ABS_01=::100
EVDEV_ABS_36=::100
# Lenovo Y700-14ISK
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapadY700-14ISK*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapadY700-14ISK:*
EVDEV_ABS_00=::27
EVDEV_ABS_01=::29
EVDEV_ABS_35=::27
EVDEV_ABS_36=::29
# Lenovo Ideapad 310S-14ISK
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad310S-14ISK*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad310S-14ISK:*
EVDEV_ABS_00=113:3960:37
EVDEV_ABS_01=100:1959:27
EVDEV_ABS_35=113:3960:37
EVDEV_ABS_36=100:1959:27
# Lenovo Ideapad 500S-13ISK
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK:*
EVDEV_ABS_00=125:3955:37
EVDEV_ABS_01=104:1959:27
EVDEV_ABS_35=125:3954:37
EVDEV_ABS_36=104:1959:27
# Lenovo Yoga 500-14ISK
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14ISK*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14ISK:*
EVDEV_ABS_00=124:3955:36
EVDEV_ABS_01=103:1959:26
EVDEV_ABS_35=124:3955:36
EVDEV_ABS_36=103:1959:26
# Lenovo Flex 3 15-inch
-evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnLENOVO*:pvrFlex3-15*
+evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnLENOVO*:pvrFlex3-15:*
EVDEV_ABS_00=::38
EVDEV_ABS_01=::28
EVDEV_ABS_35=::38
EVDEV_ABS_36=::28
# Lenovo ThinkPad Edge 13 (02173BG)
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*02173BG*:*pvrThinkPadEdge*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*02173BG*:*pvrThinkPadEdge:*
EVDEV_ABS_00=916:6077:55
EVDEV_ABS_01=653:5395:116
EVDEV_ABS_35=916:6077:55
EVDEV_ABS_36=653:5395:116
# Lenovo Yoga 500-14IBD, 80N4
-evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14IBD*
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14IBD:*
EVDEV_ABS_00=117:3952:36
EVDEV_ABS_01=105:1960:26
EVDEV_ABS_35=117:3952:36
EVDEV_ABS_36=::52
# Lenovo Legion Y9000X2020
-evdev:name:MSFT0001:02 04F3:304B Touchpad:dmi:*svnLENOVO:*pvrLenovoLegionY9000X2020*
+evdev:name:MSFT0001:02 04F3:304B Touchpad:dmi:*svnLENOVO:*pvrLenovoLegionY9000X2020:*
EVDEV_ABS_00=::31
EVDEV_ABS_01=::30
EVDEV_ABS_35=::31
EVDEV_ABS_36=::11:8
# Razer Blade Stealth (2016)
-evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth*
+evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth:*
EVDEV_ABS_00=0:4064:29
EVDEV_ABS_01=0:2405:37
EVDEV_ABS_35=0:4064:29
#########################################
# Samsung 305V4
-evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A*
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A:*
EVDEV_ABS_00=0:2480:28
EVDEV_ABS_01=0:1116:24
EVDEV_ABS_35=0:2480:28
EVDEV_ABS_36=0:1116:24
# Samsung 880Z5E
-evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E*
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E:*
EVDEV_ABS_00=::30
EVDEV_ABS_01=::29
EVDEV_ABS_35=::30
#########################################
# Star LabTop Mk III
-evdev:name:ALPS0001:00 0911:5288 Touchpad:dmi:*svnStarLabs:pnLabTop*
+evdev:name:ALPS0001:00 0911:5288 Touchpad:dmi:*svnStarLabs:pnLabTop:*
EVDEV_ABS_00=0:2627:25
EVDEV_ABS_01=0:1331:20
EVDEV_ABS_35=0:2627:25
#########################################
# Toshiba Tecra M11
-evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnTOSHIBA:pnTECRAM11*
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnTOSHIBA:pnTECRAM11:*
EVDEV_ABS_00=90:962:11
EVDEV_ABS_01=51:681:14
# Toshiba Satellite R830
-evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnTOSHIBA:pnSATELLITER830*
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnTOSHIBA:pnSATELLITER830:*
EVDEV_ABS_00=1238:5785:53
EVDEV_ABS_01=1045:4826:76
EVDEV_ABS_35=1238:5785:53
#########################################
# Trust Flex Graphics Tablet
-evdev:input:b0003v2179p0004*
+evdev:input:b0003v2179p0004:*
EVDEV_ABS_00=::234
EVDEV_ABS_01=::328
#########################################
# WALTOP International Corp. Slim Tablet
-evdev:input:b0003v172Fp0031*
+evdev:input:b0003v172Fp0031:*
EVDEV_ABS_00=0:10000:400
EVDEV_ABS_01=0:6250:400
#WALTOP International Corp. Graphics Tablet
-evdev:input:b0003v172Fp0047*
+evdev:input:b0003v172Fp0047:*
EVDEV_ABS_00=0:20000:80
EVDEV_ABS_01=0:12500:80
# The lookup keys are composed in:
# 60-input-id.rules
#
-# Note: The format of the "input-id:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
+# Note: The format of the "input-id:" prefix match key is a contract between
+# the rules file and the hardware data, it might change in later revisions to
+# support more or better matches, it is not necessarily expected to be a stable
+# ABI.
#
# Match string formats:
-# id-input:modalias:<modalias>
+# id-input:modalias:<modalias pattern>
#
# To add local entries, create a new file
# /etc/udev/hwdb.d/61-input-id-local.hwdb
# udevadm info /dev/input/eventXX.
#
# This file must only be used where the input_id builtin assigns the wrong
-# properties or lacks the assignment of some properties. This is almost
-# always caused by a device not adhering to the standard of the device's
-# type.
+# properties or lacks the assignment of some properties. This is almost always
+# caused by a device not adhering to the standard of the device's type.
#
# Allowed properties are:
-# ID_INPUT
-# ID_INPUT_ACCELEROMETER, ID_INPUT_MOUSE,
-# ID_INPUT_POINTINGSTICK, ID_INPUT_TOUCHSCREEN, ID_INPUT_TOUCHPAD,
-# ID_INPUT_TABLET, ID_INPUT_TABLET_PAD, ID_INPUT_JOYSTICK, ID_INPUT_KEY,
-# ID_INPUT_KEYBOARD, ID_INPUT_SWITCH, ID_INPUT_TRACKBALL
+# ID_INPUT, ID_INPUT_ACCELEROMETER, ID_INPUT_MOUSE, ID_INPUT_POINTINGSTICK,
+# ID_INPUT_TOUCHSCREEN, ID_INPUT_TOUCHPAD, ID_INPUT_TABLET,
+# ID_INPUT_TABLET_PAD, ID_INPUT_JOYSTICK, ID_INPUT_KEY, ID_INPUT_KEYBOARD,
+# ID_INPUT_SWITCH, ID_INPUT_TRACKBALL
#
# ID_INPUT
# * MUST be set when ANY of ID_INPUT_* is set
# ID_INPUT_TABLET
# * MUST be set when setting ID_INPUT_TABLET_PAD
#
-# Allowed values are 1 and 0 to set or unset, repsectively.
+# Allowed values are 1 and 0 to set or unset, respectively.
#
# NOT allowed in this file are:
# ID_INPUT_WIDTH_MM, ID_INPUT_HEIGHT_MM, ID_INPUT_TOUCHPAD_INTEGRATION
#
+# All matches should end in ':*' to allow future expansions of the match key.
# Example:
-# id-input:modalias:input:b0003v1234pABCD*
+# id-input:modalias:input:b0003v1234pABCD:*
# ID_INPUT_TOUCHPAD=1
# ID_INPUT=1
# Sort by brand, model
# UC-Logic TABLET 1060N Pad
-id-input:modalias:input:b0003v5543p0081*
+id-input:modalias:input:b0003v5543p0081:*
ID_INPUT_TABLET=1
ID_INPUT_TABLET_PAD=1
# XP-PEN STAR 06
-id-input:modalias:input:b0003v28bdp0078*
+id-input:modalias:input:b0003v28bdp0078:*
ID_INPUT_TABLET=1
# Lite-On Tech IBM USB Travel Keyboard with Ultra Nav Mouse
-id-input:modalias:input:b0003v04B3p301Ee0100-e0,1,2,4*
+id-input:modalias:input:b0003v04B3p301Ee0100-e0,1,2,4*:*
ID_INPUT_POINTINGSTICK=1
# Logitech Ultrathin Touch Mouse
-id-input:modalias:input:b0005v046DpB00De0700*
+id-input:modalias:input:b0005v046DpB00De0700:*
ID_INPUT_MOUSE=1
# The lookup keys are composed in:
# 60-evdev.rules
#
-# Note: The format of the "evdev:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
+# Note: The format of the "evdev:" prefix match key is a contract between the
+# rules file and the hardware data, it might change in later revisions to
+# support more or better matches, it is not necessarily expected to be a stable
+# ABI.
#
# Supported hardware matches are:
# - Generic input devices match:
# /sys/class/input/input?/capabilities/ev" and <vendor> is the
# firmware-provided string exported by the kernel DMI modalias,
# see /sys/class/dmi/id/modalias
-
+#
+# All matches should end in ':*' to allow future expansions of the match key.
# ######################### KEY MAPPING ######################################
#
# A device with a fixed keyboard layout that must not be changed by
# the desktop environment may specify that layout as:
-# XKB_FIXED_LAYOUT="us"
-# XKB_FIXED_VARIANT=""
+# XKB_FIXED_LAYOUT=us
+# XKB_FIXED_VARIANT=
# Examples of such devices: the Yubikey or other key-code generating
# devices.
# A device where the scan code to key code mapping is insufficient and
# requires a special key code to symbol configuration may specify that with:
-# XKB_FIXED_MODEL="xkbmodel"
+# XKB_FIXED_MODEL=xkbmodel
# Examples of such devices: Chromebooks where the top row is used for both
# media and F1-F10 keys.
##########################################
# common keys
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:*
KEYBOARD_KEY_86=wlan # Fn+F3 or Fn+Q for comunication key
KEYBOARD_KEY_a5=help # Fn+F1
KEYBOARD_KEY_a6=setup # Fn+F2 Acer eSettings
KEYBOARD_KEY_f9=prog1 # Launch NTI shadow
# Acer kernel driver
-evdev:name:Acer WMI hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnAcer*:pvr*
+evdev:name:Acer WMI hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnAcer*:*
KEYBOARD_KEY_82=f21 # Touchpad toggle
# Aspire models
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*:*
KEYBOARD_KEY_84=bluetooth # sent when bluetooth module missing, and key pressed
KEYBOARD_KEY_d9=bluetooth # Bluetooth off
KEYBOARD_KEY_92=media # Acer arcade
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5720*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnZG8*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5720*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnZG8*:*
KEYBOARD_KEY_f4=prog3 # e-key
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5920G:*
KEYBOARD_KEY_89=fastforward
KEYBOARD_KEY_9e=back
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*7750G:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*7750G:*
KEYBOARD_KEY_e0=!pageup
# Predator PH 315-52
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredator*PH*315-52:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredator*PH*315-52:*
KEYBOARD_KEY_ef=kbdillumup # Fn+F10
KEYBOARD_KEY_f0=kbdillumdown # Fn+F9
# Travelmate C300
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:*
KEYBOARD_KEY_67=f24 # FIXME: rotate screen
KEYBOARD_KEY_68=up
KEYBOARD_KEY_69=down
KEYBOARD_KEY_6c=screenlock # FIXME: lock tablet device/buttons
# Travelmate P648-G2-MG, P648-G3-M and P645-S
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G2-MG*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G3-M*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P645-S*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G2-MG*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G3-M*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P645-S*:*
KEYBOARD_KEY_8a=f20 # Microphone mute button; should be micmute
# on some models this isn't brightnessup
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5610*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5620*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5720*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5610*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5620*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5720*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*6593:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:*
KEYBOARD_KEY_ee=screenlock
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:*
KEYBOARD_KEY_a9=!switchvideomode # Fn+F5
# Packard Bell and Gateway models
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pn*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pn*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn*:*
KEYBOARD_KEY_86=wlan # Fn+F3 or Fn+Q for comunication key
###########################################################
# Alienware
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*
+# Alienware/Dell reserves these keys; safe to apply on all their devices
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*:*
KEYBOARD_KEY_81=f21 # Touchpad toggle
KEYBOARD_KEY_8a=ejectcd
-
-# Alienware/Dell reserves these keys; safe to apply on all their devices
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*:pvr*
- KEYBOARD_KEY_bf=!prog1 #graphics amplifier, cable plug-in event
- KEYBOARD_KEY_c1=!prog2 #graphics amplifier, undock-button event
- KEYBOARD_KEY_c2=!power #graphics amplifier, surprise undock event
+ KEYBOARD_KEY_bf=!prog1 # graphics amplifier, cable plug-in event
+ KEYBOARD_KEY_c1=!prog2 # graphics amplifier, undock-button event
+ KEYBOARD_KEY_c2=!power # graphics amplifier, surprise undock event
# Alienware M17xR3 laptops
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pnM17xR3:*
# Asus
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnASUS:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnASUS:pn*:*
KEYBOARD_KEY_ed=volumeup
KEYBOARD_KEY_ee=volumedown
KEYBOARD_KEY_ef=mute
-evdev:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
-evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
-evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
+evdev:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
+evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
+evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:*
KEYBOARD_KEY_6b=f21 # Touchpad Toggle
# USB keyboard in Asus FX503VD
-evdev:input:b0003v0B05p1869*
+evdev:input:b0003v0B05p1869:*
KEYBOARD_KEY_ff31007c=f20 # Remap micmute to f20
###########################################################
# BenQ
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:*
KEYBOARD_KEY_6e=wlan
###########################################################
# Clevo
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnNotebook:pnW65_67SZ:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnNotebook:pnW65_67SZ:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_a2=!playpause
KEYBOARD_KEY_ae=!volumedown
# COMPAQ
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*E500*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*Evo*N*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*E500*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*Evo*N*:*
KEYBOARD_KEY_a3=www # I key
KEYBOARD_KEY_9a=search
KEYBOARD_KEY_9e=email
KEYBOARD_KEY_9f=homepage
-evdev:input:b0003v049Fp0051*
+evdev:input:b0003v049Fp0051:*
KEYBOARD_KEY_0c0011=presentation
KEYBOARD_KEY_0c0012=addressbook
KEYBOARD_KEY_0c0013=info
# Dell
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pn*:*
KEYBOARD_KEY_81=playpause # Play/Pause
KEYBOARD_KEY_82=stopcd # Stop
KEYBOARD_KEY_83=previoussong # Previous song
KEYBOARD_KEY_d9=f21 # Touchpad toggle
#
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*910:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*101[012]:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*910:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*101[012]:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:*
KEYBOARD_KEY_84=wlan
# Dell Inspiron 1520 and Latitude 2110
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1520:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*2110:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1520:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*2110:*
KEYBOARD_KEY_85=unknown # Brightness Down, also emitted by acpi-video, ignore
KEYBOARD_KEY_86=unknown # Brightness Up, also emitted by acpi-video, ignore
# Dell Inspiron 537*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron537*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron537*:*
KEYBOARD_KEY_88=!wlan # Fn-PrtScr rfkill
# Latitude XT2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*XT2:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*XT2:*
KEYBOARD_KEY_9b=up # tablet rocker up
KEYBOARD_KEY_9e=enter # tablet rocker press
KEYBOARD_KEY_9f=back # tablet back
KEYBOARD_KEY_a3=down # tablet rocker down
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnStudio*155[78]:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnStudio*155[78]:*
KEYBOARD_KEY_a0=! # mute
KEYBOARD_KEY_ae=! # volume down
KEYBOARD_KEY_b0=! # volume up
# Dell Touchpad
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:*
KEYBOARD_KEY_88=! # wireless switch
KEYBOARD_KEY_9e=!f21
# Dell Latitude E7*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*E7*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*E7*:*
KEYBOARD_KEY_88=unknown # Fn-PrtScr rfkill - handled in HW
# Dell XPS
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:*
KEYBOARD_KEY_8c=!unknown
# Dell XPS L702x
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDellInc.:pnDellSystemXPSL702X:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDellInc.:pnDellSystemXPSL702X:*
KEYBOARD_KEY_84=prog1
KEYBOARD_KEY_85=prog2
# Dell XPS12 9Q33
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS12-9Q33*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS12-9Q33*:*
KEYBOARD_KEY_88=wlan
KEYBOARD_KEY_65=direction # Screen Rotate
# Dell Latitude microphone mute
-evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*
+evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:*
# Dell Precision microphone mute
-evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*
+evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:*
KEYBOARD_KEY_100150=f20 # Mic mute toggle, should be micmute
###########################################################
# Everex
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnEverex:pnXT5000*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnEverex:pnXT5000*:*
KEYBOARD_KEY_5c=media
KEYBOARD_KEY_65=f21 # Fn+F5 Touchpad toggle
KEYBOARD_KEY_67=prog3 # Fan speed control button
# Fujitsu
##########################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*M*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*M*:*
KEYBOARD_KEY_97=prog2
KEYBOARD_KEY_9f=prog1
KEYBOARD_KEY_a9=switchvideomode # Fn+F10 Cycle between available video outputs
# Amilo Pa 2548
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pa*2548*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pa*2548*:*
KEYBOARD_KEY_e0=volumedown
KEYBOARD_KEY_e1=volumeup
KEYBOARD_KEY_e5=prog1
# Amilo Pro Edition V3505
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*Edition*V3505*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*Edition*V3505*:*
KEYBOARD_KEY_a5=help # Fn+F1
KEYBOARD_KEY_a9=switchvideomode # Fn+F3
KEYBOARD_KEY_d9=brightnessdown # Fn+F8
KEYBOARD_KEY_e0=brightnessup # Fn+F9
# Amilo Pro v3205
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*V3205*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*V3205*:*
KEYBOARD_KEY_f4=f21 # FIXME: silent-mode decrease CPU/GPU clock
KEYBOARD_KEY_f7=switchvideomode # Fn+F3
# Amilo Si 1520
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*Amilo*Si*1520*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*Amilo*Si*1520*:*
KEYBOARD_KEY_e1=wlan
KEYBOARD_KEY_f3=wlan
KEYBOARD_KEY_ee=brightnessdown
KEYBOARD_KEY_f7=video
# Esprimo Mobile V5
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V5*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V5*:*
KEYBOARD_KEY_a9=switchvideomode
KEYBOARD_KEY_d9=brightnessdown
KEYBOARD_KEY_df=sleep
KEYBOARD_KEY_ef=brightnessup
# Esprimo Mobile V6
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V6*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V6*:*
KEYBOARD_KEY_ce=brightnessup
KEYBOARD_KEY_ef=brightnessdown
###########################################################
# Slimstar 320
-evdev:input:b0003v0458p0708*
+evdev:input:b0003v0458p0708:*
KEYBOARD_KEY_0900f0=scrollup
KEYBOARD_KEY_0900f1=scrolldown
KEYBOARD_KEY_0900f3=back
# Hewlett Packard
###########################################################
-evdev:name:Intel HID events:dmi:bvn*:bvr*:bd*:svnHP*:pn*:pvr*
+evdev:name:Intel HID events:dmi:bvn*:bvr*:bd*:svnHP*:pn*:*
KEYBOARD_KEY_8=unknown # Use hp-wireless instead
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*:*
KEYBOARD_KEY_81=fn_esc
KEYBOARD_KEY_89=battery # Fn+F8
KEYBOARD_KEY_8a=screenlock # Fn+F6
KEYBOARD_KEY_ee=switchvideomode # Fn+F4
# Tablet
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][aA][bB][lL][eE][tT]*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][aA][bB][lL][eE][tT]*:*
KEYBOARD_KEY_82=prog2 # Funny Key
KEYBOARD_KEY_83=prog1 # Q
KEYBOARD_KEY_84=tab
KEYBOARD_KEY_87=pagedown
# Pavilion
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*:*
KEYBOARD_KEY_88=media # FIXME: quick play
KEYBOARD_KEY_b7=print
KEYBOARD_KEY_d8=!f23 # touchpad off
KEYBOARD_KEY_d9=!f22 # touchpad on
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:*
KEYBOARD_KEY_b7=print
KEYBOARD_KEY_c2=media # FIXME: quick play
KEYBOARD_KEY_c6=break
KEYBOARD_KEY_94=reserved
# Pavilion 13 x360 (Tablet mode and SYSRQ key)
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*13*x360*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*13*x360*:*
KEYBOARD_KEY_d7=!f22 # touchpad off
KEYBOARD_KEY_d9=unknown
KEYBOARD_KEY_d2=sysrq # Fn+Print = SYSRQ
# Spectre x360 13 (Prevents random airplane mode activation)
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360*13*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360Convertible*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360*13*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360Convertible*:*
KEYBOARD_KEY_d7=unknown
# Spectre x360 13
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPSpectrex360Convertible13*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPSpectrex360Convertible13*:*
KEYBOARD_KEY_82=f20 # Fn+F12; Microphone mute button, should be micmute
# HP Elite x2 1013 G3
KEYBOARD_KEY_08=unknown # rfkill is also reported by HP Wireless hotkeys
# Elitebook
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2230s*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2230s*:*
KEYBOARD_KEY_88=presentation
KEYBOARD_KEY_d9=help # I key (high keycode: "info")
# Presario
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Presario*CQ*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Presario*CQ*:*
KEYBOARD_KEY_d8=f21
KEYBOARD_KEY_d9=f21
# 2510p 2530p
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2510p*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2530p*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2510p*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2530p*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:*
KEYBOARD_KEY_d8=!f23 # touchpad off
KEYBOARD_KEY_d9=!f22 # touchpad on
# 2570p
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:*
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
# TX2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][xX]2*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][xX]2*:*
KEYBOARD_KEY_c2=media
KEYBOARD_KEY_d8=!f23 # Toggle touchpad button on tx2 (OFF)
KEYBOARD_KEY_d9=!f22 # Toggle touchpad button on tx2 (ON)
# Presario 2100
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnPresario*2100*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnPresario*2100*:*
KEYBOARD_KEY_f0=help
KEYBOARD_KEY_f1=screenlock
KEYBOARD_KEY_f3=search
# Elitebook 8440p
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8440p:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8440p:*
KEYBOARD_KEY_88=www
KEYBOARD_KEY_a0=mute
KEYBOARD_KEY_ae=volumedown
KEYBOARD_KEY_ec=mail
# Elitebook 8460p
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8460p:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8460p:*
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
KEYBOARD_KEY_b3=prog1 # Fn+F11 - Ambient Light Sensor button
KEYBOARD_KEY_b1=prog2 # Fn+ESC - System information button
# HDX9494nr
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHDX9494NR:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHDX9494NR:*
KEYBOARD_KEY_b2=www # Fn+F3
KEYBOARD_KEY_d8=!f23 # touchpad off
KEYBOARD_KEY_d9=!f22 # touchpad on
# HP EliteBook 725 G2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:*
# HP EliteBook
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBook*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPEliteBook*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBook*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPEliteBook*:*
# HP ProBook 440 G2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP440G2:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP440G2:*
# several HP ProBooks 4xx
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook4*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHP*ProBook*4*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook4*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHP*ProBook*4*:*
# HP ZBook
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPZBook*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPZBook*:*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
# HP ZBook 15 G2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook15G2:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook15G2:*
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
# HP ProBook 11 G1
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook11G1:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook11G1:*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
KEYBOARD_KEY_d8=f21 # touchpad toggle
KEYBOARD_KEY_d9=f21 # touchpad toggle
# HP ZBook Studio G4
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPZBookStudioG4:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPZBookStudioG4:*
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
-# HP Folio 1040g2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:pvr*
+# HP EliteBook Folio 1040 G2
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:*
KEYBOARD_KEY_d8=!f23 # touchpad off
KEYBOARD_KEY_d9=!f22 # touchpad on
+# HP EliteBook Folio G1
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPEliteBookFolioG1:*
+ KEYBOARD_KEY_64=calendar
+ KEYBOARD_KEY_81=micmute
+
# HP ProBook 650
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:*
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
# HP ProBook 6555b
KEYBOARD_KEY_b2=www # Earth
# HP ProBook 440 G3
-evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3*
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3*:*
# HP ProBook 640 G2
-evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*640*G2*
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*640*G2*:*
KEYBOARD_KEY_85=unknown # lid close; also reported via special evdev
KEYBOARD_KEY_f8=unknown # rf kill; also reported via special evdev
# HP ProBook 645 G4
-evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*645*G4*
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*645*G4*:*
KEYBOARD_KEY_73=slash # Slash key
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
##########################################################
# Huawei WMI hotkeys driver
-evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*
+evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI:*
KEYBOARD_KEY_287=f20 # Microphone mute button, should be micmute
# Huawei MACH-WX9
-evdev:atkbd:dmi:bvn*:bvr*:svnHUAWEI*:pnMACH-WX9:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:svnHUAWEI*:pnMACH-WX9:*
KEYBOARD_KEY_f7=unknown
KEYBOARD_KEY_f8=fn
-evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*:pnMACH-WX9:pvr*
+evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*:pnMACH-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
###########################################################
# thinkpad_acpi driver
-evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnIBM*:pn*:pvr*
+evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnIBM*:pn*:*
KEYBOARD_KEY_01=battery # Fn+F2
KEYBOARD_KEY_02=screenlock # Fn+F3
KEYBOARD_KEY_03=sleep # Fn+F4
KEYBOARD_KEY_17=prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
# IBM Thinkpad USB Keyboard Trackpoint
-evdev:input:b0003v04B3p301[89]*
+evdev:input:b0003v04B3p301[89]:*
KEYBOARD_KEY_900f0=screenlock
KEYBOARD_KEY_900f1=wlan
KEYBOARD_KEY_900f2=switchvideomode
###########################################################
# Symphony
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINVENTEC:pnSYMPHONY*6.0/7.0:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINVENTEC:pnSYMPHONY*6.0/7.0:*
KEYBOARD_KEY_f3=prog2
KEYBOARD_KEY_f4=prog1
###########################################################
# thinkpad_acpi driver
-evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*
KEYBOARD_KEY_01=screenlock
KEYBOARD_KEY_02=battery
KEYBOARD_KEY_03=sleep
KEYBOARD_KEY_45=bookmarks
# ThinkPad Keyboard with TrackPoint
-evdev:input:b0003v17EFp6009*
+evdev:input:b0003v17EFp6009:*
KEYBOARD_KEY_090012=screenlock # Fn+F2
KEYBOARD_KEY_090013=battery # Fn+F3
KEYBOARD_KEY_090014=wlan # Fn+F5
KEYBOARD_KEY_090010=f20 # Microphone mute button; should be micmute
# Lenovo 3000
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*3000*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*3000*:*
KEYBOARD_KEY_8b=switchvideomode # Fn+F7 video
KEYBOARD_KEY_96=wlan # Fn+F5 wireless
KEYBOARD_KEY_97=sleep # Fn+F4 suspend
KEYBOARD_KEY_b4=prog1
# lenovo-ideapad
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnS10-*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnS10-*:*
KEYBOARD_KEY_81=rfkill # does nothing in BIOS
KEYBOARD_KEY_83=display_off # BIOS toggles screen state
KEYBOARD_KEY_b9=brightnessup # does nothing in BIOS
KEYBOARD_KEY_f3=f21
# Thinkpad X200_Tablet
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X2*Tablet*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X2*Tablet*:*
KEYBOARD_KEY_5d=menu
KEYBOARD_KEY_63=fn
KEYBOARD_KEY_66=screenlock
KEYBOARD_KEY_6c=direction # rotate screen
# ThinkPad X6 Tablet
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X6*Tablet*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X6*Tablet*:*
KEYBOARD_KEY_6c=direction # rotate
KEYBOARD_KEY_68=leftmeta # toolbox
KEYBOARD_KEY_6b=esc # escape
KEYBOARD_KEY_69=enter # enter on d-pad
# ThinkPad X41 Tablet
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnIBM*:pn18666TU:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnIBM*:pn18666TU:*
KEYBOARD_KEY_6c=direction # rotate
KEYBOARD_KEY_68=leftmeta # toolbox
KEYBOARD_KEY_6b=esc # escape
KEYBOARD_KEY_69=enter # enter on d-pad
# IdeaPad
-evdev:name:Ideapad extra buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+evdev:name:Ideapad extra buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*
KEYBOARD_KEY_0d=rfkill # airplane mode switch (toggle all wireless devices)
KEYBOARD_KEY_08=f20 # micmute
KEYBOARD_KEY_42=f23
KEYBOARD_KEY_43=f22
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*Y550*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*Y550*:*
KEYBOARD_KEY_95=media
KEYBOARD_KEY_a3=play
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*U300s*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*U300s*:*
KEYBOARD_KEY_f1=f21
KEYBOARD_KEY_ce=f20 # micmute
-evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
# For 10th gen it should be pn81Q8 instead of pn81Q7 but
# I don't have a device to test
# perhaps pn81Q* would work for both generations
-evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO:pn81Q7*:pvrLenovoYogaS940*
+evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO:pn81Q7*:pvrLenovoYogaS940:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
# Lenovo Y50-70
-evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*20378*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*20378*:*
KEYBOARD_KEY_f3=f21 # Fn+F6 (toggle touchpad)
# V480
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:*
KEYBOARD_KEY_f1=f21
# Lenovo ThinkCentre M800z/M820z/M920z AIO machines
# key_scancode 00 is KEY_MICMUTE
-evdev:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+evdev:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*
KEYBOARD_KEY_00=f20
# enhanced USB keyboard
-evdev:input:b0003v04B3p301B*
+evdev:input:b0003v04B3p301B:*
KEYBOARD_KEY_90001=prog1 # ThinkVantage
KEYBOARD_KEY_90002=screenlock
KEYBOARD_KEY_90003=file
# 27MHz wireless keyboards, these all have a PID of 00?? and all send c10xx
# logitech custom consumer usage-page codes. The mappings below are the most
# common, but some mapping may differ, especially the Fn F1-F12 mappings
-evdev:input:b0003v046Dp00*
+evdev:input:b0003v046Dp00??:*
KEYBOARD_KEY_c0183=media # HUT:config, kbd:Media/Music player button
KEYBOARD_KEY_c1001=chat # Messenger button
KEYBOARD_KEY_c1002=camera # Webcam button
KEYBOARD_KEY_c104c=prog4 # Smartkey D (Fn + F12) → XF86Launch4
# Cordless Access Keyboard (27 MHz, modelnumber Y-RH35)
-evdev:input:b0003v046Dp0042*
+evdev:input:b0003v046Dp0042:*
KEYBOARD_KEY_c1041=new
KEYBOARD_KEY_c1042=reply
KEYBOARD_KEY_c1043=forward
KEYBOARD_KEY_c104c=audio
# "Cordless Rechargeable Desktop" keyboard (27 MHz, modelnumber Y-RK49)
-evdev:input:b0003v046Dp0045*
+evdev:input:b0003v046Dp0045:*
KEYBOARD_KEY_c1041=new
KEYBOARD_KEY_c1042=reply
KEYBOARD_KEY_c1043=forward
KEYBOARD_KEY_c104c=audio
# S510 keyboard (27 MHz, modelnumber Y-RAK73)
-evdev:input:b0003v046Dp0056*
+evdev:input:b0003v046Dp0056:*
KEYBOARD_KEY_c1041=battery # Battery icon (Fn + F1)
# MX3000 keyboard (27 MHz, modelnumber Y-RAM74)
# Note if the "Special Button Function" in the HID++ features register gets
# cleared then the scroll-wheel events for these buttons go away and then
# tilting the scrollwheel left/right starts sending c1022 / c1024 events
-evdev:input:b0003v046Dp0057*
+evdev:input:b0003v046Dp0057:*
KEYBOARD_KEY_c1041=battery # Battery icon (Fn + F1)
#KEYBOARD_KEY_c101d=scrolldown # Button below scrollwheel (see note above)
#KEYBOARD_KEY_c1024=scrollright # Right click on scroll-wheel (see note above)
# MX3200 keyboard (27 MHz, modelnumber Y-RAV80)
-evdev:input:b0003v046Dp005C*
+evdev:input:b0003v046Dp005C:*
KEYBOARD_KEY_c1001=phone # VOIP button
KEYBOARD_KEY_c1016=record # Record button
KEYBOARD_KEY_c1041=wordprocessor # Word icon (Fn + F1)
KEYBOARD_KEY_c1048=prog4 # Smartkey D (Fn + F8) → XF86Launch4
# EX100 keyboard (27 MHz, modelnumber Y-RBH94)
-evdev:input:b0003v046Dp0065*
+evdev:input:b0003v046Dp0065:*
KEYBOARD_KEY_c104b=battery # Battery icon (Fn + F11)
KEYBOARD_KEY_c104c=ejectcd # Eject icon (Fn + F12)
# S520 keyboard (27 MHz, modelnumber Y-RBA97)
# Note this one uses non-standard codes for FN + F9 - Fn + F12?
-evdev:input:b0003v046Dp0066*
+evdev:input:b0003v046Dp0066:*
KEYBOARD_KEY_c100e=prog4 # Smartkey D (Fn + F12) → XF86Launch4
KEYBOARD_KEY_c1019=prog1 # Smartkey A (Fn + F9) → XF86Launch1
KEYBOARD_KEY_c101a=prog2 # Smartkey B (Fn + F10) → XF86Launch2
KEYBOARD_KEY_c106f=battery # Battery icon
# S510 remote control (27 MHz)
-evdev:input:b0003v046Dp00FE*
+evdev:input:b0003v046Dp00FE:*
KEYBOARD_KEY_c1018=media # Media button
# MX5000 keyboard (HID proxy mode and bluetooth matches)
-evdev:input:b0003v046DpB305*
-evdev:input:b0005v046DpB305*
+evdev:input:b0003v046DpB305:*
+evdev:input:b0005v046DpB305:*
KEYBOARD_KEY_c0230=zoomreset # HUT says fullscreen, kbd says 100%
KEYBOARD_KEY_c1004=send # Send and receive / sync button
KEYBOARD_KEY_c1006=coffee # Status (online/away) button
KEYBOARD_KEY_c103b=prog4 # Smartkey D → XF86Launch4
# MX5500 keyboard (HID proxy mode and bluetooth matches)
-evdev:input:b0003v046DpB30B*
-evdev:input:b0005v046DpB30B*
+evdev:input:b0003v046DpB30B:*
+evdev:input:b0005v046DpB30B:*
KEYBOARD_KEY_c0183=media # HUT says consumer control configuration, kbd says Media Center
KEYBOARD_KEY_c100e=images # Camera icon, "Photo Gallery"
KEYBOARD_KEY_c100f=config # Window with gear icon
KEYBOARD_KEY_c103b=prog4 # Smartkey D → XF86Launch4
# Logitech K811
-evdev:input:b0005v046DpB317*
+evdev:input:b0005v046DpB317:*
KEYBOARD_KEY_70047=brightnessdown
KEYBOARD_KEY_70048=brightnessup
# iTouch
-evdev:input:b0003v046DpC308*
+evdev:input:b0003v046DpC308:*
KEYBOARD_KEY_90001=shop # Shopping
KEYBOARD_KEY_90002=config # iTouch
KEYBOARD_KEY_90003=finance # Finance
KEYBOARD_KEY_c0183=media # Media
# Cordless Desktop S510
-evdev:input:b0003v046DpC50C*
+evdev:input:b0003v046DpC50C:*
KEYBOARD_KEY_d4=up # zoomin
KEYBOARD_KEY_cc=down # zoomout
# Wave cordless
-evdev:input:b0003v046DpC317*
+evdev:input:b0003v046DpC317:*
KEYBOARD_KEY_9001c=scale # expo
KEYBOARD_KEY_9001f=down # zoomout
KEYBOARD_KEY_90020=up # zoomin
KEYBOARD_KEY_9004c=ejectclosecd
# Wave cordless
-evdev:input:b0003v046DpC517*
+evdev:input:b0003v046DpC517:*
KEYBOARD_KEY_c101f=down # zoomout
KEYBOARD_KEY_c1020=up # zoomin
KEYBOARD_KEY_c1005=camera
KEYBOARD_KEY_c104c=ejectclosecd
# Cordless Wave Pro
-evdev:input:b0003v046DpC529*
+evdev:input:b0003v046DpC529:*
KEYBOARD_KEY_0c01b6=camera
KEYBOARD_KEY_0c0183=media
KEYBOARD_KEY_0c0184=wordprocessor
KEYBOARD_KEY_0c022e=down # zoomout
# Logitech Presenter R400
-evdev:input:b0003v046DpC52D*
+evdev:input:b0003v046DpC52D:*
KEYBOARD_KEY_070029=presentation
KEYBOARD_KEY_07003e=presentation
KEYBOARD_KEY_070037=displaytoggle
# Internet Navigator
-evdev:input:b0003v046DpC309*
+evdev:input:b0003v046DpC309:*
KEYBOARD_KEY_90001=chat # Messenger/SMS
KEYBOARD_KEY_90002=camera # webcam
KEYBOARD_KEY_90003=prog1 # iTouch
###########################################################
# Pro 7000
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:*
KEYBOARD_KEY_97=prog2
KEYBOARD_KEY_9f=prog1
KEYBOARD_KEY_a0=mute # Fn+F5
###########################################################
# Akoya
-evdev:atkbd:dmi:bvn*:bvr*:svnMEDION*:pnS3409*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnP6669*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:svnMEDION*:pnS3409*:*
+evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:*
+evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnP6669*:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
KEYBOARD_KEY_df=sleep
# FID2060
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:*
KEYBOARD_KEY_6b=channeldown # Thottle Down
KEYBOARD_KEY_6d=channelup # Thottle Up
# NB-A555
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDIONNB:pnA555*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDIONNB:pnA555*:*
KEYBOARD_KEY_63=www # N button
KEYBOARD_KEY_66=prog1 # link 1 button
KEYBOARD_KEY_67=email # envelope button
KEYBOARD_KEY_69=prog2 # link 2 button
# Erazer
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMedion*:pnErazer*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMedion*:pnErazer*:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
###########################################################
# Microsoft Natural Ergonomic Keyboard 4000
-evdev:input:b0003v045Ep00DB*
+evdev:input:b0003v045Ep00DB:*
KEYBOARD_KEY_c022d=up # zoomin
KEYBOARD_KEY_c022e=down # zoomout
# Microsoft (Razer produced) Reclusa keyboard
-evdev:input:b0003v1532p0200*
+evdev:input:b0003v1532p0200:*
KEYBOARD_KEY_c01c9=shuffle
KEYBOARD_KEY_c01ca=up # zoomin
KEYBOARD_KEY_c01cb=down # zoomout
# Micro Star
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*:*
KEYBOARD_KEY_a0=mute # Fn+F9
KEYBOARD_KEY_ae=volumedown # Fn+F7
KEYBOARD_KEY_b0=volumeup # Fn+F8
KEYBOARD_KEY_b2=www # e button
+ KEYBOARD_KEY_c2=ejectcd
KEYBOARD_KEY_df=sleep # Fn+F12
KEYBOARD_KEY_e2=bluetooth # satellite dish2
KEYBOARD_KEY_e4=f21 # Fn+F3 Touchpad disable
KEYBOARD_KEY_f8=brightnessup # Fn+F5
KEYBOARD_KEY_f9=search
-#
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE60*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE70*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE60*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE70*:*
KEYBOARD_KEY_c2=ejectcd
# some MSI models generate ACPI/input events on the LNXVIDEO input devices,
# plus some extra synthesized ones on atkbd as an echo of actually changing the
# brightness; so ignore those atkbd ones, to avoid loops
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U-100*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U100*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U-100*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U100*:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*N033:*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*VR420*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*PR200*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*VR420*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*PR200*:*
KEYBOARD_KEY_f7=reserved
KEYBOARD_KEY_f8=reserved
KEYBOARD_KEY_e4=reserved
# MSI Prestige15 A10SC specific keycodes. Needed for microphone and screen rotation
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*A10SC*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*A10SC*:*
KEYBOARD_KEY_f1=f20
KEYBOARD_KEY_f2=f21
# MSI
###########################################################
-evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:pvr*
+evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:*
KEYBOARD_KEY_0213=f22
KEYBOARD_KEY_0214=f23
###########################################################
# Teres-I
-evdev:input:b0003v15BAp003C*
+evdev:input:b0003v15BAp003C:*
KEYBOARD_KEY_70066=sleep # Fn+F1
KEYBOARD_KEY_700f6=wlan # Fn+F2
KEYBOARD_KEY_700c7=f21 # Fn+F3 touchpad toggle
###########################################################
# Model 2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:*
KEYBOARD_KEY_8e=wlan
KEYBOARD_KEY_f0=switchvideomode
KEYBOARD_KEY_f1=mute
# The key code identifiers used below exactly match the text
# labels on the keys/buttons (or standard icons on the buttons
# that have no text labels), except as noted.
-evdev:input:b0003v05A4p9735*
+evdev:input:b0003v05A4p9735:*
KEYBOARD_KEY_c0015=back
KEYBOARD_KEY_c0012=forward
KEYBOARD_KEY_c000c=stop
###########################################################
# Plantronics .Audio 626 DSP
-evdev:input:b0003v047FpC006*
+evdev:input:b0003v047FpC006:*
KEYBOARD_KEY_b002f=f20 # Microphone mute button; should be micmute
###########################################################
###########################################################
# Purism Librem 13 V2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v2*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v2*:*
KEYBOARD_KEY_56=backslash
# Purism Librem 13 V3
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v3*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v3*:*
KEYBOARD_KEY_56=backslash
# Purism Librem 13 V4
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v4*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v4*:*
KEYBOARD_KEY_56=backslash
###########################################################
# Samsung
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*:*
KEYBOARD_KEY_74=prog1 # User key
KEYBOARD_KEY_75=www
KEYBOARD_KEY_78=mail
KEYBOARD_KEY_f9=!f23 # Fn+F10 Touchpad off
# Series 3
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:*
KEYBOARD_KEY_ce=! # Fn+F1 launch control setting
# Series 5
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_a8=! # Fn Lock - Function lock on
KEYBOARD_KEY_a9=! # Fn Lock - Function lock off
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_a8=! # Fn Lock - Function lock on
KEYBOARD_KEY_a9=! # Fn Lock - Function lock off
# Series 7 / 9
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*350V*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*670Z*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700G*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34]*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*940X3G*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*350V*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*670Z*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700G*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34]*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*940X3G*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_a0=!mute # Fn+F6 mute
KEYBOARD_KEY_ae=!volumedown # Fn+F7
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]*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34][AB]*:*
KEYBOARD_KEY_ce=! # Fn+F8 keyboard backlight up
KEYBOARD_KEY_8d=! # Fn+F7 keyboard backlight down
KEYBOARD_KEY_96=! # Fn+F1 performance mode (?)
KEYBOARD_KEY_97=! # Fn+F12 Wi-Fi toggle
KEYBOARD_KEY_d5=! # Fn+F6 battery life extender
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_8d=!prog3 # Fn+F6 performance mode
KEYBOARD_KEY_97=!kbdillumdown # Fn+F7 keyboard backlight down
KEYBOARD_KEY_d5=!wlan # Fn+F12 Wi-Fi toggle
# Series 7 Ultra
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*7[34]0U3E*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*7[34]0U3E*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down
KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up
KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch
# ATIV Book 6 / 8
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*[68][78]0Z*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*[68][78]0Z*:*
KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up
KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down
# SQ1US
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pnSQ1US:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pnSQ1US:*
KEYBOARD_KEY_d4=menu
KEYBOARD_KEY_d8=f1
KEYBOARD_KEY_d9=f10
KEYBOARD_KEY_ee=f11
# SX20S
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*SX20S*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*SX20S*:*
KEYBOARD_KEY_74=mute
KEYBOARD_KEY_75=mute
KEYBOARD_KEY_77=f22 # Touchpad on
KEYBOARD_KEY_79=f23 # Touchpad off
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:*
KEYBOARD_KEY_ad=leftmeta
###########################################################
###########################################################
# sony-laptop driver
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*:*
KEYBOARD_KEY_06=mute # Fn+F2
KEYBOARD_KEY_07=volumedown # Fn+F3
KEYBOARD_KEY_08=volumeup # Fn+F4
KEYBOARD_KEY_0e=zoom # Fn+F10
KEYBOARD_KEY_10=suspend # Fn+F12
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-C1*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-K25*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-F[1-6]*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FX*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FRV*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-GR*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-TR*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-NV*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-Z*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*VGN-S360*:pvr*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-C1*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-K25*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-F[1-6]*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FX*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FRV*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-GR*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-TR*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-NV*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-Z*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*VGN-S360*:*
KEYBOARD_KEY_06=battery
KEYBOARD_KEY_07=mute
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-AR71*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW*:pvr*
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-Z21*:pvr*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-AR71*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW*:*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-Z21*:*
KEYBOARD_KEY_00=brightnessdown # Fn+F5
KEYBOARD_KEY_10=brightnessup # Fn+F6
KEYBOARD_KEY_11=switchvideomode # Fn+F7
KEYBOARD_KEY_17=prog1
KEYBOARD_KEY_20=media
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW250*:pvr*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW250*:*
KEYBOARD_KEY_10=suspend # Fn+F12
-evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVPC*:pvr*
+evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVPC*:*
KEYBOARD_KEY_05=f21 # Fn+F1 -> KEY_F21 (The actual touchpad toggle)
KEYBOARD_KEY_0d=down # Fn+F9 zoomout
KEYBOARD_KEY_0e=up # Fn+F10 zoomin
# System76
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnSystem76*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnSystem76*:pn*:*
KEYBOARD_KEY_f7=f21 # Touchpad toggle
KEYBOARD_KEY_f8=f21 # Touchpad toggle
# T-bao
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnT-bao:pnTbookair:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnT-bao:pnTbookair:*
KEYBOARD_KEY_76=f21 # Touchpad toggle
###########################################################
###########################################################
# Satellite A100
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITE*A100:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITE*A100:*
KEYBOARD_KEY_a4=stopcd
KEYBOARD_KEY_b2=www
# Satellite A110
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*A110:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*A110:*
KEYBOARD_KEY_92=stop
KEYBOARD_KEY_93=www
KEYBOARD_KEY_94=media
KEYBOARD_KEY_f7=playpause
# Satellite M30X
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*M30X:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*M30X:*
KEYBOARD_KEY_ef=brightnessdown
KEYBOARD_KEY_d9=brightnessup
KEYBOARD_KEY_ee=screenlock
KEYBOARD_KEY_9f=f23 # touchpad disable
# Satellite P75-A
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:*
KEYBOARD_KEY_ef=brightnessdown
KEYBOARD_KEY_ee=brightnessup
KEYBOARD_KEY_a9=switchvideomode # switch display outputs
KEYBOARD_KEY_d4=wlan # RF Switch Off
# Satellite U940
-evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITEU940:pvr*
+evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITEU940:*
KEYBOARD_KEY_13c=brightnessdown
KEYBOARD_KEY_13d=brightnessup
KEYBOARD_KEY_13e=switchvideomode
KEYBOARD_KEY_13f=f21 # Touchpad toggle
# Satellite P75-A7200
-evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr*
+evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:*
KEYBOARD_KEY_13c=brightnessdown
KEYBOARD_KEY_13d=brightnessup
KEYBOARD_KEY_13e=switchvideomode
# VIA
###########################################################
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnVIA:pnK8N800:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnVIA:pnK8N800:*
KEYBOARD_KEY_81=prog1
###########################################################
# VIOS
###########################################################
-evdev:name:SIPODEV USB Composite Device:dmi:bvn*:bvr*:bd*:svnVIOS:pnLTH17:pvr*
+evdev:name:SIPODEV USB Composite Device:dmi:bvn*:bvr*:bd*:svnVIOS:pnLTH17:*
KEYBOARD_KEY_70073=f21 # Touchpad toggle
###########################################################
###########################################################
# P325J
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINET:pnP325J:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINET:pnP325J:*
KEYBOARD_KEY_76=f21 # Touchpad toggle
###########################################################
##########################################
# Ideazon Zboard Merc
-evdev:input:b0003v1038p0210*
+evdev:input:b0003v1038p0210:*
KEYBOARD_KEY_c0227=q
KEYBOARD_KEY_c0223=w
KEYBOARD_KEY_c0221=e
KEYBOARD_KEY_70079=f6
# Ideazon Zboard Fang
-evdev:input:b0003v1038p0310*
+evdev:input:b0003v1038p0310:*
KEYBOARD_KEY_70059=1
KEYBOARD_KEY_7005b=3
KEYBOARD_KEY_70040=equal
###########################################################
# Common Volume Keys
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*SIEMENS:pnAMILO*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*SIEMENS:pnAMILO*:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFOXCONN:pnQBOOK:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMTC:pn*:pvrA0:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMio*Technology:pnN890:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPEGATRON*CORP.:pnSpring*Peak:*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*[uU][35]0[05]*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSATELLITE*[uU][35]0[05]*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*Pro*[uU]300*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnEQUIUM [uU][35]0[05]*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*[uU][35]0[05]*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSATELLITE*[uU][35]0[05]*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*Pro*[uU]300*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnEQUIUM [uU][35]0[05]*:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnViooo*Corporation:pnPT17:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHANNspree:pnSN10E100:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pni1520M:*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pn*nScreen*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pnJoybook*Lite*:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pn*nScreen*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pnJoybook*Lite*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:*
KEYBOARD_KEY_a0=! # mute
KEYBOARD_KEY_ae=! # volume down
KEYBOARD_KEY_b0=! # volume up
# with an accompanying variant (defined with XKB_FIXED_VARIANT) if necessary.
# Yubico Yubico Yubikey II"
-evdev:input:b0003v1050p0010*
+evdev:input:b0003v1050p0010:*
# Yubico Yubikey NEO OTP+CCID
-evdev:input:b0003v1050p0111*
+evdev:input:b0003v1050p0111:*
# Yubico Yubikey NEO OTP+U2F+CCID
-evdev:input:b0003v1050p0116*
+evdev:input:b0003v1050p0116:*
# OKE Electron Company USB barcode reader
-evdev:input:b0003v05FEp1010*
- XKB_FIXED_LAYOUT="us"
- XKB_FIXED_VARIANT=""
+evdev:input:b0003v05FEp1010:*
+ XKB_FIXED_LAYOUT=us
+ XKB_FIXED_VARIANT=
######################### LACK OF MODIFIER LEDS ############################
# This section lists keyboard which do not have their own LEDs for some
# Presence of a LED is implicit when the property is absent.
# Logitech K750
-evdev:input:b0003v046Dp4002*
+evdev:input:b0003v046Dp4002:*
KEYBOARD_LED_NUMLOCK=0
KEYBOARD_LED_CAPSLOCK=0
# PFU Limited HHKB Professional JP
-evdev:input:b0003v04FEp000D*
+evdev:input:b0003v04FEp000D:*
KEYBOARD_LED_NUMLOCK=0
KEYBOARD_LED_CAPSLOCK=0
# Lenovo ThinkPad T430s
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT430s
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT430s:*
KEYBOARD_LED_CAPSLOCK=0
# Lenovo ThinkPad T440s
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s:*
KEYBOARD_LED_CAPSLOCK=0
# Lenovo ThinkPad T450s
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s:*
KEYBOARD_LED_CAPSLOCK=0
# Lenovo ThinkPad T560s
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560s
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560s:*
KEYBOARD_LED_CAPSLOCK=0
KEYBOARD_LED_NUMLOCK=0
# Lenovo ThinkPad X1 Carbon 3rd Gen
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:*
KEYBOARD_LED_CAPSLOCK=0
######################### FIXED MODEL DEVICES #############################
# The model must be an xkb compatible model (defined with XKB_FIXED_MODEL).
# Chromebooks
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:pvr*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPeppy:pvr*
- XKB_FIXED_MODEL="chromebook"
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPeppy:*
+ XKB_FIXED_MODEL=chromebook
# The lookup keys are composed in:
# 60-sensor.rules
#
-# Note: The format of the "sensor:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
+# Note: The format of the "sensor:" prefix match key is a contract between the
+# rules file and the hardware data, it might change in later revisions to
+# support more or better matches, it is not necessarily expected to be a stable
+# ABI.
#
# Match string formats:
-# sensor:modalias:<parent device modalias>:dmi:<dmi string>
+# sensor:modalias:<parent modalias pattern>:dmi:<dmi pattern>
#
-# The device modalias can be seen in the `modalias` file
-# of the sensor parent, for example:
-# cat /sys/`udevadm info -q path -n /dev/iio:device0`/../modalias
+# The device modalias can be seen in the `modalias` file of the sensor parent,
+# for example:
+# cat /sys/`udevadm info -q path -n /dev/iio:device0`/../modalias
#
# The full DMI string of the running machine can be read from
# /sys/class/dmi/id/modalias
# where <matrix> is a mount-matrix in the format specified in the IIO
# subsystem[1]. The default, when unset, is equivalent to:
# ACCEL_MOUNT_MATRIX=1, 0, 0; 0, 1, 0; 0, 0, 1
-# eg. the identity matrix.
+# eg. the identity matrix,
# and <value> is an integer value above which an object is considered
# close by a proximity sensor:
# PROXIMITY_NEAR_LEVEL=100
# or 'display'. The default, when unset, is equivalent to:
# ACCEL_LOCATION=display
#
+# All matches should end in ':*' to allow future expansions of the match key.
+
# Sort by brand, model
#########################################
# Acer
#########################################
-sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-011*
+sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-011:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-012*
+sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-012:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:BOSC0200*:dmi:*svnAcer*:*TP-SW5-017-17BU*
+sensor:modalias:acpi:BOSC0200*:dmi:*svnAcer*:*TP-SW5-017-17BU:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, -1
sensor:modalias:acpi:BMA250E*:dmi:*:svnAcer:pnIconiaW1-810:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
-sensor:modalias:acpi:SMO8500:*:dmi:*Acer*:pnOneS1002*
+sensor:modalias:acpi:SMO8500:*:dmi:*Acer*:pnOneS1002:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1
sensor:modalias:acpi:KIOX0009*:dmi:*:svnAcer:pnOneS1003:*
sensor:modalias:acpi:BOSC0200*:dmi:*:svnAcer*:pnSwitchSW312-31:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-32*
-sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-33*
- ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
-
-sensor:modalias:acpi:BOSC0200*:dmi:*svnAcer*:*pnSpinSP111-34*
+sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-32:*
+sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-33:*
+sensor:modalias:acpi:BOSC0200*:dmi:*svnAcer*:*pnSpinSP111-34:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
#########################################
#########################################
# AsusTek
#########################################
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100CHI*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100CHI:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT300CHI*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT300CHI:*
ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnM80TA*
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TA*
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT200TA*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnM80TA:*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TA:*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT200TA:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnTP201SA*
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pn*E205SA*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnTP201SA:*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pn*E205SA:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LA*
-sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD*
+sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LA:*
+sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN*
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:KXJ2109*:dmi:*:svnASUSTeK*:pnME176C*
+sensor:modalias:acpi:KXJ2109*:dmi:*:svnASUSTeK*:pnME176C:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
-sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LJ*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LJ:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LAB*
-sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LAB:*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LD*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LD:*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LAB:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-sensor:modalias:acpi:BOSC0200*:dmi:*svn*ASUSTeK*:*pn*TP412UA*
+sensor:modalias:acpi:BOSC0200*:dmi:*svn*ASUSTeK*:*pn*TP412UA:*
ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1
#########################################
# Axxo
#########################################
-sensor:modalias:acpi:SMO8500*:dmi:*:svnStandard:pnWCBT1011:*
+sensor:modalias:acpi:SMO8500*:dmi:*:svnStandard:pnWCBT1011::*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrG1D_S165*:svnilife:pnS165:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+# Chuwi Hi8 (CWI509)
+sensor:modalias:acpi:BMA250E*:dmi:*svnilife*:pnS806:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
# Chuwi Hi8 Pro (CWI513)
sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnX1D3_C806N:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# Chuwi HiBook does not have its product name filled, so we
# match the entire dmi-alias, assuming that the use of a BOSC0200 +
# bios-version + bios-date combo is unique
-sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/07/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/07/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
# Chuwi HiBook Pro (CWI526)
# Chuwi CoreBook
# Chuwi CoreBook does not have its product name filled, so we
# match the entire dmi-alias
-sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrY13D_KB133.103:bd06/01/2018:svnHampoo:pnDefaultstring:pvrV100:rvnHampoo:rnY13D_KB133:rvrV100:cvnDefaultstring:ct9:cvrDefaultstring:
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrY13D_KB133.103:bd06/01/2018:svnHampoo:pnDefaultstring:pvrV100:rvnHampoo:rnY13D_KB133:rvrV100:cvnDefaultstring:ct9:cvrDefaultstring:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
#########################################
# Cytrix (Mytrix)
#########################################
-sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t*
+sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnDell*:pnVostro5581:*
ACCEL_LOCATION=base
+sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnDell*:pnLatitude9520:*:ct10:*
+ ACCEL_LOCATION=base
+
+sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnDell*:pnLatitude7420:*
+ ACCEL_LOCATION=base
+
# Dell Venue 8 Pro 3845
-sensor:modalias:acpi:INVN6500*:dmi:*svnDellInc.*:pnVenue8Pro3845*
+sensor:modalias:acpi:INVN6500*:dmi:*svnDellInc.*:pnVenue8Pro3845:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# Dell Venue 10 Pro 5055
-sensor:modalias:acpi:INVN6500*:dmi:*svnDell*:pnVenue10Pro5055*
+sensor:modalias:acpi:INVN6500*:dmi:*svnDell*:pnVenue10Pro5055:*
ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1
#########################################
# DEXP
#########################################
-sensor:modalias:acpi:SMO8500*:dmi:*svn*DEXP*:*pn*DEXPOEM*
+sensor:modalias:acpi:SMO8500*:dmi:*svn*DEXP*:*pn*DEXPOEM:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
#########################################
#########################################
# Endless
#########################################
-sensor:modalias:acpi:ACCE0001*:dmi:*svnEndless*:*pnELT-NL3*
+sensor:modalias:acpi:ACCE0001*:dmi:*svnEndless*:*pnELT-NL3:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 0, 0, -1; -1, 0, 0
#########################################
#########################################
# Google Chromebooks
#########################################
-sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE*
+sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
# caroline board (Samsung Chromebook Pro) reports itself as svnGoogle
-sensor:modalias:platform:cros-ec-accel:dmi:*:svnGoogle:pnCaroline*
+sensor:modalias:platform:cros-ec-accel:dmi:*:svnGoogle:pnCaroline*:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
# Dell Inspiron Chromebook 14 2-in-1
-sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*
+sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
# nocturne board (Google Pixel Slate)
-sensor:modalias:platform:cros-ec-accel:dmi:*Google_Nocturne*
+sensor:modalias:platform:cros-ec-accel:dmi:*Google_Nocturne*:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
#########################################
# and no other devices have both board_name *and* product_name set to
# "Default string". So combined with the sensor modalias and BIOS date this
# should be unique enough to identify the GPDwin
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd10/25/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd11/18/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/23/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/26/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd02/21/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd03/20/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/25/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd10/25/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd11/18/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/23/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/26/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd02/21/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd03/20/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/25/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
ACCEL_LOCATION=base
#########################################
# The I.T.Works TW891 2-in-1's DMI has the product-name field set, but not
# the sys-vendor field. This makes the DMI data a bit generic, so we match
# the whole dmi modalias, except for the BIOS version/date
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnTobefilledbyO.E.M.:pnTW891:pvrTobefilledbyO.E.M.:rvnTobefilledbyO.E.M.:rnTW891:rvr1.0:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnTobefilledbyO.E.M.:pnTW891:pvrTobefilledbyO.E.M.:rvnTobefilledbyO.E.M.:rnTW891:rvr1.0:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
# I.T.Works TW701 7" windows tablet, same hw as Trekstor ST70416-6
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
# NB111
-sensor:modalias:acpi:KIOX010A*:dmi:*svn*IRBIS*:*pn*NB111*
+sensor:modalias:acpi:KIOX010A*:dmi:*svn*IRBIS*:*pn*NB111:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
#TW118
#########################################
# iOTA 360
#########################################
-sensor:modalias:acpi:KIOX000A*:dmi:*svn*iOTA*:*pn*IOTA2210*
+sensor:modalias:acpi:KIOX000A*:dmi:*svn*iOTA*:*pn*IOTA2210:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
#########################################
#########################################
# EZpad mini 3
-sensor:modalias:acpi:BOSC0200*:dmi:bvnINSYDECorp.:bvrjumperx.T87.KFBNEE*
+sensor:modalias:acpi:BOSC0200*:dmi:bvnINSYDECorp.:bvrjumperx.T87.KFBNEE:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# EZpad 6 Pro
#########################################
# Lamina
#########################################
-sensor:modalias:acpi:SMO8500*:dmi:*svnLamina*:*pnT701BR.SE*
+sensor:modalias:acpi:SMO8500*:dmi:*svnLamina*:*pnT701BR.SE:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
-sensor:modalias:acpi:KIOX000A*:dmi:*svnLAMINA:pnT-1016BNORD*
+sensor:modalias:acpi:KIOX000A*:dmi:*svnLAMINA:pnT-1016BNORD:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
#########################################
sensor:modalias:acpi:NCPE0388*:dmi:*:rnLenovoYOGA510-14IKB:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1
-sensor:modalias:acpi:BOSC0200*:dmi:*ThinkPadYoga11e3rdGen*
+sensor:modalias:acpi:BOSC0200*:dmi:*ThinkPadYoga11e3rdGen:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
# Miix3-1030
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
# IdeaPad Miix 300
-sensor:modalias:acpi:SMO8500*:dmi:bvnLENOVO:*:pvrMIIX300-*
+sensor:modalias:acpi:SMO8500*:dmi:bvnLENOVO:*:pvrMIIX300-*:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# IdeaPad Miix 310 note this only is for BIOS version (bvr) 1HCN4?WW and 1HCN2?WW, which has
# IdeaPad Miix 320, different batches use a different sensor
sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XF:*
-sensor:modalias:acpi:SMO8840*:dmi:*:svnLENOVO:pn80XF:pvrLenovoMIIX320*
+sensor:modalias:acpi:SMO8840*:dmi:*:svnLENOVO:pn80XF:pvrLenovoMIIX320:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# IdeaPad Miix 510, multiple expressions match different internal names
#########################################
# MPMAN
#########################################
+
+# MPMAN Converter 9, same hw as the I.T.Works TW891 2-in-1
+sensor:modalias:acpi:SMO8500*:dmi:*:svnMPMAN:pnConverter9:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
+# MPMAN MPWIN895C
sensor:modalias:acpi:BMA250E*:dmi:*:svnMPMAN:pnMPWIN8900CL:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# Onda v975w, generic DMI strings, match entire dmi modalias inc. bios-date
-sensor:modalias:acpi:SMO8500*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd07/25/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:SMO8500*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd07/25/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
#########################################
# The Point of View TAB-P800W does not have its product name filled, so we
# match the entire dmi-alias, assuming that the use of a BMA250E +
# bios-version + bios-date combo is unique
-sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1013:bd08/22/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
-sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1013:bd08/22/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
+sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
# Point of View TAB-P1005W-232 (v2.0)
#########################################
# SCT101CTM
-sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrSCH12i.WJ210Z.KtBJRCA03*
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrSCH12i.WJ210Z.KtBJRCA03:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
# Teclast X98 Plus I (A5C6), generic DMI strings, match entire dmi modalias inc. bios-date
-sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.011:bd11/03/2015:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnCherryTrailCR:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.011:bd11/03/2015:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnCherryTrailCR:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
# Teclast X98 Plus II
#########################################
# Thundersoft TST168 tablet, generic DMI strings, match entire dmi modalias inc. bios-date
-sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd04/15/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd04/15/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
#
# If the property is missing, user-space can assume:
# ID_INPUT_JOYSTICK_INTEGRATION=external
+#
+# All matches should end in ':*' to allow future expansions of the match key.
joystick:bluetooth:*
ID_INPUT_JOYSTICK_INTEGRATION=external
###########################################################
# GPD Win, Classic and XBox 360 compat modes
-joystick:usb:v11c5p5507*
-joystick:usb:v045ep028e*
+joystick:usb:v11c5p5507:*
+joystick:usb:v045ep028e:*
ID_INPUT_JOYSTICK_INTEGRATION=internal
# The lookup keys are composed in:
# 70-mouse.rules
#
-# Note: The format of the "mouse:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
+# Note: The format of the "mouse:" prefix match key is a contract between the
+# rules file and the hardware data, it might change in later revisions to
+# support more or better matches, it is not necessarily expected to be a stable
+# ABI.
#
-# Match string format:
+# Match key format:
# mouse:<subsystem>:v<vid>p<pid>:name:<name>:
#
# Supported subsystems: usb, bluetooth
# vid/pid as 4-digit hex lowercase vendor/product
#
# if vid/pid is unavailable, use
-# mouse:*:name:<name>:
+# mouse:*:name:<name>:*
# if name is unavailable, use
-# mouse:<subsystem>:v<vid>p<pid>:*
+# mouse:<subsystem>:v<vid>p<pid>:*
#
# For example, the following 5 matches all match the same mouse:
-# mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse:
-# mouse:usb:*:name:Lenovo Optical USB Mouse:
-# mouse:usb:v17efp6019:*
-# mouse:*:name:Lenovo Optical USB Mouse:
+# mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse:*
+# mouse:usb:*:name:Lenovo Optical USB Mouse:*
+# mouse:usb:v17efp6019:*
+# mouse:*:name:Lenovo Optical USB Mouse:*
+#
+# All matches should end in ':*' to allow future expansions of the match key.
#
# To add local entries, create a new file
# /etc/udev/hwdb.d/71-mouse-local.hwdb
# and add your rules there. To load the new rules execute (as root):
# systemd-hwdb update
# udevadm trigger /dev/input/eventXX
-# where /dev/input/eventXX is the mouse in question. If in
-# doubt, simply use /dev/input/event* to reload all input rules.
+# where /dev/input/eventXX is the mouse in question. If in doubt, simply use
+# /dev/input/event* to reload all input rules.
#
# If your changes are generally applicable, preferably send them as a pull
# request to
# udevadm info /dev/input/eventXX.
#
# Allowed properties are:
-# ID_INPUT_TRACKBALL
-# MOUSE_DPI
-# MOUSE_WHEEL_CLICK_ANGLE
-# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL
-# MOUSE_WHEEL_CLICK_COUNT
-# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL
+# ID_INPUT_TRACKBALL
+# MOUSE_DPI
+# MOUSE_WHEEL_CLICK_ANGLE
+# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL
+# MOUSE_WHEEL_CLICK_COUNT
+# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL
#
#########################################
# ID_INPUT_TRACKBALL #
#########################################
#
# DPI settings are specified as
-# MOUSE_DPI=<dpi>[@<frequency>]
+# MOUSE_DPI=<dpi>[@<frequency>]
#
# Where <dpi> is the resolution in dots per inch, and <frequency> the
# sampling frequency in Hz (optional). If a device supports dynamic
##########################################
# Generic
##########################################
-mouse:*:name:*Trackball*:
-mouse:*:name:*trackball*:
-mouse:*:name:*TrackBall*:
+mouse:*:name:*Trackball*:*
+mouse:*:name:*trackball*:*
+mouse:*:name:*TrackBall*:*
ID_INPUT_TRACKBALL=1
##########################################
# Apple MagicMouse
# Note: this device changes name once connected to a mac, the name ends up
# as $username`s mouse
-mouse:bluetooth:v05acp030d:name:*:
+mouse:bluetooth:v05acp030d:name:*:*
MOUSE_DPI=1300@1000
##########################################
##########################################
# Chicony 2.4G Multimedia Wireless Kit MG-0919
-mouse:usb:v04f2p0963:name:Chicony 2.4G Multimedia Wireless Kit:
+mouse:usb:v04f2p0963:name:Chicony 2.4G Multimedia Wireless Kit:*
MOUSE_DPI=1000@142
##########################################
##########################################
# Dell MUAR DEL7
-mouse:usb:v413cp3012:name:Dell Dell USB Optical Mouse:
+mouse:usb:v413cp3012:name:Dell Dell USB Optical Mouse:*
MOUSE_DPI=400@166
# Dell USB Laser Mouse
-mouse:usb:v046dpc063:name:DELL DELL USB Laser Mouse:
+mouse:usb:v046dpc063:name:DELL DELL USB Laser Mouse:*
MOUSE_DPI=1000@125
# Dell MS116t
-mouse:usb:v413cp301a:name:PixArt Dell MS116 USB Optical Mouse:
+mouse:usb:v413cp301a:name:PixArt Dell MS116 USB Optical Mouse:*
MOUSE_DPI=1000@125
##########################################
#########################################
# Dynex Wired Optical Mouse (DX-WMSE2)
-mouse:usb:v0461p4d46:name:USB Optical Mouse:
+mouse:usb:v0461p4d46:name:USB Optical Mouse:*
MOUSE_DPI=1000@125
##########################################
# Fujitsu Siemens
##########################################
-mouse:usb:v0461p4d16:name:USB Optical Mouse:
+mouse:usb:v0461p4d16:name:USB Optical Mouse:*
MOUSE_DPI=500@125
##########################################
##########################################
# SNES Mouse plugged into a Retrode 2
-mouse:usb:v0403p97c1:name:Retrode SNES Mouse:
+mouse:usb:v0403p97c1:name:Retrode SNES Mouse:*
MOUSE_DPI=235@126
##########################################
##########################################
# FM-901 Wireless Mouse
-mouse:usb:v1ea7p000b:name:2.4G RF Mouse:
+mouse:usb:v1ea7p000b:name:2.4G RF Mouse:*
MOUSE_DPI=*800@125 1600@125
# WK-727
-mouse:usb:v04d9p0499:name:*
+mouse:usb:v04d9p0499:name:*:*
MOUSE_DPI=800@125
##########################################
##########################################
# HandShoe Mouse
-mouse:usb:v192fp0916:name:USB Optical Mouse:
+mouse:usb:v192fp0916:name:USB Optical Mouse:*
MOUSE_DPI=1000@128
##########################################
##########################################
# Hoverstop active ergonomic mouse
-mouse:usb:v088dp1234:name:HoverStop NL Hoverstop active ergonomic mouse:
+mouse:usb:v088dp1234:name:HoverStop NL Hoverstop active ergonomic mouse:*
MOUSE_DPI=400@129
##########################################
##########################################
# HP USB 1000dpi Laser Mouse
-mouse:usb:v0458p0133:name:Mouse Laser Mouse:
+mouse:usb:v0458p0133:name:Mouse Laser Mouse:*
MOUSE_DPI=1000@125
MOUSE_WHEEL_CLICK_ANGLE=15
# HP X1000
# Dell MS111-T
-mouse:usb:v093ap2510:name:PixArt USB Optical Mouse:
-mouse:usb:v093ap2510:name:PIXART USB OPTICAL MOUSE:
+mouse:usb:v093ap2510:name:PixArt USB Optical Mouse:*
+mouse:usb:v093ap2510:name:PIXART USB OPTICAL MOUSE:*
MOUSE_DPI=1000@125
# HP X1200 Optical Mouse
-mouse:usb:v03f0p0641:name:PixArt HP X1200 USB Optical Mouse:
+mouse:usb:v03f0p0641:name:PixArt HP X1200 USB Optical Mouse:*
MOUSE_DPI=1100@125
##########################################
##########################################
# Kensington Expert Mouse trackball
-mouse:usb:v047dp1020:*Kensington Expert Mouse*
+mouse:usb:v047dp1020:*Kensington Expert Mouse*:*
ID_INPUT_TRACKBALL=1
##########################################
##########################################
# Lenovo Optical USB Mouse
-mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse:
+mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse:*
MOUSE_DPI=1000@125
# Lenovo M-U0025-O
-mouse:usb:v17efp6019:name:Logitech Lenovo USB Optical Mouse:
+mouse:usb:v17efp6019:name:Logitech Lenovo USB Optical Mouse:*
MOUSE_DPI=1000@166
# Lenovo USB mouse model MO28UOL
-mouse:usb:v04b3p310c:name:USB Optical Mouse:
+mouse:usb:v04b3p310c:name:USB Optical Mouse:*
MOUSE_DPI=400@142
# Lenovo Precision USB Mouse
-mouse:usb:v17efp6050:name:Lenovo Precision USB Mouse:
+mouse:usb:v17efp6050:name:Lenovo Precision USB Mouse:*
MOUSE_DPI=1200@127
# Lenovo MOBGUL
-mouse:usb:v17efp601d:name:Primax Lenovo Laser Mouse:
+mouse:usb:v17efp601d:name:Primax Lenovo Laser Mouse:*
MOUSE_DPI=1600@125
# Lenovo MOBGULA
-mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse:
+mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse:*
MOUSE_DPI=1600@125
# ThinkPad USB Laser Mouse
-mouse:usb:v17efp6044:name:ThinkPad USB Laser Mouse:
+mouse:usb:v17efp6044:name:ThinkPad USB Laser Mouse:*
MOUSE_DPI=1200@125
##########################################
## G Series ##
# Logitech G5 Laser Mouse
-mouse:usb:v046dpc049:name:Logitech USB Gaming Mouse:
+mouse:usb:v046dpc049:name:Logitech USB Gaming Mouse:*
MOUSE_DPI=400@500 *800@500 2000@500
# Logitech G500s Laser Gaming Mouse
-mouse:usb:v046dpc24e:name:Logitech G500s Laser Gaming Mouse:
+mouse:usb:v046dpc24e:name:Logitech G500s Laser Gaming Mouse:*
MOUSE_DPI=400@500 *800@500 2000@500
# Logitech G9
-mouse:usb:v046dpc048:name:Logitech G9 Laser Mouse:
+mouse:usb:v046dpc048:name:Logitech G9 Laser Mouse:*
MOUSE_DPI=400@1000 800@1000 *1600@1000
# Logitech G9x [Call of Duty MW3 Edition]
-mouse:usb:v046dpc249:name:Logitech G9x Laser Mouse:
+mouse:usb:v046dpc249:name:Logitech G9x Laser Mouse:*
MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000
# Logitech G100s Optical Gaming Mouse
-mouse:usb:v046dpc247:name:Logitech G100s Optical Gaming Mouse:
+mouse:usb:v046dpc247:name:Logitech G100s Optical Gaming Mouse:*
MOUSE_DPI=*1000@500 1750@500 2500@500
# Logitech G400 (Wired)
-mouse:usb:v046dpc245:name:Logitech Gaming Mouse G400:
+mouse:usb:v046dpc245:name:Logitech Gaming Mouse G400:*
MOUSE_DPI=400@1000 *800@1000 1800@1000 3600@1000
# Logitech G400s (Wired)
-mouse:usb:v046dpc24c:name:Logitech G400s Optical Gaming Mouse:
+mouse:usb:v046dpc24c:name:Logitech G400s Optical Gaming Mouse:*
MOUSE_DPI=400@1000 *800@1000 2000@1000 4000@1000
# Logitech G402 Hyperion Fury
-mouse:usb:v046dpc07e:name:Logitech Gaming Mouse G402:
+mouse:usb:v046dpc07e:name:Logitech Gaming Mouse G402:*
MOUSE_DPI=400@1000 *800@1000 1600@1000 3200@1000
# Logitech G500 Mouse
-mouse:usb:v046dpc068:name:Logitech G500:
+mouse:usb:v046dpc068:name:Logitech G500:*
MOUSE_DPI=*1600@500 2600@500 3600@500
# Logitech G502 Proteus Spectrum
-mouse:usb:v046dpc332:name:Logitech Gaming Mouse G502:
+mouse:usb:v046dpc332:name:Logitech Gaming Mouse G502:*
# Logitech G502 HERO SE
-mouse:usb:v046dpc08b:name:Logitech G502 HERO SE:
+mouse:usb:v046dpc08b:name:Logitech G502 HERO SE:*
# Logitech G502 Hero
-mouse:usb:v046dpc08b:name:Logitech G502 HERO Gaming Mouse:
+mouse:usb:v046dpc08b:name:Logitech G502 HERO Gaming Mouse:*
MOUSE_DPI=1200@1000 *2400@1000 3200@1000 6400@1000
# Logitech G700 Laser Mouse (Wired)
-mouse:usb:v046dpc06b:name:Logitech G700 Laser Mouse:
+mouse:usb:v046dpc06b:name:Logitech G700 Laser Mouse:*
# Logitech G700 Laser Mouse (Wireless)
-mouse:usb:v046dpc531:name:Logitech USB Receiver:
+mouse:usb:v046dpc531:name:Logitech USB Receiver:*
MOUSE_DPI=*1000@500 3800@500 500@1000 1500@1000 2000@1000
# Logitech G703 (Wired)
-mouse:usb:v046dpc087:name:Logitech G703 Wired/Wireless Gaming Mouse:
+mouse:usb:v046dpc087:name:Logitech G703 Wired/Wireless Gaming Mouse:*
# Logitech G703 (Wireless)
-mouse:usb:v046dpc539:name:Logitech USB Receiver Mouse:
+mouse:usb:v046dpc539:name:Logitech USB Receiver Mouse:*
MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000
## M Series ##
# Logitech Wireless Mouse M185
-mouse:usb:v046dp4008:name:Logitech M185:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4008:
+mouse:usb:v046dp4008:name:Logitech M185:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4008:*
MOUSE_DPI=1000@125
# Logitech Wireless Mouse M510
-mouse:usb:v046dp1025:name:Logitech M510:
+mouse:usb:v046dp1025:name:Logitech M510:*
MOUSE_DPI=1000@125
# Logitech M705 (marathon mouse)
-mouse:usb:v046dp101b:name:Logitech M705:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101b:
+mouse:usb:v046dp101b:name:Logitech M705:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101b:*
MOUSE_DPI=1000@125
# Logitech M705 (newer version?)
-mouse:usb:v046dp406d:name:Logitech M705:
+mouse:usb:v046dp406d:name:Logitech M705:*
MOUSE_DPI=1000@167
# Logitech M305 Wireless Optical Mouse
-mouse:usb:v046dpc52f:name:Logitech USB Receiver:
+mouse:usb:v046dpc52f:name:Logitech USB Receiver:*
MOUSE_DPI=1000@170
# Logitech Wireless Mouse M310
-mouse:usb:v046dp1024:name:Logitech M310:
+mouse:usb:v046dp1024:name:Logitech M310:*
MOUSE_DPI=1100@168
# Logitech Wireless Mouse M325
-mouse:usb:v046dp400a:name:Logitech M325:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:400a:
+mouse:usb:v046dp400a:name:Logitech M325:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:400a:*
MOUSE_DPI=600@166
MOUSE_WHEEL_CLICK_ANGLE=20
# Logitech M570 trackball
-mouse:usb:v046dp1028:name:Logitech M570:
+mouse:usb:v046dp1028:name:Logitech M570:*
MOUSE_DPI=540@167
ID_INPUT_TRACKBALL=1
## MX Series ##
# Logitech Performance MX
-mouse:usb:v046dp101a:name:Logitech Performance MX:
+mouse:usb:v046dp101a:name:Logitech Performance MX:*
MOUSE_DPI=1000@166
# Logitech MX Revolution
-mouse:usb:v046dpc51a:name:Logitech USB Receiver:
+mouse:usb:v046dpc51a:name:Logitech USB Receiver:*
MOUSE_DPI=800@200
# Logitech MX 518
-mouse:usb:v046dpc01e:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc01e:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=400@125 *800@125 1600@125
# Logitech MX1000 Laser Cordless Mouse
-mouse:bluetooth:v046dpb003:name:Logitech MX1000 mouse:
+mouse:bluetooth:v046dpb003:name:Logitech MX1000 mouse:*
MOUSE_DPI=800@80
# Logitech Anywhere MX
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:1017:
-mouse:usb:v046dp1017:name:Logitech Anywhere MX:
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:1017:*
+mouse:usb:v046dp1017:name:Logitech Anywhere MX:*
MOUSE_WHEEL_CLICK_ANGLE=20
# Logitech Anywhere MX 2S (via Logitech Unifying Receiver)
-mouse:usb:v046dp406a:name:Logitech MX Anywhere 2S:
+mouse:usb:v046dp406a:name:Logitech MX Anywhere 2S:*
MOUSE_WHEEL_CLICK_ANGLE=20
# Logitech Anywhere MX 2S (via Bluetooth)
-mouse:bluetooth:v046dpb01a:name:MX Anywhere 2S Mouse:
+mouse:bluetooth:v046dpb01a:name:MX Anywhere 2S Mouse:*
MOUSE_WHEEL_CLICK_ANGLE=20
# Logitech MX Master (via Logitech Unifying Receiver)
# Horiz wheel has 14 stops, angle is rounded up
-mouse:usb:v046dp4060:name:Logitech MX Master:
-mouse:usb:v046dp4041:name:Logitech MX Master:
+mouse:usb:v046dp4060:name:Logitech MX Master:*
+mouse:usb:v046dp4041:name:Logitech MX Master:*
MOUSE_DPI=1000@166
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
# Logitech MX Master (via Bluetooth)
# Horiz wheel has 14 stops, angle is rounded up
-mouse:bluetooth:v046dpb012:name:MX Master Mouse:
+mouse:bluetooth:v046dpb012:name:MX Master Mouse:*
MOUSE_DPI=1000@2000
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
# Logitech MX Master 2S (via Logitech Unifying Receiver)
# Horiz wheel has 14 stops, angle is rounded up
-mouse:usb:v046dp4069:name:Logitech MX Master 2s:
+mouse:usb:v046dp4069:name:Logitech MX Master 2s:*
MOUSE_DPI=1000@125
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
# Logitech MX Master 2S (via Bluetooth)
# Horiz wheel has 14 stops, angle is rounded up
-mouse:bluetooth:v046dpb019:name:MX Master 2S Mouse:
+mouse:bluetooth:v046dpb019:name:MX Master 2S Mouse:*
MOUSE_DPI=1000@2000
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14
# Logitech MX Ergo (via Bluetooth)
-mouse:bluetooth:v046dpb01d:name:MX Ergo Mouse:
+mouse:bluetooth:v046dpb01d:name:MX Ergo Mouse:*
ID_INPUT_TRACKBALL=1
## Other ##
# Logitech M-BJ58 Optical Mouse
-mouse:usb:v046dpc00e:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc00e:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=400@125
# Logitech Mini Optical Mouse
-mouse:usb:v046dpc016:name:Logitech Optical USB Mouse:
+mouse:usb:v046dpc016:name:Logitech Optical USB Mouse:*
MOUSE_DPI=400@125
# Logitech MX310 Optical Mouse
-mouse:usb:v046dpc01b:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc01b:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=400@125
# Logitech USB-PS/2 M-BT58
-mouse:usb:v046dpc03e:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc03e:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=400@125
# Logitech TrackMan Marble Wheel USB
-mouse:usb:v046dpc401:name:Logitech USB-PS/2 Trackball:
+mouse:usb:v046dpc401:name:Logitech USB-PS/2 Trackball:*
MOUSE_DPI=400@125
# Logitech Cordless MouseMan Optical M-RM63
-mouse:usb:v046dpc501:name:Logitech USB Receiver:
+mouse:usb:v046dpc501:name:Logitech USB Receiver:*
MOUSE_DPI=800@63
# Logitech USB-PS/2 M-BZ96C
-mouse:usb:v046dpc045:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc045:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=600@125
# Logitech MX400 Performance Laser Mouse
-mouse:usb:v046dpc043:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc043:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=800@125
# Logitech MX1000 Laser Cordless Mouse
-mouse:usb:v046dpc50e:name:Logitech USB RECEIVER:
+mouse:usb:v046dpc50e:name:Logitech USB RECEIVER:*
MOUSE_DPI=800@125
# Logitech Cordless Click! Plus
-mouse:usb:v046dpc50e:name:Logitech USB Receiver:
+mouse:usb:v046dpc50e:name:Logitech USB Receiver:*
MOUSE_DPI=800@125
# Logitech, Inc. RX 300 Optical Mouse
-mouse:usb:v046dpc040:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc040:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=800@125
# Logitech, Inc. RX 250 Optical Mouse
-mouse:usb:v046dpc050:name:Logitech USB-PS/2 Optical Mouse:
+mouse:usb:v046dpc050:name:Logitech USB-PS/2 Optical Mouse:*
MOUSE_DPI=1000@142
# Logitech B605 Wireless Mouse (also M505)
-mouse:usb:v046dp101d:name:Logitech B605:
-mouse:usb:v046dp101d:name:Logitech M505:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101d:
+mouse:usb:v046dp101d:name:Logitech B605:*
+mouse:usb:v046dp101d:name:Logitech M505:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101d:*
MOUSE_DPI=900@166
# Logitech Cordless Desktop Wave Mouse
-mouse:usb:v046dpc517:name:Logitech USB Receiver:
+mouse:usb:v046dpc517:name:Logitech USB Receiver:*
MOUSE_DPI=950@125
# Logitech RX1000 Laser Mouse
-mouse:usb:v046dpc046:name:Logitech USB Optical Mouse:
+mouse:usb:v046dpc046:name:Logitech USB Optical Mouse:*
MOUSE_DPI=1000@125
# Logitech M100 Optical Mouse
-mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
+mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:*
MOUSE_DPI=1000@125
# Logitech USB Laser Mouse M-U0011-O rebranded as "terra Laser"
-mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
+mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:*
MOUSE_DPI=1000@125
# Logitech USB Laser Mouse M-U0007 [M500]
-mouse:usb:v046dpc069:name:Logitech USB Laser Mouse:
+mouse:usb:v046dpc069:name:Logitech USB Laser Mouse:*
MOUSE_DPI=1000@125
# Logitech V500 Cordless Notebook Mouse
-mouse:usb:v046dpc510:name:Logitech USB Receiver:
+mouse:usb:v046dpc510:name:Logitech USB Receiver:*
MOUSE_DPI=1000@125
# Logitech M560 Wireless Mouse
-mouse:usb:v046dp402d:name:Logitech M560:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d:
+mouse:usb:v046dp402d:name:Logitech M560:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d:*
MOUSE_DPI=1000@125
# Logitech MK260 Wireless Combo Receiver aka M-R0011
-mouse:usb:v046dpc52e:name:Logitech USB Receiver:
+mouse:usb:v046dpc52e:name:Logitech USB Receiver:*
MOUSE_DPI=1000@200
# Logitech USB Laser Mouse M-UAS144 [LS1 Laser Mouse]
-mouse:usb:v046dpc062:name:Logitech USB Laser Mouse:
+mouse:usb:v046dpc062:name:Logitech USB Laser Mouse:*
MOUSE_DPI=1200@125
# Logitech T620 (or, the soap)
-mouse:usb:v046dp4027:name:Logitech T620:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4027:
+mouse:usb:v046dp4027:name:Logitech T620:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4027:*
MOUSE_DPI=1200@250
# Logitech ZoneTouch Mouse T400
-mouse:usb:v046dp4026:name:Logitech T400:
-mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4026:
+mouse:usb:v046dp4026:name:Logitech T400:*
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4026:*
MOUSE_DPI=1300@166
# Logitech TrackMan Wheel (USB)
-mouse:usb:v046dpc404:name:Logitech Trackball:
+mouse:usb:v046dpc404:name:Logitech Trackball:*
MOUSE_DPI=300@125
# Logitech Ultrathin Touch Mouse
-mouse:bluetooth:v046dpb00d:name:Ultrathin Touch Mouse:
+mouse:bluetooth:v046dpb00d:name:Ultrathin Touch Mouse:*
MOUSE_DPI=1000@1000
# ImPS/2 Logitech Wheel Mouse
-mouse:ps2:*:name:ImPS/2 Logitech Wheel Mouse:
+mouse:ps2:*:name:ImPS/2 Logitech Wheel Mouse:*
MOUSE_DPI=400@100
# ImExPS/2 Logitech Wheel Mouse
-mouse:ps2:*:name:ImExPS/2 Logitech Wheel Mouse:
+mouse:ps2:*:name:ImExPS/2 Logitech Wheel Mouse:*
MOUSE_DPI=400@250
##########################################
# Microsoft
##########################################
-mouse:usb:v045ep0040:name:Microsoft Microsoft 3-Button Mouse with IntelliEye(TM):
+mouse:usb:v045ep0040:name:Microsoft Microsoft 3-Button Mouse with IntelliEye(TM):*
MOUSE_DPI=400@125
# Note: unsure that these work, it's likely that all devices on these
# receivers show up with the same vid/pid/name
# Microsoft Wireless Mouse 5000
-mouse:usb:v045ep0745:name:Microsoft Microsoft® 2.4GHz Transceiver v6.0:
+mouse:usb:v045ep0745:name:Microsoft Microsoft® 2.4GHz Transceiver v6.0:*
MOUSE_DPI=800@142
# Microsoft Comfort Mouse 4500
-mouse:usb:v045ep076c:name:Microsoft Microsoft® Comfort Mouse 4500:
+mouse:usb:v045ep076c:name:Microsoft Microsoft® Comfort Mouse 4500:*
MOUSE_DPI=1000@125
# Microsoft Wireless Mobile Mouse 4000
-mouse:usb:v045ep0745:name:Microsoft Microsoft® Nano Transceiver v2.0:
+mouse:usb:v045ep0745:name:Microsoft Microsoft® Nano Transceiver v2.0:*
MOUSE_DPI=1000@142
# Microsoft Sculpt Ergonomic Mouse
-mouse:usb:v045ep07a5:name:Microsoft Microsoft® 2.4GHz Transceiver v9.0:
+mouse:usb:v045ep07a5:name:Microsoft Microsoft® 2.4GHz Transceiver v9.0:*
MOUSE_DPI=1000@142
# Microsoft Arc Touch Mouse USB
-mouse:usb:v045ep07b1:name:Microsoft Microsoft® Nano Transceiver v1.0:
+mouse:usb:v045ep07b1:name:Microsoft Microsoft® Nano Transceiver v1.0:*
MOUSE_DPI=1400@142
# Microsoft Wireless Laser Mouse 8000
-mouse:bluetooth:v045ep0702:name:Microsoft Wireless Laser Mouse 8000:
+mouse:bluetooth:v045ep0702:name:Microsoft Wireless Laser Mouse 8000:*
MOUSE_DPI=1000@1000
# Microsoft Sculpt Comfort Mouse
-mouse:bluetooth:v045ep07a2:name:Microsoft Sculpt Comfort Mouse:
+mouse:bluetooth:v045ep07a2:name:Microsoft Sculpt Comfort Mouse:*
MOUSE_DPI=1000@2000
# Microsoft Arc Touch Mouse SE:
-mouse:bluetooth:v045ep07f3:name:Arc Touch Mouse SE:
+mouse:bluetooth:v045ep07f3:name:Arc Touch Mouse SE:*
MOUSE_DPI=1000@2000
# Microsoft Surface Mouse
-mouse:bluetooth:v0000p0000:name:Surface Mouse:
+mouse:bluetooth:v0000p0000:name:Surface Mouse:*
MOUSE_DPI=2000@2000
# Microsoft Classic IntelliMouse
-mouse:usb:v045ep0823:name:Microsoft Microsoft?? Classic IntelliMouse??:
+mouse:usb:v045ep0823:name:Microsoft Microsoft?? Classic IntelliMouse??:*
MOUSE_DPI=3200@1000
##########################################
##########################################
#Mionix Avior 7000
-mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000:
+mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000:*
MOUSE_DPI=400@1000 *1600@1000 7000@1000
MOUSE_WHEEL_CLICK_ANGLE=15
##########################################
# MODECOM MC-WM4 Wireless Optical Mouse
-mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:
+mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
MOUSE_DPI=*800@126 1600@126
##########################################
##########################################
# Oklick 406S Bluetooth Laser Mouse
-mouse:bluetooth:v056ep0061:name:Laser BTmouse:
+mouse:bluetooth:v056ep0061:name:Laser BTmouse:*
MOUSE_DPI=*800@333 1600@333
##########################################
##########################################
# P-Active Wireless Mouse PA-27K2
-mouse:usb:v0425p0101:name:G-Tech CHINA USB Wireless Mouse & KeyBoard V1.01 :
+mouse:usb:v0425p0101:name:G-Tech CHINA USB Wireless Mouse & KeyBoard V1.01 :*
MOUSE_DPI=800@125
##########################################
##########################################
# Razer Abyssus
-mouse:usb:v1532p0042:name:Razer Razer Abyssus:
+mouse:usb:v1532p0042:name:Razer Razer Abyssus:*
MOUSE_DPI=1600@1000
# Razer DeathAdder Black Edition
-mouse:usb:v1532p0029:name:Razer Razer DeathAdder:
+mouse:usb:v1532p0029:name:Razer Razer DeathAdder:*
MOUSE_DPI=3500@1000
##########################################
##########################################
# Roccat Lua (ROC-11-310)
-mouse:usb:v1e7dp2c2e:name:ROCCAT ROCCAT Lua:
+mouse:usb:v1e7dp2c2e:name:ROCCAT ROCCAT Lua:*
MOUSE_DPI=250@125 500@125 1000@125 1250@125 1500@125 1750@125 2000@125 250@250 500@250 1000@250 1250@250 1500@250 1750@250 2000@250 250@500 500@500 1000@500 1250@500 1500@500 1750@500 2000@500 250@1000 500@1000 *1000@1000 1250@1000 1500@1000 1750@1000 2000@1000
MOUSE_WHEEL_CLICK_ANGLE=15
##########################################
# Sharkoon Shark Force Gaming Mouse
-mouse:usb:v093ap2521:name:USB OPTICAL MOUSE:
+mouse:usb:v093ap2521:name:USB OPTICAL MOUSE:*
MOUSE_DPI=*1000@125 1600@125 600@125
##########################################
##########################################
# SteelSeries Sensei Raw
-mouse:usb:v1038p1369:name:SteelSeries Sensei Raw Gaming Mouse:
+mouse:usb:v1038p1369:name:SteelSeries Sensei Raw Gaming Mouse:*
MOUSE_DPI=1000@1022
##########################################
##########################################
# Trust illuminated mouse gxt 152
-mouse:usb:v145fp01ac:name:HID-compliant Mouse Trust Gaming Mouse:
+mouse:usb:v145fp01ac:name:HID-compliant Mouse Trust Gaming Mouse:*
MOUSE_DPI=*800@528 1200@537 1600@536 2400@521
##########################################
MOUSE_WHEEL_CLICK_ANGLE=23
# Zowie ZA12
-mouse:usb:v1af3p0001:name:Kingsis Peripherals ZOWIE Gaming mouse:
+mouse:usb:v1af3p0001:name:Kingsis Peripherals ZOWIE Gaming mouse:*
MOUSE_DPI=400@125 *800@125 1600@125 3200@125 400@500 800@500 1600@500 3200@500 400@1000 800@1000 1600@1000 3200@1000
MOUSE_WHEEL_CLICK_COUNT=16
MOUSE_WHEEL_CLICK_ANGLE=23
#
# Supported hardware matches are:
# - Generic input devices match:
-# evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV
+# evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV:*
# This matches on the kernel modalias of the input-device, mainly:
# ZZZZ is the bus-id (see /usr/include/linux/input.h BUS_*), YYYY, XXXX and
# WWW are the 4-digit hex uppercase vendor, product and version ID and VVVV
# in /sys/class/input/eventX/device/id.
#
# - Input driver device name and DMI data match:
-# evdev:name:<input device name>:dmi:bvn*:bvr*:bd*:svn<vendor>:pn*
+# evdev:name:<input device name>:dmi:bvn*:bvr*:bd*:svn<vendor>:pn*:*
# <input device name> is the name device specified by the driver,
# <vendor> is the firmware-provided string from the kernel DMI modalias,
# see /sys/class/dmi/id/modalias
#
+# All matches should end in ':*' to allow future expansions of the match key.
+#
# To add local entries, create a new file
# /etc/udev/hwdb.d/71-pointingstick-local.hwdb
# and add your rules there. To load the new rules execute (as root):
# drivers/input/mouse/trackpoint.c in the Linux kernel sources.
#
-#
# Sort by brand, model
#########################################
#########################################
# Latitude D620
-evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:pvr*
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:*
POINTINGSTICK_CONST_ACCEL=0.5
# Latitude E5570
-evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE5570*:pvr*
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE5570*:*
POINTINGSTICK_CONST_ACCEL=0.1
# Latitude E6320
-evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr*
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:*
POINTINGSTICK_CONST_ACCEL=2.0
# Latitude E6400
-evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr*
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:*
POINTINGSTICK_CONST_ACCEL=1.5
# Latitude E7470
-evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:pvr*
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:*
POINTINGSTICK_CONST_ACCEL=0.6
#########################################
POINTINGSTICK_CONST_ACCEL=1.25
# Lenovo UltraNav SK-8845 (USB keyboard)
-evdev:input:b0003v06CBp0009*
+evdev:input:b0003v06CBp0009:*
POINTINGSTICK_CONST_ACCEL=2.5
POINTINGSTICK_SENSITIVITY=200
#
# vid/pid as 4-digit hex lowercase vendor/product
#
+# All matches should end in ':*' to allow future expansions of the match key.
+#
# To add local entries, create a new file
# /etc/udev/hwdb.d/71-touchpad-local.hwdb
# and add your rules there. To load the new rules execute (as root):
###########################################################
# Logitech
###########################################################
-touchpad:usb:v046d*
+touchpad:usb:v046dp????:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Wacom
###########################################################
-touchpad:usb:v056a*
+touchpad:usb:v056ap????:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
<tr class="odd"><td>Teracue AG</td><td>TCAG</td><td>12/07/2012</td> </tr>
<tr class="even"><td>Texas Instruments</td><td>TXNW</td><td>01/01/2010</td> </tr>
<tr class="odd"><td>The Linux Foundation</td><td>LNUX</td><td>04/04/2014</td> </tr>
- <tr class="even"><td>Toshiba Corporation</td><td>TOSB</td><td>07/07/2015</td> </tr>
+ <tr class="even"><td>Dynabook Inc.</td><td>TOSB</td><td>07/07/2015</td> </tr>
<tr class="odd"><td>VAIO Corporation</td><td>VAIO</td><td>04/18/2014</td> </tr>
<tr class="even"><td>Validity Sensors, Inc</td><td>VFSI</td><td>06/17/2013</td> </tr>
<tr class="odd"><td>Wacom</td><td>WCOM</td><td>11/17/2011</td> </tr>
<tr class="even"><td>Fujitsu Limited</td><td>FUJI</td><td>06/18/2019</td> </tr>
<tr class="odd"><td>Phytium Technology Co. Ltd.</td><td>PHYT</td><td>02/14/2020</td> </tr>
<tr class="even"><td>CHENGDU HAIGUANG IC DESIGN CO., LTD</td><td>HYGO</td><td>07/15/2020</td> </tr>
+ <tr class="odd"><td>PixArt imaging inc.</td><td>PIXA</td><td>07/15/2020</td> </tr>
+ <tr class="even"><td>Loongson Technology Corporation Limited</td><td>LOON</td><td>09/10/2020</td> </tr>
</tbody>
</table>
</body>
Bayan Lepas Penang 11900\r
MY\r
\r
-A4-68-BC (hex) Private\r
-A468BC (base 16) Private\r
-\r
00-50-79 (hex) Private\r
005079 (base 16) Private\r
\r
Hong Kong Hong Kong 999077\r
HK\r
\r
-74-95-EC (hex) ALPS ELECTRIC CO., LTD.\r
-7495EC (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
AC-5A-EE (hex) China Mobile Group Device Co.,Ltd.\r
AC5AEE (base 16) China Mobile Group Device Co.,Ltd.\r
32 Xuanwumen West Street,Xicheng District\r
Shanghai 200040\r
CN\r
\r
-00-06-F7 (hex) ALPS ELECTRIC CO., LTD.\r
-0006F7 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
-00-07-04 (hex) ALPS ELECTRIC CO., LTD.\r
-000704 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
-00-06-F5 (hex) ALPS ELECTRIC CO., LTD.\r
-0006F5 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
-34-C7-31 (hex) ALPS ELECTRIC CO., LTD.\r
-34C731 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
9C-69-B4 (hex) IEEE Registration Authority\r
9C69B4 (base 16) IEEE Registration Authority\r
445 Hoes Lane\r
Concord Ontario L4K 5C7\r
CA\r
\r
-64-D4-BD (hex) ALPS ELECTRIC CO., LTD.\r
-64D4BD (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- KAKUDA-CITY MIYAGI-PREF 981-1595\r
- JP\r
-\r
-04-98-F3 (hex) ALPS ELECTRIC CO., LTD.\r
-0498F3 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1 NISHIDA\r
- KAKUDA MIYAGI PREF 9876-8501\r
- JP\r
-\r
-00-21-4F (hex) ALPS ELECTRIC CO., LTD.\r
-00214F (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
44-B4-33 (hex) tide.co.,ltd\r
44B433 (base 16) tide.co.,ltd\r
9F Kapeul GreatValley A-dong, Digitalro 9-ghil 32, Geumcheon-gu\r
shenzhen guangdong 518000\r
CN\r
\r
-94-7B-BE (hex) Ubicquia\r
-947BBE (base 16) Ubicquia\r
- 3281 Fairlane Farms Rd\r
- Wellington FL 33449\r
- US\r
-\r
EC-C0-6A (hex) PowerChord Group Limited\r
ECC06A (base 16) PowerChord Group Limited\r
1 Blythe Road\r
Tenei-village.Iwase-country Fukushima-prefecture 962-0512\r
JP\r
\r
-88-DA-1A (hex) Redpine Signals, Inc.\r
-88DA1A (base 16) Redpine Signals, Inc.\r
- 2107, N. First St\r
- San Jose CA 95131-2019\r
- US\r
-\r
98-EF-9B (hex) OHSUNG\r
98EF9B (base 16) OHSUNG\r
335-4,SANHODAERO,GUMI,GYEONG BUK,KOREA\r
Seocho-gu, Seoul 137-130\r
KR\r
\r
-00-26-4E (hex) Rail & Road Protec GmbH\r
-00264E (base 16) Rail & Road Protec GmbH\r
- Norderhofenden 12-13\r
- Flensburg 24937\r
- DE\r
-\r
00-26-4F (hex) Krüger &Gothe GmbH\r
00264F (base 16) Krüger &Gothe GmbH\r
Atzendorfer Straße 19\r
CHIMNEY ROCK CO 81127\r
US\r
\r
-00-60-65 (hex) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH\r
-006065 (base 16) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH\r
- EGGELSBERG 120\r
- 5142 EGGELSBERG \r
- AT\r
-\r
00-60-5D (hex) SCANIVALVE CORP.\r
00605D (base 16) SCANIVALVE CORP.\r
1722 N. MADSON STREET\r
Cupertino CA 95014\r
US\r
\r
-BC-42-8C (hex) ALPS ELECTRIC CO., LTD.\r
-BC428C (base 16) ALPS ELECTRIC CO., LTD.\r
- nishida 6-1 \r
- Kakuda-City Miyagi-Pref 981-1595\r
- JP\r
-\r
F0-7C-C7 (hex) Juniper Networks\r
F07CC7 (base 16) Juniper Networks\r
1133 Innovation Way\r
Farmington Hills MI 48335\r
US\r
\r
-BC-0F-9A (hex) D-Link International\r
-BC0F9A (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
30-B2-37 (hex) GD Midea Air-Conditioning Equipment Co.,Ltd.\r
30B237 (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd.\r
Midea Global Innovation Center,Beijiao Town,Shunde\r
Dongguan Guangdong 523808\r
CN\r
\r
+04-05-DD (hex) Shenzhen Cultraview Digital Technology Co., Ltd\r
+0405DD (base 16) Shenzhen Cultraview Digital Technology Co., Ltd\r
+ F6,M6,Maqueling, High-tech park, Nanshan district\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+38-97-A4 (hex) ELECOM CO.,LTD.\r
+3897A4 (base 16) ELECOM CO.,LTD.\r
+ 2F Kudan First Place Bldg. 4-1-28\r
+ Chiyoda-ku Kudan Kita 102-0073\r
+ JP\r
+\r
+E4-33-AE (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+E433AE (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+DC-E9-94 (hex) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+DCE994 (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
+38-7A-3C (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+387A3C (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+8C-CE-4E (hex) Espressif Inc.\r
+8CCE4E (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+B8-2D-28 (hex) AMPAK Technology,Inc.\r
+B82D28 (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
+C4-41-37 (hex) Quectel Wireless Solutions Co., Ltd.\r
+C44137 (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
+EC-C8-9C (hex) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+ECC89C (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd.\r
+ No.555 Qianmo Road\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+F0-13-C1 (hex) Hannto Technology Co., Ltd\r
+F013C1 (base 16) Hannto Technology Co., Ltd\r
+ Rm 704,No.1,Lane 88,Shengrong Road, Free Trade Pilot Area,\r
+ Shanghai Shanghai 200120\r
+ CN\r
+\r
+F8-0D-AC (hex) HP Inc.\r
+F80DAC (base 16) HP Inc.\r
+ 10300 Energy Dr\r
+ Spring TX 77389\r
+ US\r
+\r
+88-DA-1A (hex) Redpine Signals, Inc.\r
+88DA1A (base 16) Redpine Signals, Inc.\r
+ Plot 87, Sagar Society \r
+ Hyderabad AP 500034\r
+ IN\r
+\r
+40-B5-C1 (hex) Cisco Systems, Inc\r
+40B5C1 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+E4-47-91 (hex) Iris ID Systems, Inc.\r
+E44791 (base 16) Iris ID Systems, Inc.\r
+ 8 Clarke Drive\r
+ Cranbury 08512\r
+ US\r
+\r
+00-60-65 (hex) B&R Industrial Automation GmbH \r
+006065 (base 16) B&R Industrial Automation GmbH \r
+ B&R Straße 1\r
+ Eggelsberg 5142\r
+ AT\r
+\r
+84-9D-C2 (hex) Shanghai MXCHIP Information Technology Co., Ltd.\r
+849DC2 (base 16) Shanghai MXCHIP Information Technology Co., Ltd.\r
+ 9th Floor, No. 5 Building, 2145 Jinshajiang Rd., Putuo District\r
+ Shanghai 200333\r
+ CN\r
+\r
+18-45-16 (hex) Texas Instruments\r
+184516 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+D0-2E-AB (hex) Texas Instruments\r
+D02EAB (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+84-54-DF (hex) Huawei Device Co., Ltd.\r
+8454DF (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+F0-F7-E7 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F0F7E7 (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-84-A5 (hex) Intel Corporate\r
+E884A5 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+8C-55-BB (hex) Songwoo Information & Technology Co., Ltd\r
+8C55BB (base 16) Songwoo Information & Technology Co., Ltd\r
+ 24-9, Jinju-daero 404beon-gil, Jinju-si, Gyeongsangnam-do, Korea \r
+ Jinju Gyeongsangnam-do 52826\r
+ KR\r
+\r
+7C-8F-DE (hex) DWnet Technologies(Suzhou) Corporation\r
+7C8FDE (base 16) DWnet Technologies(Suzhou) Corporation\r
+ No.8,Tangzhuang Road, Suzhou Industrial Park, Jiangsu, China\r
+ Suzhou 21500\r
+ CN\r
+\r
+98-F1-81 (hex) New H3C Technologies Co., Ltd\r
+98F181 (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+90-80-8F (hex) Huawei Device Co., Ltd.\r
+90808F (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+40-A9-CF (hex) Amazon Technologies Inc.\r
+40A9CF (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+58-95-D8 (hex) IEEE Registration Authority\r
+5895D8 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+08-38-E6 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.\r
+0838E6 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.\r
+ No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan\r
+ Wuhan Hubei 430000\r
+ CN\r
+\r
+E8-C2-DD (hex) Infinix mobility limited\r
+E8C2DD (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
+48-D8-90 (hex) FN-LINK TECHNOLOGY LIMITED\r
+48D890 (base 16) FN-LINK TECHNOLOGY LIMITED\r
+ A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District\r
+ SHENZHEN GUANGDONG 518100\r
+ CN\r
+\r
+78-1F-11 (hex) RAB Lighting\r
+781F11 (base 16) RAB Lighting\r
+ Northvale (NJ) 141 Legrand Ave. Northvale, NJ 07647\r
+ Northvale NJ 07647\r
+ US\r
+\r
+F8-B9-5A (hex) LG Innotek\r
+F8B95A (base 16) LG Innotek\r
+ 26, Hanamsandan 5beon-ro\r
+ Gwangju Gwangsan-gu 506-731\r
+ KR\r
+\r
+C4-1C-9C (hex) JiQiDao\r
+C41C9C (base 16) JiQiDao\r
+ No.19, SuYuan Avenue, Jiangning District\r
+ NanJing Jiangsu 210000\r
+ CN\r
+\r
+D4-4F-67 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+D44F67 (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-FF-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B4FF98 (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
+84-71-27 (hex) Silicon Laboratories\r
+847127 (base 16) Silicon Laboratories\r
+ 400 West Cesar Chavez Street\r
+ Austin TX 78701\r
+ US\r
+\r
+00-26-4E (hex) r2p GmbH\r
+00264E (base 16) r2p GmbH\r
+ Norderhofenden 12-13\r
+ Flensburg 24937\r
+ DE\r
+\r
+B0-BB-E5 (hex) Sagemcom Broadband SAS\r
+B0BBE5 (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+90-B4-DD (hex) Private\r
+90B4DD (base 16) Private\r
+\r
+C4-18-E9 (hex) Samsung Electronics Co.,Ltd\r
+C418E9 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+1C-E5-7F (hex) Samsung Electronics Co.,Ltd\r
+1CE57F (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+B0-C5-3C (hex) Cisco Systems, Inc\r
+B0C53C (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+EC-CE-13 (hex) Cisco Systems, Inc\r
+ECCE13 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+10-71-00 (hex) Huawei Device Co., Ltd.\r
+107100 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+8C-FD-DE (hex) Sagemcom Broadband SAS\r
+8CFDDE (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+A4-68-BC (hex) Oakley Inc.\r
+A468BC (base 16) Oakley Inc.\r
+ 1 Icon\r
+ Foothill Ranch CA 92610\r
+ US\r
+\r
+60-7E-A4 (hex) Shanghai Imilab Technology Co.Ltd\r
+607EA4 (base 16) Shanghai Imilab Technology Co.Ltd\r
+ 29F, A Tower, New Caohejing International Business Center, Guiping Road, Xuhui District\r
+ Shanghai Shanghai 200000\r
+ CN\r
+\r
+24-11-45 (hex) Xiaomi Communications Co Ltd\r
+241145 (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
+78-95-EB (hex) ITEL MOBILE LIMITED\r
+7895EB (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-9F-4E (hex) COOSEA GROUP (HK) COMPANY LIMITED\r
+1C9F4E (base 16) COOSEA GROUP (HK) COMPANY LIMITED\r
+ UNIT 5-6 16/F MULTIFIELD PLAZA 3-7A PRAT AVENUE TSIMSHATSUI\r
+ KL 999077\r
+ HK\r
+\r
+14-AB-02 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+14AB02 (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
+BC-5B-D5 (hex) ARRIS Group, Inc.\r
+BC5BD5 (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+08-55-31 (hex) Routerboard.com\r
+085531 (base 16) Routerboard.com\r
+ Mikrotikls SIA\r
+ Riga Riga LV1009\r
+ LV\r
+\r
+3C-61-05 (hex) Espressif Inc.\r
+3C6105 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+24-06-AA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+2406AA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+84-30-95 (hex) Hon Hai Precision IND.CO.,LTD\r
+843095 (base 16) Hon Hai Precision IND.CO.,LTD\r
+ No. 66 Chung Shan Road TU-Cheng Industrial district TAIPEI TAIWAN \r
+ TAIPEI TAIWAN 33859\r
+ CN\r
+\r
+08-65-F0 (hex) JM Zengge Co., Ltd\r
+0865F0 (base 16) JM Zengge Co., Ltd\r
+ 5/F Torch building, Jinou Road#288, Jianghai District\r
+ Jiangmen Guangdong 529080\r
+ CN\r
+\r
+AC-47-1B (hex) Huawei Device Co., Ltd.\r
+AC471B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+00-31-92 (hex) TP-Link Corporation Limited\r
+003192 (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
+A4-CC-B9 (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+A4CCB9 (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
+90-FF-D6 (hex) Honor Device Co., Ltd.\r
+90FFD6 (base 16) Honor Device Co., Ltd.\r
+ A1701, Block AB, Building 1, Tianan Yungu Phase I, Gangtou Community, Bantian Street\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+6C-B8-81 (hex) zte corporation\r
+6CB881 (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
+98-9A-B9 (hex) zte corporation\r
+989AB9 (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
+00-8A-55 (hex) Huawei Device Co., Ltd.\r
+008A55 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+64-A2-8A (hex) Huawei Device Co., Ltd.\r
+64A28A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+B4-56-E3 (hex) Apple, Inc.\r
+B456E3 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+4C-20-B8 (hex) Apple, Inc.\r
+4C20B8 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+14-88-E6 (hex) Apple, Inc.\r
+1488E6 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+EC-0D-E4 (hex) Amazon Technologies Inc.\r
+EC0DE4 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+BC-0F-9A (hex) D-Link International\r
+BC0F9A (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+B0-45-30 (hex) BSkyB Ltd\r
+B04530 (base 16) BSkyB Ltd\r
+ 130 Kings Road\r
+ Brentwood Essex 08854\r
+ GB\r
+\r
+6C-A0-B4 (hex) BSkyB Ltd\r
+6CA0B4 (base 16) BSkyB Ltd\r
+ 130 Kings Road\r
+ Brentwood Essex 08854\r
+ GB\r
+\r
+94-7B-BE (hex) Ubicquia LLC\r
+947BBE (base 16) Ubicquia LLC\r
+ BoA Building–Suite 1750, 401 E. Las Olas Boulevard\r
+ Fort Lauderdale FL 33301\r
+ US\r
+\r
+24-64-9F (hex) Huawei Device Co., Ltd.\r
+24649F (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+0C-17-73 (hex) Huawei Device Co., Ltd.\r
+0C1773 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E8-1E-92 (hex) Huawei Device Co., Ltd.\r
+E81E92 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+88-8E-68 (hex) Huawei Device Co., Ltd.\r
+888E68 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+80-74-84 (hex) ALL Winner (Hong Kong) Limited\r
+807484 (base 16) ALL Winner (Hong Kong) Limited\r
+ Unit No.1301,13F,Sunbeam Plaza,1155 Canton Road,Mongkok,Kowloon,Hong Kong\r
+ Hong Kong 999077\r
+ CN\r
+\r
+8C-AE-49 (hex) IEEE Registration Authority\r
+8CAE49 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+74-95-EC (hex) ALPSALPINE CO,.LTD\r
+7495EC (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-21-4F (hex) ALPSALPINE CO,.LTD\r
+00214F (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+04-98-F3 (hex) ALPSALPINE CO,.LTD\r
+0498F3 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1 NISHIDA\r
+ KAKUDA MIYAGI PREF 9876-8501\r
+ JP\r
+\r
+64-D4-BD (hex) ALPSALPINE CO,.LTD\r
+64D4BD (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ KAKUDA-CITY MIYAGI-PREF 981-1595\r
+ JP\r
+\r
+34-C7-31 (hex) ALPSALPINE CO,.LTD\r
+34C731 (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
+00-06-F5 (hex) ALPSALPINE CO,.LTD\r
+0006F5 (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
+00-07-04 (hex) ALPSALPINE CO,.LTD\r
+000704 (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
+00-06-F7 (hex) ALPSALPINE CO,.LTD\r
+0006F7 (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
+BC-42-8C (hex) ALPSALPINE CO,.LTD\r
+BC428C (base 16) ALPSALPINE CO,.LTD\r
+ nishida 6-1 \r
+ Kakuda-City Miyagi-Pref 981-1595\r
+ JP\r
+\r
9C-FF-C2 (hex) AVI Systems GmbH\r
9CFFC2 (base 16) AVI Systems GmbH\r
Dr. Franz Wilhelmstraße 2A\r
Bayan Lepas Penang 11900\r
MY\r
\r
-04-76-6E (hex) ALPS ELECTRIC CO., LTD.\r
-04766E (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
-AC-7A-4D (hex) ALPS ELECTRIC CO., LTD.\r
-AC7A4D (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- KAKUDA-CITY MIYAGI-PREF 981-1595\r
- JP\r
-\r
00-1B-B5 (hex) Cherry GmbH\r
001BB5 (base 16) Cherry GmbH\r
Cherrystraße 1\r
Auerbach i. d. Opf. Bayern D-91275\r
DE\r
\r
-00-26-43 (hex) ALPS ELECTRIC CO., LTD.\r
-002643 (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-38-C0-96 (hex) ALPS ELECTRIC CO., LTD.\r
-38C096 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- KAKUDA-CITY MIYAGI-PREF 981-1595\r
- JP\r
-\r
D0-51-57 (hex) LEAX Arkivator Telecom\r
D05157 (base 16) LEAX Arkivator Telecom\r
NanShan District YueHaiMen Street\r
DONG GUAN GUANG DONG 523860\r
CN\r
\r
-78-32-1B (hex) D-Link International\r
-78321B (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
60-18-03 (hex) Daikin Air-conditioning (Shanghai) Co., Ltd.\r
601803 (base 16) Daikin Air-conditioning (Shanghai) Co., Ltd.\r
318 Shen Fu Road, Xin Zhuang Industry Zone, Shanghai, 201108, China\r
Seoul 140-847\r
KR\r
\r
-00-1B-2E (hex) Sinkyo Electron Inc\r
-001B2E (base 16) Sinkyo Electron Inc\r
- 3-3-21 asahigaoka\r
- hino-city Tokyo 191-0065\r
- JP\r
-\r
00-1B-5F (hex) Alien Technology\r
001B5F (base 16) Alien Technology\r
18220 Butterfield Blvd.\r
Sunnyvale CA 94089\r
US\r
\r
-30-B2-16 (hex) ABB Power Grids Germany AG – Grid Automation\r
-30B216 (base 16) ABB Power Grids Germany AG – Grid Automation\r
- Kallstadter Strasse 1\r
- Mannheim 68309\r
- DE\r
-\r
00-09-91 (hex) Intelligent Platforms, LLC.\r
000991 (base 16) Intelligent Platforms, LLC.\r
2500 Austin Drive\r
Dongguan Guangdong 523808\r
CN\r
\r
-5C-34-00 (hex) HISENSE VISUAL TECHNOLOGY CO.,LTD\r
-5C3400 (base 16) HISENSE VISUAL TECHNOLOGY CO.,LTD\r
- Qianwangang Road 218\r
- Qingdao Shandong 266510\r
- CN\r
-\r
78-45-58 (hex) Ubiquiti Networks Inc.\r
784558 (base 16) Ubiquiti Networks Inc.\r
685 Third Avenue, 27th Floor\r
New York NY 10017\r
US\r
\r
+64-F9-47 (hex) Senscomm Semiconductor Co., Ltd.\r
+64F947 (base 16) Senscomm Semiconductor Co., Ltd.\r
+ Room 303-309, 3rd Floor International Building, NO.2 Suzhou Avenue West\r
+ Suzhou Jiangsu 215000\r
+ CN\r
+\r
+DC-00-B0 (hex) FREEBOX SAS\r
+DC00B0 (base 16) FREEBOX SAS\r
+ 16 rue de la Ville l'Eveque\r
+ PARIS IdF 75008\r
+ FR\r
+\r
+70-74-14 (hex) Murata Manufacturing Co., Ltd.\r
+707414 (base 16) Murata Manufacturing Co., Ltd.\r
+ 1-10-1, Higashikotari\r
+ Nagaokakyo-shi Kyoto 617-8555\r
+ JP\r
+\r
+A0-76-4E (hex) Espressif Inc.\r
+A0764E (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+B4-FB-E3 (hex) AltoBeam (China) Inc.\r
+B4FBE3 (base 16) AltoBeam (China) Inc.\r
+ B808, Tsinghua Tongfang Hi-Tech Plaza, Haidian\r
+ Beijing Beijing 100083\r
+ CN\r
+\r
+18-87-40 (hex) Xiaomi Communications Co Ltd\r
+188740 (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
+34-1C-F0 (hex) Xiaomi Communications Co Ltd\r
+341CF0 (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
+10-D7-B0 (hex) Sagemcom Broadband SAS\r
+10D7B0 (base 16) Sagemcom Broadband SAS\r
+ 250, route de l'Empereur\r
+ Rueil Malmaison Cedex hauts de seine 92848\r
+ FR\r
+\r
+44-59-43 (hex) zte corporation\r
+445943 (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
+34-36-54 (hex) zte corporation\r
+343654 (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
74-8F-3C (hex) Apple, Inc.\r
748F3C (base 16) Apple, Inc.\r
1 Infinite Loop\r
Cupertino CA 95014\r
US\r
\r
-44-59-43 (hex) zte corporation\r
-445943 (base 16) zte corporation\r
- 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
- shenzhen guangdong 518057\r
+6C-09-BF (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+6C09BF (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
CN\r
\r
-34-36-54 (hex) zte corporation\r
-343654 (base 16) zte corporation\r
- 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
- shenzhen guangdong 518057\r
+30-AF-CE (hex) vivo Mobile Communication Co., Ltd.\r
+30AFCE (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
CN\r
\r
-64-F9-47 (hex) Senscomm Semiconductor Co., Ltd.\r
-64F947 (base 16) Senscomm Semiconductor Co., Ltd.\r
- Room 303-309, 3rd Floor International Building, NO.2 Suzhou Avenue West\r
- Suzhou Jiangsu 215000\r
+FC-6D-D1 (hex) APRESIA Systems, Ltd.\r
+FC6DD1 (base 16) APRESIA Systems, Ltd.\r
+ Tsukuba Network Technical Center, Kidamari 3550\r
+ Tsuchiura-shi Ibaraki-ken 300-0026\r
+ JP\r
+\r
+80-C9-55 (hex) Redpine Signals, Inc.\r
+80C955 (base 16) Redpine Signals, Inc.\r
+ Plot 87, Sagar Society \r
+ Hyderabad AP 500034\r
+ IN\r
+\r
+CC-4F-5C (hex) IEEE Registration Authority\r
+CC4F5C (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+30-B2-16 (hex) Hitachi ABB Power Grids – Grid Automation\r
+30B216 (base 16) Hitachi ABB Power Grids – Grid Automation\r
+ Kallstadter Strasse 1\r
+ Mannheim 68309\r
+ DE\r
+\r
+4C-6D-58 (hex) Juniper Networks\r
+4C6D58 (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+5C-ED-8C (hex) Hewlett Packard Enterprise\r
+5CED8C (base 16) Hewlett Packard Enterprise\r
+ 8000 Foothills Blvd.\r
+ Roseville CA 95747\r
+ US\r
+\r
+30-D0-42 (hex) Dell Inc.\r
+30D042 (base 16) Dell Inc.\r
+ One Dell Way\r
+ Round Rock TX 78682\r
+ US\r
+\r
+C0-C9-E3 (hex) TP-LINK TECHNOLOGIES CO.,LTD.\r
+C0C9E3 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.\r
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan\r
+ Shenzhen Guangdong 518057\r
CN\r
\r
-DC-00-B0 (hex) FREEBOX SAS\r
-DC00B0 (base 16) FREEBOX SAS\r
- 16 rue de la Ville l'Eveque\r
- PARIS IdF 75008\r
+F8-8C-21 (hex) TP-LINK TECHNOLOGIES CO.,LTD.\r
+F88C21 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.\r
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+C4-27-8C (hex) Huawei Device Co., Ltd.\r
+C4278C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+80-8F-E8 (hex) Intelbras\r
+808FE8 (base 16) Intelbras\r
+ BR 101, km 210, S/N°\r
+ São José Santa Catarina 88104800\r
+ BR\r
+\r
+18-CC-18 (hex) Intel Corporate\r
+18CC18 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+7C-73-EB (hex) Huawei Device Co., Ltd.\r
+7C73EB (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E4-8F-1D (hex) Huawei Device Co., Ltd.\r
+E48F1D (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-E3-42 (hex) Tuya?HK?Limietd\r
+84E342 (base 16) Tuya?HK?Limietd\r
+ FLAT/RM 806 BLK ? 8/F CHEUNG SHA WAN PLAZA 833 CHEUNG SHA WAN ROAD KL\r
+ hongkong Hong Kong 999077\r
+ CN\r
+\r
+C0-3C-59 (hex) Intel Corporate\r
+C03C59 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+FC-CD-2F (hex) IEEE Registration Authority\r
+FCCD2F (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+94-B2-71 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+94B271 (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-05-8C (hex) mMax Communications, Inc.\r
+78058C (base 16) mMax Communications, Inc.\r
+ 5151 California Ave., Suite 100\r
+ Irvine CA 92617\r
+ US\r
+\r
+C4-A7-2B (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD\r
+C4A72B (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
+CC-F5-5F (hex) E FOCUS INSTRUMENTS INDIA PRIVATE LIMITED\r
+CCF55F (base 16) E FOCUS INSTRUMENTS INDIA PRIVATE LIMITED\r
+ PLOT NO 21, 1ST FLOOR, NO 22, SAMAYAPURAM MAIN ROAD PORUR\r
+ CHENNAI TAMIL NADU 600116\r
+ IN\r
+\r
+D0-C3-1E (hex) JUNGJIN Electronics Co.,Ltd\r
+D0C31E (base 16) JUNGJIN Electronics Co.,Ltd\r
+ 41-11, Yangjipyeon-ro\r
+ Uiwang-si Gyeonggi-do 16007\r
+ KR\r
+\r
+14-13-33 (hex) AzureWave Technology Inc.\r
+141333 (base 16) AzureWave Technology Inc.\r
+ 8F., No. 94, Baozhong Rd.\r
+ New Taipei City Taiwan 231\r
+ TW\r
+\r
+A4-17-8B (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A4178B (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-34-00 (hex) Hisense Electric Co.,Ltd\r
+5C3400 (base 16) Hisense Electric Co.,Ltd\r
+ Qianwangang Road 218\r
+ Qingdao Shandong 266510\r
+ CN\r
+\r
+4C-3B-DF (hex) Microsoft Corporation\r
+4C3BDF (base 16) Microsoft Corporation\r
+ One Microsoft Way\r
+ REDMOND WA 98052\r
+ US\r
+\r
+08-7C-39 (hex) Amazon Technologies Inc.\r
+087C39 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+D8-10-CB (hex) Andrea Informatique\r
+D810CB (base 16) Andrea Informatique\r
+ 30 Rue Jules Guesde\r
+ Paris 75014\r
FR\r
\r
-70-74-14 (hex) Murata Manufacturing Co., Ltd.\r
-707414 (base 16) Murata Manufacturing Co., Ltd.\r
- 1-10-1, Higashikotari\r
- Nagaokakyo-shi Kyoto 617-8555\r
+FC-19-28 (hex) Actions Microelectronics Co., Ltd\r
+FC1928 (base 16) Actions Microelectronics Co., Ltd\r
+ 201, No 9 Building, Software Park,Kejizhonger Rd.,\r
+ Shenzhen Gangdong 518057\r
+ CN\r
+\r
+3C-D2-E5 (hex) New H3C Technologies Co., Ltd\r
+3CD2E5 (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+B0-98-BC (hex) Huawei Device Co., Ltd.\r
+B098BC (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+24-01-6F (hex) Huawei Device Co., Ltd.\r
+24016F (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+D0-59-19 (hex) zte corporation\r
+D05919 (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
+E0-91-3C (hex) Kyeungin CNS Co., Ltd.\r
+E0913C (base 16) Kyeungin CNS Co., Ltd.\r
+ 13, Gyeongin-ro, Sosa-gu\r
+ Bucheon-si Gyeonggi-do 14730\r
+ KR\r
+\r
+00-B8-81 (hex) New platforms LLC\r
+00B881 (base 16) New platforms LLC\r
+ Varshavskoe shosse, 35, Bld. 1\r
+ Moscow 117105\r
+ RU\r
+\r
+00-1B-2E (hex) Sinkyo Electron Inc\r
+001B2E (base 16) Sinkyo Electron Inc\r
+ 1-22-19 Daimachi\r
+ Hachioji-city Tokyo 193-0931\r
JP\r
\r
-A0-76-4E (hex) Espressif Inc.\r
-A0764E (base 16) Espressif Inc.\r
+C4-37-72 (hex) Virtuozzo International GmbH\r
+C43772 (base 16) Virtuozzo International GmbH\r
+ Vordergasse 59\r
+ Schaffhausen 8200\r
+ CH\r
+\r
+CC-3B-27 (hex) TECNO MOBILE LIMITED\r
+CC3B27 (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
+08-58-A5 (hex) Beijing Vrv Software Corpoaration Limited.\r
+0858A5 (base 16) Beijing Vrv Software Corpoaration Limited.\r
+ Room 1602, block C, Zhongguancun Science and technology development building, 34 Zhongguancun South Street\r
+ Beijing Beijing 100000\r
+ CN\r
+\r
+98-3F-60 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+983F60 (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-3F-DD (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C03FDD (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
+30-32-35 (hex) Qingdao Intelligent&Precise Electronics Co.,Ltd.\r
+303235 (base 16) Qingdao Intelligent&Precise Electronics Co.,Ltd.\r
+ No.218 Qianwangang Road\r
+ Qingdao Shangdong 266510\r
+ CN\r
+\r
+E0-E2-E6 (hex) Espressif Inc.\r
+E0E2E6 (base 16) Espressif Inc.\r
Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
Shanghai Shanghai 201203\r
CN\r
\r
+9C-73-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+9C7370 (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
+58-24-29 (hex) Google, Inc.\r
+582429 (base 16) Google, Inc.\r
+ 1600 Amphitheatre Parkway\r
+ Mountain View CA 94043\r
+ US\r
+\r
+E8-0A-EC (hex) Jiangsu Hengtong Optic-Electric Co., LTD\r
+E80AEC (base 16) Jiangsu Hengtong Optic-Electric Co., LTD\r
+ 88 Hengtong Dadao, Qidu Town, Wujiang District\r
+ Suzhou Jiangsu Province 215200\r
+ CN\r
+\r
+C4-DE-7B (hex) Huawei Device Co., Ltd.\r
+C4DE7B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-1B-77 (hex) Intel Corporate\r
+841B77 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+7C-C2-94 (hex) Beijing Xiaomi Mobile Software Co., Ltd\r
+7CC294 (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
+40-D4-BD (hex) SK Networks Service CO., LTD.\r
+40D4BD (base 16) SK Networks Service CO., LTD.\r
+ 120, Jangan-ro, Jangan-gu\r
+ Suwon-si Gyeonggi-do 16312\r
+ KR\r
+\r
+68-D4-8B (hex) Hailo Technologies Ltd.\r
+68D48B (base 16) Hailo Technologies Ltd.\r
+ 94 Yigal Alon\r
+ Tel Aviv 6789139\r
+ IL\r
+\r
+6C-1A-75 (hex) Huawei Device Co., Ltd.\r
+6C1A75 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+6C-76-37 (hex) Huawei Device Co., Ltd.\r
+6C7637 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+18-EE-86 (hex) Novatel Wireless Solutions, Inc.\r
+18EE86 (base 16) Novatel Wireless Solutions, Inc.\r
+ 9710 Scranton Rd., Suite 200\r
+ San Diego CA 92121\r
+ US\r
+\r
+A0-9F-10 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD\r
+A09F10 (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
+20-1B-88 (hex) Dongguan Liesheng Electronic Co., Ltd.\r
+201B88 (base 16) Dongguan Liesheng Electronic Co., Ltd.\r
+ F5, Building B, North Block, Gaosheng Tech Park, No. 84 Zhongli Road, Nancheng District, Dongguan Ci\r
+ dongguan guangdong 523000\r
+ CN\r
+\r
+24-94-93 (hex) FibRSol Global Network Limited\r
+249493 (base 16) FibRSol Global Network Limited\r
+ 17, Deep vihar, Vikas Nagar,, Near Mayank hospital,, Uttam Nagar,\r
+ New Delhi Delhi 110059\r
+ IN\r
+\r
+28-D0-44 (hex) Shenzhen Xinyin technology company\r
+28D044 (base 16) Shenzhen Xinyin technology company\r
+ 2/F, Building C, Jianxing Technology Building, Shahe West Road, Xili Street, Nanshan District \r
+ Shenzhen Guangdong 518055\r
+ CN\r
+\r
+A8-40-7D (hex) GD Midea Air-Conditioning Equipment Co.,Ltd.\r
+A8407D (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
+FC-4B-57 (hex) Peerless Instrument Division of Curtiss-Wright \r
+FC4B57 (base 16) Peerless Instrument Division of Curtiss-Wright \r
+ 1966D Broadhollow Road\r
+ East Farmingdale NY 11735\r
+ US\r
+\r
+5C-10-C5 (hex) Samsung Electronics Co.,Ltd\r
+5C10C5 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+E8-EB-34 (hex) Cisco Systems, Inc\r
+E8EB34 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+58-60-D8 (hex) ARRIS Group, Inc.\r
+5860D8 (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+9C-9A-C0 (hex) LEGO System A/S\r
+9C9AC0 (base 16) LEGO System A/S\r
+ Aastvej 1\r
+ Billund DK-7190\r
+ DK\r
+\r
+3C-BD-C5 (hex) Arcadyan Corporation\r
+3CBDC5 (base 16) Arcadyan Corporation\r
+ No.8, Sec.2, Guangfu Rd.\r
+ Hsinchu City Hsinchu 30071\r
+ TW\r
+\r
+DC-8C-1B (hex) vivo Mobile Communication Co., Ltd.\r
+DC8C1B (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+A8-DA-0C (hex) SERVERCOM (INDIA) PRIVATE LIMITED\r
+A8DA0C (base 16) SERVERCOM (INDIA) PRIVATE LIMITED\r
+ E-43/1 OKHLA INDUSTRIAL AREA PHASE-II NEW DELHI SOUTH DELHI\r
+ NEW DELHI 110001\r
+ IN\r
+\r
+F8-53-29 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+F85329 (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
+50-A5-DC (hex) ARRIS Group, Inc.\r
+50A5DC (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+74-B7-B3 (hex) Shenzhen YOUHUA Technology Co., Ltd\r
+74B7B3 (base 16) Shenzhen YOUHUA Technology Co., Ltd\r
+ Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District\r
+ Shenzhen Guangdong 518055\r
+ CN\r
+\r
+88-15-C5 (hex) Huawei Device Co., Ltd.\r
+8815C5 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+B4-1B-B0 (hex) Apple, Inc.\r
+B41BB0 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+58-D3-49 (hex) Apple, Inc.\r
+58D349 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F4-34-F0 (hex) Apple, Inc.\r
+F434F0 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+B0-8C-75 (hex) Apple, Inc.\r
+B08C75 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+A4-AA-FE (hex) Huawei Device Co., Ltd.\r
+A4AAFE (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+F8-3B-7E (hex) Huawei Device Co., Ltd.\r
+F83B7E (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+9C-28-B3 (hex) Apple, Inc.\r
+9C28B3 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+A0-78-17 (hex) Apple, Inc.\r
+A07817 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+5C-87-30 (hex) Apple, Inc.\r
+5C8730 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+DC-9B-D6 (hex) TCT mobile ltd\r
+DC9BD6 (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
+74-EC-B2 (hex) Amazon Technologies Inc.\r
+74ECB2 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+70-40-FF (hex) Huawei Device Co., Ltd.\r
+7040FF (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+34-D6-93 (hex) Huawei Device Co., Ltd.\r
+34D693 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E0-1F-ED (hex) Nokia Shanghai Bell Co., Ltd.\r
+E01FED (base 16) Nokia Shanghai Bell Co., Ltd.\r
+ No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai \r
+ Shanghai 201206\r
+ CN\r
+\r
+14-6B-9A (hex) zte corporation\r
+146B9A (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-32-1B (hex) D-Link International\r
+78321B (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+04-E7-7E (hex) We Corporation Inc.\r
+04E77E (base 16) We Corporation Inc.\r
+ 201, 33, Deokcheon-ro, Manan-gu\r
+ Anyang-si Gyeonggi-do 14088\r
+ KR\r
+\r
+4C-52-EC (hex) SOLARWATT GmbH\r
+4C52EC (base 16) SOLARWATT GmbH\r
+ Maria-Reiche-Str. 2a\r
+ Dresden 01109\r
+ DE\r
+\r
+30-D9-41 (hex) Raydium Semiconductor Corp.\r
+30D941 (base 16) Raydium Semiconductor Corp.\r
+ 2F, No. 23, LiHsin Rd., Hsinchu Science Park\r
+ Hsinchu, Taiwan, R.O.C. TW 300\r
+ TW\r
+\r
+00-26-43 (hex) ALPSALPINE CO,.LTD\r
+002643 (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+38-C0-96 (hex) ALPSALPINE CO,.LTD\r
+38C096 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ KAKUDA-CITY MIYAGI-PREF 981-1595\r
+ JP\r
+\r
+AC-7A-4D (hex) ALPSALPINE CO,.LTD\r
+AC7A4D (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ KAKUDA-CITY MIYAGI-PREF 981-1595\r
+ JP\r
+\r
+04-76-6E (hex) ALPSALPINE CO,.LTD\r
+04766E (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
84-80-94 (hex) Meter, Inc.\r
848094 (base 16) Meter, Inc.\r
148 Townsend St\r
KYOTO KYOTO 601-8501\r
JP\r
\r
-F0-4F-7C (hex) Private\r
-F04F7C (base 16) Private\r
-\r
70-54-25 (hex) ARRIS Group, Inc.\r
705425 (base 16) ARRIS Group, Inc.\r
6450 Sequence Drive\r
Dongguan Guangdong 523808\r
CN\r
\r
-F0-A2-25 (hex) Private\r
-F0A225 (base 16) Private\r
-\r
50-A1-32 (hex) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
50A132 (base 16) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
Chudong science and technology park, 111 shaxin road, tangxia town,\r
Nagaokakyo-shi Kyoto 617-8555\r
JP\r
\r
-58-16-D7 (hex) ALPS ELECTRIC CO., LTD.\r
-5816D7 (base 16) ALPS ELECTRIC CO., LTD.\r
- nishida 6-1 \r
- Kakuda-City Miyagi-Pref 981-1595\r
- JP\r
-\r
FC-A4-7A (hex) IEEE Registration Authority\r
FCA47A (base 16) IEEE Registration Authority\r
445 Hoes Lane\r
Hangzhou Zhejiang 310053\r
CN\r
\r
-00-24-33 (hex) ALPS ELECTRIC CO., LTD.\r
-002433 (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-00-23-06 (hex) ALPS ELECTRIC CO., LTD.\r
-002306 (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-B4-EC-02 (hex) ALPS ELECTRIC CO., LTD.\r
-B4EC02 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
64-60-38 (hex) Hirschmann Automation and Control GmbH\r
646038 (base 16) Hirschmann Automation and Control GmbH\r
Stuttgarter Straße 45-51\r
Piscataway NJ 08554\r
US\r
\r
-E0-75-0A (hex) ALPS ELECTRIC CO., LTD.\r
-E0750A (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- kakuda-City 981-1595\r
- US\r
-\r
-00-19-C1 (hex) ALPS ELECTRIC CO., LTD.\r
-0019C1 (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-00-16-FE (hex) ALPS ELECTRIC CO., LTD.\r
-0016FE (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-9C-8D-7C (hex) ALPS ELECTRIC CO., LTD.\r
-9C8D7C (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
D4-25-CC (hex) IEEE Registration Authority\r
D425CC (base 16) IEEE Registration Authority\r
445 Hoes Lane\r
Walnut CA 91789\r
US\r
\r
-BC-75-36 (hex) ALPS ELECTRIC CO., LTD.\r
-BC7536 (base 16) ALPS ELECTRIC CO., LTD.\r
- nishida 6-1 \r
- Kakuda-City Miyagi-Pref 981-1595\r
- JP\r
-\r
-E0-AE-5E (hex) ALPS ELECTRIC CO., LTD.\r
-E0AE5E (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-3-36 Furukawanakazato,\r
- Osaki Miyagi-pref 989-6181\r
- JP\r
-\r
D4-B7-61 (hex) Sichuan AI-Link Technology Co., Ltd.\r
D4B761 (base 16) Sichuan AI-Link Technology Co., Ltd.\r
Anzhou,Industrial Park\r
Dongguan, Guangdong 523770\r
CN\r
\r
-0C-B6-D2 (hex) D-Link International\r
-0CB6D2 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
78-29-ED (hex) ASKEY COMPUTER CORP\r
7829ED (base 16) ASKEY COMPUTER CORP\r
10F,No.119,JIANKANG RD,ZHONGHE DIST\r
shenzhen guangdong 518057\r
CN\r
\r
-28-3B-82 (hex) D-Link International\r
-283B82 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
D4-90-9C (hex) Apple, Inc.\r
D4909C (base 16) Apple, Inc.\r
1 Infinite Loop\r
REICHSHOF-Sinspert 51580\r
DE\r
\r
-E8-C3-20 (hex) Austco Communication Systems Pty Ltd\r
-E8C320 (base 16) Austco Communication Systems Pty Ltd\r
- 40 O'Malley Street\r
- Osborne Park Western Australia 6017\r
- AU\r
-\r
C4-36-DA (hex) Rusteletech Ltd.\r
C436DA (base 16) Rusteletech Ltd.\r
Ordzhonikidze Str. 11, Bldg. 40, Off. 15 \r
San Giuliano Milanese Milano 20098\r
IT\r
\r
-00-23-86 (hex) Tour & Andersson AB\r
-002386 (base 16) Tour & Andersson AB\r
- Annelund\r
- Ljung 524 80\r
- US\r
-\r
00-23-83 (hex) InMage Systems Inc\r
002383 (base 16) InMage Systems Inc\r
3255-1 Scott Blvd, #104\r
Beijing 100091\r
CN\r
\r
-00-23-A7 (hex) Redpine Signals, Inc.\r
-0023A7 (base 16) Redpine Signals, Inc.\r
- Plot 87, Sagar Society\r
- Hyderabad AP 500034\r
- IN\r
-\r
00-23-9B (hex) Elster Solutions, LLC\r
00239B (base 16) Elster Solutions, LLC\r
208 South Rogers Lane\r
\r
JP\r
\r
-00-07-89 (hex) Allradio Co., Ltd\r
-000789 (base 16) Allradio Co., Ltd\r
- 861-5, Gwanyang-Dong, Dongan-Gu,\r
- Anyang-si, Gyeonggi-do, 430-803\r
- KR\r
-\r
00-07-B9 (hex) Ginganet Corporation\r
0007B9 (base 16) Ginganet Corporation\r
Kintetsu Shin Namba Building\r
Piscataway NJ 08554\r
US\r
\r
+D4-48-2D (hex) Shenzhen Deejoy Lighting Technology Co.,Ltd.\r
+D4482D (base 16) Shenzhen Deejoy Lighting Technology Co.,Ltd.\r
+ 3rd Floor, Building B3, Xujingchang Industrial Park,Xinhe Community Fuyong Town,Baoan District\r
+ Shenzhen Guangdong 518103\r
+ CN\r
+\r
D8-F8-AF (hex) DAONTEC\r
D8F8AF (base 16) DAONTEC\r
219, Gasan digital 1-ro\r
Seoul KS013\r
KR\r
\r
-D4-48-2D (hex) Shenzhen Deejoy Lighting Technology Co.,Ltd.\r
-D4482D (base 16) Shenzhen Deejoy Lighting Technology Co.,Ltd.\r
- 3rd Floor, Building B3, Xujingchang Industrial Park,Xinhe Community Fuyong Town,Baoan District\r
- Shenzhen Guangdong 518103\r
+40-8C-4C (hex) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
+408C4C (base 16) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
+ Chudong science and technology park, 111 shaxin road, tangxia town,\r
+ dongguan city guangdong province 523710\r
+ CN\r
+\r
+6C-AD-AD (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+6CADAD (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
+CC-E0-DA (hex) Baidu Online Network Technology (Beijing) Co., Ltd\r
+CCE0DA (base 16) Baidu Online Network Technology (Beijing) Co., Ltd\r
+ Baidu Campus, No.10 Shangdi 10th Street, Haidian District\r
+ Beijing 100085\r
+ CN\r
+\r
+14-1B-30 (hex) Shenzhen Yipingfang Network Technology Co., Ltd.\r
+141B30 (base 16) Shenzhen Yipingfang Network Technology Co., Ltd.\r
+ 21 / F, Kangjia R & D building, No.28, Keji South 12th Road, Nanshan District, Shenzhen City, Guangdong Province, China\r
+ Shenzhen Nanshan District 518000\r
+ CN\r
+\r
+F4-6F-ED (hex) Fiberhome Telecommunication Technologies Co.,LTD\r
+F46FED (base 16) Fiberhome Telecommunication Technologies Co.,LTD\r
+ No.5 DongXin Road\r
+ Wuhan Hubei 430074\r
+ CN\r
+\r
+94-B9-7E (hex) Espressif Inc.\r
+94B97E (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+A8-30-1C (hex) Qingdao Intelligent&Precise Electronics Co.,Ltd.\r
+A8301C (base 16) Qingdao Intelligent&Precise Electronics Co.,Ltd.\r
+ No.218 Qianwangang Road\r
+ Qingdao Shangdong 266510\r
+ CN\r
+\r
+D8-F3-BC (hex) Liteon Technology Corporation\r
+D8F3BC (base 16) Liteon Technology Corporation\r
+ 4F, 90, Chien 1 Road\r
+ New Taipei City Taiwan 23585\r
+ TW\r
+\r
+B8-47-7A (hex) Dasan Electron Co., Ltd.\r
+B8477A (base 16) Dasan Electron Co., Ltd.\r
+ 705 HaeAn-Ro #307, SangRok-Gu\r
+ Ansan KyungKi 15588\r
+ KR\r
+\r
+7C-78-B2 (hex) Wyze Labs Inc\r
+7C78B2 (base 16) Wyze Labs Inc\r
+ 4030 Lake Washington Boulevard NE\r
+ Kirkland WA 98033\r
+ US\r
+\r
+D8-37-3B (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd\r
+D8373B (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd\r
+ 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District\r
+ Shenzhen Guangdong 518055\r
+ CN\r
+\r
+6C-2D-24 (hex) Zhen Shi Information Technology (Shanghai) Co., Ltd.\r
+6C2D24 (base 16) Zhen Shi Information Technology (Shanghai) Co., Ltd.\r
+ 5F, Building 3?No. 401 Caobao Road, Xuhui District, Shanghai, China\r
+ Shanghai Shanghai 200233\r
+ CN\r
+\r
+B8-AE-1C (hex) Smart Cube., Ltd\r
+B8AE1C (base 16) Smart Cube., Ltd\r
+ 13F.-3, No. 78, Sec. 2, Anhe Rd., Da’an Dist., Taipei City 106, Taiwan (R.O.C.)\r
+ Taipei 106\r
+ TW\r
+\r
+80-03-84 (hex) Ruckus Wireless\r
+800384 (base 16) Ruckus Wireless\r
+ 350 West Java Drive\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+FC-69-8C (hex) ANDREAS STIHL AG & Co. KG\r
+FC698C (base 16) ANDREAS STIHL AG & Co. KG\r
+ Badstraße 115\r
+ Waiblingen 71336\r
+ DE\r
+\r
+00-23-A7 (hex) Redpine Signals, Inc.\r
+0023A7 (base 16) Redpine Signals, Inc.\r
+ Plot 87, Sagar Society \r
+ Hyderabad AP 500034\r
+ IN\r
+\r
+44-CE-3A (hex) Jiangsu Huacun Electronic Technology Co., Ltd.\r
+44CE3A (base 16) Jiangsu Huacun Electronic Technology Co., Ltd.\r
+ C4, 9th Floor, 266 New Century Avenue, Tongzhou District\r
+ Nantong City Jiangsu Province 226300\r
+ CN\r
+\r
+9C-1E-A4 (hex) Renesas Electronics (Penang) Sdn. Bhd.\r
+9C1EA4 (base 16) Renesas Electronics (Penang) Sdn. Bhd.\r
+ Phase 3, Bayan Lepas FIZ\r
+ Bayan Lepas Penang 11900\r
+ MY\r
+\r
+4C-EF-56 (hex) Shenzhen Sundray Technologies Company Limited\r
+4CEF56 (base 16) Shenzhen Sundray Technologies Company Limited\r
+ 5th Floor, Block A4, Nanshan ipark,NO.1001 Xue Yuan Road, Nanshan District, Shenzhen 518055, P.R. China\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+E4-C3-2A (hex) TP-LINK TECHNOLOGIES CO.,LTD.\r
+E4C32A (base 16) TP-LINK TECHNOLOGIES CO.,LTD.\r
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+90-9A-4A (hex) TP-LINK TECHNOLOGIES CO.,LTD.\r
+909A4A (base 16) TP-LINK TECHNOLOGIES CO.,LTD.\r
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+BC-97-89 (hex) Huawei Device Co., Ltd.\r
+BC9789 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+3C-E0-38 (hex) Plumeria Networks, Inc.\r
+3CE038 (base 16) Plumeria Networks, Inc.\r
+ 6701 Koll Center Parkway Suite 250\r
+ Pleasanton CA 94566\r
+ US\r
+\r
+AC-12-2F (hex) Fantasia Trading LLC\r
+AC122F (base 16) Fantasia Trading LLC\r
+ 5350 Ontario Mills Pkwy, Suite 100\r
+ Ontario CA 91764\r
+ US\r
+\r
+FC-45-C3 (hex) Texas Instruments\r
+FC45C3 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+AC-6A-A3 (hex) Shenzhen Kertong Technology Co.,Ltd\r
+AC6AA3 (base 16) Shenzhen Kertong Technology Co.,Ltd\r
+ 405,Fuyuan Building ,District 45 Bao’an\r
+ Shenzhen Guangdong 518101\r
+ CN\r
+\r
+E8-4F-4B (hex) Shenzhen Delos Electronic Co., Ltd\r
+E84F4B (base 16) Shenzhen Delos Electronic Co., Ltd\r
+ Rm 603, Tower B, Galaxy World Building, No.1 Yabao Road,Longgang District,Shenzhen,P.R.China.\r
+ shenzhen guangdong 518000\r
+ CN\r
+\r
+B0-4A-39 (hex) Beijing Roborock Technology Co., Ltd.\r
+B04A39 (base 16) Beijing Roborock Technology Co., Ltd.\r
+ Floor 6,Building C,Kangjian Baosheng Plaza,No. 8 Heiquan Road,Haidian District\r
+ Beijing Beijing 100085\r
+ CN\r
+\r
+A4-F9-E4 (hex) AirVine Scientific, Inc.\r
+A4F9E4 (base 16) AirVine Scientific, Inc.\r
+ 1500 Wyatt Drive, Suite 9\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+F4-4F-D3 (hex) shenzhen hemuwei technology co.,ltd\r
+F44FD3 (base 16) shenzhen hemuwei technology co.,ltd\r
+ 220, Building C, IoT Industrial Park, Bantian Street, Longgang District\r
+ shenzhen guangdong 518000\r
+ CN\r
+\r
+68-45-71 (hex) Huawei Device Co., Ltd.\r
+684571 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-93-A0 (hex) Huawei Device Co., Ltd.\r
+8493A0 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+9C-8E-9C (hex) Huawei Device Co., Ltd.\r
+9C8E9C (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+40-14-AD (hex) Huawei Device Co., Ltd.\r
+4014AD (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+A8-74-84 (hex) zte corporation\r
+A87484 (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
+E0-4B-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+E04BA6 (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-B6-D3 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C8B6D3 (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
+FC-8D-3D (hex) Leapfive Tech. Ltd.\r
+FC8D3D (base 16) Leapfive Tech. Ltd.\r
+ huaruizhididasha 8ceng\r
+ shenzhen guangdong 518057\r
+ CN\r
+\r
+00-23-86 (hex) IMI Hydronic Engineering international SA\r
+002386 (base 16) IMI Hydronic Engineering international SA\r
+ Route de Crassier 19\r
+ Eysins 1262\r
+ CH\r
+\r
+A0-69-74 (hex) Honor Device Co., Ltd.\r
+A06974 (base 16) Honor Device Co., Ltd.\r
+ A1701, Block AB, Building 1, Tianan Yungu Phase I, Gangtou Community, Bantian Street\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+C0-33-DA (hex) Shenzhen JRUN Technologies CO., LTD\r
+C033DA (base 16) Shenzhen JRUN Technologies CO., LTD\r
+ A Zone,9F,Huilongda Industrial Park,Shuitian Private Industrial Park,Shiyan Street,Bao,an District.\r
+ Shenzhen Guangdong 518101\r
+ CN\r
+\r
+60-70-72 (hex) SHENZHEN HONGDE SMART LINK TECHNOLOGY CO., LTD\r
+607072 (base 16) SHENZHEN HONGDE SMART LINK TECHNOLOGY CO., LTD\r
+ Fu Qian Road, Longhua district\r
+ ShenZhen GuangDong province 518000\r
+ CN\r
+\r
+DC-B7-FC (hex) Alps Electric (Ireland) Ltd\r
+DCB7FC (base 16) Alps Electric (Ireland) Ltd\r
+ MOUNT LEADER INDUSTRIAL ESTATE\r
+ MILLSTREET CO. CORK P51 XC56\r
+ IE\r
+\r
+AC-FA-A5 (hex) digitron\r
+ACFAA5 (base 16) digitron\r
+ tehnopark A -701, 697 PanGyo-ro, Bundong \r
+ Seongnam GyeongGiDO 13511\r
+ KR\r
+\r
+78-C9-5E (hex) Midmark RTLS \r
+78C95E (base 16) Midmark RTLS \r
+ 2600 Millercreek Rd\r
+ Traverse City MI 49684\r
+ US\r
+\r
+20-CD-6E (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd.\r
+20CD6E (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
+BC-69-CB (hex) Panasonic Life Solutions Networks Co., Ltd.\r
+BC69CB (base 16) Panasonic Life Solutions Networks Co., Ltd.\r
+ 2-12-7, Higashi-Shinbashi\r
+ Minato-Ku Tokyo 105-0021\r
+ JP\r
+\r
+08-93-56 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+089356 (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
+00-07-89 (hex) Allradio Co., Ltd\r
+000789 (base 16) Allradio Co., Ltd\r
+ 76, Deokcheon-ro 34beon-gil, Manan-gu\r
+ Anyang-si,Gyeonggi-do Republic of Korea 430-803\r
+ KR\r
+\r
+6C-14-6E (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+6C146E (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
+44-E9-68 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+44E968 (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
+DC-4A-9E (hex) IEEE Registration Authority\r
+DC4A9E (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+E0-C3-77 (hex) Samsung Electronics Co.,Ltd\r
+E0C377 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+4C-FB-F4 (hex) Optimal Audio Ltd\r
+4CFBF4 (base 16) Optimal Audio Ltd\r
+ Century Point, Halifax Rd\r
+ High Wycombe HP12 3SL\r
+ GB\r
+\r
+84-60-82 (hex) Private\r
+846082 (base 16) Private\r
+\r
+64-03-7F (hex) Samsung Electronics Co.,Ltd\r
+64037F (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+B4-9D-02 (hex) Samsung Electronics Co.,Ltd\r
+B49D02 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+80-9F-F5 (hex) Samsung Electronics Co.,Ltd\r
+809FF5 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+64-79-24 (hex) Huawei Device Co., Ltd.\r
+647924 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+D8-CC-98 (hex) Huawei Device Co., Ltd.\r
+D8CC98 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+F0-4F-7C (hex) Amazon Technologies Inc.\r
+F04F7C (base 16) Amazon Technologies Inc.\r
+ PO Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+F0-A2-25 (hex) Amazon Technologies Inc.\r
+F0A225 (base 16) Amazon Technologies Inc.\r
+ PO Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+B4-0E-DE (hex) Intel Corporate\r
+B40EDE (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+E0-2B-E9 (hex) Intel Corporate\r
+E02BE9 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+DC-B7-2E (hex) Xiaomi Communications Co Ltd\r
+DCB72E (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
+B8-87-6E (hex) Yandex Services AG\r
+B8876E (base 16) Yandex Services AG\r
+ Werftestrasse 4, \r
+ Luzern 6005\r
+ CH\r
+\r
+F8-6D-73 (hex) Zengge Co., Limited\r
+F86D73 (base 16) Zengge Co., Limited\r
+ 3/F, B Building, Second Laowei Industrial Zone, Longhua District\r
+ Shenzhen Guangdong 518109\r
+ CN\r
+\r
+58-86-94 (hex) EFM Networks\r
+588694 (base 16) EFM Networks\r
+ 6F, Benposra II 1197-1 Bojeong Giheung Gu\r
+ Yong In Kyunggi do 446913\r
+ KR\r
+\r
+AC-37-28 (hex) Taicang T&W Electronics\r
+AC3728 (base 16) Taicang T&W Electronics\r
+ 89# Jiang Nan RD\r
+ Suzhou Jiangsu 215412\r
+ CN\r
+\r
+BC-99-30 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+BC9930 (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-68-E7 (hex) Espressif Inc.\r
+E868E7 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+D0-BC-C1 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD\r
+D0BCC1 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD\r
+ Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China\r
+ Weifang Shandong 261205\r
+ CN\r
+\r
+6C-E8-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+6CE874 (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
+C4-69-F0 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C469F0 (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-94-35 (hex) ARRIS Group, Inc.\r
+C09435 (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+18-B6-CC (hex) We Corporation Inc.\r
+18B6CC (base 16) We Corporation Inc.\r
+ 201, 33, Deokcheon-ro, Manan-gu\r
+ Anyang-si Gyeonggi-do 14088\r
+ KR\r
+\r
+F8-5E-42 (hex) Technicolor CH USA Inc.\r
+F85E42 (base 16) Technicolor CH USA Inc.\r
+ 5030 Sugarloaf Parkway Bldg 6 \r
+ Lawrenceville GA 30044\r
+ US\r
+\r
+30-A0-23 (hex) ROCK PATH S.R.L\r
+30A023 (base 16) ROCK PATH S.R.L\r
+ Via Federico Borromeo 2, 20017 Rho (MI), Italy\r
+ Milan 20017\r
+ IT\r
+\r
+E8-48-B8 (hex) TP-Link Corporation Limited\r
+E848B8 (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
+78-CB-2C (hex) Join Digital, Inc.\r
+78CB2C (base 16) Join Digital, Inc.\r
+ 75 E Santa Clara St., 6th Floor\r
+ San Jose CA 95113\r
+ US\r
+\r
+30-9E-1D (hex) OHSUNG\r
+309E1D (base 16) OHSUNG\r
+ 335-4,SANHODAERO,GUMI,GYEONG BUK,KOREA\r
+ GUMI GYEONG BUK 730-030\r
+ KR\r
+\r
+68-79-12 (hex) IEEE Registration Authority\r
+687912 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+EC-64-88 (hex) Honor Device Co., Ltd.\r
+EC6488 (base 16) Honor Device Co., Ltd.\r
+ A1701, Block AB, Building 1, Tianan Yungu Phase I, Gangtou Community, Bantian Street\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+74-D6-CB (hex) New H3C Technologies Co., Ltd\r
+74D6CB (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+0C-3A-FA (hex) New H3C Technologies Co., Ltd\r
+0C3AFA (base 16) New H3C Technologies Co., Ltd\r
+ 466 Changhe Road, Binjiang District\r
+ Hangzhou Zhejiang 310052\r
+ CN\r
+\r
+28-3B-82 (hex) D-Link International\r
+283B82 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+0C-B6-D2 (hex) D-Link International\r
+0CB6D2 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+60-BE-C4 (hex) Apple, Inc.\r
+60BEC4 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F8-B1-DD (hex) Apple, Inc.\r
+F8B1DD (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F8-66-5A (hex) Apple, Inc.\r
+F8665A (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+A8-81-7E (hex) Apple, Inc.\r
+A8817E (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+8C-47-6E (hex) IEEE Registration Authority\r
+8C476E (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+48-70-1E (hex) Texas Instruments\r
+48701E (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+E8-C3-20 (hex) Austco Marketing & Service (USA) ltd.\r
+E8C320 (base 16) Austco Marketing & Service (USA) ltd.\r
+ 9155 Sterling St Unit 100\r
+ Irving TX 75063\r
+ US\r
+\r
+50-8E-49 (hex) Xiaomi Communications Co Ltd\r
+508E49 (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
+AC-33-28 (hex) Huawei Device Co., Ltd.\r
+AC3328 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+D4-76-A0 (hex) Fortinet, Inc.\r
+D476A0 (base 16) Fortinet, Inc.\r
+ 899 Kifer Road\r
+ Sunnyvale 94086\r
+ US\r
+\r
+B4-EC-02 (hex) ALPSALPINE CO,.LTD\r
+B4EC02 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-23-06 (hex) ALPSALPINE CO,.LTD\r
+002306 (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+00-24-33 (hex) ALPSALPINE CO,.LTD\r
+002433 (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+9C-8D-7C (hex) ALPSALPINE CO,.LTD\r
+9C8D7C (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-16-FE (hex) ALPSALPINE CO,.LTD\r
+0016FE (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+00-19-C1 (hex) ALPSALPINE CO,.LTD\r
+0019C1 (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+E0-75-0A (hex) ALPSALPINE CO,.LTD\r
+E0750A (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ kakuda-City 981-1595\r
+ US\r
+\r
+E0-AE-5E (hex) ALPSALPINE CO,.LTD\r
+E0AE5E (base 16) ALPSALPINE CO,.LTD\r
+ 6-3-36 Furukawanakazato,\r
+ Osaki Miyagi-pref 989-6181\r
+ JP\r
+\r
+BC-75-36 (hex) ALPSALPINE CO,.LTD\r
+BC7536 (base 16) ALPSALPINE CO,.LTD\r
+ nishida 6-1 \r
+ Kakuda-City Miyagi-Pref 981-1595\r
+ JP\r
+\r
+58-16-D7 (hex) ALPSALPINE CO,.LTD\r
+5816D7 (base 16) ALPSALPINE CO,.LTD\r
+ nishida 6-1 \r
+ Kakuda-City Miyagi-Pref 981-1595\r
+ JP\r
+\r
F8-D0-27 (hex) Seiko Epson Corporation\r
F8D027 (base 16) Seiko Epson Corporation\r
2070 Kotobuki Koaka\r
San Jose CA 94568\r
US\r
\r
-60-63-4C (hex) D-Link International\r
-60634C (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
20-5F-3D (hex) Cambridge Communication Systems Ltd\r
205F3D (base 16) Cambridge Communication Systems Ltd\r
Victory House, Vision Park, Chivers Way, Histon\r
Ulsan 44922\r
KR\r
\r
-30-C3-D9 (hex) ALPS ELECTRIC CO., LTD.\r
-30C3D9 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
00-32-17 (hex) Cisco Systems, Inc\r
003217 (base 16) Cisco Systems, Inc\r
80 West Tasman Drive\r
San Jose CA 94568\r
US\r
\r
-00-1B-FB (hex) ALPS ELECTRIC CO., LTD.\r
-001BFB (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
94-E0-D6 (hex) China Dragon Technology Limited\r
94E0D6 (base 16) China Dragon Technology Limited\r
B4 Bldg.Haoshan 1st Industry Park,\r
SHEN ZHEN GUANG DONG 518000\r
CN\r
\r
-AC-F8-5C (hex) Private\r
-ACF85C (base 16) Private\r
-\r
3C-37-86 (hex) NETGEAR\r
3C3786 (base 16) NETGEAR\r
350 East Plumeria Drive\r
Roseville CA 95747\r
US\r
\r
-00-AD-24 (hex) D-Link International\r
-00AD24 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
54-06-8B (hex) Ningbo Deli Kebei Technology Co.LTD\r
54068B (base 16) Ningbo Deli Kebei Technology Co.LTD\r
zone 2nd , 301#, Road Xuxiake, Ninghai yuelong district\r
Budapest 1191\r
HU\r
\r
-18-0F-76 (hex) D-Link International\r
-180F76 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
14-A7-2B (hex) currentoptronics Pvt.Ltd\r
14A72B (base 16) currentoptronics Pvt.Ltd\r
CRT Building, Jupitor Jn , Near Time kids Koothattukulam - Piravom Rd\r
Orlando FL 32837\r
US\r
\r
-00-16-3B (hex) VertexRSI/General Dynamics\r
-00163B (base 16) VertexRSI/General Dynamics\r
- 2120 Old Gatesburg Rd.\r
- State college PA 16803\r
- US\r
-\r
00-16-37 (hex) CITEL SpA\r
001637 (base 16) CITEL SpA\r
Via L. G. Columella, 36\r
Zilina 01124\r
SK\r
\r
-00-0B-4E (hex) VertexRSI, General Dynamics SatCOM Technologies, Inc.\r
-000B4E (base 16) VertexRSI, General Dynamics SatCOM Technologies, Inc.\r
- 3750 W. Loop 281\r
- Longview TX 75604\r
- US\r
-\r
00-0B-4D (hex) Emuzed\r
000B4D (base 16) Emuzed\r
46750 Lakeview Boulevard\r
TAIWAN TAIWAN R.O.C.\r
TW\r
\r
-00-03-34 (hex) Newport Electronics\r
-000334 (base 16) Newport Electronics\r
- 2229 So. Yale St.\r
- Santa Ana CA 92704\r
- US\r
-\r
00-03-3A (hex) Silicon Wave, Inc.\r
00033A (base 16) Silicon Wave, Inc.\r
6256 Greenwich Drive\r
Hattingen NRW 45527\r
DE\r
\r
-C4-E9-0A (hex) D-Link International\r
-C4E90A (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
C4-44-7D (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
C4447D (base 16) HUAWEI TECHNOLOGIES CO.,LTD\r
No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park\r
Foshan Guangdong 528311\r
CN\r
\r
-84-EA-97 (hex) Shenzhen iComm Semiconductor Co., Ltd.\r
-84EA97 (base 16) Shenzhen iComm Semiconductor Co., Ltd.\r
- Room 501A,Block B,Digital Building,Garden City,No.1079 Nanhai Road,Nanshan District\r
- Shenzhen 518067\r
- CN\r
-\r
5C-3A-3D (hex) zte corporation\r
5C3A3D (base 16) zte corporation\r
12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China\r
Dongguan Guangdong 523808\r
CN\r
\r
-F0-B4-D2 (hex) D-Link International\r
-F0B4D2 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
5C-3A-45 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
5C3A45 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District\r
Seoul 05836\r
KR\r
\r
+FC-44-9F (hex) zte corporation\r
+FC449F (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
+20-4E-F6 (hex) AzureWave Technology Inc.\r
+204EF6 (base 16) AzureWave Technology Inc.\r
+ 8F., No. 94, Baozhong Rd.\r
+ New Taipei City Taiwan 231\r
+ TW\r
+\r
44-35-83 (hex) Apple, Inc.\r
443583 (base 16) Apple, Inc.\r
1 Infinite Loop\r
Cupertino CA 95014\r
US\r
\r
-FC-44-9F (hex) zte corporation\r
-FC449F (base 16) zte corporation\r
+38-CA-73 (hex) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
+38CA73 (base 16) Shenzhen MiaoMing Intelligent Technology Co.,Ltd\r
+ Chudong science and technology park, 111 shaxin road, tangxia town,\r
+ dongguan city guangdong province 523710\r
+ CN\r
+\r
+6C-0D-C4 (hex) Beijing Xiaomi Electronics Co., Ltd.\r
+6C0DC4 (base 16) Beijing Xiaomi Electronics Co., Ltd.\r
+ Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District\r
+ Beijing Beijing 10085\r
+ CN\r
+\r
+C4-40-F6 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+C440F6 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+A4-7D-9F (hex) Shenzhen iComm Semiconductor CO.,LTD\r
+A47D9F (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
+84-EA-97 (hex) Shenzhen iComm Semiconductor CO.,LTD\r
+84EA97 (base 16) Shenzhen iComm Semiconductor CO.,LTD\r
+ Room 501A,Block B,Digital Building,Garden City,No.1079 Nanhai Road,Nanshan District\r
+ Shenzhen 518067\r
+ CN\r
+\r
+00-55-B1 (hex) Shanghai Baud Data Communication Co.,Ltd.\r
+0055B1 (base 16) Shanghai Baud Data Communication Co.,Ltd.\r
+ NO.123 JULI RD\r
+ PUDONG ZHANGJIANG HIGH-TECH PARK SHANGHAI 201203\r
+ CN\r
+\r
+74-90-1F (hex) Ragile Networks Inc.\r
+74901F (base 16) Ragile Networks Inc.\r
+ 35649 Embassy common Fremont ca 94536\r
+ Fremont CA 94536\r
+ US\r
+\r
+C0-25-2F (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.\r
+C0252F (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
+54-9F-C6 (hex) Cisco Systems, Inc\r
+549FC6 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+F0-1D-2D (hex) Cisco Systems, Inc\r
+F01D2D (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+68-3E-26 (hex) Intel Corporate\r
+683E26 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+8C-55-4A (hex) Intel Corporate\r
+8C554A (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+40-1C-83 (hex) Intel Corporate\r
+401C83 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+44-3B-32 (hex) Intelbras\r
+443B32 (base 16) Intelbras\r
+ BR 101, km 210, S/N°\r
+ São José Santa Catarina 88104800\r
+ BR\r
+\r
+F8-3B-1D (hex) Technicolor CH USA Inc.\r
+F83B1D (base 16) Technicolor CH USA Inc.\r
+ 5030 Sugarloaf Parkway Bldg 6 \r
+ Lawrenceville GA 30044\r
+ US\r
+\r
+D4-1B-81 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+D41B81 (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
+F4-0B-9F (hex) CIG SHANGHAI CO LTD\r
+F40B9F (base 16) CIG SHANGHAI CO LTD\r
+ 5th Floor, Building 8 No 2388 Chenhang Road\r
+ SHANGHAI 201114\r
+ CN\r
+\r
+78-45-B3 (hex) Huawei Device Co., Ltd.\r
+7845B3 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+20-DC-FD (hex) Huawei Device Co., Ltd.\r
+20DCFD (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+FC-65-B3 (hex) Huawei Device Co., Ltd.\r
+FC65B3 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+10-9D-7A (hex) Huawei Device Co., Ltd.\r
+109D7A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+DC-63-73 (hex) OBARA KOREA\r
+DC6373 (base 16) OBARA KOREA\r
+ 97-23, Barangongdan-ro 4-gil\r
+ Hwaseong-si Gyeonggi-do 18623\r
+ KR\r
+\r
+D4-7E-E4 (hex) China Mobile IOT Company Limited\r
+D47EE4 (base 16) China Mobile IOT Company Limited\r
+ NO.8 Yu Ma Road, NanAn Area\r
+ Chongqing Chongqing 401336\r
+ CN\r
+\r
+88-89-2F (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+88892F (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-E5-B0 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+28E5B0 (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-02-20 (hex) Xiaomi Communications Co Ltd\r
+4C0220 (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
+1C-A8-52 (hex) SENSAIO PTE LTD\r
+1CA852 (base 16) SENSAIO PTE LTD\r
+ 160 Robinson Road #14-04\r
+ SINGAPORE SINGAPORE 068914\r
+ SG\r
+\r
+78-7D-F3 (hex) Sterlite Technologies Limited\r
+787DF3 (base 16) Sterlite Technologies Limited\r
+ IFFCO Tower, 3rd Floor, Plot No.3, Sector 29,CH Baktawar Singh Rd, Institutional Area,\r
+ Gurugram Haryana 122002\r
+ IN\r
+\r
+C0-94-AD (hex) zte corporation\r
+C094AD (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
+D0-21-AC (hex) Yo Labs LLC\r
+D021AC (base 16) Yo Labs LLC\r
+ 3460 Hillview Ave.\r
+ Palo Alto CA 94304\r
+ US\r
+\r
+34-2B-70 (hex) Arris\r
+342B70 (base 16) Arris\r
+ 2500 Walsh Ave.\r
+ Santa Clara CA 95014\r
+ US\r
+\r
+1C-90-BE (hex) Ericsson AB\r
+1C90BE (base 16) Ericsson AB\r
+ Torshamnsgatan 36\r
+ Stockholm SE-164 80\r
+ SE\r
+\r
+00-16-3B (hex) Communications & Power Industries\r
+00163B (base 16) Communications & Power Industries\r
+ Suite , 60 Decibel Road\r
+ State College PA 16801\r
+ US\r
+\r
+9C-B2-E8 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+9CB2E8 (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
+74-73-1D (hex) ifm electronic gmbh\r
+74731D (base 16) ifm electronic gmbh\r
+ ifm-Straße 1\r
+ Tettnang BW 88069\r
+ DE\r
+\r
+00-0B-4E (hex) Communications & Power Industries\r
+000B4E (base 16) Communications & Power Industries\r
+ 1000 Klein Road\r
+ Plano TX 75074\r
+ US\r
+\r
+00-03-34 (hex) Omega Engineering Inc.\r
+000334 (base 16) Omega Engineering Inc.\r
+ 800 Connecticut Ave. Suite 5N01,\r
+ Norwalk CT 06854\r
+ US\r
+\r
+5C-61-99 (hex) CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.\r
+5C6199 (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
+E8-DB-84 (hex) Espressif Inc.\r
+E8DB84 (base 16) Espressif Inc.\r
+ Room 204, Building 2, 690 Bibo Rd, Pudong New Area\r
+ Shanghai Shanghai 201203\r
+ CN\r
+\r
+D0-55-09 (hex) Nintendo Co.,Ltd\r
+D05509 (base 16) Nintendo Co.,Ltd\r
+ 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU\r
+ KYOTO KYOTO 601-8501\r
+ JP\r
+\r
+A0-77-51 (hex) ASMedia Technology Inc.\r
+A07751 (base 16) ASMedia Technology Inc.\r
+ 6F, No.115, Minquan Rd.,\r
+ New Taipei City 23141\r
+ TW\r
+\r
+30-56-84 (hex) SHENZHEN YUNJI INTELLIGENT TECHNOLOGY CO.,LTD\r
+305684 (base 16) SHENZHEN YUNJI INTELLIGENT TECHNOLOGY CO.,LTD\r
+ A-SIDE A2 BUILDING 2/F ENET NEW INDUSTRIAL PARK,NO.20 DAFU INDUSTRIAL ZONE, AOBEI COMMUNITY, GUANLAN, LONGHUA NEW DISTRICT\r
+ SHENZHEN GUANGDONG 518000\r
+ CN\r
+\r
+14-56-3A (hex) Huawei Device Co., Ltd.\r
+14563A (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+70-90-B7 (hex) Huawei Device Co., Ltd.\r
+7090B7 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+38-FC-98 (hex) Intel Corporate\r
+38FC98 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+24-94-94 (hex) Hong Kong Bouffalo Lab Limited\r
+249494 (base 16) Hong Kong Bouffalo Lab Limited\r
+ RM 1903, 19/F Lee Garden One 33 Hysan Avenue, Causeway Bay\r
+ HongKong 999077\r
+ HK\r
+\r
+30-BE-3B (hex) Mitsubishi Electric Corporation\r
+30BE3B (base 16) Mitsubishi Electric Corporation\r
+ 2-7-3 Marunouchi, Chiyoda-ku\r
+ Tokyo 100-8310\r
+ JP\r
+\r
+0C-B7-89 (hex) Honor Device Co., Ltd.\r
+0CB789 (base 16) Honor Device Co., Ltd.\r
+ A1701, Block AB, Building 1, Tianan Yungu Phase I, Gangtou Community, Bantian Street\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+78-91-E9 (hex) Raisecom Technology CO.,LTD\r
+7891E9 (base 16) Raisecom Technology CO.,LTD\r
+ No. 11, East Area, No. 10 Block, East Xibeiwang Road\r
+ Beijing 100094\r
+ CN\r
+\r
+8C-34-01 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+8C3401 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD\r
+ NO.18 HAIBIN ROAD,\r
+ DONG GUAN GUANG DONG 523860\r
+ CN\r
+\r
+60-DB-98 (hex) Calix Inc.\r
+60DB98 (base 16) Calix Inc.\r
+ 2777 Orchard Pkwy\r
+ San Jose CA 95131\r
+ US\r
+\r
+68-72-C3 (hex) Samsung Electronics Co.,Ltd\r
+6872C3 (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+70-B1-3D (hex) Samsung Electronics Co.,Ltd\r
+70B13D (base 16) Samsung Electronics Co.,Ltd\r
+ 129, Samsung-ro, Youngtongl-Gu\r
+ Suwon Gyeonggi-Do 16677\r
+ KR\r
+\r
+FC-7F-F1 (hex) Aruba, a Hewlett Packard Enterprise Company\r
+FC7FF1 (base 16) Aruba, a Hewlett Packard Enterprise Company\r
+ 3333 Scott Blvd\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+3C-A3-7E (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+3CA37E (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-E4-3B (hex) ASIX Electronics Corporation\r
+F8E43B (base 16) ASIX Electronics Corporation\r
+ 4F, No. 8, Hsin Ann Road, Hsinchu Science Park\r
+ Hsinchu 30078\r
+ TW\r
+\r
+F8-5E-A0 (hex) Intel Corporate\r
+F85EA0 (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+50-2F-9B (hex) Intel Corporate\r
+502F9B (base 16) Intel Corporate\r
+ Lot 8, Jalan Hi-Tech 2/3 \r
+ Kulim Kedah 09000\r
+ MY\r
+\r
+48-EF-61 (hex) Huawei Device Co., Ltd.\r
+48EF61 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+78-F0-9B (hex) Huawei Device Co., Ltd.\r
+78F09B (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+00-E9-3A (hex) AzureWave Technology Inc.\r
+00E93A (base 16) AzureWave Technology Inc.\r
+ 8F., No. 94, Baozhong Rd.\r
+ New Taipei City Taiwan 231\r
+ TW\r
+\r
+00-C5-2C (hex) Juniper Networks\r
+00C52C (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+00-34-A1 (hex) RF-LAMBDA USA INC.\r
+0034A1 (base 16) RF-LAMBDA USA INC.\r
+ 9115 Brown Deer Road | San Diego\r
+ CA 92121\r
+ US\r
+\r
+60-35-73 (hex) Earda Technologies co Ltd\r
+603573 (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
+A4-97-33 (hex) ASKEY COMPUTER CORP\r
+A49733 (base 16) ASKEY COMPUTER CORP\r
+ 10F,No.119,JIANKANG RD,ZHONGHE DIST\r
+ NEW TAIPEI TAIWAN 23585\r
+ TW\r
+\r
+5C-FB-3A (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD.\r
+5CFB3A (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
+18-0F-76 (hex) D-Link International\r
+180F76 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+00-AD-24 (hex) D-Link International\r
+00AD24 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+60-63-4C (hex) D-Link International\r
+60634C (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+C4-E9-0A (hex) D-Link International\r
+C4E90A (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+F0-B4-D2 (hex) D-Link International\r
+F0B4D2 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+E0-1C-FC (hex) D-Link International\r
+E01CFC (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+F0-2F-74 (hex) ASUSTek COMPUTER INC.\r
+F02F74 (base 16) ASUSTek COMPUTER INC.\r
+ 15,Li-Te Rd., Peitou, Taipei 112, Taiwan\r
+ Taipei Taiwan 112\r
+ TW\r
+\r
+00-6E-02 (hex) Xovis AG\r
+006E02 (base 16) Xovis AG\r
+ Industriestrasse 1\r
+ Zollikofen Bern 3052\r
+ CH\r
+\r
+AC-F8-5C (hex) Chengdu Higon Integrated Circuit Design Co,. Ltd.\r
+ACF85C (base 16) Chengdu Higon Integrated Circuit Design Co,. Ltd.\r
+ Suite22-31, 11Floor, Block E5,Tianfu Software Park, Chengdu Gaoxin District\r
+ Chengdu Sichuan 610041\r
+ CN\r
+\r
+18-11-71 (hex) Guangzhou Doctorpai Education & Technology Co.,Ltd\r
+181171 (base 16) Guangzhou Doctorpai Education & Technology Co.,Ltd\r
+ Floor 5, Building C1, Greenland Central Plaza\r
+ Huangpu District, Guangzhou Guangdong Province 510700\r
+ CN\r
+\r
+E0-6D-17 (hex) Apple, Inc.\r
+E06D17 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F0-B3-EC (hex) Apple, Inc.\r
+F0B3EC (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+F4-65-A6 (hex) Apple, Inc.\r
+F465A6 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+78-98-E8 (hex) D-Link International\r
+7898E8 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+44-F2-1B (hex) Apple, Inc.\r
+44F21B (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+74-65-0C (hex) Apple, Inc.\r
+74650C (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+FC-D4-36 (hex) Motorola Mobility LLC, a Lenovo Company\r
+FCD436 (base 16) Motorola Mobility LLC, a Lenovo Company\r
+ 222 West Merchandise Mart Plaza\r
+ Chicago IL 60654\r
+ US\r
+\r
+0C-EC-8D (hex) Motorola Mobility LLC, a Lenovo Company\r
+0CEC8D (base 16) Motorola Mobility LLC, a Lenovo Company\r
+ 222 West Merchandise Mart Plaza\r
+ Chicago IL 60654\r
+ US\r
+\r
+18-4F-5D (hex) JRC Mobility Inc.\r
+184F5D (base 16) JRC Mobility Inc.\r
+ NAKANO CENTRAL PARK EAST 10-1, Nakano 4-chome\r
+ Nakano-ku Tokyo 164-8570\r
+ JP\r
+\r
+10-3F-44 (hex) Xiaomi Communications Co Ltd\r
+103F44 (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
+08-CB-E5 (hex) R3 - Reliable Realtime Radio Communications GmbH\r
+08CBE5 (base 16) R3 - Reliable Realtime Radio Communications GmbH\r
+ Bismarckstrasse 10-12\r
+ Berlin Berlin 10625\r
+ DE\r
+\r
+F0-23-AE (hex) AMPAK Technology,Inc.\r
+F023AE (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
+E0-77-26 (hex) Huawei Device Co., Ltd.\r
+E07726 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+94-A6-7E (hex) NETGEAR\r
+94A67E (base 16) NETGEAR\r
+ 350 East Plumeria Drive\r
+ San Jose CA 95134\r
+ US\r
+\r
+A8-9A-D7 (hex) Nokia\r
+A89AD7 (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+48-25-67 (hex) Poly\r
+482567 (base 16) Poly\r
+ 6001 America Center Drive\r
+ San Jose CA 95002\r
+ US\r
+\r
+F8-7A-41 (hex) Cisco Systems, Inc\r
+F87A41 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+84-F1-47 (hex) Cisco Systems, Inc\r
+84F147 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+24-9F-89 (hex) Texas Instruments\r
+249F89 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+24-76-25 (hex) Texas Instruments\r
+247625 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+30-C3-D9 (hex) ALPSALPINE CO,.LTD\r
+30C3D9 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-1B-FB (hex) ALPSALPINE CO,.LTD\r
+001BFB (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\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
Taipei 112\r
TW\r
\r
-EC-AD-E0 (hex) D-Link International\r
-ECADE0 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
78-DA-07 (hex) Zhejiang Tmall Technology Co., Ltd.\r
78DA07 (base 16) Zhejiang Tmall Technology Co., Ltd.\r
Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, \r
Shenzhen Guangdong 518000\r
CN\r
\r
-60-38-0E (hex) ALPS ELECTRIC CO., LTD.\r
-60380E (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi\r
- Soma-city Fukushima 976-8501\r
- JP\r
-\r
-FC-62-B9 (hex) ALPS ELECTRIC CO., LTD.\r
-FC62B9 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- kakuda-city Miyagi-Pref 981-1595\r
- JP\r
-\r
-00-02-C7 (hex) ALPS ELECTRIC CO., LTD.\r
-0002C7 (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi, Sama-City,\r
- Sama 00000\r
- JP\r
-\r
-00-1E-3D (hex) ALPS ELECTRIC CO., LTD.\r
-001E3D (base 16) ALPS ELECTRIC CO., LTD.\r
- 1-2-1, Okinouchi,\r
- Soma-city, Fukushima-pref., 976-8501\r
- JP\r
-\r
-28-A1-83 (hex) ALPS ELECTRIC CO., LTD.\r
-28A183 (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
4C-DD-7D (hex) LHP Telematics LLC\r
4CDD7D (base 16) LHP Telematics LLC\r
17406 Tiller Ct. STE 100\r
westfield IN 46074\r
US\r
\r
-48-F0-7B (hex) ALPS ELECTRIC CO., LTD.\r
-48F07B (base 16) ALPS ELECTRIC CO., LTD.\r
- 6-1\r
- Kakuda Miyagi-Pref 981-1595\r
- JP\r
-\r
B8-BC-5B (hex) Samsung Electronics Co.,Ltd\r
B8BC5B (base 16) Samsung Electronics Co.,Ltd\r
129, Samsung-ro, Youngtongl-Gu\r
Piscataway NJ 08554\r
US\r
\r
-F4-8C-EB (hex) D-Link International\r
-F48CEB (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
74-3A-65 (hex) NEC Corporation\r
743A65 (base 16) NEC Corporation\r
7-1, Shiba 5-chome, Minato-ku\r
Mountain View CA 94041\r
US\r
\r
-58-D5-6E (hex) D-Link International\r
-58D56E (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
0C-53-31 (hex) ETH Zurich\r
0C5331 (base 16) ETH Zurich\r
Dept. Computer Science, Universitätstr. 6\r
Oranienburg Brandenburg 16515\r
DE\r
\r
-60-81-2B (hex) Custom Control Concepts\r
-60812B (base 16) Custom Control Concepts\r
- 6020 S 190th ST\r
- Kent Washington 98032\r
- US\r
-\r
1C-1C-FD (hex) Dalian Hi-Think Computer Technology, Corp\r
1C1CFD (base 16) Dalian Hi-Think Computer Technology, Corp\r
Hi-Think Software Building,No.6 Hi-Tech Street, Qixianling Industrial Base, Hi-Tech Zone, Dalian, China\r
Mountain View CA 94043\r
US\r
\r
-00-1A-65 (hex) Seluxit\r
-001A65 (base 16) Seluxit\r
- Nyhavnsgade 9, 2.sal\r
- Aalborg Nord Jylland 9000\r
- DK\r
-\r
00-1A-54 (hex) Hip Shing Electronics Ltd.\r
001A54 (base 16) Hip Shing Electronics Ltd.\r
Unit 1/2/3, 20/F, New Treasure Center\r
Barneveld Gelderland 3772 MT\r
NL\r
\r
-00-14-5A (hex) Neratec Solutions AG\r
-00145A (base 16) Neratec Solutions AG\r
- Rosswiesstrasse 29\r
- CH-8608 Bubikon ZH\r
- CH\r
-\r
00-14-5B (hex) SeekerNet Inc.\r
00145B (base 16) SeekerNet Inc.\r
300 Satellite Blvd.\r
SEOCHO-KU SEOUL \r
KR\r
\r
-00-90-D2 (hex) ARTEL VIDEO SYSTEMS\r
-0090D2 (base 16) ARTEL VIDEO SYSTEMS\r
- 237 CEDAR HILL ST.\r
- MARLBORO MA 01752\r
- US\r
-\r
00-01-FE (hex) DIGITAL EQUIPMENT CORPORATION\r
0001FE (base 16) DIGITAL EQUIPMENT CORPORATION\r
301 ROCKRIMMON BLVD, SOUTH\r
Reno NV 89507\r
US\r
\r
-98-C9-7C (hex) Shenzhen iComm Semiconductor CO,LTD\r
-98C97C (base 16) Shenzhen iComm Semiconductor CO,LTD\r
- Room 504A,Block B,Digital Building,Garden City,No.1079 Nanhai Road,Nanshan District,Shenzhen\r
- shenzhen Guangdong 518067\r
- CN\r
-\r
E0-92-A7 (hex) Feitian Technologies Co., Ltd\r
E092A7 (base 16) Feitian Technologies Co., Ltd\r
Floor 17, Tower B, Huizhi Mansion, No.9 Xueqing Rd, Haidian District\r
Gumi Gyeongbuk 730-350\r
KR\r
\r
-34-0A-33 (hex) D-Link International\r
-340A33 (base 16) D-Link International\r
- 1 Internal Business Park, #03-12,The Synergy, Singapore\r
- Singapore Singapore 609917\r
- SG\r
-\r
84-D8-1B (hex) TP-LINK TECHNOLOGIES CO.,LTD.\r
84D81B (base 16) TP-LINK TECHNOLOGIES CO.,LTD.\r
Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan\r
Cupertino CA 95014\r
US\r
\r
+EC-C3-02 (hex) HUMAX Co., Ltd.\r
+ECC302 (base 16) HUMAX Co., Ltd.\r
+ HUMAX Village, 216, Hwangsaeul-ro, Bu\r
+ Seongnam-si Gyeonggi-do 463-875\r
+ KR\r
+\r
+98-C9-7C (hex) Shenzhen iComm Semiconductor CO.,LTD\r
+98C97C (base 16) Shenzhen iComm Semiconductor CO.,LTD\r
+ Room 504A,Block B,Digital Building,Garden City,No.1079 Nanhai Road,Nanshan District,Shenzhen\r
+ shenzhen Guangdong 518067\r
+ CN\r
+\r
+00-C3-43 (hex) E-T-A Circuit Breakers Ltd\r
+00C343 (base 16) E-T-A Circuit Breakers Ltd\r
+ 6 Telford Close\r
+ Aylesbury Buckinghamshire HP198DG\r
+ GB\r
+\r
58-20-8A (hex) IEEE Registration Authority\r
58208A (base 16) IEEE Registration Authority\r
445 Hoes Lane\r
Piscataway NJ 08554\r
US\r
+\r
+00-90-D2 (hex) Artel Video Systems\r
+0090D2 (base 16) Artel Video Systems\r
+ 5B Lyberty Way\r
+ Westford MA 01886\r
+ US\r
+\r
+6C-1E-D7 (hex) vivo Mobile Communication Co., Ltd.\r
+6C1ED7 (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+F0-AA-0B (hex) Arra Networks/ Spectramesh\r
+F0AA0B (base 16) Arra Networks/ Spectramesh\r
+ 9201 Ward Pkwy #101\r
+ Kansas City MO 64114\r
+ US\r
+\r
+94-56-41 (hex) Palo Alto Networks\r
+945641 (base 16) Palo Alto Networks\r
+ 3000 Tannery Way\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+80-F5-B5 (hex) Texas Instruments\r
+80F5B5 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+1C-30-08 (hex) Hui Zhou Gaoshengda Technology Co.,LTD\r
+1C3008 (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
+98-06-3A (hex) Home Control Singapore Pte Ltd\r
+98063A (base 16) Home Control Singapore Pte Ltd\r
+ 151 Lorong Chuan\r
+ Singapore 556741\r
+ SG\r
+\r
+B4-BA-12 (hex) China Mobile (Hangzhou) Information Technology Co.,Ltd.\r
+B4BA12 (base 16) China Mobile (Hangzhou) Information Technology Co.,Ltd.\r
+ No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District\r
+ Hangzhou Zhejiang 311100\r
+ CN\r
+\r
+5C-F9-FD (hex) Taicang T&W Electronics\r
+5CF9FD (base 16) Taicang T&W Electronics\r
+ 89# Jiang Nan RD\r
+ Suzhou Jiangsu 215412\r
+ CN\r
+\r
+38-98-E9 (hex) Huawei Device Co., Ltd.\r
+3898E9 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+48-A5-16 (hex) Huawei Device Co., Ltd.\r
+48A516 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+18-36-72 (hex) Shaoxing ShunChuang Technology CO.,LTD\r
+183672 (base 16) Shaoxing ShunChuang Technology CO.,LTD\r
+ N.O.398 west tongjiang load shangyu\r
+ Shaoxing Zhejiang 312300\r
+ CN\r
+\r
+28-DE-65 (hex) Aruba, a Hewlett Packard Enterprise Company\r
+28DE65 (base 16) Aruba, a Hewlett Packard Enterprise Company\r
+ 3333 Scott Blvd\r
+ Santa Clara CA 95054\r
+ US\r
+\r
+B0-A6-51 (hex) Cisco Systems, Inc\r
+B0A651 (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+D4-91-0F (hex) Amazon Technologies Inc.\r
+D4910F (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+B8-5F-B0 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B85FB0 (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
+C4-FB-AA (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+C4FBAA (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-DC-CA (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+ACDCCA (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
+64-A2-00 (hex) Xiaomi Communications Co Ltd\r
+64A200 (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
+C0-78-31 (hex) Huawei Device Co., Ltd.\r
+C07831 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+84-CC-63 (hex) Huawei Device Co., Ltd.\r
+84CC63 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+E0-E0-C2 (hex) China Mobile Group Device Co.,Ltd.\r
+E0E0C2 (base 16) China Mobile Group Device Co.,Ltd.\r
+ 32 Xuanwumen West Street,Xicheng District\r
+ Beijing 100053\r
+ CN\r
+\r
+F0-64-26 (hex) Extreme Networks, Inc.\r
+F06426 (base 16) Extreme Networks, Inc.\r
+ 6480 Via Del Oro\r
+ San Jose CA 95119\r
+ US\r
+\r
+70-3A-2D (hex) Shenzhen V-Link Technology CO., LTD.\r
+703A2D (base 16) Shenzhen V-Link Technology CO., LTD.\r
+ Room 1803, BaiRuiDa Building, Bantian Sub-district, LongGang District\r
+ Shenzhen GuangDong 518000\r
+ CN\r
+\r
+1C-45-C2 (hex) Huizhou City Sunsin lntelligent Technology Co.,Ltd\r
+1C45C2 (base 16) Huizhou City Sunsin lntelligent Technology Co.,Ltd\r
+ Outside No.6 community, Zhongkai high tech Zone, Huizhou\r
+ Huizhou 516000\r
+ CN\r
+\r
+7C-4E-09 (hex) Shenzhen Skyworth Wireless Technology Co.,Ltd\r
+7C4E09 (base 16) Shenzhen Skyworth Wireless Technology Co.,Ltd\r
+ Unit 3A01,Block A Skyworth Building,Gaoxin Ave.I.S.,Nanshan District\r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+EC-7E-91 (hex) ITEL MOBILE LIMITED\r
+EC7E91 (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
+FC-96-43 (hex) Juniper Networks\r
+FC9643 (base 16) Juniper Networks\r
+ 1133 Innovation Way\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+A8-B0-88 (hex) eero inc.\r
+A8B088 (base 16) eero inc.\r
+ 660 3rd Street\r
+ San Francisco CA 94107\r
+ US\r
+\r
+00-1A-65 (hex) Seluxit\r
+001A65 (base 16) Seluxit\r
+ Sofiendalsvej 74\r
+ Aalborg SV 9200\r
+ DK\r
+\r
+28-0F-C5 (hex) Beijing Leadsec Technology Co., Ltd.\r
+280FC5 (base 16) Beijing Leadsec Technology Co., Ltd.\r
+ Venus Plaza No.21Zhongguancun Software Park,No.8 Dongbeiwang Xilu, Haidian District\r
+ Beijing Beijing 100193\r
+ CN\r
+\r
+1C-EC-72 (hex) Allradio Co., Ltd\r
+1CEC72 (base 16) Allradio Co., Ltd\r
+ 76, Deokcheon-ro 34beon-gil, Manan-gu\r
+ Anyang-si,Gyeonggi-do Republic of Korea 430-803\r
+ KR\r
+\r
+E0-E1-A9 (hex) Shenzhen Four Seas Global Link Network Technology Co., Ltd.\r
+E0E1A9 (base 16) Shenzhen Four Seas Global Link Network Technology Co., Ltd.\r
+ Room 607-610, Block B, TAOJINDI Electronic Business Incubation Base\r
+ Tenglong Road, Longhua District, Shenzhen Guangdong 518000\r
+ CN\r
+\r
+6C-14-14 (hex) BUJEON ELECTRONICS Co,.Ltd\r
+6C1414 (base 16) BUJEON ELECTRONICS Co,.Ltd\r
+ 59, Seonjinan-gil, Sangnok-gu\r
+ Ansan-si Gyeonggi-do 15633\r
+ KR\r
+\r
+C4-3C-EA (hex) BUFFALO.INC\r
+C43CEA (base 16) BUFFALO.INC\r
+ AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku\r
+ Nagoya Aichi Pref. 460-8315\r
+ JP\r
+\r
+B0-EC-DD (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+B0ECDD (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-67-84 (hex) Google, Inc.\r
+AC6784 (base 16) Google, Inc.\r
+ 1600 Amphitheatre Parkway\r
+ Mountain View CA 94043\r
+ US\r
+\r
+90-DE-80 (hex) Shenzhen Century Xinyang Technology Co., Ltd\r
+90DE80 (base 16) Shenzhen Century Xinyang Technology Co., Ltd\r
+ 3F, North Building, Bantian High-tech industrial Zone, No. 2 of Bell Road\r
+ Shenzhen Guangdong 518129\r
+ CN\r
+\r
+E4-DC-43 (hex) Huawei Device Co., Ltd.\r
+E4DC43 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+24-30-F8 (hex) Huawei Device Co., Ltd.\r
+2430F8 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+9C-5F-B0 (hex) Samsung Electronics Co.,Ltd\r
+9C5FB0 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+E8-7F-6B (hex) Samsung Electronics Co.,Ltd\r
+E87F6B (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+FC-B6-9D (hex) Zhejiang Dahua Technology Co., Ltd.\r
+FCB69D (base 16) Zhejiang Dahua Technology Co., Ltd.\r
+ No.1199,Waterfront Road \r
+ Hangzhou Zhejiang 310053\r
+ CN\r
+\r
+18-5B-B3 (hex) Samsung Electronics Co.,Ltd\r
+185BB3 (base 16) Samsung Electronics Co.,Ltd\r
+ #94-1, Imsoo-Dong\r
+ Gumi Gyeongbuk 730-350\r
+ KR\r
+\r
+94-F2-BB (hex) Valeo Vision Systems\r
+94F2BB (base 16) Valeo Vision Systems\r
+ Dunmore Road\r
+ Tuam Co. Galway H54 Y276\r
+ IE\r
+\r
+64-20-E0 (hex) T3 Technology Co., Ltd.\r
+6420E0 (base 16) T3 Technology Co., Ltd.\r
+ No.65/113, Chamnan Phenjati, 12A Floor, Rama9 road\r
+ Bangkok Bangkok 10310\r
+ TH\r
+\r
+5C-C0-A0 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+5CC0A0 (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-F3-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+04F352 (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
+EC-A1-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+ECA1D1 (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-6D-A4 (hex) HUAWEI TECHNOLOGIES CO.,LTD\r
+A46DA4 (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-8B-0A (hex) Cisco Systems, Inc\r
+488B0A (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+24-94-CB (hex) ARRIS Group, Inc.\r
+2494CB (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+78-6A-1F (hex) ARRIS Group, Inc.\r
+786A1F (base 16) ARRIS Group, Inc.\r
+ 6450 Sequence Drive\r
+ San Diego CA 92121\r
+ US\r
+\r
+8C-7A-15 (hex) Ruckus Wireless\r
+8C7A15 (base 16) Ruckus Wireless\r
+ 350 West Java Drive\r
+ Sunnyvale CA 94089\r
+ US\r
+\r
+84-11-C2 (hex) IEEE Registration Authority\r
+8411C2 (base 16) IEEE Registration Authority\r
+ 445 Hoes Lane\r
+ Piscataway NJ 08554\r
+ US\r
+\r
+28-AD-18 (hex) Hui Zhou Gaoshengda Technology Co.,LTD\r
+28AD18 (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
+24-A4-87 (hex) Huawei Device Co., Ltd.\r
+24A487 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+C4-5A-86 (hex) Huawei Device Co., Ltd.\r
+C45A86 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+20-AC-9C (hex) China Telecom Corporation Limited\r
+20AC9C (base 16) China Telecom Corporation Limited\r
+ 31 Jinrong Street, Xicheng District, Beijing, China\r
+ Beijing, China 100033\r
+ CN\r
+\r
+74-78-27 (hex) Dell Inc.\r
+747827 (base 16) Dell Inc.\r
+ One Dell Way\r
+ Round Rock TX 78682\r
+ US\r
+\r
+10-96-93 (hex) Amazon Technologies Inc.\r
+109693 (base 16) Amazon Technologies Inc.\r
+ P.O Box 8102\r
+ Reno NV 89507\r
+ US\r
+\r
+E4-F1-D4 (hex) vivo Mobile Communication Co., Ltd.\r
+E4F1D4 (base 16) vivo Mobile Communication Co., Ltd.\r
+ #283,BBK Road\r
+ Wusha,Chang'An DongGuan City,Guangdong, 523860\r
+ CN\r
+\r
+94-09-D3 (hex) shenzhen maxtopic technology co.,ltd\r
+9409D3 (base 16) shenzhen maxtopic technology co.,ltd\r
+ F3,Building 4, Ji'an Industrial Park, Songbai Blvd\r
+ shenzhen guangdong 518108\r
+ CN\r
+\r
+58-D5-6E (hex) D-Link International\r
+58D56E (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+F4-8C-EB (hex) D-Link International\r
+F48CEB (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+EC-AD-E0 (hex) D-Link International\r
+ECADE0 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+34-0A-33 (hex) D-Link International\r
+340A33 (base 16) D-Link International\r
+ 1 Internal Business Park, #03-12,The Synergy\r
+ Singapore Singapore 609917\r
+ SG\r
+\r
+BC-62-CE (hex) SHENZHEN NETIS TECHNOLOGY CO.,LTD\r
+BC62CE (base 16) SHENZHEN NETIS TECHNOLOGY CO.,LTD\r
+ 8 Floor, Bd B, information port, Langshan RD, Nanshan district, \r
+ Shenzhen Guangdong 518057\r
+ CN\r
+\r
+78-2E-56 (hex) China Mobile Group Device Co.,Ltd.\r
+782E56 (base 16) China Mobile Group Device Co.,Ltd.\r
+ 32 Xuanwumen West Street,Xicheng District\r
+ Beijing 100053\r
+ CN\r
+\r
+C4-0B-31 (hex) Apple, Inc.\r
+C40B31 (base 16) Apple, Inc.\r
+ 1 Infinite Loop\r
+ Cupertino CA 95014\r
+ US\r
+\r
+30-24-A9 (hex) HP Inc.\r
+3024A9 (base 16) HP Inc.\r
+ 10300 Energy Dr\r
+ Spring TX 77389\r
+ US\r
+\r
+A8-6E-4E (hex) Huawei Device Co., Ltd.\r
+A86E4E (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+94-5F-34 (hex) Renesas Electronics (Penang) Sdn. Bhd.\r
+945F34 (base 16) Renesas Electronics (Penang) Sdn. Bhd.\r
+ Phase 3, Bayan Lepas FIZ\r
+ Bayan Lepas Penang 11900\r
+ MY\r
+\r
+60-3C-EE (hex) LG Electronics (Mobile Communications)\r
+603CEE (base 16) LG Electronics (Mobile Communications)\r
+ 60-39, Gasan-dong, Geumcheon-gu\r
+ Seoul 153-801\r
+ KR\r
+\r
+2C-4A-11 (hex) Ciena Corporation\r
+2C4A11 (base 16) Ciena Corporation\r
+ 7035 Ridge Road\r
+ Hanover MD 21076\r
+ US\r
+\r
+1C-4C-48 (hex) ITEL MOBILE LIMITED\r
+1C4C48 (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
+C4-CB-54 (hex) Fibocom Auto Inc.\r
+C4CB54 (base 16) Fibocom Auto Inc.\r
+ 5/F,Tower A,Technology Building II,1057# Nanhai Blvd\r
+ Shenzhen Guangdong 518054\r
+ CN\r
+\r
+10-2D-31 (hex) Shenzhen Americas Trading Company LLC\r
+102D31 (base 16) Shenzhen Americas Trading Company LLC\r
+ 1308 Capital Ave.Suite #7\r
+ Plano TX 75074\r
+ US\r
+\r
+2C-07-86 (hex) Huawei Device Co., Ltd.\r
+2C0786 (base 16) Huawei Device Co., Ltd.\r
+ No.2 of Xincheng Road, Songshan Lake Zone\r
+ Dongguan Guangdong 523808\r
+ CN\r
+\r
+0C-35-4F (hex) Nokia\r
+0C354F (base 16) Nokia\r
+ 600 March Road\r
+ Kanata Ontario K2K 2E6\r
+ CA\r
+\r
+60-81-2B (hex) Astronics Custom Control Concepts\r
+60812B (base 16) Astronics Custom Control Concepts\r
+ 6020 S 190th ST\r
+ Kent Washington 98032\r
+ US\r
+\r
+F8-A7-3A (hex) Cisco Systems, Inc\r
+F8A73A (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+B8-11-4B (hex) Cisco Systems, Inc\r
+B8114B (base 16) Cisco Systems, Inc\r
+ 80 West Tasman Drive\r
+ San Jose CA 94568\r
+ US\r
+\r
+30-E2-83 (hex) Texas Instruments\r
+30E283 (base 16) Texas Instruments\r
+ 12500 TI Blvd\r
+ Dallas TX 75243\r
+ US\r
+\r
+00-02-C7 (hex) ALPSALPINE CO,.LTD\r
+0002C7 (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi, Sama-City,\r
+ Sama 00000\r
+ JP\r
+\r
+FC-62-B9 (hex) ALPSALPINE CO,.LTD\r
+FC62B9 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ kakuda-city Miyagi-Pref 981-1595\r
+ JP\r
+\r
+60-38-0E (hex) ALPSALPINE CO,.LTD\r
+60380E (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi\r
+ Soma-city Fukushima 976-8501\r
+ JP\r
+\r
+28-A1-83 (hex) ALPSALPINE CO,.LTD\r
+28A183 (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-1E-3D (hex) ALPSALPINE CO,.LTD\r
+001E3D (base 16) ALPSALPINE CO,.LTD\r
+ 1-2-1, Okinouchi,\r
+ Soma-city, Fukushima-pref., 976-8501\r
+ JP\r
+\r
+48-F0-7B (hex) ALPSALPINE CO,.LTD\r
+48F07B (base 16) ALPSALPINE CO,.LTD\r
+ 6-1\r
+ Kakuda Miyagi-Pref 981-1595\r
+ JP\r
+\r
+00-14-5A (hex) Westermo Neratec AG\r
+00145A (base 16) Westermo Neratec AG\r
+ Rosswiesstrasse 29\r
+ CH-8608 Bubikon ZH\r
+ CH\r
Saga 840-8502\r
JP\r
\r
-34-04-9E (hex) Private\r
-C00000-CFFFFF (base 16) Private\r
-\r
2C-48-35 (hex) Phasor Solutions Ltd\r
D00000-DFFFFF (base 16) Phasor Solutions Ltd\r
The Record Hall, 16 Baldwin Gardens\r
Kaohsiung 807\r
TW\r
\r
+CC-4F-5C (hex) Beijing Cotytech Technology Co.,LTD.\r
+C00000-CFFFFF (base 16) Beijing Cotytech Technology Co.,LTD.\r
+ Rm2302,Block B,Haojing Building,Zhichunlu,Haidian District,Beijing\r
+ Beijing 100192\r
+ CN\r
+\r
+CC-4F-5C (hex) Smiths US Innovation LLC\r
+700000-7FFFFF (base 16) Smiths US Innovation LLC\r
+ 3125 SKYWAY CT\r
+ Fremont CA 94539\r
+ US\r
+\r
+CC-4F-5C (hex) Watertech S.p.A.\r
+600000-6FFFFF (base 16) Watertech S.p.A.\r
+ STRADA ANTICA FORNACE 2/4\r
+ CANELLI ITALY 14053\r
+ IT\r
+\r
+CC-4F-5C (hex) Ontex BV\r
+B00000-BFFFFF (base 16) Ontex BV\r
+ Genthof 5\r
+ Buggenhout NA 9255\r
+ BE\r
+\r
+CC-4F-5C (hex) lesswire GmbH\r
+100000-1FFFFF (base 16) lesswire GmbH\r
+ Rudower Chaussee 30\r
+ Berlin Germany 12489\r
+ DE\r
+\r
+FC-CD-2F (hex) Ningbo Bull Digital Technology Co., LTD\r
+000000-0FFFFF (base 16) Ningbo Bull Digital Technology Co., LTD\r
+ No.32 Sanhai Road, East Guanhaiwei Industrial zone\r
+ Cixi City Zhejiang 315314\r
+ CN\r
+\r
+FC-CD-2F (hex) QCTEK CO.,LTD.\r
+500000-5FFFFF (base 16) QCTEK CO.,LTD.\r
+ 6F., No.496, Bannan Rd., Zhonghe Dist., New Taipei City 235, Taiwan (R.O.C.)\r
+ New Taipei City New Taipei City 235\r
+ TW\r
+\r
+CC-4F-5C (hex) Spark Biomedical\r
+400000-4FFFFF (base 16) Spark Biomedical\r
+ 4428 Irvin Simmons Drive\r
+ Dallas TX 75229\r
+ US\r
+\r
+58-95-D8 (hex) Shenzhen DOOGEE Hengtong Technology CO.,LTD\r
+000000-0FFFFF (base 16) Shenzhen DOOGEE Hengtong Technology CO.,LTD\r
+ Shenzhen DOOGEE Hengtong Technology CO.,LTD\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+DC-4A-9E (hex) Astrogate Inc.\r
+700000-7FFFFF (base 16) Astrogate Inc.\r
+ 11F-6, No. 120, Qiaohe Rd., Zhonghe Dist.\r
+ New Taipei City 235\r
+ TW\r
+\r
+58-95-D8 (hex) Loftie\r
+900000-9FFFFF (base 16) Loftie\r
+ 26 Grove St, Apt. 5C\r
+ New York NY 10014\r
+ US\r
+\r
+58-95-D8 (hex) Peak Communications Limited\r
+A00000-AFFFFF (base 16) Peak Communications Limited\r
+ Suite 1, Commercial House One, Eden Island, Republic of Seychelles\r
+ Eden Island 123\r
+ SC\r
+\r
+58-95-D8 (hex) LOCTEK ERGONOMIC TECHNOLOGY CORP.\r
+C00000-CFFFFF (base 16) LOCTEK ERGONOMIC TECHNOLOGY CORP.\r
+ No. 588, Qihang South Road, Yinzhou Economic Development Zone\r
+ Ningbo City Zhejiang 315100\r
+ CN\r
+\r
+58-95-D8 (hex) Norgren Manufacturing Co., Ltd.\r
+600000-6FFFFF (base 16) Norgren Manufacturing Co., Ltd.\r
+ Block 3, No 1885 Duhui Road, Minhang District\r
+ Shanghai Shanghai 201108\r
+ CN\r
+\r
+DC-4A-9E (hex) TATTILE SRL\r
+600000-6FFFFF (base 16) TATTILE SRL\r
+ VIA DONIZETTI, 1/3/5\r
+ MAIRANO BRESCIA 25030\r
+ IT\r
+\r
+DC-4A-9E (hex) Methodex Systems Pvt. Ltd.\r
+800000-8FFFFF (base 16) Methodex Systems Pvt. Ltd.\r
+ 607-8 Meghdoot, 94 Nehru Place\r
+ New Delhi Delhi 110019\r
+ IN\r
+\r
+84-11-C2 (hex) LLC STC MZTA\r
+400000-4FFFFF (base 16) LLC STC MZTA\r
+ 33/26 Mironovskaya str.\r
+ Moscow Moscow 115280\r
+ RU\r
+\r
+84-11-C2 (hex) Futurecom Systems Group\r
+200000-2FFFFF (base 16) Futurecom Systems Group\r
+ 3277 Langstaff Rd\r
+ Concord Ontario L4K 5P8\r
+ CA\r
+\r
+DC-4A-9E (hex) HAPPIEST BABY INC.\r
+D00000-DFFFFF (base 16) HAPPIEST BABY INC.\r
+ 3115 S La Cienega Blvd.\r
+ Los Angeles CA 90016\r
+ US\r
+\r
+68-79-12 (hex) Wingtech Mobile Communications Co., Ltd.\r
+A00000-AFFFFF (base 16) Wingtech Mobile Communications Co., Ltd.\r
+ No.777,Yazhong Road,Nanhu District,\r
+ Jiaxing Zhejiang 314006\r
+ CN\r
+\r
+68-79-12 (hex) Swisscom Broadcast Ltd\r
+B00000-BFFFFF (base 16) Swisscom Broadcast Ltd\r
+ Ostermundigenstrasse 99\r
+ Bern 3050\r
+ CH\r
+\r
+68-79-12 (hex) CNDI CO.,LTD\r
+200000-2FFFFF (base 16) CNDI CO.,LTD\r
+ 33-13, EUNHAENG-RO, 218 BEON-GIL\r
+ SIHEUNG-SI GYEONGGI-DO 14908\r
+ KR\r
+\r
+68-79-12 (hex) Copper Labs, Inc.\r
+500000-5FFFFF (base 16) Copper Labs, Inc.\r
+ 3015 Sterling Circle #200\r
+ Boulder CO 80301\r
+ US\r
+\r
+84-11-C2 (hex) Kazdream Technologies LLP\r
+000000-0FFFFF (base 16) Kazdream Technologies LLP\r
+ 10, Turkestan Str.\r
+ Nur-Sultan 010000\r
+ KZ\r
+\r
+8C-47-6E (hex) HuiZhou MIKI Communication Equipment Co.,LTD\r
+200000-2FFFFF (base 16) HuiZhou MIKI Communication Equipment Co.,LTD\r
+ NO.39,GuangTai Road HuiNan HI-techindustrial Park.Zhongkai Hi-tech Zone\r
+ Huizhou 516000\r
+ CN\r
+\r
+8C-47-6E (hex) Xertified AB\r
+900000-9FFFFF (base 16) Xertified AB\r
+ Horisontvagen 60\r
+ Stockholm Stockholm 12830\r
+ SE\r
+\r
+34-04-9E (hex) ClearCaptions LLC\r
+C00000-CFFFFF (base 16) ClearCaptions LLC\r
+ 595 Menlo Drive\r
+ Rocklin CA 95765\r
+ US\r
+\r
+8C-47-6E (hex) Chipsafer Pte. Ltd.\r
+000000-0FFFFF (base 16) Chipsafer Pte. Ltd.\r
+ 2 Changi South Lane\r
+ Singapore 486123\r
+ SG\r
+\r
+8C-AE-49 (hex) Gigawave\r
+A00000-AFFFFF (base 16) Gigawave\r
+ Unit 4 Metro Business Park, ballycurreen\r
+ cork T12 HP60\r
+ IE\r
+\r
+8C-AE-49 (hex) Chengdu BillDTE Technology Co., Ltd\r
+600000-6FFFFF (base 16) Chengdu BillDTE Technology Co., Ltd\r
+ Chengdu BiiDTE Technology Co.,Ltd\r
+ Chengdu Sichuan 610041\r
+ CN\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 DIEGO CA 92123\r
US\r
\r
-34-04-9E (hex) Private\r
-900000-9FFFFF (base 16) Private\r
-\r
38-B8-EB (hex) Private\r
700000-7FFFFF (base 16) Private\r
\r
Taipei City 10482\r
TW\r
\r
-24-15-10 (hex) Medicomp, Inc\r
-800000-8FFFFF (base 16) Medicomp, Inc\r
- \r
- \r
- \r
-\r
28-B7-7C (hex) Annapurna labs\r
400000-4FFFFF (base 16) Annapurna labs\r
Matam Scientific Industries Center, Building 8.2\r
Suzhou Jiangsu 215000\r
CN\r
\r
+58-20-8A (hex) Shangyin Intelligence Technology Shandong Co.,Ltd\r
+600000-6FFFFF (base 16) Shangyin Intelligence Technology Shandong Co.,Ltd\r
+ 2205,Building 2,Sanqingqisheng Square,No.1666,Xinluo Street\r
+ Jinan Shandong 250014\r
+ CN\r
+\r
+58-20-8A (hex) Annapurna labs\r
+000000-0FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+58-20-8A (hex) UPM Technology, Inc\r
+E00000-EFFFFF (base 16) UPM Technology, Inc\r
+ 3000 NE Stucki ave ste #100\r
+ Hillsboro 97124\r
+ US\r
+\r
+CC-4F-5C (hex) Kymati GmbH\r
+500000-5FFFFF (base 16) Kymati GmbH\r
+ Am Hochacker 5\r
+ Grasbrunn 85630\r
+ DE\r
+\r
+FC-CD-2F (hex) Loupedeck Oy\r
+200000-2FFFFF (base 16) Loupedeck Oy\r
+ Museokatu 8 A 6\r
+ Helsinki 00100\r
+ FI\r
+\r
+FC-CD-2F (hex) Aroma Retail\r
+900000-9FFFFF (base 16) Aroma Retail\r
+ 5525 S. Valley View Blvd, ste 2\r
+ Las Vegas NV 89118\r
+ US\r
+\r
+58-95-D8 (hex) Sercomm Corporation.\r
+200000-2FFFFF (base 16) Sercomm Corporation.\r
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen\r
+ Miao-Lih Hsuan 115\r
+ TW\r
+\r
+DC-4A-9E (hex) LEACH INTERNATIONAL EUROPE\r
+300000-3FFFFF (base 16) LEACH INTERNATIONAL EUROPE\r
+ 2 RUE GOETHE\r
+ SARRALBE MOSELLE 57430\r
+ FR\r
+\r
+DC-4A-9E (hex) LongSung Technology (Shanghai) Co.,Ltd. \r
+A00000-AFFFFF (base 16) LongSung Technology (Shanghai) Co.,Ltd. \r
+ Room 606, Block B, Bldg. 1, No. 3000 Longdong Avenue., Zhangjiang Hi-Tech Park, Pudong District\r
+ ShangHai 201203\r
+ CN\r
+\r
+DC-4A-9E (hex) Nuove Tecnologie srl\r
+500000-5FFFFF (base 16) Nuove Tecnologie srl\r
+ VIALE RIMEMBRANZE 47/B, VAT N° IT10907840150\r
+ Lainate Milan 20045\r
+ IT\r
+\r
+DC-4A-9E (hex) AiSight GmbH\r
+900000-9FFFFF (base 16) AiSight GmbH\r
+ Gertraudenstr 10-12\r
+ Berlin 10178\r
+ DE\r
+\r
+84-11-C2 (hex) Leybold GmbH\r
+800000-8FFFFF (base 16) Leybold GmbH\r
+ Bonnerstr. 498\r
+ Cologne 50968\r
+ DE\r
+\r
+68-79-12 (hex) Globus Infocom Limited\r
+C00000-CFFFFF (base 16) Globus Infocom Limited\r
+ A 65, Sector 4, Noida\r
+ Noida U P 201301\r
+ IN\r
+\r
+68-79-12 (hex) Babbit and Friends, SIA\r
+700000-7FFFFF (base 16) Babbit and Friends, SIA\r
+ Maiznicas iela 8 - 5\r
+ Riga Riga LV1001\r
+ LV\r
+\r
+68-79-12 (hex) Ametek Solidstate Controls\r
+E00000-EFFFFF (base 16) Ametek Solidstate Controls\r
+ 875 DEARBORN DR\r
+ COLUMBUS OH 43085-1586\r
+ US\r
+\r
+68-79-12 (hex) LEAPS s.r.o.\r
+900000-9FFFFF (base 16) LEAPS s.r.o.\r
+ Na rolich 655/8\r
+ Praha 4 Czech 141 00\r
+ CZ\r
+\r
+8C-47-6E (hex) AU Optronics Corporation\r
+A00000-AFFFFF (base 16) AU Optronics Corporation\r
+ No. 1 Li-Hsin Rd. 2, Hsinchu Science Park\r
+ Hsinchu 30078, Taiwan, R.O.C. 802\r
+ TW\r
+\r
+8C-47-6E (hex) IntelliVIX Co. Ltd.\r
+800000-8FFFFF (base 16) IntelliVIX Co. Ltd.\r
+ 4, Hyoryeong-ro 34-gil, Seocho-gu\r
+ Seoul 06704\r
+ KR\r
+\r
+24-15-10 (hex) Private\r
+800000-8FFFFF (base 16) Private\r
+ \r
+ \r
+ \r
+\r
+34-04-9E (hex) Church & Dwight Co., Inc.\r
+900000-9FFFFF (base 16) Church & Dwight Co., Inc.\r
+ 500 Charles Ewing Blvd\r
+ Ewing NJ 08628\r
+ US\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
santa clara CA 95050\r
US\r
\r
-58-E8-76 (hex) Private\r
-000000-0FFFFF (base 16) Private\r
-\r
30-09-F9 (hex) Beijing Mydreamplus Information Technology Co., Ltd.\r
600000-6FFFFF (base 16) Beijing Mydreamplus Information Technology Co., Ltd.\r
Room 301-2, North Building, No. 11, CangJingGuan Lane, DongCheng District,\r
Richmond Hill ON L4B 2N1\r
CA\r
\r
+58-20-8A (hex) Aggregate Co.,Ltd.\r
+300000-3FFFFF (base 16) Aggregate Co.,Ltd.\r
+ Toso Building 4F, 1-9-8 Yayoi-cho\r
+ nakano-ku tokyo 164-0013\r
+ JP\r
+\r
18-FD-CB (hex) Gosuncn Technology Group Co.,LTD.\r
400000-4FFFFF (base 16) Gosuncn Technology Group Co.,LTD.\r
6F,2819 KaiChuang Blvd.,Science Town,Huangpu District\r
Guangzhou City Guangdong 510530\r
CN\r
\r
+58-20-8A (hex) MARS DIGI TECH CO .,LTD\r
+200000-2FFFFF (base 16) MARS DIGI TECH CO .,LTD\r
+ RM 2314,Build No.B2,GuiMiao Road,NanShan District\r
+ ShenZhen Guangdong 518054\r
+ CN\r
+\r
+58-20-8A (hex) pureLiFi Ltd\r
+700000-7FFFFF (base 16) pureLiFi Ltd\r
+ Rosebery House, 9 Haymarket Terrace\r
+ Edinburgh EH12 5EZ\r
+ GB\r
+\r
+CC-4F-5C (hex) Feelmore Labs\r
+800000-8FFFFF (base 16) Feelmore Labs\r
+ 370 Jay Street, Floor 7\r
+ Brooklyn NY 11201\r
+ US\r
+\r
+FC-CD-2F (hex) HEAD-DIRECT (KUNSHAN) Co. Ltd\r
+B00000-BFFFFF (base 16) HEAD-DIRECT (KUNSHAN) Co. Ltd\r
+ Kunshan Bacheng West Yingbing Rd. shangkunzhichuang chanyeyuan C2#\r
+ Suzhou Jiangsu 215311\r
+ CN\r
+\r
+58-E8-76 (hex) Zhuhai Raysharp Technology Co.,Ltd\r
+000000-0FFFFF (base 16) Zhuhai Raysharp Technology Co.,Ltd\r
+ No.100 of Keji Liu Rd.6, Hi-Tech Zone\r
+ Zhuhai Guangdong 519080\r
+ CN\r
+\r
+FC-CD-2F (hex) Asesorias y Servicios Innovaxxion SPA\r
+800000-8FFFFF (base 16) Asesorias y Servicios Innovaxxion SPA\r
+ Alonso de Cordova 5320, of 1403, Las condes\r
+ Santiago RM 7550000\r
+ CL\r
+\r
+FC-CD-2F (hex) Annapurna labs\r
+600000-6FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+FC-CD-2F (hex) Suzhou lehui display co.,ltd\r
+700000-7FFFFF (base 16) Suzhou lehui display co.,ltd\r
+ ?225 Jinfeng Road?Suzhou New District?Jiangsu Province\r
+ suzhou 215129\r
+ CN\r
+\r
+58-95-D8 (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
+58-95-D8 (hex) Tonnet Telecommunication International Co., Ltd.\r
+300000-3FFFFF (base 16) Tonnet Telecommunication International Co., Ltd.\r
+ 10F,No.6,Ln.609,Sec.5 Chongxin Rd., Sanchong Dist.\r
+ New Taipei 241\r
+ TW\r
+\r
+FC-CD-2F (hex) Eltek brojila d.o.o.\r
+E00000-EFFFFF (base 16) Eltek brojila d.o.o.\r
+ Svetice 24\r
+ Zagreb 10000\r
+ HR\r
+\r
+58-95-D8 (hex) Gmv sistemas SAU\r
+E00000-EFFFFF (base 16) Gmv sistemas SAU\r
+ C/ Juan Herrera 17 P.T.B. ,Parcela 101\r
+ Boecillo Valladolid 47151 \r
+ ES\r
+\r
+58-95-D8 (hex) Unity Surveillance, Inc.\r
+400000-4FFFFF (base 16) Unity Surveillance, Inc.\r
+ 629 East Grand Ave\r
+ Hot Springs National Park AR 71901\r
+ US\r
+\r
+DC-4A-9E (hex) ADIAL\r
+400000-4FFFFF (base 16) ADIAL\r
+ 87 Rue Alexandre Fleming\r
+ LISIEUX 14100\r
+ FR\r
+\r
+DC-4A-9E (hex) Advanced Electronics Ltd\r
+100000-1FFFFF (base 16) Advanced Electronics Ltd\r
+ Balliol Business Park\r
+ Newcastle NE12 8EW\r
+ GB\r
+\r
+DC-4A-9E (hex) HEFEI DATANG STORAGE TECHNOLOGY CO.,LTD\r
+C00000-CFFFFF (base 16) HEFEI DATANG STORAGE TECHNOLOGY CO.,LTD\r
+ 7F BLOCK C J2 BUILDING INNOVATION PARK HIGH TECH DISTRICT\r
+ HEFEI AN HUI PROVINCE PR CHINA 220038\r
+ CN\r
+\r
+DC-4A-9E (hex) SES-imagotag Deutschland GmbH\r
+E00000-EFFFFF (base 16) SES-imagotag Deutschland GmbH\r
+ Bundesstrasse 16\r
+ Ettenheim BW 77955\r
+ DE\r
+\r
+84-11-C2 (hex) KESSEL AG\r
+600000-6FFFFF (base 16) KESSEL AG\r
+ Bahnhofstraße 31\r
+ Lenting 85101\r
+ DE\r
+\r
+84-11-C2 (hex) igus GmbH\r
+A00000-AFFFFF (base 16) igus GmbH\r
+ Spicher Str. 1a\r
+ Köln 51147\r
+ DE\r
+\r
+68-79-12 (hex) Neurolab\r
+D00000-DFFFFF (base 16) Neurolab\r
+ Naberezhnaya Shlyuzovaya, d. 6, str. 3, et. 3, pom. 1\r
+ Moscow - 115114\r
+ RU\r
+\r
+68-79-12 (hex) Annapurna labs\r
+100000-1FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+68-79-12 (hex) McDonald's Corporation\r
+400000-4FFFFF (base 16) McDonald's Corporation\r
+ 110 N. Carpenter Street\r
+ Chicago 60607\r
+ US\r
+\r
+8C-47-6E (hex) Oxford Nanopore Technologies Ltd.\r
+600000-6FFFFF (base 16) Oxford Nanopore Technologies Ltd.\r
+ Gosling Building, Edmund Halley Road, Oxford Science Park\r
+ Oxford Oxfordshire OX4 4DQ\r
+ GB\r
+\r
+8C-47-6E (hex) innolectric AG\r
+D00000-DFFFFF (base 16) innolectric AG\r
+ Universitaetsstr. 136\r
+ Bochum 44799 \r
+ DE\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
Los Gatos CA 95032\r
US\r
\r
-20-85-93 (hex) Private\r
-900000-9FFFFF (base 16) Private\r
-\r
24-15-10 (hex) Topgolf Sweden AB\r
900000-9FFFFF (base 16) Topgolf Sweden AB\r
Svärdvägen 11\r
Huizhou Guangdong 516223\r
CN\r
\r
+58-20-8A (hex) SAMBO HITECH\r
+D00000-DFFFFF (base 16) SAMBO HITECH\r
+ 469,Seokjung-ro,Namdong-Gu\r
+ Incheon 21501\r
+ KR\r
+\r
18-FD-CB (hex) Accel Robotics\r
500000-5FFFFF (base 16) Accel Robotics\r
9160 KEARNY VILLA CT\r
San Diego CA 92123\r
US\r
\r
+58-20-8A (hex) Infodev Electronic Designers Intl.\r
+B00000-BFFFFF (base 16) Infodev Electronic Designers Intl.\r
+ 1995 rue Frank-Carrel Suite 202\r
+ Quebec Quebec G1N4H9\r
+ CA\r
+\r
+58-20-8A (hex) Conductix-Wampfler\r
+A00000-AFFFFF (base 16) Conductix-Wampfler\r
+ 10102 Fst\r
+ omaha NE 68127\r
+ US\r
+\r
+58-20-8A (hex) JIA HUANG JHAN YE CO.,LTD\r
+500000-5FFFFF (base 16) JIA HUANG JHAN YE CO.,LTD\r
+ 1F., No. 19, Huanmei 2nd St., Donggang Township\r
+ Plngtung County 928\r
+ TW\r
+\r
+CC-4F-5C (hex) MatchX GmbH\r
+200000-2FFFFF (base 16) MatchX GmbH\r
+ Adalbert Str.8\r
+ Berlin 10999\r
+ DE\r
+\r
+FC-CD-2F (hex) SCOPUS INTERNATIONAL-BELGIUM\r
+A00000-AFFFFF (base 16) SCOPUS INTERNATIONAL-BELGIUM\r
+ Cable Centre, Raja International Building, \r
+ Andamukkam, Kollam Kerala 691 001\r
+ IN\r
+\r
+58-95-D8 (hex) Epiphan Systems Inc\r
+700000-7FFFFF (base 16) Epiphan Systems Inc\r
+ 400 March Rd Suite 510\r
+ Ottawa Ontario K2K3H4\r
+ CA\r
+\r
+FC-CD-2F (hex) Spedos ADS a.s.\r
+C00000-CFFFFF (base 16) Spedos ADS a.s.\r
+ Hranická771\r
+ Valašské Mezi?í?í 75701\r
+ CZ\r
+\r
+58-95-D8 (hex) SuZhou Ruishengwei Intelligent Technology Co.,Ltd\r
+B00000-BFFFFF (base 16) SuZhou Ruishengwei Intelligent Technology Co.,Ltd\r
+ Room 507?Building 1?ZhongXuXin Science Park?NO.91?Weixin Road?Suzhou Industrial Park\r
+ SuZhou JiangSu 215021\r
+ CN\r
+\r
+58-95-D8 (hex) Alunos AG\r
+D00000-DFFFFF (base 16) Alunos AG\r
+ Zugerstrasse\r
+ Unteraegeri 6314\r
+ CH\r
+\r
+20-85-93 (hex) Mastodon Design\r
+900000-9FFFFF (base 16) Mastodon Design\r
+ 176 Anderson Ave, Suite F112\r
+ Rochester NY 14607\r
+ US\r
+\r
+DC-4A-9E (hex) Dongguan Huili electroacoustic Industrial Co.,ltd\r
+000000-0FFFFF (base 16) Dongguan Huili electroacoustic Industrial Co.,ltd\r
+ Dalang Town, Biyun Cai Bai Cun East Second Street 66,A4 Building 501\r
+ Dongguan Guangdong 523770\r
+ CN\r
+\r
+84-11-C2 (hex) Guangdong Creator&Flyaudio Electronic Technology Co.,LTD\r
+B00000-BFFFFF (base 16) Guangdong Creator&Flyaudio Electronic Technology Co.,LTD\r
+ Block D1, No.3 Industrial Zone, Banxianshan, Hengli Town\r
+ Dongguan Guangdong 523460\r
+ CN\r
+\r
+84-11-C2 (hex) C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.\r
+900000-9FFFFF (base 16) C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.\r
+ Teknopark ?stanbul, TGB, Sanayi Mah. Teknopark Bulvar?, No:1, Blok:1 Kat:2, Kurtköy-Pendik 34912, ?STANBUL\r
+ Istanbul 34912\r
+ TR\r
+\r
+84-11-C2 (hex) Beijing Dayu Technology Co., Ltd.\r
+100000-1FFFFF (base 16) Beijing Dayu Technology Co., Ltd.\r
+ 11B-660, Building 13, Wangjing Xiyuan, Chaoyang\r
+ Beijing 100000\r
+ CN\r
+\r
+84-11-C2 (hex) Hitachi,Ltd.\r
+300000-3FFFFF (base 16) Hitachi,Ltd.\r
+ 2-1,Shintoyofuta\r
+ Kashiwa-shi Chiba 277-0804\r
+ JP\r
+\r
+84-11-C2 (hex) Dangerous Music Group, LLC\r
+E00000-EFFFFF (base 16) Dangerous Music Group, LLC\r
+ 701 South Mountain Road\r
+ New City NY 10956\r
+ US\r
+\r
+8C-47-6E (hex) Private\r
+700000-7FFFFF (base 16) Private\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
Vienna 1210\r
AT\r
\r
+58-20-8A (hex) SAMIL CTS Co., Ltd.\r
+800000-8FFFFF (base 16) SAMIL CTS Co., Ltd.\r
+ 8F, Woolim Lion's Valley 3cha, 24 Dunchon Daero 388beon-gil, Jungwon-gu\r
+ Seongnam-si Gyeonggi-do, KOREA 13403\r
+ KR\r
+\r
18-FD-CB (hex) ENERGIE IP\r
700000-7FFFFF (base 16) ENERGIE IP\r
48 rue du Château d’eau \r
Paris Ile-de-France 75010\r
FR\r
\r
-58-20-8A (hex) SAMIL CTS Co., Ltd.\r
-800000-8FFFFF (base 16) SAMIL CTS Co., Ltd.\r
- 8F, Woolim Lion's Valley 3cha, 24 Dunchon Daero 388beon-gil, Jungwon-gu\r
- Seongnam-si Gyeonggi-do, KOREA 13403\r
- KR\r
+CC-4F-5C (hex) Shanghai Zenchant Electornics Co.,LTD\r
+300000-3FFFFF (base 16) Shanghai Zenchant Electornics Co.,LTD\r
+ Room 1202, building a, Noble international, 908 Xiuwen Road, Minhang District\r
+ ShangHai ShangHai 201199\r
+ CN\r
+\r
+CC-4F-5C (hex) Dtrovision\r
+900000-9FFFFF (base 16) Dtrovision\r
+ 22-10 STATE RT 208\r
+ Fair Lawn NJ 07410\r
+ US\r
+\r
+CC-4F-5C (hex) AZ-TECHNOLOGY SDN BHD\r
+A00000-AFFFFF (base 16) AZ-TECHNOLOGY SDN BHD\r
+ A108 & A109 BLOCK A KELANA BUSINESS CENTRE NO: 97 JALAN SS7/2 KELANA JAYA\r
+ PETALING JAYA SELANGOR 47301\r
+ MY\r
+\r
+CC-4F-5C (hex) Buttons (Beijing) Technology Limited\r
+E00000-EFFFFF (base 16) Buttons (Beijing) Technology Limited\r
+ Room 202, Floor 2, Building No. 3, No. 9 Xiaoying Road, Chaoyang District\r
+ Beijing 100101\r
+ CN\r
+\r
+FC-CD-2F (hex) Shenzhen Smartbyte Technology Co., Ltd.\r
+D00000-DFFFFF (base 16) Shenzhen Smartbyte Technology Co., Ltd.\r
+ 6th Floor, Building D, Huiqing Science and Technology Park, No. 8 Dafu Industrial Zone, Guanlan Street, Longhua District, Shenzhen\r
+ shenzhen guangdong 518110\r
+ CN\r
+\r
+FC-CD-2F (hex) Siren Care(Shanghai) information and technology company\r
+100000-1FFFFF (base 16) Siren Care(Shanghai) information and technology company\r
+ Room 205, Floor 2, B Zone, Building 2, No 1899, Jiahao Rd, Jiading\r
+ Shanghai 201802\r
+ CN\r
+\r
+FC-CD-2F (hex) Xmitech Technology Co., Limited\r
+300000-3FFFFF (base 16) Xmitech Technology Co., Limited\r
+ RM888, F8,Tower B,Xinnengyuan Building\r
+ shenzhen 518054\r
+ CN\r
+\r
+FC-CD-2F (hex) Genitek Engineering sprl\r
+400000-4FFFFF (base 16) Genitek Engineering sprl\r
+ Rue Edouard Belin, 5\r
+ Mont-Saint-Guibert 1435\r
+ BE\r
+\r
+58-95-D8 (hex) shenzhen UDD Technologies,co.,Ltd\r
+100000-1FFFFF (base 16) shenzhen UDD Technologies,co.,Ltd\r
+ Unit D, 6th Floor, Jialitai Bldg., No.45 Yanshan Road, Shekou, Nanshan District, Shenzhen, China\r
+ shenzhen guangdong 51800\r
+ CN\r
+\r
+58-95-D8 (hex) elgris UG\r
+500000-5FFFFF (base 16) elgris UG\r
+ Langerweher Str. 10\r
+ Inden Deutschland 52459\r
+ DE\r
+\r
+CC-4F-5C (hex) Beijing Neutron Technology CO.,LTD.\r
+D00000-DFFFFF (base 16) Beijing Neutron Technology CO.,LTD.\r
+ Beijing Neutron Technology CO.,LTD. \r
+ Beijing Beijing 100193\r
+ CN\r
+\r
+DC-4A-9E (hex) Maxvision Technology Corp.\r
+B00000-BFFFFF (base 16) Maxvision Technology Corp.\r
+ 16F,East Block,High-tech Plaza Phase II,Tianan Cyber Park,Futian District,Shenzhen.\r
+ Shenzhen. 518000\r
+ CN\r
+\r
+DC-4A-9E (hex) Annapurna labs\r
+200000-2FFFFF (base 16) Annapurna labs\r
+ Matam Scientific Industries Center, Building 8.2\r
+ Mail box 15123 Haifa 3508409\r
+ IL\r
+\r
+84-11-C2 (hex) Provision-ISR\r
+C00000-CFFFFF (base 16) Provision-ISR\r
+ 11 Atir Yeda St.\r
+ Kfar Saba Israel 4464310\r
+ IL\r
+\r
+84-11-C2 (hex) Goldmund Switzerland\r
+D00000-DFFFFF (base 16) Goldmund Switzerland\r
+ Chemin Grenet 21, 1214\r
+ Vernier Geneva 1214\r
+ CH\r
+\r
+84-11-C2 (hex) AIBIoT GmbH\r
+500000-5FFFFF (base 16) AIBIoT GmbH\r
+ Hornemannstr. 12\r
+ Hildesheim Lower Saxony 31137\r
+ DE\r
+\r
+84-11-C2 (hex) Ei3 Corporation\r
+700000-7FFFFF (base 16) Ei3 Corporation\r
+ 2 Blue Hill Plaza, Ste 1544\r
+ Pearl River NY 10965\r
+ US\r
+\r
+68-79-12 (hex) Stephan Electronics SARL\r
+300000-3FFFFF (base 16) Stephan Electronics SARL\r
+ Maupas 9\r
+ Lausanne 1004\r
+ CH\r
+\r
+68-79-12 (hex) ShangHai Aigentoo Information Technology Co., Ltd\r
+800000-8FFFFF (base 16) ShangHai Aigentoo Information Technology Co., Ltd\r
+ Room 1126,Building 1,Xin Ye Building,388 Tianlin Road,Xuhui District\r
+ Shanghai 200080\r
+ CN\r
+\r
+68-79-12 (hex) APPOTRONICS CO., LTD\r
+600000-6FFFFF (base 16) APPOTRONICS CO., LTD\r
+ 4th Floor,SZICC,NO.1089,Chaguang Road,Nanshan District, Shenzhen, China\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+68-79-12 (hex) PCTEL, Inc.\r
+000000-0FFFFF (base 16) PCTEL, Inc.\r
+ 471 Brighton Drive\r
+ Bloomingdale IL 60108\r
+ US\r
+\r
+8C-47-6E (hex) Shanghai Satellite Communication Technology Co.,Ltd\r
+300000-3FFFFF (base 16) Shanghai Satellite Communication Technology Co.,Ltd\r
+ Shanghai Satellite Communication Technology Co.,Ltd\r
+ Shanghai Shanghai 201800\r
+ CN\r
+\r
+8C-47-6E (hex) Square Inc.\r
+500000-5FFFFF (base 16) Square Inc.\r
+ 1455 Market St.\r
+ San Francisco CA 94103\r
+ US\r
+\r
+8C-47-6E (hex) Faravid Communication&Data Analysis\r
+B00000-BFFFFF (base 16) Faravid Communication&Data Analysis\r
+ 18th unit, No.2, Houman Alley Abbaspour Av., \r
+ Vanak Sq. Tehran 1435633413\r
+ IR\r
+\r
+8C-47-6E (hex) Edge Networks Inc\r
+C00000-CFFFFF (base 16) Edge Networks Inc\r
+ 943 W. Overland Road, Suite 152\r
+ Meridian ID 83642\r
+ US\r
+\r
+8C-47-6E (hex) TelWare Corporation\r
+100000-1FFFFF (base 16) TelWare Corporation\r
+ 1824 Industrial Center Circle\r
+ Charlotte NC 28213\r
+ US\r
+\r
+8C-47-6E (hex) Shenzhen Juding Electronics Co., Ltd.\r
+400000-4FFFFF (base 16) Shenzhen Juding Electronics Co., Ltd.\r
+ 5th Floor, Building B5, Fenghuanggang Third Industrial Zone, No.231, Baotian 1st Road, Baoan District\r
+ Shenzhen Guangdong 518100\r
+ CN\r
+\r
+8C-47-6E (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
Buchlovice 68708\r
CZ\r
\r
-70-B3-D5 (hex) C Tech Bilişim Teknolojileri San. ve Tic. AŞ\r
-DCD000-DCDFFF (base 16) C Tech Bilişim Teknolojileri San. ve Tic. AŞ\r
- Teknopark İstanbul, TGB, Sanayi Mah. Teknopark Bulvarı, No:1, Blok:1 Kat:2, Kurtköy-Pendik 34912, İSTANBUL\r
- Istanbul 34912\r
- TR\r
-\r
70-B3-D5 (hex) BRS Sistemas Eletrônicos\r
356000-356FFF (base 16) BRS Sistemas Eletrônicos\r
Rua Gomes de Freitas, 491 / 204\r
Miami FL 33131\r
US\r
\r
-70-B3-D5 (hex) GRIDSMART Technologies\r
-7EC000-7ECFFF (base 16) GRIDSMART Technologies\r
- 10545 Hardin Valley Rd\r
- Knoxville TN 37932\r
- US\r
-\r
70-B3-D5 (hex) ChamSys Ltd\r
0BE000-0BEFFF (base 16) ChamSys Ltd\r
Unit 3B Richmond Works, Pitt Road\r
Neusaess Bayern 85356\r
DE\r
\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-261000-261FFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
70-B3-D5 (hex) Shangnuo company\r
82B000-82BFFF (base 16) Shangnuo company\r
Nong'an district\r
Menlo Park 94025\r
US\r
\r
+70-B3-D5 (hex) ABL Space Systems\r
+F7F000-F7FFFF (base 16) ABL Space Systems\r
+ 224 Oregon St\r
+ El Segundo CA 90245\r
+ US\r
+\r
+70-B3-D5 (hex) DUEVI SRL\r
+F41000-F41FFF (base 16) DUEVI SRL\r
+ VIA BARD 12/A\r
+ TORINO TORINO 10142\r
+ IT\r
+\r
+70-B3-D5 (hex) Daifuku CO., Ltd.\r
+3A2000-3A2FFF (base 16) Daifuku CO., Ltd.\r
+ 1225 Nakazaiji, Hino-cho, Gamo-gun, Shiga\r
+ Gamo-gun Shiga-ken 529-1692\r
+ JP\r
+\r
+70-B3-D5 (hex) CLARESYS LIMITED\r
+485000-485FFF (base 16) CLARESYS LIMITED\r
+ 154E Brook Drive, Milton Park\r
+ Abingdon OX14 4SD\r
+ GB\r
+\r
+70-B3-D5 (hex) Elmeasure India Pvt Ltd\r
+93D000-93DFFF (base 16) Elmeasure India Pvt Ltd\r
+ No.47-P, KIADB Hardware Park, Huvinayakanahalli\r
+ Bengaluru Karnataka 562149\r
+ IN\r
+\r
+70-B3-D5 (hex) Panamera\r
+7B1000-7B1FFF (base 16) Panamera\r
+ Rua. Dr. Brasilio Vicente de Castro, 111\r
+ Critiba Parana 81200-526\r
+ BR\r
+\r
+70-B3-D5 (hex) QUNU LABS PRIVATE LIMITED\r
+9A6000-9A6FFF (base 16) QUNU LABS PRIVATE LIMITED\r
+ Centenary Building, 2nd Floor,, East Wing, No. 28 M.G. Road\r
+ BANGALORE KARNATAKA 560025\r
+ IN\r
+\r
+70-B3-D5 (hex) ALTIT.CO.,Ltd.\r
+552000-552FFF (base 16) ALTIT.CO.,Ltd.\r
+ Gasan Digital 1 ro 88, 1905\r
+ Seoul Korea 08590\r
+ KR\r
+\r
+70-B3-D5 (hex) Harman Connected Services Corporation India Pvt. Ltd.\r
+423000-423FFF (base 16) Harman Connected Services Corporation India Pvt. Ltd.\r
+ Plot No 3 & 3A, EOIZ Industrial Area, Sy.No.85 and 86, KIADB, Whitefield,\r
+ Bengaluru Karnataka 560066\r
+ IN\r
+\r
+70-B3-D5 (hex) Galaxy Next Generation, Inc.\r
+E1D000-E1DFFF (base 16) Galaxy Next Generation, Inc.\r
+ 285 Big A Rd \r
+ Toccoa GA 30577\r
+ US\r
+\r
+70-B3-D5 (hex) Gigaband IP LLC\r
+E9F000-E9FFFF (base 16) Gigaband IP LLC\r
+ 85 N Brookside St\r
+ Chandler AZ 85225\r
+ US\r
+\r
+70-B3-D5 (hex) Intrinsic Group Limited\r
+663000-663FFF (base 16) Intrinsic Group Limited\r
+ The Maltings\r
+ Allendale Northumberland NE47 9EE\r
+ GB\r
+\r
+70-B3-D5 (hex) Barcelona Smart Technologies\r
+D5E000-D5EFFF (base 16) Barcelona Smart Technologies\r
+ C/Joaquim Molins 5\r
+ Barcelona Catalunya 08028\r
+ ES\r
+\r
+70-B3-D5 (hex) C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.\r
+DCD000-DCDFFF (base 16) C TECH BILISIM TEKNOLOJILERI SAN. VE TIC. A.S.\r
+ Teknopark İstanbul, TGB, Sanayi Mah. Teknopark Bulvarı, No:1, Blok:1 Kat:2, Kurtköy-Pendik 34912, İSTANBUL\r
+ Istanbul 34912\r
+ TR\r
+\r
+70-B3-D5 (hex) TableConnect GmbH\r
+7BD000-7BDFFF (base 16) TableConnect GmbH\r
+ Schlossgasse 13/2/3\r
+ Vienna Vienna 1050\r
+ AT\r
+\r
+70-B3-D5 (hex) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+7EC000-7ECFFF (base 16) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+ 10545 Hardin Valley Rd\r
+ Knoxville TN 37932\r
+ US\r
+\r
+70-B3-D5 (hex) Eldes Ltd\r
+8B6000-8B6FFF (base 16) Eldes Ltd\r
+ Ukmerges 283b\r
+ Vilnius LT-06313\r
+ LT\r
+\r
+70-B3-D5 (hex) Foerster-Technik GmbH\r
+453000-453FFF (base 16) Foerster-Technik GmbH\r
+ Gerwigstraße 25\r
+ Engen Baden-Württemberg 78234\r
+ DE\r
+\r
+70-B3-D5 (hex) BTG Instruments AB\r
+D85000-D85FFF (base 16) BTG Instruments AB\r
+ Industrigatan 1-3\r
+ Saffle Varmland 66132\r
+ SE\r
+\r
+70-B3-D5 (hex) Circle Consult ApS\r
+23D000-23DFFF (base 16) Circle Consult ApS\r
+ Rundforbivej 271A\r
+ Naerum 2850\r
+ DK\r
+\r
+70-B3-D5 (hex) CreevX\r
+BF4000-BF4FFF (base 16) CreevX\r
+ 158A Staffordstown Rd\r
+ Randalstown Antrim BT41 3LH\r
+ GB\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+261000-261FFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Velvac Incorporated\r
+44F000-44FFFF (base 16) Velvac Incorporated\r
+ 2405 S. Calhoun Road\r
+ New Berlin WI 53151-2709\r
+ US\r
+\r
+70-B3-D5 (hex) Connido Limited\r
+71D000-71DFFF (base 16) Connido Limited\r
+ 35 Kingsland Road\r
+ London E2 8AA\r
+ GB\r
+\r
70-B3-D5 (hex) EVCO SPA\r
A80000-A80FFF (base 16) EVCO SPA\r
VIA FELTRE N. 81\r
Meersburg 88709\r
DE\r
\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-1BE000-1BEFFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-B9A000-B9AFFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
70-B3-D5 (hex) ABECO Industrie Computer GmbH\r
F02000-F02FFF (base 16) ABECO Industrie Computer GmbH\r
Industriestrasse 2\r
Straelen NRW 47638\r
DE\r
\r
+70-B3-D5 (hex) Abbott Diagnostics Technologies AS\r
+DDE000-DDEFFF (base 16) Abbott Diagnostics Technologies AS\r
+ P. O. Box 6863 Rodeløkka\r
+ Oslo Oslo 0504\r
+ NO\r
+\r
70-B3-D5 (hex) PuS GmbH und Co. KG\r
09D000-09DFFF (base 16) PuS GmbH und Co. KG\r
Hainstr. 13\r
Taipei 114\r
TW\r
\r
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd\r
+B22000-B22FFF (base 16) YUYAMA MFG Co.,Ltd\r
+ 1-4-30\r
+ MEISHINGUCHI,TOYONAKA OSAKA 561-0841\r
+ JP\r
+\r
+70-B3-D5 (hex) Laser Imagineering Vertriebs GmbH\r
+3EE000-3EEFFF (base 16) Laser Imagineering Vertriebs GmbH\r
+ Rudolf-Diesel-Weg 5\r
+ Moelln 23879\r
+ DE\r
+\r
+70-B3-D5 (hex) Guan Show Technologe Co., Ltd.\r
+1BA000-1BAFFF (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) Serveron / Qualitrol\r
+B1C000-B1CFFF (base 16) Serveron / Qualitrol\r
+ 13550 SW Karl Braun Drive\r
+ Beaverton OR 97005\r
+ US\r
+\r
+70-B3-D5 (hex) Gentec\r
+83D000-83DFFF (base 16) Gentec\r
+ 2625 Dalton\r
+ Quebec G1P 3S9\r
+ CA\r
+\r
+70-B3-D5 (hex) Xirgo Technologies LLC\r
+1A2000-1A2FFF (base 16) Xirgo Technologies LLC\r
+ 188 Camino Ruiz\r
+ Camarillo CA 93012\r
+ US\r
+\r
+70-B3-D5 (hex) HAN CHANG\r
+859000-859FFF (base 16) HAN CHANG\r
+ 171, Gasan digital 1-ro, Geumcheon-gu, Seoul, Republic of Korea\r
+ Seoul Geumcheon-gu, Seoul 08503\r
+ KR\r
+\r
+70-B3-D5 (hex) Daatrics LTD\r
+B69000-B69FFF (base 16) Daatrics LTD\r
+ 4th Floor, 86-90 Paul Street\r
+ LONDON EC2A 4NE\r
+ GB\r
+\r
+70-B3-D5 (hex) Guangdong Transtek Medical Electronics Co., Ltd.\r
+8D4000-8D4FFF (base 16) Guangdong Transtek Medical Electronics Co., Ltd.\r
+ Zone A, No.105, Dongli Road, Torch Development District\r
+ Zhongshan Guangdong 528437\r
+ CN\r
+\r
+70-B3-D5 (hex) Williams Sound LLC\r
+58B000-58BFFF (base 16) Williams Sound LLC\r
+ 10300 Valley View Road\r
+ Eden Prairie MN 55344\r
+ US\r
+\r
+70-B3-D5 (hex) BrainboxAI Inc\r
+E44000-E44FFF (base 16) BrainboxAI Inc\r
+ 2075 boul Robert-Bourassa, Suite 500\r
+ MONTREAL QUEBEC H3A 2L1\r
+ CA\r
+\r
+70-B3-D5 (hex) Cardinal Kinetic\r
+09C000-09CFFF (base 16) Cardinal Kinetic\r
+ 2748 Circleport Drive\r
+ Erlanger KY 41018\r
+ US\r
+\r
+70-B3-D5 (hex) Sicon srl\r
+6C8000-6C8FFF (base 16) Sicon srl\r
+ Via Sila 1/3\r
+ Isola Vicentina Vicenza 36033\r
+ IT\r
+\r
+70-B3-D5 (hex) Private\r
+A31000-A31FFF (base 16) Private\r
+\r
+70-B3-D5 (hex) Clockwork Dog\r
+5D7000-5D7FFF (base 16) Clockwork Dog\r
+ 43 Philpot Street\r
+ London E1 2JH\r
+ GB\r
+\r
+70-B3-D5 (hex) SUN ELECTRONICS CO.,LTD.\r
+D82000-D82FFF (base 16) SUN ELECTRONICS CO.,LTD.\r
+ 667-2,Furugori,Misato-machi,Kodama-gun\r
+ Saitama-ken 367-0111\r
+ JP\r
+\r
+70-B3-D5 (hex) BIRTECH TECHNOLOGY\r
+E65000-E65FFF (base 16) BIRTECH TECHNOLOGY\r
+ Ak is Business Center, Tuzla, Istanbul / Turkey\r
+ Istanbul Tuzla 34944\r
+ TR\r
+\r
+70-B3-D5 (hex) Transit Solutions, LLC.\r
+E68000-E68FFF (base 16) Transit Solutions, LLC.\r
+ 114 West Grandview Avenue\r
+ Zelienople PA 16063\r
+ US\r
+\r
+70-B3-D5 (hex) Nuance Hearing Ltd.\r
+35B000-35BFFF (base 16) Nuance Hearing Ltd.\r
+ Raoul Wallenberg 24, Building A1, Floor 3\r
+ Tel Aviv 6971920\r
+ IL\r
+\r
+70-B3-D5 (hex) xTom GmbH\r
+8B5000-8B5FFF (base 16) xTom GmbH\r
+ Kreuzstr.60\r
+ Duesseldorf NRW 40210\r
+ DE\r
+\r
+70-B3-D5 (hex) E-Controls\r
+6E2000-6E2FFF (base 16) E-Controls\r
+ PASSATGE GARROTXA, 6\r
+ SANT BOI DE LLOBREGAT 08830\r
+ ES\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+B9A000-B9AFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+1BE000-1BEFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Integrated Protein Technologies, Inc.\r
+FAC000-FACFFF (base 16) Integrated Protein Technologies, Inc.\r
+ PO box 1839\r
+ Evanston IL 60204\r
+ US\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
Daejeon 34016\r
KR\r
\r
-70-B3-D5 (hex) Private\r
-A03000-A03FFF (base 16) Private\r
-\r
70-B3-D5 (hex) Insitu Inc.\r
D36000-D36FFF (base 16) Insitu Inc.\r
901 E Bingen Point Way\r
70-B3-D5 (hex) Private\r
591000-591FFF (base 16) Private\r
\r
-70-B3-D5 (hex) Private\r
-376000-376FFF (base 16) Private\r
-\r
00-1B-C5 (hex) Corporate Systems Engineering \r
015000-015FFF (base 16) Corporate Systems Engineering \r
1215 Brookville Way\r
Three Rivers MI 49093\r
US\r
\r
-70-B3-D5 (hex) Private\r
-738000-738FFF (base 16) Private\r
-\r
70-B3-D5 (hex) Ya Batho Trading (Pty) Ltd\r
AE6000-AE6FFF (base 16) Ya Batho Trading (Pty) Ltd\r
9 Estee Ackerman Street\r
Kyoto City Kyoto-fu 604-8411\r
JP\r
\r
-70-B3-D5 (hex) Private\r
-B71000-B71FFF (base 16) Private\r
-\r
70-B3-D5 (hex) Engage Technologies\r
977000-977FFF (base 16) Engage Technologies\r
7041 Boone Avenue North\r
Oakland CA 94612\r
US\r
\r
-70-B3-D5 (hex) Energybox Limited\r
-FA4000-FA4FFF (base 16) Energybox Limited\r
- 4901 Central Plaza, 18 Harbour Road\r
- Wanchai Hong Kong 0000\r
- HK\r
-\r
70-B3-D5 (hex) OrbiWise SA\r
078000-078FFF (base 16) OrbiWise SA\r
c/o Fongit\r
Brzeg Dolny 56-120\r
PL\r
\r
-70-B3-D5 (hex) PCTEL\r
-ED2000-ED2FFF (base 16) PCTEL\r
- 22600 gateway center drive, Suite 100\r
- Clarksburg MD 20871\r
- US\r
-\r
70-B3-D5 (hex) Computechnic AG\r
7D4000-7D4FFF (base 16) Computechnic AG\r
Rietlistrasse 3\r
SEOUL 07796\r
KR\r
\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-C17000-C17FFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-70C000-70CFFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
70-B3-D5 (hex) Antlia Systems\r
416000-416FFF (base 16) Antlia Systems\r
401 N Michigan Ave Ste 1200\r
Macleod VIC 3085\r
AU\r
\r
+70-B3-D5 (hex) Season Electronics Ltd\r
+0F5000-0F5FFF (base 16) Season Electronics Ltd\r
+ 600 Nest Business Park \r
+ Havant Hampshire PO9 5TL\r
+ GB\r
+\r
+70-B3-D5 (hex) Proemion GmbH\r
+A03000-A03FFF (base 16) Proemion GmbH\r
+ Donaustraße 14\r
+ Fulda Hessen 36043\r
+ DE\r
+\r
+70-B3-D5 (hex) Magenta Labs, Inc.\r
+376000-376FFF (base 16) Magenta Labs, Inc.\r
+ 164 Townsend Street Unit 1\r
+ San Francisco CA 94107\r
+ US\r
+\r
+70-B3-D5 (hex) AC Power Corp.\r
+49C000-49CFFF (base 16) AC Power Corp.\r
+ 3F, No.200, Gangqian Rd., Neihu District\r
+ Taipei City 11494\r
+ TW\r
+\r
+70-B3-D5 (hex) Technological Ray GmbH\r
+4D7000-4D7FFF (base 16) Technological Ray GmbH\r
+ Zeppelinstraße 1\r
+ Hösbach Bayern 63768\r
+ DE\r
+\r
+70-B3-D5 (hex) PCS Inc.\r
+622000-622FFF (base 16) PCS Inc.\r
+ 4974 Provident Drive\r
+ Cincinnati OH 45246\r
+ US\r
+\r
+70-B3-D5 (hex) GRYPHON SECURE INC\r
+738000-738FFF (base 16) GRYPHON SECURE INC\r
+ 1015 - 2225 SHEPPARD AVE E\r
+ TORONTO ONTARIO M2J 5C2\r
+ CA\r
+\r
+70-B3-D5 (hex) Beringar\r
+6EF000-6EFFFF (base 16) Beringar\r
+ citypoint - 65 Haymarket Terrace\r
+ Edinburgh Lothian EH12 5HD\r
+ GB\r
+\r
+70-B3-D5 (hex) Satsky Communication Equipment Co.,Ltd.\r
+247000-247FFF (base 16) Satsky Communication Equipment Co.,Ltd.\r
+ 6/F., 710 building, Liantang Pengji Industrial Zone,Luohu District\r
+ Shenzhen Guangdong 518000\r
+ CN\r
+\r
+70-B3-D5 (hex) LITUM BILGI TEKNOLOJILERI SAN. VE TIC. A.S.\r
+483000-483FFF (base 16) LITUM BILGI TEKNOLOJILERI SAN. VE TIC. A.S.\r
+ ?evket Özçelik Sk. No:29 Kültür Mah. Litum Plaza\r
+ IZMIR 35220\r
+ TR\r
+\r
+70-B3-D5 (hex) Shanghai Hourui Technology Co., Ltd.\r
+9A3000-9A3FFF (base 16) Shanghai Hourui Technology Co., Ltd.\r
+ Room A1001A,Building A,No.1618 Yishan Road\r
+ Shanghai 201103\r
+ CN\r
+\r
+70-B3-D5 (hex) Optiver Pty Ltd\r
+B71000-B71FFF (base 16) Optiver Pty Ltd\r
+ 39 HUNTER ST\r
+ SYDNEY NSW 2000\r
+ AU\r
+\r
+70-B3-D5 (hex) GEGA ELECTRONIQUE\r
+573000-573FFF (base 16) GEGA ELECTRONIQUE\r
+ 1 RUE SAINT ELOI\r
+ MONTCEAU LES MINES SAONE ET LOIRE 71300\r
+ FR\r
+\r
+70-B3-D5 (hex) DAVE SRL\r
+27B000-27BFFF (base 16) DAVE SRL\r
+ VIA TALPONEDO 29/A\r
+ PORCIA PORDENONE 330850\r
+ IT\r
+\r
+70-B3-D5 (hex) ZAO ZEO\r
+619000-619FFF (base 16) ZAO ZEO\r
+ Khachaturiana 14a\r
+ Moscow 127562\r
+ RU\r
+\r
+70-B3-D5 (hex) Nuand LLC\r
+7D8000-7D8FFF (base 16) Nuand LLC\r
+ 680 Mission Street #41H\r
+ San Francisco CA 94105\r
+ US\r
+\r
+70-B3-D5 (hex) Jinga-hi, Inc.\r
+9BB000-9BBFFF (base 16) Jinga-hi, Inc.\r
+ 20303 Clifden Way\r
+ CUPERTINO CA 95014\r
+ US\r
+\r
+70-B3-D5 (hex) SeaTech Intelligent Technology (Shanghai) Co., LTD\r
+380000-380FFF (base 16) SeaTech Intelligent Technology (Shanghai) Co., LTD\r
+ 5th Flr,7Bldg,No.518,Xinzhuan Road\r
+ Shanghai Shanghai 201612\r
+ CN\r
+\r
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme\r
+8FB000-8FBFFF (base 16) MB connect line GmbH Fernwartungssysteme\r
+ Winnettener Straße 6\r
+ Dinkelsbuehl Bavaria 91550\r
+ DE\r
+\r
+70-B3-D5 (hex) ABC Electric Co.\r
+3C8000-3C8FFF (base 16) ABC Electric Co.\r
+ Room 266, 1333 Road Xinlong\r
+ Shanghai 201101\r
+ CN\r
+\r
+70-B3-D5 (hex) Senquire Pte. Ltd\r
+962000-962FFF (base 16) Senquire Pte. Ltd\r
+ 12, Bedok Reservoir View,, 17-37\r
+ Singapore Singapore 479237\r
+ SG\r
+\r
+70-B3-D5 (hex) WILMORE ELECTRONICS COMPANY\r
+ED4000-ED4FFF (base 16) WILMORE ELECTRONICS COMPANY\r
+ 607 US HIGHWAY 70A E\r
+ HILLSBOROUGH NC 27278-8526\r
+ US\r
+\r
+70-B3-D5 (hex) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+CBF000-CBFFFF (base 16) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+ 10545 Hardin Valley Rd\r
+ Knoxville TN 37932\r
+ US\r
+\r
+70-B3-D5 (hex) Veo Robotics, Inc.\r
+6C4000-6C4FFF (base 16) Veo Robotics, Inc.\r
+ 411 Waverley Oaks Rd. Suite 107\r
+ Waltham MA 02452\r
+ US\r
+\r
+70-B3-D5 (hex) PCTEL, Inc.\r
+ED2000-ED2FFF (base 16) PCTEL, Inc.\r
+ 22600 gateway center drive, Suite 100\r
+ Clarksburg MD 20871\r
+ US\r
+\r
+70-B3-D5 (hex) Energybox Limited\r
+FA4000-FA4FFF (base 16) Energybox Limited\r
+ 8/F., Green 18, HK Science Park\r
+ Sha Tin Hong Kong 0000\r
+ HK\r
+\r
+70-B3-D5 (hex) eBZ GmbH\r
+C57000-C57FFF (base 16) eBZ GmbH\r
+ Neusser Straße 8\r
+ Bielefeld NRW 33649\r
+ DE\r
+\r
+70-B3-D5 (hex) Teneo IoT B.V.\r
+CDD000-CDDFFF (base 16) Teneo IoT B.V.\r
+ Landbouwstraat 5-06\r
+ Winterswijk 7101 EK\r
+ NL\r
+\r
+70-B3-D5 (hex) tetronik GmbH AEN\r
+909000-909FFF (base 16) tetronik GmbH AEN\r
+ Silberbachstr.10\r
+ Taunusstein Hessen 65232\r
+ DE\r
+\r
+70-B3-D5 (hex) EBE Mobility & Green Energy GmbH\r
+624000-624FFF (base 16) EBE Mobility & Green Energy GmbH\r
+ Prießnitzgasse 16\r
+ Mödling Austria 2340\r
+ AT\r
+\r
+70-B3-D5 (hex) WuXi anktech Co., Ltd \r
+B61000-B61FFF (base 16) WuXi anktech Co., Ltd \r
+ Room1801, No.6 Third Financial Street, Binhu District, Wuxi City, Jiangsu Province\r
+ Wuxi jiangsu 214000\r
+ CN\r
+\r
+70-B3-D5 (hex) Power Element \r
+D17000-D17FFF (base 16) Power Element \r
+ Verkhnyaya Krasnoselskaya 2/1\r
+ Moscow moscow 107140\r
+ RU\r
+\r
+70-B3-D5 (hex) ISRV Zrt.\r
+AB1000-AB1FFF (base 16) ISRV Zrt.\r
+ Löv?ház utca 2-6. IV. emelet\r
+ Budapest PEST 1024 \r
+ HU\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+70C000-70CFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+C17000-C17FFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Boundary Technologies Ltd\r
+BBC000-BBCFFF (base 16) Boundary Technologies Ltd\r
+ 61 Dublin Street\r
+ Edinburgh Midlothian EH3 6NL\r
+ GB\r
+\r
+70-B3-D5 (hex) Microvision\r
+5F5000-5F5FFF (base 16) Microvision\r
+ 272, Digital-ro, 1004ho Microvision.\r
+ Guro-gu, Seoul, Republic of Korea 08848\r
+ KR\r
+\r
70-B3-D5 (hex) YUYAMA MFG Co.,Ltd\r
BBB000-BBBFFF (base 16) YUYAMA MFG Co.,Ltd\r
3-3-1\r
Bristol BS1 2PH\r
GB\r
\r
-70-B3-D5 (hex) GRIDSMART Technologies\r
-D50000-D50FFF (base 16) GRIDSMART Technologies\r
- 10545 Hardin Valley Rd\r
- Knoxville TN 37932\r
- US\r
-\r
70-B3-D5 (hex) Shenzhen Siera Technology Ltd\r
1BD000-1BDFFF (base 16) Shenzhen Siera Technology Ltd\r
Room 2039, Shenhai Building, Wanzhong Village, Bulong Road, Minzhi, Longhua district, City: Shenzhen\r
Taipei City Taiwan 115-73\r
TW\r
\r
-70-B3-D5 (hex) Private\r
-E22000-E22FFF (base 16) Private\r
-\r
70-B3-D5 (hex) H3D, Inc.\r
3F2000-3F2FFF (base 16) H3D, Inc.\r
812 Avis Drive\r
Marlborough SN8 1LH\r
GB\r
\r
-70-B3-D5 (hex) Private\r
-DE9000-DE9FFF (base 16) Private\r
-\r
70-B3-D5 (hex) ST Aerospace Systems\r
27F000-27FFFF (base 16) ST Aerospace Systems\r
505A Airport Road Paya Lebar\r
Carouge 1227\r
CH\r
\r
-70-B3-D5 (hex) Cubitech\r
-B86000-B86FFF (base 16) Cubitech\r
- 4-6 Kiprou str\r
- Tavros Athens 17778\r
- GR\r
-\r
70-B3-D5 (hex) CDS Institute of Management Strategy, Inc.\r
3A3000-3A3FFF (base 16) CDS Institute of Management Strategy, Inc.\r
Fukuyoshi-cho Billding 7F, Roppongi 2-2-6\r
São Paulo São Paulo 04760-020\r
BR\r
\r
-70-B3-D5 (hex) Yokogawa Denshikiki Co.,Ltd\r
-7F0000-7F0FFF (base 16) Yokogawa Denshikiki Co.,Ltd\r
- Minami Shinjuku Hoshino Bldg. 5-23-13 Sendagaya\r
- Shibuya-ku Tokyo 151-0051\r
- JP\r
-\r
70-B3-D5 (hex) IK MULTIMEDIA PRODUCTION SRL\r
2FB000-2FBFFF (base 16) IK MULTIMEDIA PRODUCTION SRL\r
Via dell'Industria 46\r
New Delhi 110019\r
IN\r
\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-A1B000-A1BFFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
70-B3-D5 (hex) Melissa Climate Jsc\r
2DD000-2DDFFF (base 16) Melissa Climate Jsc\r
Gen. Gurko 4 Street\r
Hsinchu 300\r
TW\r
\r
+70-B3-D5 (hex) NUBURU Inc.\r
+DC7000-DC7FFF (base 16) NUBURU Inc.\r
+ 7442 S. Tucson Way\r
+ Centennial CO 80112\r
+ US\r
+\r
+70-B3-D5 (hex) Vigorcloud Co., Ltd.\r
+A3E000-A3EFFF (base 16) Vigorcloud Co., Ltd.\r
+ 3F., No. 11, Xinpo 1st St., Xindian Dist.,\r
+ New Taipei City 231\r
+ TW\r
+\r
+70-B3-D5 (hex) Tornado Modular Systems\r
+40C000-40CFFF (base 16) Tornado Modular Systems\r
+ Inzhenernaya st. 4a\r
+ Novosibirsk Novosibirsk 630128\r
+ RU\r
+\r
+70-B3-D5 (hex) SECUREAN CO.,Ltd\r
+10B000-10BFFF (base 16) SECUREAN CO.,Ltd\r
+ danny@securean.com\r
+ Incheon 2nd floor, 16 Giljuro, Seogu 22793\r
+ KR\r
+\r
70-B3-D5 (hex) Projects Unlimited Inc.\r
7C5000-7C5FFF (base 16) Projects Unlimited Inc.\r
6300 Sand Lake Road\r
Dayton OH 45414\r
US\r
\r
+70-B3-D5 (hex) RFHIC\r
+25E000-25EFFF (base 16) RFHIC\r
+ 41-14, Burim-ro 170beon-gil\r
+ Dongan-gu, Anyang-si Gyeonggi-do 14055\r
+ KR\r
+\r
+70-B3-D5 (hex) Hilo\r
+B86000-B86FFF (base 16) Hilo\r
+ 4-6 Kiprou str\r
+ Tavros Athens 17778\r
+ GR\r
+\r
+70-B3-D5 (hex) Federated Wireless, Inc. \r
+E22000-E22FFF (base 16) Federated Wireless, Inc. \r
+ 4301 North Fairfax Drive, Suite 310 \r
+ Arlington VA 22203\r
+ US\r
+\r
+70-B3-D5 (hex) Nocix, LLC\r
+BE2000-BE2FFF (base 16) Nocix, LLC\r
+ 201 East 16th Ave\r
+ North Kansas City MO 64116\r
+ US\r
+\r
+70-B3-D5 (hex) ADDE\r
+79C000-79CFFF (base 16) ADDE\r
+ 21 impasse frédéric faÿs\r
+ Villeurbanne 69100\r
+ FR\r
+\r
+70-B3-D5 (hex) DEUTA-WERKE GmbH\r
+F6B000-F6BFFF (base 16) DEUTA-WERKE GmbH\r
+ Paffrather Str. 140\r
+ Bergisch Gladbach North Rhine-Westphalia 51465\r
+ DE\r
+\r
+70-B3-D5 (hex) Servotronix Motion Control\r
+B0E000-B0EFFF (base 16) Servotronix Motion Control\r
+ 21C Yagia Kapayim st.\r
+ Petach Tikva 49130\r
+ IL\r
+\r
+70-B3-D5 (hex) Matrix Telematics Limited\r
+B83000-B83FFF (base 16) Matrix Telematics Limited\r
+ Merlin Court, Atlantic Street\r
+ Altrincham Cheshire WA14 5NL\r
+ GB\r
+\r
+70-B3-D5 (hex) STACKFORCE GmbH\r
+E87000-E87FFF (base 16) STACKFORCE GmbH\r
+ Biengener Str. 3\r
+ Eschbach 79427\r
+ DE\r
+\r
+70-B3-D5 (hex) Qlinx Technologies\r
+EC9000-EC9FFF (base 16) Qlinx Technologies\r
+ 1717 N Street NW Ste 1\r
+ Washington DC 20036\r
+ US\r
+\r
+70-B3-D5 (hex) Pantherun Technologies Pvt Ltd\r
+B14000-B14FFF (base 16) Pantherun Technologies Pvt Ltd\r
+ 311 6th main road Hal 2nd stage\r
+ Bangalore Karnataka 560038\r
+ IN\r
+\r
+70-B3-D5 (hex) Liberator Pty Ltd\r
+561000-561FFF (base 16) Liberator Pty Ltd\r
+ 265?Gilbert Street\r
+ Adelaide SA 5000\r
+ AU\r
+\r
+70-B3-D5 (hex) EASTERN SCIENCE & TECHNOLOGY CO., LTD\r
+2DF000-2DFFFF (base 16) EASTERN SCIENCE & TECHNOLOGY CO., LTD\r
+ 6F.,No.963, Zhongzheng Rd, Zhonghe Dist.\r
+ New Taipei City 235\r
+ TW\r
+\r
+70-B3-D5 (hex) Imenco Ltd\r
+3D1000-3D1FFF (base 16) Imenco Ltd\r
+ Campus 1 Innovation Park, Balgownie Road\r
+ Bridge of Don Aberdeen AB22 8GT\r
+ GB\r
+\r
+70-B3-D5 (hex) Contec Americas Inc.\r
+883000-883FFF (base 16) Contec Americas Inc.\r
+ 3991 Sarno Rd\r
+ Melbourne FL 32934\r
+ US\r
+\r
+70-B3-D5 (hex) Hon Hai Precision IND.CO.,LTD\r
+B45000-B45FFF (base 16) Hon Hai Precision IND.CO.,LTD\r
+ No. 66 Chung Shan Road TU-Cheng Industrial district TAIPEI TAIWAN \r
+ TAIPEI TAIWAN 33859\r
+ CN\r
+\r
+70-B3-D5 (hex) International Super Computer Co., Ltd.\r
+806000-806FFF (base 16) International Super Computer Co., Ltd.\r
+ 807-3, 8 / F, block F, No. 9, Shangdi Third Street, Haidian District\r
+ Beijing 100085\r
+ CN\r
+\r
+70-B3-D5 (hex) Rivercity Innovations Ltd.\r
+156000-156FFF (base 16) Rivercity Innovations Ltd.\r
+ 116 Research Drive, Suit 217\r
+ Saskatoon Saskatchewan S7N 3R3\r
+ CA\r
+\r
+70-B3-D5 (hex) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+D50000-D50FFF (base 16) Cubic ITS, Inc. dba GRIDSMART Technologies\r
+ 10545 Hardin Valley Rd\r
+ Knoxville TN 37932\r
+ US\r
+\r
+70-B3-D5 (hex) myenergi Ltd\r
+3A6000-3A6FFF (base 16) myenergi Ltd\r
+ Church View Business Centre, Binbrook\r
+ Market Rasen Lincolnshire LN8 6BY\r
+ GB\r
+\r
+70-B3-D5 (hex) eumig industrie-TV GmbH.\r
+C46000-C46FFF (base 16) eumig industrie-TV GmbH.\r
+ Gewerbeparkstrasse 9\r
+ Anif Salzburg 5081\r
+ AT\r
+\r
+70-B3-D5 (hex) IWS Global Pty Ltd\r
+8F9000-8F9FFF (base 16) IWS Global Pty Ltd\r
+ 29 Oxleigh Dr\r
+ Perth Western Australia 6090\r
+ AU\r
+\r
+70-B3-D5 (hex) SERTEC SRL\r
+621000-621FFF (base 16) SERTEC SRL\r
+ VIA LOMBARDIA, 7/8\r
+ BUSSOLENGO VERONA 37012\r
+ IT\r
+\r
+70-B3-D5 (hex) QDevil\r
+921000-921FFF (base 16) QDevil\r
+ Fruebjergvej 3\r
+ København Ø 2100\r
+ DK\r
+\r
+70-B3-D5 (hex) Macromatic Industrial Controls, Inc.\r
+118000-118FFF (base 16) Macromatic Industrial Controls, Inc.\r
+ W134N5345 Campbell Drive\r
+ Menomonee Falls WI 53051\r
+ US\r
+\r
+70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG\r
+4C3000-4C3FFF (base 16) EA Elektroautomatik GmbH & Co. KG\r
+ Helmholtzstraße 31-33\r
+ Viersen NRW 41747\r
+ DE\r
+\r
+70-B3-D5 (hex) EkspertStroyProekt LLC\r
+DE9000-DE9FFF (base 16) EkspertStroyProekt LLC\r
+ office 400, str.61, d.2/4, Luzhnetskaya nab.\r
+ Moscow Moscow 119270\r
+ RU\r
+\r
+70-B3-D5 (hex) YDK Technologies Co.,Ltd\r
+7F0000-7F0FFF (base 16) YDK Technologies Co.,Ltd\r
+ Minami Shinjuku Hoshino Bldg. 5-23-13 Sendagaya\r
+ Shibuya-ku Tokyo 151-0051\r
+ JP\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+A1B000-A1BFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+BEB000-BEBFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
70-B3-D5 (hex) DISMUNTEL SAL\r
92C000-92CFFF (base 16) DISMUNTEL SAL\r
Pol ind cotes\r
Palo Alto CA 94303\r
US\r
\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-7A4000-7A4FFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-832000-832FFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
-70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
-F5D000-F5DFFF (base 16) Potter Electric Signal Co. LLC\r
- 5757 Phantom Drive, Suite 125\r
- Hazelwood MO 63042\r
- US\r
-\r
70-B3-D5 (hex) KMtronic ltd\r
6D6000-6D6FFF (base 16) KMtronic ltd\r
Dobri Czintulov 28A str.\r
No. 25, Tianrong road, Tianliao second industrial park, Yutang street, Guangming new district\r
Shenzhen Guangdong 518132\r
CN\r
+\r
+70-B3-D5 (hex) CAST Group of Companies Inc.\r
+BDE000-BDEFFF (base 16) CAST Group of Companies Inc.\r
+ 35 Ripley Ave.\r
+ Toronto Ontario M6S3P2\r
+ CA\r
+\r
+70-B3-D5 (hex) Momentum Data Systems\r
+116000-116FFF (base 16) Momentum Data Systems\r
+ 5432 Bolsa Ave Unit B\r
+ Huntington Beach CA 92649\r
+ US\r
+\r
+70-B3-D5 (hex) Camozzi Automation SpA\r
+3AB000-3ABFFF (base 16) Camozzi Automation SpA\r
+ Via Eritrea 20/I\r
+ BRESCIA ITALY 25080\r
+ IT\r
+\r
+70-B3-D5 (hex) PuS GmbH und Co. KG\r
+322000-322FFF (base 16) PuS GmbH und Co. KG\r
+ Hainstr. 13\r
+ Gera Germany 07545\r
+ DE\r
+\r
+70-B3-D5 (hex) Ci4Rail\r
+195000-195FFF (base 16) Ci4Rail\r
+ Vogelweiherstrasse 20\r
+ Nürnberg Bavaria 90441\r
+ DE\r
+\r
+70-B3-D5 (hex) Arris\r
+988000-988FFF (base 16) Arris\r
+ 2500 Walsh Ave.\r
+ Santa Clara CA 95014\r
+ US\r
+\r
+70-B3-D5 (hex) Xirgo Technologies LLC\r
+646000-646FFF (base 16) Xirgo Technologies LLC\r
+ 188 Camino Ruiz\r
+ Camarillo CA 93012\r
+ US\r
+\r
+70-B3-D5 (hex) Transit Solutions, LLC.\r
+4E2000-4E2FFF (base 16) Transit Solutions, LLC.\r
+ 114 West Grandview Avenue\r
+ Zelienople PA 16063\r
+ US\r
+\r
+70-B3-D5 (hex) JD Squared, Inc.\r
+562000-562FFF (base 16) JD Squared, Inc.\r
+ 915 Riverview Drive\r
+ Johnson City TN 37601\r
+ US\r
+\r
+70-B3-D5 (hex) VOCAL Technologies Ltd.\r
+7B5000-7B5FFF (base 16) VOCAL Technologies Ltd.\r
+ 520 LEE ENTRANCE STE 202\r
+ BUFFALO NY 142282583\r
+ US\r
+\r
+70-B3-D5 (hex) Deltronic Security AB\r
+CEC000-CECFFF (base 16) Deltronic Security AB\r
+ E A Rosengrensgata 4\r
+ Västra Frölunda 421 31\r
+ SE\r
+\r
+70-B3-D5 (hex) Atman Tecnologia Ltda\r
+F90000-F90FFF (base 16) Atman Tecnologia Ltda\r
+ Avenida Adalberto Simão Nader\r
+ Vitória Espírito Santo 29070-010\r
+ BR\r
+\r
+70-B3-D5 (hex) Shenyang TECHE Technology Co.,Ltd\r
+47D000-47DFFF (base 16) Shenyang TECHE Technology Co.,Ltd\r
+ oom2302, Changfeng building, 26-2 Pangjiang street, Dadong District\r
+ Shenyang Liaoning 110041\r
+ CN\r
+\r
+70-B3-D5 (hex) Öresundskraft AB\r
+668000-668FFF (base 16) Öresundskraft AB\r
+ Västra Sandgatan 4\r
+ Helsingborg 25225\r
+ SE\r
+\r
+70-B3-D5 (hex) Omsk Manufacturing Association named after A.S. Popov\r
+A61000-A61FFF (base 16) Omsk Manufacturing Association named after A.S. Popov\r
+ 10 Let Oktyabrya str, 195\r
+ Omsk 644009\r
+ RU\r
+\r
+70-B3-D5 (hex) DELITECH GROUP\r
+018000-018FFF (base 16) DELITECH GROUP\r
+ 425 Rue du Trident\r
+ VENDARGUES 34740\r
+ FR\r
+\r
+70-B3-D5 (hex) Larraioz Elektronika\r
+176000-176FFF (base 16) Larraioz Elektronika\r
+ FACT Larraioz, Ctra GI3162 km 2,2\r
+ Zarautz 20800\r
+ ES\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+7A4000-7A4FFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+F5D000-F5DFFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) Potter Electric Signal Co. LLC\r
+832000-832FFF (base 16) Potter Electric Signal Co. LLC\r
+ 1609 Park 370 Place\r
+ Hazelwood MO 63042\r
+ US\r
+\r
+70-B3-D5 (hex) ICsec S.A.\r
+395000-395FFF (base 16) ICsec S.A.\r
+ Wichrowa 1A\r
+ Poznan 60-446\r
+ PL\r
from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd,
OneOrMore, Combine, Or, Optional, Suppress, Group,
nums, alphanums, printables,
- stringEnd, pythonStyleComment, QuotedString,
+ stringEnd, pythonStyleComment,
ParseBaseException)
except ImportError:
print('pyparsing is not available')
EMPTYLINE = LineEnd()
COMMENTLINE = pythonStyleComment + EOL
INTEGER = Word(nums)
-STRING = QuotedString('"')
REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER))
SIGNED_REAL = Combine(Optional(Word('-+')) + REAL)
UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
matchline = (matchline_typed | matchline_general) + EOL
propertyline = (White(' ', exact=1).suppress() +
- Combine(UDEV_TAG - '=' - Word(alphanums + '_=:@*.!-;, "') - Optional(pythonStyleComment)) +
+ Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "'))
+ - Optional(pythonStyleComment)) +
EOL)
propertycomment = White(' ', exact=1) + pythonStyleComment + EOL
dpi_setting = (Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ'))('SETTINGS*')
mount_matrix_row = SIGNED_REAL + ',' + SIGNED_REAL + ',' + SIGNED_REAL
mount_matrix = (mount_matrix_row + ';' + mount_matrix_row + ';' + mount_matrix_row)('MOUNT_MATRIX')
+ xkb_setting = Optional(Word(alphanums + '+-/@._'))
props = (('MOUSE_DPI', Group(OneOrMore(dpi_setting))),
('MOUSE_WHEEL_CLICK_ANGLE', INTEGER),
('POINTINGSTICK_CONST_ACCEL', REAL),
('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))),
('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))),
- ('XKB_FIXED_LAYOUT', STRING),
- ('XKB_FIXED_VARIANT', STRING),
- ('XKB_FIXED_MODEL', STRING),
+ ('XKB_FIXED_LAYOUT', xkb_setting),
+ ('XKB_FIXED_VARIANT', xkb_setting),
+ ('XKB_FIXED_MODEL', xkb_setting),
('KEYBOARD_LED_NUMLOCK', Literal('0')),
('KEYBOARD_LED_CAPSLOCK', Literal('0')),
('ACCEL_MOUNT_MATRIX', mount_matrix),
except ParseBaseException as e:
error('Pattern {!r} is invalid: {}', rest, e)
continue
- if rest[-1] not in '*:':
- error('pattern {} does not end with "*" or ":"', match)
+
+ if not rest.endswith(':*'):
+ error("pattern {!r} does not end with ':*'", match)
matches.sort()
prev = None
#
# List of PCI ID's
#
-# Version: 2020.07.21
-# Date: 2020-07-21 03:15:02
+# Version: 2020.10.11
+# Date: 2020-10-11 03:15:01
#
# Maintained by Albert Pool, Martin Mares, and other volunteers from
# the PCI ID Project at https://pci-ids.ucw.cz/.
1000 9363 MegaRAID SAS 9361-4i
1000 9364 MegaRAID SAS 9364-8i
1000 936a MegaRAID SAS 9364-8i
+ 1000 9380 MegaRAID SAS 9380-8e
1028 1f41 PERC H830 Adapter
1028 1f42 PERC H730P Adapter
1028 1f43 PERC H730 Adapter
1028 200b HBA355i Adapter
1028 200c HBA355i Front
1028 200d HBA355e Adapter
- 1028 200e HBA355i MX
+ 1028 200e HBA350i MX
1d49 0205 ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA
1d49 0206 ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA
00e7 Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx
13e9 Ariel
1478 Navi 10 XL Upstream Port of PCI Express Switch
1479 Navi 10 XL Downstream Port of PCI Express Switch
- 154c Kryptos
+ 154c Kryptos [Radeon RX 350]
154e Garfield
1551 Arlene
1552 Pooky
3154 RV380/M24 GL [Mobility FireGL V3200]
3155 RV380 GL [FireMV 2400]
3171 RV380 GL [FireMV 2400] (Secondary)
- 3e50 RV380 [Radeon X600]
+ 3e50 RV380 [Radeon X550/X600]
3e54 RV380 GL [FireGL V3200]
- 3e70 RV380 [Radeon X600] (Secondary)
+ 3e70 RV380 [Radeon X550/X600] (Secondary)
4136 RS100 [Mobility IGP 320M]
4137 RS200 [Radeon IGP 340]
4144 R300 [Radeon 9500]
5044 All-In-Wonder 128 PCI
1002 0028 Rage 128 AIW
1002 0029 Rage 128 AIW
- 5046 Rage 4 [Rage 128 PRO AGP 4X TMDS]
+ 5046 Rage 4 [Rage 128 PRO AGP 4X]
1002 0004 Rage Fury Pro
1002 0008 Rage Fury Pro/Xpert 2000 Pro
1002 0014 Rage Fury Pro
1002 0048 Rage Fury Pro
1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device)
1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)
- 5050 Rage128 [Xpert 128 PCI]
+ 5050 Rage 4 [Rage 128 PRO PCI / Xpert 128 PCI]
1002 0008 Xpert 128
- 5052 Rage 128 PRO AGP 4X TMDS
+ 5052 Rage 4 [Rage 128 PRO AGP 4X]
5144 R100 [Radeon 7200 / All-In-Wonder Radeon]
1002 0008 Radeon 7000/Radeon VE
1002 0009 Radeon 7000/Radeon
524c Rage 128 VR AGP
1002 0008 Xpert 99/Xpert 2000
1002 0088 Xpert 99
- 5346 Rage 128 SF/4x AGP 2x
- 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL
534d Rage 128 4X AGP 4x
1002 0008 Xpert 99/Xpert 2000
1002 0018 Xpert 2000
554a R423 [Radeon X800 XT Platinum Edition]
554b R423 [Radeon X800 GT/SE]
1002 0302 Radeon X800 SE
- 554d R430 [Radeon X800 XL]
+ 554d R480 [Radeon X800 GTO2/XL]
1002 0322 All-In-Wonder X800 XL
1458 2124 GV-R80L256V-B (AGP)
554e R430 [All-In-Wonder X800 GT]
5551 R423 GL [FireGL V5100]
5569 R423 [Radeon X800 PRO] (Secondary)
556b R423 [Radeon X800 GT] (Secondary)
- 556d R430 [Radeon X800 XL] (Secondary)
+ 556d R480 [Radeon X800 GTO2/XL] (Secondary)
1458 2125 GV-R80L256V-B (AGP)
556f R430 [Radeon X800] (Secondary)
5571 R423 GL [FireGL V5100] (Secondary)
5957 RX780/RX790 Host Bridge
1849 5957 A770CrossFire Motherboard
5958 RD780 Host Bridge
- 5960 RV280 [Radeon 9200 PRO]
+ 5960 RV280 [Radeon 9200 PRO / 9250]
17af 2020 Excalibur Radeon 9250
5961 RV280 [Radeon 9200]
1002 2f72 All-in-Wonder 9200 Series
1642 3c81 Radeon HD 8670
1642 3c91 Radeon HD 8670
1642 3f09 Radeon R7 350
- 6611 Oland [Radeon HD 8570 / R7 240/340 / Radeon 520 OEM]
+ 6611 Oland [Radeon HD 8570 / R5 430 OEM / R7 240/340 / Radeon 520 OEM]
1028 210b Radeon R5 240 OEM
1642 1869 Radeon 520 OEM
174b 4248 Radeon R7 240 OEM
67cc Ellesmere [Polaris10]
67cf Ellesmere [Polaris10]
67d0 Ellesmere [Radeon Pro V7300X / V7350x2]
+ 67d7 Ellesmere [Radeon Pro WX 5100 / Barco MXRT-6700]
67df Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]
1002 0b37 Radeon RX 480
1028 1722 Radeon RX 570X
1682 9480 Radeon RX 480
1682 9588 Radeon RX 580 XTR
1682 c570 Radeon RX 570
+ 1682 c580 Radeon RX 580
174b e347 Radeon RX 470/480
174b e349 Radeon RX 470
1787 a470 Radeon RX 470
67ef Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X]
1028 1703 RX 560D OEM OC 2 GB
103c 3421 Radeon RX 460
+ 1043 0561 AREZ Radeon RX 560
106b 0160 Radeon Pro 460
106b 0166 Radeon Pro 455
106b 0167 Radeon Pro 450
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
6880 Lexington [Radeon HD 6550M]
103c 163c Pavilion dv6 Radeon HD 6550M
6888 Cypress XT [FirePro V8800]
148c 9380 Radeon R9 380
# Make naming scheme consistent
174b e308 Radeon R9 380 Nitro 4G D5
+ 693b Tonga PRO GL [FirePro W7100 / Barco MXRT-7600]
694c Polaris 22 XT [Radeon RX Vega M GH]
694e Polaris 22 XL [Radeon RX Vega M GL]
694f Polaris 22 MGL XL [Radeon Pro WX Vega M GL]
7100 R520 [Radeon X1800 XT]
7101 R520/M58 [Mobility Radeon X1800 XT]
7102 R520/M58 [Mobility Radeon X1800]
- 7104 R520 GL [FireGL V7200]
+ 7104 R520 GL [FireGL V7200 / Barco MXTR-5100]
13cc 3d0a MXRT-5100
7109 R520 [Radeon X1800 XL]
1002 0322 All-in-Wonder X1800XL
9612 RS780M [Mobility Radeon HD 3200]
9613 RS780MC [Mobility Radeon HD 3100]
9614 RS780D [Radeon HD 3300]
+ 9615 RS780E [Radeon HD 3200]
9616 RS780L [Radeon 3000]
9640 Sumo [Radeon HD 6550D]
9641 Sumo [Radeon HD 6620G]
9917 Trinity [Radeon HD 7620G]
9918 Trinity [Radeon HD 7600G]
9919 Trinity [Radeon HD 7500G]
- 991e Bishop
+ 991e Bishop [Xbox One S APU]
9920 Liverpool [Playstation 4 APU]
9921 Liverpool HDMI/DP Audio Controller
9922 Starshp
1466 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 6
1467 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 7
1468 Zeppelin Cryptographic Coprocessor NTBCCP
+ 1470 Vega 10 PCIe Bridge
+ 1471 Vega 10 PCIe Bridge
1480 Starship/Matisse Root Complex
1462 7c37 X570-A PRO motherboard
1481 Starship/Matisse IOMMU
105d 0009 Imagine 128 series 2e 4Mb DRAM
105d 000a Imagine 128 series 2 8Mb VRAM
105d 000b Imagine 128 series 2 8Mb H-VRAM
- 11a4 000a Barco Metheus 5 Megapixel
- 13cc 0000 Barco Metheus 5 Megapixel
- 13cc 0004 Barco Metheus 5 Megapixel
- 13cc 0005 Barco Metheus 5 Megapixel
- 13cc 0006 Barco Metheus 5 Megapixel
- 13cc 0008 Barco Metheus 5 Megapixel
- 13cc 0009 Barco Metheus 5 Megapixel
- 13cc 000a Barco Metheus 5 Megapixel
- 13cc 000c Barco Metheus 5 Megapixel
+ 11a4 000a Metheus 5 Megapixel
+ 13cc 0000 Metheus 5 Megapixel
+ 13cc 0004 Metheus 5 Megapixel
+ 13cc 0005 Metheus 5 Megapixel
+ 13cc 0006 Metheus 5 Megapixel
+ 13cc 0008 Metheus 5 Megapixel
+ 13cc 0009 Metheus 5 Megapixel
+ 13cc 000a Metheus 5 Megapixel
+ 13cc 000c Metheus 5 Megapixel
493d Imagine 128 T2R [Ticket to Ride]
- 11a4 000a Barco Metheus 5 Megapixel, Dual Head
- 11a4 000b Barco Metheus 5 Megapixel, Dual Head
- 13cc 0002 Barco Metheus 4 Megapixel, Dual Head
- 13cc 0003 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0007 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0008 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0009 Barco Metheus 5 Megapixel, Dual Head
- 13cc 000a Barco Metheus 5 Megapixel, Dual Head
+ 11a4 000a Metheus 5 Megapixel, Dual Head
+ 11a4 000b Metheus 5 Megapixel, Dual Head
+ 13cc 0002 Metheus 4 Megapixel, Dual Head
+ 13cc 0003 Metheus 5 Megapixel, Dual Head
+ 13cc 0007 Metheus 5 Megapixel, Dual Head
+ 13cc 0008 Metheus 5 Megapixel, Dual Head
+ 13cc 0009 Metheus 5 Megapixel, Dual Head
+ 13cc 000a Metheus 5 Megapixel, Dual Head
5348 Revolution 4
105d 0037 Revolution IV-FP AGP (For SGI 1600SW)
11a4 0028 PVS5600M
1682 211c GeForce 6600 256MB DDR DUAL DVI TV
00f3 NV43 [GeForce 6200]
00f4 NV43 [GeForce 6600 LE]
- 00f5 G71 [GeForce 7800 GS]
+ 00f5 G71 [GeForce 7800 GS AGP]
00f6 NV43 [GeForce 6800 GS/XT]
1682 217e XFX GeForce 6800 XTreme 256MB DDR3 AGP
00f8 NV45GL [Quadro FX 3400/4400]
02a0 NV2A [XGPU]
02a5 MCPX CPU Bridge
02a6 MCPX Memory Controller
- 02e0 G73 [GeForce 7600 GT]
+ 02e0 G73 [GeForce 7600 GT AGP]
02e0 2249 GF 7600GT 560M 256MB DDR3 DUAL DVI TV
- 02e1 G73 [GeForce 7600 GS]
+ 02e1 G73 [GeForce 7600 GS AGP]
1682 222b PV-T73K-UAL3 (256MB)
1682 2247 GF 7600GS 512MB DDR2
- 02e2 G73 [GeForce 7300 GT]
- 02e3 G71 [GeForce 7900 GS]
- 02e4 G71 [GeForce 7950 GT]
+ 02e2 G73 [GeForce 7300 GT AGP]
+ 02e3 G71 [GeForce 7900 GS AGP]
+ 02e4 G71 [GeForce 7950 GT AGP]
1682 2271 PV-T71A-YDF7 (512MB)
+ 02e5 G71 [GeForce 7600 GS AGP]
02f0 C51 Host Bridge
103c 2a34 Pavilion a1677c
103c 30b7 Presario V6133CL
1e04 TU102 [GeForce RTX 2080 Ti]
1e07 TU102 [GeForce RTX 2080 Ti Rev. A]
1462 3715 RTX 2080 Ti GAMING X TRIO
- 1e2d TU102B
- 1e2e TU102B
+ 1e2d TU102 [GeForce RTX 2080 Ti Engineering Sample]
+ 1e2e TU102 [GeForce RTX 2080 Ti 12GB Engineering Sample]
1e30 TU102GL [Quadro RTX 6000/8000]
10de 129e Quadro RTX 8000
10de 12ba Quadro RTX 6000
- 1e36 TU102GL
+ 1e36 TU102GL [Quadro RTX 6000]
1e37 TU102GL [GRID RTX T10-4/T10-8/T10-16]
10de 1347 GRID RTX T10-8
10de 1348 GRID RTX T10-4
1f51 TU106BM [GeForce RTX 2060 Mobile]
1f54 TU106BM [GeForce RTX 2070 Mobile]
1f55 TU106BM [GeForce RTX 2060 Mobile]
+ 1f76 TU106GLM [Quadro RTX 3000 Mobile Refresh]
1f81 TU117
1f82 TU117 [GeForce GTX 1650]
1f91 TU117M [GeForce GTX 1650 Mobile / Max-Q]
1f95 TU117M [GeForce GTX 1650 Ti Mobile]
1f96 TU117M [GeForce GTX 1650 Mobile / Max-Q]
1f97 TU117M [GeForce MX450]
+ 1f98 TU117M [GeForce MX450]
1f99 TU117M
+ 1f9c TU117M [GeForce MX450]
1fae TU117GL
1fb8 TU117GLM [Quadro T2000 Mobile / Max-Q]
1fb9 TU117GLM [Quadro T1000 Mobile]
21bf TU116GL
21c4 TU116 [GeForce GTX 1660 SUPER]
21d1 TU116BM [GeForce GTX 1660 Ti Mobile]
+ 2204 GA102 [GeForce RTX 3090]
+ 2206 GA102 [GeForce RTX 3080 10GB / 20GB]
+ 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]
+ 223f GA102GL
+ 2482 GA104 [GeForce RTX 3070 Ti]
+ 2484 GA104 [GeForce RTX 3070]
+ 2486 GA104 [GeForce RTX 3060 Ti]
+ 249c GA104M [GeForce RTX 3070 Mobile]
+ 249d GA104M [GeForce RTX 3070 Mobile / Max-Q]
+ 24af GA104 [GeForce RTX 3070 Engineering Sample]
+ 24bf GA104 [GeForce RTX 3070 Engineering Sample]
+ 252f GA106 [GeForce RTX 3060 Engineering Sample]
10df Emulex Corporation
0720 OneConnect NIC (Skyhawk)
103c 1934 FlexFabric 20Gb 2-port 650M Adapter
17aa b023 ThinkPad E595
c821 RTL8821CE 802.11ac PCIe Wireless Network Adapter
c822 RTL8822CE 802.11ac PCIe Wireless Network Adapter
+ c82f RTL8822CE 802.11ac PCIe Wireless Network Adapter
d723 RTL8723DE 802.11b/g/n PCIe Adapter
10ed Ascii Corporation
7310 V7310
117c 00a2 Celerity FC-321E
117c 00a3 Celerity FC-322E
117c 00ac Celerity FC-324E
+ 00bb Celerity FC 32/64Gb/s Gen 7 Fibre Channel HBA
+ 117c 00bc Celerity FC-321P
+ 117c 00bd Celerity FC-322P
+ 117c 00be Celerity FC-324P
+ 00e6 ExpressSAS GT 12Gb/s SAS/SATA HBA
+ 117c 00c0 ExpressSAS H1280 GT
+ 117c 00c1 ExpressSAS H1208 GT
+ 117c 00c2 ExpressSAS H1244 GT
+ 117c 00c3 ExpressSAS H12F0 GT
+ 117c 00c4 ExpressSAS H120F GT
8013 ExpressPCI UL4D
8014 ExpressPCI UL4S
8027 ExpressPCI UL5D
0314 Model 14 Road Runner Frame Grabber
0324 Model 24 Road Runner Frame Grabber
0344 Model 44 Road Runner Frame Grabber
+ b04e Claxon CXP4 CoaXPress frame grabber
118e Hermstedt GmbH
118f Green Logic
1190 Tripace
0811 SM811 LynxE
0820 SM820 Lynx3D
0910 SM910
+ 2262 SM2262/SM2262EN SSD Controller
1270 Olympus Optical Co., Ltd.
1271 GW Instruments
1272 Telematics International
13c9 Eaton Corporation
13ca Iomega Corporation
13cb Yano Electric Co Ltd
-13cc Metheus Corporation
+13cc BARCO
13cd Compatible Systems Corporation
13ce Cocom A/S
13cf Studio Audio & Video Ltd
144c Catalina Research Inc
144d Samsung Electronics Co Ltd
1600 Apple PCIe SSD
+ a544 Exynos 8890 PCIe Root Complex
a800 XP941 PCIe SSD
a802 NVMe SSD Controller SM951/PM951
a804 NVMe SSD Controller SM961/PM961
1028 2097 EMC PowerEdge Express Flash Ent NVMe AGN SED RI U.2 Gen4 1.92TB
1028 2098 EMC PowerEdge Express Flash Ent NVMe AGN SED RI U.2 Gen4 3.84TB
1028 2099 EMC PowerEdge Express Flash Ent NVMe AGN SED RI U.2 Gen4 7.68TB
+ ecec Exynos 8895 PCIe Root Complex
144e OLITEC
144f Askey Computer Corp.
1450 Octave Communications Ind.
16d5 BCM57407 NetXtreme-E 10GBase-T Ethernet Controller
16d6 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller
14e4 4120 NetXtreme E-Series Advanced Dual-port 10Gb SFP+ Ethernet Network Daughter Card
+ 14e4 4126 NetXtreme-E Dual-port 10G SFP+ Ethernet OCP 3.0 Adapter (BCM957412N4120C)
152d 8b20 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller
152d 8b22 BCM57412 NetXtreme-E 25Gb RDMA Ethernet Controller
16d7 BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller
14e4 1402 BCM957414A4142CC 10Gb/25Gb Ethernet PCIe
14e4 1404 BCM957414M4142C OCP 2x25G Type1 wRoCE
14e4 4140 NetXtreme E-Series Advanced Dual-port 25Gb SFP28 Network Daughter Card
+ 14e4 4146 NetXtreme-E Dual-port 25G SFP28 Ethernet OCP 3.0 Adapter (BCM957414N4140C)
1590 020e Ethernet 25Gb 2-port 631SFP28 Adapter
1590 0211 Ethernet 25Gb 2-port 631FLR-SFP28 Adapter
16d8 BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller
1028 1feb NetXtreme-E 10Gb SFP+ Adapter
- 14e4 4163 BCM957416M4163C OCP 2x10GBT Type1 wRoCE
+ 14e4 4163 NetXtreme-E Dual-port 10GBASE-T Ethernet OCP 2.0 Adapter (BCM957416M4163C)
+ 14e4 4166 NetXtreme-E Dual-port 10GBASE-T Ethernet OCP 3.0 Adapter (BCM957416N4160C)
1590 020c Ethernet 10Gb 2-port 535T Adapter
1590 0212 Ethernet 10Gb 2-port 535FLR-T Adapter
16d9 BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller
16e7 BCM57404 NetXtreme-E Ethernet Partition
16e8 BCM57406 NetXtreme-E Ethernet Partition
16e9 BCM57407 NetXtreme-E 25Gb Ethernet Controller
+ 16eb BCM57412 NetXtreme-E RDMA Partition
16ec BCM57414 NetXtreme-E Ethernet Partition
16ed BCM57414 NetXtreme-E RDMA Partition
16ee BCM57416 NetXtreme-E Ethernet Partition
103c 30c0 Compaq 6710b
17aa 3a23 IdeaPad S10e
1750 BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet
+ 14e4 2100 NetXtreme-E Dual-port 100G QSFP56 Ethernet PCIe4.0 x16 Adapter (BCM957508-P2100G)
+ 14e4 5208 NetXtreme-E Dual-port 100G QSFP56 Ethernet OCP 3.0 Adapter (BCM957508-N2100G)
1751 BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet
1752 BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet
+ 1800 BCM57502 NetXtreme-E Ethernet Partition
+ 1801 BCM57504 NetXtreme-E Ethernet Partition
+ 1802 BCM57508 NetXtreme-E Ethernet Partition
+ 1803 BCM57502 NetXtreme-E RDMA Partition
+ 1804 BCM57504 NetXtreme-E RDMA Partition
+ 1805 BCM57508 NetXtreme-E RDMA Partition
1806 BCM5750X NetXtreme-E Ethernet Virtual Function
1807 BCM5750X NetXtreme-E RDMA Virtual Function
3352 BCM3352
4410 BCM4413 iLine32 HomePNA 2.0
4411 BCM4413 V.90 56k modem
4412 BCM4412 10/100BaseT
+ 441f BCM4361 802.11ac Dual-Band Wireless Network Controller
+ 4420 BCM4361 802.11ac 2.4 GHz Wireless Network Controller
+ 4421 BCM4361 802.11ac 5 GHz Wireless Network Controller
4430 BCM44xx CardBus iLine32 HomePNA 2.0
4432 BCM4432 CardBus 10/100BaseT
4464 BCM4364 802.11ac Wireless Network Adapter
1526 ISS, Inc
1527 SOLECTRON
1528 ACKSYS
-1529 AMERICAN MICROSystems Inc
+# nee American Microsystems Inc
+1529 ON Semiconductor
152a QUICKTURN DESIGN Systems
152b FLYTECH Technology CO Ltd
152c MACRAIGOR Systems LLC
1100 PCI Express Core Reference Design
110f PCI Express Core Reference Design Virtual Function
1110 XpressRich Reference Design
+ 1111 XpressRich-AXI Ref Design
+ 1112 QuickPCIe
1113 XpressSwitch
+ 1114 Inspector
+ 1115 XpressLINK Ref Design
+ 1116 XpressLINK-SOC Ref Design
be00 PCI Express Bridge
1557 MEDIASTAR Co Ltd
1558 CLEVO/KAPOK Computer
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
- 15b3 0125 Tencent ConnectX-5 EN Ex network interface card for OCP 3.0, with host management, 50GbE Dual-port QSFP28, PCIe4.0 x16, Thumbscrew (pull-tab) bracket
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
+ 15b3 0125 Tencent ConnectX-5 EN Ex network interface card for OCP 3.0, with host management, 50GbE Dual-port QSFP28, PCIe4.0 x16, Thumbscrew (pull-tab) bracket
101a MT28800 Family [ConnectX-5 Ex Virtual Function]
101b MT28908 Family [ConnectX-6]
101c MT28908 Family [ConnectX-6 Virtual Function]
0041 QCA6164 802.11ac Wireless Network Adapter
0042 QCA9377 802.11ac Wireless Network Adapter
11ad 08a6 Qualcomm Atheros QCA9377 802.11ac Wireless Network Adapter
+# compatible with Lenovo's BIOS lock
+ 17aa 0901 Qualcomm Atheros QCA9377 Wireless Network Adapter
0046 QCA9984 802.11ac Wave 2 Wireless Network Adapter
0050 QCA9887 802.11ac Wireless Network Adapter
0207 AR5210 Wireless Network Adapter [AR5000 802.11a]
0142 PCA7208AS - Analog inputs/Outputs
0143 PCA7408AL - Analog Inputs/Outputs
0144 PCA7408AS - Analog Inputs/Outputs
+ 0145 PCA-7228AL Multifunction PCI IO card
+ 0146 PCA-7228AS Multifunction PCI IO card
+ 0147 PCA7428AL Multifunction PCI IO card
+ 0148 PCA7428AS Multifunction PCI IO card
+ 0149 PCA7228EL Multifunction PCI IO card with isolated analog inputs
+ 0150 PCA7428EL Multifunction PCI IO card with isolated analog inputs
+ 0151 PCA7628AL - PCI card with analog inputs, counters and DIO
+ 0152 PCA7628AS PCI card with analog inputs, outputs, counters and DIO
+ 0161 PCA7288A PCI card with analog outputs, counters and DIO
+ 0180 PCI1052 Communication card for MicroUnit network
0214 PCT-7424C (F0) PC card with standard counters
0215 PCT-7424C (F1) PC card with standard counters
0216 PCT-7424E (F0) PC card with standard counters
8083 GL880 USB 1.1 UHCI controller
8084 GL880 USB 2.0 EHCI controller
9750 GL9750 SD Host Controller
+ e763 GL9763E eMMC Controller
17aa Lenovo
402b Intel 82599ES 10Gb 2-port Server Adapter X520-2
17ab Phillips Components
0002 AGN300 802.11 a/b/g True MIMO Wireless Card
1385 6d00 WPNT511 RangeMax 240 Mbps Wireless CardBus Adapter
1737 0054 WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400
+ 0105 MSM8998 PCIe Root Complex
+ 0108 SM8150/SA8195P PCIe Root Complex
+ 0300 MDM9x35 LTE Modem
+ 0301 MDM9640 PCIe Root Complex
+ 0302 MDM9x55 LTE Modem [Snapdragon X12]
0400 Datacenter Technologies QDF2432 PCI Express Root Port
0401 Datacenter Technologies QDF2400 PCI Express Root Port
+ 1000 QCS405 PCIe Root Complex
17cc NetChip Technology, Inc
2280 USB 2.0
17cd Cadence Design Systems, Inc.
0087 MPC8343
00b4 MPC8315E
00b6 MPC8314E
- 1a56 1101 Killer Xeno Pro Gigabit Ethernet Controller
+ 1a56 1101 Bigfoot Killer Xeno Pro Gigabit Ethernet Controller
00c2 MPC8379E
00c3 MPC8379
00c4 MPC8378E
7011 MPC8641D PCI Host Bridge
7018 MPC8610
c006 MPC8308
- 1a56 1201 Killer E2100 Gigabit Ethernet Controller
+ 1a56 1201 Bigfoot Killer E2100 Gigabit Ethernet Controller
# PCIe interface for emulator
fc02 RedStone
# CFI device over PCIe
1966 Orad Hi-Tec Systems
1975 DVG64 family
1977 DVG128 family
+ 1979 3DVG/UHD3
+ 1980 HDV2/UHD2
+ 1234 3160 UHD2LC
+ 1234 3300 Legacy UHD2
+ 1234 3410 UHD2
# nee Atheros Communications, Inc. nee Attansic Technology Corp.
1969 Qualcomm Atheros
1026 AR8121/AR8113/AR8114 Gigabit or Fast Ethernet
0009 CAN interface PCI104 HS/HS
1a08 Sierra semiconductor
0000 SC15064
+1a0d SEAKR Engineering
1a0e DekTec Digital Video B.V.
083f DTA-2111 VHF/UHF Modulator
1a17 Force10 Networks, Inc.
0065 Atomix HDMI STAN
0070 RED Rocket
0090 CinePlay
-1a56 Bigfoot Networks, Inc.
+# nee Bigfoot Networks, now owned by Intel
+1a56 Rivet Networks
1a57 Highly Reliable Systems
1a58 Razer USA Ltd.
1a5d Celoxica
4254 0552 S952 v3
1ae0 Google, Inc.
0042 Compute Engine Virtual Ethernet [gVNIC]
+ abcd Airbrush Combined Paintbox IPU/Oscar Edge TPU [Pixel Neural Core]
1ae3 SANBlaze Technology, Inc.
1ae7 First Wise Media GmbH
0520 HFC-S PCI A [X-TENSIONS XC-520]
1ae8 Silicon Software GmbH
- 0a40 microEnable IV-BASE x1
- 0a41 microEnable IV-FULL x1
- 0a44 microEnable IV-FULL x4
- 0e44 microEnable IV-GigE x4
+# CameraLink frame grabber for Visual Applets
+ 0751 mE5 marathon VCL
+# CameraLink HS frame grabber
+ 0752 mE5 marathon AF2
+# CoaXpress frame grabber
+ 0753 mE5 marathon ACX QP
+# CameraLink frame grabber
+ 0754 mE5 marathon ACL
+# CoaXpress frame grabber
+ 0755 mE5 marathon ACX SP
+# CoaXpress frame grabber
+ 0756 mE5 marathon ACX DP
+# CoaXpress frame grabber for Visual Applets
+ 0757 mE5 marathon VCX QP
+# CameraLink HS frame grabber for Visual Applets
+ 0758 mE5 marathon VF2
+# CameraLink frame grabber for Visual Applets / AI applications
+ 0759 mE5 marathon VCLx
+# CameraLink frame grabber
+ 0a40 microEnable IV AD1-CL
+# CameraLink frame grabber for Visual Applets
+ 0a41 microEnable IV VD1-CL
+# CameraLink frame grabber
+ 0a42 microEnable IV AD4-CL
+# CameraLink frame grabber for Visual Applets
+ 0a44 microEnable IV VD4-CL
+# CameraLink frame grabber
+ 0a45 microEnable IV AS1-CL
+# CoaXpress frame grabber
+ 0a53 microEnable 5 AQ8-CXP6B
+# CoaXpress frame grabber for Visual Applets
+ 0a54 microEnable 5 VQ8-CXP6B
+# CoaXpress frame grabber for Visual Applets
+ 0a56 microEnable 5 VQ8-CXP6D
+# CoaXpress frame grabber
+ 0a57 microEnable 5 AQ8-CXP6D
+# CameraLink frame grabber for Visual Applets
+ 0a58 microEnable 5 VD8-CL
+# CameraLink frame grabber
+ 0a5a microEnable 5 AD8-CL
+# OEM product
+ 0b52 mE5 Abacus 4G Base
+# OEM product
+ 0b53 mE5 Abacus 4G Base II
+# OEM product
+ 0b61 mE6 Abacus 4TG
+# CoaXpress frame grabber
+ 0b63 CXP-12 Interface Card 1C
+# GigE Vision frame grabber
+ 0e42 microEnable IV AQ4-GE
+# GigE Vision frame grabber for Visual Applets
+ 0e44 microEnable IV VQ4-GE
1ae9 Wilocity Ltd.
0101 Wil6200 PCI Express Upstream Port
0200 Wil6200 PCI Express Port
0612 ASM1062 Serial ATA Controller
1849 0612 Motherboard
1042 ASM1042 SuperSpeed USB Host Controller
+ 1043 1059 K53SM motherboard
1043 8488 P8B WS Motherboard
1849 1042 Motherboard
1080 ASM1083/1085 PCIe to PCI Bridge
1242 ASM1142 USB 3.1 Host Controller
1343 ASM1143 USB 3.1 Host Controller
2142 ASM2142 USB 3.1 Host Controller
+ 3242 ASM3242 USB 3.2 Host Controller
1b26 Netcope Technologies, a.s.
c132 COMBO-LXT155
c1c0 NFB-100G1-e0
0602 NumaChip N602
1b4b Marvell Technology Group Ltd.
0640 88SE9128 SATA III 6Gb/s RAID Controller
+ 2241 88NR2241 Non-Volatile memory controller
+ 1d49 0306 ThinkSystem M.2 NVMe 2-Bay RAID Enablement Kit
+ 1d49 0307 ThinkSystem 7mm NVMe 2-Bay Rear RAID Enablement Kit
9120 88SE9120 SATA 6Gb/s Controller
9123 88SE9123 PCIe SATA 6.0 Gb/s controller
dc93 600e DC-6xxe series SATA 6G controller
1028 1fe2 BOSS-S1 Adapter
1028 2010 BOSS-S2 Adapter
1d49 0300 ThinkSystem M.2 with Mirroring Enablement Kit
+ 1d49 0301 ThinkSystem SR630 x16 PCIE with 4 SATA ports Riser
+ 1d49 0302 ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit
+ 1d49 0303 ThinkSystem SE350 M.2 SATA 4-Bay Data RAID Mirroring Enablement Kit
+ 1d49 0304 ThinkSystem M.2 SATA 2-Bay RAID Enablement Kit
+ 1d49 0305 ThinkSystem 7mm SATA 2-Bay Rear RAID Enablement Kit
9235 88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller
9445 88SE9445 PCIe 2.0 x4 4-Port SAS/SATA 6 Gbps RAID Controller
9480 88SE9480 SAS/SATA 6Gb/s RAID controller
9485 88SE9485 SAS/SATA 6Gb/s controller
+1b4c GALAX
1b55 NetUP Inc.
18f6 Dual DVB Universal CI card
18f7 Dual DVB Universal CI card rev 1.4
1285 PC300 NVMe Solid State Drive 1TB
1327 BC501 NVMe Solid State Drive 512GB
1504 SC300 512GB M.2 2280 SATA Solid State Drive
+ 2839 PE8000 Series NVMe Solid State Drive
+ 0100 1c5c PE8000 Series NVMe Solid State Drive
1c5f Beijing Memblaze Technology Co. Ltd.
000d PBlaze5 520/526 AIC
003d PBlaze5 920/926 AIC
1c8c Mobiveil, Inc.
1cb0 Shannon Systems
d000 Venice NVMe SSD
- 1cb0 2f10 Venice-E Series U.2 SSD
- 1cb0 2f11 Venice Series U.2 SSD
- 1cb0 2f12 Venice-X Series U.2 SSD
- 1cb0 af10 Venice-E Series AIC SSD
- 1cb0 af11 Venice Series AIC SSD
- 1cb0 af12 Venice-X Series AIC SSD
+ 1cb0 2010 Venice-E Series OCS U.2
+ 1cb0 2011 Venice Series OCS U.2
+ 1cb0 2012 Venice-X Series OCS U.2
+# Venice-E Series NVMe U.2 SSD(1.92T/3.84T/7.68T)
+ 1cb0 2f10 Venice-E Series NVMe U.2
+# Venice Series NVMe U.2 SSD(2T/4T/8T)
+ 1cb0 2f11 Venice Series NVMe U.2
+# Venice-X Series NVMe U.2 SSD(1.6T/3.2T/6.4T)
+ 1cb0 2f12 Venice-X Series NVMe U.2
+ 1cb0 a010 Venice-E Series OCS AIC
+ 1cb0 a012 Venice-X Series OCS AIC
+# Venice-E Series NVMe AIC SSD(1.92T/3.84T/7.68T)
+ 1cb0 af10 Venice-E Series NVMe AIC
+# Venice-X Series NVMe AIC SSD(1.6T/3.2T/6.4T)
+ 1cb0 af12 Venice-X Series NVMe AIC
1cb1 Collion UG & Co.KG
1cb5 Focusrite Audio Engineering Ltd
0002 Clarett
1d72 Xiaomi
1d78 DERA Storage
1512 TAI NVMe Controller
- 1d78 2003 D5457 HHHL 1.6TB NVMe SSD
1d78 2004 D5437 HHHL 2TB NVMe SSD
- 1d78 2005 D5457 HHHL 3.2TB NVMe SSD
1d78 2006 D5437 HHHL 4TB NVMe SSD
- 1d78 2007 D5457 HHHL 6.4TB NVMe SSD
1d78 2008 D5437 HHHL 8TB NVMe SSD
- 1d78 2103 D5457 U.2 1.6TB NVMe SSD
1d78 2104 D5437 U.2 2TB NVMe SSD
- 1d78 2105 D5457 U.2 3.2TB NVMe SSD
1d78 2106 D5437 U.2 4TB NVMe SSD
- 1d78 2107 D5457 U.2 6.4TB NVMe SSD
1d78 2108 D5437 U.2 8TB NVMe SSD
+ 1d78 3003 D5457 HHHL 1.6TB NVMe SSD
+ 1d78 3005 D5457 HHHL 3.2TB NVMe SSD
+ 1d78 3007 D5457 HHHL 6.4TB NVMe SSD
+ 1d78 3103 D5457 U.2 1.6TB NVMe SSD
+ 1d78 3105 D5457 U.2 3.2TB NVMe SSD
+ 1d78 3107 D5457 U.2 6.4TB NVMe SSD
1d7c Aerotech, Inc.
1d82 NETINT Technologies Inc.
0101 Codensity D400 SSD
0401 StarDragon4800 PCI Express Root Port
1dc5 FADU Inc.
1dcd Liqid Inc.
-1dd8 Pensando Systems Inc
+1dd8 Pensando Systems
1000 DSC Capri Upstream 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 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
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 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
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 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
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 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
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 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
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 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
1de0 Groq
0000 Q100 Tensor Streaming Processor
1de1 Tekram Technology Co.,Ltd.
1de5 Eideticom, Inc
1000 IO Memory Controller
2000 NoLoad Hardware Development Kit
+ 3000 eBPF-based PCIe Accelerator
1dee Biwin Storage Technology Co., Ltd.
1def Ampere Computing, LLC
e005 eMAG PCI Express Root Port 0
0204 ACE-NIC-NID Programmable Network Accelerator
1df3 0001 ENA1020Z
1df3 0002 ENA1020ZS
+ 0205 ACE-NIC250 Programmable Network Accelerator
+ 1df3 0000 Maintenance Mode
+ 1df3 0001 ENA2250F
+ 0206 ACE-NIC200 Programmable Network Accelerator
+ 1df3 0000 Maintenance Mode
+ 1df3 0001 ENA2200F
1df7 opencpi.org
0001 ml605
0002 alst4
1181 TDM 8 Port E1/T1/J1 Adapter
1e0f KIOXIA Corporation
0007 NVMe SSD Controller Cx6
+ 1028 2078 DC NVMe CD6 RI 960GB
+ 1028 2079 DC NVMe CD6 RI 1.92TB
+ 1028 207a DC NVMe CD6 RI 3.84TB
+ 1028 207b DC NVMe CD6 RI 7.68TB
+ 1028 207c DC NVMe CD6 RI 15.36TB
+ 1028 207e Dell Ent NVMe CM6 RI 1.92TB
+ 1028 207f Dell Ent NVMe CM6 RI 3.84TB
+ 1028 2080 Dell Ent NVMe CM6 RI 7.68TB
+ 1028 2081 Dell Ent NVMe CM6 RI 15.36TB
+ 1028 2084 Dell Ent NVMe CM6 MU 1.6TB
+ 1028 2085 Dell Ent NVMe CM6 MU 3.2TB
+ 1028 2086 Dell Ent NVMe CM6 MU 6.4TB
+ 1028 210a Dell Ent NVMe FIPS CM6 RI 1.92TB
+ 1028 210b Dell Ent NVMe FIPS CM6 RI 3.84TB
+ 1028 210c Dell Ent NVMe FIPS CM6 RI 7.68TB
+ 1028 210d Dell Ent NVMe FIPS CM6 RI15.36TB
+ 1028 210e Dell Ent NVMe FIPS CM6 MU 1.6TB
+ 1028 210f Dell Ent NVMe FIPS CM6 MU 3.2TB
+ 1028 2110 Dell Ent NVMe FIPS CM6 MU 6.4TB
+ 1e0f 0001 Generic NVMe CM6 RI 3.84TB
1e17 Arnold & Richter Cine Technik GmbH & Co. Betriebs KG
1e24 Squirrels Research Labs
0101 Acorn CLE-101
0001 T10 [CloudBlazer]
# nee Thinci, Inc
1e38 Blaize, Inc
+ 0102 Xplorer X1600
1e3d Burlywood, Inc
1e49 Yangtze Memory Technologies Co.,Ltd
1e4b MAXIO Technology (Hangzhou) Ltd.
0100 The device has already been deleted.
0000 0100 PY8800 64GB Accelerator
1e6b Axiado Corp.
+1e7c Brainchip Inc
+ bca1 AKD1000 Neural Network Coprocessor [Akida]
1e85 Heitec AG
1e89 ID Quantique SA
0002 Quantis-PCIe-40M
# aka SED Systems
1e94 Calian SED
1e95 Solid State Storage Technology Corporation
+1eb1 VeriSilicon Inc
+ 1001 Video Accelerator
# nee Tumsan Oy
1fc0 Ascom (Finland) Oy
0300 E2200 Dual E1/Rawpipe Card
2348 Racore
2010 8142 100VG/AnyLAN
2646 Kingston Technology Company, Inc.
+ 2263 A2000, M.2, 500GB
270b Xantel Corporation
270f Chaintech Computer Co. Ltd
2711 AVID Technology Inc.
3442 Bihl+Wiedemann GmbH
1783 AS-i 3.0 cPCI Master
1922 AS-i 3.0 PCI Master
-3475 Arastra Inc.
+3475 Arista Networks, Inc.
3513 ARCOM Control Systems Ltd
37d9 ITD Firm ltd.
1138 SCHD-PH-8 Phase detector
0100 Permedia II 2D+3D
07a1 Wildcat III 6210
07a2 Sun XVR-500 Graphics Accelerator
+ 3d3d 1047 Sun XVR-600 Graphics Accelerator
07a3 Wildcat IV 7210
1004 Permedia
3d04 Permedia
1043 844d P8B WS Motherboard
0172 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
0176 3rd Gen Core processor Graphics Controller
+ 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
+ 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
- 02f0 Wireless-AC 9462
- 8086 0070 Intel(R) Wi-Fi 6 AX201 160MHz
+ 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
+ 8086 0034 Wireless-AC 9560 160MHz
+ 8086 0070 Wi-Fi 6 AX201 160MHz
+ 8086 0074 Wi-Fi 6 AX201 160MHz
+ 02f5 Comet Lake PCH-LP SCS3
02f9 Comet Lake Thermal Subsytem
02fc Comet Lake Integrated Sensor Solution
0309 80303 I/O Processor PCI-to-PCI Bridge
0406 Haswell Integrated Graphics Controller
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 309f ThinkCentre M83
0416 4th Gen Core Processor Integrated Graphics Controller
17aa 220e ThinkPad T440p
06eb Comet Lake PCH Serial IO I2C Controller #3
06ed Comet Lake USB 3.1 xHCI Host Controller
06ef Comet Lake PCH Shared SRAM
- 06f0 Wi-Fi 6 AX201
+ 06f0 Comet Lake PCH CNVi WiFi
+ 8086 0034 Wireless-AC 9560
+ 8086 0074 Wi-Fi 6 AX201 160MHz
+ 8086 02a4 Wireless-AC 9462
06f9 Comet Lake PCH Thermal Controller
06fb Comet Lake PCH Serial IO SPI Controller #2
0700 CE Media Processor A/V Bridge
1d49 4714 Thinksystem Intel P4600 NVMe AIC
1d49 4802 Thinksystem U.2 P4510 NVMe SSD
1d49 4812 Thinksystem U.2 P4610 NVMe SSD
- 8086 4308 Intel SSD D5-P4320 and D5-P4326
+ 8086 4308 SSD D5-P4320 and D5-P4326
8086 4702 NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4500)
8086 4704 NVMe Datacenter SSD [3DNAND] SE AIC (P4500)
8086 4712 NVMe Datacenter SSD [3DNAND] ME 2.5" U.2 (P4600)
0bf6 Atom Processor D2xxx/N2xxx DRAM Controller
0bf7 Atom Processor D2xxx/N2xxx DRAM Controller
0c00 4th Gen Core Processor DRAM Controller
+ 103c 1998 EliteDesk 800 G1
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
0c08 Xeon E3-1200 v3 Processor DRAM Controller
0c09 Xeon E3-1200 v3/4th Gen Core Processor PCI Express x4 Controller
0c0c Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 309f ThinkCentre M83
0c46 Atom Processor S1200 PCI Express Root Port 1
1539 I211 Gigabit Network Connection
153a Ethernet Connection I217-LM
103c 1909 ZBook 15
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 309f ThinkCentre M83
153b Ethernet Connection I217-V
8086 0009 Ethernet Network Adapter E810-C-Q1
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
1593 Ethernet Controller E810-C for SFP
1137 02c3 E810XXVDA4 4x25/10 GbE SFP28 PCIe NIC
8086 0002 Ethernet Network Adapter E810-L-2
15d3 JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016]
15d4 JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016]
15d5 Ethernet SDI Adapter FM10420-25GbE-DA2
- 8086 0001 Intel(R) Ethernet SDI Adapter FM10420-25GbE-DA2
+ 8086 0001 Ethernet SDI Adapter FM10420-25GbE-DA2
15d6 Ethernet Connection (5) I219-V
15d7 Ethernet Connection (4) I219-LM
15d8 Ethernet Connection (4) I219-V
15ec JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018]
15ef JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018]
15f0 JHL7540 Thunderbolt 3 USB Controller [Titan Ridge DD 2018]
- 15f2 Intel(R) Ethernet Controller I225-LM
- 15f3 Intel(R) Ethernet Controller I225-V
+ 15f2 Ethernet Controller I225-LM
+ 8086 0001 Ethernet Network Adapter I225-T1
+ 8086 0002 Ethernet Network Adapter I225-T1
+ 15f3 Ethernet Controller I225-V
15f4 Ethernet Connection (15) I219-LM
15f5 Ethernet Connection (15) I219-V
15f6 I210 Gigabit Ethernet Connection
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 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16)
+ 1901 6th-9th 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
1775 11cc CC11/CL11
27e2 82801GR/GH/GHM (ICH7 Family) PCI Express Port 6
1775 11cc CC11/CL11
- 280b Intel(R) Display Audio
2810 82801HB/HR (ICH8/R) LPC Interface Controller
1043 81ec P5B
2811 82801HEM (ICH8M-E) LPC Interface Controller
2ffc Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers
2ffd Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers
2ffe Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers
+ 3140 Easel/Monette Hill Image Processor [Pixel Visual Core]
3165 Wireless 3165
# Stone Peak 1x1
8086 4010 Dual Band Wireless AC 3165
3185 UHD Graphics 605
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
3192 Gemini Lake P2SB
3197 Celeron/Pentium Silver Processor PCI-default ISA-bridge
3198 Celeron/Pentium Silver Processor High Definition Audio
31d9 Gemini Lake PCI Express Root Port
31da Gemini Lake PCI Express Root Port
31db Gemini Lake PCI Express Root Port
+ 31dc AC 1550i Wireless
31ee Celeron/Pentium Silver Processor Serial IO UART Host Controller
31f0 Gemini Lake Host Bridge
3200 GD31244 PCI-X SATA HBA
372c Xeon C5500/C3500 Reserved
373f Xeon C5500/C3500 IOxAPIC
37c8 C62x Chipset QuickAssist Technology
+ 8086 0001 QuickAssist Adapter 8960
+ 8086 0002 QuickAssist Adapter 8970
37cc Ethernet Connection X722
37cd Ethernet Virtual Function 700 Series
37ce Ethernet Connection X722 for 10GbE backplane
3e18 8th Gen Core 4-core Workstation Processor Host Bridge/DRAM Registers [Coffee Lake S]
3e1f 8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S]
1458 5000 Z370 AORUS Gaming K3-CF
- 3e30 8th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S]
+ 3e30 8th/9th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S]
3e33 8th/9th Gen Core Processor Host Bridge/DRAM Registers [Coffee Lake]
3e34 Coffee Lake HOST and DRAM Controller
3e81 8th Gen Core Processor PCIe Controller (x16)
8a1f Ice Lake Thunderbolt 3 PCI Express Root Port #1
8a21 Ice Lake Thunderbolt 3 PCI Express Root Port #2
8a23 Ice Lake Thunderbolt 3 PCI Express Root Port #3
- 8a51 Intel Iris Plus Graphics G7 (Ice Lake)
+ 8a51 Iris Plus Graphics G7 (Ice Lake)
8a52 Iris Plus Graphics G7
8a56 Iris Plus Graphics G1 (Ice Lake)
8a5a Iris Plus Graphics G4 (Ice Lake)
- 8a5c Intel Iris Plus Graphics G4 (Ice Lake)
+ 8a5c Iris Plus Graphics G4 (Ice Lake)
8c00 8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode]
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 309f ThinkCentre M83
8c03 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
103c 1909 ZBook 15
8c0e 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
8c0f 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
8c10 8 Series/C220 Series Chipset Family PCI Express Root Port #1
+ 103c 1998 EliteDesk 800 G1
1043 8534 ASUS H81I-PLUS
17aa 220e ThinkPad T440p
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
17aa 220e ThinkPad T440p
8c13 8 Series/C220 Series Chipset Family PCI Express Root Port #2
8c14 8 Series/C220 Series Chipset Family PCI Express Root Port #3
8c1f 8 Series/C220 Series Chipset Family PCI Express Root Port #8
8c20 8 Series/C220 Series Chipset High Definition Audio Controller
103c 1909 ZBook 15
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 309f ThinkCentre M83
8c21 8 Series/C220 Series Chipset High Definition Audio Controller
8c22 8 Series/C220 Series Chipset Family SMBus Controller
103c 1909 ZBook 15
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 309f ThinkCentre M83
8c23 8 Series Chipset Family CHAP Counters
8c24 8 Series Chipset Family Thermal Management Controller
8c26 8 Series/C220 Series Chipset Family USB EHCI #1
103c 1909 ZBook 15
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 2210 ThinkPad T540p
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 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 309f ThinkCentre M83
8c33 8 Series/C220 Series Chipset Family LAN Controller
8c34 8 Series/C220 Series Chipset Family NAND Controller
8c3a 8 Series/C220 Series Chipset Family MEI Controller #1
103c 1909 ZBook 15
+ 103c 1998 EliteDesk 800 G1
17aa 220e ThinkPad T440p
17aa 309f ThinkCentre M83
8c3b 8 Series/C220 Series Chipset Family MEI Controller #2
8c3c 8 Series/C220 Series Chipset Family IDE-r Controller
8c3d 8 Series/C220 Series Chipset Family KT Controller
+ 103c 1998 EliteDesk 800 G1
8c40 8 Series/C220 Series Chipset Family LPC Controller
8c41 8 Series Chipset Family Mobile Super SKU LPC Controller
8c42 8 Series/C220 Series Chipset Family Desktop Super SKU LPC Controller
17aa 309f ThinkCentre M83
8c4d 8 Series/C220 Series Chipset Family LPC Controller
8c4e Q87 Express LPC Controller
+ 103c 1998 EliteDesk 800 G1
8c4f QM87 Express LPC Controller
103c 1909 ZBook 15
17aa 220e ThinkPad T440p
9b41 UHD Graphics
9b44 10th Gen Core Processor Host Bridge/DRAM Registers
9b54 10th Gen Core Processor Host Bridge/DRAM Registers
+ 9b61 Comet Lake-U v1 4c Host Bridge/DRAM Controller
9b64 10th Gen Core Processor Host Bridge/DRAM Registers
9bc4 UHD Graphics
+ 9bc8 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]
1a56 1552 Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)
a379 Cannon Lake PCH Thermal Controller
1028 0869 Vostro 3470
+ a382 400 Series Chipset Family SATA AHCI Controller
+ a3a3 Comet Lake PCH-V SMBus Host Controller
+ a3b1 Comet Lake PCH-V Thermal Subsystem
a620 6400/6402 Advanced Memory Buffer (AMB)
abc0 Omni-Path Fabric Switch Silicon 100 Series
b152 21152 PCI-to-PCI Bridge
d158 Core Processor Miscellaneous Registers
f1a5 SSD 600P Series
f1a6 SSD Pro 7600p/760p/E 6100p Series
- 8086 390b Intel Corporation SSD Pro 7600p/760p/E 6100p Series [NVM Express]
+ 8086 390b SSD Pro 7600p/760p/E 6100p Series [NVM Express]
f1a8 SSD 660P Series
8088 Beijing Wangxun Technology Co., Ltd.
0101 WX1860A2 Gigabit Ethernet Controller
9005 0552 Series 8 - ASR-8805 - 8 internal 0 external 12G SAS Port/PCIe 3.0
9005 0553 Series 8 - ASR-8085 - 0 internal 8 external 12G SAS Port/PCIe 3.0
9005 0554 Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0
- 028f Smart Storage PQI 12G SAS/PCIe 3
+ 028f Smart Storage PQI SAS
103c 0600 Smart Array P408i-p SR Gen10
103c 0601 Smart Array P408e-p SR Gen10
103c 0602 Smart Array P408i-a SR Gen10
C 00 Unclassified device
00 Non-VGA unclassified device
01 VGA compatible unclassified device
+ 05 Image coprocessor
C 01 Mass storage controller
00 SCSI storage controller
01 IDE interface
<tr class="even"><td>Torus Systems Ltd</td><td>TRS</td><td>11/29/1996</td> </tr>
<tr class="odd"><td>Toshiba America Info Systems Inc</td><td>TAI</td><td>11/29/1996</td> </tr>
<tr class="even"><td>Toshiba America Info Systems Inc</td><td>TSB</td><td>11/29/1996</td> </tr>
- <tr class="odd"><td>Toshiba Corporation</td><td>TOS</td><td>11/29/1996</td> </tr>
+ <tr class="odd"><td>Dynabook Inc.</td><td>TOS</td><td>11/29/1996</td> </tr>
<tr class="even"><td>Toshiba Corporation</td><td>TTP</td><td>07/07/2015</td> </tr>
<tr class="odd"><td>Toshiba Global Commerce Solutions, Inc.</td><td>TGC</td><td>06/26/2012</td> </tr>
<tr class="even"><td>Toshiba Matsushita Display Technology Co., Ltd</td><td>LCD</td><td>05/24/2000</td> </tr>
<tr class="even"><td>TECNART CO.,LTD.</td><td>PIS</td><td>10/22/2019</td> </tr>
<tr class="odd"><td>Moxa Inc.</td><td>MHQ</td><td>10/22/2019</td> </tr>
<tr class="even"><td>Disguise Technologies</td><td>DSG</td><td>10/22/2019</td> </tr>
+ <tr class="odd"><td>Comark LLC</td><td>CMK</td><td>07/15/2020</td> </tr>
+ <tr class="even"><td>Megapixel Visual Realty</td><td>MPV</td><td>07/15/2020</td> </tr>
+ <tr class="odd"><td>Skyworth</td><td>SKW</td><td>07/15/2020</td> </tr>
+ <tr class="even"><td>Meta View, Inc.</td><td>CFR</td><td>07/15/2020</td> </tr>
+ <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>
</tbody>
</table>
</body>
# The latest version can be obtained from
# http://www.linux-usb.org/usb.ids
#
-# Version: 2020.07.06
-# Date: 2020-07-06 20:34:08
+# Version: 2020.08.26
+# Date: 2020-08-26 20:34:09
#
# Vendors, devices and interfaces. Please keep sorted.
3111 OfficeJet 4100 series
3117 EWS 2605dtn
311d Atheros AR9285 Malbec Bluetooth Adapter
+ 312a LaserJet Pro M701n
3202 PhotoSmart 1215
3207 4 GB flash drive
3211 OfficeJet 4105 series
3220 Sound Blaster Tactic(3D) Sigma sound card
3232 Sound Blaster Premium HD [SBX]
3237 SB X-Fi Surround 5.1 Pro
+ 3263 SB X-Fi Surround 5.1 Pro
3f00 E-Mu Xboard 25 MIDI Controller
3f02 E-Mu 0202
3f04 E-Mu 0404
c22d G510 Gaming Keyboard
c22e G510 Gaming Keyboard onboard audio
c231 G13 Virtual Mouse
+ c232 Gaming Virtual Keyboard
c245 G400 Optical Mouse
c246 Gaming Mouse G300
c247 G100S Optical Gaming Mouse
c008 Audio 655 DSP
c00e Blackwire C310 headset
c03b HD1
+ da60 DA60
0480 Toshiba America Inc
0001 InTouch Module
0004 InTouch Module
048d Integrated Technology Express, Inc.
1165 IT1165 Flash Controller
1172 Flash Drive
- 1234 Mass storage
+ 1234 Chipsbank CBM2199 Flash Drive
1336 SD/MMC Cardreader
1345 Multi Cardreader
8297 IT8297 RGB LED Controller
a050 Chatman V1
a052 USB-zyTemp
a055 Keyboard
+ a075 Optical Gaming Mouse
a096 Keyboard
a09f E-Signal LUOM G10 Mechanical Gaming Mouse
a100 Mouse [HV-MS735]
685c GT-I9250 Phone [Galaxy Nexus] (Mass storage mode)
685d GT-I9100 Phone [Galaxy S II] (Download mode)
685e GT-I9100 / GT-C3350 Phones (USB Debugging mode)
- 6860 Galaxy series, misc. (MTP mode)
+ 6860 Galaxy A5 (MTP)
6863 Galaxy series, misc. (tethering mode)
6864 GT-I9070 (network tethering, USB debugging enabled)
6865 Galaxy (PTP mode)
1080 NET1080 USB-USB Bridge
1200 SSDC Adapter II
1265 File-backed Storage Gadget
- 3424 Lumidigm Venus fingerprint sensor
+ 3424 V30x/V4xx fingerprint sensor [Lumidigm]
a0f0 Cambridge Electronic Devices Power1401 mk 2
a140 USB Clik! 40
a141 (OME) PocketZip 40 MP3 Player Driver
a4a2 Linux-USB Ethernet/RNDIS Gadget
a4a3 Linux-USB user-mode isochronous source/sink
a4a4 Linux-USB user-mode bulk source/sink
- a4a5 Pocketbook Pro 903 / Mobius 2 Action Cam / xDuoo X3
+ a4a5 Pocketbook Pro 903 / Mobius 2 Action Cam / xDuoo X3 / PocketBook Pro 602
a4a6 Linux-USB Serial Gadget
a4a7 Linux-USB Serial Gadget (CDC ACM mode)
a4a8 Linux-USB Printer Gadget
035b Walkman NWZ-A828
035c NWZ-A726/A728/A729
035f UP-DR200 Photo Printer
+ 0360 M2 Card Reader
0382 Memory Stick PRO-HG Duo Adaptor (MSAC-UAH1)
0385 Walkman NWZ-E436F
0387 IC Recorder (P)
106d Porsche Design Mobile Drive
106e Porsche Design Desktop Drive
1094 Rugged THB
+ 1095 Rugged
a601 HardDrive
a602 CD R/W
05a0 Vetronix Corp.
4001 Bluetooth Headset in DFU mode
4002 Bluetooth Headset Series 2
4003 Bluetooth Headset Series 2 in DFU mode
+ 400d SoundLink Color II speaker in DFU mode
+ 40fe SoundLink Color II speaker
bc50 SoundLink Wireless Mobile speaker
bc51 SoundLink Wireless Mobile speaker in DFU mode
05a8 Spacetec IMC Corp.
0361 SunplusIT INC. HP Truevision HD Webcam
036e Webcam
0374 HP EliteBook integrated HD Webcam
+ 038e HP Wide Vision HD integrated webcam
03a1 XiaoMi Webcam
03b1 Webcam
03bc HP Wide Vision HD Integrated Webcam
0610 Onext EG210U MODEM
0611 AlDiga AL-11U Quad-band GSM/GPRS/EDGE modem
1231 Orico SATA External Hard Disk Drive Lay-Flat Docking Station with USB 3.0 & eSATA interfaces.
- 2303 PL2303 Serial Port
+ 2303 PL2303 Serial Port / Mobile Action MA-8910P
2305 PL2305 Parallel Port
2306 Raylink Bridge Controller
2307 PL2307 USB-ATAPI4 Bridge
01c9 OKI B430 Mono Printer
020b OKI ES4140 Mono Printer
02bb OKI PT390 POS Printer
+ 0383 MC563 Multifunction Printer
0a91 B2500MFP (printer+scanner)
3801 B6100 Laser Printer
06bd AGFA-Gevaert NV
b4b5 SDDR-89 V4 ImageMate 12-in-1 Reader
b6b7 SDDR-99 V4 ImageMate 5-in-1 Reader
b6ba CF SDDR-289
+ cfc9 SDDR-489 ImageMate Pro Reader
0782 Trackerball
0783 C3PO
0003 LTC31 SmartCard Reader
0968 Catalyst Enterprises, Inc.
096e Feitian Technologies, Inc.
0005 ePass2000
+ 0006 HID Dongle (for OEMs - manufacturer string is "OEM")
0120 Microcosm Ltd Dinkey
0305 ePass2000Auto
0309 ePass3000GM
0a5f Zebra
0009 LP2844 Printer
0050 P120i / WM120i
+ 0080 GK420d Label Printer
0081 GK420t Label Printer
0084 GX420d Desktop Label Printer
008b HC100 wristbands Printer
ff01 Wireless Missile Launcher
0a82 Syscan
4600 TravelScan 460/464
+ 6605 ScanShell 800N
0a83 NextComm, Inc.
0a84 Maui Innovative Peripherals
0a85 Idexx Labs
b728 RTL8723B Bluetooth
b72a RTL8723B Bluetooth
b812 RTL88x2bu [AC1200 Techkey]
+ f179 RTL8188FTV 802.11b/g/n 1T1R 2.4G WLAN Adapter
0bdb Ericsson Business Mobile Networks BV
1000 BV Bluetooth Device
1002 Bluetooth Device 1.2
0c3c Radius Co., Ltd
0c3d Innocom, Inc.
0c3e Nextcell, Inc.
+0c40 ELMCU
+ 8000 2.4GHz receiver
0c44 Motorola iDEN
0021 iDEN P2k0 Device
0022 iDEN P2k1 Device
1158 A56AK
184c VoIP Phone
1a90 2M pixel Microscope Camera (with capture button) [Andonstar V160]
+ 5004 Redragon Mitra RGB Keyboard
5101 2.4G Wireless Device [Rii MX3]
6001 Genius VideoCAM NB
6005 Sweex Mini Webcam
0f69 Dionex Corp.
0f6a Vibren Technologies, Inc.
0f6e INTELLIGENT SYSTEMS
- 0100 GameBoy Color Emulator
+ 0100 IS-CGB-EMULATOR
0201 GameBoy Advance Flash Gang Writer
- 0202 GameBoy Advance Capture
- 0300 Gamecube DOL Viewer
- 0400 NDS Emulator
- 0401 NDS UIC
- 0402 NDS Writer
- 0403 NDS Capture
- 0404 NDS Emulator (Lite)
+ 0202 IS-AGB-CAPTURE
+ 0300 IS-DOL-VIEWER
+ 0400 IS-NITRO-EMULATOR
+ 0401 IS-NITRO-UIC
+ 0402 IS-NITRO-WRITER
+ 0403 IS-NITRO-CAPTURE
+ 0404 IS-NITRO-EMULATOR (DS Lite)
+ 0500 IS-TWL-DEBUGGER
+ 0501 IS-TWL-CAPTURE
0f73 DFI
0f78 Guntermann & Drunck GmbH
0f7c DQ Technology, Inc.
1501 Pine-Tum Enterprise Co., Ltd.
1504 Bixolon CO LTD
001f SRP-350II Thermal Receipt Printer
+1508 Fibocom
1509 First International Computer, Inc.
0a01 LI-3100 Area Meter
0a02 LI-7000 CO2/H2O Gas Analyzer
004a RZ03-0133 Gaming Lapboard, Keyboard Mouse Combo, Dongle [Turret Dongle]
004c Diamondback Chroma
004d DeathAdder 2000 (Cynosa Pro Bundle)
+ 004f RZ01-0145, Gaming Mouse [DeathAdder 2000 (Alternate)]
0050 Naga Hex V2
0053 Naga Chroma
0054 DeathAdder 3500
007a RC30-0305 Gaming Mouse [Viper Ultimate (Wired)]
007b RC30-0305 Gaming Mouse Dongle [Viper Ultimate (Wireless)]
007e RC30-030502 Mouse Dock
+ 0083 RC30-0315, Gaming Mouse [Basilisk X HyperSpeed]
0084 RZ01-0321 Gaming Mouse [DeathAdder V2]
0085 RZ01-0316 Gaming Mouse [Basilisk V2]
- 0088 Razer Basilisk Ultimate Dongle
+ 0086 Gaming Mouse [Basilisk Ultimate, Wired]
+ 0088 Gaming Mouse [Basilisk Ultimate, Wireless, Receiver]
+ 008a RZ01-0325, Gaming Mouse [Viper Mini]
0101 Copperhead Mouse
0102 Tarantula Keyboard
0103 Gaming Keyboard [Reclusa]
024d Blade 15 Studio Edition (2019)
0253 RZ09-0330, Gaming Laptop [Blade 15 Advanced (Early 2020)]
0255 RZ09-0328, Gaming Laptop [Blade 15 Base Model (2020)]
+ 0256 RZ09--0329, Gaming Laptop [Blade Pro 17 Full HD (2020)]
+ 025d RZ03-0338, Gaming Keyboard [Ornata V2]
0300 RZ06-0063 Motion Sensing Controllers [Hydra]
0401 Gaming Arcade Stick [Panthera]
0501 Kraken 7.1
051a Nari Ultimate
051c Nari (Wireless)
051d Nari (Wired)
+ 051e RC30-026902, Gaming Headset [Nari Essential, Wireless, Receiver]
+ 051f RC30-026901, Gaming Headset [Nari Essential, Wired]
0520 Kraken Tournament Edition
0521 Kraken Kitty Edition
0527 RZ04-0318 Gaming Headset [Kraken Ultimate]
0a00 Atrox Arcade Stick for Xbox One
0a02 ManO'War
0a03 Wildcat
+ 0a15 RZ06-0199, Gaming Controller [Wolverine Tournament Edition]
0c00 RZ02-0135 Hard Gaming Mouse Mat [Firefly]
0c01 Goliathus
0c02 Goliathus Extended
8007 US-122 Audio/Midi Interface
1605 ACCES I/O Products, Inc.
0001 DIO-32 (No Firmware Yet)
+ 0002 USB-DIO-48 (No Firmware Yet)
+ 0003 USB-DIO-96 (No Firmware Yet)
+ 0004 USB-DIO-32I (No Firmware Yet)
+ 0005 USB-DIO24 (based on -CTR6) (No Firmware Yet)
+ 0006 USB-DIO24-CTR6 (No Firmware Yet)
1606 Umax
0002 Astra 1236U Scanner
0010 Astra 1220U
<refnamediv>
<refname>bootctl</refname>
- <refpurpose>Control the firmware and boot manager settings</refpurpose>
+ <refpurpose>Control EFI firmware boot settings and manage boot loader</refpurpose>
</refnamediv>
<refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para><command>bootctl</command> can check the EFI boot loader status, list available boot loaders and boot loader
- entries, and install, update, or remove the
- <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> boot loader on the
- current system.</para>
+ <para><command>bootctl</command> can check the EFI firmware and boot loader status, list and manage
+ available boot loaders and boot loader entries, and install, update, or remove the
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> boot
+ loader on the current system.</para>
</refsect1>
<refsect1>
- <title>Commands</title>
- <variablelist>
+ <title>Generic EFI Firmware/Boot Loader Commands</title>
+
+ <para>These commands are available on any EFI system, regardless of the boot loader used.</para>
+ <variablelist>
<varlistentry>
<term><option>status</option></term>
loaders and the current default boot loader entry. If no command is specified, this is the implied
default.</para></listitem>
</varlistentry>
+ </variablelist>
+
+ <varlistentry>
+ <term><option>reboot-to-firmware</option> <optional><replaceable>BOOL</replaceable></optional></term>
+
+ <listitem><para>Query or set the "Reboot-Into-Firmware-Setup" flag of the EFI firmware. Takes a
+ boolean argument which controls whether to show the firmware setup on next system reboot. If the
+ argument is omitted shows the current status of the flag, or whether the flag is supported. This
+ controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more
+ low-level and allows setting the flag independently from actually requesting a
+ reboot.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>systemd-efi-options</option> <optional><replaceable>STRING</replaceable></optional></term>
+
+ <listitem><para>When called without the optional argument, prints the current value of the
+ <literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the
+ variable to that value. See
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ for the meaning of that variable.</para></listitem>
+ </varlistentry>
+ </refsect1>
+
+ <refsect1>
+ <title>Boot Loader Specification Commands</title>
+
+ <para>These commands are available for all boot loaders that implement the <ulink
+ url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink> and/or the <ulink
+ url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>, such as
+ <command>systemd-boot</command>.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>list</option></term>
+
+ <listitem><para>Shows all available boot loader entries implementing the <ulink
+ url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>, as well as any
+ other entries discovered or automatically generated by a boot loader implementing the <ulink
+ url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader
+ Interface</ulink>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>set-default</option> <replaceable>ID</replaceable></term>
+ <term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
+
+ <listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string as
+ argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
+ the <option>set-default</option> will set it persistently for all future boots.</para></listitem>
+
+ <listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
+ <option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
+ entry for all future boots, the current default boot loader entry for the next boot, and the currently booted
+ boot loader entry. These special IDs are resolved to the current values of the EFI variables
+ <varname>LoaderEntryDefault</varname>, <varname>LoaderEntryOneShot</varname> and <varname>LoaderEntrySelected</varname>,
+ see <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink> for details.
+ These special IDs are primarily useful as a quick way to persistently make the currently booted boot loader
+ entry the default choice, or to upgrade the default boot loader entry for the next boot to the default boot
+ loader entry for all future boots, but may be used for other operations too.
+ </para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title><command>systemd-boot</command> Commands</title>
+
+ <para>These commands manage the <command>systemd-boot</command> EFI boot loader, and do not work in
+ conjunction with other boot loaders.</para>
+
+ <variablelist>
<varlistentry>
<term><option>install</option></term>
information.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><option>systemd-efi-options</option> <optional><replaceable>STRING</replaceable></optional></term>
-
- <listitem><para>When called without the optional argument, prints the current value of the
- <literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the
- variable to that value. See
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- for the meaning of that variable.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>reboot-to-firmware</option> <optional><replaceable>BOOL</replaceable></optional></term>
-
- <listitem><para>Query or set the "Reboot-Into-Firmware-Setup" flag of the EFI firmware. Takes a
- boolean argument which controls whether to show the firmware setup on next system reboot. If the
- argument is omitted shows the current status of the flag, or whether the flag is supported. This
- controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more
- low-level and allows setting the flag independently from actually requesting a
- reboot.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>list</option></term>
-
- <listitem><para>Shows all available boot loader entries implementing the <ulink
- url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader
- Specification</ulink>, as well as any other entries discovered or automatically generated by the boot
- loader.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>set-default</option> <replaceable>ID</replaceable></term>
- <term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
-
- <listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string as argument. The
- <option>set-oneshot</option> command will set the default entry only for the next boot, the
- <option>set-default</option> will set it persistently for all future boots.</para></listitem>
- </varlistentry>
-
</variablelist>
</refsect1>
<filename>initrd-root-fs.target</filename> is reached. The service
<filename>initrd-parse-etc.service</filename> scans
<filename>/sysroot/etc/fstab</filename> for a possible
- <filename>/usr</filename> mount point and additional entries
+ <filename>/usr/</filename> mount point and additional entries
marked with the <emphasis>x-initrd.mount</emphasis> option. All
entries found are mounted below <filename>/sysroot</filename>, and
<filename>initrd-fs.target</filename> is reached. The service
<para>Controls whether credential data reported by
<command>list</command> or <command>status</command> shall
be augmented with data from
- <filename>/proc</filename>. When this is turned on, the data
+ <filename>/proc/</filename>. When this is turned on, the data
shown is possibly inconsistent, as the data read from
- <filename>/proc</filename> might be more recent than the rest of
+ <filename>/proc/</filename> might be more recent than the rest of
the credential information. Defaults to <literal>yes</literal>.</para>
</listitem>
</varlistentry>
device or file, or a specification of a block device via
<literal>UUID=</literal> followed by the UUID.</para>
- <para>The third field specifies an absolute path to a file to read the encryption key from. Optionally,
+ <para>The third field specifies an absolute path to a file with the encryption key. Optionally,
the path may be followed by <literal>:</literal> and an fstab device specification (e.g. starting with
- <literal>LABEL=</literal> or similar); in which case, the path is relative to the device file system
- root. If the field is not present or set to <literal>none</literal> or <literal>-</literal>, a key file
+ <literal>LABEL=</literal> or similar); in which case the path is taken relative to the device file system
+ root. If the field is not present or is <literal>none</literal> or <literal>-</literal>, a key file
named after the volume to unlock (i.e. the first column of the line), suffixed with
<filename>.key</filename> is automatically loaded from the <filename>/etc/cryptsetup-keys.d/</filename>
and <filename>/run/cryptsetup-keys.d/</filename> directories, if present. Otherwise, the password has to
<varlistentry>
<term><option>cipher=</option></term>
- <listitem><para>Specifies the cipher to use. See
- <citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for possible values and the default value of this option. A
- cipher with unpredictable IV values, such as
- <literal>aes-cbc-essiv:sha256</literal>, is
- recommended.</para></listitem>
+ <listitem><para>Specifies the cipher to use. See <citerefentry
+ project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for possible values and the default value of this option. A cipher with unpredictable IV values, such
+ as <literal>aes-cbc-essiv:sha256</literal>, is recommended. Embedded commas in the cipher
+ specification need to be escaped by preceding them with a backslash, see example below.</para>
+ </listitem>
</varlistentry>
<varlistentry>
relevant for LUKS devices. See
<citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default value of this
- option.</para></listitem>
+ option.</para>
+
+ <para>Optionally, the path may be followed by <literal>:</literal> and an fstab device specification
+ (e.g. starting with <literal>UUID=</literal> or similar); in which case, the path is relative to the
+ device file system root. The device gets mounted automatically for LUKS device activation duration only.
+ </para></listitem>
</varlistentry>
<varlistentry>
<title>Examples</title>
<example>
<title>/etc/crypttab example</title>
- <para>Set up four encrypted block devices. One using LUKS for
- normal storage, another one for usage as a swap device and two
- TrueCrypt volumes.</para>
+ <para>Set up four encrypted block devices. One using LUKS for normal storage, another one for usage as
+ a swap device and two TrueCrypt volumes. For the fourth device, the option string is interpreted as two
+ options <literal>cipher=xchacha12,aes-adiantum-plain64</literal>,
+ <literal>keyfile-timeout=10s</literal>.</para>
<programlisting>luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b
swap /dev/sda7 /dev/urandom swap
truecrypt /dev/sda2 /etc/container_password tcrypt
hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile
-external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s</programlisting>
+external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s,cipher=xchacha12\,aes-adiantum-plain64
+</programlisting>
</example>
<example>
and follow the same overriding rules. They are text files with the
<filename>.negative</filename> suffix. Empty lines and lines whose first character is
<literal>;</literal> are ignored. Each line specifies one domain name which is the root of a DNS
- subtree where validation shall be disabled.</para>
+ subtree where validation shall be disabled. For example:</para>
+
+ <programlisting># Reverse IPv4 mappings
+10.in-addr.arpa
+16.172.in-addr.arpa
+168.192.in-addr.arpa
+...
+# Some custom domains
+prod
+stag
+</programlisting>
<para>Negative trust anchors are useful to support private DNS
subtrees that are not referenced from the Internet DNS hierarchy,
<title>Setup environment to allow access to a program installed in
<filename index="false">/opt/foo</filename></title>
- <para><filename>/etc/environment.d/60-foo.conf</filename>:
+ <para><filename index="false">/etc/environment.d/60-foo.conf</filename>:
</para>
<programlisting>
FOO_DEBUG=force-software-gl,log-verbose
<term><filename>/tmp/</filename></term>
<listitem><para>The place for small temporary files. This directory is usually mounted as a
<literal>tmpfs</literal> instance, and should hence not be used for larger files. (Use
- <filename>/var/tmp/</filename> for larger files.) Since the directory is accessible to other users of
- the system, it is essential that this directory is only written to with the <citerefentry
- project='man-pages'><refentrytitle>mkstemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry
- project='man-pages'><refentrytitle>mkdtemp</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
- related calls. This directory is usually flushed at boot-up. Also, files that are not accessed within
- a certain time are usually automatically deleted. If applications find the environment variable
- <varname>$TMPDIR</varname> set, they should prefer using the directory specified in it over directly
- referencing <filename>/tmp/</filename> (see <citerefentry
+ <filename>/var/tmp/</filename> for larger files.) This directory is usually flushed at boot-up. Also,
+ files that are not accessed within a certain time may be automatically deleted.</para>
+
+ <para>If applications find the environment variable <varname>$TMPDIR</varname> set, they should use
+ the directory specified in it instead of <filename>/tmp/</filename> (see <citerefentry
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> and
<ulink url="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03">IEEE
- Std 1003.1</ulink> for details). For further details about this directory, see <ulink
- url="https://systemd.io/TEMPORARY_DIRECTORIES">Using /tmp/ And /var/tmp/
- Safely</ulink>.</para></listitem>
+ Std 1003.1</ulink> for details).</para>
+
+ <para>Since <filename>/tmp/</filename> is accessible to other users of the system, it is essential
+ that files and subdirectories under this directory are only created with <citerefentry
+ project='man-pages'><refentrytitle>mkstemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry
+ project='man-pages'><refentrytitle>mkdtemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ and similar calls. For more details, see <ulink url="https://systemd.io/TEMPORARY_DIRECTORIES">Using
+ /tmp/ and /var/tmp/ Safely</ulink>.</para>
+ </listitem>
</varlistentry>
</variablelist>
<term><filename>/var/tmp/</filename></term>
<listitem><para>The place for larger and persistent temporary files. In contrast to
<filename>/tmp/</filename>, this directory is usually mounted from a persistent physical file system
- and can thus accept larger files. (Use <filename>/tmp/</filename> for smaller files.) This directory
- is generally not flushed at boot-up, but time-based cleanup of files that have not been accessed for
- a certain time is applied. The same security restrictions as with <filename>/tmp/</filename> apply,
- and hence only <citerefentry
+ and can thus accept larger files. (Use <filename>/tmp/</filename> for small ephemeral files.) This
+ directory is generally not flushed at boot-up, but time-based cleanup of files that have not been
+ accessed for a certain time is applied.</para>
+
+ <para>If applications find the environment variable <varname>$TMPDIR</varname> set, they should use
+ the directory specified in it instead of <filename>/var/tmp/</filename> (see <citerefentry
+ project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ details).</para>
+
+ <para>The same security restrictions as with <filename>/tmp/</filename> apply: <citerefentry
project='man-pages'><refentrytitle>mkstemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry
- project='man-pages'><refentrytitle>mkdtemp</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
- similar calls should be used to make use of this directory. If applications find the environment
- variable <varname>$TMPDIR</varname> set, they should prefer using the directory specified in it over
- directly referencing <filename>/var/tmp/</filename> (see <citerefentry
- project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
- details). For further details about this directory, see <ulink
- url="https://systemd.io/TEMPORARY_DIRECTORIES">Using /tmp/ And /var/tmp/
- Safely</ulink>.</para></listitem>
+ project='man-pages'><refentrytitle>mkdtemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ and similar calls should be used. For further details about this directory, see <ulink
+ url="https://systemd.io/TEMPORARY_DIRECTORIES">Using /tmp/ and /var/tmp/ Safely</ulink>.</para>
+ </listitem>
</varlistentry>
</variablelist>
directives of service units (see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details).</para>
+
+ <para><filename>/tmp/</filename>, <filename>/var/tmp/</filename> and <filename>/dev/shm/</filename>
+ should be mounted <option>nosuid</option> and <option>nodev</option>, which means that set-user-id mode
+ and character or block special devices are not interpreted on those file systems. In general it is not
+ possible to mount them <option>noexec</option>, because various programs use those directories for
+ dynamically generated or optimized code, and with that flag those use cases would break. Using this flag
+ is OK on special-purpose installations or systems where all software that may be installed is known and
+ doesn't require such functionality. See the discussion of
+ <option>nosuid</option>/<option>nodev</option>/<option>noexec</option> in <citerefentry
+ project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> and
+ <constant>PROT_EXEC</constant> in <citerefentry
+ project='man-pages'><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
+ </para>
</refsect1>
<refsect1>
<refsect1>
<title>System Packages</title>
- <para>Developers of system packages should follow strict rules
- when placing their own files in the file system. The following
- table lists recommended locations for specific types of files
- supplied by the vendor.</para>
+ <para>Developers of system packages should follow strict rules when placing their files in the file
+ system. The following table lists recommended locations for specific types of files supplied by the
+ vendor.</para>
<table>
- <title>System Package Vendor Files Locations</title>
+ <title>System package vendor files locations</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="directory" />
<colspec colname="purpose" />
<filename>/usr/share/</filename> hierarchy to the locations
defined by the various relevant specifications.</para>
- <para>During runtime, and for local configuration and runtime state,
- additional directories are defined:</para>
+ <para>The following directories shall be used by the package for local configuration and files created
+ during runtime:</para>
<table>
- <title>System Package Variable Files Locations</title>
+ <title>System package variable files locations</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="directory" />
<colspec colname="purpose" />
<refsect1>
<title>User Packages</title>
- <para>Programs running in user context should follow strict rules
- when placing their own files in the user's home directory. The
- following table lists recommended locations in the home directory
- for specific types of files supplied by the vendor if the
- application is installed in the home directory. (Note, however,
- that user applications installed system-wide should follow the
- rules outlined above regarding placing vendor files.)</para>
+ <para>Programs running in user context should follow strict rules when placing their own files in the
+ user's home directory. The following table lists recommended locations in the home directory for specific
+ types of files supplied by the vendor if the application is installed in the home directory. (User
+ applications installed system-wide are covered by the rules outlined above for vendor files.)</para>
<table>
- <title>User Package Vendor File Locations</title>
+ <title>Vendor package file locations under the home directory of the user</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="directory" />
<colspec colname="purpose" />
</row>
<row>
<entry><filename>~/.local/lib/<replaceable>arch-id</replaceable>/</filename></entry>
- <entry>Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes.</entry>
+ <entry>Public shared libraries of the package. As above, be careful with using overly generic names, and pick unique names for your libraries to place here to avoid name clashes.</entry>
</row>
<row>
<entry><filename>~/.local/lib/<replaceable>package</replaceable>/</filename></entry>
</tgroup>
</table>
- <para>Additional static vendor files may be installed in the
- <filename>~/.local/share/</filename> hierarchy to the locations
- defined by the various relevant specifications.</para>
+ <para>Additional static vendor files may be installed in the <filename>~/.local/share/</filename>
+ hierarchy, mirroring the subdirectories specified in the section "Vendor-supplied operating system
+ resources" above.</para>
- <para>During runtime, and for local configuration and state,
- additional directories are defined:</para>
+ <para>The following directories shall be used by the package for per-user local configuration and files
+ created during runtime:</para>
<table>
- <title>User Package Variable File Locations</title>
+ <title>User package variable file locations</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="directory" />
<colspec colname="purpose" />
<listitem><para>Read the user's JSON record from the specified file. If passed as
<literal>-</literal> read the user record from standard input. The supplied JSON object must follow
- the structure documented on <ulink url="https://systemd.io/USER_RECORD">JSON User Records</ulink>.
+ the structure documented in <ulink url="https://systemd.io/USER_RECORD">JSON User Records</ulink>.
This option may be used in conjunction with the <command>create</command> and
<command>update</command> commands (see below), where it allows configuring the user record in JSON
as-is, instead of setting the individual user record properties (see below).</para></listitem>
<varlistentry>
<term><option>--timezone=</option><replaceable>TIMEZONE</replaceable></term>
- <listitem><para>Takes a timezone specification as string that sets the timezone for the specified
- user. Expects a `tzdata` location string. When the user logs in the <varname>$TZ</varname>
- environment variable is initialized from this setting. Example:
- <option>--timezone=Europe/Amsterdam</option> will result in the environment variable
- <literal>TZ=:Europe/Amsterdam</literal>.</para></listitem>
+ <listitem><para>Takes a time zone location name that sets the timezone for the specified user. When
+ the user logs in the <varname>$TZ</varname> environment variable is initialized from this
+ setting. Example: <option>--timezone=Europe/Amsterdam</option> will result in the environment
+ variable <literal>TZ=:Europe/Amsterdam</literal>. (<literal>:</literal> is used intentionally as part
+ of the timezone specification, see
+ <citerefentry project='man-pages'><refentrytitle>tzset</refentrytitle><manvolnum>3</manvolnum></citerefentry>.)
+ </para></listitem>
</varlistentry>
<varlistentry>
<listitem><para>Takes a path to a Linux <literal>hidraw</literal> device
(e.g. <filename>/dev/hidraw1</filename>), referring to a FIDO2 security token implementing the
- <literal>hmac-secret</literal> extension, that shall be able to unlock the user account. If used, a
- random salt value is generated on the host, which is passed to the FIDO2 device, which calculates a
- HMAC hash of it, keyed by its internal secret key. The result is then used as key for unlocking the
- user account. The random salt is included in the user record, so that whenever authentication is
- needed it can be passed again to the FIDO2 token, to retrieve the actual key.</para>
+ <literal>hmac-secret</literal> extension that shall be able to unlock the user account. A random salt
+ value is generated on the host and passed to the FIDO2 device, which calculates a HMAC hash of the
+ salt using an internal secret key. The result is then used as the key to unlock the user account. The
+ random salt is included in the user record, so that whenever authentication is needed it can be
+ passed to the FIDO2 token again.</para>
<para>Instead of a valid path to a FIDO2 <literal>hidraw</literal> device the special strings
<literal>list</literal> and <literal>auto</literal> may be specified. If <literal>list</literal> is
<listitem><para>Takes a password hint to store alongside the user record. This string is stored
accessible only to privileged users and the user itself and may not be queried by other users.
- Example: <option>--password-hint="My first pet's name"</option></para></listitem>
+ Example: <option>--password-hint="My first pet's name"</option>.</para></listitem>
</varlistentry>
<varlistentry>
their home directories are removed from memory.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>deactivate-all</command></term>
+
+ <listitem><para>Execute the <command>deactivate</command> command on all active home directories at
+ once. This operation is generally executed on system shut down (i.e. by <command>systemctl
+ poweroff</command> and related commands), to ensure all active user's home directories are fully
+ deactivated before <filename>/home/</filename> and related file systems are unmounted.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>with</command> <replaceable>USER</replaceable> <replaceable>COMMAND…</replaceable></term>
ninja -C "@BUILD_ROOT@" "$target"
fullname="@BUILD_ROOT@/$target"
-redirect="$(readlink "$fullname" 2>/dev/null)"
+redirect="$(test -f "$fullname" && readlink "$fullname" || :)"
if [ -n "$redirect" ]; then
ninja -C "@BUILD_ROOT@" "man/$redirect"
the local administration directory <filename>/etc/udev/hwdb.d</filename>.
All hwdb files are collectively sorted and processed in lexical order,
regardless of the directories in which they live. However, files with
- identical filenames replace each other. Files in <filename>/etc</filename>
+ identical filenames replace each other. Files in <filename>/etc/</filename>
have the highest priority and take precedence over files with the same
- name in <filename>/usr/lib</filename>. This can be used to override a
+ name in <filename>/usr/lib/</filename>. This can be used to override a
system-supplied hwdb file with a local file if needed;
- a symlink in <filename>/etc</filename> with the same name as a hwdb file in
- <filename>/usr/lib</filename>, pointing to <filename>/dev/null</filename>,
+ a symlink in <filename>/etc/</filename> with the same name as a hwdb file in
+ <filename>/usr/lib/</filename>, pointing to <filename>/dev/null</filename>,
disables that hwdb file entirely. hwdb files must have the extension
<filename>.hwdb</filename>; other extensions are ignored.</para>
they are combined by OR. Every match line must start at the first character of the
line.</para>
+ <para>Match patterns consist of literal characters, and shell-style wildcards:</para>
+ <itemizedlist>
+ <listitem><para>Asterisk <literal>*</literal> matches any number of characters
+ </para></listitem>
+ <listitem><para>Question mark <literal>?</literal> matches a single character
+ </para></listitem>
+ <listitem><para>Character list <literal>[<replaceable>chars</replaceable>]</literal> matches one of
+ the characters <replaceable>chars</replaceable> listed between <literal>[</literal> and
+ <literal>]</literal>. A range may be specified as with a dash as
+ <literal>[<replaceable>first</replaceable>-<replaceable>last</replaceable>]</literal>. The match may
+ be inverted with a caret <literal>[^…]</literal>.</para></listitem>
+ </itemizedlist>
+
<para>The match lines are followed by one or more key-value pair lines, which are
recognized by a leading space character. The key name and value are separated by
<literal>=</literal>. An empty line signifies the end of a record. Lines beginning
# it defines, and the ordering convention.
# A record with three matches and one property
-mouse:*:name:*Trackball*:
-mouse:*:name:*trackball*:
-mouse:*:name:*TrackBall*:
+mouse:*:name:*Trackball*:*
+mouse:*:name:*trackball*:*
+mouse:*:name:*TrackBall*:*
+ ID_INPUT_TRACKBALL=1
+
+# The rule above could be also be written in a form that
+# matches Tb, tb, TB, tB:
+mouse:*:name:*[tT]rack[bB]all*:*
ID_INPUT_TRACKBALL=1
# A record with a single match and five properties
-mouse:usb:v046dp4041:name:Logitech MX Master:
+mouse:usb:v046dp4041:name:Logitech MX Master:*
MOUSE_DPI=1000@166
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
<title>Overriding of properties</title>
<programlisting># /usr/lib/udev/hwdb.d/60-keyboard.hwdb
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*:*
KEYBOARD_KEY_a1=help
KEYBOARD_KEY_a2=setup
KEYBOARD_KEY_a3=battery
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn123*
+# Match vendor name "Acer" and any product name starting with "X123"
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer:pnX123*:*
KEYBOARD_KEY_a2=wlan
# /etc/udev/hwdb.d/70-keyboard.hwdb
# disable wlan key on all at keyboards
evdev:atkbd:*
- KEYBOARD_KEY_a2=reserved</programlisting>
+ KEYBOARD_KEY_a2=reserved
+ PROPERTY_WITH_SPACES=some string</programlisting>
<para>If the hwdb consists of those two files, a keyboard with the lookup string
- <literal>evdev:atkbd:dmi:bvnAcer:bdXXXXX:bd08/05/2010:svnAcer:pn123</literal>
+ <literal>evdev:atkbd:dmi:bvnAcer:bdXXXXX:bd08/05/2010:svnAcer:pnX123</literal>
will match all three records, and end up with the following properties:</para>
<programlisting>KEYBOARD_KEY_a1=help
KEYBOARD_KEY_a2=reserved
-KEYBOARD_KEY_a3=battery</programlisting>
+KEYBOARD_KEY_a3=battery
+PROPERTY_WITH_SPACES=some string</programlisting>
+
</example>
</refsect1>
with <literal>Runtime</literal> apply to the journal files
when stored on a volatile in-memory file system, more
specifically <filename>/run/log/journal</filename>. The former
- is used only when <filename>/var</filename> is mounted,
+ is used only when <filename>/var/</filename> is mounted,
writable, and the directory
<filename>/var/log/journal</filename> exists. Otherwise, only
the latter applies. Note that this means that during early
<listitem>
<para>This parameter controls whether the system shall boot up in volatile mode. Takes a boolean argument, or
the special value <literal>state</literal>. If false (the default), normal boot mode is selected, the root
- directory and <filename>/var</filename> are mounted as specified on the kernel command line or
+ directory and <filename>/var/</filename> are mounted as specified on the kernel command line or
<filename>/etc/fstab</filename>, or otherwise configured. If true, full state-less boot mode is selected. In
this case the root directory is mounted as volatile memory file system (<literal>tmpfs</literal>), and only
- <filename>/usr</filename> is mounted from the file system configured as root device, in read-only mode. This
+ <filename>/usr/</filename> is mounted from the file system configured as root device, in read-only mode. This
enables fully state-less boots were the vendor-supplied OS is used as shipped, with only default
- configuration and no stored state in effect, as <filename>/etc</filename> and <filename>/var</filename> (as
+ configuration and no stored state in effect, as <filename>/etc/</filename> and <filename>/var/</filename> (as
well as all other resources shipped in the root file system) are reset at boot and lost on shutdown. If this
setting is set to <literal>state</literal> the root file system is mounted read-only, however
- <filename>/var</filename> is mounted as a volatile memory file system (<literal>tmpfs</literal>), so that the
+ <filename>/var/</filename> is mounted as a volatile memory file system (<literal>tmpfs</literal>), so that the
system boots up with the normal configuration applied, but all state reset at boot and lost at shutdown. If
this setting is set to <literal>overlay</literal> the root file system is set up as
<literal>overlayfs</literal> mount combining the read-only root directory with a writable
the invoking terminal is determined to be UTF-8 compatible).</para></listitem>
</varlistentry>
+ <varlistentry id='lesssecure'>
+ <term><varname>$SYSTEMD_PAGERSECURE</varname></term>
+
+ <listitem><para>Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if
+ false, disabled. If <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, secure mode is enabled
+ if the effective UID is not the same as the owner of the login session, see <citerefentry
+ project='man-pages'><refentrytitle>geteuid</refentrytitle><manvolnum>2</manvolnum></citerefentry> and
+ <citerefentry><refentrytitle>sd_pid_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ In secure mode, <option>LESSSECURE=1</option> will be set when invoking the pager, and the pager shall
+ disable commands that open or create new files or start new subprocesses. When
+ <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, pagers which are not known to implement
+ secure mode will not be used. (Currently only
+ <citerefentry><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> implements
+ secure mode.)</para>
+
+ <para>Note: when commands are invoked with elevated privileges, for example under <citerefentry
+ project='man-pages'><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
+ <citerefentry
+ project='die-net'><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>, care
+ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the
+ pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname>
+ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note
+ that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be
+ honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completly
+ disable the pager using <option>--no-pager</option> instead.</para></listitem>
+ </varlistentry>
+
<varlistentry id='colors'>
<term><varname>$SYSTEMD_COLORS</varname></term>
<listitem><para>Persistently attach one or more devices to a
seat. The devices should be specified via device paths in the
- <filename>/sys</filename> file system. To create a new seat,
+ <filename>/sys/</filename> file system. To create a new seat,
attach at least one graphics card to a previously unused seat
name. Seat names may consist only of a–z, A–Z, 0–9,
<literal>-</literal> and <literal>_</literal> and must be
<term><varname>KillOnlyUsers=</varname></term>
<term><varname>KillExcludeUsers=</varname></term>
- <listitem><para>These settings take space-separated lists of usernames that override
- the <varname>KillUserProcesses=</varname> setting. A user name may be added to
- <varname>KillExcludeUsers=</varname> to exclude the processes in the session scopes of
- that user from being killed even if <varname>KillUserProcesses=yes</varname> is set. If
- <varname>KillExcludeUsers=</varname> is not set, the <literal>root</literal> user is
- excluded by default. <varname>KillExcludeUsers=</varname> may be set to an empty value
- to override this default. If a user is not excluded, <varname>KillOnlyUsers=</varname>
- is checked next. If this setting is specified, only the session scopes of those users
- will be killed. Otherwise, users are subject to the
- <varname>KillUserProcesses=yes</varname> setting.</para></listitem>
+ <listitem><para>These settings take space-separated lists of usernames that override the
+ <varname>KillUserProcesses=</varname> setting. A user name may be added to
+ <varname>KillExcludeUsers=</varname> to exclude the processes in the session scopes of that user from
+ being killed even if <varname>KillUserProcesses=yes</varname> is set. If
+ <varname>KillExcludeUsers=</varname> is not set, the <literal>root</literal> user is excluded by
+ default. <varname>KillExcludeUsers=</varname> may be set to an empty value to override this
+ default. If a user is not excluded, <varname>KillOnlyUsers=</varname> is checked next. If this
+ setting is specified, only the processes in the session scopes of those users will be
+ killed. Otherwise, users are subject to the <varname>KillUserProcesses=yes</varname> setting.
+ </para></listitem>
</varlistentry>
<varlistentry>
<para>For operating system images which are created once and used on multiple
machines, for example for containers or in the cloud,
- <filename>/etc/machine-id</filename> should be an empty file in the generic file
- system image. An ID will be generated during boot and saved to this file if
- possible. Having an empty file in place is useful because it allows a temporary file
- to be bind-mounted over the real file, in case the image is used read-only.</para>
+ <filename>/etc/machine-id</filename> should be either missing or an empty file in the generic file
+ system image (the difference between the two options is described under "First Boot Semantics" below). An
+ ID will be generated during boot and saved to this file if possible. Having an empty file in place is
+ useful because it allows a temporary file to be bind-mounted over the real file, in case the image is
+ used read-only.</para>
<para><citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
may be used to initialize <filename>/etc/machine-id</filename> on mounted (but not
<para><citerefentry><refentrytitle>systemd-machine-id-commit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
will attempt to write the machine ID to the file system if
- <filename>/etc/machine-id</filename> or <filename>/etc</filename> are read-only during
+ <filename>/etc/machine-id</filename> or <filename>/etc/</filename> are read-only during
early boot but become writable later on.</para>
</refsect1>
+ <refsect1>
+ <title>First Boot Semantics</title>
+
+ <para><filename>/etc/machine-id</filename> is used to decide whether a boot is the first one. The rules
+ are as follows:</para>
+
+ <orderedlist>
+ <listitem><para>If <filename>/etc/machine-id</filename> does not exist, this is a first boot. During
+ early boot, <command>systemd</command> will write <literal>unitialized\n</literal> to this file and overmount
+ a temporary file which contains the actual machine ID. Later (after <filename>first-boot-complete.target</filename>
+ has been reached), the real machine ID will be written to disk.</para></listitem>
+
+ <listitem><para>If <filename>/etc/machine-id</filename> contains the string <literal>uninitialized</literal>,
+ a boot is also considered the first boot. The same mechanism as above applies.</para></listitem>
+
+ <listitem><para>If <filename>/etc/machine-id</filename> exists and is empty, a boot is
+ <emphasis>not</emphasis> considered the first boot. <command>systemd</command> will still bind-mount a file
+ containing the actual machine-id over it and later try to commit it to disk (if <filename>/etc/</filename> is
+ writable).</para></listitem>
+
+ <listitem><para>If <filename>/etc/machine-id</filename> already contains a valid machine-id, this is
+ not a first boot.</para></listitem>
+ </orderedlist>
+
+ <para>If by any of the above rules, a first boot is detected, units with <varname>ConditionFirstBoot=yes</varname>
+ will be run.</para>
+ </refsect1>
+
<refsect1>
<title>Relation to OSF UUIDs</title>
<itemizedlist>
<listitem><para>Directory trees containing an OS, including the
- top-level directories <filename>/usr</filename>,
- <filename>/etc</filename>, and so on.</para></listitem>
+ top-level directories <filename>/usr/</filename>,
+ <filename>/etc/</filename>, and so on.</para></listitem>
<listitem><para>btrfs subvolumes containing OS trees, similar to regular directory trees.</para></listitem>
<term><command>clean</command></term>
<listitem><para>Remove hidden VM or container images (or all). This command removes all hidden machine images
- from <filename>/var/lib/machines</filename>, i.e. those whose name begins with a dot. Use <command>machinectl
+ from <filename>/var/lib/machines/</filename>, i.e. those whose name begins with a dot. Use <command>machinectl
list-images --all</command> to see a list of all machine images, including the hidden ones.</para>
<para>When combined with the <option>--all</option> switch removes all images, not just hidden ones. This
- command effectively empties <filename>/var/lib/machines</filename>.</para>
+ command effectively empties <filename>/var/lib/machines/</filename>.</para>
<para>Note that commands such as <command>machinectl pull-tar</command> or <command>machinectl
pull-raw</command> usually create hidden, read-only, unmodified machine images from the downloaded image first,
<command>import-tar</command> is used, the file specified as
the first argument should be a tar archive, possibly compressed
with xz, gzip or bzip2. It will then be unpacked into its own
- subvolume in <filename>/var/lib/machines</filename>. When
+ subvolume in <filename>/var/lib/machines/</filename>. When
<command>import-raw</command> is used, the file should be a
qcow2 or raw disk image, possibly compressed with xz, gzip or
bzip2. If the second argument (the resulting image name) is
<filename>/usr/lib/machines/</filename>. For compatibility reasons,
the directory <filename>/var/lib/container/</filename> is
searched, too. Note that images stored below
- <filename>/usr</filename> are always considered read-only. It is
+ <filename>/usr/</filename> are always considered read-only. It is
possible to symlink machines images from other directories into
<filename>/var/lib/machines/</filename> to make them available for
control with <command>machinectl</command>.</para>
'@INPUT@'],
input : dbus_docs)
- if conf.get('DEVELOPER_MODE') == 1
+ if conf.get('BUILD_MODE') == 'BUILD_MODE_DEVELOPER'
test('dbus-docs-fresh',
update_dbus_docs_py,
args : ['--build-dir=@0@'.format(project_build_root),
hostname. When using dynamic hostnames, this is traditionally
achieved by patching <filename>/etc/hosts</filename> at the same
time as changing the hostname. This is problematic since it
- requires a writable <filename>/etc</filename> file system and is
+ requires a writable <filename>/etc/</filename> file system and is
fragile because the file might be edited by the administrator at
the same time. With <command>nss-myhostname</command> enabled,
changing <filename>/etc/hosts</filename> is unnecessary, and on
--- /dev/null
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!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+ -->
+
+<refentry id="oomctl" conditional='ENABLE_OOMD'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>oomctl</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>oomctl</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>oomctl</refname>
+ <refpurpose>Analyze the state stored in <command>systemd-oomd</command></refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>oomctl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>oomctl</command> may be used to get information about the various contexts read in by
+ the <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> userspace
+ out-of-memory (OOM) killer,
+ <citerefentry><refentrytitle>systemd-oomd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
+
+ <para>The following commands are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>dump</command></term>
+
+ <listitem><para>Show the current state of the cgroup(s) and system context(s) stored by
+ <command>systemd-oomd</command>.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <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" />
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
--- /dev/null
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!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+ -->
+
+<refentry id="oomd.conf" conditional='ENABLE_OOMD'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>oomd.conf</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>oomd.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>oomd.conf</refname>
+ <refname>oomd.conf.d</refname>
+ <refpurpose>Global <command>systemd-oomd</command> configuration files</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/etc/systemd/oomd.conf</filename></para>
+ <para><filename>/etc/systemd/oomd.conf.d/*.conf</filename></para>
+ <para><filename>/usr/lib/systemd/oomd.conf.d/*.conf</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>These files configure the various parameters of the
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> userspace
+ out-of-memory (OOM) killer,
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ See <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
+
+ </refsect1>
+
+ <xi:include href="standard-conf.xml" xpointer="main-conf" />
+
+ <refsect1>
+ <title>[OOM] Section Options</title>
+
+ <para>The following options are available in the [OOM] section:</para>
+
+ <variablelist class='config-directives'>
+ <varlistentry>
+ <term><varname>SwapUsedLimitPercent=</varname></term>
+
+ <listitem><para>Sets the limit for swap usage on the system before <command>systemd-oomd</command> will
+ take action. If the percentage of swap used on the system is more than what is defined here,
+ <command>systemd-oomd</command> will act on eligible descendant cgroups, starting from the ones with the
+ highest swap usage to the lowest swap usage. Which cgroups are monitored and what
+ action gets taken depends on what the unit has configured for <varname>ManagedOOMSwap=</varname>.
+ Takes a percentage value between 0% and 100%, inclusive. Defaults to 90%.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>DefaultMemoryPressureLimitPercent=</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>.
+ 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,
+ 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>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>oomctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
out h send_fd);
ReleaseHome(in s user_name);
LockAllHomes();
+ DeactivateAllHomes();
properties:
readonly a(sso) AutoLogin = [...];
};
<variablelist class="dbus-method" generated="True" extra-ref="LockAllHomes()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="DeactivateAllHomes()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="AutoLogin"/>
<!--End of Autogenerated section-->
<para><function>LockAllHomes()</function> locks all active home directories that only have references
that opted into automatic suspending during system suspend. This is usually invoked automatically
shortly before system suspend.</para>
+
+ <para><function>DeactivateAllHomes()</function> deactivates all home areas that are currently
+ active. This is usually invoked automatically shortly before system shutdown.</para>
</refsect2>
<refsect2>
operation (as in that case we know the total size on disk). If a socket or pipe is specified, progress information is not
available. The file descriptor argument is followed by a local name for the image. This should be a
name suitable as a hostname and will be used to name the imported image below
- <filename>/var/lib/machines</filename>. A tar import is placed as a directory tree or a
+ <filename>/var/lib/machines/</filename>. A tar import is placed as a directory tree or a
<citerefentry project="man-pages"><refentrytitle>btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
subvolume below <filename>/var/lib/machines/</filename> under the specified name with no suffix
appended. A raw import is placed as a file in <filename>/var/lib/machines/</filename> with the
stored on disk.</para>
<para><function>AttachDevice()</function> may be used to assign a specific device to a specific
- seat. The device is identified by its <filename>/sys</filename> path and must be eligible for seat
+ seat. The device is identified by its <filename>/sys/</filename> path and must be eligible for seat
assignments. <function>AttachDevice()</function> takes three arguments: the seat id, the sysfs path,
and a boolean for controlling polkit interactivity (see below). Device assignments are persistently
stored on disk. To create a new seat, simply specify a previously unused seat id. For more information
about the seat assignment logic see
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat for Linux</ulink>.
- </para>
+ <citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para><function>FlushDevices()</function> removes all explicit seat assignments for devices, resetting
all assignments to the automatic defaults. The only argument it takes is the polkit interactivity
--- /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+ -->
+
+<refentry id="org.freedesktop.oom1" conditional='ENABLE_OOMD'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>org.freedesktop.oom1</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>org.freedesktop.oom1</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>org.freedesktop.oom1</refname>
+ <refpurpose>The D-Bus interface of systemd-oomd</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Introduction</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ is a system service which implements a userspace out-of-memory (OOM) killer. 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-oomd" node="/org/freedesktop/oom1" interface="org.freedesktop.oom1.Manager">
+node /org/freedesktop/oom1 {
+ interface org.freedesktop.oom1.Manager {
+ methods:
+ DumpByFileDescriptor(out h fd);
+ };
+ interface org.freedesktop.DBus.Peer { ... };
+ interface org.freedesktop.DBus.Introspectable { ... };
+ interface org.freedesktop.DBus.Properties { ... };
+};
+ </programlisting>
+
+ <!--method DumpByFileDescriptor is not documented!-->
+
+ <!--Autogenerated cross-references for systemd.directives, do not edit-->
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.oom1.Manager"/>
+
+ <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.oom1.Manager"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="DumpByFileDescriptor()"/>
+
+ <!--End of Autogenerated section-->
+
+ <refsect2>
+ <title>Methods</title>
+
+ <para>...</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>
readonly as DNSSECNegativeTrustAnchors = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DNSStubListener = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ResolvConfMode = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
};
</programlisting>
- <!--method SetLinkDNSEx is not documented!-->
-
- <!--method SetLinkDefaultRoute is not documented!-->
-
- <!--method SetLinkDNSOverTLS is not documented!-->
-
<!--method RegisterService is not documented!-->
<!--method UnregisterService is not documented!-->
<!--method ResetServerFeatures is not documented!-->
- <!--property LLMNR is not documented!-->
-
- <!--property MulticastDNS is not documented!-->
-
- <!--property DNSOverTLS is not documented!-->
-
- <!--property DNSEx is not documented!-->
-
- <!--property FallbackDNS is not documented!-->
-
- <!--property FallbackDNSEx is not documented!-->
-
- <!--property CurrentDNSServer is not documented!-->
-
- <!--property CurrentDNSServerEx is not documented!-->
-
- <!--property DNSSEC is not documented!-->
-
<!--property DNSSECNegativeTrustAnchors is not documented!-->
- <!--property DNSStubListener is not documented!-->
-
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.resolve1.Manager"/>
<variablelist class="dbus-property" generated="True" extra-ref="DNSStubListener"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ResolvConfMode"/>
+
<!--End of Autogenerated section-->
<refsect2>
<title>Methods</title>
- <para><function>ResolveHostname()</function> takes a hostname and resolves it to one or more IP addresses.
- As parameters it takes the Linux network interface index to execute the query on, or 0 if it may be
- done on any suitable interface. The <varname>name</varname> parameter specifies the hostname to
- resolve. Note that if required, IDNA conversion is applied to this name unless it is resolved via LLMNR or MulticastDNS. The <varname>family</varname> parameter
- limits the results to a specific address family. It may be <constant>AF_INET</constant>,
- <constant>AF_INET6</constant> or <constant>AF_UNSPEC</constant>. If <constant>AF_UNSPEC</constant> is specified (recommended), both kinds are retrieved, subject
- to local network configuration (i.e. if no local, routable IPv6 address is found, no IPv6 address is
- retrieved; and similarly for IPv4). A 64-bit <varname>flags</varname> field may be used to alter the
- behaviour of the resolver operation (see below). The method returns an array of address records. Each
- address record consists of the interface index the address belongs to, an address family as well as a
- byte array with the actual IP address data (which either has 4 or 16 elements, depending on the address
- family). The returned address family will be one of <constant>AF_INET</constant> or
- <constant>AF_INET6</constant>. For IPv6, the returned address interface index should be used to
- initialize the .sin6_scope_id field of a <structname>struct sockaddr_in6</structname> instance to permit
- support for resolution to link-local IP addresses. The address array is followed by the canonical name
- of the host, which may or may not be identical to the resolved hostname. Finally, a 64-bit
- <varname>flags</varname> field is returned that is defined similarly to the <varname>flags</varname>
- field that was passed in, but contains information about the resolved data (see below). If the hostname
- passed in is an IPv4 or IPv6 address formatted as string, it is parsed, and the result is returned. In
- this case, no network communication is done.</para>
+ <para><function>ResolveHostname()</function> takes a hostname and resolves it to one or more IP
+ addresses. As parameters it takes the Linux network interface index to execute the query on, or 0 if
+ it may be done on any suitable interface. The <varname>name</varname> parameter specifies the hostname
+ to resolve. Note that if required, IDNA conversion is applied to this name unless it is resolved via
+ LLMNR or MulticastDNS. The <varname>family</varname> parameter limits the results to a specific address
+ family. It may be <constant>AF_INET</constant>, <constant>AF_INET6</constant> or
+ <constant>AF_UNSPEC</constant>. If <constant>AF_UNSPEC</constant> is specified (recommended), both
+ kinds are retrieved, subject to local network configuration (i.e. if no local, routable IPv6 address is
+ found, no IPv6 address is retrieved; and similarly for IPv4). A 64-bit <varname>flags</varname> field
+ may be used to alter the behaviour of the resolver operation (see below). The method returns an array
+ of address records. Each address record consists of the interface index the address belongs to, an
+ address family as well as a byte array with the actual IP address data (which either has 4 or 16
+ elements, depending on the address family). The returned address family will be one of
+ <constant>AF_INET</constant> or <constant>AF_INET6</constant>. For IPv6, the returned address interface
+ index should be used to initialize the .sin6_scope_id field of a
+ <structname>struct sockaddr_in6</structname> instance to permit support for resolution to link-local IP
+ addresses. The address array is followed by the canonical name of the host, which may or may not be
+ identical to the resolved hostname. Finally, a 64-bit <varname>flags</varname> field is returned that
+ is defined similarly to the <varname>flags</varname> field that was passed in, but contains information
+ about the resolved data (see below). If the hostname passed in is an IPv4 or IPv6 address formatted as
+ string, it is parsed, and the result is returned. In this case, no network communication is
+ done.</para>
<para><function>ResolveAddress()</function> executes the reverse operation: it takes an IP address and
acquires one or more hostnames for it. As parameters it takes the interface index to execute the query
<constant>AF_INET6</constant>), followed by a 4-byte or 16-byte array with the raw address data. This
method is a one-step shortcut for retrieving the Link object for a network interface using
<function>GetLink()</function> (see above) and then invoking the <function>SetDNS()</function> method
- (see below) on it.
+ (see below) on it.</para>
+
+ <para><function>SetLinkDNSEx()</function> is similar to <function>SetLinkDNS()</function>, but allows
+ an IP port (instead of the default 53) and DNS name to be specified for each DNS server. The server
+ name is used for Server Name Indication (SNI), which is useful when DNS-over-TLS is
+ used. C.f. <varname>DNS=</varname> in
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
- <para>Network management software integrating with <filename>systemd-resolved</filename> should
- call this method (and the five below) after the interface appeared in the kernel (and thus after a
- network interface index has been assigned), but before the network interfaces is activated
- (<constant>IFF_UP</constant> set) so that all settings take effect during the full time the network
- interface is up. It is safe to alter settings while the interface is up, however. Use
- <function>RevertLink()</function> (described below) to reset all per-interface settings.</para>
+ <para><function>SetLinkDefaultRoute()</function> specifies whether the link shall be used as the
+ default route for name queries. See the description of name routing in
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for details.</para>
<para>The <function>SetLinkDomains()</function> method sets the search and routing domains to use on a
specific network interface for DNS look-ups. It takes a network interface index and an array of domains,
Negative Trust Anchors (NTAs) for a specific network interface. It takes a network interface index and a
list of domains as arguments.</para>
- <para>The <function>RevertLink()</function> method may be used to revert all per-link settings done with
- the six methods described above to the defaults again.</para>
+ <para>The <function>SetLinkDNSOverTLS()</function> method enables or disables DNS-over-TLS.
+ C.f. <varname>DNSOverTLS=</varname> in
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for details.</para>
+
+ <para>Network management software integrating with <filename>systemd-resolved</filename> should call
+ <function>SetLinkDNS()</function> or <function>SetLinkDNSEx()</function>,
+ <function>SetLinkDefaultRoute()</function>, <function>SetLinkDomains()</function> and others after the
+ interface appeared in the kernel (and thus after a network interface index has been assigned), but
+ before the network interfaces is activated (<constant>IFF_UP</constant> set) so that all settings take
+ effect during the full time the network interface is up. It is safe to alter settings while the
+ interface is up, however. Use <function>RevertLink()</function> (described below) to reset all
+ per-interface settings.</para>
+
+ <para>The <function>RevertLink()</function> method may be used to revert all per-link settings
+ described above to the defaults.</para>
<refsect3>
<title>The Flags Parameter</title>
classic unicast DNS, LLMNR via IPv4/UDP and IPv6/UDP respectively, as well as MulticastDNS via
IPv4/UDP and IPv6/UDP. If all of these five bits are off on input (which is strongly recommended) the
look-up will be done via all suitable protocols for the specific look-up. Note that these flags
- operate as filter only, but cannot force a look-up to be done via a protocol. Specifically, <filename>systemd-resolved</filename>
- will only route look-ups within the .local TLD to MulticastDNS (plus some reverse look-up address
- domains), and single-label names to LLMNR (plus some reverse address lookup domains). It will route
- neither of these to Unicast DNS servers. Also, it will do LLMNR and Multicast DNS only on interfaces
- suitable for multicast.</para>
+ operate as filter only, but cannot force a look-up to be done via a protocol. Specifically,
+ <filename>systemd-resolved</filename> will only route look-ups within the .local TLD to MulticastDNS
+ (plus some reverse look-up address domains), and single-label names to LLMNR (plus some reverse
+ address lookup domains). It will route neither of these to Unicast DNS servers. Also, it will do
+ LLMNR and Multicast DNS only on interfaces suitable for multicast.</para>
<para>On output, these five flags indicate which protocol was used to execute the operation, and hence
where the data was found.</para>
the data is "rightfully" unauthenticated (which includes cases where the underlying protocol or server
does not support authenticating data).</para>
</refsect3>
-
- </refsect2>
+ </refsect2>
<refsect2>
<title>Properties</title>
+ <para>The <varname>LLMNR</varname> and <varname>MulticastDNS</varname> properties report whether LLMNR
+ and MulticastDNS are (globally) enabled. Each may be one of <literal>yes</literal>,
+ <literal>no</literal>, and <literal>resolve</literal>. See <function>SetLinkLLMNR()</function>
+ and <function>SetLinkMulticastDNS()</function> above.</para>
+
<para><varname>LLMNRHostname</varname> contains the hostname currently exposed on the network via
LLMNR. It usually follows the system hostname as may be queried via
<citerefentry project="man-pages"><refentrytitle>gethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
but may differ if a conflict is detected on the network.</para>
- <para><varname>DNS</varname> contains an array of all DNS servers currently used by
- <filename>systemd-resolved</filename>. It contains similar information as the DNS server data written to
- /run/systemd/resolve/resolv.conf. Each structure in the array consists of a numeric network interface
- index, an address family, and a byte array containing the DNS server address (either 4 bytes in length
- for IPv4 or 16 bytes in lengths for IPv6). The array contains DNS servers configured system-wide,
- including those possibly read from a foreign <filename>/etc/resolv.conf</filename> or the
- <varname>DNS=</varname> setting in <filename>/etc/systemd/resolved.conf</filename>, as well as
- per-interface DNS server information either retrieved from
+ <para><varname>DNS</varname> and <varname>DNSEx</varname> contain arrays of all DNS servers currently
+ used by <filename>systemd-resolved</filename>. <varname>DNS</varname> contains information similar to
+ the DNS server data in <filename>/run/systemd/resolve/resolv.conf</filename>. Each structure in the
+ array consists of a numeric network interface index, an address family, and a byte array containing the
+ DNS server address (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
+ <varname>DNSEx</varname> is similar, but additionally contains the IP port and server name (used for
+ Server Name Indication, SNI). Both arrays contain DNS servers configured system-wide, including those
+ possibly read from a foreign <filename>/etc/resolv.conf</filename> or the <varname>DNS=</varname>
+ setting in <filename>/etc/systemd/resolved.conf</filename>, as well as per-interface DNS server
+ information either retrieved from
<citerefentry><refentrytitle>systemd-networkd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- or configured by external software via <function>SetLinkDNS()</function> (see above). The network
- interface index will be 0 for the system-wide configured services and non-zero for the per-link
- servers.</para>
+ or configured by external software via <function>SetLinkDNS()</function> or
+ <function>SetLinkDNSEx()</function> (see above). The network interface index will be 0 for the
+ system-wide configured services and non-zero for the per-link servers.</para>
+
+ <para><varname>FallbackDNS</varname> and <varname>FallbackDNSEx</varname> contain arrays of all DNS
+ servers configured as fallback servers, if any, using the same format as <varname>DNS</varname> and
+ <varname>DNSEx</varname> described above. See the description of <varname>FallbackDNS=</varname> in
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ the description of when those servers are used.</para>
+
+ <para><varname>CurrentDNSServer</varname> and <varname>CurrentDNSServerEx</varname> specify the server
+ that is currently used for query resolution, in the same format as a single entry in the
+ <varname>DNS</varname> and <varname>DNSEx</varname> arrays described above.</para>
- <para>Similarly, the <varname>Domains</varname> property contains an array of all search and
- routing domains currently used by <filename>systemd-resolved</filename>. Each entry consists of a network interface index (again, 0
- encodes system-wide entries), the actual domain name, and whether the entry is used only for routing
- (true) or for both routing and searching (false).</para>
+ <para>Similarly, the <varname>Domains</varname> property contains an array of all search and routing
+ domains currently used by <filename>systemd-resolved</filename>. Each entry consists of a network
+ interface index (again, 0 encodes system-wide entries), the actual domain name, and whether the entry
+ is used only for routing (true) or for both routing and searching (false).</para>
<para>The <varname>TransactionStatistics</varname> property contains information about the number of
transactions <filename>systemd-resolved</filename> has processed. It contains a pair of unsigned 64-bit counters, the first
operations so far. It exposes three 64-bit counters: the first being the total number of current cache
entries (both positive and negative), the second the number of cache hits, and the third the number of
cache misses. The latter counters may be reset using <function>ResetStatistics()</function> (see
- above). </para>
+ above).</para>
+
+ <para>The <varname>DNSSEC</varname> property specifies current status of DNSSEC validation. It is one
+ of <literal>yes</literal> (validation is enforced), <literal>no</literal> (no validation is done),
+ <literal>allow-downgrade</literal> (validation is done if the current DNS server supports it). See the
+ description of <varname>DNSSEC=</varname> in
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
<para>The <varname>DNSSECStatistics</varname> property contains information about the DNSSEC
validations executed so far. It contains four 64-bit counters: the number of secure, insecure, bogus,
DNSSEC is supported by DNS servers until it verifies that this is not the case. Thus, the reported
value may initially be true, until the first transactions are executed.</para>
- <para>The <varname>LogLevel</varname> property shows the (maximum) log level of the manager, with the
- same values as the <option>--log-level=</option> option described in
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+ <para>The <varname>DNSOverTLS</varname> boolean property reports whether DNS-over-TLS is enabled.
+ </para>
+
+ <para>The <varname>ResolvConfMode</varname> property exposes how <filename>/etc/resolv.conf</filename>
+ is managed on the host. Currently, the values <literal>uplink</literal>, <literal>stub</literal>,
+ <literal>static</literal> (these three correspond to the three different files
+ <filename>systemd-resolved.service</filename> provides), <literal>foreign</literal> (the file is
+ managed by admin or another service, <filename>systemd-resolved.service</filename> just consumes it),
+ <literal>missing</literal> (<filename>/etc/resolv.conf</filename> is missing).</para>
+
+ <para>The <varname>DNSStubListener</varname> property reports whether the stub listener on port 53 is
+ enabled. Possible values are <literal>yes</literal> (enabled), <literal>no</literal> (disabled),
+ <literal>udp</literal> (only the UDP listener is enabled), and <literal>tcp</literal> (only the TCP
+ listener is enabled).</para>
</refsect2>
</refsect1>
};
</programlisting>
- <!--method SetDNSEx is not documented!-->
-
- <!--method SetDomains is not documented!-->
-
- <!--method SetDefaultRoute is not documented!-->
-
- <!--method SetLLMNR is not documented!-->
-
- <!--method SetMulticastDNS is not documented!-->
-
- <!--method SetDNSOverTLS is not documented!-->
-
- <!--method SetDNSSEC is not documented!-->
-
- <!--method SetDNSSECNegativeTrustAnchors is not documented!-->
-
- <!--method Revert is not documented!-->
-
- <!--property DNSEx is not documented!-->
-
- <!--property CurrentDNSServer is not documented!-->
-
- <!--property CurrentDNSServerEx is not documented!-->
-
- <!--property DefaultRoute is not documented!-->
-
- <!--property LLMNR is not documented!-->
-
- <!--property MulticastDNS is not documented!-->
-
- <!--property DNSOverTLS is not documented!-->
-
- <!--property DNSSEC is not documented!-->
-
<!--property DNSSECNegativeTrustAnchors is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<function>SetLinkDNS()</function> on the Manager object, the main difference being that the later
expects an interface index to be specified. Invoking the methods on the Manager interface has the
benefit of reducing roundtrips, as it is not necessary to first request the Link object path via
- <function>GetLink()</function> before invoking the methods. For further details on these methods see
- the <interfacename>Manager</interfacename> documentation above.</para>
+ <function>GetLink()</function> before invoking the methods. The same relationship holds for
+ <function>SetDNSEx()</function>, <function>SetDomains()</function>,
+ <function>SetDefaultRoute()</function>, <function>SetLLMNR()</function>,
+ <function>SetMulticastDNS()</function>, <function>SetDNSOverTLS()</function>,
+ <function>SetDNSSEC()</function>, <function>SetDNSSECNegativeTrustAnchors()</function>, and
+ <function>Revert()</function>. For further details on these methods see the
+ <interfacename>Manager</interfacename> documentation above.</para>
</refsect2>
<refsect2>
assumed available until it is detected that the configured server does not actually support it. Thus,
this property may initially report that DNSSEC is supported on an interface.</para>
+ <para><varname>DefaultRoute</varname> exposes a boolean field that indicates whether the interface will
+ be used as default route for name queries. See <function>SetLinkDefaultRoute()</function> above.</para>
+
<para>The other properties reflect the state of the various configuration settings for the link which
- may be set with the various methods calls such as SetDNS() or SetLLMNR().</para>
+ may be set with the various methods calls such as <function>SetDNS()</function> or
+ <function>SetLLMNR()</function>.</para>
</refsect2>
</refsect1>
file.</para>
<para><function>EnableUnitFiles()</function> may be used to enable one or more units in the system (by
- creating symlinks to them in <filename>/etc</filename> or <filename>/run</filename>). It takes a list
+ creating symlinks to them in <filename>/etc/</filename> or <filename>/run/</filename>). It takes a list
of unit files to enable (either just file names or full absolute paths if the unit files are residing
outside the usual unit search paths) and two booleans: the first controls whether the unit shall be
- enabled for runtime only (true, <filename>/run</filename>), or persistently (false,
- <filename>/etc</filename>). The second one controls whether symlinks pointing to other units shall be
+ enabled for runtime only (true, <filename>/run/</filename>), or persistently (false,
+ <filename>/etc/</filename>). The second one controls whether symlinks pointing to other units shall be
replaced if necessary. This method returns one boolean and an array of the changes made. The boolean
signals whether the unit files contained any enablement information (i.e. an [Install]) section. The
changes array consists of structures with three strings: the type of the change (one of
format.</para>
<para>Similarly, <function>DisableUnitFiles()</function> disables one or more units in the system,
- i.e. removes all symlinks to them in <filename>/etc</filename> and <filename>/run</filename>.</para>
+ i.e. removes all symlinks to them in <filename>/etc/</filename> and <filename>/run/</filename>.</para>
<para>The <function>EnableUnitFilesWithFlags()</function> and <function>DisableUnitFilesWithFlags()</function>
take in options as flags instead of booleans to allow for extendability, defined as follows:</para>
flag. Taints may be used to lower the chance of bogus bug reports. The following taints are currently
known: <literal>split-usr</literal>, <literal>mtab-not-symlink</literal>,
<literal>cgroups-missing</literal>, <literal>local-hwclock</literal>. <literal>split-usr</literal> is
- set if <filename>/usr</filename> is not pre-mounted when systemd is first invoked. See
+ set if <filename>/usr/</filename> is not pre-mounted when systemd is first invoked. See
<ulink url="http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken">
Booting Without /usr is Broken</ulink>
for details why this is bad. <literal>mtab-not-symlink</literal> indicates that
<literal>disabled</literal>, and <literal>invalid</literal>. <literal>enabled</literal> indicates that a
unit file is permanently enabled. <literal>enable-runtime</literal> indicates the unit file is only
temporarily enabled and will no longer be enabled after a reboot (that means, it is enabled via
- <filename>/run</filename> symlinks, rather than <filename>/etc</filename>). <literal>linked</literal>
- indicates that a unit is linked into <filename>/etc</filename> permanently. <literal>linked-runtime</literal>
- indicates that a unit is linked into <filename>/run</filename> temporarily (until the next
+ <filename>/run/</filename> symlinks, rather than <filename>/etc/</filename>). <literal>linked</literal>
+ indicates that a unit is linked into <filename>/etc/</filename> permanently. <literal>linked-runtime</literal>
+ indicates that a unit is linked into <filename>/run/</filename> temporarily (until the next
reboot). <literal>masked</literal> indicates that the unit file is masked permanently.
- <literal>masked-runtime</literal> indicates that it is masked in <filename>/run</filename> temporarily
+ <literal>masked-runtime</literal> indicates that it is masked in <filename>/run/</filename> temporarily
(until the next reboot). <literal>static</literal> indicates that the unit is statically enabled, i.e.
always enabled and doesn't need to be enabled explicitly. <literal>invalid</literal> indicates that it
could not be determined whether the unit file is enabled.</para>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <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="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <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="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <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="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--property EnvironmentFiles is not documented!-->
<!--property PassEnvironment is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <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="Environment"/>
<variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
+
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+
<!--End of Autogenerated section-->
<refsect2>
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property DisableControllers is not documented!-->
+ <!--property ManagedOOMSwap is not documented!-->
+
+ <!--property ManagedOOMMemoryPressure is not documented!-->
+
+ <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+
<!--property KillMode is not documented!-->
<!--property KillSignal is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="DisableControllers"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMSwap"/>
+
+ <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="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
<filename>/etc/os-release</filename> should be a relative symlink
to <filename>/usr/lib/os-release</filename>, to provide
compatibility with applications only looking at
- <filename>/etc</filename>. A relative symlink instead of an
+ <filename>/etc/</filename>. A relative symlink instead of an
absolute symlink is necessary to avoid breaking the link in a
chroot or initrd environment such as dracut.</para>
<command>attach</command> command above, and removes the unit file copies, drop-ins and image symlink
again. This command expects an image name or path as parameter. Note that if a path is specified only the last
component of it (i.e. the file or directory name itself, not the path to it) is used for finding matching unit
- files. This is a convencience feature to allow all arguments passed as <command>attach</command> also to
+ files. This is a convenience feature to allow all arguments passed as <command>attach</command> also to
<command>detach</command>.</para></listitem>
<para>If <option>--now</option> and/or <option>--enable</option> are passed, the portable service(s) are
['nss-mymachines', '8', ['libnss_mymachines.so.2'], 'ENABLE_NSS_MYMACHINES'],
['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_NSS_RESOLVE'],
['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'],
+ ['oomctl', '1', [], 'ENABLE_OOMD'],
+ ['oomd.conf', '5', ['oomd.conf.d'], 'ENABLE_OOMD'],
['org.freedesktop.LogControl1', '5', [], ''],
['org.freedesktop.home1', '5', [], 'ENABLE_HOMED'],
['org.freedesktop.hostname1', '5', [], 'ENABLE_HOSTNAMED'],
['org.freedesktop.locale1', '5', [], 'ENABLE_LOCALED'],
['org.freedesktop.login1', '5', [], 'ENABLE_LOGIND'],
['org.freedesktop.machine1', '5', [], 'ENABLE_MACHINED'],
+ ['org.freedesktop.oom1', '5', [], 'ENABLE_OOMD'],
['org.freedesktop.resolve1', '5', [], 'ENABLE_RESOLVE'],
['org.freedesktop.systemd1', '5', [], ''],
['org.freedesktop.timedate1', '5', [], 'ENABLE_TIMEDATED'],
'SD_EVENT_ONESHOT',
'sd_event_source_get_enabled'],
''],
+ ['sd_event_source_set_exit_on_failure',
+ '3',
+ ['sd_event_source_get_exit_on_failure'],
+ ''],
['sd_event_source_set_floating', '3', ['sd_event_source_get_floating'], ''],
['sd_event_source_set_prepare', '3', [], ''],
['sd_event_source_set_priority',
['systemd-networkd.service', '8', ['systemd-networkd'], 'ENABLE_NETWORKD'],
['systemd-notify', '1', [], ''],
['systemd-nspawn', '1', [], ''],
+ ['systemd-oomd.service', '8', ['systemd-oomd'], 'ENABLE_OOMD'],
['systemd-path', '1', [], ''],
['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'],
['systemd-pstore.service', '8', ['systemd-pstore'], 'ENABLE_PSTORE'],
''],
['udev_device_has_tag',
'3',
- ['udev_device_get_devlinks_list_entry',
+ ['udev_device_get_current_tags_list_entry',
+ 'udev_device_get_devlinks_list_entry',
'udev_device_get_properties_list_entry',
'udev_device_get_property_value',
'udev_device_get_sysattr_list_entry',
'udev_device_get_sysattr_value',
'udev_device_get_tags_list_entry',
+ 'udev_device_has_current_tag',
'udev_device_set_sysattr_value'],
''],
['udev_device_new_from_syspath',
systemd-logind, instead.</para>
<para>These functions synchronously access data in
- <filename>/proc</filename>, <filename>/sys/fs/cgroup</filename>
- and <filename>/run</filename>. All of these are virtual file
+ <filename>/proc/</filename>, <filename>/sys/fs/cgroup/</filename>
+ and <filename>/run/</filename>. All of these are virtual file
systems, hence the runtime cost of the accesses is relatively
cheap.</para>
<para>
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat on Linux</ulink>
- for an introduction to multi-seat support on Linux and the background for this set of APIs.
+ may also be of historical interest.
</para>
</refsect1>
-
</refentry>
for the credential fields that could not be determined atomically
at peer connection time, and which were later added by reading
augmenting credential data from
- <filename>/proc</filename>. Similarly, for credential objects
+ <filename>/proc/</filename>. Similarly, for credential objects
retrieved via <function>sd_bus_get_owner_creds()</function>, the
mask is set for the fields that could not be determined atomically
at bus creation time, but have been augmented. Similarly, for
<para><function>sd_bus_creds_get_augmented_mask()</function>
returns the mask of fields that have been augmented from data in
- <filename>/proc</filename>, and are thus not suitable for
+ <filename>/proc/</filename>, and are thus not suitable for
authorization decisions.</para>
<para><function>sd_bus_creds_ref()</function> always returns the
is equivalent to <function>sd_bus_open()</function>. This description string is used in log
messages about the bus object, and including a "name" for the bus makes them easier to
understand. Some messages are emitted during bus initialization, hence using this function is
- prefereable to setting the description later with
+ preferable to setting the description later with
<function>sd_bus_open_with_description()</function>. The argument is copied internally and will
not be referenced after the function returns.</para>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
-
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para>The specified parameters are invalid.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><constant>-ENOMEDIUM</constant></term>
+
+ <listitem><para>The requested bus type is not available because of invalid environment (for example
+ the user session bus is not available because <varname>$XDG_RUNTIME_DIR</varname> is not set).
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><constant>-ENOMEM</constant></term>
<refsect1>
<title>Description</title>
- <para><function>sd_bus_message_read_array()</function> gives access to an element array in
- message <parameter>m</parameter>. The "read pointer" in the message must be right before an
- array of type <parameter>type</parameter>. As a special case, <parameter>type</parameter> may be
- <constant>NUL</constant>, in which case any type is acceptable. A pointer to the array data is
- returned in the parameter <parameter>ptr</parameter> and the size of array data (in bytes) is
- returned in the parameter <parameter>size</parameter>. If <parameter>size</parameter> is 0, a
- valid non-null pointer will be returned, but it may not be dereferenced. The data is aligned as
- appropriate for the data type. The data is part of the message — it may not be modified and is
- valid only as long as the message is referenced. After this function returns, the "read pointer"
- points at the next element after the array.</para>
+ <para><function>sd_bus_message_read_array()</function> provides access to an array elements in the
+ bus message <parameter>m</parameter>. The "read pointer" in the message must be right before an array of type
+ <parameter>type</parameter>. As a special case, <parameter>type</parameter> may be
+ <constant>NUL</constant>, in which case any trivial type is acceptable. A pointer to the array data is returned
+ in the parameter <parameter>ptr</parameter> and the size of array data (in bytes) is returned in the
+ parameter <parameter>size</parameter>. If the returned <parameter>size</parameter> parameter is 0, a
+ valid non-null pointer will be returned as <parameter>ptr</parameter>, but it may not be
+ dereferenced. The data is aligned as appropriate for the data type. The data is part of the message — it
+ may not be modified and is valid only as long as the message is referenced. After this function returns,
+ the "read pointer" points at the next element after the array.</para>
<para>Note that this function only supports arrays of trivial types, i.e. arrays of booleans, the various
integer types, as well as floating point numbers. In particular it may not be used for arrays of strings,
<title>Return Value</title>
<para>
- On success, <function>sd_bus_message_read_array()</function> returns 0 or
- a positive integer. On failure, it returns a negative errno-style error
- code.
+ On success and when an array was read, <function>sd_bus_message_read_array()</function> returns an
+ integer greater than zero. If invoked while inside a container element (such as an array, e.g. when
+ operating on an array of arrays) and the final element of the outer container has been read already and
+ the read pointer is thus behind the last element of the outer container this call returns 0 (and the
+ returned pointer will be <constant>NULL</constant> and the size will be 0). On failure, it returns a
+ negative errno-style error code.
</para>
<refsect2>
single receiver). It's behavior is similar to calling
<citerefentry><refentrytitle>sd_bus_message_set_destination</refentrytitle><manvolnum>3</manvolnum></citerefentry>
followed by calling <function>sd_bus_send()</function>.</para>
+
+ <para><function>sd_bus_send()</function>/<function>sd_bus_send_to()</function> will write the message
+ directly to the underlying transport (e.g. kernel socket buffer) if possible. If the connection is not
+ set up fully yet the message is queued locally. If the transport buffers are congested any unwritten
+ message data is queued locally, too. If the connection has been closed or is currently being closed the
+ call fails.
+ <citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry> should
+ be invoked to write out any queued message data to the transport.</para>
</refsect1>
<refsect1>
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_call_method</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_destination</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_reply_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_reply_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
<citerefentry
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
- <para>If the second parameter of
- <function>sd_event_add_child()</function> is passed as NULL no
- reference to the event source object is returned. In this case the
- event source is considered "floating", and will be destroyed
- implicitly when the event loop itself is destroyed.</para>
+ <para>If the second parameter of <function>sd_event_add_child()</function> is passed as
+ <constant>NULL</constant> no reference to the event source object is returned. In this case the event
+ source is considered "floating", and will be destroyed implicitly when the event loop itself is
+ destroyed.</para>
<para>Note that the <parameter>handler</parameter> function is
invoked at a time where the child process is not reaped yet (and
event sources are installed will not be reaped by the event loop
implementation.</para>
+ <para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_child()</function> is
+ <constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
+ event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
+ the exit code parameter to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
<para>If both a child process state change event source and a
<constant>SIGCHLD</constant> signal event source is installed in
the same event loop, the configured event source priorities decide
<constant>SD_EVENT_OFF</constant> with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
- <para>If the second parameter of these functions is passed as
- NULL no reference to the event source object is returned. In this
- case the event source is considered "floating", and will be
- destroyed implicitly when the event loop itself is
- destroyed.</para>
+ <para>If the second parameter of these functions is passed as <constant>NULL</constant> no reference to
+ the event source object is returned. In this case the event source is considered "floating", and will be
+ destroyed implicitly when the event loop itself is destroyed.</para>
+
+ <para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_defer()</function> or
+ <function>sd_event_add_post()</function> is <constant>NULL</constant>, and the event source fires, this
+ will be considered a request to exit the event loop. In this case, the <parameter>userdata</parameter>
+ parameter, cast to an integer, is passed as the exit code parameter to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Similar
+ functionality is not available for <function>sd_event_add_exit()</function>, as these types of event
+ sources are only dispatched when exiting anyway.</para>
</refsect1>
<refsect1>
function to call when the inode changes. The handler function will be passed the <parameter>userdata</parameter>
pointer, which may be chosen freely by the caller. The handler also receives a pointer to a <structname>struct
inotify_event</structname> structure containing information about the inode event. The <parameter>mask</parameter>
- parameter specifie which types of inode events to watch specifically. It must contain an OR-ed combination of
+ parameter specifies which types of inode events to watch specifically. It must contain an OR-ed combination of
<constant>IN_ACCESS</constant>, <constant>IN_ATTRIB</constant>, <constant>IN_CLOSE_WRITE</constant>, … flags. See
<citerefentry project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
further information.</para>
it with
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
- <para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as NULL no reference to the
- event source object is returned. In this case the event source is considered "floating", and will be destroyed
- implicitly when the event loop itself is destroyed.</para>
+ <para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as
+ <constant>NULL</constant> no reference to the event source object is returned. In this case the event
+ source is considered "floating", and will be destroyed implicitly when the event loop itself is
+ destroyed.</para>
+
+ <para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_inotify()</function> is
+ <constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
+ event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
+ the exit code parameter to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para><function>sd_event_source_get_inotify_mask()</function> retrieves the configured inotify watch mask of an
event source created previously with <function>sd_event_add_inotify()</function>. It takes the event source object
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
+ <para>If the <parameter>handler</parameter> to <function>sd_event_add_io()</function> is
+ <constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
+ event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
+ the exit code parameter to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
<para>Note that this call does not take possession of the file descriptor passed in, ownership (and thus
the duty to close it when it is no longer needed) remains with the caller. However, with the
<function>sd_event_source_set_io_fd_own()</function> call (see below) the event source may optionally
threads before this function is called (using <citerefentry
project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
<citerefentry
- project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>). If
- the handler is not specified (<parameter>handler</parameter> is <constant>NULL</constant>), a default
- handler which causes the program to exit cleanly will be used.</para>
+ project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
<para>By default, the event source is enabled permanently
(<constant>SD_EVENT_ON</constant>), but this may be changed with
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
+ <para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_signal()</function> is
+ <constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
+ event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
+ the exit code parameter to
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
<para><function>sd_event_source_get_signal()</function> returns
the configured signal number of an event source created previously
with <function>sd_event_add_signal()</function>. It takes the
"floating", and will be destroyed implicitly when the event loop
itself is destroyed.</para>
- <para>If the <parameter>handler</parameter> to
- <function>sd_event_add_time()</function> is
- <constant>NULL</constant>, and the event source fires, this will
- be considered a request to exit the event loop. In this case, the
- <parameter>userdata</parameter> parameter, cast to an integer, is
- used for the exit code passed to
+ <para>If the <parameter>handler</parameter> parameter to <function>sd_event_add_time()</function> is
+ <constant>NULL</constant>, and the event source fires, this will be considered a request to exit the
+ event loop. In this case, the <parameter>userdata</parameter> parameter, cast to an integer, is passed as
+ the exit code parameter to
<citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>Use <constant>CLOCK_BOOTTIME_ALARM</constant> and
conflict with regular exit codes returned by
<function>sd_event_loop()</function>, if these exit codes shall be
distinguishable.</para>
+
+ <para>Note that for most event source types passing the callback pointer as <constant>NULL</constant> in
+ the respective constructor call (i.e. in
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ …) has the effect of <function>sd_event_exit()</function> being invoked once the event source triggers,
+ with the specified userdata pointer cast to an integer as the exit code parameter. This is useful to
+ automatically terminate an event loop after some condition, such as a time-out or reception of
+ <constant>SIGTERM</constant> or similar. See the documentation for the respective constructor call for
+ details.</para>
</refsect1>
<refsect1>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
--- /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+ -->
+
+<refentry id="sd_event_source_set_exit_on_failure" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_exit_on_failure</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_exit_on_failure</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_exit_on_failure</refname>
+ <refname>sd_event_source_get_exit_on_failure</refname>
+
+ <refpurpose>Set or retrieve the exit-on-failure feature of event sources</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include <systemd/sd-event.h></funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_exit_on_failure</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_exit_on_failure</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_exit_on_failure()</function> may be used to set/unset the
+ exit-on-failure flag of the event source object specified as <parameter>source</parameter>. The flag
+ defaults to off. If on and the callback function set for the event source returns a failure code (i.e. a
+ negative value) the event loop is exited too, using the callback return code as the exit code for
+ <citerefentry><refentrytitle>sd_event_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
+ off, the event source is disabled but the event loop continues to run. Setting this flag is useful for
+ "dominant" event sources that define the purpose and reason for the event loop, and whose failure hence
+ should propagate to the event loop itself — as opposed to "auxiliary" event sources whose failures should
+ remain local and affect the event source, but not propagate further.</para>
+
+ <para><function>sd_event_source_get_exit_on_failure()</function> may be used to query the flag currently
+ set for the event source object <parameter>source</parameter>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_set_exit_on_failure()</function> returns a non-negative
+ integer. <function>sd_event_source_get_exit_on_failure()</function> returns 0 if the flag is off, > 0
+ if the flag is on. On failure, both return a negative errno-style error code.</para>
+
+ <refsect2>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para><parameter>source</parameter> is not a valid pointer to an
+ <structname>sd_event_source</structname> object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para>The event source refers to an exit event source (as created with
+ <citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>),
+ for which this functionality is not supported.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect2>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
<constant>NULL</constant>, it is checked whether the file
descriptor is bound to the specified filename. Special files in
this context are character device nodes and files in
- <filename>/proc</filename> or <filename>/sys</filename>.</para>
+ <filename>/proc/</filename> or <filename>/sys/</filename>.</para>
</refsect1>
<refsect1>
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This is
useful for implementing services that can restart after an explicit request or a crash without losing
state. Any open sockets and other file descriptors which should not be closed during the restart may be stored
- this way. Application state can either be serialized to a file in <filename>/run</filename>, or better, stored
+ this way. Application state can either be serialized to a file in <filename>/run/</filename>, or better, stored
in a <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory
file descriptor. Note that the service manager will accept messages for a service only if its
<varname>FileDescriptorStoreMax=</varname> setting is non-zero (defaults to zero, see
<function>sd_peer_get_cgroup()</function> calls operate similar to
their PID counterparts, but operate on a connected AF_UNIX socket
and retrieve information about the connected peer process. Note
- that these fields are retrieved via <filename>/proc</filename>,
+ that these fields are retrieved via <filename>/proc/</filename>,
and hence are not suitable for authorization purposes, as they are
subject to races.</para>
</refsect1>
<entry>Operating system ID</entry>
<entry>The operating system identifier of the running system, as read from the <varname>ID=</varname> field of <filename>/etc/os-release</filename>. See <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry>
</row>
+ <row id='T'>
+ <entry><literal>%T</literal></entry>
+ <entry>Directory for temporary files</entry>
+ <entry>This is either <filename>/tmp<!-- no / --></filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to. (Note that the directory may be specified without a trailing slash.)</entry>
+ </row>
<row id='v'>
<entry><literal>%v</literal></entry>
<entry>Kernel release</entry>
<entry>Identical to <command>uname -r</command> output.</entry>
</row>
+ <row id='V'>
+ <entry><literal>%V</literal></entry>
+ <entry>Directory for larger and persistent temporary files</entry>
+ <entry>This is either <filename>/var/tmp<!-- no / --></filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to. (Note that the directory may be specified without a trailing slash.)</entry>
+ </row>
<row id='w'>
<entry><literal>%w</literal></entry>
<entry>Operating system version ID</entry>
followed by <literal>=</literal>, see SYNOPSIS.</para>
<para>Any access permission errors and attempts to write variables not present on the local system are
- logged at debug level and do not cause the service to fail. Moreover, if a variable assignment is
- prefixed with a single <literal>-</literal> character, failure to set the variable for other reasons will
- be logged at debug level and will not cause the service to fail. In other cases, errors when setting
- variables are logged with higher priority and cause the service to return failure at the end (after
- processing other variables).</para>
+ logged at debug level and do not cause the service to fail. Other types of errors when setting variables
+ are logged with higher priority and cause the service to return failure at the end (after processing
+ other variables). As an exception, if a variable assignment is prefixed with a single
+ <literal>-</literal> character, failure to set the variable for any reason will be logged at debug level
+ and will not cause the service to fail.</para>
<para>The settings configured with <filename>sysctl.d</filename> files will be applied early on boot. The
network interface-specific options will also be applied individually for each network interface as it
directories, an additional symlink is created, linking it into the unit configuration path, thus ensuring
it is found when requested by commands such as <command>start</command>. The file system where the linked
unit files are located must be accessible when systemd is started (e.g. anything underneath
- <filename>/home</filename> or <filename>/var</filename> is not allowed, unless those directories are
+ <filename>/home/</filename> or <filename>/var/</filename> is not allowed, unless those directories are
located on the root file system).</para>
<para>This command will print the file system operations executed. This output may be suppressed by passing
<command>disable</command>. The effect of this command is that a unit file is made available for commands
such as <command>start</command>, even though it is not installed directly in the unit search path. The
file system where the linked unit files are located must be accessible when systemd is started
- (e.g. anything underneath <filename>/home</filename> or <filename>/var</filename> is not allowed, unless
+ (e.g. anything underneath <filename>/home/</filename> or <filename>/var/</filename> is not allowed, unless
those directories are located on the root file system).</para>
</listitem>
</varlistentry>
<literal>foo.service.d/</literal> with all their contained files are removed, both below the persistent and
runtime configuration directories (i.e. below <filename>/etc/systemd/system</filename> and
<filename>/run/systemd/system</filename>); if the unit file has a vendor-supplied version (i.e. a unit file
- located below <filename>/usr</filename>) any matching persistent or runtime unit file that overrides it is
+ located below <filename>/usr/</filename>) any matching persistent or runtime unit file that overrides it is
removed, too. Note that if a unit file has no vendor-supplied version (i.e. is only defined below
<filename>/etc/systemd/system</filename> or <filename>/run/systemd/system</filename>, but not in a unit
- file stored below <filename>/usr</filename>), then it is not removed. Also, if a unit is masked, it is
+ file stored below <filename>/usr/</filename>), then it is not removed. Also, if a unit is masked, it is
unmasked.</para>
<para>Effectively, this command may be used to undo all changes made with <command>systemctl
not already exist, new unit files will be opened for editing.</para>
<para>If <option>--runtime</option> is specified, the changes will
- be made temporarily in <filename>/run</filename> and they will be
+ be made temporarily in <filename>/run/</filename> and they will be
lost on the next reboot.</para>
<para>If the temporary file is empty upon exit, the modification of
<para>Note that this command cannot be used to remotely edit units
and that you cannot temporarily edit units which are in
- <filename>/etc</filename>, since they take precedence over
- <filename>/run</filename>.</para>
+ <filename>/etc/</filename>, since they take precedence over
+ <filename>/run/</filename>.</para>
</listitem>
</varlistentry>
(and related commands), make changes only temporarily, so
that they are lost on the next reboot. This will have the
effect that changes are not made in subdirectories of
- <filename>/etc</filename> but in <filename>/run</filename>,
+ <filename>/etc/</filename> but in <filename>/run/</filename>,
with identical immediate effects, however, since the latter
is lost on reboot, the changes are lost too.</para>
<xi:include href="less-variables.xml" xpointer="pager"/>
<xi:include href="less-variables.xml" xpointer="less"/>
<xi:include href="less-variables.xml" xpointer="lesscharset"/>
+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
<xi:include href="less-variables.xml" xpointer="colors"/>
<xi:include href="less-variables.xml" xpointer="urlify"/>
</refsect1>
It is intended to be used after boot to ensure that users are
properly notified.</para>
- <para>See the <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">
- developer documentation</ulink> for more information about the
- system password logic.</para>
+ <para>See the <ulink url="https://systemd.io/PASSWORD_AGENTS/">developer
+ documentation</ulink> for more information about the system password logic.
+ </para>
<para>Note that these services invoke
<citerefentry><refentrytitle>systemd-tty-ask-password-agent</refentrytitle><manvolnum>1</manvolnum></citerefentry>
or similar.</para>
<para>Additional password agents may be implemented according to
- the <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">systemd
- Password Agent Specification</ulink>.</para>
+ the <ulink url="https://systemd.io/PASSWORD_AGENTS/">systemd Password Agent
+ Specification</ulink>.</para>
<para>If a password is queried on a TTY, the user may press TAB to
hide the asterisks normally shown for each character typed.
file paths or are assumed in the systemd control group hierarchy.
If no argument is specified and the current working directory is
beneath the control group mount point
- <filename>/sys/fs/cgroup</filename>, shows the contents of the
+ <filename>/sys/fs/cgroup/</filename>, shows the contents of the
control group the working directory refers to. Otherwise, the full
systemd control group hierarchy is shown.</para>
<term><option>-r</option></term>
<term><option>--raw</option></term>
- <listitem><para>Format byte counts (as in memory usage and I/O metrics)
+ <listitem><para>Format byte counts (as in memory usage and I/O metrics) and CPU time
with raw numeric values rather than human-readable
numbers.</para></listitem>
</varlistentry>
LUKS device given by the UUID appear under the provided
name.</para>
+ <para>This parameter is the analogue of the first <citerefentry><refentrytitle>crypttab</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> field <replaceable>volume-name</replaceable>.</para>
+
<para><varname>rd.luks.name=</varname> is honored only by
initial RAM disk (initrd) while <varname>luks.name=</varname>
is honored by both the main system and the initrd.</para>
</varlistentry>
<varlistentry>
- <term><varname>luks.options=</varname></term>
- <term><varname>rd.luks.options=</varname></term>
+ <term><varname>luks.data=</varname></term>
+ <term><varname>rd.luks.data=</varname></term>
- <listitem><para>Takes a LUKS super block UUID followed by an
- <literal>=</literal> and a string of options separated by
- commas as argument. This will override the options for the
- given UUID.</para>
- <para>If only a list of options, without an UUID, is
- specified, they apply to any UUIDs not specified elsewhere,
- and without an entry in
- <filename>/etc/crypttab</filename>.</para><para>
- <varname>rd.luks.options=</varname> is honored only by initial
- RAM disk (initrd) while <varname>luks.options=</varname> is
- honored by both the main system and the initrd.</para>
+ <listitem><para>Takes a LUKS super block UUID followed by a <literal>=</literal> and a block device
+ specification for device hosting encrypted data.</para>
+
+ <para>For those entries specified with <varname>rd.luks.uuid=</varname> or
+ <varname>luks.uuid=</varname>, the data device will be set to the one specified by
+ <varname>rd.luks.data=</varname> or <varname>luks.data=</varname> of the corresponding UUID.</para>
+
+ <para>LUKS data device parameter is usefull for specifying encrypted data devices with detached headers specified in
+ <varname>luks.options</varname> entry containing <literal>header=</literal> argument. For example,
+ <varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40
+ <varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/path/to/luks.hdr
+ <varname>rd.luks.data=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=/dev/sdx.
+ Hence, in this case, we will attempt to unlock LUKS device assembled from data device <literal>/dev/sdx</literal>
+ and LUKS header (metadata) put in <literal>/path/to/luks.hdr</literal> file. This syntax is for now
+ only supported on a per-device basis, i.e. you have to specify LUKS device UUID.</para>
+
+ <para>This parameter is the analogue of the second <citerefentry><refentrytitle>crypttab</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> field <replaceable>encrypted-device</replaceable>.</para>
+
+ <para><varname>rd.luks.data=</varname> is honored only by initial RAM disk (initrd) while
+ <varname>luks.data=</varname> is honored by both the main system and the initrd.</para>
</listitem>
</varlistentry>
This syntax is for now only supported on a per-device basis,
i.e. you have to specify LUKS device UUID.</para>
+ <para>This parameter is the analogue of the third <citerefentry><refentrytitle>crypttab</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> field <replaceable>key-file</replaceable>.</para>
+
<para><varname>rd.luks.key=</varname>
is honored only by initial RAM disk
(initrd) while
the initrd.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>luks.options=</varname></term>
+ <term><varname>rd.luks.options=</varname></term>
+
+ <listitem><para>Takes a LUKS super block UUID followed by an
+ <literal>=</literal> and a string of options separated by
+ commas as argument. This will override the options for the
+ given UUID.</para>
+ <para>If only a list of options, without an UUID, is
+ specified, they apply to any UUIDs not specified elsewhere,
+ and without an entry in
+ <filename>/etc/crypttab</filename>.</para>
+
+ <para>This parameter is the analogue of the fourth <citerefentry><refentrytitle>crypttab</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> field <replaceable>options</replaceable>.</para>
+
+ <para>It is possible to specify an external device which
+ should be mounted before we attempt to unlock the LUKS device.
+ systemd-cryptsetup will assemble LUKS device by combining
+ data device specified in <varname>luks.data</varname> with
+ detached LUKS header found in <literal>header=</literal>
+ argument. For example,
+ <varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40
+ <varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/luks.hdr:LABEL=hdrdev
+ <varname>rd.luks.data=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=/dev/sdx.
+ Hence, in this case, we will attempt to mount file system
+ residing on the block device with label <literal>hdrdev</literal>, and look
+ for <literal>luks.hdr</literal> on that file system. Said header will be used
+ to unlock (decrypt) encrypted data stored on /dev/sdx.
+ This syntax is for now only supported on a per-device basis,
+ i.e. you have to specify LUKS device UUID.</para>
+
+ <para><varname>rd.luks.options=</varname> is honored only by initial
+ RAM disk (initrd) while <varname>luks.options=</varname> is
+ honored by both the main system and the initrd.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<para><filename>systemd-cryptsetup@.service</filename> will ask
for hard disk passwords via the <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">
- password agent logic</ulink>, in order to query the user for the
- password using the right mechanism at boot and during
- runtime.</para>
+ url="https://systemd.io/PASSWORD_AGENTS/">password agent logic</ulink>, in
+ order to query the user for the password using the right mechanism at boot
+ and during runtime.</para>
<para>At early boot and when the system manager configuration is reloaded, <filename>/etc/crypttab</filename> is
translated into <filename>systemd-cryptsetup@.service</filename> units by
<para><command>systemd-delta</command> may be used to identify and
compare configuration files that override other configuration
- files. Files in <filename>/etc</filename> have highest priority,
- files in <filename>/run</filename> have the second highest
- priority, …, files in <filename>/usr/lib</filename> have lowest
+ files. Files in <filename>/etc/</filename> have highest priority,
+ files in <filename>/run/</filename> have the second highest
+ priority, …, files in <filename>/usr/lib/</filename> have lowest
priority. Files in a directory with higher priority override files
with the same name in directories of lower priority. In addition,
certain configuration files can have <literal>.d</literal>
<para>The command line argument will be split into a prefix and a
suffix. Either is optional. The prefix must be one of the
directories containing configuration files
- (<filename>/etc</filename>, <filename>/run</filename>,
- <filename>/usr/lib</filename>, …). If it is given, only
+ (<filename>/etc/</filename>, <filename>/run/</filename>,
+ <filename>/usr/lib/</filename>, …). If it is given, only
overriding files contained in this directory will be shown.
Otherwise, all overriding files will be shown. The suffix must be
a name of a subdirectory containing configuration files like
</thead>
<tbody>
<row>
- <entry valign="top" morerows="12">VM</entry>
+ <entry valign="top" morerows="13">VM</entry>
<entry><varname>qemu</varname></entry>
<entry>QEMU software virtualization, without KVM</entry>
</row>
<entry>Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems), for legacy and KVM hypervisor</entry>
</row>
+ <row>
+ <entry><varname>powervm</varname></entry>
+ <entry>IBM PowerVM hypervisor - comes as firmware with some IBM POWER servers</entry>
+ </row>
+
<row>
<entry><varname>xen</varname></entry>
<entry>Xen hypervisor (only domU, not dom0)</entry>
</row>
<row>
- <entry valign="top" morerows="8">Container</entry>
+ <entry valign="top" morerows="9">Container</entry>
<entry><varname>openvz</varname></entry>
<entry>OpenVZ/Virtuozzo</entry>
</row>
<para>OS images may use any kind of Linux-supported file systems. In addition they may make use of LUKS
disk encryption, and contain Verity integrity information. Note that qualifying OS images may be booted
- with <citerefentry><refentrytitle>system-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
+ with <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<option>--image=</option> switch, and be used as root file system for system service using the
<varname>RootImage=</varname> unit file setting, see
- <citerefentry><refentrytitle>system.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>Note that the partition table shown when invoked without command switch (as listed below) does not
necessarily show all partitions included in the image, but just the partitions that are understood and
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>system-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>system.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>,
<citerefentry project='man-pages'><refentrytitle>umount</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>fdisk</refentrytitle><manvolnum>8</manvolnum></citerefentry>
basic system settings interactively on the first boot, or
optionally non-interactively when a system image is created.
The service is started if <varname>ConditionFirstBoot=yes</varname>
- is satisfied. This essentially means that <filename>/etc</filename>
+ is satisfied. This essentially means that <filename>/etc/</filename>
is empty, see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
<varlistentry>
<term><option>--prompt</option></term>
- <listitem><para>Query the user for locale, keymap, timezone, hostname
- and root password. This is equivalent to specifying
+ <listitem><para>Query the user for locale, keymap, timezone, hostname,
+ root's password, and root's shell. This is equivalent to specifying
<option>--prompt-locale</option>,
<option>--prompt-keymap</option>,
<option>--prompt-timezone</option>,
<varlistentry>
<term><varname>mount.usr=</varname></term>
- <listitem><para>Takes the <filename>/usr</filename> filesystem
+ <listitem><para>Takes the <filename>/usr/</filename> filesystem
to be mounted by the initrd. If
<varname>mount.usrfstype=</varname> or
<varname>mount.usrflags=</varname> is set, then
<varname>root=</varname>.</para>
<para>Otherwise, this parameter defaults to the
- <filename>/usr</filename> entry found in
+ <filename>/usr/</filename> entry found in
<filename>/etc/fstab</filename> on the root filesystem.</para>
<para><varname>mount.usr=</varname> is honored by the initrd.
<varlistentry>
<term><varname>mount.usrfstype=</varname></term>
- <listitem><para>Takes the <filename>/usr</filename> filesystem
+ <listitem><para>Takes the <filename>/usr/</filename> filesystem
type that will be passed to the mount command. If
<varname>mount.usr=</varname> or
<varname>mount.usrflags=</varname> is set, then
set in <varname>rootfstype=</varname>.</para>
<para>Otherwise, this value will be read from the
- <filename>/usr</filename> entry in
+ <filename>/usr/</filename> entry in
<filename>/etc/fstab</filename> on the root filesystem.</para>
<para><varname>mount.usrfstype=</varname> is honored by the
<varlistentry>
<term><varname>mount.usrflags=</varname></term>
- <listitem><para>Takes the <filename>/usr</filename> filesystem
+ <listitem><para>Takes the <filename>/usr/</filename> filesystem
mount options to use. If <varname>mount.usr=</varname> or
<varname>mount.usrfstype=</varname> is set, then
<varname>mount.usrflags=</varname> will default to the value
set in <varname>rootflags=</varname>.</para>
<para>Otherwise, this value will be read from the
- <filename>/usr</filename> entry in
+ <filename>/usr/</filename> entry in
<filename>/etc/fstab</filename> on the root filesystem.</para>
<para><varname>mount.usrflags=</varname> is honored by the
<citerefentry><refentrytitle>systemd-volatile-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is run as part of the initial RAM disk ("initrd"). This service changes the mount table before transitioning to
the host system, so that a volatile memory file system (<literal>tmpfs</literal>) is used as root directory,
- with only <filename>/usr</filename> mounted into it from the configured root file system, in read-only
+ with only <filename>/usr/</filename> mounted into it from the configured root file system, in read-only
mode. This way the system operates in fully stateless mode, with all configuration and state reset at boot and
- lost at shutdown, as <filename>/etc</filename> and <filename>/var</filename> will be served from the (initially
+ lost at shutdown, as <filename>/etc/</filename> and <filename>/var/</filename> will be served from the (initially
unpopulated) volatile memory file system.</para>
<para>If set to <option>state</option> the generator will leave the root directory mount point unaltered,
- however will mount a <literal>tmpfs</literal> file system to <filename>/var</filename>. In this mode the normal
- system configuration (i.e. the contents of <literal>/etc</literal>) is in effect (and may be modified during
- system runtime), however the system state (i.e. the contents of <literal>/var</literal>) is reset at boot and
+ however will mount a <literal>tmpfs</literal> file system to <filename>/var/</filename>. In this mode the normal
+ system configuration (i.e. the contents of <literal>/etc/</literal>) is in effect (and may be modified during
+ system runtime), however the system state (i.e. the contents of <literal>/var/</literal>) is reset at boot and
lost at shutdown.</para>
<para>If this setting is set to <literal>overlay</literal> the root file system is set up as
<literal>tmpfs</literal>, so that no modifications are made to disk, but the file system may be modified
nonetheless with all changes being lost at reboot.</para>
- <para>Note that in none of these modes the root directory, <filename>/etc</filename>, <filename>/var</filename>
+ <para>Note that in none of these modes the root directory, <filename>/etc/</filename>, <filename>/var/</filename>
or any other resources stored in the root file system are physically removed. It's thus safe to boot a system
that is normally operated in non-volatile mode temporarily into volatile mode, without losing data.</para>
<para>Note that with the exception of <literal>overlay</literal> mode, enabling this setting will only work
- correctly on operating systems that can boot up with only <filename>/usr</filename> mounted, and are able to
- automatically populate <filename>/etc</filename>, and also <filename>/var</filename> in case of
+ correctly on operating systems that can boot up with only <filename>/usr/</filename> mounted, and are able to
+ automatically populate <filename>/etc/</filename>, and also <filename>/var/</filename> in case of
<literal>systemd.volatile=yes</literal>.</para></listitem>
</varlistentry>
<listitem><para>Takes a path to the resume device. Both
persistent block device paths like
- <filename>/dev/disk/by-foo/bar</filename> and
+ <filename index="false">/dev/disk/by-foo/bar</filename> and
<citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>-style
specifiers like <literal>FOO=bar</literal> are
supported.</para></listitem>
<para>In order to migrate a home directory from a host <literal>foobar</literal> to another host
<literal>quux</literal> it is hence sufficient to copy
<filename>/var/lib/systemd/home/local.public</filename> from the host <literal>foobar</literal> to
- <literal>quux</literal>, maybe calling the file on the destination
- <filename>/var/lib/systemd/home/foobar.public</filename>, reflecting the origin of the key. If the user
- record should be modifiable on <literal>quux</literal> the pair
+ <literal>quux</literal>, maybe calling the file on the destination <filename
+ index="false">/var/lib/systemd/home/foobar.public</filename>, reflecting the origin of the key. If the
+ user record should be modifiable on <literal>quux</literal> the pair
<filename>/var/lib/systemd/home/local.public</filename> and
<filename>/var/lib/systemd/home/local.private</filename> need to be copied from <literal>foobar</literal>
to <literal>quux</literal>, and placed under the identical paths there, as currently only a single
<listitem><para>Request that journal data from <filename>/run/</filename> is flushed to
<filename>/var/</filename> in order to make it persistent (if this is enabled). This must be used
- after <filename>/var/</filename> is mounted, as otherwise log data from <filename>/run</filename> is
- never flushed to <filename>/var</filename> regardless of the configuration. Use the
+ after <filename>/var/</filename> is mounted, as otherwise log data from <filename>/run/</filename> is
+ never flushed to <filename>/var/</filename> regardless of the configuration. Use the
<command>journalctl --flush</command> command to request flushing of the journal files, and wait for
the operation to complete. See
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
stopped uncleanly, or if the files are found to be corrupted,
they are renamed using the <literal>.journal~</literal>
suffix, and <command>systemd-journald</command> starts writing
- to a new file. <filename>/run</filename> is used when
+ to a new file. <filename>/run/</filename> is used when
<filename>/var/log/journal</filename> is not available, or
when <option>Storage=volatile</option> is set in the
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
transient machine ID file on a memory file system, and mount it
over <filename>/etc/machine-id</filename>, during the early boot
phase. This service is then invoked in a later boot phase, as soon
- as <filename>/etc</filename> has been remounted writable and the
+ as <filename>/etc/</filename> has been remounted writable and the
ID may thus be committed to disk to make it permanent.</para>
</refsect1>
<literal>tmpfs</literal>) to
<filename>/etc/machine-id</filename> during the early phase of
the boot process. This may happen because
- <filename>/etc</filename> is initially read-only and was
+ <filename>/etc/</filename> is initially read-only and was
missing a valid machine ID file at that point.</para>
<para>This command will execute no operation if
<filename>/etc/machine-id</filename> is not mounted from a
- memory file system, or if <filename>/etc</filename> is
+ memory file system, or if <filename>/etc/</filename> is
read-only. The command will write the current transient
machine ID to disk and unmount the
<filename>/etc/machine-id</filename> mount point in a
For more information please consult
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
- <citerefentry><refentrytitle>org.freedesktop.machine1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>org.freedesktop.machine1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
and
- <citerefentry><refentrytitle>org.freedesktop.LogControl1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>org.freedesktop.LogControl1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>A small companion daemon
<title>Description</title>
<para><filename>systemd-modules-load.service</filename> is an early boot service that loads kernel
- modules. It reads static configuration from files in <filename>/usr</filename> and
- <filename>/etc</filename>, but also runtime configuration from <filename>/run</filename> and the kernel
+ modules. It reads static configuration from files in <filename>/usr/</filename> and
+ <filename>/etc/</filename>, but also runtime configuration from <filename>/run/</filename> and the kernel
command line (see below).</para>
<para>See
<term><option>--type=</option></term>
<term><option>-t</option></term>
- <listitem><para>Specifies the file system type to mount (e.g. <literal>vfat</literal>, <literal>ext4</literal>,
- …). If omitted (or set to <literal>auto</literal>) the file system is determined automatically.</para></listitem>
+ <listitem><para>Specifies the file system type to mount (e.g. <literal>vfat</literal> or
+ <literal>ext4</literal>). If omitted or set to <literal>auto</literal>, the file system type is
+ determined automatically.</para></listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><option>--no-block</option></term>
- <listitem><para>Do not synchronously wait for the requested operation to finish.
- Use of this option is only recommended when <command>systemd-notify</command>
- is spawned by the service manager, or when the invoking process is directly spawned
- by the service manager and has enough privileges to allow <command>systemd-notify
- </command> to send the notification on its behalf. Sending notifications with
+ <listitem><para>Do not synchronously wait for the requested operation to finish. Use of this option
+ is only recommended when <command>systemd-notify</command> is spawned by the service manager, or when
+ the invoking process is directly spawned by the service manager and has enough privileges to allow
+ <command>systemd-notify</command> to send the notification on its behalf. Sending notifications with
this option set is prone to race conditions in all other cases.</para></listitem>
</varlistentry>
<para><command>systemd-nspawn</command> may be invoked on any directory tree containing an operating system tree,
using the <option>--directory=</option> command line option. By using the <option>--machine=</option> option an OS
tree is automatically searched for in a couple of locations, most importantly in
- <filename>/var/lib/machines</filename>, the suggested directory to place OS container images installed on the
+ <filename>/var/lib/machines/</filename>, the suggested directory to place OS container images installed on the
system.</para>
<para>In contrast to <citerefentry
may be used to boot full Linux-based operating systems in a container.</para>
<para><command>systemd-nspawn</command> limits access to various kernel interfaces in the container to read-only,
- such as <filename>/sys</filename>, <filename>/proc/sys</filename> or <filename>/sys/fs/selinux</filename>. The
+ such as <filename>/sys/</filename>, <filename>/proc/sys/</filename> or <filename>/sys/fs/selinux/</filename>. The
host's network interfaces and the system clock may not be changed from within the container. Device nodes may not
be created. The host system cannot be rebooted and kernel modules may not be loaded from within the
container.</para>
template unit file, making it usually unnecessary to alter this template file directly.</para>
<para>Note that <command>systemd-nspawn</command> will mount file systems private to the container to
- <filename>/dev</filename>, <filename>/run</filename> and similar. These will not be visible outside of the
+ <filename>/dev/</filename>, <filename>/run/</filename> and similar. These will not be visible outside of the
container, and their contents will be lost when the container exits.</para>
<para>Note that running two <command>systemd-nspawn</command> containers from the same directory tree will not make
terminated. When the mode parameter is specified as <option>no</option> (the default), the whole OS tree is
made available writable (unless <option>--read-only</option> is specified, see above).</para>
- <para>Note that if one of the volatile modes is chosen, its effect is limited to the root file system (or
- <filename>/var/</filename> in case of <option>state</option>), and any other mounts placed in the hierarchy are
- unaffected — regardless if they are established automatically (e.g. the EFI system partition that might be
- mounted to <filename>/efi/</filename> or <filename>/boot/</filename>) or explicitly (e.g. through an additional
- command line option such as <option>--bind=</option>, see below). This means, even if
- <option>--volatile=overlay</option> is used changes to <filename>/efi/</filename> or
- <filename>/boot/</filename> are prohibited in case such a partition exists in the container image operated on,
- and even if <option>--volatile=state</option> is used the hypothetical file <filename>/etc/foobar</filename> is
- potentially writable if <option>--bind=/etc/foobar</option> if used to mount it from outside the read-only
- container <filename>/etc</filename> directory.</para>
+ <para>Note that if one of the volatile modes is chosen, its effect is limited to the root file system
+ (or <filename>/var/</filename> in case of <option>state</option>), and any other mounts placed in the
+ hierarchy are unaffected — regardless if they are established automatically (e.g. the EFI system
+ partition that might be mounted to <filename>/efi/</filename> or <filename>/boot/</filename>) or
+ explicitly (e.g. through an additional command line option such as <option>--bind=</option>, see
+ below). This means, even if <option>--volatile=overlay</option> is used changes to
+ <filename>/efi/</filename> or <filename>/boot/</filename> are prohibited in case such a partition
+ exists in the container image operated on, and even if <option>--volatile=state</option> is used the
+ hypothetical file <filename index="false">/etc/foobar</filename> is potentially writable if
+ <option>--bind=/etc/foobar</option> if used to mount it from outside the read-only container
+ <filename>/etc/</filename> directory.</para>
<para>The <option>--ephemeral</option> option is closely related to this setting, and provides similar
behaviour by making a temporary, ephemeral copy of the whole OS image and executing that. For further details,
<literal>user.verity.usrhash</literal> extended file attribute or via a <filename>.usrhash</filename>
file adjacent to the disk image, following the same format and logic as for the root hash for the
root file system described here. Note that there's currently no switch to configure the root hash for
- the <filename>/usr/</filename> from the command line.</para></listitem>
+ the <filename>/usr/</filename> from the command line.</para>
+
+ <para>Also see the <varname>RootHash=</varname> option in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </listitem>
</varlistentry>
<varlistentry>
<term><option>--root-hash-sig=</option></term>
- <listitem><para>Takes a PKCS7 formatted binary signature of the <option>--root-hash=</option> option as a path
- to a DER encoded signature file or as an ASCII base64 string encoding of the DER encoded signature, prefixed
- by <literal>base64:</literal>. The dm-verity volume will only be opened if the signature of the root hash hex
- string is valid and done by a public key present in the kernel keyring. If this option is not specified, but a
- file with the <filename>.roothash.p7s</filename> suffix is found next to the image file, bearing otherwise the
- same name (except if the image has the <filename>.raw</filename> suffix, in which case the signature file must
- not have it in its name), the signature is read from it and automatically used.</para>
-
- <para>The root hash for the <filename>/usr/</filename> file system included in a disk image may be
- configured via a <filename>.usrhash.p7s</filename> file adjacent to the disk image. There's currently
- no switch to configure the signature of the root hash of the <filename>/usr/</filename> file system
- from the command line.</para></listitem>
+ <listitem><para>Takes a PKCS7 signature of the <option>--root-hash=</option> option.
+ The semantics are the same as for the <varname>RootHashSignature=</varname> option, see
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
</varlistentry>
<varlistentry>
and mount options. The source path may optionally be prefixed with a <literal>+</literal> character. If so, the
source path is taken relative to the image's root directory. This permits setting up bind mounts within the
container image. The source path may be specified as empty string, in which case a temporary directory below
- the host's <filename>/var/tmp</filename> directory is used. It is automatically removed when the container is
+ the host's <filename>/var/tmp/</filename> directory is used. It is automatically removed when the container is
shut down. Mount options are comma-separated and currently, only <option>rbind</option> and
<option>norbind</option> are allowed, controlling whether to create a recursive or a regular bind
mount. Defaults to "rbind". Backslash escapes are interpreted, so <literal>\:</literal> may be used to embed
point for the overlay file system in the container. At least
two paths have to be specified.</para>
- <para>The source paths may optionally be prefixed with <literal>+</literal> character. If so they are taken
- relative to the image's root directory. The uppermost source path may also be specified as empty string, in
- which case a temporary directory below the host's <filename>/var/tmp</filename> is used. The directory is
- removed automatically when the container is shut down. This behaviour is useful in order to make read-only
- container directories writable while the container is running. For example, use the
- <literal>--overlay=+/var::/var</literal> option in order to automatically overlay a writable temporary
- directory on a read-only <filename>/var</filename> directory.</para>
+ <para>The source paths may optionally be prefixed with <literal>+</literal> character. If so they are
+ taken relative to the image's root directory. The uppermost source path may also be specified as an
+ empty string, in which case a temporary directory below the host's <filename>/var/tmp/</filename> is
+ used. The directory is removed automatically when the container is shut down. This behaviour is
+ useful in order to make read-only container directories writable while the container is running. For
+ example, use <literal>--overlay=+/var::/var</literal> in order to automatically overlay a writable
+ temporary directory on a read-only <filename>/var/</filename> directory.</para>
<para>For details about overlay file systems, see <ulink
url="https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt">overlayfs.txt</ulink>. Note
--- /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+ -->
+
+<refentry id="systemd-oomd.service" conditional='ENABLE_OOMD'>
+
+ <refentryinfo>
+ <title>systemd-oomd.service</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-oomd.service</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-oomd.service</refname>
+ <refname>systemd-oomd</refname>
+ <refpurpose>A userspace out-of-memory (OOM) killer</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>systemd-oomd.service</filename></para>
+ <para><filename>/usr/lib/systemd/systemd-oomd</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-oomd</command> is a system service that uses cgroups-v2 and pressure stall information (PSI)
+ to monitor and take action on processes before an OOM occurs in kernel space.</para>
+
+ <para>You can enable monitoring and actions on units by setting <varname>ManagedOOMSwap=</varname> and/or
+ <varname>ManagedOOMMemoryPressure=</varname> to the appropriate value. <command>systemd-oomd</command> will
+ periodically poll enabled units' cgroup data to detect when corrective action needs to occur. When an action needs
+ to happen, it will only be performed on the descendant cgroups of the enabled units. More precisely, only cgroups with
+ <filename>memory.oom.group</filename> set to <constant>1</constant> and leaf cgroup nodes are eligible candidates.
+ Action will be taken recursively on all of the processes under the chosen candidate.</para>
+
+ <para>See
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more information about the configuration of this service.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Setup Information</title>
+
+ <para>The system must be running systemd with a full unified cgroup hierarchy for the expected cgroups-v2 features.
+ Furthermore, resource accounting must be turned on for all units monitored by <command>systemd-oomd</command>.
+ The easiest way to turn on resource accounting is by ensuring the values for <varname>DefaultCPUAccounting</varname>,
+ <varname>DefaultIOAccounting</varname>, <varname>DefaultMemoryAccounting</varname>, and
+ <varname>DefaultTasksAccounting</varname> are set to <constant>true</constant> in
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+ <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.
+ 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>
+ for more details on swap.</para>
+
+ <para>Be aware that if you intend to enable monitoring and actions on <filename>user.slice</filename>,
+ <filename>user-$UID.slice</filename>, or their ancestor cgroups, it is highly recommended that your programs be
+ managed by the systemd user manager to prevent running too many processes under the same session scope (and thus
+ avoid a situation where memory intensive tasks trigger <command>systemd-oomd</command> to kill everything under the
+ cgroup). If you're using a desktop environment like GNOME, it already spawns many session components with the
+ systemd user manager.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Usage Recommendations</title>
+
+ <para><varname>ManagedOOMSwap=</varname> works with the system-wide swap values, so setting it on the root slice
+ <filename>-.slice</filename>, and allowing all descendant cgroups to be eligible candidates may make the most
+ sense.</para>
+
+ <para><varname>ManagedOOMMemoryPressure=</varname> tends to work better on the cgroups below the root slice
+ <filename>-.slice</filename>. For units which tend to have processes that are less latency sensitive (e.g.
+ <filename>system.slice</filename>), a higher limit like the default of 60% may be acceptable, as those processes
+ can usually ride out slowdowns caused by lack of memory without serious consequences. However, something like
+ <filename>user@$UID.service</filename> may prefer a much lower value like 40%.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>oomctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+</refentry>
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>, or
gathered from the partition table (when
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- is active) to the root file system, the <filename>/usr</filename> file system, and the kernel API file
+ is active) to the root file system, the <filename>/usr/</filename> file system, and the kernel API file
systems. This is required so that the mount options of these file systems — which are pre-mounted by the
kernel, the initial RAM disk, container environments or system manager code — are updated to those
configured in <filename>/etc/fstab</filename> and the other sources. This service ignores normal file
- systems and only changes the root file system (i.e. <filename>/</filename>), <filename>/usr</filename>,
- and the virtual kernel API file systems such as <filename>/proc</filename>, <filename>/sys</filename> or
- <filename>/dev</filename>. This service executes no operation if no configuration is found
+ systems and only changes the root file system (i.e. <filename>/</filename>), <filename>/usr/</filename>,
+ and the virtual kernel API file systems such as <filename>/proc/</filename>, <filename>/sys/</filename> or
+ <filename>/dev/</filename>. This service executes no operation if no configuration is found
(<filename>/etc/fstab</filename> does not exist or lists no entries for the mentioned file systems, or
the partition table does not contain relevant entries).</para>
<refsect1>
<title>Synthetic Records</title>
- <para><command>systemd-resolved</command> synthesizes DNS resource records (RRs) for the following
+ <para><command>systemd-resolved</command> synthetizes DNS resource records (RRs) for the following
cases:</para>
<itemizedlist>
<listitem><para>The local, configured hostname is resolved to all locally configured IP addresses
ordered by their scope, or — if none are configured — the IPv4 address 127.0.0.2 (which is on the local
- loopback) and the IPv6 address ::1 (which is the local host).</para></listitem>
+ loopback interface) and the IPv6 address ::1 (which is the local host).</para></listitem>
<listitem><para>The hostnames <literal>localhost</literal> and <literal>localhost.localdomain</literal>
- (as well as any hostname ending in <literal>.localhost</literal> or
- <literal>.localhost.localdomain</literal>) are resolved to the IP addresses 127.0.0.1 and ::1.
+ as well as any hostname ending in <literal>.localhost</literal> or
+ <literal>.localhost.localdomain</literal> are resolved to the IP addresses 127.0.0.1 and ::1.
</para></listitem>
<listitem><para>The hostname <literal>_gateway</literal> is resolved to all current default routing
according to the following rules:</para>
<itemizedlist>
- <listitem><para>Names for which synthetic records are generated (as listed in the previous section) are
- never routed to the network and a reply is sent immediately. In particular this means that lookups for
- <literal>localhost</literal> are never routed to the network.</para></listitem>
-
- <listitem><para>Single-label names are routed to all local interfaces capable of IP multicasting, where
- LLMNR is not disabled, using the LLMNR protocol. Lookups for IPv4 addresses are only sent via LLMNR on
- IPv4, and lookups for IPv6 addresses are only sent via LLMNR on IPv6. Lookups for the locally
- configured hostname and the <literal>_gateway</literal> hostname are never routed to LLMNR.
- </para></listitem>
-
- <listitem><para>Multi-label names with the domain suffix <literal>.local</literal> are routed to all
- local interfaces capable of IP multicasting, where MulticastDNS is not disabled, using the MulticastDNS
- protocol. As with LLMNR, IPv4 address lookups are sent via IPv4 and IPv6 address lookups are sent via
- IPv6.</para></listitem>
-
- <listitem><para>Resolution of address records (A and AAAA) via unicast DNS (i.e. not LLMNR or
- MulticastDNS) for non-synthesized single-label names is allowed for non-top-level domains. This means
- that such records can be resolved when search domains are defined. For any interface which defines
- search domains, such look-ups are routed to that interface, suffixed with each of the search domains
- defined on that interface in turn. When global search domains are defined, such look-ups are routed to
- all interfaces, suffixed by each of the global search domains in turn. Additionally, lookup of
- single-label names via unicast DNS may be enabled with the
- <varname>ResolveUnicastSingleLabel=yes</varname> setting. The details of which servers are queried and
- how the final reply is chosen are described below. Note that this means that address queries for
- single-label names are never sent out to remote DNS servers by default, and if no search domains are
- defined, resolution will fail.</para></listitem>
-
- <listitem><para>Other multi-label names are routed to all local interfaces that have a DNS server
- configured, plus the globally configured DNS servers if there are any. Note that by default, lookups for
- domains with the <literal>.local</literal> suffix are not routed to DNS servers, unless the domain is
- specified explicitly as routing or search domain for the DNS server and interface. This means that on
- networks where the <literal>.local</literal> domain is defined in a site-specific DNS server, explicit
- search or routing domains need to be configured to make lookups within this DNS domain work. Note that
- these days, it's generally recommended to avoid defining <literal>.local</literal> in a DNS server, as
- <ulink url="https://tools.ietf.org/html/rfc6762">RFC6762</ulink> reserves this domain for exclusive
+ <listitem><para>Names for which synthetic records are generated (the local hostname,
+ <literal>localhost</literal> and <literal>localdomain</literal>, local gateway, as listed in the
+ previous section) and addresses configured in <filename>/etc/hosts</filename> are never routed to the
+ network and a reply is sent immediately.</para></listitem>
+
+ <listitem><para>Single-label names are resolved using LLMNR on all local interfaces where LLMNR is
+ enabled. Lookups for IPv4 addresses are only sent via LLMNR on IPv4, and lookups for IPv6 addresses are
+ only sent via LLMNR on IPv6. Note that lookups for single-label synthetized names are not routed to
+ LLMNR, MulticastDNS or unicast DNS.</para></listitem>
+
+ <listitem><para>Queries for the address records (A and AAAA) of single-label non-synthetized names are
+ resolved via unicast DNS using search domains. For any interface which defines search domains, such
+ look-ups are routed to that interface, suffixed with each of the search domains defined on that
+ interface in turn. When global search domains are defined, such look-ups are routed to all interfaces,
+ suffixed by each of the global search domains in turn. Additionally, lookup of single-label names via
+ unicast DNS may be enabled with the <varname>ResolveUnicastSingleLabel=yes</varname> setting. The
+ details of which servers are queried and how the final reply is chosen are described below. Note that
+ this means that address queries for single-label names are never sent out to remote DNS servers by
+ default, and resoulution is only possible if search domains are defined.</para></listitem>
+
+ <listitem><para>Multi-label names with the domain suffix <literal>.local</literal> are resolved using
+ MulticastDNS on all local interfaces where MulticastDNS is enabled. As with LLMNR, IPv4 address lookups
+ are sent via IPv4 and IPv6 address lookups are sent via IPv6.</para></listitem>
+
+ <listitem><para>Queries for multi-label names are routed via unicast DNS on local interfaces that have
+ a DNS server configured, plus the globally configured DNS servers if there are any. Which interfaces
+ are used is determined by the routing logic based on search and route-only domains, described below.
+ Note that by default, lookups for domains with the <literal>.local</literal> suffix are not routed to
+ DNS servers, unless the domain is specified explicitly as routing or search domain for the DNS server
+ and interface. This means that on networks where the <literal>.local</literal> domain is defined in a
+ site-specific DNS server, explicit search or routing domains need to be configured to make lookups work
+ within this DNS domain. Note that these days, it's generally recommended to avoid defining
+ <literal>.local</literal> in a DNS server, as <ulink
+ url="https://tools.ietf.org/html/rfc6762">RFC6762</ulink> reserves this domain for exclusive
MulticastDNS use.</para></listitem>
- <listitem><para>Address lookups are routed similarly to multi-label names, with the exception that
- addresses from the link-local address range are never routed to unicast DNS and are only resolved using
- LLMNR and MulticastDNS (when enabled).</para></listitem>
+ <listitem><para>Address lookups (reverse lookups) are routed similarly to multi-label names, with the
+ exception that addresses from the link-local address range are never routed to unicast DNS and are only
+ resolved using LLMNR and MulticastDNS (when enabled).</para></listitem>
</itemizedlist>
<para>If lookups are routed to multiple interfaces, the first successful response is returned (thus
effectively merging the lookup zones on all matching interfaces). If the lookup failed on all interfaces,
the last failing response is returned.</para>
- <para>Routing of lookups may be influenced by configuring per-interface domain names and other
- settings. See
+ <para>Routing of lookups is determined by the per-interface routing domains (search and route-only) and
+ global search domains. See
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> and
- <citerefentry><refentrytitle>resolvectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
- details. The following query routing logic applies for unicast DNS traffic:</para>
+ <citerefentry><refentrytitle>resolvectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for a
+ description how those settings are set dynamically and the discussion of <varname>Domains=</varname> in
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for a
+ description of globally configured DNS settings.</para>
+
+ <para>The following query routing logic applies for unicast DNS traffic:</para>
<itemizedlist>
<listitem><para>If a name to look up matches (that is: is equal to or has as suffix) any of the
- configured search or route-only domains of any link (see
- <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
- or the globally configured DNS settings (see the discussion of <varname>Domains=</varname> in
- <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
- "best matching" search/route-only domain is determined: the matching one with the most labels. The
- query is then sent to all DNS servers of any links or the globally configured DNS servers associated
- with this "best matching" search/route-only domain. (Note that more than one link might have this same
- "best matching" search/route-only domain configured, in which case the query is sent to all of them in
- parallel).</para>
+ configured routing domains (search or route-only) of any link, or the globally configured DNS settings,
+ "best matching" routing domain is determined: the matching one with the most labels. The query is then
+ sent to all DNS servers of any links or the globally configured DNS servers associated with this "best
+ matching" routing domain. (Note that more than one link might have this same "best matching" routing
+ domain configured, in which case the query is sent to all of them in parallel).</para>
<para>In case of single-label names, when search domains are defined, the same logic applies, except
- that the name is first suffixed by the search domain.</para></listitem>
+ that the name is first suffixed by each of the search domains in turn. Note that this search logic
+ doesn't apply to any names with at least one dot. Also see the discussion about compatiblity with
+ the traditional glibc resolver below.</para></listitem>
- <listitem><para>If a query does not match any configured search/route-only domain (neither per-link nor
- global), it is sent to all DNS servers that are configured on links with the "DNS default route" option
- set, as well as the globally configured DNS server.</para></listitem>
+ <listitem><para>If a query does not match any configured routing domain (either per-link or global), it
+ is sent to all DNS servers that are configured on links with the <varname>DefaultRoute=</varname>
+ option set, as well as the globally configured DNS server.</para></listitem>
- <listitem><para>If there is no link configured as "DNS default route" and no global DNS server
- configured, the compiled-in fallback DNS server is used.</para></listitem>
+ <listitem><para>If there is no link configured as <varname>DefaultRoute=</varname> and no global DNS
+ server configured, one of the compiled-in fallback DNS servers is used.</para></listitem>
- <listitem><para>Otherwise the query is failed as no suitable DNS servers could be determined.
+ <listitem><para>Otherwise the unicast DNS query fails, as no suitable DNS servers can be determined.
</para></listitem>
</itemizedlist>
- <para>The "DNS default route" option is a boolean setting configurable with <command>resolvectl</command>
- or in <filename>.network</filename> files. If not set, it is implicitly determined based on the
- configured DNS domains for a link: if there's any route-only domain (not matching <literal>~.</literal>)
- it defaults to false, otherwise to true.</para>
+ <para>The <varname>DefaultRoute=</varname> option is a boolean setting configurable with
+ <command>resolvectl</command> or in <filename>.network</filename> files. If not set, it is implicitly
+ determined based on the configured DNS domains for a link: if there's a route-only domain other than
+ <literal>~.</literal>, it defaults to false, otherwise to true.</para>
<para>Effectively this means: in order to support single-label non-synthetized names, define appropriate
- search domains. In order to preferably route all DNS queries not explicitly matched by search/route-only
- domain configuration to a specific link, configure a <literal>~.</literal> route-only domain on it. This
- will ensure that other links will not be considered for these queries (unless they too carry such a
- route-only domain). In order to route all such DNS queries to a specific link only if no other link
- is preferable, set the "DNS default route" option for the link to true and do not configure a
+ search domains. In order to preferably route all DNS queries not explicitly matched by routing domain
+ configuration to a specific link, configure a <literal>~.</literal> route-only domain on it. This will
+ ensure that other links will not be considered for these queries (unless they too carry such a routing
+ domain). In order to route all such DNS queries to a specific link only if no other link is preferred,
+ set the <varname>DefaultRoute=</varname> option for the link to true and do not configure a
<literal>~.</literal> route-only domain on it. Finally, in order to ensure that a specific link never
- receives any DNS traffic not matching any of its configured search/route-only domains, set the "DNS
- default route" option for it to false.</para>
+ receives any DNS traffic not matching any of its configured routing domains, set the
+ <varname>DefaultRoute=</varname> option for it to false.</para>
- <para>See the <ulink url="https://www.freedesktop.org/wiki/Software/systemd/resolved">resolved D-Bus API
- Documentation</ulink> for information about the APIs <filename>systemd-resolved</filename> provides.
- </para>
+ <para>See
+ <citerefentry><refentrytitle>org.freedesktop.resolve1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for information about the D-Bus APIs <filename>systemd-resolved</filename> provides.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility with the traditional glibc stub resolver</title>
+
+ <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
+ <citerefentry><refentrytitle>nss-dns</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+ <itemizedlist>
+ <listitem><para>Some names are always resolved internally (see Synthetic Records above). Traditionally
+ they would be resolved by <filename>nss-files</filename>, and only if provided in
+ <filename>/etc/hosts</filename>.</para></listitem>
+
+ <listitem><para>Single-label names are not resolved for A and AAAA records using unicast DNS (unless
+ overriden with <varname>ResolveUnicastSingleLabel=</varname>, see
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
+ This is similar to the <option>no-tld-query</option> option being set in
+ <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+
+ <listitem><para>Search domains are not used for <emphasis>suffixing</emphasis> of multi-label names.
+ (Search domains are nevertheless used for lookup <emphasis>routing</emphasis>, for names that were
+ originally specified as single-label or multi-label.) Any name with at least one dot is always
+ interpreted as a FQDN. <filename>nss-dns</filename> would resolve names both as relative (using search
+ domains) and absolute FQDN names. Some names would be resolved as relative first, and after that query
+ has failed, as absolute, while other names would be resolved in opposite order. The
+ <varname>ndots</varname> option in <filename>/etc/resolv.conf</filename> was used to control how many
+ dots the name needs to have to be resolved as relative first. This stub resolver does not implement
+ this at all: multi-label names are only resolved as FQDNs. (There are currently more than 1500
+ top-level domain names defined, and new ones are added regularly, often using "attractive" names that
+ are also likely to be used locally. Not looking up multi-label names in this fashion avoids fragility
+ in both directions: a valid global name could be obscured by a local name, and resolution of a relative
+ local name could suddenly break when a new top-level domain is created, or when a new subdomain of a
+ top-level domain in registered. Resolving any given name as either relative or absolute avoids this
+ ambiguity.)</para></listitem>
+
+ <listitem><para>This resolver has a notion of the special <literal>.local</literal> domain used for
+ MulticastDNS, and will not route queries with that suffix to unicast DNS servers unless explicitly
+ configured, see above. Also, reverse lookups for link-local addresses are not sent to unicast DNS
+ servers.</para></listitem>
+
+ <listitem><para>This resolver reads and caches <filename>/etc/hosts</filename> internally. (In other
+ words, <filename>nss-resolve</filename> replaces <filename>nss-files</filename> in addition to
+ <filename>nss-dns</filename>). Entries in <filename>/etc/hosts</filename> have highest priority.</para>
+ </listitem>
+
+ <listitem><para>This resolver also implements LLMNR and MulticastDNS in addition to the classic unicast
+ DNS protocol, and will resolve single-label names using LLMNR (when enabled) and names ending in
+ <literal>.local</literal> using MulticastDNS (when enabled).</para></listitem>
+
+ <listitem><para>Environment variables <varname>$LOCALDOMAIN</varname> and
+ <varname>$RES_OPTIONS</varname> described in
+ <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> are not
+ supported currently.</para></listitem>
+ </itemizedlist>
</refsect1>
<refsect1>
synchronous way.</para></listitem>
</varlistentry>
</variablelist>
-
</refsect1>
<refsect1>
<para>See
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for information about the configuration of sysctl settings. After sysctl configuration is
- changed on disk, it must be written to the files in <filename>/proc/sys</filename> before it
+ changed on disk, it must be written to the files in <filename>/proc/sys/</filename> before it
takes effect. It is possible to update specific settings, or simply to reload all configuration,
see Examples below.</para>
</refsect1>
and administrator-controlled files under <filename>/usr/share/user-tmpfiles.d/</filename>. Users may use
this to create and clean up files under their control, but the system instance performs global cleanup
and is not influenced by user configuration. Note that this means a time-based cleanup configured in the
- system instance, such as the one typically configured for <filename>/tmp</filename>, will thus also
- affect files created by the user instance if they are placed in <filename>/tmp</filename>, even if the
+ system instance, such as the one typically configured for <filename>/tmp/</filename>, will thus also
+ affect files created by the user instance if they are placed in <filename>/tmp/</filename>, even if the
user instance's time-based cleanup is turned off.</para>
</refsect1>
runtime.</para>
<para><command>systemd-tty-ask-password-agent</command> implements
- the <ulink url="https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">Password
- Agents Specification</ulink>, and is one of many possible response agents which
+ the <ulink url="https://systemd.io/PASSWORD_AGENTS/">Password Agents
+ Specification</ulink>, and is one of many possible response agents which
answer to queries formulated with
<citerefentry><refentrytitle>systemd-ask-password</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para>
<refnamediv>
<refname>systemd-update-done.service</refname>
<refname>systemd-update-done</refname>
- <refpurpose>Mark <filename>/etc</filename> and <filename>/var</filename> fully updated</refpurpose>
+ <refpurpose>Mark <filename>/etc/</filename> and <filename>/var/</filename> fully updated</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-update-done.service</filename> is a
service that is invoked as part of the first boot after the vendor
- operating system resources in <filename>/usr</filename> have been
+ operating system resources in <filename>/usr/</filename> have been
updated. This is useful to implement offline updates of
- <filename>/usr</filename> which might require updates to
- <filename>/etc</filename> or <filename>/var</filename> on the
+ <filename>/usr/</filename> which might require updates to
+ <filename>/etc/</filename> or <filename>/var/</filename> on the
following boot.</para>
<para><filename>systemd-update-done.service</filename> updates the
file modification time (mtime) of the stamp files
<filename>/etc/.updated</filename> and
<filename>/var/.updated</filename> to the modification time of the
- <filename>/usr</filename> directory, unless the stamp files are
+ <filename>/usr/</filename> directory, unless the stamp files are
already newer.</para>
<para>Services that shall run after offline upgrades of
- <filename>/usr</filename> should order themselves before
+ <filename>/usr/</filename> should order themselves before
<filename>systemd-update-done.service</filename>, and use the
<varname>ConditionNeedsUpdate=</varname> (see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
- condition to make sure to run when <filename>/etc</filename> or
- <filename>/var</filename> are older than <filename>/usr</filename>
+ condition to make sure to run when <filename>/etc/</filename> or
+ <filename>/var/</filename> are older than <filename>/usr/</filename>
according to the modification times of the files described above.
- This requires that updates to <filename>/usr</filename> are always
+ This requires that updates to <filename>/usr/</filename> are always
followed by an update of the modification time of
- <filename>/usr</filename>, for example by invoking
+ <filename>/usr/</filename>, for example by invoking
<citerefentry project='man-pages'><refentrytitle>touch</refentrytitle><manvolnum>1</manvolnum></citerefentry>
on it.</para>
<para><filename>systemd-volatile-root.service</filename> is a service that replaces the root directory with a
volatile memory file system (<literal>tmpfs</literal>), mounting the original (non-volatile)
- <filename>/usr</filename> inside it read-only. This way, vendor data from <filename>/usr</filename> is available as
- usual, but all configuration data in <filename>/etc</filename>, all state data in <filename>/var</filename> and all
+ <filename>/usr/</filename> inside it read-only. This way, vendor data from <filename>/usr/</filename> is available as
+ usual, but all configuration data in <filename>/etc/</filename>, all state data in <filename>/var/</filename> and all
other resources stored directly under the root directory are reset on boot and lost at shutdown, enabling fully
stateless systems.</para>
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details.</para>
- <para>Device units are named after the <filename>/sys</filename>
- and <filename>/dev</filename> paths they control. Example: the
+ <para>Device units are named after the <filename>/sys/</filename>
+ and <filename>/dev/</filename> paths they control. Example: the
device <filename index="false">/dev/sda5</filename> is exposed in
systemd as <filename>dev-sda5.device</filename>. For details about
the escaping logic used to convert a file system path to a unit
<filename>/run/systemd/dnssd</filename> and the local administration network directory
<filename>/etc/systemd/dnssd</filename>. All configuration files are collectively sorted and processed in
lexical order, regardless of the directories in which they live. However, files with identical filenames
- replace each other. Files in <filename>/etc</filename> have the highest priority, files in
- <filename>/run</filename> take precedence over files with the same name in
- <filename>/usr/lib</filename>. This can be used to override a system-supplied configuration file with a
+ replace each other. Files in <filename>/etc/</filename> have the highest priority, files in
+ <filename>/run/</filename> take precedence over files with the same name in
+ <filename>/usr/lib/</filename>. This can be used to override a system-supplied configuration file with a
local file if needed.</para>
<para>Along with the network service file <filename>foo.dnssd</filename>, a "drop-in" directory
<para>In addition to <filename>/etc/systemd/dnssd</filename>, drop-in <literal>.d</literal> directories
can be placed in <filename>/usr/lib/systemd/dnssd</filename> or <filename>/run/systemd/dnssd</filename>
- directories. Drop-in files in <filename>/etc</filename> take precedence over those in
- <filename>/run</filename> which in turn take precedence over those in <filename>/usr/lib</filename> or
+ directories. Drop-in files in <filename>/etc/</filename> take precedence over those in
+ <filename>/run/</filename> which in turn take precedence over those in <filename>/usr/lib/</filename> or
<filename>/usr/local/lib</filename>. Drop-in files under any of these directories take precedence over
the main network service file wherever located.</para>
</refsect1>
to <filename>/dev/null</filename> or an empty file can be used to mask a generator, thereby
preventing it from running. Please note that the order of the two directories with the highest
priority is reversed with respect to the unit load path, and generators in
- <filename>/run</filename> overwrite those in <filename>/etc</filename>.</para>
+ <filename>/run/</filename> overwrite those in <filename>/etc/</filename>.</para>
<para>After installing new generators or updating the configuration, <command>systemctl
daemon-reload</command> may be executed. This will re-run all generators, updating environment
paths. This is equivalent to having them listed explicitly in
<varname>RequiresMountsFor=</varname>.</para></listitem>
- <listitem><para>Similar, units with <varname>PrivateTmp=</varname> enabled automatically get mount unit
- dependencies for all mounts required to access <filename>/tmp</filename> and <filename>/var/tmp</filename>. They
- will also gain an automatic <varname>After=</varname> dependency on
- <citerefentry><refentrytitle>systemd-tmpfiles-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para></listitem>
+ <listitem><para>Similarly, units with <varname>PrivateTmp=</varname> enabled automatically get mount
+ unit dependencies for all mounts required to access <filename>/tmp/</filename> and
+ <filename>/var/tmp/</filename>. They will also gain an automatic <varname>After=</varname> dependency
+ on
+ <citerefentry><refentrytitle>systemd-tmpfiles-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para></listitem>
<listitem><para>Units whose standard output or error output is connected to <option>journal</option> or
<option>kmsg</option> (or their combinations with console output, see below) automatically acquire
case the image has multiple partitions, otherwise partition name <literal>root</literal> is implied.
Options for multiple partitions can be specified in a single line with space separators. Assigning an empty
string removes previous assignments. Duplicated options are ignored. For a list of valid mount options, please
- refer to <citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ refer to
+ <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para>
<para>Valid partition names follow the <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable
Partitions Specification</ulink>.</para>
<varlistentry>
<term><varname>RootHashSignature=</varname></term>
- <listitem><para>Takes a PKCS7 formatted binary signature of the <varname>RootHash=</varname> option as a path
- to a DER encoded signature file or as an ASCII base64 string encoding of the DER encoded signature, prefixed
- by <literal>base64:</literal>. The dm-verity volume will only be opened if the signature of the root hash
- signature is valid and created by a public key present in the kernel keyring. If this option is not specified,
- but a file with the <filename>.roothash.p7s</filename> suffix is found next to the image file, bearing otherwise
- the same name (except if the image has the <filename>.raw</filename> suffix, in which case the signature file
- must not have it in its name), the signature is read from it and automatically used.</para>
+ <listitem><para>Takes a PKCS7 signature of the <varname>RootHash=</varname> option as a path to a
+ DER-encoded signature file, or as an ASCII base64 string encoding of a DER-encoded signature prefixed
+ by <literal>base64:</literal>. The dm-verity volume will only be opened if the signature of the root
+ hash is valid and signed by a public key present in the kernel keyring. If this option is not
+ specified, but a file with the <filename>.roothash.p7s</filename> suffix is found next to the image
+ file, bearing otherwise the same name (except if the image has the <filename>.raw</filename> suffix,
+ in which case the signature file must not have it in its name), the signature is read from it and
+ automatically used.</para>
<para>If the disk image contains a separate <filename>/usr/</filename> partition it may also be
Verity protected, in which case the signature for the root hash may configured via a
<term><varname>MountAPIVFS=</varname></term>
<listitem><para>Takes a boolean argument. If on, a private mount namespace for the unit's processes is created
- and the API file systems <filename>/proc</filename>, <filename>/sys</filename>, and <filename>/dev</filename>
+ and the API file systems <filename>/proc/</filename>, <filename>/sys/</filename>, and <filename>/dev/</filename>
are mounted inside of it, unless they are already mounted. Note that this option has no effect unless used in
conjunction with <varname>RootDirectory=</varname>/<varname>RootImage=</varname> as these three mounts are
generally mounted in the host anyway, and unless the root directory is changed, the private mount namespace
- will be a 1:1 copy of the host's, and include these three mounts. Note that the <filename>/dev</filename> file
+ will be a 1:1 copy of the host's, and include these three mounts. Note that the <filename>/dev/</filename> file
system of the host is bind mounted if this option is used without <varname>PrivateDevices=</varname>. To run
the service with a private, minimal version of <filename>/dev/</filename>, combine this option with
<varname>PrivateDevices=</varname>.</para>
<listitem><para>Takes a profile name as argument. The process executed by the unit will switch to
this profile when started. Profiles must already be loaded in the kernel, or the unit will fail. If
prefixed by <literal>-</literal>, all errors will be ignored. This setting has no effect if AppArmor
- is not enabled. This setting not affect commands prefixed with <literal>+</literal>.</para>
+ is not enabled. This setting does not affect commands prefixed with <literal>+</literal>.</para>
</listitem>
</varlistentry>
<listitem><para>Sets the CPU scheduling policy for executed processes. Takes one of <option>other</option>,
<option>batch</option>, <option>idle</option>, <option>fifo</option> or <option>rr</option>. See
- <citerefentry><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ <citerefentry project='man-pages'><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
<listitem><para>Sets the CPU scheduling priority for executed processes. The available priority range depends
on the selected CPU scheduling policy (see above). For real-time scheduling policies an integer between 1
(lowest priority) and 99 (highest priority) can be used. See
- <citerefentry><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ <citerefentry project='man-pages'><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>CPUSchedulingResetOnFork=</varname></term>
- <listitem><para>Takes a boolean argument. If true, elevated CPU scheduling priorities and policies will be
- reset when the executed processes fork, and can hence not leak into child processes. See
- <citerefentry><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
- details. Defaults to false.</para></listitem>
+ <listitem><para>Takes a boolean argument. If true, elevated CPU scheduling priorities and policies
+ will be reset when the executed processes call
+ <citerefentry project='man-pages'><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ and can hence not leak into child processes. See
+ <citerefentry project='man-pages'><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for details. Defaults to false.</para></listitem>
</varlistentry>
<varlistentry>
are specified by the lower and upper CPU indices separated by a dash. This option may be specified more than
once, in which case the specified CPU affinity masks are merged. If the empty string is assigned, the mask
is reset, all assignments prior to this will have no effect. See
- <citerefentry><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ <citerefentry project='man-pages'><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
<term><varname>ProtectSystem=</varname></term>
<listitem><para>Takes a boolean argument or the special values <literal>full</literal> or
- <literal>strict</literal>. If true, mounts the <filename>/usr</filename> and the boot loader
+ <literal>strict</literal>. If true, mounts the <filename>/usr/</filename> and the boot loader
directories (<filename>/boot</filename> and <filename>/efi</filename>) read-only for processes
- invoked by this unit. If set to <literal>full</literal>, the <filename>/etc</filename> directory is
+ invoked by this unit. If set to <literal>full</literal>, the <filename>/etc/</filename> directory is
mounted read-only, too. If set to <literal>strict</literal> the entire file system hierarchy is
- mounted read-only, except for the API file system subtrees <filename>/dev</filename>,
- <filename>/proc</filename> and <filename>/sys</filename> (protect these directories using
+ mounted read-only, except for the API file system subtrees <filename>/dev/</filename>,
+ <filename>/proc/</filename> and <filename>/sys/</filename> (protect these directories using
<varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
<varname>ProtectControlGroups=</varname>). This setting ensures that any modification of the vendor-supplied
operating system (and optionally its configuration, and local mounts) is prohibited for the service. It is
<term><varname>ProtectHome=</varname></term>
<listitem><para>Takes a boolean argument or the special values <literal>read-only</literal> or
- <literal>tmpfs</literal>. If true, the directories <filename>/home</filename>,
+ <literal>tmpfs</literal>. If true, the directories <filename>/home/</filename>,
<filename>/root</filename>, and <filename>/run/user</filename> are made inaccessible and empty for
processes invoked by this unit. If set to <literal>read-only</literal>, the three directories are
made read-only instead. If set to <literal>tmpfs</literal>, temporary file systems are mounted on the
<term><varname>LogsDirectory=</varname></term>
<term><varname>ConfigurationDirectory=</varname></term>
- <listitem><para>These options take a whitespace-separated list of directory names. The specified directory
- names must be relative, and may not include <literal>..</literal>. If set, one or more
- directories by the specified names will be created (including their parents) below the locations
- defined in the following table, when the unit is started. Also, the corresponding environment variable
- is defined with the full path of directories. If multiple directories are set, then in the environment variable
- the paths are concatenated with colon (<literal>:</literal>).</para>
+ <listitem><para>These options take a whitespace-separated list of directory names. The specified
+ directory names must be relative, and may not include <literal>..</literal>. If set, when the unit is
+ started, one or more directories by the specified names will be created (including their parents)
+ below the locations defined in the following table. Also, the corresponding environment variable will
+ be defined with the full paths of the directories. If multiple directories are set, then in the
+ environment variable the paths are concatenated with colon (<literal>:</literal>).</para>
<table>
<title>Automatic directory creation and environment variables</title>
<tgroup cols='4'>
<para>Use <varname>RuntimeDirectory=</varname> to manage one or more runtime directories for the unit and bind
their lifetime to the daemon runtime. This is particularly useful for unprivileged daemons that cannot create
- runtime directories in <filename>/run</filename> due to lack of privileges, and to make sure the runtime
+ runtime directories in <filename>/run/</filename> due to lack of privileges, and to make sure the runtime
directory is cleaned up automatically after use. For runtime directories that require more complex or different
configuration or lifetime guarantees, please consider using
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>The directories defined by these options are always created under the standard paths used by systemd
- (<filename>/var</filename>, <filename>/run</filename>, <filename>/etc</filename>, …). If the service needs
+ (<filename>/var/</filename>, <filename>/run/</filename>, <filename>/etc/</filename>, …). If the service needs
directories in a different location, a different mechanism has to be used to create them.</para>
<para><citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> provides
<para>Example: if a system service unit has the following,
<programlisting>RuntimeDirectory=foo/bar baz</programlisting>
- the service manager creates <filename>/run/foo</filename> (if it does not exist),
+ the service manager creates <filename index='false'>/run/foo</filename> (if it does not exist),
<filename index='false'>/run/foo/bar</filename>, and <filename index='false'>/run/baz</filename>. The
directories <filename index='false'>/run/foo/bar</filename> and
and manually restarted. Here, the automatic restart means the operation specified in
<varname>Restart=</varname>, and manual restart means the one triggered by <command>systemctl restart
foo.service</command>. If set to <option>yes</option>, then the directories are not removed when the service is
- stopped. Note that since the runtime directory <filename>/run</filename> is a mount point of
+ stopped. Note that since the runtime directory <filename>/run/</filename> is a mount point of
<literal>tmpfs</literal>, then for system services the directories specified in
<varname>RuntimeDirectory=</varname> are removed when the system is rebooted.</para></listitem>
</varlistentry>
<term><varname>ReadOnlyPaths=</varname></term>
<term><varname>InaccessiblePaths=</varname></term>
- <listitem><para>Sets up a new file system namespace for executed processes. These options may be used to limit
- access a process might have to the file system hierarchy. Each setting takes a space-separated list of paths
- relative to the host's root directory (i.e. the system running the service manager). Note that if paths
- contain symlinks, they are resolved relative to the root directory set with
+ <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
+ relative to the host's root directory (i.e. the system running the service manager). Note that if
+ paths contain symlinks, they are resolved relative to the root directory set with
<varname>RootDirectory=</varname>/<varname>RootImage=</varname>.</para>
<para>Paths listed in <varname>ReadWritePaths=</varname> are accessible from within the namespace
<para>Example: if a unit has the following,
<programlisting>TemporaryFileSystem=/var:ro
BindReadOnlyPaths=/var/lib/systemd</programlisting>
- then the invoked processes by the unit cannot see any files or directories under <filename>/var</filename> except for
+ then the invoked processes by the unit cannot see any files or directories under <filename>/var/</filename> except for
<filename>/var/lib/systemd</filename> or its contents.</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
<varlistentry>
<term><varname>PrivateTmp=</varname></term>
- <listitem><para>Takes a boolean argument. If true, sets up a new file system namespace for the 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
+ <listitem><para>Takes a boolean argument. If true, sets up a new file system namespace for the
+ 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 <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 implicitly <varname>After=</varname> ordering on
+ 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
+ implicitly <varname>After=</varname> ordering on
<citerefentry><refentrytitle>systemd-tmpfiles-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is added.</para>
<varlistentry>
<term><varname>PrivateDevices=</varname></term>
- <listitem><para>Takes a boolean argument. If true, sets up a new <filename>/dev</filename> mount for the
+ <listitem><para>Takes a boolean argument. If true, sets up a new <filename>/dev/</filename> mount for the
executed processes and only adds API pseudo devices such as <filename>/dev/null</filename>,
<filename>/dev/zero</filename> or <filename>/dev/random</filename> (as well as the pseudo TTY subsystem) to it,
but no physical devices such as <filename>/dev/sda</filename>, system memory <filename>/dev/mem</filename>,
for details). Note that using this setting will disconnect propagation of mounts from the service to the host
(propagation in the opposite direction continues to work). This means that this setting may not be used for
services which shall be able to install mount points in the main mount namespace. The new
- <filename>/dev</filename> will be mounted read-only and 'noexec'. The latter may break old programs which try
+ <filename>/dev/</filename> will be mounted read-only and 'noexec'. The latter may break old programs which try
to set up executable memory by using
<citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> of
<filename>/dev/zero</filename> instead of using <constant>MAP_ANON</constant>. For this setting the same
<term><varname>ProtectKernelTunables=</varname></term>
<listitem><para>Takes a boolean argument. If true, kernel variables accessible through
- <filename>/proc/sys</filename>, <filename>/sys</filename>, <filename>/proc/sysrq-trigger</filename>,
+ <filename>/proc/sys/</filename>, <filename>/sys/</filename>, <filename>/proc/sysrq-trigger</filename>,
<filename>/proc/latency_stats</filename>, <filename>/proc/acpi</filename>,
<filename>/proc/timer_stats</filename>, <filename>/proc/fs</filename> and <filename>/proc/irq</filename> will
be made read-only to all processes of the unit. Usually, tunable kernel variables should be initialized only at
<listitem><para>Takes a boolean argument. If true, the Linux Control Groups (<citerefentry
project='man-pages'><refentrytitle>cgroups</refentrytitle><manvolnum>7</manvolnum></citerefentry>) hierarchies
- accessible through <filename>/sys/fs/cgroup</filename> will be made read-only to all processes of the
+ accessible through <filename>/sys/fs/cgroup/</filename> will be made read-only to all processes of the
unit. Except for container managers no services should require write access to the control groups hierarchies;
it is hence recommended to turn this on for most services. For this setting the same restrictions regarding
mount propagation and privileges apply as for <varname>ReadOnlyPaths=</varname> and related calls, see
</row>
<row>
<entry>@process</entry>
- <entry>Process control, execution, namespaceing operations (<citerefentry project='man-pages'><refentrytitle>clone</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>, …)</entry>
+ <entry>Process control, execution, namespacing operations (<citerefentry project='man-pages'><refentrytitle>clone</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>, …)</entry>
</row>
<row>
<entry>@raw-io</entry>
</row>
<row>
<entry>@known</entry>
- <entry>All system calls defined by the kernel. This list is defined statically in systemd based on a kernel version that was available when this systmed version was released. It will become progressively more out-of-date as the kernel is updated.</entry>
+ <entry>All system calls defined by the kernel. This list is defined statically in systemd based on a kernel version that was available when this systemd version was released. It will become progressively more out-of-date as the kernel is updated.</entry>
</row>
</tbody>
</tgroup>
<varlistentry>
<term><varname>$LOG_NAMESPACE</varname></term>
- <listitem><para>If the <varname>LogNamespace=</varname> service setting is used, contains name of the
- selected logging namespace.</para></listitem>
+ <listitem><para>Contains the name of the selected logging namespace when the
+ <varname>LogNamespace=</varname> service setting is used.</para></listitem>
</varlistentry>
<varlistentry>
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry project='man-pages'><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry>
</para>
</refsect1>
<para>Directory paths for generator output differ by priority:
<filename>…/generator.early</filename> has priority higher than the admin
- configuration in <filename>/etc</filename>, while
+ configuration in <filename>/etc/</filename>, while
<filename>…/generator</filename> has lower priority than
- <filename>/etc</filename> but higher than vendor configuration in
- <filename>/usr</filename>, and <filename>…/generator.late</filename> has priority
+ <filename>/etc/</filename> but higher than vendor configuration in
+ <filename>/usr/</filename>, and <filename>…/generator.late</filename> has priority
lower than all other configuration. See the next section and the discussion of
unit load paths and unit overriding in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
mask a generator, thereby preventing it from running. Please note
that the order of the two directories with the highest priority is
reversed with respect to the unit load path, and generators in
- <filename>/run</filename> overwrite those in
- <filename>/etc</filename>.</para>
+ <filename>/run/</filename> overwrite those in
+ <filename>/etc/</filename>.</para>
<para>After installing new generators or updating the
configuration, <command>systemctl daemon-reload</command> may be
in case of the system generators and
<filename>$XDG_RUNTIME_DIR/generator.early</filename> in case of the user
generators. Unit files placed in this directory override unit files in
- <filename>/usr</filename>, <filename>/run</filename> and
- <filename>/etc</filename>. This means that unit files placed in this
+ <filename>/usr/</filename>, <filename>/run/</filename> and
+ <filename>/etc/</filename>. This means that unit files placed in this
directory take precedence over all normal configuration, both vendor and
user/administrator.</para>
</listitem>
<citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
or <command>systemd</command> itself (this means: no
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!
- Non-essential file systems like <filename>/var</filename> and
- <filename>/home</filename> are mounted after generators have run. Generators
+ Non-essential file systems like <filename>/var/</filename> and
+ <filename>/home/</filename> are mounted after generators have run. Generators
can however rely on the most basic kernel functionality to be available,
- including a mounted <filename>/sys</filename>, <filename>/proc</filename>,
- <filename>/dev</filename>, <filename>/usr</filename>.
+ including a mounted <filename>/sys/</filename>, <filename>/proc/</filename>,
+ <filename>/dev/</filename>, <filename>/usr/</filename>.
</para>
</listitem>
<para>Generators may write out dynamic unit files or just hook unit files
into other units with the usual <filename>.wants/</filename> or
<filename>.requires/</filename> symlinks. Often, it is nicer to simply
- instantiate a template unit file from <filename>/usr</filename> with a
+ instantiate a template unit file from <filename>/usr/</filename> with a
generator instead of writing out entirely dynamic unit files. Of course, this
works only if a single parameter is to be used.</para>
</listitem>
<orderedlist numeration="lowerroman">
<listitem>
<para>User configuration should override vendor configuration. This
- (mostly) means that stuff from <filename>/etc</filename> should override
- stuff from <filename>/usr</filename>.</para>
+ (mostly) means that stuff from <filename>/etc/</filename> should override
+ stuff from <filename>/usr/</filename>.</para>
</listitem>
<listitem>
argv[1] as location to place the generated unit files in order to allow the
user to override <filename>/etc/fstab</filename> with their own native unit
files, but also to ensure that <filename>/etc/fstab</filename> overrides any
- vendor default from <filename>/usr</filename>.</para>
+ vendor default from <filename>/usr/</filename>.</para>
<para>After editing <filename>/etc/fstab</filename>, the user should invoke
<command>systemctl daemon-reload</command>. This will re-run all generators and
<literal>file:/</literal>, <literal>man:</literal> or <literal>info:</literal> URL.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>TID=</varname></term>
+ <listitem>
+ <para>The numeric thread ID (TID) the log message originates from.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<term><varname>_SYSTEMD_OWNER_UID=</varname></term>
<listitem>
- <para>The control group path in the systemd hierarchy, the
- the systemd slice unit name, the systemd unit name, the
- unit name in the systemd user manager (if any), the systemd
- session ID (if any), and the owner UID of the systemd user
- unit or systemd session (if any) of the process the journal
- entry originates from.</para>
+ <para>The control group path in the systemd hierarchy, the systemd slice unit name, the systemd
+ unit name, the unit name in the systemd user manager (if any), the systemd session ID (if any), and
+ the owner UID of the systemd user unit or systemd session (if any) of the process the journal entry
+ originates from.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>_KERNEL_DEVICE=</varname></term>
<listitem>
- <para>The kernel device name. If the entry is associated to
- a block device, the major and minor of the device node,
- separated by <literal>:</literal> and prefixed by
- <literal>b</literal>. Similar for character devices but
- prefixed by <literal>c</literal>. For network devices, this
- is the interface index prefixed by <literal>n</literal>. For
- all other devices, this is the subsystem name prefixed by
- <literal>+</literal>, followed by <literal>:</literal>,
- followed by the kernel device name.</para>
+ <para>The kernel device name. If the entry is associated to a block device, contains the major and
+ minor numbers of the device node, separated by <literal>:</literal> and prefixed by
+ <literal>b</literal>. Similarly for character devices, but prefixed by <literal>c</literal>. For
+ network devices, this is the interface index prefixed by <literal>n</literal>. For all other
+ devices, this is the subsystem name prefixed by <literal>+</literal>, followed by
+ <literal>:</literal>, followed by the kernel device name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>_UDEV_SYSNAME=</varname></term>
<listitem>
<para>The kernel device name as it shows up in the device
- tree below <filename>/sys</filename>.</para>
+ tree below <filename>/sys/</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>_UDEV_DEVNODE=</varname></term>
<listitem>
<para>The device node path of this device in
- <filename>/dev</filename>.</para>
+ <filename>/dev/</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>_UDEV_DEVLINK=</varname></term>
<listitem>
<para>Additional symlink names pointing to the device node
- in <filename>/dev</filename>. This field is frequently set
+ in <filename>/dev/</filename>. This field is frequently set
more than once per entry.</para>
</listitem>
</varlistentry>
ignored. All link files are collectively sorted and processed in
lexical order, regardless of the directories in which they live.
However, files with identical filenames replace each other. Files
- in <filename>/etc</filename> have the highest priority, files in
- <filename>/run</filename> take precedence over files with the same
- name in <filename>/usr/lib</filename>. This can be used to
+ in <filename>/etc/</filename> have the highest priority, files in
+ <filename>/run/</filename> take precedence over files with the same
+ name in <filename>/usr/lib/</filename>. This can be used to
override a system-supplied link file with a local file if needed.
As a special case, an empty file (file size 0) or symlink with the
same name pointing to <filename>/dev/null</filename> disables the
<para>If a mount point is configured in both
<filename>/etc/fstab</filename> and a unit file that is stored
- below <filename>/usr</filename>, the former will take precedence.
- If the unit file is stored below <filename>/etc</filename>, it
+ below <filename>/usr/</filename>, the former will take precedence.
+ If the unit file is stored below <filename>/etc/</filename>, it
will take precedence. This means: native unit files take
precedence over traditional configuration files, but this is
superseded by the rule that configuration in
- <filename>/etc</filename> will always take precedence over
- configuration in <filename>/usr</filename>.</para>
+ <filename>/etc/</filename> will always take precedence over
+ configuration in <filename>/usr/</filename>.</para>
</refsect1>
<refsect1>
<para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
<constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
number is ignored.</para>
+
+ <para>In some configurations a parent PCI bridge of a given network controller may be associated
+ with a slot. In such case we don't generate this device property to avoid possible naming conflicts.</para>
</listitem>
</varlistentry>
<refsect1>
<title>History</title>
- <para>The following "naming schemes" have been defined:</para>
+ <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>
<variablelist>
<varlistentry>
multiple similarly named containers (who only differ in container name suffix) should be less
likely (but still possible, since the 24bit hash value is very small).</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><constant>v247</constant></term>
+
+ <listitem><para>If the PCI slot is assocated 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>
+ </varlistentry>
+
</variablelist>
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
directory <filename>/run/systemd/network</filename> and the local administration network
directory <filename>/etc/systemd/network</filename>. All configuration files are collectively
sorted and processed in lexical order, regardless of the directories in which they live.
- However, files with identical filenames replace each other. Files in <filename>/etc</filename>
- have the highest priority, files in <filename>/run</filename> take precedence over files with
- the same name in <filename>/usr/lib</filename>. This can be used to override a system-supplied
+ However, files with identical filenames replace each other. Files in <filename>/etc/</filename>
+ have the highest priority, files in <filename>/run/</filename> take precedence over files with
+ the same name in <filename>/usr/lib/</filename>. This can be used to override a system-supplied
configuration file with a local file if needed. As a special case, an empty file (file size 0)
or symlink with the same name pointing to <filename>/dev/null</filename> disables the
configuration file entirely (it is "masked").</para>
<para>In addition to <filename>/etc/systemd/network</filename>, drop-in <literal>.d</literal>
directories can be placed in <filename>/usr/lib/systemd/network</filename> or
<filename>/run/systemd/network</filename> directories. Drop-in files in
- <filename>/etc</filename> take precedence over those in <filename>/run</filename> which in turn
- take precedence over those in <filename>/usr/lib</filename>. Drop-in files under any of these
+ <filename>/etc/</filename> take precedence over those in <filename>/run/</filename> which in turn
+ take precedence over those in <filename>/usr/lib/</filename>. Drop-in files under any of these
directories take precedence over the main netdev file wherever located. (Of course, since
- <filename>/run</filename> is temporary and <filename>/usr/lib</filename> is for vendors, it is
+ <filename>/run/</filename> is temporary and <filename>/usr/lib/</filename> is for vendors, it is
unlikely drop-ins should be used in either of those places.)</para>
</refsect1>
<refsect1>
<title>[MACVTAP] Section Options</title>
- <para>The [MACVTAP] section applies for
- netdevs of kind <literal>macvtap</literal> and accepts the
- same key as [MACVLAN].</para>
+ <para>The [MACVTAP] section applies for netdevs of kind <literal>macvtap</literal> and accepts the same
+ keys as [MACVLAN].</para>
</refsect1>
<refsect1>
<refsect1>
<title>[IPVTAP] Section Options</title>
- <para>The [IPVTAP] section only applies for
- netdevs of kind <literal>ipvtap</literal> and accepts the
- same key as [IPVLAN].</para>
+ <para>The [IPVTAP] section only applies for netdevs of kind <literal>ipvtap</literal> and accepts the
+ same keys as [IPVLAN].</para>
</refsect1>
<refsect1>
<varlistentry>
<term><varname>DestinationPort=</varname></term>
<listitem>
- <para>Configures the default destination UDP port on a per-device basis.
- If destination port is not specified then Linux kernel default will be used.
- Set destination port 4789 to get the IANA assigned value. If not set or if the
- destination port is assigned the empty string the default port of 4789 is used.</para>
+ <para>Configures the default destination UDP port. If the destination port is not specified then
+ Linux kernel default will be used. Set to 4789 to get the IANA assigned value.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PortRange=</varname></term>
<listitem>
- <para>Configures VXLAN port range. VXLAN bases source
- UDP port based on flow to help the receiver to be able
- to load balance based on outer header flow. It
- restricts the port range to the normal UDP local
- ports, and allows overriding via configuration.</para>
+ <para>Configures the source port range for the VXLAN. The kernel assigns the source UDP port based
+ on the flow to help the receiver to do load balancing. When this option is not set, the normal
+ range of local UDP ports is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>IPDoNotFragment=</varname></term>
<listitem>
- <para>Accepts the same key in [VXLAN] section.</para>
+ <para>Accepts the same key as in [VXLAN] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PeerTunnelId=</varname></term>
<listitem>
<para>Specifies the peer tunnel id. Takes a number in the range 1—4294967295. The value used must
- match the <literal>PeerTunnelId=</literal> value being used at the peer. This setting is
- compulsory.</para>
+ match the <literal>TunnelId=</literal> value being used at the peer. This setting is compulsory.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>Port=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecReceiveChannel] section.</para>
+ <para>Accepts the same key as in [MACsecReceiveChannel] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecReceiveChannel] section.</para>
+ <para>Accepts the same key as in [MACsecReceiveChannel] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PacketNumber=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecTransmitAssociation] section.</para>
+ <para>Accepts the same key as in [MACsecTransmitAssociation] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>KeyId=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecTransmitAssociation] section.</para>
+ <para>Accepts the same key as in [MACsecTransmitAssociation] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Key=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecTransmitAssociation] section.</para>
+ <para>Accepts the same key as in [MACsecTransmitAssociation] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>KeyFile=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecTransmitAssociation] section.</para>
+ <para>Accepts the same key as in [MACsecTransmitAssociation] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Activate=</varname></term>
<listitem>
- <para>Accepts the same key in [MACsecTransmitAssociation] section.</para>
+ <para>Accepts the same key as in [MACsecTransmitAssociation] section.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Specifies the encapsulation mechanism used to store networking packets of various protocols
inside the UDP packets. Supports the following values:
- <literal>FooOverUDP</literal> provides the simplest no frills model of UDP encapsulation, it simply
+ <literal>FooOverUDP</literal> provides the simplest no-frills model of UDP encapsulation, it simply
encapsulates packets directly in the UDP payload. <literal>GenericUDPEncapsulation</literal> is a
generic and extensible encapsulation, it allows encapsulation of packets for any IP protocol and
optional data as part of the encapsulation. For more detailed information see <ulink
<varlistentry>
<term><varname>Port=</varname></term>
<listitem>
- <para>Specifies the port number, where the IP encapsulation packets will arrive. Please take note
- that the packets will arrive with the encapsulation will be removed. Then they will be manually fed
- back into the network stack, and sent ahead for delivery to the real destination. This option is
- mandatory.</para>
+ <para>Specifies the port number where the encapsulated packets will arrive. Those packets will be
+ removed and manually fed back into the network stack with the encapsulation removed to be sent to
+ the real destination. This option is mandatory.</para>
</listitem>
</varlistentry>
<varlistentry>
<filename>/run/systemd/network</filename> and the local administration network directory
<filename>/etc/systemd/network</filename>. All configuration files are collectively sorted and processed
in lexical order, regardless of the directories in which they live. However, files with identical
- filenames replace each other. Files in <filename>/etc</filename> have the highest priority, files in
- <filename>/run</filename> take precedence over files with the same name under
- <filename>/usr</filename>. This can be used to override a system-supplied configuration file with a local
+ filenames replace each other. Files in <filename>/etc/</filename> have the highest priority, files in
+ <filename>/run/</filename> take precedence over files with the same name under
+ <filename>/usr/</filename>. This can be used to override a system-supplied configuration file with a local
file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to
<filename>/dev/null</filename> disables the configuration file entirely (it is "masked").</para>
<para>In addition to <filename>/etc/systemd/network</filename>, drop-in <literal>.d</literal>
directories can be placed in <filename>/usr/lib/systemd/network</filename> or
<filename>/run/systemd/network</filename> directories. Drop-in files in
- <filename>/etc</filename> take precedence over those in <filename>/run</filename> which in turn
- take precedence over those in <filename>/usr/lib</filename>. Drop-in files under any of these
+ <filename>/etc/</filename> take precedence over those in <filename>/run/</filename> which in turn
+ take precedence over those in <filename>/usr/lib/</filename>. Drop-in files under any of these
directories take precedence over the main network file wherever located.</para>
<para>Note that an interface without any static IPv6 addresses configured, and neither DHCPv6
</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>IPv6PrefixDelegation=</varname></term>
- <listitem><para>Whether to enable or disable Router Advertisement sending on a link. Allowed
- values are <literal>static</literal> which distributes prefixes as defined in the
- [IPv6PrefixDelegation] and any [IPv6Prefix] sections, <literal>dhcpv6</literal> which requests
- prefixes using a DHCPv6 client configured for another link and any values configured in the
- [IPv6PrefixDelegation] section while ignoring all static prefix configuration sections,
- <literal>yes</literal> which uses both static configuration and DHCPv6, and
- <literal>false</literal> which turns off IPv6 prefix delegation altogether. Defaults to
- <literal>false</literal>. See the [IPv6PrefixDelegation] and the [IPv6Prefix] sections for more
+ <term><varname>IPv6SendRA=</varname></term>
+ <listitem><para>Whether to enable or disable Router Advertisement sending on a link. Takes a
+ boolean value. When enabled, prefixes configured in [IPv6Prefix] sections and routes
+ configured in [IPv6RoutePrefix] sections are distributed as defined in the [IPv6SendRA]
+ section. If <varname>DHCPv6PrefixDelegation=</varname> is enabled, then the delegated
+ prefixes are also distributed. See <varname>DHCPv6PrefixDelegation=</varname> setting and the
+ [IPv6SendRA], [IPv6Prefix], [IPv6RoutePrefix], and [DHCPv6PrefixDelegation] sections for more
configuration options.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DHCPv6PrefixDelegation=</varname></term>
+ <listitem><para>Takes a boolean value. When enabled, requests prefixes using a DHCPv6 client
+ configured on another link. By default, an address within each delegated prefix will be
+ assigned, and the prefixes will be announced through IPv6 Router Advertisement when
+ <varname>IPv6SendRA=</varname> is enabled. Such default settings can be configured in
+ [DHCPv6PrefixDelegation] section.</para></listitem>
+ </varlistentry>
<varlistentry>
<term><varname>IPv6MTUBytes=</varname></term>
<listitem><para>Configures IPv6 maximum transmission unit (MTU).
<varlistentry>
<term><varname>Gateway=</varname></term>
<listitem>
- <para>Takes the gateway address or special value <literal>_dhcp</literal>. If
- <literal>_dhcp</literal>, then the gateway address provided by DHCP (or in the IPv6 case,
- provided by IPv6 RA) is used.</para>
+ <para>Takes the gateway address or the special values <literal>_dhcp4</literal> and
+ <literal>_ipv6ra</literal>. If <literal>_dhcp4</literal> or <literal>_ipv6ra</literal> is
+ set, then the gateway address provided by DHCPv4 or IPv6 RA is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>InitialCongestionWindow=</varname></term>
<listitem>
- <para>The TCP initial congestion window is used during the start of a TCP connection. During the start of a TCP
- session, when a client requests a resource, the server's initial congestion window determines how many data bytes
- will be sent during the initial burst of data. Takes a size in bytes between 1 and 4294967295 (2^32 - 1). The usual
- suffixes K, M, G are supported and are understood to the base of 1024. When unset, the kernel's default will be used.
- </para>
+ <para>The TCP initial congestion window is used during the start of a TCP connection.
+ During the start of a TCP session, when a client requests a resource, the server's initial
+ congestion window determines how many packets will be sent during the initial burst of data
+ without waiting for acknowledgement. Takes a number between 1 and 1023. Note that 100 is
+ considered an extremely large value for this option. When unset, the kernel's default
+ (typically 10) will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>InitialAdvertisedReceiveWindow=</varname></term>
<listitem>
- <para>The TCP initial advertised receive window is the amount of receive data (in bytes) that can initially be buffered at one time
- on a connection. The sending host can send only that amount of data before waiting for an acknowledgment and window update
- from the receiving host. Takes a size in bytes between 1 and 4294967295 (2^32 - 1). The usual suffixes K, M, G are supported
- and are understood to the base of 1024. When unset, the kernel's default will be used.
- </para>
+ <para>The TCP initial advertised receive window is the amount of receive data (in bytes)
+ that can initially be buffered at one time on a connection. The sending host can send only
+ that amount of data before waiting for an acknowledgment and window update from the
+ receiving host. Takes a number between 1 and 1023. Note that 100 is considered an extremely
+ large value for this option. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>MUDURL=</varname></term>
<listitem>
- <para>When configured, the Manufacturer Usage Descriptions (MUD) URL will be sent to the
- DHCPv4 server. Takes an URL of length up to 255 characters. A superficial verification that
- the string is a valid URL will be performed. DHCPv4 clients are intended to have at most one
- MUD URL associated with them. See
- <ulink url="https://tools.ietf.org/html/rfc8520">RFC 8520</ulink>.</para>
+ <para>When configured, the specified Manufacturer Usage Description (MUD) URL will be sent to the
+ DHCPv4 server. Takes a URL of length up to 255 characters. A superficial verification that the
+ string is a valid URL will be performed. DHCPv4 clients are intended to have at most one MUD URL
+ associated with them. See <ulink url="https://tools.ietf.org/html/rfc8520">RFC 8520</ulink>.
+ </para>
+
+ <para>MUD is an embedded software standard defined by the IETF that allows IoT device makers to
+ advertise device specifications, including the intended communication patterns for their device
+ when it connects to the network. The network can then use this to author a context-specific
+ access policy, so the device functions only within those parameters.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MUDURL=</varname></term>
<listitem>
- <para>When configured, the Manufacturer Usage Descriptions (MUD) URL will be sent to the DHCPV6 server.
- Takes an URL of length up to 255 characters. A superficial verification that the string is a valid URL
- will be performed. DHCPv6 clients are intended to have at most one MUD URL associated with them. See
- <ulink url="https://tools.ietf.org/html/rfc8520">RFC 8520</ulink>.</para>
+ <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
+ [DHCPv4] section described above.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RequestOptions=</varname></term>
<listitem>
- <para>When configured, allows to set arbitrary request options in the DHCPv6 request options list and will
- sent to the DHCPV6 server. A whitespace-separated list of integers in the range 1..254. Defaults to unset.</para>
+ <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>
</listitem>
</varlistentry>
<refsect1>
<title>[DHCPv6PrefixDelegation] Section Options</title>
- <para>The [DHCPv6PrefixDelegation] section configures delegated prefix assigned by DHCPv6 server.
- The settings in this section are used only when <varname>IPv6PrefixDelegation=</varname> setting is
- enabled, or set to <literal>dhcp6</literal>.</para>
+ <para>The [DHCPv6PrefixDelegation] section configures delegated prefixes assigned by DHCPv6 server.
+ The settings in this section are used only when <varname>DHCPv6PrefixDelegation=</varname> setting
+ is enabled.</para>
<variablelist class='network-directives'>
<varlistentry>
delegation. You can either set "auto" (the default) or a specific subnet ID (as defined in
<ulink url="https://tools.ietf.org/html/rfc4291#section-2.5.4">RFC 4291</ulink>, section
2.5.4), in which case the allowed value is hexadecimal, from 0 to 0x7fffffffffffffff
- inclusive. This option is only effective when used together with
- <varname>IPv6PrefixDelegation=</varname> and the corresponding configuration on the upstream
- interface.</para>
+ inclusive.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Announce=</varname></term>
+ <listitem>
+ <para>Takes a boolean. When enabled, and <varname>IPv6SendRA=</varname> in [Network] section
+ is enabled, the delegated prefixes are distributed through the IPv6 Router Advertisement.
+ Defaults to yes.</para>
</listitem>
</varlistentry>
<term><varname>Assign=</varname></term>
<listitem>
<para>Takes a boolean. Specifies whether to add an address from the delegated prefixes which
- are received from the WAN interface by the <varname>IPv6PrefixDelegation=</varname>. When
- true (on LAN interfce), the EUI-64 algorithm will be used to form an interface identifier
- from the delegated prefixes. Defaults to true.</para>
+ are received from the WAN interface by the DHCPv6 Prefix Delegation. When true (on LAN
+ interfce), the EUI-64 algorithm will be used by default to form an interface identifier from
+ the delegated prefixes. See also <varname>Token=</varname> setting below. Defaults to yes.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Token=</varname></term>
<listitem>
- <para>Specifies an optional address generation mode for <varname>Assign=</varname>. Takes an
- IPv6 address. When set, the lower bits of the supplied address are combined with the upper
- bits of a delegatad prefix received from the WAN interface by the
- <varname>IPv6PrefixDelegation=</varname> prefixes to form a complete address.</para>
+ <para>Specifies an optional address generation mode for assigning an address in each
+ delegated prefix. Takes an IPv6 address. When set, the lower bits of the supplied address is
+ combined with the upper bits of each delegatad prefix received from the WAN interface by the
+ DHCPv6 Prefix Delegation to form a complete address. When <varname>Assign=</varname> is
+ disabled, this setting is ignored. When unset, the EUI-64 algorithm will be used to form
+ addresses. Defaults to unset.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>UseOnLinkPrefix=</varname></term>
<listitem>
- <para>When true (the default), the onlink prefix received in the Router Advertisement will be used and take
- precedence over any statically configured ones.</para>
+ <para>When true (the default), the onlink prefix received in the Router Advertisement will be
+ used and takes precedence over any statically configured ones.</para>
</listitem>
</varlistentry>
</refsect1>
<refsect1>
- <title>[IPv6PrefixDelegation] Section Options</title>
- <para>The [IPv6PrefixDelegation] section contains settings for sending IPv6 Router Advertisements and
- whether to act as a router, if enabled via the <varname>IPv6PrefixDelegation=</varname> option described
- above. IPv6 network prefixes are defined with one or more [IPv6Prefix] sections.</para>
+ <title>[IPv6SendRA] Section Options</title>
+ <para>The [IPv6SendRA] section contains settings for sending IPv6 Router Advertisements and whether
+ to act as a router, if enabled via the <varname>IPv6SendRA=</varname> option described above. IPv6
+ network prefixes or routes are defined with one or more [IPv6Prefix] or [IPv6RoutePrefix] sections.
+ </para>
<variablelist class='network-directives'>
<refsect1>
<title>[LLDP] Section Options</title>
<para>The [LLDP] section manages the Link Layer Discovery Protocol (LLDP) and accepts the following
- keys.</para>
+ keys:</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>MUDURL=</varname></term>
<listitem>
- <para>Controls support for Ethernet LLDP packet's Manufacturer Usage Description (MUD). MUD is an embedded software
- standard defined by the IETF that allows IoT Device makers to advertise device specifications, including the intended
- communication patterns for their device when it connects to the network. The network can then use this intent to author
- a context-specific access policy, so the device functions only within those parameters. Takes an URL of length up to 255
- characters. A superficial verification that the string is a valid URL
- will be performed. See
- <ulink url="https://tools.ietf.org/html/rfc8520">RFC 8520</ulink> for details. The MUD URL received
- from the LLDP packets will be saved at the state files and can be read via
+ <para>When configured, the specified Manufacturer Usage Descriptions (MUD) URL will be sent in
+ LLDP packets. The syntax and semantics are the same as for <varname>MUDURL=</varname> in the
+ [DHCPv4] section described above.</para>
+
+ <para>The MUD URLs received via LLDP packets are saved and can be read using the
<function>sd_lldp_neighbor_get_mud_url()</function> function.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>LimitBytes=</varname></term>
<listitem>
- <para>Specifies the hard limit on the FIFO size in bytes. 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. When suffixed with K, M, or G, the specified
- size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults
- to unset and kernel's default is used.</para>
+ <para>Specifies the hard limit in bytes on the FIFO buffer size. 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. When suffixed with K, M, or G, the specified size is parsed
+ as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults to unset and
+ kernel default is used.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>PriorityMap=</varname></term>
<listitem>
- <para>The priority map maps the priority of a packet to a band. The argument is a white-space
- 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 0..255. This setting can be
- specified multiple times. If an empty string is assigned, then the all previous assignments
- are cleared.</para>
+ <para>The priority map maps the priority of a packet to a band. The argument is a whitespace
+ 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
+ times. If an empty string is assigned, then the all previous assignments are cleared.</para>
</listitem>
</varlistentry>
</variablelist>
Name=enp2s0
[Network]
-IPv6PrefixDelegation=dhcpv6</programlisting>
+IPv6SendRA=yes
+DHCPv6PrefixDelegation=yes</programlisting>
- <para>This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the
- DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.</para>
+ <para>This will enable DHCPv6-PD on the interface enp1s0 as an upstream interface where the
+ DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.
+ The delegated prefixes are distributed by IPv6 Router Advertisement on the downstream network.
+ </para>
</example>
<example>
created that points to <filename index="false">/var/lib/system-update</filename> (or
wherever the directory with the upgrade files is located) and the system is rebooted. This
symlink is in the root directory, since we need to check for it very early at boot, at a
- time where <filename>/var</filename> is not available yet.</para>
+ time where <filename>/var/</filename> is not available yet.</para>
</listitem>
<listitem>
script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds
you should trigger the reboot in your own code, for example by invoking logind's
<command>Reboot()</command> call or calling <command>systemctl reboot</command>. See
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/logind">logind dbus API</ulink>
- for details.</para>
+ <citerefentry><refentrytitle>org.freedesktop.login1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details about the logind D-Bus API.</para>
</listitem>
<listitem>
<xi:include href="supported-controllers.xml" xpointer="controllers-text" />
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>ManagedOOMSwap=auto|kill</varname></term>
+ <term><varname>ManagedOOMMemoryPressure=auto|kill</varname></term>
+
+ <listitem>
+ <para>Specifies how
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ will act on this unit's cgroups. Defaults to <option>auto</option>.</para>
+
+ <para>When set to <option>kill</option>, <command>systemd-oomd</command> will actively monitor this unit's
+ cgroup metrics to decide whether it needs to act. If the cgroup passes the limits set by
+ <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> or its
+ overrides, <command>systemd-oomd</command> will send a <constant>SIGKILL</constant> to all of the processes
+ under the chosen candidate cgroup. Note that only descendant cgroups can be eligible candidates for killing;
+ the unit that set its property to <option>kill</option> is not a candidate (unless one of its ancestors set
+ their property to <option>kill</option>). You can find more details on candidates and kill behavior at
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ and <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Setting
+ either of these properties to <option>kill</option> will also automatically acquire
+ <varname>After=</varname> and <varname>Wants=</varname> dependencies on
+ <filename>systemd-oomd.service</filename> unless <varname>DefaultDependencies=no</varname>.
+ </para>
+
+ <para>When set to <option>auto</option>, <command>systemd-oomd</command> will not actively use this cgroup's
+ data for monitoring and detection. However, if an ancestor cgroup has one of these properties set to
+ <option>kill</option>, a unit with <option>auto</option> can still be an eligible candidate for
+ <command>systemd-oomd</command> to act on.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ManagedOOMMemoryPressureLimitPercent=</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>.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
The documentation for control groups and specific controllers in the Linux kernel:
<ulink url="https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html">Control Groups v2</ulink>.
</para>
has <varname>RemainAfterExit=</varname> not set) it will not show up as started afterwards, but
as dead.</para></listitem>
- <listitem><para>Behavior of <option>dbus</option> is similar to <option>simple</option>; however, it is
- expected that the service acquires a name on the D-Bus bus, as configured by
- <varname>BusName=</varname>. systemd will proceed with starting follow-up units after the D-Bus bus name
- has been acquired. Service units with this option configured implicitly gain dependencies on the
- <filename>dbus.socket</filename> unit. This type is the default if <varname>BusName=</varname> is
- specified.</para></listitem>
+ <listitem><para>Behavior of <option>dbus</option> is similar to <option>simple</option>; however,
+ it is expected that the service acquires a name on the D-Bus bus, as configured by
+ <varname>BusName=</varname>. systemd will proceed with starting follow-up units after the D-Bus
+ bus name has been acquired. Service units with this option configured implicitly gain
+ dependencies on the <filename>dbus.socket</filename> unit. This type is the default if
+ <varname>BusName=</varname> is specified. A service unit of this type is considered to be in the
+ activating state until the specified bus name is acquired. It is considered activated while the
+ bus name is taken. Once the bus name is released the service is considered being no longer
+ functional which has the effect that the service manager attempts to terminate any remaining
+ processes belonging to the service. Services that drop their bus name as part of their shutdown
+ logic thus should be prepared to receive a <constant>SIGTERM</constant> (or whichever signal is
+ configured in <varname>KillSignal=</varname>) as result.</para></listitem>
<listitem><para>Behavior of <option>notify</option> is similar to <option>exec</option>; however, it is
expected that the service sends a notification message via
<literal>FDSTORE=1</literal> messages. This is useful for implementing services that can restart
after an explicit request or a crash without losing state. Any open sockets and other file
descriptors which should not be closed during the restart may be stored this way. Application state
- can either be serialized to a file in <filename>/run</filename>, or better, stored in a
+ can either be serialized to a file in <filename>/run/</filename>, or better, stored in a
<citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
memory file descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service
manager. All file descriptors passed to the service manager from a specific service are passed back
into words, and afterwards removed.</para>
<para>If the command is not a full (absolute) path, it will be resolved to a full path using a
- fixed search path determinted at compilation time. Searched directories include
+ fixed search path determined at compilation time. Searched directories include
<filename>/usr/local/bin/</filename>, <filename>/usr/bin/</filename>, <filename>/bin/</filename>
on systems using split <filename>/usr/bin/</filename> and <filename>/bin/</filename>
directories, and their <filename>sbin/</filename> counterparts on systems using split
<title>Simple service</title>
<para>The following unit file creates a service that will
- execute <filename>/usr/sbin/foo-daemon</filename>. Since no
+ execute <filename index="false">/usr/sbin/foo-daemon</filename>. Since no
<varname>Type=</varname> is specified, the default
<varname>Type=</varname><option>simple</option> will be assumed.
systemd will assume the unit to be started immediately after the
argument. Behavior otherwise is very similar to the
<varname>ListenFIFO=</varname> directive above. Use this to
open character device nodes as well as special files in
- <filename>/proc</filename> and
- <filename>/sys</filename>.</para></listitem>
+ <filename>/proc/</filename> and
+ <filename>/sys/</filename>.</para></listitem>
</varlistentry>
<varlistentry>
url="https://www.kernel.org/doc/Documentation/usb/functionfs.txt">USB
FunctionFS</ulink> endpoints location to listen on, for
implementation of USB gadget functions. This expects an
- absolute file system path of FunctionFS mount point as the argument.
+ absolute file system path of a FunctionFS mount point as the argument.
Behavior otherwise is very similar to the <varname>ListenFIFO=</varname>
directive above. Use this to open the FunctionFS endpoint
<filename>ep0</filename>. When using this option, the
<filename>emergency.target</filename>,
<filename>exit.target</filename>,
<filename>final.target</filename>,
+ <filename>first-boot-complete.target</filename>,
<filename>getty.target</filename>,
<filename>getty-pre.target</filename>,
<filename>graphical.target</filename>,
<filename>hybrid-sleep.target</filename>,
<filename>suspend-then-hibernate.target</filename>,
<filename>initrd.target</filename>,
+ <filename>initrd-cryptsetup.target</filename>,
<filename>initrd-fs.target</filename>,
<filename>initrd-root-device.target</filename>,
<filename>initrd-root-fs.target</filename>,
<varname>DefaultDependencies=no</varname>).</para>
<para>Usually, this should pull-in all local mount points plus
- <filename>/var</filename>, <filename>/tmp</filename> and
- <filename>/var/tmp</filename>, swap devices, sockets, timers,
+ <filename>/var/</filename>, <filename>/tmp/</filename> and
+ <filename>/var/tmp/</filename>, swap devices, sockets, timers,
path units and other basic initialization necessary for general
purpose daemons. The mentioned mount points are special cased
to allow them to be remote.
<varlistentry>
<term><filename>cryptsetup.target</filename></term>
<listitem>
- <para>A target that pulls in setup services for all
- encrypted block devices.</para>
+ <para>A target that pulls in setup services for local encrypted block devices.
+ See <filename>remote-cryptsetup.target</filename> below for the equivalent target for remote
+ volumes, and <filename>initrd-cryptsetup.target</filename> below for the equivalent target in the
+ initrd.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><filename>initrd.target</filename></term>
<listitem>
- <para>This is the default target in the initramfs, similar to <filename>default.target</filename>
+ <para>This is the default target in the initrd, similar to <filename>default.target</filename>
in the main system. It is used to mount the real root and transition to it. See
<citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
more discussion.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><filename>initrd-cryptsetup.target</filename></term>
+ <listitem>
+ <para>A target that pulls in setup services for all encrypted block devices. See
+ <filename>cryptsetup.target</filename> and <filename>remote-cryptsetup.target</filename> for the
+ equivalent targets in the real root.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><filename>initrd-fs.target</filename></term>
<listitem>
<para>Similar to <filename>cryptsetup.target</filename>, but for encrypted
devices which are accessed over the network. It is used for
<citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- entries marked with <option>_netdev</option>.</para>
+ entries marked with <option>_netdev</option>.
+ See <filename>cryptsetup.target</filename> for the equivalent target for local volumes, and
+ <filename>initrd-cryptsetup.target</filename> for the equivalent target in the initrd.</para>
</listitem>
</varlistentry>
<varlistentry>
pulled in via a <option>Wants=</option> dependency of the storage daemon and thus generally not be
part of any transaction unless a storage daemon is used. The instance name for instances of this
template unit must be a properly escaped block device node path, e.g.
- <filename>blockdev@dev-mapper-foobar.target</filename> for the storage device
- <filename>/dev/mapper/foobar</filename>.</para></listitem>
+ <filename index="false">blockdev@dev-mapper-foobar.target</filename> for the storage device
+ <filename index="false">/dev/mapper/foobar</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>cryptsetup-pre.target</filename></term>
stopped.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><filename>first-boot-complete.target</filename></term>
+ <listitem>
+ <para>This passive target is intended as a synchronization point for units that need to run once
+ during the first boot. Only after all units ordered before this target have finished, will the
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ be committed to disk, marking the first boot as completed. If the boot is aborted at any time
+ before that, the next boot will re-run any units with <varname>ConditionFirstBoot=yes</varname>.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><filename>getty-pre.target</filename></term>
<listitem>
<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>.
+ dependency on <literal>xdg-desktop-autostart.target</literal>.</para>
</listitem>
</varlistentry>
</variablelist>
<filename>$XDG_RUNTIME_DIR/systemd/user.control/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/transient/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/generator.early/*</filename>
-<filename>~/.config/systemd/user/*</filename>
+<filename>$XDG_CONFIG_HOME/systemd/user/*</filename>
+<filename>$XDG_CONFIG_DIRS/systemd/user/*</filename>
<filename>/etc/systemd/user/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/user/*</filename>
<filename>/run/systemd/user/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/generator/*</filename>
-<filename>~/.local/share/systemd/user/*</filename>
+<filename>$XDG_DATA_HOME/systemd/user/*</filename>
+<filename>$XDG_DATA_DIRS/systemd/user/*</filename>
<filename index='false'>…</filename>
<filename>/usr/lib/systemd/user/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/generator.late/*</filename></literallayout></para>
<para>In addition to <filename>/etc/systemd/system</filename>, the drop-in <literal>.d/</literal>
directories for system services can be placed in <filename>/usr/lib/systemd/system</filename> or
- <filename>/run/systemd/system</filename> directories. Drop-in files in <filename>/etc</filename>
- take precedence over those in <filename>/run</filename> which in turn take precedence over those
- in <filename>/usr/lib</filename>. Drop-in files under any of these directories take precedence
+ <filename>/run/systemd/system</filename> directories. Drop-in files in <filename>/etc/</filename>
+ take precedence over those in <filename>/run/</filename> which in turn take precedence over those
+ in <filename>/usr/lib/</filename>. Drop-in files under any of these directories take precedence
over unit files wherever located. Multiple drop-in files with different names are applied in
lexicographic order, regardless of which of the directories they reside in.</para>
start it even manually.</para>
<para>The unit file format is covered by the
- <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise">Interface
- Stability Promise</ulink>.</para>
+ <ulink url="https://systemd.io/PORTABILITY_AND_STABILITY/">Interface
+ Portability and Stability Promise</ulink>.</para>
</refsect1>
<para>When the input qualifies as absolute file system path, this algorithm is extended slightly: the path to the
root directory <literal>/</literal> is encoded as single dash <literal>-</literal>. In addition, any leading,
trailing or duplicate <literal>/</literal> characters are removed from the string before transformation. Example:
- <filename>/foo//bar/baz/</filename> becomes <literal>foo-bar-baz</literal>.</para>
+ <filename index="false">/foo//bar/baz/</filename> becomes <literal>foo-bar-baz</literal>.</para>
<para>This escaping is fully reversible, as long as it is known whether the escaped string was a path (the
unescaping results are different for paths and non-path strings). The
<entry><filename>$XDG_CONFIG_HOME/systemd/user</filename> or <filename>$HOME/.config/systemd/user</filename></entry>
<entry>User configuration (<varname>$XDG_CONFIG_HOME</varname> is used if set, <filename>~/.config</filename> otherwise)</entry>
</row>
+ <row>
+ <entry><filename>$XDG_CONFIG_DIRS/systemd/user</filename> or <filename>/etc/xdg/systemd/user</filename></entry>
+ <entry>Additional configuration directories as specified by the XDG base directory specification (<varname>$XDG_CONFIG_DIRS</varname> is used if set, <filename>/etc/xdg</filename> otherwise)</entry>
+ </row>
<row>
<entry><filename>/etc/systemd/user</filename></entry>
<entry>User units created by the administrator</entry>
<entry><filename>$XDG_DATA_HOME/systemd/user</filename> or <filename>$HOME/.local/share/systemd/user</filename></entry>
<entry>Units of packages that have been installed in the home directory (<varname>$XDG_DATA_HOME</varname> is used if set, <filename>~/.local/share</filename> otherwise)</entry>
</row>
+ <row>
+ <entry><filename>$XDG_DATA_DIRS/systemd/user</filename> or <filename>/usr/local/share/systemd/user</filename> and <filename>/usr/share/systemd/user</filename></entry>
+ <entry>Additional data directories as specified by the XDG base directory specification (<varname>$XDG_DATA_DIRS</varname> is used if set, <filename>/usr/local/share</filename> and <filename>/usr/share</filename> otherwise)</entry>
+ </row>
<row>
<entry><filename>$dir/systemd/user</filename> for each <varname index="false">$dir</varname> in <varname>$XDG_DATA_DIRS</varname></entry>
<entry>Additional locations for installed user units, one for each entry in <varname>$XDG_DATA_DIRS</varname></entry>
<varname>PrivateTmp=</varname> directives (see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details). If a unit that has this setting set is started, its processes will see the same
- <filename>/tmp</filename>, <filename>/var/tmp</filename> and network namespace as one listed unit
+ <filename>/tmp/</filename>, <filename>/var/tmp/</filename> and network namespace as one listed unit
that is started. If multiple listed units are already started, it is not defined which namespace is
- joined. Note that this setting only has an effect if
+ joined. Note that this setting only has an effect if
<varname>PrivateNetwork=</varname>/<varname>NetworkNamespacePath=</varname> and/or
<varname>PrivateTmp=</varname> is enabled for both the unit that joins the namespace and the unit
whose namespace is joined.</para></listitem>
<literal>vmware</literal>,
<literal>microsoft</literal>,
<literal>oracle</literal>,
+ <literal>powervm</literal>,
<literal>xen</literal>,
<literal>bochs</literal>,
<literal>uml</literal>,
argument must either be a single word, or an assignment (i.e. two words, separated by
<literal>=</literal>). In the former case the kernel command line is searched for the word
appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is
- looked for with right and left hand side matching.</para>
+ looked for with right and left hand side matching. This operates on the kernel command line
+ communicated to userspace via <filename>/proc/cmdline</filename>, except when the service manager
+ is invoked as payload of a container manager, in which case the command line of <filename>PID
+ 1</filename> is used instead (i.e. <filename>/proc/1/cmdline</filename>).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ConditionNeedsUpdate=</varname></term>
- <listitem><para>Takes one of <filename>/var</filename> or <filename>/etc</filename> as argument,
+ <listitem><para>Takes one of <filename>/var/</filename> or <filename>/etc/</filename> as argument,
possibly prefixed with a <literal>!</literal> (to invert the condition). This condition may be
used to conditionalize units on whether the specified directory requires an update because
- <filename>/usr</filename>'s modification time is newer than the stamp file
+ <filename>/usr/</filename>'s modification time is newer than the stamp file
<filename>.updated</filename> in the specified directory. This is useful to implement offline
- updates of the vendor operating system resources in <filename>/usr</filename> that require updating
- of <filename>/etc</filename> or <filename>/var</filename> on the next following boot. Units making
+ updates of the vendor operating system resources in <filename>/usr/</filename> that require updating
+ of <filename>/etc/</filename> or <filename>/var/</filename> on the next following boot. Units making
use of this condition should order themselves before
<citerefentry><refentrytitle>systemd-update-done.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
to make sure they run before the stamp file's modification time gets reset indicating a completed
<term><varname>ConditionFirstBoot=</varname></term>
<listitem><para>Takes a boolean argument. This condition may be used to conditionalize units on
- whether the system is booting up with an unpopulated <filename>/etc</filename> directory
- (specifically: an <filename>/etc</filename> with no <filename>/etc/machine-id</filename>). This may
- be used to populate <filename>/etc</filename> on the first boot after factory reset, or when a new
- system instance boots up for the first time.</para>
+ whether the system is booting up for the first time. This roughly means that <filename>/etc/</filename>
+ is unpopulated (for details, see "First Boot Semantics" in
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
+ This may be used to populate <filename>/etc/</filename> on the first boot after factory reset, or
+ when a new system instance boots up for the first time.</para>
+
+ <para>For robustness, units with <varname>ConditionFirstBoot=yes</varname> should order themselves
+ before <filename>first-boot-complete.target</filename> and pull in this passive target with
+ <varname>Wants=</varname>. This ensures that in a case of an aborted first boot, these units will
+ be re-run during the next system startup.</para>
<para>If the <varname>systemd.condition-first-boot=</varname> option is specified on the kernel
command line (taking a boolean), it will override the result of this condition check, taking
<row>
<entry><literal>%E</literal></entry>
<entry>Configuration directory root</entry>
- <entry>This is either <filename>/etc</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to (for user managers).</entry>
+ <entry>This is either <filename>/etc/</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to (for user managers).</entry>
</row>
<row>
<entry><literal>%f</literal></entry>
<row>
<entry><literal>%t</literal></entry>
<entry>Runtime directory root</entry>
- <entry>This is either <filename>/run</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
- </row>
- <row>
- <entry><literal>%T</literal></entry>
- <entry>Directory for temporary files</entry>
- <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
+ <entry>This is either <filename>/run/</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
</row>
+ <xi:include href="standard-specifiers.xml" xpointer="T"/>
<row>
<entry><literal>%g</literal></entry>
<entry>User group</entry>
Note that this setting is <emphasis>not</emphasis> influenced by the <varname>User=</varname> setting configurable in the [Service] section of the service unit.</entry>
</row>
<xi:include href="standard-specifiers.xml" xpointer="v"/>
- <row>
- <entry><literal>%V</literal></entry>
- <entry>Directory for larger and persistent temporary files</entry>
- <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
- </row>
+ <xi:include href="standard-specifiers.xml" xpointer="V"/>
<xi:include href="standard-specifiers.xml" xpointer="w"/>
<xi:include href="standard-specifiers.xml" xpointer="W"/>
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
<para>After running <command>systemctl enable</command>, a
symlink
- <filename>/etc/systemd/system/multi-user.target.wants/foo.service</filename>
+ <filename index="false">/etc/systemd/system/multi-user.target.wants/foo.service</filename>
linking to the actual unit will be created. It tells systemd to
pull in the unit when starting
<filename>multi-user.target</filename>. The inverse
that need to be executed as part of the boot process. For example,
it sets the hostname or configures the loopback network device. It
also sets up and mounts various API file systems, such as
- <filename>/sys</filename> or <filename>/proc</filename>.</para>
+ <filename>/sys/</filename> or <filename>/proc/</filename>.</para>
<para>For more information about the concepts and
ideas behind systemd, please refer to the
<ulink url="http://0pointer.de/blog/projects/systemd.html">Original Design Document</ulink>.</para>
- <para>Note that some but not all interfaces provided
- by systemd are covered by the
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise">Interface
- Stability Promise</ulink>.</para>
+ <para>Note that some but not all interfaces provided by systemd are covered by the
+ <ulink url="https://systemd.io/PORTABILITY_AND_STABILITY/">Interface Portability and Stability Promise</ulink>.</para>
<para>Units may be generated dynamically at boot and system
manager reload time, for example based on other configuration
</para>
<para>Systems which invoke systemd in a container or initrd environment should implement the <ulink
- url="https://systemd.io/CONTAINER_INTERFACE">Container Interface</ulink> or <ulink
- url="https://www.freedesktop.org/wiki/Software/systemd/InitrdInterface">initrd Interface</ulink>
+ url="https://systemd.io/CONTAINER_INTERFACE">Container Interface</ulink> or
+ <ulink url="https://systemd.io/INITRD_INTERFACE/">initrd Interface</ulink>
specifications, respectively.</para>
</refsect1>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$SYSTEMD_LOG_COLOR</varname></term>
- <listitem><para>Controls whether systemd highlights important
- log messages. This can be overridden with
- <option>--log-color</option>.</para></listitem>
+ <listitem><para>Controls whether systemd highlights important log messages. This can be overridden
+ with <option>--log-color=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$SYSTEMD_LOG_LEVEL</varname></term>
- <listitem><para>systemd reads the log level from this
- environment variable. This can be overridden with
- <option>--log-level=</option>.</para></listitem>
+ <listitem><para>systemd reads the log level from this environment variable. This can be overridden
+ with <option>--log-level=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$SYSTEMD_LOG_LOCATION</varname></term>
- <listitem><para>Controls whether systemd prints the code
- location along with log messages. This can be overridden with
- <option>--log-location</option>.</para></listitem>
+ <listitem><para>Controls whether systemd prints the code location along with log messages. This can
+ be overridden with <option>--log-location=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$SYSTEMD_LOG_TARGET</varname></term>
- <listitem><para>systemd reads the log target from this
- environment variable. This can be overridden with
- <option>--log-target=</option>.</para></listitem>
+ <listitem><para>systemd reads the log target from this environment variable. This can be overridden
+ with <option>--log-target=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$SYSTEMD_LOG_TIME</varname></term>
- <listitem><para>Controls whether systemd prefixes log
- messages with the current time. This can be overridden with
- <option>--log-time=</option>.</para></listitem>
+ <listitem><para>Controls whether systemd prefixes log messages with the current time. This can be
+ overridden with <option>--log-time=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_LOG_TID</varname></term>
+ <listitem><para>Controls whether systemd prefixes log messages with the current thread ID
+ (TID).</para></listitem>
</varlistentry>
<varlistentry>
<para>These variables may contain a list of paths, separated by colons
(<literal>:</literal>). When set, if the list ends with an empty
component (<literal>...:</literal>), this list is prepended to the
- usual set of of paths. Otherwise, the specified list replaces the usual
+ usual set of paths. Otherwise, the specified list replaces the usual
set of paths.
</para></listitem>
</varlistentry>
<xi:include href="less-variables.xml" xpointer="pager"/>
<xi:include href="less-variables.xml" xpointer="less"/>
<xi:include href="less-variables.xml" xpointer="lesscharset"/>
+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
<xi:include href="less-variables.xml" xpointer="colors"/>
<xi:include href="less-variables.xml" xpointer="urlify"/>
<term><varname>systemd.log_location</varname></term>
<term><varname>systemd.log_target=</varname></term>
<term><varname>systemd.log_time</varname></term>
+ <term><varname>systemd.log_tid</varname></term>
<listitem><para>Controls log output, with the same effect as the
- <varname>$SYSTEMD_LOG_COLOR</varname>,
- <varname>$SYSTEMD_LOG_LEVEL</varname>,
- <varname>$SYSTEMD_LOG_LOCATION</varname>,
- <varname>$SYSTEMD_LOG_TARGET</varname>,
- <varname>$SYSTEMD_LOG_TIME</varname>, environment variables described above.
- <varname>systemd.log_color</varname>, <varname>systemd.log_location</varname>, and
- <varname>systemd.log_time</varname> can be specified without an argument, with the
- same effect as a positive boolean.</para></listitem>
+ <varname>$SYSTEMD_LOG_COLOR</varname>, <varname>$SYSTEMD_LOG_LEVEL</varname>,
+ <varname>$SYSTEMD_LOG_LOCATION</varname>, <varname>$SYSTEMD_LOG_TARGET</varname>,
+ <varname>$SYSTEMD_LOG_TIME</varname>, and <varname>$SYSTEMD_LOG_TID</varname> environment variables
+ described above. <varname>systemd.log_color</varname>, <varname>systemd.log_location</varname>,
+ <varname>systemd.log_time</varname>, and <varname>systemd.log_tid=</varname> can be specified without
+ an argument, with the same effect as a positive boolean.</para></listitem>
</varlistentry>
<varlistentry>
<para>Those options correspond directly to options listed above in "Kernel Command Line". Both forms
may be used equivalently for the system manager, but it is recommended to use the forms listed above in
this context, because they are properly namespaced. When an option is specified both on the kernel
- command line, and as a normal command line argument, the latter has higher precedence.</para>
+ command line and as a normal command line argument, the latter has higher precedence.</para>
<para>When <command>systemd</command> is used as a user manager, the kernel command line is ignored and
- the options described are understood. Nevertheless, <command>systemd</command> is usually started in
- this mode through the
+ only the options described below are understood. Nevertheless, <command>systemd</command> is usually
+ started in this mode through the
<citerefentry><refentrytitle>user@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
service, which is shared between all users, and it may be more convenient to use configuration files to
- modify settings, see
- <citerefentry><refentrytitle>systemd-user.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- or a drop-in that specifies one of the environment variables listed above in the Environment section,
- see
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ modify settings (see
+ <citerefentry><refentrytitle>systemd-user.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
+ or a drop-in that specifies one of the environment variables listed above in the Environment section
+ (see the discussion of <varname>Environment=</varname> and <varname>EnvironmentFile=</varname> in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</para>
<variablelist>
<varlistentry>
<xi:include href="standard-specifiers.xml" xpointer="l"/>
<xi:include href="standard-specifiers.xml" xpointer="m"/>
<xi:include href="standard-specifiers.xml" xpointer="o"/>
- <row>
- <entry><literal>%T</literal></entry>
- <entry>Directory for temporary files</entry>
- <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
- </row>
+ <xi:include href="standard-specifiers.xml" xpointer="T"/>
<xi:include href="standard-specifiers.xml" xpointer="v"/>
- <row>
- <entry><literal>%V</literal></entry>
- <entry>Directory for larger and persistent temporary files</entry>
- <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
- </row>
+ <xi:include href="standard-specifiers.xml" xpointer="V"/>
<xi:include href="standard-specifiers.xml" xpointer="w"/>
<xi:include href="standard-specifiers.xml" xpointer="W"/>
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
<emphasis>creation</emphasis> of regular files, directories, pipes, and device nodes, adjustments to
their <emphasis>access mode, ownership, attributes, quota assignments, and contents</emphasis>, and
finally their time-based <emphasis>removal</emphasis>. It is mostly commonly used for volatile and
- temporary files and directories (such as those located under <filename>/run</filename>,
- <filename>/tmp</filename>, <filename>/var/tmp</filename>, the API file systems such as
- <filename>/sys</filename> or <filename>/proc</filename>, as well as some other directories below
- <filename>/var</filename>).</para>
+ temporary files and directories (such as those located under <filename>/run/</filename>,
+ <filename>/tmp/</filename>, <filename>/var/tmp/</filename>, the API file systems such as
+ <filename>/sys/</filename> or <filename>/proc/</filename>, as well as some other directories below
+ <filename>/var/</filename>).</para>
<para><command>systemd-tmpfiles</command> uses this configuration to create volatile files and
directories during boot and to do periodic cleanup afterwards. See
<citerefentry><refentrytitle>systemd-tmpfiles</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
the description of <filename>systemd-tmpfiles-setup.service</filename>,
- <filename>systemd-tmpfiles-cleanup.service</filename>, and associated units.</para>
+ <filename>systemd-tmpfiles-clean.service</filename>, and associated units.</para>
- <para>System daemons frequently require private runtime directories below <filename>/run</filename> to
+ <para>System daemons frequently require private runtime directories below <filename>/run/</filename> to
store communication sockets and similar. For these, it is better to use
<varname>RuntimeDirectory=</varname> in their unit files (see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
<para>It is recommended to use <varname>Q</varname> for subvolumes that typically contain further subvolumes,
and where it is desirable to have accounting and quota limits on all child subvolumes together. Examples for
- <varname>Q</varname> are typically <filename>/home</filename> or <filename>/var/lib/machines</filename>. In
+ <varname>Q</varname> are typically <filename>/home/</filename> or <filename>/var/lib/machines/</filename>. In
contrast, <varname>q</varname> should be used for subvolumes that either usually do not include further
subvolumes or where no accounting and quota limits are needed that apply to all child subvolumes
- together. Examples for <varname>q</varname> are typically <filename>/var</filename> or
- <filename>/var/tmp</filename>. </para>
+ together. Examples for <varname>q</varname> are typically <filename>/var/</filename> or
+ <filename>/var/tmp/</filename>. </para>
<para>As with <varname>q</varname>, <varname>Q</varname> has no effect on the quota group hierarchy if the
subvolume already exists, regardless of whether the subvolume already belong to a quota group or not.
<row>
<entry><literal>%t</literal></entry>
<entry>System or user runtime directory</entry>
- <entry>In <option>--user</option> mode, this is the same <varname>$XDG_RUNTIME_DIR</varname>, and <filename>/run</filename> otherwise.</entry>
- </row>
- <row>
- <entry><literal>%T</literal></entry>
- <entry>Directory for temporary files</entry>
- <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
+ <entry>In <option>--user</option> mode, this is the same <varname>$XDG_RUNTIME_DIR</varname>, and <filename>/run/</filename> otherwise.</entry>
</row>
+ <xi:include href="standard-specifiers.xml" xpointer="T"/>
<row>
<entry><literal>%g</literal></entry>
<entry>User group</entry>
<entry>This is the numeric UID of the user running the command. In case of the system instance this resolves to <constant>0</constant>.</entry>
</row>
<xi:include href="standard-specifiers.xml" xpointer="v"/>
- <row>
- <entry><literal>%V</literal></entry>
- <entry>Directory for larger and persistent temporary files</entry>
- <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
- </row>
+ <xi:include href="standard-specifiers.xml" xpointer="V"/>
<xi:include href="standard-specifiers.xml" xpointer="w"/>
<xi:include href="standard-specifiers.xml" xpointer="W"/>
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
<term><varname>resolve_names=</varname></term>
<listitem>
- <para>Specifes when systemd-udevd should resolve names of users and groups. When set to
+ <para>Specifies when systemd-udevd should resolve names of users and groups. When set to
<option>early</option> (the default), names will be resolved when the rules are parsed.
When set to <option>late</option>, names will be resolved for every event. When set to
<option>never</option>, names will never be resolved and all devices will be owned by
<refsect1><title>Description</title>
<para>udev supplies the system software with device events, manages permissions
- of device nodes and may create additional symlinks in the <filename>/dev</filename>
+ of device nodes and may create additional symlinks in the <filename>/dev/</filename>
directory, or renames network interfaces. The kernel usually just assigns unpredictable
device names based on the order of discovery. Meaningful symlinks or network device
names provide a way to reliably identify devices based on their properties or
volatile runtime directory <filename>/run/udev/rules.d</filename> and the local administration
directory <filename>/etc/udev/rules.d</filename>. All rules files are collectively sorted and
processed in lexical order, regardless of the directories in which they live. However, files with
- identical filenames replace each other. Files in <filename>/etc</filename> have the highest priority,
- files in <filename>/run</filename> take precedence over files with the same name under
- <filename>/usr</filename>. This can be used to override a system-supplied rules file with a local
- file if needed; a symlink in <filename>/etc</filename> with the same name as a rules file in
- <filename>/usr/lib</filename>, pointing to <filename>/dev/null</filename>, disables the rules file
+ identical filenames replace each other. Files in <filename>/etc/</filename> have the highest priority,
+ files in <filename>/run/</filename> take precedence over files with the same name under
+ <filename>/usr/</filename>. This can be used to override a system-supplied rules file with a local
+ file if needed; a symlink in <filename>/etc/</filename> with the same name as a rules file in
+ <filename>/usr/lib/</filename>, pointing to <filename>/dev/null</filename>, disables the rules file
entirely. Rule files must have the extension <filename>.rules</filename>; other extensions are
ignored.</para>
<function>udev_device_new_from_subsystem_sysname</function>, and
<function>udev_device_new_from_device_id</function>
create the device object based on information found in
- <filename>/sys</filename>, annotated with properties from the udev-internal
- device database. A syspath is any subdirectory of <filename>/sys</filename>,
+ <filename>/sys/</filename>, annotated with properties from the udev-internal
+ device database. A syspath is any subdirectory of <filename>/sys/</filename>,
with the restriction that a subdirectory of <filename>/sys/devices</filename>
(or a symlink to one) represents a real device and as such must contain
a <filename>uevent</filename> file. <function>udev_device_new_from_devnum</function>
<term><option>-p</option></term>
<term><option>--path=<replaceable>DEVPATH</replaceable></option></term>
<listitem>
- <para>The <filename>/sys</filename> path of the device to query, e.g.
- <filename><optional>/sys</optional>/class/block/sda</filename>. This option is an alternative to
+ <para>The <filename>/sys/</filename> path of the device to query, e.g.
+ <filename><optional>/sys/</optional>/class/block/sda</filename>. This option is an alternative to
the positional argument with a <filename>/sys/</filename> prefix. <command>udevadm info
--path=/class/block/sda</command> is equivalent to <command>udevadm info
/sys/class/block/sda</command>.</para>
<term><option>--name=<replaceable>FILE</replaceable></option></term>
<listitem>
<para>The name of the device node or a symlink to query,
- e.g. <filename><optional>/dev</optional>/sda</filename>. This option is an alternative to the
+ e.g. <filename><optional>/dev/</optional>/sda</filename>. This option is an alternative to the
positional argument with a <filename>/dev/</filename> prefix. <command>udevadm info
--name=sda</command> is equivalent to <command>udevadm info /dev/sda</command>.</para>
</listitem>
<term><option>--sysname-match=<replaceable>NAME</replaceable></option></term>
<listitem>
<para>Trigger events for devices for which the last component (i.e. the filename) of the
- <filename>/sys</filename> path matches the specified <replaceable>PATH</replaceable>. This option
+ <filename>/sys/</filename> path matches the specified <replaceable>PATH</replaceable>. This option
supports shell style pattern matching. When this option is specified more than once, then each
matching result is ORed, that is, all devices which have any of the specified
<replaceable>NAME</replaceable> are triggered.</para>
<para>In addition, optional positional arguments can be used
to specify device names or sys paths. They must start with
- <filename>/dev</filename> or <filename>/sys</filename>
+ <filename>/dev/</filename> or <filename>/sys/</filename>
respectively.</para>
</refsect2>
project_source_root).stdout().strip()
conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path)
-conf.set10('DEVELOPER_MODE', get_option('mode') == 'developer',
- description : 'enable additional checks only suitable in development')
+conf.set('BUILD_MODE', 'BUILD_MODE_' + get_option('mode').to_upper(),
+ description : 'tailor build to development or release builds')
want_ossfuzz = get_option('oss-fuzz')
want_libfuzzer = get_option('llvm-fuzz')
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
+substs.set('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata'))
substs.set('RC_LOCAL_PATH', get_option('rc-local'))
substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>'''],
+ ['mallinfo', '''#include <malloc.h>'''],
+ ['close_range', '''#include <unistd.h>'''],
]
have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
endif
conf.set('TIME_EPOCH', time_epoch)
-system_uid_max = get_option('system-uid-max')
-if system_uid_max == -1
- system_uid_max = run_command(
- awk,
- '/^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }',
- '/etc/login.defs').stdout().strip()
- if system_uid_max == ''
- system_uid_max = 999
- else
- system_uid_max = system_uid_max.to_int()
+foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1], # Also see login.defs(5).
+ ['system-uid-max', 'SYS_UID_MAX', 999],
+ ['system-alloc-gid-min', 'SYS_GID_MIN', 1],
+ ['system-gid-max', 'SYS_GID_MAX', 999]]
+ v = get_option(tuple[0])
+ if v == -1
+ v = run_command(
+ awk,
+ '/^\s*@0@\s+/ { uid=$2 } END { print uid }'.format(tuple[1]),
+ '/etc/login.defs').stdout().strip()
+ if v == ''
+ v = tuple[2]
+ else
+ v = v.to_int()
+ endif
endif
+ conf.set(tuple[0].underscorify().to_upper(), v)
+ substs.set(tuple[0].underscorify().to_upper(), v)
+endforeach
+if conf.get('SYSTEM_ALLOC_UID_MIN') >= conf.get('SYSTEM_UID_MAX')
+ error('Invalid uid allocation range')
endif
-conf.set('SYSTEM_UID_MAX', system_uid_max)
-substs.set('systemuidmax', system_uid_max)
-
-system_gid_max = get_option('system-gid-max')
-if system_gid_max == -1
- system_gid_max = run_command(
- awk,
- '/^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }',
- '/etc/login.defs').stdout().strip()
- if system_gid_max == ''
- system_gid_max = 999
- else
- system_gid_max = system_gid_max.to_int()
- endif
+if conf.get('SYSTEM_ALLOC_GID_MIN') >= conf.get('SYSTEM_GID_MAX')
+ error('Invalid gid allocation range')
endif
-conf.set('SYSTEM_GID_MAX', system_gid_max)
-substs.set('systemgidmax', system_gid_max)
dynamic_uid_min = get_option('dynamic-uid-min')
dynamic_uid_max = get_option('dynamic-uid-max')
have = have and conf.get('HAVE_PAM') == 1
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'
+ error('oomd is not available in release mode (yet)')
+ endif
+endif
+conf.set10('ENABLE_OOMD', have)
+
want_remote = get_option('remote')
if want_remote != 'false'
have_deps = [conf.get('HAVE_MICROHTTPD') == 1,
'idn',
'ima',
'initrd',
+ 'compat-mutable-uid-boundaries',
'ldconfig',
'localed',
'logind',
'networkd',
'nss-myhostname',
'nss-systemd',
+ 'oomd',
'portabled',
'pstore',
'quotacheck',
have = get_option(term)
name = 'ENABLE_' + term.underscorify().to_upper()
conf.set10(name, have)
+ substs.set10(name, have)
endforeach
+enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
+
foreach tuple : [['nss-mymachines', 'machined'],
['nss-resolve', 'resolve']]
want = get_option(tuple[0])
subdir('src/journal-remote')
subdir('src/coredump')
subdir('src/pstore')
+subdir('src/oom')
subdir('src/hostname')
subdir('src/import')
subdir('src/partition')
public_programs += executable(
'systemctl',
+ 'src/systemctl/systemctl-add-dependency.c',
+ 'src/systemctl/systemctl-add-dependency.h',
+ 'src/systemctl/systemctl-cancel-job.c',
+ 'src/systemctl/systemctl-cancel-job.h',
+ 'src/systemctl/systemctl-clean-or-freeze.c',
+ 'src/systemctl/systemctl-clean-or-freeze.h',
+ 'src/systemctl/systemctl-compat-halt.c',
+ 'src/systemctl/systemctl-compat-halt.h',
+ 'src/systemctl/systemctl-compat-runlevel.c',
+ 'src/systemctl/systemctl-compat-runlevel.h',
+ 'src/systemctl/systemctl-compat-shutdown.c',
+ 'src/systemctl/systemctl-compat-shutdown.h',
+ 'src/systemctl/systemctl-compat-telinit.c',
+ 'src/systemctl/systemctl-compat-telinit.h',
+ 'src/systemctl/systemctl-daemon-reload.c',
+ 'src/systemctl/systemctl-daemon-reload.h',
+ 'src/systemctl/systemctl-edit.c',
+ 'src/systemctl/systemctl-edit.h',
+ 'src/systemctl/systemctl-enable.c',
+ 'src/systemctl/systemctl-enable.h',
+ 'src/systemctl/systemctl-is-active.c',
+ 'src/systemctl/systemctl-is-active.h',
+ 'src/systemctl/systemctl-is-enabled.c',
+ 'src/systemctl/systemctl-is-enabled.h',
+ 'src/systemctl/systemctl-is-system-running.c',
+ 'src/systemctl/systemctl-is-system-running.h',
+ 'src/systemctl/systemctl-kill.c',
+ 'src/systemctl/systemctl-kill.h',
+ 'src/systemctl/systemctl-list-dependencies.c',
+ 'src/systemctl/systemctl-list-dependencies.h',
+ 'src/systemctl/systemctl-list-jobs.c',
+ 'src/systemctl/systemctl-list-jobs.h',
+ 'src/systemctl/systemctl-list-machines.c',
+ 'src/systemctl/systemctl-list-machines.h',
+ 'src/systemctl/systemctl-list-unit-files.c',
+ 'src/systemctl/systemctl-list-unit-files.h',
+ 'src/systemctl/systemctl-list-units.c',
+ 'src/systemctl/systemctl-list-units.h',
+ 'src/systemctl/systemctl-log-setting.c',
+ 'src/systemctl/systemctl-log-setting.h',
+ 'src/systemctl/systemctl-logind.c',
+ 'src/systemctl/systemctl-logind.h',
+ 'src/systemctl/systemctl-preset-all.c',
+ 'src/systemctl/systemctl-preset-all.h',
+ 'src/systemctl/systemctl-reset-failed.c',
+ 'src/systemctl/systemctl-reset-failed.h',
+ 'src/systemctl/systemctl-service-watchdogs.c',
+ 'src/systemctl/systemctl-service-watchdogs.h',
+ 'src/systemctl/systemctl-set-default.c',
+ 'src/systemctl/systemctl-set-default.h',
+ 'src/systemctl/systemctl-set-environment.c',
+ 'src/systemctl/systemctl-set-environment.h',
+ 'src/systemctl/systemctl-set-property.c',
+ 'src/systemctl/systemctl-set-property.h',
+ 'src/systemctl/systemctl-show.c',
+ 'src/systemctl/systemctl-show.h',
+ 'src/systemctl/systemctl-start-special.c',
+ 'src/systemctl/systemctl-start-special.h',
+ 'src/systemctl/systemctl-start-unit.c',
+ 'src/systemctl/systemctl-start-unit.h',
+ 'src/systemctl/systemctl-switch-root.c',
+ 'src/systemctl/systemctl-switch-root.h',
+ 'src/systemctl/systemctl-sysv-compat.c',
+ 'src/systemctl/systemctl-sysv-compat.h',
+ 'src/systemctl/systemctl-trivial-method.c',
+ 'src/systemctl/systemctl-trivial-method.h',
+ 'src/systemctl/systemctl-util.c',
+ 'src/systemctl/systemctl-util.c',
+ 'src/systemctl/systemctl-util.h',
'src/systemctl/systemctl.c',
- 'src/systemctl/sysv-compat.h',
- 'src/systemctl/sysv-compat.c',
+ 'src/systemctl/systemctl.h',
include_directories : includes,
link_with : systemctl_link_with,
dependencies : [threads,
install_dir : rootlibexecdir)
endif
+if conf.get('ENABLE_OOMD') == 1
+ executable('systemd-oomd',
+ systemd_oomd_sources,
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+
+ public_programs += executable(
+ 'oomctl',
+ oomctl_sources,
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootbindir)
+endif
+
if conf.get('ENABLE_BINFMT') == 1
public_programs += executable(
'systemd-binfmt',
install_rpath : rootlibexecdir,
install : true)
-if conf.get('ENABLE_SYSUSERS') == 1
- public_programs += executable(
+if enable_sysusers
+ exe = executable(
'systemd-sysusers',
'src/sysusers/sysusers.c',
include_directories : includes,
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
+ public_programs += exe
+
+ if want_tests != 'false'
+ test('test-sysusers',
+ test_sysusers_sh,
+ # https://github.com/mesonbuild/meson/issues/2681
+ args : exe.full_path())
+ endif
if have_standalone_binaries
- public_programs += executable(
+ exe = executable(
'systemd-sysusers.standalone',
'src/sysusers/sysusers.c',
include_directories : includes,
+ c_args : '-DSTANDALONE',
link_with : [libshared_static,
libbasic,
libbasic_gcrypt,
libjournal_client],
install : true,
install_dir : rootbindir)
+ public_programs += exe
+
+ if want_tests != 'false'
+ test('test-sysusers.standalone',
+ test_sysusers_sh,
+ # https://github.com/mesonbuild/meson/issues/2681
+ args : exe.full_path())
+ endif
endif
endif
'systemd-tmpfiles.standalone',
systemd_tmpfiles_sources,
include_directories : includes,
+ c_args : '-DSTANDALONE',
link_with : [libshared_static,
libbasic,
libbasic_gcrypt,
get_option('debug-tty')),
'TTY GID: @0@'.format(tty_gid),
'users GID: @0@'.format(substs.get('USERS_GID')),
- 'maximum system UID: @0@'.format(system_uid_max),
- 'maximum system GID: @0@'.format(system_gid_max),
- 'minimum dynamic UID: @0@'.format(dynamic_uid_min),
- 'maximum dynamic UID: @0@'.format(dynamic_uid_max),
- 'minimum container UID base: @0@'.format(container_uid_base_min),
- 'maximum container UID base: @0@'.format(container_uid_base_max),
+ 'system UIDs: <=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_UID_MAX'),
+ 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@–@1@'.format(dynamic_uid_min, dynamic_uid_max),
+ 'container UID bases: @0@–@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')),
['libcurl'],
['idn'],
['initrd'],
+ ['compat-mutable-uid-boundaries'],
['libidn2'],
['libidn'],
['libiptc'],
['DNS-over-TLS(openssl)', conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1],
['coredump'],
['pstore'],
+ ['oomd'],
['polkit'],
['legacy pkla', install_polkit_pkla],
['efi'],
description : 'override the git version string')
option('mode', type : 'combo', choices : ['developer', 'release'],
- description : 'enable additional checks suitable for systemd development')
+ description : 'autoenable features suitable for systemd development/release builds')
option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'],
description : '''/bin, /sbin aren't symlinks into /usr''')
description : '''install a static library for libsystemd''')
option('static-libudev', type : 'combo',
choices : ['false', 'true', 'pic', 'no-pic'],
- description : '''install a static library for libudev''')
+ description : 'install a static library for libudev')
option('standalone-binaries', type : 'boolean', value : 'false',
- description : '''also build standalone versions of supported binaries''')
+ description : 'also build standalone versions of supported binaries')
option('sysvinit-path', type : 'string', value : '/etc/init.d',
description : 'the directory where the SysV init scripts are located')
description : 'path to telinit')
option('rc-local', type : 'string',
value : '/etc/rc.local')
-option('initrd', type: 'boolean',
+option('initrd', type : 'boolean',
description : 'install services for use when running systemd in initrd')
+option('compat-mutable-uid-boundaries', type : 'boolean', value : 'false',
+ description : 'look at uid boundaries in /etc/login.defs for compatibility')
option('quotaon-path', type : 'string', description : 'path to quotaon')
option('quotacheck-path', type : 'string', description : 'path to quotacheck')
description : 'install the coredump handler')
option('pstore', type : 'boolean',
description : 'install the pstore archival tool')
+option('oomd', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'install the userspace oom killer')
option('logind', type : 'boolean',
description : 'install the systemd-logind stack')
option('hostnamed', type : 'boolean',
description : 'use unit name or description in messages by default')
option('time-epoch', type : 'integer', value : '-1',
description : 'time epoch for time clients')
+option('system-alloc-uid-min', type : 'integer', value : '-1',
+ description : 'minimum system UID used when allocating')
+option('system-alloc-gid-min', type : 'integer', value : '-1',
+ description : 'minimum system GID used when allocating')
option('system-uid-max', type : 'integer', value : '-1',
description : 'maximum system UID')
option('system-gid-max', type : 'integer', value : '-1',
#
#
# Viktar Vaŭčkievič <victorenator@gmail.com>, 2015, 2016.
+# Zmicer Turok <nashtlumach@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-19 18:02+0200\n"
-"PO-Revision-Date: 2016-06-09 19:47+0300\n"
-"Last-Translator: Viktar Vaŭčkievič <victorenator@gmail.com>\n"
-"Language-Team: \n"
+"PO-Revision-Date: 2020-10-16 06:30+0000\n"
+"Last-Translator: Zmicer Turok <nashtlumach@gmail.com>\n"
+"Language-Team: Belarusian <https://translate.fedoraproject.org/projects/"
+"systemd/master/be/>\n"
"Language: be\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
-"X-Generator: Lokalize 2.0\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 4.2.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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f адпÑ\80аÑ\9eкÑ\96 паÑ\80олÑ\8f назад Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме."
+msgstr "Ð\9aаб адпÑ\80авÑ\96Ñ\86Ñ\8c паÑ\80олÑ\8c назад Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме, паÑ\82Ñ\80бÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
-msgstr "Кіраваць сэрвісамі і іншымі сістэмнымі адзінкамі"
+msgstr "Кіраванне сістэмнымі службамі і іншымі адзінкамі"
#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f кÑ\96Ñ\80аваннÑ\8f Ñ\81Ñ\8dÑ\80вÑ\96Ñ\81амÑ\96 Ñ\96 Ñ\96нÑ\88Ñ\8bмÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bмÑ\96 "
-"адзінкамі."
+"Ð\94лÑ\8f кÑ\96Ñ\80аваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bмÑ\96 Ñ\81лÑ\83жбамÑ\96 Ñ\96 Ñ\96нÑ\88Ñ\8bмÑ\96 адзÑ\96нкамÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аўтэнтыфікацыя."
#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
-msgstr "Кіраваць файламі сэрвісаў і іншых сістэмных адзінак"
+msgstr "Кіраванне файламі сістэмных службаў і іншых адзінак"
#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f кÑ\96Ñ\80аваннÑ\8f Ñ\84айламÑ\96 Ñ\81Ñ\8dÑ\80вÑ\96Ñ\81аÑ\9e Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bÑ\85 "
-"адзінак."
+"Ð\94лÑ\8f кÑ\96Ñ\80аваннÑ\8f Ñ\84айламÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bÑ\85 Ñ\81лÑ\83жбаÑ\9e Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 адзÑ\96нак паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аўтэнтыфікацыя."
#: src/core/org.freedesktop.systemd1.policy.in:54
msgid "Set or unset system and service manager environment variables"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c або Ñ\81кÑ\96нÑ\83Ñ\86Ñ\8c зменнÑ\8bÑ\8f аÑ\81Ñ\8fÑ\80оддзÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага мÑ\8dнÑ\8dджÑ\8dÑ\80а"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c зменнÑ\8bÑ\8f аÑ\81Ñ\8fÑ\80оддзÑ\8f кÑ\96Ñ\80аÑ\9eнÑ\96ка Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b"
#: src/core/org.freedesktop.systemd1.policy.in:55
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f або Ñ\81кÑ\96дÑ\83 зменнÑ\8bÑ\85 аÑ\81Ñ\8fÑ\80оддзÑ\8f "
-"сістэмнага мэнэджэра."
+"Ð\94лÑ\8f наладкÑ\96 зменнÑ\8bÑ\85 аÑ\81Ñ\8fÑ\80оддзÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага кÑ\96Ñ\80аÑ\9eнÑ\96ка паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аўтэнтыфікацыя."
#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 systemd."
+msgstr "Ð\9aаб пеÑ\80аÑ\87Ñ\8bÑ\82аÑ\86Ñ\8c Ñ\81Ñ\82ан systemd, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/home/org.freedesktop.home1.policy:13
msgid "Create a home area"
-msgstr ""
+msgstr "Стварыць хатнюю прастору"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 systemd."
+msgstr "Ð\94лÑ\8f Ñ\81Ñ\82ваÑ\80Ñ\8dннÑ\8f Ñ\85аÑ\82нÑ\8fй пÑ\80аÑ\81Ñ\82оÑ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/home/org.freedesktop.home1.policy:23
msgid "Remove a home area"
-msgstr ""
+msgstr "Выдаліць хатнюю прастору"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 systemd."
+msgstr "Ð\94лÑ\8f вÑ\8bдаленнÑ\8f Ñ\85аÑ\82нÑ\8fй пÑ\80аÑ\81Ñ\82оÑ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/home/org.freedesktop.home1.policy:33
msgid "Check credentials of a home area"
-msgstr ""
+msgstr "Праверыць уліковыя даныя хатняй прасторы"
#: 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 ""
-"Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і "
-"месцамі."
+msgstr "Для праверкі ўліковых даных хатняй прасторы патрабуецца аўтэнтыфікацыя."
#: src/home/org.freedesktop.home1.policy:43
msgid "Update a home area"
-msgstr ""
+msgstr "Абнавіць хатнюю прастору"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f далÑ\83Ñ\87Ñ\8dннÑ\8f пÑ\80Ñ\8bлад да пÑ\80аÑ\86оÑ\9eнÑ\8bÑ\85 меÑ\81Ñ\86аÑ\9e."
+msgstr "Ð\94лÑ\8f абнаÑ\9eленнÑ\8f Ñ\85аÑ\82нÑ\8fй пÑ\80аÑ\81Ñ\82оÑ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/home/org.freedesktop.home1.policy:53
msgid "Resize a home area"
-msgstr ""
+msgstr "Змяніць памер хатняй прасторы"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамленнÑ\8f"
+msgstr "Ð\94лÑ\8f зменÑ\8b памеÑ\80Ñ\83 Ñ\85аÑ\82нÑ\8fй пÑ\80аÑ\81Ñ\82оÑ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/home/org.freedesktop.home1.policy:63
msgid "Change password of a home area"
-msgstr ""
+msgstr "Змяніць пароль для хатняй прасторы"
#: 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 ""
-"Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і "
-"месцамі."
+msgstr "Для змены пароля для хатняй прасторы патрабуецца аўтэнтыфікацыя."
#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set hostname"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\96мÑ\8f вÑ\83зла"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c назвÑ\83 кампâ\80\99Ñ\8eÑ\82аÑ\80а"
#: src/hostname/org.freedesktop.hostname1.policy:21
msgid "Authentication is required to set the local hostname."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\96мÑ\8f вÑ\83зла."
+msgstr "Ð\94лÑ\8f наладкÑ\96 назвÑ\8b кампâ\80\99Ñ\8eÑ\82аÑ\80а паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/hostname/org.freedesktop.hostname1.policy:30
msgid "Set static hostname"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\81Ñ\82аÑ\82Ñ\8bÑ\87нае Ñ\96мÑ\8f вÑ\83зла"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c Ñ\81Ñ\82аÑ\82Ñ\8bÑ\87нÑ\83Ñ\8e назвÑ\83 кампâ\80\99Ñ\8eÑ\82аÑ\80а"
#: src/hostname/org.freedesktop.hostname1.policy:31
msgid ""
"Authentication is required to set the statically configured local hostname, "
"as well as the pretty hostname."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\8fк Ñ\81Ñ\82аÑ\82Ñ\8bÑ\87нага Ñ\82ак Ñ\96 пÑ\80Ñ\8bгожага Ñ\96мÑ\8f "
-"вÑ\83зла."
+"Ð\94лÑ\8f наладкÑ\96 Ñ\8fк Ñ\81Ñ\82аÑ\82Ñ\8bÑ\87най, Ñ\82ак Ñ\96 зÑ\80азÑ\83мелай, назвÑ\8b кампâ\80\99Ñ\8eÑ\82аÑ\80а паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\96нÑ\84аÑ\80маÑ\86Ñ\8bÑ\8e аб маÑ\88Ñ\8bне"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c звеÑ\81Ñ\82кÑ\96 пÑ\80а кампâ\80\99Ñ\8eÑ\82аÑ\80"
#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
-msgstr ""
-"Неабходна аўтэнтыфікацыя для ўсталявання інфармацыі аб лакальнай машыне."
+msgstr "Для наладкі звестак пра камп’ютар патрабуецца аўтэнтыфікацыя."
#: src/hostname/org.freedesktop.hostname1.policy:51
msgid "Get product UUID"
-msgstr ""
+msgstr "Атрымаць 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 '$(unit)'."
+msgstr "Ð\94лÑ\8f аÑ\82Ñ\80Ñ\8bманнÑ\8f UUID пÑ\80адÑ\83кÑ\82Ñ\83 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
-msgstr "Ð\86мпаÑ\80Ñ\82аваÑ\86Ñ\8c вобÑ\80аз Ð\92Ð\9c або кантэйнера"
+msgstr "Ð\86мпаÑ\80Ñ\82аваÑ\86Ñ\8c вобÑ\80аз вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнай маÑ\88Ñ\8bнÑ\8b або кантэйнера"
#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
-msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера"
+msgstr ""
+"Для імпарту вобраза віртуальнай машыны або кантэйнера патрабуецца "
+"аўтэнтыфікацыя"
#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
-msgstr "ÐкÑ\81паÑ\80Ñ\82аваÑ\86Ñ\8c вобÑ\80аз Ð\92Ð\9c або кантэйнера"
+msgstr "ÐкÑ\81паÑ\80Ñ\82аваÑ\86Ñ\8c вобÑ\80аз вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнай маÑ\88Ñ\8bнÑ\8b або кантэйнера"
#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
-msgstr "Неабходна аўтэнтыфікацыя для экспарту вобраза ВМ або кантэйнера"
+msgstr ""
+"Для экспарту вобраза віртуальнай машыны або кантэйнера патрабуецца "
+"аўтэнтыфікацыя"
#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
-msgstr "СпампаваÑ\86Ñ\8c вобÑ\80аз Ð\92Ð\9c або кантэйнера"
+msgstr "СпампаваÑ\86Ñ\8c вобÑ\80аз вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнай маÑ\88Ñ\8bнÑ\8b або кантэйнера"
#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
-msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера"
+msgstr ""
+"Для спампоўвання вобраза віртуальнай машыны або кантэйнера патрабуецца "
+"аўтэнтыфікацыя"
#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
-msgstr "УÑ\81Ñ\82алÑ\8fваць сістэмную лакаль"
+msgstr "Ð\9dаладзÑ\96ць сістэмную лакаль"
#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнай лакалÑ\96."
+msgstr "Ð\94лÑ\8f наладкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнай лакалÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bÑ\8f налады клавіятуры"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c паÑ\80амеÑ\82Ñ\80ы клавіятуры"
#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8bÑ\85 налад клавÑ\96Ñ\8fÑ\82Ñ\83Ñ\80Ñ\8b."
+msgstr "Ð\94лÑ\8f наладкÑ\96 паÑ\80амеÑ\82Ñ\80аÑ\9e клавÑ\96Ñ\8fÑ\82Ñ\83Ñ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e "
-"сістэмы."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, "
+"патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c вÑ\8bклÑ\8eÑ\87Ñ\8dнне "
-"сістэмы."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c вÑ\8bклÑ\8eÑ\87Ñ\8dнне Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, "
+"патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
-msgstr "Ð\94азволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c заÑ\81Ñ\8bпаннÑ\8e Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b"
+msgstr "Ð\94азволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c пеÑ\80аÑ\85одÑ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83"
#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c заÑ\81Ñ\8bпаннÑ\8e "
-"сістэмы."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c пеÑ\80аÑ\85одÑ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83, "
+"патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
-msgstr "Ð\94азволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c заÑ\81Ñ\8bпанне Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b"
+msgstr "Ð\94азволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c пеÑ\80аÑ\85од Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83"
#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c заÑ\81Ñ\8bпанне "
-"сістэмы."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам заÑ\82Ñ\80Ñ\8bмлÑ\96ваÑ\86Ñ\8c пеÑ\80аÑ\85од Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83, "
+"патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
"Authentication is required for an application to inhibit automatic system "
"suspend."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c аÑ\9eÑ\82амаÑ\82Ñ\8bÑ\87намÑ\83 "
-"прыпыненню сістэмы."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c аÑ\9eÑ\82амаÑ\82Ñ\8bÑ\87намÑ\83 пÑ\80Ñ\8bпÑ\8bненнÑ\8e "
+"сістэмы, патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
-msgstr ""
-"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу выключэння"
+msgstr "Дазволіць праграмам перашкаджаць сістэме апрацоўваць кнопку выключэння"
#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме "
-"апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c клавÑ\96Ñ\88Ñ\83 вÑ\8bклÑ\8eÑ\87Ñ\8dння."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c кнопкÑ\83 "
+"вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bя."
#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
-msgstr ""
-"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу прыпынення"
+msgstr "Дазволіць праграмам перашкаджаць сістэме апрацоўваць кнопку прыпынення"
#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме "
-"апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c клавÑ\96Ñ\88Ñ\83 пÑ\80Ñ\8bпÑ\8bнення."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c кнопкÑ\83 "
+"пÑ\80Ñ\8bпÑ\8bненнÑ\8f, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bя."
#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
-"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу гібернацыі"
+"Дазволіць праграмам перашкаджаць сістэме апрацоўваць кнопку пераходу ў рэжым "
+"сну"
#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме "
-"апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c клавÑ\96Ñ\88Ñ\83 гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c кнопкÑ\83 "
+"пеÑ\80аÑ\85одÑ\83 Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
-msgstr ""
-"Дазволіць праграмам перашкаджаць сістэме апрацоўваць закрыццё крышкі ноўтбука"
+msgstr "Дазволіць праграмам перашкаджаць сістэме апрацоўваць закрыццё ноўтбука"
#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f дазволÑ\83 пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме "
-"апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c закÑ\80Ñ\8bÑ\86Ñ\86Ñ\91 кÑ\80Ñ\8bÑ\88кÑ\96 ноÑ\9eÑ\82бÑ\83ка."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пеÑ\80аÑ\88каджаÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dме апÑ\80аÑ\86оÑ\9eваÑ\86Ñ\8c закÑ\80Ñ\8bÑ\86Ñ\86Ñ\91 "
+"ноÑ\9eÑ\82бÑ\83ка, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:117
msgid "Allow non-logged-in user to run programs"
-msgstr ""
-"Дазволіць карыстальніку, якія яшчэ не ўвайшоў у сістэму, выконваць праграмы"
+msgstr "Дазволіць праграмам працаваць у фоне па-за сеансам карыстальніка"
#: src/login/org.freedesktop.login1.policy:118
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
-"Ð\9dеабÑ\85однÑ\8b вÑ\96давоÑ\87нÑ\8b запÑ\8bÑ\82 длÑ\8f вÑ\8bкананнÑ\8f пÑ\80агÑ\80ам каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96ка, Ñ\8fкÑ\96 Ñ\8fÑ\88Ñ\87Ñ\8d не "
-"ўвайшоў у сістэму."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пÑ\80аÑ\86аваÑ\86Ñ\8c па-за Ñ\81еанÑ\81ам каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96ка, "
+"патрабуецца відавочны запыт."
#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
-msgstr ""
-"Дазволіць карыстальнікам, якія яшчэ не ўвайшлі ў сістэму, выконваць праграмы"
+msgstr "Дазволіць праграмам працаваць у фоне па-за сеансам карыстальніка"
#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f вÑ\8bкананнÑ\8f пÑ\80агÑ\80ам каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96ка, Ñ\8fкÑ\96 Ñ\8fÑ\88Ñ\87Ñ\8d не "
-"ўвайшоў у сістэму."
+"Ð\94лÑ\8f Ñ\82аго, каб дазволÑ\96Ñ\86Ñ\8c пÑ\80агÑ\80амам пÑ\80аÑ\86аваÑ\86Ñ\8c па-за межамÑ\96 Ñ\81еанÑ\81а "
+"карыстальніка, патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required to attach a device to a seat."
-msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў."
+msgstr ""
+"Для таго, каб дазволіць далучаць прылады да працоўных месцаў, патрабуецца "
+"аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
-msgstr "Ð\90дклÑ\8eÑ\87аць прылады ад працоўных месцаў"
+msgstr "Ð\90длÑ\83Ñ\87Ñ\8bць прылады ад працоўных месцаў"
#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to reset how devices are attached to seats."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f адклÑ\8eÑ\87Ñ\8dннÑ\8f пÑ\80Ñ\8bлад ад пÑ\80аÑ\86оÑ\9eнÑ\8bÑ\85 меÑ\81Ñ\86аÑ\9e."
+msgstr "Ð\94лÑ\8f адлÑ\83Ñ\87Ñ\8dннÑ\8f пÑ\80Ñ\8bлад ад пÑ\80аÑ\86оÑ\9eнÑ\8bÑ\85 меÑ\81Ñ\86аÑ\9e паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required to power off the system."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
-msgstr "Ð\92Ñ\8bклÑ\8eÑ\87Ñ\8bÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e"
+msgstr "Ð\92Ñ\8bклÑ\8eÑ\87Ñ\8bÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96"
#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required to power off the system while other users are "
"logged in."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 "
-"каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e."
+"Ð\94лÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application is inhibiting this"
"Authentication is required to power off the system while an application is "
"inhibiting this."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, калÑ\96 пÑ\80агÑ\80амÑ\8b перашкаджаюць "
-"гÑ\8dÑ\82амÑ\83."
+"Ð\94лÑ\8f вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 пÑ\80агÑ\80амамÑ\96, Ñ\8fкÑ\96Ñ\8f перашкаджаюць "
+"вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required to reboot the system."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
-msgstr "Ð\9fеÑ\80азагÑ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e"
+msgstr "Ð\9fеÑ\80азагÑ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96"
#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required to reboot the system while other users are logged "
"in."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 "
-"каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e."
+"Ð\94лÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application is inhibiting this"
"Authentication is required to reboot the system while an application is "
"inhibiting this."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, калÑ\96 пÑ\80агÑ\80амÑ\8b "
-"пеÑ\80аÑ\88каджаÑ\8eÑ\86Ñ\8c гÑ\8dÑ\82амÑ\83."
+"Ð\94лÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 пÑ\80агÑ\80амамÑ\96, Ñ\8fкÑ\96Ñ\8f пеÑ\80аÑ\88каджаÑ\8eÑ\86Ñ\8c "
+"вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:224
-#, fuzzy
-#| msgid "Hibernate the system"
msgid "Halt the system"
-msgstr "Ð\93Ñ\96беÑ\80наваць сістэму"
+msgstr "СпÑ\8bнÑ\96ць сістэму"
#: src/login/org.freedesktop.login1.policy:225
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to halt the system."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f Ñ\81пÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:235
-#, fuzzy
-#| msgid "Hibernate the system while other users are logged in"
msgid "Halt the system while other users are logged in"
-msgstr "Ð\93Ñ\96беÑ\80наваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e"
+msgstr "СпÑ\8bнÑ\96Ñ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96"
#: src/login/org.freedesktop.login1.policy:236
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to hibernate the system while other users are "
-#| "logged in."
msgid ""
"Authentication is required to halt the system while other users are logged "
"in."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 "
-"каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e."
+"Ð\94лÑ\8f Ñ\81пÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:246
-#, fuzzy
-#| msgid "Hibernate the system while an application is inhibiting this"
msgid "Halt the system while an application is inhibiting this"
-msgstr "Ð\93Ñ\96беÑ\80наваць сістэму, калі праграмы перашкаджаюць гэтаму"
+msgstr "СпÑ\8bнÑ\96ць сістэму, калі праграмы перашкаджаюць гэтаму"
#: src/login/org.freedesktop.login1.policy:247
-#, 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 ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, калÑ\96 пÑ\80агÑ\80амÑ\8b пеÑ\80аÑ\88каджаÑ\8eÑ\86Ñ\8c "
-"гÑ\8dÑ\82амÑ\83."
+"Ð\94лÑ\8f Ñ\81пÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 пÑ\80агÑ\80амамÑ\96, Ñ\8fкÑ\96Ñ\8f пеÑ\80аÑ\88каджаÑ\8eÑ\86Ñ\8c вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e, "
+"паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required to suspend the system."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
-msgstr "Ð\9fÑ\80Ñ\8bпÑ\8bнÑ\96Ñ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e"
+msgstr "Ð\9fÑ\80Ñ\8bпÑ\8bнÑ\96Ñ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96"
#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required to suspend the system while other users are "
"logged in."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 "
-"каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e."
+"Ð\94лÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application is inhibiting this"
"Authentication is required to suspend the system while an application is "
"inhibiting this."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, калÑ\96 пÑ\80агÑ\80амÑ\8b перашкаджаюць "
-"гÑ\8dÑ\82амÑ\83."
+"Ð\94лÑ\8f пÑ\80Ñ\8bпÑ\8bненнÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b з акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 пÑ\80агÑ\80амамÑ\96, Ñ\8fкÑ\96Ñ\8f перашкаджаюць "
+"вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
-msgstr "Ð\93Ñ\96беÑ\80наваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dму"
+msgstr "Ð\9fеÑ\80авеÑ\81Ñ\86Ñ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81ну"
#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required to hibernate the system."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f пеÑ\80аводÑ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
-msgstr "Ð\93Ñ\96беÑ\80наваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e"
+msgstr "Ð\9fеÑ\80авеÑ\81Ñ\86Ñ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96"
#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required to hibernate the system while other users are "
"logged in."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b пÑ\80Ñ\8b пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82наÑ\81Ñ\86Ñ\96 Ñ\96нÑ\88Ñ\8bÑ\85 "
-"каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96каÑ\9e."
+"Ð\94лÑ\8f пеÑ\80аводÑ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83 з Ñ\96нÑ\88Ñ\8bмÑ\96 пÑ\80Ñ\8bÑ\81Ñ\83Ñ\82нÑ\8bмÑ\96 каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 "
+"паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application is inhibiting this"
-msgstr "Ð\93Ñ\96беÑ\80наваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dму, калі праграмы перашкаджаюць гэтаму"
+msgstr "Ð\9fеÑ\80авеÑ\81Ñ\86Ñ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81ну, калі праграмы перашкаджаюць гэтаму"
#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required to hibernate the system while an application is "
"inhibiting this."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b, калÑ\96 пÑ\80агÑ\80амÑ\8b перашкаджаюць "
-"гÑ\8dÑ\82амÑ\83."
+"Ð\94лÑ\8f пеÑ\80аводÑ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b Ñ\9e Ñ\80Ñ\8dжÑ\8bм Ñ\81нÑ\83 з акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 пÑ\80агÑ\80амамÑ\96, Ñ\8fкÑ\96Ñ\8f перашкаджаюць "
+"вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8e, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
-msgstr "Кіраваць актыўнымі сесіямі, карыстальнікамі і працоўнымі месцамі"
+msgstr "Кіраванне актыўнымі сеансамі, карыстальнікамі і працоўнымі месцамі"
#: src/login/org.freedesktop.login1.policy:322
msgid "Authentication is required to manage active sessions, users and seats."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f кÑ\96Ñ\80аваннÑ\8f акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 Ñ\81еÑ\81Ñ\96Ñ\8fмÑ\96, каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 і "
-"меÑ\81Ñ\86амÑ\96."
+"Ð\94лÑ\8f кÑ\96Ñ\80аваннÑ\8f акÑ\82Ñ\8bÑ\9eнÑ\8bмÑ\96 Ñ\81еанÑ\81амÑ\96, каÑ\80Ñ\8bÑ\81Ñ\82алÑ\8cнÑ\96камÑ\96 Ñ\96 пÑ\80аÑ\86оÑ\9eнÑ\8bмÑ\96 меÑ\81Ñ\86амі "
+"паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
-msgstr "Ð\91лакаваÑ\86Ñ\8c або Ñ\80азблакаваÑ\86Ñ\8c акÑ\82Ñ\8bÑ\9eнÑ\83Ñ\8e Ñ\81еÑ\81Ñ\96Ñ\8e"
+msgstr "Ð\97аблакаваÑ\86Ñ\8c або Ñ\80азблакаваÑ\86Ñ\8c акÑ\82Ñ\8bÑ\9eнÑ\8bÑ\8f Ñ\81еанÑ\81Ñ\8b"
#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
-"Неабходна аўтэнтыфікацыя для блакіроўкі або разблакіроўкі актыўнай сесіі."
+"Для таго, каб заблакаваць ці разблакаваць актыўныя сеансы, патрабуецца "
+"аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:341
msgid "Set the reboot \"reason\" in the kernel"
-msgstr ""
+msgstr "Вызначыць \"прычыну\" перазапуску"
#: src/login/org.freedesktop.login1.policy:342
-#, fuzzy
-#| msgid "Authentication is required to set the system timezone."
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
-msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу."
+msgstr ""
+"Для таго, каб вызначыць прычыну перазапуску, патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:352
-#, fuzzy
-#| msgid "Allow indication to the firmware to boot to setup interface"
msgid "Indicate to the firmware to boot to setup interface"
-msgstr "Ð\94азволÑ\96Ñ\86Ñ\8c Ñ\83казанне пÑ\80аÑ\88Ñ\8bÑ\9eÑ\86Ñ\8b на загÑ\80Ñ\83зкÑ\83 Ñ\96нÑ\82Ñ\8dÑ\80Ñ\84ейÑ\81Ñ\83 налад"
+msgstr "Ð\97апÑ\83Ñ\81Ñ\86Ñ\96Ñ\86Ñ\8c наладкÑ\83 пÑ\80аÑ\88Ñ\8bÑ\9eкÑ\96 падÑ\87аÑ\81 наÑ\81Ñ\82Ñ\83пнага запÑ\83Ñ\81кÑ\83"
#: src/login/org.freedesktop.login1.policy:353
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
-msgstr ""
-"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад."
+msgstr "Для таго, каб запусціць наладку прашыўкі, патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:363
msgid "Indicate to the boot loader to boot to the boot loader menu"
-msgstr ""
+msgstr "Вывесці меню загрузчыка падчас наступнага запуску"
#: src/login/org.freedesktop.login1.policy:364
-#, 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 ""
-"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад."
+"Для вываду меню загрузчыка падчас наступнага запуску патрабуецца "
+"аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot a specific entry"
-msgstr ""
+msgstr "Абраць пэўны загрузачны запіс падчас наступнага запуску"
#: 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 into a "
"specific boot loader entry."
msgstr ""
-"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад."
+"Для таго, каб абраць пэўны загрузачны запіс падчас наступнага запуску, "
+"патрабуецца аўтэнтыфікацыя."
#: src/login/org.freedesktop.login1.policy:385
msgid "Set a wall message"
-msgstr "УÑ\81Ñ\82алÑ\8fваць усеагульнае паведамленне"
+msgstr "Ð\92Ñ\8bзнаÑ\87Ñ\8bць усеагульнае паведамленне"
#: src/login/org.freedesktop.login1.policy:386
msgid "Authentication is required to set a wall message"
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамлення"
+msgstr "Ð\94лÑ\8f вÑ\8bзнаÑ\87Ñ\8dннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамленнÑ\8f паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bя"
#: src/login/org.freedesktop.login1.policy:395
msgid "Change Session"
-msgstr ""
+msgstr "Змяніць сеанс"
#: src/login/org.freedesktop.login1.policy:396
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to change the virtual terminal."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\96мÑ\8f вÑ\83зла."
+msgstr "Ð\94лÑ\8f зменÑ\8b вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнага Ñ\81еанÑ\81а паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eваÑ\85одÑ\83 Ñ\9e лакалÑ\8cнÑ\8b канÑ\82Ñ\8dйнеÑ\80."
+msgstr "Ð\94лÑ\8f Ñ\9eваÑ\85одÑ\83 Ñ\9e лакалÑ\8cнÑ\8b канÑ\82Ñ\8dйнеÑ\80 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
-msgstr "Увайсці ў лакальны вузел"
+msgstr "Увайсці на лакальны камп’ютар"
#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eваÑ\85одÑ\83 Ñ\9e лакалÑ\8cнÑ\8b вÑ\83зел."
+msgstr "Ð\94лÑ\8f Ñ\9eваÑ\85одÑ\83 на лакалÑ\8cнÑ\8b кампâ\80\99Ñ\8eÑ\82аÑ\80 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
-msgstr "Атрымаць абалонку на лакальным кантэйнеры"
+msgstr "Атрымаць абалонку ў лакальным кантэйнеры"
#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f аÑ\82Ñ\80Ñ\8bманнÑ\8f абалонкÑ\96 на лакалÑ\8cнÑ\8bм канÑ\82Ñ\8dйнеÑ\80Ñ\8b."
+"Ð\94лÑ\8f аÑ\82Ñ\80Ñ\8bманнÑ\8f абалонкÑ\96 Ñ\9e лакалÑ\8cнÑ\8bм канÑ\82Ñ\8dйнеÑ\80Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
-msgstr "Ð\90Ñ\82Ñ\80Ñ\8bмаÑ\86Ñ\8c абалонкÑ\83 на лакалÑ\8cнÑ\8bм вÑ\83зле"
+msgstr "Ð\90Ñ\82Ñ\80Ñ\8bмаÑ\86Ñ\8c абалонкÑ\83 на лакалÑ\8cнÑ\8bм кампâ\80\99Ñ\8eÑ\82аÑ\80Ñ\8b"
#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
-msgstr "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным вузле."
+msgstr ""
+"Для атрымання абалонкі на лакальным камп’ютары патрабуецца аўтэнтыфікацыя."
#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
-msgstr "Атрымаць псеўда TTY на лакальным кантэйнеры"
+msgstr "Атрымаць псеўда-тэрмінал у лакальным кантэйнеры"
#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
-"Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным кантэйнеры."
+"Для атрымання псеўда-тэрмінала ў лакальным кантэйнеры патрабуецца "
+"аўтэнтыфікацыя."
#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
-msgstr "Атрымаць псеўда TTY на лакальным вузле"
+msgstr "Атрымаць псеўда-тэрмінал на лакальным камп’ютары"
#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным вузле."
+msgstr ""
+"Для атрымання псеўда-тэрмінала на лакальным камп’ютары патрабуецца "
+"аўтэнтыфікацыя."
#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
-msgstr "Кіраваць лакальнымі віртуальнымі машынамі або кантэйнерамі"
+msgstr "Кіраванне лакальнымі віртуальнымі машынамі або кантэйнерамі"
#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f кÑ\96Ñ\80аваннÑ\8f лакалÑ\8cнÑ\8bмÑ\96 вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнÑ\8bмÑ\96 маÑ\88Ñ\8bнамÑ\96 Ñ\96 "
-"канÑ\82Ñ\8dйнеÑ\80амÑ\96."
+"Ð\94лÑ\8f кÑ\96Ñ\80аваннÑ\8f лакалÑ\8cнÑ\8bмÑ\96 вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнÑ\8bмÑ\96 маÑ\88Ñ\8bнамÑ\96 Ñ\96 канÑ\82Ñ\8dйнеÑ\80амÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
-msgstr "Кіраваць вобразамі лакальных віртуальных машын і кантэйнераў"
+msgstr "Кіраванне вобразамі лакальных віртуальных машын і кантэйнераў"
#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f кÑ\96Ñ\80аваннÑ\8f вобÑ\80азамÑ\96 лакалÑ\8cнÑ\8bÑ\85 вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнÑ\8bÑ\85 маÑ\88Ñ\8bн "
-"і кантэйнераў."
+"Ð\94лÑ\8f кÑ\96Ñ\80аваннÑ\8f вобÑ\80азамÑ\96 лакалÑ\8cнÑ\8bÑ\85 вÑ\96Ñ\80Ñ\82Ñ\83алÑ\8cнÑ\8bÑ\85 маÑ\88Ñ\8bн Ñ\96 канÑ\82Ñ\8dйнеÑ\80аÑ\9e "
+"патрабуецца аўтэнтыфікацыя."
#: src/network/org.freedesktop.network1.policy:22
msgid "Set NTP servers"
-msgstr ""
+msgstr "Вызначыць серверы NTP"
#: src/network/org.freedesktop.network1.policy:23
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to set NTP servers."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f вÑ\8bзнаÑ\87Ñ\8dннÑ\8f Ñ\81еÑ\80веÑ\80аÑ\9e NTP паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
msgid "Set DNS servers"
-msgstr ""
+msgstr "Вызначыць серверы DNS"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to set DNS servers."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f вÑ\8bзнаÑ\87Ñ\8dннÑ\8f Ñ\81еÑ\80веÑ\80аÑ\9e DNS паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
msgid "Set domains"
-msgstr ""
+msgstr "Вызначыць дамены"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\81пÑ\8bненнÑ\8f '$(unit)'."
+msgstr "Ð\94лÑ\8f вÑ\8bзнаÑ\87Ñ\8dннÑ\8f даменаÑ\9e паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
-msgstr ""
+msgstr "Вызначыць прадвызначаны маршрут"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\96мÑ\8f вÑ\83зла."
+msgstr "Ð\94лÑ\8f вÑ\8bзнаÑ\87Ñ\8dннÑ\8f пÑ\80адвÑ\8bзнаÑ\87анага маÑ\80Ñ\88Ñ\80Ñ\83Ñ\82Ñ\83 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
msgid "Enable/disable LLMNR"
-msgstr ""
+msgstr "Уключыць / адключыць LLMNR"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\86Ñ\96 адклÑ\8eÑ\87Ñ\8dннÑ\8f LLMNR паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
msgid "Enable/disable multicast DNS"
-msgstr ""
+msgstr "Уключыць / адключыць multicast DNS"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eваÑ\85одÑ\83 Ñ\9e лакалÑ\8cнÑ\8b вÑ\83зел."
+msgstr "Ð\94лÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\86Ñ\96 адклÑ\8eÑ\87Ñ\8dннÑ\8f multicast DNS паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
msgid "Enable/disable DNS over TLS"
-msgstr ""
+msgstr "Уключыць / адключыць DNS паверх TLS"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\96мÑ\8f вÑ\83зла."
+msgstr "Ð\94лÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\86Ñ\96 адклÑ\8eÑ\87Ñ\8dннÑ\8f DNS павеÑ\80Ñ\85 TLS паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
msgid "Enable/disable DNSSEC"
-msgstr ""
+msgstr "Уключыць / адключыць DNSSEC"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f гÑ\96беÑ\80наÑ\86Ñ\8bÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\86Ñ\96 адклÑ\8eÑ\87Ñ\8dннÑ\8f DNSSEC паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
msgid "Set DNSSEC Negative Trust Anchors"
-msgstr ""
+msgstr "Вызначыць DNSSEC Negative Trust Anchors"
#: 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 "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі."
+msgstr ""
+"Для вызначэння DNSSEC Negative Trust Anchors патрабуецца аўтэнтыфікацыя."
#: src/network/org.freedesktop.network1.policy:121
msgid "Revert NTP settings"
-msgstr ""
+msgstr "Скінуць налады NTP"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f Ñ\82аго, каб Ñ\81кÑ\96нÑ\83Ñ\86Ñ\8c наладÑ\8b NTP, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:132
msgid "Revert DNS settings"
-msgstr ""
+msgstr "Скінуць налады DNS"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f Ñ\82аго, каб Ñ\81кÑ\96нÑ\83Ñ\86Ñ\8c наладÑ\8b DNS, паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:143
msgid "DHCP server sends force renew message"
-msgstr ""
+msgstr "Сервер DHCP адпраўляе паведамленне з прымусовым абнаўленнем"
#: 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 "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення"
+msgstr ""
+"Для адпраўкі паведамлення з прымусовым абнаўленнем патрабуецца "
+"аўтэнтыфікацыя."
#: src/network/org.freedesktop.network1.policy:154
msgid "Renew dynamic addresses"
-msgstr ""
+msgstr "Абнавіць дынамічныя адрасы"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамленнÑ\8f"
+msgstr "Ð\94лÑ\8f абнаÑ\9eленнÑ\8f дÑ\8bнамÑ\96Ñ\87нÑ\8bÑ\85 адÑ\80аÑ\81оÑ\9e паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:165
msgid "Reload network settings"
-msgstr ""
+msgstr "Перазагрузіць налады сеткі"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 systemd."
+msgstr "Ð\94лÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 налад Ñ\81еÑ\82кÑ\96 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/network/org.freedesktop.network1.policy:176
msgid "Reconfigure network interface"
-msgstr ""
+msgstr "Змяніць канфігурацыю сеткавага інтэрфейсу"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80азагÑ\80Ñ\83зкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\8b."
+msgstr "Ð\94лÑ\8f зменÑ\8b канÑ\84Ñ\96гÑ\83Ñ\80аÑ\86Ñ\8bÑ\96 Ñ\81еÑ\82кавага Ñ\96нÑ\82Ñ\8dÑ\80Ñ\84ейÑ\81Ñ\83 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
-msgstr ""
+msgstr "Прачытаць вобраз пераноснай службы"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\96мпаÑ\80Ñ\82Ñ\83 вобÑ\80аза Ð\92Ð\9c або канÑ\82Ñ\8dйнеÑ\80а"
+msgstr "Ð\94лÑ\8f Ñ\87Ñ\8bÑ\82аннÑ\8f вобÑ\80аза пеÑ\80аноÑ\81най Ñ\81лÑ\83жбÑ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/portable/org.freedesktop.portable1.policy:23
msgid "Attach or detach a portable service image"
-msgstr ""
+msgstr "Далучыць альбо адлучыць вобраз пераноснай службы"
#: 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 "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў."
+msgstr ""
+"Для далучэння альбо адлучэння вобраза пераноснай службы патрабуецца "
+"аўтэнтыфікацыя."
#: src/portable/org.freedesktop.portable1.policy:34
msgid "Delete or modify portable service image"
-msgstr ""
+msgstr "Выдаліць альбо змяніць вобраз пераноснай службы"
#: 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 "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера"
+msgstr ""
+"Для выдалення альбо змены вобраза пераноснай службы патрабуецца "
+"аўтэнтыфікацыя."
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
-msgstr ""
+msgstr "Рэгістрацыя службы DNS-SD"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамлення"
+msgstr "Ð\94лÑ\8f Ñ\80Ñ\8dгÑ\96Ñ\81Ñ\82Ñ\80аÑ\86Ñ\8bÑ\96 Ñ\81лÑ\83жбÑ\8b DNS-SD паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bя"
#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
-msgstr ""
+msgstr "Выдаленне службы DNS-SD"
#: 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 "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eÑ\81еагÑ\83лÑ\8cнага паведамлення"
+msgstr "Ð\94лÑ\8f вÑ\8bдаленнÑ\8f Ñ\81лÑ\83жбÑ\8b DNS-SD паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bя"
#: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings"
-msgstr ""
+msgstr "Скінуць налады вырашэння назваў"
#: 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 "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры."
+msgstr ""
+"Для таго, каб скінуць налады вырашэння назваў, патрабуецца аўтэнтыфікацыя."
#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
-msgstr "УÑ\81Ñ\82алÑ\8fваць сістэмны час"
+msgstr "Ð\9dаладзÑ\96ць сістэмны час"
#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f наладкÑ\96 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81Ñ\83 паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнÑ\8b часавы пояс"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c часавы пояс"
#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмнага Ñ\87аÑ\81авога поÑ\8fÑ\81Ñ\83."
+msgstr "Ð\94лÑ\8f наладкÑ\96 Ñ\87аÑ\81авога поÑ\8fÑ\81а паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
-msgstr "УÑ\81Ñ\82алÑ\8fваÑ\86Ñ\8c Ñ\87аÑ\81авÑ\8b поÑ\8fÑ\81 (мÑ\8fÑ\81Ñ\86овÑ\8b або UTC), Ñ\83 Ñ\8fкÑ\96м RTC заÑ\85оÑ\9eвае Ñ\87аÑ\81"
+msgstr "Ð\9dаладзÑ\96Ñ\86Ñ\8c апаÑ\80аÑ\82нÑ\8b гадзÑ\96ннÑ\96к на мÑ\8fÑ\81Ñ\86овÑ\8b Ñ\87аÑ\81 алÑ\8cбо UTC"
#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
-msgstr ""
-"Неабходна аўтэнтыфікацыя для ўсталявання часавога поясу (мясцовы або UTC), у "
-"якім захоўваецца час у RTC."
+msgstr "Для наладкі апаратнага гадзінніка патрабуецца аўтэнтыфікацыя."
#: src/timedate/org.freedesktop.timedate1.policy:53
msgid "Turn network time synchronization on or off"
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr ""
-"Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f або вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96нÑ\85Ñ\80анÑ\96заÑ\86Ñ\8bÑ\96 Ñ\87аÑ\81Ñ\83 па "
-"сетцы."
+"Ð\94лÑ\8f Ñ\9eклÑ\8eÑ\87Ñ\8dннÑ\8f або вÑ\8bклÑ\8eÑ\87Ñ\8dннÑ\8f Ñ\81Ñ\96нÑ\85Ñ\80анÑ\96заÑ\86Ñ\8bÑ\96 Ñ\87аÑ\81Ñ\83 па Ñ\81еÑ\82Ñ\86Ñ\8b паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а "
+"аўтэнтыфікацыя."
#: src/core/dbus-unit.c:362
msgid "Authentication is required to start '$(unit)'."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f запÑ\83Ñ\81кÑ\83 '$(unit)'."
+msgstr "Ð\94лÑ\8f запÑ\83Ñ\81кÑ\83 \"$(unit)\" паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/dbus-unit.c:363
msgid "Authentication is required to stop '$(unit)'."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\81пÑ\8bненнÑ\8f '$(unit)'."
+msgstr "Ð\94лÑ\8f Ñ\81пÑ\8bненнÑ\8f \"$(unit)\" паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/dbus-unit.c:364
msgid "Authentication is required to reload '$(unit)'."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 '$(unit)'."
+msgstr "Ð\94лÑ\8f пеÑ\80аÑ\87Ñ\8bÑ\82аннÑ\8f Ñ\81Ñ\82анÑ\83 \"$(unit)\" паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366
msgid "Authentication is required to restart '$(unit)'."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f пеÑ\80азапÑ\83Ñ\81кÑ\83 '$(unit)'."
+msgstr "Ð\94лÑ\8f пеÑ\80азапÑ\83Ñ\81кÑ\83 \"$(unit)\" паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/dbus-unit.c:538
-#, 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 "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'."
+msgstr ""
+"Для адпраўкі сігналу UNIX працэсам адзінкі \"$(unit)\" патрабуецца "
+"аўтэнтыфікацыя."
#: src/core/dbus-unit.c:569
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'."
+msgstr ""
+"Для таго, каб скінуць стан \"failed\" у \"$(unit)\", патрабуецца "
+"аўтэнтыфікацыя."
#: src/core/dbus-unit.c:602
msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "Ð\9dеабÑ\85одна аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f длÑ\8f Ñ\9eÑ\81Ñ\82алÑ\8fваннÑ\8f Ñ\9eлаÑ\81Ñ\86Ñ\96ваÑ\81Ñ\86ей '$(unit)'."
+msgstr "Ð\94лÑ\8f зменÑ\8b Ñ\9eлаÑ\81Ñ\86Ñ\96ваÑ\81Ñ\86ей \"$(unit)\" паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а аÑ\9eÑ\82Ñ\8dнÑ\82Ñ\8bÑ\84Ñ\96каÑ\86Ñ\8bÑ\8f."
#: src/core/dbus-unit.c:711
-#, 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 "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'."
+msgstr ""
+"Для выдалення файлаў і каталогаў, якія звязаныя з \"$(unit)\", патрабуецца "
+"аўтэнтыфікацыя."
#: src/core/dbus-unit.c:760
-#, 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 "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'."
+msgstr ""
+"Для спынення альбо ўзнаўлення працэсаў \"$(unit)\" патрабуецца "
+"аўтэнтыфікацыя."
#~ msgid "Authentication is required to kill '$(unit)'."
#~ msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'."
msgid "Check credentials of a home area"
msgstr "Tjek loginoplysninger for et hjemmeområde"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:34
msgid ""
"Authentication is required to check credentials against a user's home area."
msgid "Update a home area"
msgstr "Opdater et hjemmeområde"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:44
msgid "Authentication is required to update a user's home area."
msgstr "Der kræves godkendelse for at opdatere en brugers hjemmeområde."
msgid "Change password of a home area"
msgstr "Skift adgangskode for et hjemmeområde"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:64
msgid ""
"Authentication is required to change the password of a user's home area."
"Der kræves godkendelse for at brugere, som ikke er logget ind, kan køre "
"programmer."
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Tillad at montere af enheder til arbejdsstationer"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required to attach a device to a seat."
msgstr "Der kræves godkendelse for at montere en enhed til en arbejdsstation."
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Nulstil enhed monteret til en arbejdsstation"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to reset how devices are attached to seats."
msgstr ""
msgid "Manage active sessions, users and seats"
msgstr "Håndter aktive sessioner, brugere og arbejdsstationer"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:322
msgid "Authentication is required to manage active sessions, users and seats."
msgstr ""
msgid "Attach or detach a portable service image"
msgstr "Tilslut eller frakobl et transportabel tjeneste-aftryk"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/portable/org.freedesktop.portable1.policy:24
msgid ""
"Authentication is required to attach or detach a portable service image."
msgid "Check credentials of a home area"
msgstr ""
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:34
#, fuzzy
#| msgid ""
msgid "Update a home area"
msgstr ""
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:44
#, fuzzy
#| msgid "Authentication is required to attach a device to a seat."
msgid "Change password of a home area"
msgstr ""
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/home/org.freedesktop.home1.policy:64
#, fuzzy
#| msgid ""
"Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme "
"ausführen dürfen."
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Das Anschließen von Geräten an Arbeitsstationen erlauben"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required to attach a device to a seat."
msgstr ""
"Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation "
"notwendig."
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Zurücksetzen der an eine Arbeitsstation angeschlossenen Geräte"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to reset how devices are attached to seats."
msgstr ""
msgid "Manage active sessions, users and seats"
msgstr "Aktive Sitzungen, Benutzer und Arbeitsstationen verwalten"
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/login/org.freedesktop.login1.policy:322
msgid "Authentication is required to manage active sessions, users and seats."
msgstr ""
msgid "Attach or detach a portable service image"
msgstr ""
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
+# https://www.freedesktop.org/software/systemd/man/sd-login.html
#: src/portable/org.freedesktop.portable1.policy:24
#, fuzzy
#| msgid "Authentication is required to attach a device to a seat."
# Italian translation for systemd package
# Traduzione in italiano per il pacchetto systemd
# Daniele Medri <dmedri@gmail.com>, 2013-2020.
-# Milo Casagrande <milo@milo.name>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
-"Report-Msgid-Bugs-To: \n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
"POT-Creation-Date: 2020-08-19 18:02+0200\n"
-"PO-Revision-Date: 2020-09-15 08:29+0000\n"
-"Last-Translator: Milo Casagrande <milo@milo.name>\n"
-"Language-Team: Italian <https://translate.fedoraproject.org/projects/systemd/"
-"master/it/>\n"
+"PO-Revision-Date: 2020-10-03 09:52+0200\n"
+"Last-Translator: Daniele Medri <dmedri@gmail.com>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.2.2\n"
+"X-Generator: Poedit 2.2.1\n"
+"Language-Team: \n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgid ""
"Authentication is required to send the entered passphrase back to the system."
msgstr ""
-"È richiesto autenticarsi per inviare la frase segreta (passphrase) al "
-"sistema."
+"Autenticazione richiesta per inviare la frase segreta (passphrase) al sistema."
#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
-"È richiesto autenticarsi per gestire i servizi o le altre unità di sistema."
+"Autenticazione richiesta per gestire i servizi o le altre unità di sistema."
#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
-"È richiesto autenticarsi per gestire i file dei servizi o delle unità di "
+"Autenticazione richiesta per gestire i file dei servizi o delle unità di "
"sistema."
#: src/core/org.freedesktop.systemd1.policy.in:54
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr ""
-"È richiesto autenticarsi per configurare le variabili d'ambiente per la "
+"Autenticazione richiesta per configurare le variabili d'ambiente per la "
"gestione dei servizi e del sistema."
#: src/core/org.freedesktop.systemd1.policy.in:64
#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
-msgstr "È richiesto autenticarsi per riavviare lo stato di sistemd."
+msgstr "Autenticazione richiesta per riavviare lo stato di sistemd."
#: src/home/org.freedesktop.home1.policy:13
msgid "Create a home area"
#: src/home/org.freedesktop.home1.policy:14
msgid "Authentication is required to create a user's home area."
-msgstr "È richiesto autenticarsi per creare l'area home di un utente."
+msgstr "Autenticazione richiesta per creare l'area home di un utente."
#: src/home/org.freedesktop.home1.policy:23
msgid "Remove a home area"
#: src/home/org.freedesktop.home1.policy:24
msgid "Authentication is required to remove a user's home area."
-msgstr "È richiesto autenticarsi per rimuovere l'area home di un utente."
+msgstr "Autenticazione richiesta per rimuovere l'area home di un utente."
#: src/home/org.freedesktop.home1.policy:33
msgid "Check credentials of a home area"
msgid ""
"Authentication is required to check credentials against a user's home area."
msgstr ""
-"È richiesto autenticarsi per controllare le credenziali di un'area home per "
+"Autenticazione richiesta per controllare le credenziali di un'area home per "
"l'utente."
#: src/home/org.freedesktop.home1.policy:43
#: src/home/org.freedesktop.home1.policy:44
msgid "Authentication is required to update a user's home area."
-msgstr "È richiesto autenticarsi per aggiornare l'area home di un l'utente."
+msgstr "Autenticazione richiesta per aggiornare l'area home di un l'utente."
#: src/home/org.freedesktop.home1.policy:53
msgid "Resize a home area"
#: src/home/org.freedesktop.home1.policy:54
msgid "Authentication is required to resize a user's home area."
-msgstr "È richiesto autenticarsi per ridimensionare l'area home di un'utente."
+msgstr "Autenticazione richiesta per ridimensionare l'area home di un'utente."
#: src/home/org.freedesktop.home1.policy:63
msgid "Change password of a home area"
msgstr "Modifica password di un'area home"
#: src/home/org.freedesktop.home1.policy:64
-msgid ""
-"Authentication is required to change the password of a user's home area."
+msgid "Authentication is required to change the password of a user's home area."
msgstr ""
-"È richiesto autenticarsi per modificare la password dell'area home di un "
+"Autenticazione richiesta per modificare la password dell'area home di un "
"utente."
#: src/hostname/org.freedesktop.hostname1.policy:20
#: src/hostname/org.freedesktop.hostname1.policy:21
msgid "Authentication is required to set the local hostname."
-msgstr "È richiesto autenticarsi per configurare il nome host locale."
+msgstr "Autenticazione richiesta per configurare il nome host locale."
#: src/hostname/org.freedesktop.hostname1.policy:30
msgid "Set static hostname"
"Authentication is required to set the statically configured local hostname, "
"as well as the pretty hostname."
msgstr ""
-"È richiesto autenticarsi per configurare staticamente il nome host locale e "
+"Autenticazione richiesta per configurare staticamente il nome host locale e "
"il nome host descrittivo."
#: src/hostname/org.freedesktop.hostname1.policy:41
#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
msgstr ""
-"È richiesto autenticarsi per configurare le informazioni sulla macchina "
+"Autenticazione richiesta per configurare le informazioni sulla macchina "
"locale."
#: src/hostname/org.freedesktop.hostname1.policy:51
#: src/hostname/org.freedesktop.hostname1.policy:52
msgid "Authentication is required to get product UUID."
-msgstr "È richiesto autenticarsi per ottenere lo UUID del prodotto."
+msgstr "Autenticazione richiesta per ottenere lo UUID del prodotto."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
-msgstr "È richiesto autenticarsi per importare un'immagine VM o un container"
+msgstr "Autenticazione richiesta per importare un'immagine VM o un container"
#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
-msgstr "È richiesto autenticarsi per esportare un'immagine VM o un container"
+msgstr "Autenticazione richiesta per esportare un'immagine VM o un container"
#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
-msgstr "È richiesto autenticarsi per scaricare un'immagine VM o un container"
+msgstr "Autenticazione richiesta per scaricare un'immagine VM o un container"
#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
msgstr ""
-"È richiesto autenticarsi per configurare le impostazioni regionali di "
-"sistema."
+"Autenticazione richiesta per configurare le impostazioni regionali di sistema."
#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
-msgstr "È richiesto autenticarsi per configurare la tastiera di sistema."
+msgstr "Autenticazione richiesta per configurare la tastiera di sistema."
#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
-"È richiesto autenticarsi per un'applicazione per inibire lo spegnimento del "
+"Autenticazione richiesta per un'applicazione per inibire lo spegnimento del "
"sistema."
#: src/login/org.freedesktop.login1.policy:33
#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
-"È richiesto autenticarsi ad un'applicazione per ritardare lo spegnimento del "
+"Autenticazione richiesta ad un'applicazione per ritardare lo spegnimento del "
"sistema."
#: src/login/org.freedesktop.login1.policy:44
#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa inibire la pausa del "
+"Autenticazione richiesta affinché un'applicazione possa inibire la pausa del "
"sistema."
#: src/login/org.freedesktop.login1.policy:55
#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa ritardare la pausa "
+"Autenticazione richiesta affinché un'applicazione possa ritardare la pausa "
"del sistema."
#: src/login/org.freedesktop.login1.policy:65
"Authentication is required for an application to inhibit automatic system "
"suspend."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa inibire la "
+"Autenticazione richiesta affinché un'applicazione possa inibire la "
"sospensione automatica del sistema."
#: src/login/org.freedesktop.login1.policy:75
"Authentication is required for an application to inhibit system handling of "
"the power key."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa inibire la gestione "
+"Autenticazione richiesta affinché un'applicazione possa inibire la gestione "
"di sistema del tasto accensione."
#: src/login/org.freedesktop.login1.policy:86
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa inibire la gestione "
+"Autenticazione richiesta affinché un'applicazione possa inibire la gestione "
"di sistema del tasto di sospensione."
#: src/login/org.freedesktop.login1.policy:97
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
msgstr ""
-"È richiesto autenticarsi affinché un'applicazione possa inibire la gestione "
+"Autenticazione richiesta affinché un'applicazione possa inibire la gestione "
"di sistema del tasto di ibernazione."
#: src/login/org.freedesktop.login1.policy:107
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
msgstr ""
-"È richiesto autenticarsi per consentire a un'applicazione di inibire la "
+"Autenticazione richiesta per consentire a un'applicazione di inibire la "
"gestione di sistema alla apertura/chiusura del portatile."
#: src/login/org.freedesktop.login1.policy:117
#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
-"È richiesto autenticarsi per consentire agli utenti non connessi di eseguire "
+"Autenticazione richiesta per consentire agli utenti non connessi di eseguire "
"programmi."
#: src/login/org.freedesktop.login1.policy:137
#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required to attach a device to a seat."
msgstr ""
-"È richiesto autenticarsi per collegare un dispositivo ad una postazione."
+"Autenticazione richiesta per collegare un dispositivo ad una postazione."
#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to reset how devices are attached to seats."
msgstr ""
-"È richiesto autenticarsi per ripristinare come i dispositivi sono collegati "
+"Autenticazione richiesta per ripristinare come i dispositivi sono collegati "
"alle postazioni."
#: src/login/org.freedesktop.login1.policy:158
#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required to power off the system."
-msgstr "È richiesto autenticarsi per spegnere il sistema."
+msgstr "Autenticazione richiesta per spegnere il sistema."
#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
"Authentication is required to power off the system while other users are "
"logged in."
msgstr ""
-"È richiesto autenticarsi per spegnere il sistema mentre altri utenti sono "
+"Autenticazione richiesta per spegnere il sistema mentre altri utenti sono "
"connessi."
#: src/login/org.freedesktop.login1.policy:180
"Authentication is required to power off the system while an application is "
"inhibiting this."
msgstr ""
-"È richiesto autenticarsi per spegnere il sistema mentre un'applicazione "
+"Autenticazione richiesta per spegnere il sistema mentre un'applicazione "
"chiede di inibirne l'azione."
#: src/login/org.freedesktop.login1.policy:191
#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required to reboot the system."
-msgstr "È richiesto autenticarsi per riavviare il sistema."
+msgstr "Autenticazione richiesta per riavviare il sistema."
#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
"Authentication is required to reboot the system while other users are logged "
"in."
msgstr ""
-"È richiesto autenticarsi per riavviare il sistema mentre altri utenti sono "
+"Autenticazione richiesta per riavviare il sistema mentre altri utenti sono "
"connessi."
#: src/login/org.freedesktop.login1.policy:213
"Authentication is required to reboot the system while an application is "
"inhibiting this."
msgstr ""
-"È richiesto autenticarsi per riavviare il sistema mentre un'applicazione "
+"Autenticazione richiesta per riavviare il sistema mentre un'applicazione "
"chiede di inibirne l'azione."
#: src/login/org.freedesktop.login1.policy:224
#: src/login/org.freedesktop.login1.policy:225
msgid "Authentication is required to halt the system."
-msgstr "È richiesto autenticarsi per fermare il sistema."
+msgstr "Autenticazione richiesta per fermare il sistema."
#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system while other users are logged in"
#: src/login/org.freedesktop.login1.policy:236
msgid ""
-"Authentication is required to halt the system while other users are logged "
-"in."
+"Authentication is required to halt the system while other users are logged in."
msgstr ""
-"È richiesto autenticarsi per fermare il sistema mentre altri utenti sono "
+"Autenticazione richiesta per fermare il sistema mentre altri utenti sono "
"connessi."
#: src/login/org.freedesktop.login1.policy:246
"Authentication is required to halt the system while an application is "
"inhibiting this."
msgstr ""
-"È richiesto autenticarsi per ibernare il sistema mentre un'applicazione ne "
+"Autenticazione richiesta per ibernare il sistema mentre un'applicazione ne "
"inibisce l'azione."
#: src/login/org.freedesktop.login1.policy:257
#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required to suspend the system."
-msgstr "È richiesto autenticarsi per sospendere il sistema."
+msgstr "Autenticazione richiesta per sospendere il sistema."
#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
#: src/login/org.freedesktop.login1.policy:268
msgid ""
-"Authentication is required to suspend the system while other users are "
-"logged in."
+"Authentication is required to suspend the system while other users are logged "
+"in."
msgstr ""
-"È richiesto autenticarsi per sospendere il sistema mentre altri utenti sono "
+"Autenticazione richiesta per sospendere il sistema mentre altri utenti sono "
"connessi."
#: src/login/org.freedesktop.login1.policy:278
"Authentication is required to suspend the system while an application is "
"inhibiting this."
msgstr ""
-"È richiesto autenticarsi per sospendere il sistema mentre un'applicazione "
+"Autenticazione richiesta per sospendere il sistema mentre un'applicazione "
"chiede di inibirne l'azione."
#: src/login/org.freedesktop.login1.policy:289
#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required to hibernate the system."
-msgstr "È richiesto autenticarsi per ibernare il sistema."
+msgstr "Autenticazione richiesta per ibernare il sistema."
#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
"Authentication is required to hibernate the system while other users are "
"logged in."
msgstr ""
-"È richiesto autenticarsi per ibernare il sistema mentre altri utenti sono "
+"Autenticazione richiesta per ibernare il sistema mentre altri utenti sono "
"connessi."
#: src/login/org.freedesktop.login1.policy:310
"Authentication is required to hibernate the system while an application is "
"inhibiting this."
msgstr ""
-"È richiesto autenticarsi per ibernare il sistema mentre un'applicazione "
+"Autenticazione richiesta per ibernare il sistema mentre un'applicazione "
"chiede di inibirne l'azione."
#: src/login/org.freedesktop.login1.policy:321
#: src/login/org.freedesktop.login1.policy:322
msgid "Authentication is required to manage active sessions, users and seats."
msgstr ""
-"È richiesto autenticarsi per gestire le sessioni attive, gli utenti e le "
+"Autenticazione richiesta per gestire le sessioni attive, gli utenti e le "
"postazioni."
#: src/login/org.freedesktop.login1.policy:331
#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "È richiesto autenticarsi per bloccare o sbloccare le sessioni attive."
+msgstr "Autenticazione richiesta per bloccare o sbloccare le sessioni attive."
#: src/login/org.freedesktop.login1.policy:341
msgid "Set the reboot \"reason\" in the kernel"
#: src/login/org.freedesktop.login1.policy:342
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
msgstr ""
-"È richiesto autenticarsi per configurare il \"motivo\" del riavvio nel "
-"kernel."
+"Autenticazione richiesta per configurare il \"motivo\" del riavvio nel kernel."
#: src/login/org.freedesktop.login1.policy:352
msgid "Indicate to the firmware to boot to setup interface"
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
msgstr ""
-"È richiesto autenticarsi per indicare al firmware l'avvio di un'interfaccia "
+"Autenticazione richiesta per indicare al firmware l'avvio di un'interfaccia "
"di configurazione."
#: src/login/org.freedesktop.login1.policy:363
#: src/login/org.freedesktop.login1.policy:364
msgid ""
-"Authentication is required to indicate to the boot loader to boot to the "
-"boot loader menu."
+"Authentication is required to indicate to the boot loader to boot to the boot "
+"loader menu."
msgstr ""
-"È richiesto autenticarsi per indicate al boot loader l'avvio di uno "
-"specifico menu."
+"Autenticazione richiesta per indicate al boot loader l'avvio di uno specifico "
+"menu."
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot a specific entry"
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
msgstr ""
-"È richiesto autenticarsi per indicare al boot loader l'avvio di una "
-"specifica voce in elenco."
+"Autenticazione richiesta per indicare al boot loader l'avvio di una specifica "
+"voce in elenco."
#: src/login/org.freedesktop.login1.policy:385
msgid "Set a wall message"
#: src/login/org.freedesktop.login1.policy:386
msgid "Authentication is required to set a wall message"
-msgstr "È richiesto autenticarsi per configurare un messaggio per gli utenti"
+msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
#: src/login/org.freedesktop.login1.policy:395
msgid "Change Session"
#: src/login/org.freedesktop.login1.policy:396
msgid "Authentication is required to change the virtual terminal."
-msgstr "È richiesto autenticarsi per cambiare il terminale virtuale."
+msgstr "Autenticazione richiesta per cambiare il terminale virtuale."
#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
-msgstr "È richiesto autenticarsi per accedere ad un container locale."
+msgstr "Autenticazione richiesta per accedere ad un container locale."
#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
-msgstr "È richiesto autenticarsi per accedere ad un host locale."
+msgstr "Autenticazione richiesta per accedere ad un host locale."
#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
-msgstr "È richiesto autenticarsi per aprire una shell in un container locale."
+msgstr "Autenticazione richiesta per aprire una shell in un container locale."
#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
-msgstr "È richiesto autenticarsi per aprire una shell in un host locale."
+msgstr "Autenticazione richiesta per aprire una shell in un host locale."
#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Apri un pseudo TTY in un container locale"
#: src/machine/org.freedesktop.machine1.policy:65
-msgid ""
-"Authentication is required to acquire a pseudo TTY in a local container."
+msgid "Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
-"È richiesto autenticarsi per aprire un pseudo TTY in un container locale."
+"Autenticazione richiesta per aprire un pseudo TTY in un container locale."
#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "È richiesto autenticarsi per aprire un pseudo TTY in un host locale."
+msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale."
#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
-"È richiesto autenticarsi per gestire le virtual machine e i container locali."
+"Autenticazione richiesta per gestire le virtual machine e i container locali."
#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
"Authentication is required to manage local virtual machine and container "
"images."
msgstr ""
-"È richiesto autenticarsi per gestire le immagini delle virtual machine e dei "
+"Autenticazione richiesta per gestire le immagini delle virtual machine e dei "
"container locali."
#: src/network/org.freedesktop.network1.policy:22
#: src/network/org.freedesktop.network1.policy:23
msgid "Authentication is required to set NTP servers."
-msgstr "È richiesto autenticarsi per configurare i server NTP."
+msgstr "Autenticazione richiesta per configurare i server NTP."
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
msgid "Authentication is required to set DNS servers."
-msgstr "È richiesto autenticarsi per configurare i server DNS."
+msgstr "Autenticazione richiesta per configurare i server DNS."
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
#: src/network/org.freedesktop.network1.policy:45
#: src/resolve/org.freedesktop.resolve1.policy:56
msgid "Authentication is required to set domains."
-msgstr "È richiesto autenticarsi per configurare i domini."
+msgstr "Autenticazione richiesta per configurare i domini."
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:67
msgid "Authentication is required to set default route."
msgstr ""
-"È richiesto autenticarsi per configurare la tabella di instradamento "
+"Autenticazione richiesta per configurare la tabella di instradamento "
"predefinita."
#: src/network/org.freedesktop.network1.policy:66
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
msgid "Authentication is required to enable or disable LLMNR."
-msgstr "È richiesto autenticarsi per attivare/disattivare LLMNR."
+msgstr "Autenticazione richiesta per attivare/disattivare 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
msgid "Authentication is required to enable or disable multicast DNS."
-msgstr "È richiesto autenticarsi per abilitare/disabilitare DNS multicast."
+msgstr "Autenticazione richiesta per abilitare/disabilitare DNS multicast."
#: 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
msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr "È richiesto autenticarsi per abilitare o disabilitare DNS su TLS."
+msgstr "Autenticazione richiesta per abilitare o disabilitare DNS su 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
msgid "Authentication is required to enable or disable DNSSEC."
-msgstr "È richiesto autenticarsi per abilitare o disabilitare DNSSEC."
+msgstr "Autenticazione richiesta per abilitare o disabilitare DNSSEC."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
#: src/network/org.freedesktop.network1.policy:111
#: src/resolve/org.freedesktop.resolve1.policy:122
msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
-msgstr "È richiesto autenticarsi per configurare DNSSEC Negative Trust Anchors."
+msgstr "Autenticazione richiesta per configurare DNSSEC Negative Trust Anchors."
#: src/network/org.freedesktop.network1.policy:121
msgid "Revert NTP settings"
#: src/network/org.freedesktop.network1.policy:122
msgid "Authentication is required to reset NTP settings."
-msgstr "È richiesto autenticarsi per ripristinare le configurazioni NTP."
+msgstr "Autenticazione richiesta per ripristinare le configurazioni NTP."
#: src/network/org.freedesktop.network1.policy:132
msgid "Revert DNS settings"
#: src/network/org.freedesktop.network1.policy:133
msgid "Authentication is required to reset DNS settings."
-msgstr "È richiesto autenticarsi per ripristinare le configurazioni DNS."
+msgstr "Autenticazione richiesta per ripristinare le configurazioni DNS."
#: src/network/org.freedesktop.network1.policy:143
msgid "DHCP server sends force renew message"
#: src/network/org.freedesktop.network1.policy:144
msgid "Authentication is required to send force renew message."
-msgstr "È richiesto autenticarsi per inviare messaggi di rinnovo forzato."
+msgstr "Autenticazione richiesta per inviare messaggi di rinnovo forzato."
#: src/network/org.freedesktop.network1.policy:154
msgid "Renew dynamic addresses"
#: src/network/org.freedesktop.network1.policy:155
msgid "Authentication is required to renew dynamic addresses."
-msgstr "È richiesto autenticarsi per rinnovare gli indirizzi dinamici."
+msgstr "Autenticazione richiesta per rinnovare gli indirizzi dinamici."
#: src/network/org.freedesktop.network1.policy:165
msgid "Reload network settings"
#: src/network/org.freedesktop.network1.policy:166
msgid "Authentication is required to reload network settings."
-msgstr "È richiesto autenticarsi per ricaricare le configurazioni di rete."
+msgstr "Autenticazione richiesta per ricaricare le configurazioni di rete."
#: src/network/org.freedesktop.network1.policy:176
msgid "Reconfigure network interface"
#: src/network/org.freedesktop.network1.policy:177
msgid "Authentication is required to reconfigure network interface."
-msgstr "È richiesto autenticarsi per riconfigurare l'interfaccia di rete."
+msgstr "Autenticazione richiesta per riconfigurare l'interfaccia di rete."
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
#: src/portable/org.freedesktop.portable1.policy:14
msgid "Authentication is required to inspect a portable service image."
msgstr ""
-"È richiesto autenticarsi per ispezionare un'immagine di servizio portabile."
+"Autenticazione richiesta per ispezionare un'immagine di servizio portabile."
#: src/portable/org.freedesktop.portable1.policy:23
msgid "Attach or detach a portable service image"
msgstr "Collega o meno un'immagine di servizio portabile"
#: src/portable/org.freedesktop.portable1.policy:24
-msgid ""
-"Authentication is required to attach or detach a portable service image."
+msgid "Authentication is required to attach or detach a portable service image."
msgstr ""
-"È richiesto autenticarsi per collegare o meno un'immagine di servizio "
+"Autenticazione richiesta per collegare o meno un'immagine di servizio "
"portabile."
#: src/portable/org.freedesktop.portable1.policy:34
msgstr "Elimina o modifica un'immagine di servizio portabile"
#: src/portable/org.freedesktop.portable1.policy:35
-msgid ""
-"Authentication is required to delete or modify a portable service image."
+msgid "Authentication is required to delete or modify a portable service image."
msgstr ""
-"È richiesto autenticarsi per eliminare o modificare un'immagine di servizio "
+"Autenticazione richiesta per eliminare o modificare un'immagine di servizio "
"portabile."
#: src/resolve/org.freedesktop.resolve1.policy:22
#: src/resolve/org.freedesktop.resolve1.policy:23
msgid "Authentication is required to register a DNS-SD service"
-msgstr "È richiesto autenticarsi per registrare un servizio DNS-SD"
+msgstr "Autenticazione richiesta per registrare un servizio DNS-SD"
#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
#: src/resolve/org.freedesktop.resolve1.policy:34
msgid "Authentication is required to unregister a DNS-SD service"
msgstr ""
-"È richiesto autenticarsi per annullare la registrazione di un servizio DNS-SD"
+"Autenticazione richiesta per annullare la registrazione di un servizio DNS-SD"
#: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings"
#: src/resolve/org.freedesktop.resolve1.policy:133
msgid "Authentication is required to reset name resolution settings."
msgstr ""
-"È richiesto autenticarsi per ripristinare le configurazioni per la "
+"Autenticazione richiesta per ripristinare le configurazioni per la "
"risoluzione dei nomi."
#: src/timedate/org.freedesktop.timedate1.policy:22
#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
-msgstr "È richiesto autenticarsi per impostare l'orario di sistema."
+msgstr "Autenticazione richiesta per impostare l'orario di sistema."
#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
-msgstr "È richiesto autenticarsi per impostare il fuso orario di sistema."
+msgstr "Autenticazione richiesta per impostare il fuso orario di sistema."
#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
-"Authentication is required to control whether the RTC stores the local or "
-"UTC time."
+"Authentication is required to control whether the RTC stores the local or UTC "
+"time."
msgstr ""
-"È richiesto autenticarsi per verificare se l'orologio di sistema (RTC) è "
+"Autenticazione richiesta per verificare se l'orologio di sistema (RTC) è "
"configurato all'orario locale o al tempo civile (UTC)."
#: src/timedate/org.freedesktop.timedate1.policy:53
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr ""
-"È richiesto autenticarsi per verificare se la sincronizzazione dell'orario "
-"in rete deve essere attivata."
+"Autenticazione richiesta per verificare se la sincronizzazione dell'orario in "
+"rete deve essere attivata."
#: src/core/dbus-unit.c:362
msgid "Authentication is required to start '$(unit)'."
-msgstr "È richiesto autenticarsi per avviare «${unit}»."
+msgstr "Autenticazione richiesta per avviare '${unit}'."
#: src/core/dbus-unit.c:363
msgid "Authentication is required to stop '$(unit)'."
-msgstr "È richiesto autenticarsi per fermare «${unit}»."
+msgstr "Autenticazione richiesta per fermare '${unit}'."
#: src/core/dbus-unit.c:364
msgid "Authentication is required to reload '$(unit)'."
-msgstr "È richiesto autenticarsi per ricaricare «${unit}»."
+msgstr "Autenticazione richiesta per ricaricare '${unit}'."
#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366
msgid "Authentication is required to restart '$(unit)'."
-msgstr "È richiesto autenticarsi per riavviare «${unit}»."
+msgstr "Autenticazione richiesta per riavviare '${unit}'."
#: src/core/dbus-unit.c:538
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
msgstr ""
-"È richiesto autenticarsi per inviare un segnale UNIX ai processi di "
-"«${unit}»."
+"Autenticazione richiesta per inviare un segnale UNIX ai processi di '${unit}'."
#: src/core/dbus-unit.c:569
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
-"È richiesto autenticarsi per riconfigurare lo stato \"fallito\" di «${unit}»."
+"Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '${unit}'."
#: src/core/dbus-unit.c:602
msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "È richiesto autenticarsi per configurare le proprietà di «${unit}»."
+msgstr "Autenticazione richiesta per configurare le proprietà di '${unit}'."
#: src/core/dbus-unit.c:711
msgid ""
"Authentication is required to delete files and directories associated with "
"'$(unit)'."
msgstr ""
-"È richiesto autenticarsi per eliminare i file e le directory associate a "
-"«${unit}»."
+"Autenticazione richiesta per eliminare i file e le directory associate a "
+"'${unit}'."
#: src/core/dbus-unit.c:760
msgid ""
"Authentication is required to freeze or thaw the processes of '$(unit)' unit."
msgstr ""
-"È richiesto autenticarsi per bloccare/sbloccare il processo dell'unità "
-"«$(unit)»."
+"Autenticazione richiesta per bloccare/sbloccare il processo dell'unità "
+"'$(unit)'."
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-19 18:02+0200\n"
-"PO-Revision-Date: 2020-05-03 13:50+0200\n"
+"POT-Creation-Date: 2020-09-10 03:33+0000\n"
+"PO-Revision-Date: 2020-10-18 13:10+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
"Language: pl\n"
"przez system."
#: src/login/org.freedesktop.login1.policy:117
+msgid "Allow applications to inhibit system handling of the reboot key"
+msgstr ""
+"Zezwolenie programom na wstrzymanie obsługi klawisza ponownego uruchomienia "
+"przez system"
+
+#: src/login/org.freedesktop.login1.policy:118
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the reboot key."
+msgstr ""
+"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza ponownego "
+"uruchomienia przez system."
+
+#: src/login/org.freedesktop.login1.policy:128
msgid "Allow non-logged-in user to run programs"
msgstr "Zezwolenie niezalogowanemu użytkownikowi na uruchamianie programów"
-#: src/login/org.freedesktop.login1.policy:118
+#: src/login/org.freedesktop.login1.policy:129
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Wymagane jest bezpośrednie żądanie, aby uruchamiać programy jako "
"niezalogowany użytkownik."
-#: src/login/org.freedesktop.login1.policy:127
+#: src/login/org.freedesktop.login1.policy:138
msgid "Allow non-logged-in users to run programs"
msgstr "Zezwolenie niezalogowanym użytkownikom na uruchamianie programów"
-#: src/login/org.freedesktop.login1.policy:128
+#: src/login/org.freedesktop.login1.policy:139
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany "
"użytkownik."
-#: src/login/org.freedesktop.login1.policy:137
+#: src/login/org.freedesktop.login1.policy:148
msgid "Allow attaching devices to seats"
msgstr "Zezwolenie na podłączanie urządzeń do stanowisk"
-#: src/login/org.freedesktop.login1.policy:138
+#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to attach a device to a seat."
msgstr ""
"Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska."
-#: src/login/org.freedesktop.login1.policy:148
+#: src/login/org.freedesktop.login1.policy:159
msgid "Flush device to seat attachments"
msgstr "Usunięcie podłączenia urządzeń do stanowisk"
-#: src/login/org.freedesktop.login1.policy:149
+#: src/login/org.freedesktop.login1.policy:160
msgid "Authentication is required to reset how devices are attached to seats."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia "
"urządzeń do stanowisk."
-#: src/login/org.freedesktop.login1.policy:158
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system"
msgstr "Wyłączenie systemu"
-#: src/login/org.freedesktop.login1.policy:159
+#: src/login/org.freedesktop.login1.policy:170
msgid "Authentication is required to power off the system."
msgstr "Wymagane jest uwierzytelnienie, aby wyłączyć system."
-#: src/login/org.freedesktop.login1.policy:169
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while other users are logged in"
msgstr "Wyłączenie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy:170
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required to power off the system while other users are "
"logged in."
"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy:180
+#: src/login/org.freedesktop.login1.policy:191
msgid "Power off the system while an application is inhibiting this"
msgstr "Wyłączenie systemu, kiedy program je wstrzymuje"
-#: src/login/org.freedesktop.login1.policy:181
+#: src/login/org.freedesktop.login1.policy:192
msgid ""
"Authentication is required to power off the system while an application is "
"inhibiting this."
"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program to "
"wstrzymuje."
-#: src/login/org.freedesktop.login1.policy:191
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system"
msgstr "Ponowne uruchomienie systemu"
-#: src/login/org.freedesktop.login1.policy:192
+#: src/login/org.freedesktop.login1.policy:203
msgid "Authentication is required to reboot the system."
msgstr "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system."
-#: src/login/org.freedesktop.login1.policy:202
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while other users are logged in"
msgstr "Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy:203
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required to reboot the system while other users are logged "
"in."
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są "
"zalogowani inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy:213
+#: src/login/org.freedesktop.login1.policy:224
msgid "Reboot the system while an application is inhibiting this"
msgstr "Ponowne uruchomienie systemu, kiedy program je wstrzymuje"
-#: src/login/org.freedesktop.login1.policy:214
+#: src/login/org.freedesktop.login1.policy:225
msgid ""
"Authentication is required to reboot the system while an application is "
"inhibiting this."
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program "
"to wstrzymuje."
-#: src/login/org.freedesktop.login1.policy:224
+#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system"
msgstr "Zatrzymanie systemu"
-#: src/login/org.freedesktop.login1.policy:225
+#: src/login/org.freedesktop.login1.policy:236
msgid "Authentication is required to halt the system."
msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać system."
-#: src/login/org.freedesktop.login1.policy:235
+#: src/login/org.freedesktop.login1.policy:246
msgid "Halt the system while other users are logged in"
msgstr "Zatrzymanie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy:236
+#: src/login/org.freedesktop.login1.policy:247
msgid ""
"Authentication is required to halt the system while other users are logged "
"in."
"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy:246
+#: src/login/org.freedesktop.login1.policy:257
msgid "Halt the system while an application is inhibiting this"
msgstr "Zatrzymanie systemu, kiedy program je wstrzymuje"
-#: src/login/org.freedesktop.login1.policy:247
+#: src/login/org.freedesktop.login1.policy:258
msgid ""
"Authentication is required to halt the system while an application is "
"inhibiting this."
"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy program to "
"wstrzymuje."
-#: src/login/org.freedesktop.login1.policy:257
+#: src/login/org.freedesktop.login1.policy:268
msgid "Suspend the system"
msgstr "Uśpienie systemu"
-#: src/login/org.freedesktop.login1.policy:258
+#: src/login/org.freedesktop.login1.policy:269
msgid "Authentication is required to suspend the system."
msgstr "Wymagane jest uwierzytelnienie, aby uśpić system."
-#: src/login/org.freedesktop.login1.policy:267
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while other users are logged in"
msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy:268
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required to suspend the system while other users are "
"logged in."
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni "
"użytkownicy."
-#: src/login/org.freedesktop.login1.policy:278
+#: src/login/org.freedesktop.login1.policy:289
msgid "Suspend the system while an application is inhibiting this"
msgstr "Uśpienie systemu, kiedy program je wstrzymuje"
-#: src/login/org.freedesktop.login1.policy:279
+#: src/login/org.freedesktop.login1.policy:290
msgid ""
"Authentication is required to suspend the system while an application is "
"inhibiting this."
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program to "
"wstrzymuje."
-#: src/login/org.freedesktop.login1.policy:289
+#: src/login/org.freedesktop.login1.policy:300
msgid "Hibernate the system"
msgstr "Hibernacja systemu"
-#: src/login/org.freedesktop.login1.policy:290
+#: src/login/org.freedesktop.login1.policy:301
msgid "Authentication is required to hibernate the system."
msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system."
-#: src/login/org.freedesktop.login1.policy:299
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while other users are logged in"
msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy:300
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required to hibernate the system while other users are "
"logged in."
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy:310
+#: src/login/org.freedesktop.login1.policy:321
msgid "Hibernate the system while an application is inhibiting this"
msgstr "Hibernacja systemu, kiedy program ją wstrzymuje"
-#: src/login/org.freedesktop.login1.policy:311
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required to hibernate the system while an application is "
"inhibiting this."
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program to "
"wstrzymuje."
-#: src/login/org.freedesktop.login1.policy:321
+#: src/login/org.freedesktop.login1.policy:332
msgid "Manage active sessions, users and seats"
msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami"
-#: src/login/org.freedesktop.login1.policy:322
+#: src/login/org.freedesktop.login1.policy:333
msgid "Authentication is required to manage active sessions, users and seats."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, "
"użytkownikami i stanowiskami."
-#: src/login/org.freedesktop.login1.policy:331
+#: src/login/org.freedesktop.login1.policy:342
msgid "Lock or unlock active sessions"
msgstr "Zablokowanie lub odblokowanie aktywnych sesji"
-#: src/login/org.freedesktop.login1.policy:332
+#: src/login/org.freedesktop.login1.policy:343
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
-#: src/login/org.freedesktop.login1.policy:341
+#: src/login/org.freedesktop.login1.policy:352
msgid "Set the reboot \"reason\" in the kernel"
msgstr "Ustawienie przyczyny ponownego uruchomienia w jądrze"
-#: src/login/org.freedesktop.login1.policy:342
+#: src/login/org.freedesktop.login1.policy:353
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić przyczynę ponownego uruchomienia "
"w jądrze."
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:363
msgid "Indicate to the firmware to boot to setup interface"
msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień"
-#: src/login/org.freedesktop.login1.policy:353
+#: src/login/org.freedesktop.login1.policy:364
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
"Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że "
"należy uruchomić interfejs ustawień."
-#: src/login/org.freedesktop.login1.policy:363
+#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot to the boot loader menu"
msgstr "Wskazanie programowi startowemu, aby uruchomić jego menu"
-#: src/login/org.freedesktop.login1.policy:364
+#: src/login/org.freedesktop.login1.policy:375
msgid ""
"Authentication is required to indicate to the boot loader to boot to the "
"boot loader menu."
"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy "
"uruchomić jego menu."
-#: src/login/org.freedesktop.login1.policy:374
+#: src/login/org.freedesktop.login1.policy:385
msgid "Indicate to the boot loader to boot a specific entry"
msgstr "Wskazanie programowi startowemu, aby uruchomić podany wpis"
-#: src/login/org.freedesktop.login1.policy:375
+#: src/login/org.freedesktop.login1.policy:386
msgid ""
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy "
"uruchomić podany wpis."
-#: src/login/org.freedesktop.login1.policy:385
+#: src/login/org.freedesktop.login1.policy:396
msgid "Set a wall message"
msgstr "Ustawienie komunikatu wall"
-#: src/login/org.freedesktop.login1.policy:386
+#: src/login/org.freedesktop.login1.policy:397
msgid "Authentication is required to set a wall message"
msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
-#: src/login/org.freedesktop.login1.policy:395
+#: src/login/org.freedesktop.login1.policy:406
msgid "Change Session"
msgstr "Zmiana sesji"
-#: src/login/org.freedesktop.login1.policy:396
+#: src/login/org.freedesktop.login1.policy:407
msgid "Authentication is required to change the virtual terminal."
msgstr "Wymagane jest uwierzytelnienie, aby zmienić terminal wirtualny."
"Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację "
"czasu przez sieć."
-#: src/core/dbus-unit.c:362
+#: src/core/dbus-unit.c:359
msgid "Authentication is required to start '$(unit)'."
msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:363
+#: src/core/dbus-unit.c:360
msgid "Authentication is required to stop '$(unit)'."
msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:364
+#: src/core/dbus-unit.c:361
msgid "Authentication is required to reload '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366
+#: src/core/dbus-unit.c:362 src/core/dbus-unit.c:363
msgid "Authentication is required to restart '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:538
+#: src/core/dbus-unit.c:535
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
"Wymagane jest uwierzytelnienie, aby wysłać sygnał uniksowy do procesów "
"jednostki „$(unit)”."
-#: src/core/dbus-unit.c:569
+#: src/core/dbus-unit.c:566
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) "
"jednostki „$(unit)”."
-#: src/core/dbus-unit.c:602
+#: src/core/dbus-unit.c:599
msgid "Authentication is required to set properties on '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”."
-#: src/core/dbus-unit.c:711
+#: src/core/dbus-unit.c:708
msgid ""
"Authentication is required to delete files and directories associated with "
"'$(unit)'."
"Wymagane jest uwierzytelnienie, aby usunąć pliki i katalogi powiązane "
"z jednostką „$(unit)”."
-#: src/core/dbus-unit.c:760
+#: src/core/dbus-unit.c:757
msgid ""
"Authentication is required to freeze or thaw the processes of '$(unit)' unit."
msgstr ""
disable systemd-time-wait-sync.service
disable systemd-boot-check-no-failures.service
disable systemd-network-generator.service
+disable proc-sys-fs-binfmt_misc.mount
disable syslog.socket
IMPORT{builtin}="path_id"
-ACTION!="add", GOTO="net_setup_link_end"
+ACTION=="remove", GOTO="net_setup_link_end"
IMPORT{builtin}="net_setup_link"
# http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n955
SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name"
-SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k"
+SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k", \
+ ENV{SYSTEMD_WANTS}+="bluetooth.target", ENV{SYSTEMD_USER_WANTS}+="bluetooth.target"
-SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target", ENV{SYSTEMD_USER_WANTS}+="bluetooth.target"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0b????:*", ENV{ID_SMARTCARD_READER}="1"
ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target", ENV{SYSTEMD_USER_WANTS}+="smartcard.target"
SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target", ENV{SYSTEMD_USER_WANTS}+="sound.target"
UBUNTU_RELEASE="$(lsb_release -cs)"
create_container() {
- # create autopkgtest LXC image; this sometimes fails with "Unable to fetch
- # GPG key from keyserver", so retry a few times
- for retry in {1..5}; do
- sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH --keyserver hkp://keyserver.ubuntu.com:80 && break
- sleep $((retry*retry))
+ # Create autopkgtest LXC image; this sometimes fails with "Unable to fetch
+ # GPG key from keyserver", so retry a few times with different keyservers.
+ for keyserver in "" "keys.gnupg.net" "keys.openpgp.org" "keyserver.ubuntu.com"; do
+ for retry in {1..5}; do
+ sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH --server us.images.linuxcontainers.org ${keyserver:+--keyserver "$keyserver"} && break 2
+ sleep $((retry*retry))
+ done
done
# unconfine the container, otherwise some tests fail
['systemd-cgtop', ''],
['systemd-delta', ''],
['systemd-detect-virt', ''],
+ ['systemd-id128', ''],
['systemd-nspawn', ''],
['systemd-path', ''],
['systemd-run', ''],
[bash_systemctl, ''],
['bootctl', 'ENABLE_EFI'],
['coredumpctl', 'ENABLE_COREDUMP'],
+ ['homectl', 'ENABLE_HOMED'],
['hostnamectl', 'ENABLE_HOSTNAMED'],
['localectl', 'ENABLE_LOCALED'],
['loginctl', 'ENABLE_LOGIND'],
_loginctl_$fun() {
local -a _sys_all_sessions{,_descr}
+ _sys_all_sessions=( "self" )
+ _sys_all_sessions_descr=( "self:alias for the current session" )
+
_loginctl_all_sessions
for _ignore in $words[2,-1]; do
_sys_all_sessions[(i)$_ignore]=()
_loginctl_seats() {
local -a _sys_all_seats{,_descr}
+ _sys_all_seats=( "self" )
+ _sys_all_seats_descr=( "self:alias for the current seat" )
+
_loginctl_all_seats
for _ignore in $words[2,-1]; do
_sys_all_seats[(i)$_ignore]=()
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name '%s': %m", *i);
- if (!endswith(mangled, ".service")) {
- log_error("Unit %s is not a service unit, refusing.", *i);
- return -EINVAL;
- }
+ if (!endswith(mangled, ".service"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unit %s is not a service unit, refusing.",
+ *i);
if (unit_name_is_valid(mangled, UNIT_NAME_TEMPLATE)) {
r = unit_name_replace_instance(mangled, "test-instance", &instance);
}
}
- *ret = expanded_patterns;
- expanded_patterns = NULL; /* do not free */
+ *ret = TAKE_PTR(expanded_patterns); /* do not free */
return 0;
}
return 0;
}
-static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) {
+static void syscall_set_remove(Set *s, const SyscallFilterSet *set) {
const char *syscall;
NULSTR_FOREACH(syscall, set->value) {
(void) pager_open(arg_pager_flags);
if (strv_isempty(strv_skip(argv, 1))) {
- _cleanup_set_free_ Set *kernel = NULL;
+ _cleanup_set_free_ Set *kernel = NULL, *known = NULL;
+ const char *sys;
int i, k;
+ NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
+ if (set_put_strdup(&known, sys) < 0)
+ return log_oom();
+
k = load_kernel_syscalls(&kernel);
for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
puts("");
dump_syscall_filter(set);
- kernel_syscalls_remove(kernel, set);
+ syscall_set_remove(kernel, set);
+ if (i != SYSCALL_FILTER_SET_KNOWN)
+ syscall_set_remove(known, set);
first = false;
}
+ if (!set_isempty(known)) {
+ _cleanup_free_ char **l = NULL;
+ char **syscall;
+
+ printf("\n"
+ "# %sUngrouped System Calls%s (known but not included in any of the groups except @known):\n",
+ ansi_highlight(), ansi_normal());
+
+ l = set_get_strv(known);
+ if (!l)
+ return log_oom();
+
+ strv_sort(l);
+
+ STRV_FOREACH(syscall, l)
+ printf("# %s\n", *syscall);
+ }
+
if (k < 0) {
fputc('\n', stdout);
fflush(stdout);
size_t _n_ = n; \
assert(!size_multiply_overflow(sizeof(t), _n_)); \
assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
- (t*) alloca(sizeof(t)*_n_); \
+ (t*) alloca((sizeof(t)*_n_) ?: 1); \
})
#define newa0(t, n) \
size_t _n_ = n; \
assert(!size_multiply_overflow(sizeof(t), _n_)); \
assert(sizeof(t)*_n_ <= ALLOCA_MAX); \
- (t*) alloca0(sizeof(t)*_n_); \
+ (t*) alloca0((sizeof(t)*_n_) ?: 1); \
})
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
-#define malloc0(n) (calloc(1, (n)))
+#define malloc0(n) (calloc(1, (n) ?: 1))
static inline void *mfree(void *memory) {
free(memory);
void *_q_; \
size_t _l_ = l; \
assert(_l_ <= ALLOCA_MAX); \
- _q_ = alloca(_l_); \
+ _q_ = alloca(_l_ ?: 1); \
memcpy(_q_, p, _l_); \
})
char *_new_; \
size_t _len_ = n; \
assert(_len_ <= ALLOCA_MAX); \
- _new_ = alloca(_len_); \
+ _new_ = alloca(_len_ ?: 1); \
(void *) memset(_new_, 0, _len_); \
})
size_t _mask_ = (align) - 1; \
size_t _size_ = size; \
assert(_size_ <= ALLOCA_MAX); \
- _ptr_ = alloca(_size_ + _mask_); \
+ _ptr_ = alloca((_size_ + _mask_) ?: 1); \
(void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
})
}
for (j = 0; j < n_old_parent_qgroups; j++)
- if (old_parent_qgroups[j] == old_qgroups[i]) {
+ if (old_parent_qgroups[j] == old_qgroups[i])
/* The old subvolume shared a common
* parent qgroup with its parent
* subvolume. Let's set up something
* similar in the destination. */
copy_from_parent = true;
- }
}
if (!insert_intermediary_qgroup && !copy_from_parent)
_IDN_FEATURE_ " " \
_PCRE2_FEATURE_ " " \
_CGROUP_HIERARCHY_
+
+enum {
+ BUILD_MODE_DEVELOPER,
+ BUILD_MODE_RELEASE,
+};
return 0;
}
+int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute, bool *ret) {
+ _cleanup_free_ char *value = NULL;
+ int r;
+
+ assert(ret);
+
+ r = cg_get_attribute(controller, path, attribute, &value);
+ if (r == -ENOENT)
+ return -ENODATA;
+ if (r < 0)
+ return r;
+
+ r = parse_boolean(value);
+ if (r < 0)
+ return r;
+
+ *ret = r;
+ return 0;
+}
+
int cg_get_keyed_attribute_full(
const char *controller,
const char *path,
bool cpu_accounting_is_cheap(void) {
return get_cpu_accounting_mask() == 0;
}
+
+static const char* const managed_oom_mode_table[_MANAGED_OOM_MODE_MAX] = {
+ [MANAGED_OOM_AUTO] = "auto",
+ [MANAGED_OOM_KILL] = "kill",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(managed_oom_mode, ManagedOOMMode);
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret);
+/* Does a parse_boolean() on the attribute contents and sets ret accordingly */
+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_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
bool is_cgroup_fs(const struct statfs *s);
bool fd_is_cgroup_fs(int fd);
+
+typedef enum ManagedOOMMode {
+ MANAGED_OOM_AUTO,
+ MANAGED_OOM_KILL,
+ _MANAGED_OOM_MODE_MAX,
+ _MANAGED_OOM_MODE_INVALID = -1,
+} ManagedOOMMode;
+
+const char* managed_oom_mode_to_string(ManagedOOMMode m) _const_;
+ManagedOOMMode managed_oom_mode_from_string(const char *s) _pure_;
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
.un.sun_family = AF_UNIX, \
.un.sun_path = "\0/org/freedesktop/plymouthd", \
}
+
+#define VARLINK_ADDR_PATH_MANAGED_OOM "/run/systemd/io.system.ManagedOOM"
#include "strv.h"
#include "utf8.h"
-#define VALID_CHARS_ENV_NAME \
+/* We follow bash for the character set. Different shells have different rules. */
+#define VALID_BASH_ENV_NAME_CHARS \
DIGITS LETTERS \
"_"
-static bool env_name_is_valid_n(const char *e, size_t n) {
- const char *p;
+static bool printable_portable_character(char c) {
+ /* POSIX.1-2008 specifies almost all ASCII characters as "portable". (Only DEL is excluded, and
+ * additionally NUL and = are not allowed in variable names). We are stricter, and additionally
+ * reject BEL, BS, HT, CR, LF, VT, FF and SPACE, i.e. all whitespace. */
+
+ return c >= '!' && c <= '~';
+}
+static bool env_name_is_valid_n(const char *e, size_t n) {
if (!e)
return false;
if (n <= 0)
return false;
- if (e[0] >= '0' && e[0] <= '9')
- return false;
-
/* POSIX says the overall size of the environment block cannot
* be > ARG_MAX, an individual assignment hence cannot be
* either. Discounting the equal sign and trailing NUL this
if (n > (size_t) sysconf(_SC_ARG_MAX) - 2)
return false;
- for (p = e; p < e + n; p++)
- if (!strchr(VALID_CHARS_ENV_NAME, *p))
+ for (const char *p = e; p < e + n; p++)
+ if (!printable_portable_character(*p) || *p == '=')
return false;
return true;
word = e+1;
state = WORD;
- } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_CHARS_ENV_NAME, *e)) {
+ } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_BASH_ENV_NAME_CHARS, *e)) {
k = strnappend(r, word, e-word-1);
if (!k)
return NULL;
case VARIABLE_RAW:
assert(flags & REPLACE_ENV_ALLOW_BRACELESS);
- if (!strchr(VALID_CHARS_ENV_NAME, *e)) {
+ if (!strchr(VALID_BASH_ENV_NAME_CHARS, *e)) {
const char *t;
t = strv_env_get_n(env, word+1, e-word-1, flags);
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
+#include "sort-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "tmpfile-util.h"
return (int) (m - 1);
}
+static int cmp_int(const int *a, const int *b) {
+ return CMP(*a, *b);
+}
+
int close_all_fds(const int except[], size_t n_except) {
+ static bool have_close_range = true; /* Assume we live in the future */
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
assert(n_except == 0 || except);
+ if (have_close_range) {
+ /* In the best case we have close_range() to close all fds between a start and an end fd,
+ * which we can use on the "inverted" exception array, i.e. all intervals between all
+ * adjacent pairs from the sorted exception array. This changes loop complexity from O(n)
+ * where n is number of open fds to O(m⋅log(m)) where m is the number of fds to keep
+ * open. Given that we assume n ≫ m that's preferable to us. */
+
+ if (n_except == 0) {
+ /* Close everything. Yay! */
+
+ if (close_range(3, -1, 0) >= 0)
+ return 1;
+
+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
+ return -errno;
+
+ have_close_range = false;
+ } else {
+ _cleanup_free_ int *sorted_malloc = NULL;
+ size_t n_sorted;
+ int *sorted;
+
+ assert(n_except < SIZE_MAX);
+ n_sorted = n_except + 1;
+
+ if (n_sorted > 64) /* Use heap for large numbers of fds, stack otherwise */
+ sorted = sorted_malloc = new(int, n_sorted);
+ else
+ sorted = newa(int, n_sorted);
+
+ if (sorted) {
+ int c = 0;
+
+ memcpy(sorted, except, n_except * sizeof(int));
+
+ /* Let's add fd 2 to the list of fds, to simplify the loop below, as this
+ * allows us to cover the head of the array the same way as the body */
+ sorted[n_sorted-1] = 2;
+
+ typesafe_qsort(sorted, n_sorted, cmp_int);
+
+ for (size_t i = 0; i < n_sorted-1; i++) {
+ int start, end;
+
+ start = MAX(sorted[i], 2); /* The first three fds shall always remain open */
+ end = MAX(sorted[i+1], 2);
+
+ assert(end >= start);
+
+ if (end - start <= 1)
+ continue;
+
+ /* Close everything between the start and end fds (both of which shall stay open) */
+ if (close_range(start + 1, end - 1, 0) < 0) {
+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
+ return -errno;
+
+ have_close_range = false;
+ break;
+ }
+
+ c += end - start - 1;
+ }
+
+ if (have_close_range) {
+ /* The loop succeeded. Let's now close everything beyond the end */
+
+ if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
+ return c;
+
+ if (close_range(sorted[n_sorted-1] + 1, -1, 0) >= 0)
+ return c + 1;
+
+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
+ return -errno;
+
+ have_close_range = false;
+ }
+ }
+ }
+
+ /* Fallback on OOM or if close_range() is not supported */
+ }
+
d = opendir("/proc/self/fd");
if (!d) {
int fd, max_fd;
/* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY |
(FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
- (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0),
+ (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
+ (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0),
(FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666));
if (fd < 0) {
r = -errno;
return search_and_fopen_internal(path, mode, root, s, _f);
}
+int chase_symlinks_and_fopen_unlocked(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ const char *open_flags,
+ FILE **ret_file,
+ char **ret_path) {
+
+ _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *final_path = NULL;
+ int mode_flags, r;
+ FILE *f;
+
+ assert(path);
+ assert(open_flags);
+ assert(ret_file);
+
+ mode_flags = mode_to_flags(open_flags);
+ if (mode_flags < 0)
+ return mode_flags;
+
+ fd = chase_symlinks_and_open(path, root, chase_flags, mode_flags, ret_path ? &final_path : NULL);
+ if (fd < 0)
+ return fd;
+
+ r = fdopen_unlocked(fd, open_flags, &f);
+ if (r < 0)
+ return r;
+ TAKE_FD(fd);
+
+ *ret_file = f;
+ if (ret_path)
+ *ret_path = TAKE_PTR(final_path);
+ return 0;
+}
+
int fflush_and_check(FILE *f) {
assert(f);
typedef enum {
WRITE_STRING_FILE_CREATE = 1 << 0,
- WRITE_STRING_FILE_ATOMIC = 1 << 1,
- WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 2,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3,
- WRITE_STRING_FILE_SYNC = 1 << 4,
- WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
- WRITE_STRING_FILE_NOFOLLOW = 1 << 6,
- WRITE_STRING_FILE_MKDIR_0755 = 1 << 7,
- WRITE_STRING_FILE_MODE_0600 = 1 << 8,
+ WRITE_STRING_FILE_TRUNCATE = 1 << 1,
+ WRITE_STRING_FILE_ATOMIC = 1 << 2,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 3,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 4,
+ WRITE_STRING_FILE_SYNC = 1 << 5,
+ WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 6,
+ WRITE_STRING_FILE_NOFOLLOW = 1 << 7,
+ WRITE_STRING_FILE_MKDIR_0755 = 1 << 8,
+ WRITE_STRING_FILE_MODE_0600 = 1 << 9,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
+int chase_symlinks_and_fopen_unlocked(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ const char *open_flags,
+ FILE **ret_file,
+ char **ret_path);
+
int fflush_and_check(FILE *f);
int fflush_sync_and_check(FILE *f);
FORMAT_BYTES_TRAILING_B = 1 << 2,
} FormatBytesFlag;
-#define FORMAT_BYTES_MAX 16
+#define FORMAT_BYTES_MAX 16U
+
char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag);
+
static inline char *format_bytes(char *buf, size_t l, uint64_t t) {
return format_bytes_full(buf, l, t, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_BELOW_POINT | FORMAT_BYTES_TRAILING_B);
}
+
static inline char *format_bytes_cgroup_protection(char *buf, size_t l, uint64_t t) {
if (t == CGROUP_LIMIT_MAX) {
(void) snprintf(buf, l, "%s", "infinity");
return 0;
}
+int futimens_opath(int fd, const struct timespec ts[2]) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* Similar to fchmod_path() but for futimens() */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (utimensat(AT_FDCWD, procfs_path, ts, 0) < 0) {
+ if (errno != ENOENT)
+ return -errno;
+
+ if (proc_mounted() == 0)
+ return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
+
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
int stat_warn_permissions(const char *path, const struct stat *st) {
assert(path);
assert(st);
int fchmod_umask(int fd, mode_t mode);
int fchmod_opath(int fd, mode_t m);
+int futimens_opath(int fd, const struct timespec ts[2]);
+
int fd_warn_permissions(const char *path, int fd);
int stat_warn_permissions(const char *path, const struct stat *st);
CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */
CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */
- CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */
+ CHASE_SAFE = 1 << 3, /* Return -EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */
CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */
CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most component. With ret_fd, when the path's
.compare = trivial_compare_func,
};
+const struct hash_ops trivial_hash_ops_free = {
+ .hash = trivial_hash_func,
+ .compare = trivial_compare_func,
+ .free_key = free,
+};
+
+const struct hash_ops trivial_hash_ops_free_free = {
+ .hash = trivial_hash_func,
+ .compare = trivial_compare_func,
+ .free_key = free,
+ .free_value = free,
+};
+
void uint64_hash_func(const uint64_t *p, struct siphash *state) {
siphash24_compress(p, sizeof(uint64_t), state);
}
void trivial_hash_func(const void *p, struct siphash *state);
int trivial_compare_func(const void *a, const void *b) _const_;
extern const struct hash_ops trivial_hash_ops;
+extern const struct hash_ops trivial_hash_ops_free;
+extern const struct hash_ops trivial_hash_ops_free_free;
/* 32bit values we can always just embed in the pointer itself, but in order to support 32bit archs we need store 64bit
* values indirectly, since they don't fit in a pointer. */
return r;
}
-int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS) {
+int _hashmap_put_strdup_full(Hashmap **h, const struct hash_ops *hash_ops, const char *k, const char *v HASHMAP_DEBUG_PARAMS) {
int r;
- r = _hashmap_ensure_allocated(h, &string_hash_ops_free_free HASHMAP_DEBUG_PASS_ARGS);
+ r = _hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
return r;
}
-int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS) {
+int _set_put_strdup_full(Set **s, const struct hash_ops *hash_ops, const char *p HASHMAP_DEBUG_PARAMS) {
char *c;
int r;
assert(s);
assert(p);
- r = _set_ensure_allocated(s, &string_hash_ops_free HASHMAP_DEBUG_PASS_ARGS);
+ r = _set_ensure_allocated(s, hash_ops HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
return set_consume(*s, c);
}
-int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS) {
+int _set_put_strdupv_full(Set **s, const struct hash_ops *hash_ops, char **l HASHMAP_DEBUG_PARAMS) {
int n = 0, r;
char **i;
assert(s);
STRV_FOREACH(i, l) {
- r = _set_put_strdup(s, *i HASHMAP_DEBUG_PASS_ARGS);
+ r = _set_put_strdup_full(s, hash_ops, *i HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
return hashmap_put(PLAIN_HASHMAP(h), key, value);
}
-int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS);
-#define hashmap_put_strdup(h, k, v) _hashmap_put_strdup(h, k, v HASHMAP_DEBUG_SRC_ARGS)
+int _hashmap_put_strdup_full(Hashmap **h, const struct hash_ops *hash_ops, const char *k, const char *v HASHMAP_DEBUG_PARAMS);
+#define hashmap_put_strdup_full(h, hash_ops, k, v) _hashmap_put_strdup_full(h, hash_ops, k, v HASHMAP_DEBUG_SRC_ARGS)
+#define hashmap_put_strdup(h, k, v) hashmap_put_strdup_full(h, &string_hash_ops_free_free, k, v)
int hashmap_update(Hashmap *h, const void *key, void *value);
static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
/* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */
(void) send(h->fd, NULL, 0, 0);
- *ret = h;
- h = NULL;
+ *ret = TAKE_PTR(h);
return 0;
}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _UAPI_LINUX_IPV6_ROUTE_H
+#define _UAPI_LINUX_IPV6_ROUTE_H
+
+#include <linux/types.h>
+#include <linux/in6.h> /* For struct in6_addr. */
+
+#define RTF_DEFAULT 0x00010000 /* default - learned via ND */
+#define RTF_ALLONLINK 0x00020000 /* (deprecated and will be removed)
+ fallback, no routers on link */
+#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
+#define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */
+#define RTF_ANYCAST 0x00100000 /* Anycast */
+
+#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
+#define RTF_EXPIRES 0x00400000
+
+#define RTF_ROUTEINFO 0x00800000 /* route information - RA */
+
+#define RTF_CACHE 0x01000000 /* read-only: can not be set by user */
+#define RTF_FLOW 0x02000000 /* flow significant route */
+#define RTF_POLICY 0x04000000 /* policy route */
+
+#define RTF_PREF(pref) ((pref) << 27)
+#define RTF_PREF_MASK 0x18000000
+
+#define RTF_PCPU 0x40000000 /* read-only: can not be set by user */
+#define RTF_LOCAL 0x80000000
+
+
+struct in6_rtmsg {
+ struct in6_addr rtmsg_dst;
+ struct in6_addr rtmsg_src;
+ struct in6_addr rtmsg_gateway;
+ __u32 rtmsg_type;
+ __u16 rtmsg_dst_len;
+ __u16 rtmsg_src_len;
+ __u32 rtmsg_metric;
+ unsigned long rtmsg_info;
+ __u32 rtmsg_flags;
+ int rtmsg_ifindex;
+};
+
+#define RTMSG_NEWDEVICE 0x11
+#define RTMSG_DELDEVICE 0x12
+#define RTMSG_NEWROUTE 0x21
+#define RTMSG_DELROUTE 0x22
+
+#define IP6_RT_PRIO_USER 1024
+#define IP6_RT_PRIO_ADDRCONF 256
+
+#endif /* _UAPI_LINUX_IPV6_ROUTE_H */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_SCHED_LOADAVG_H
+#define _LINUX_SCHED_LOADAVG_H
+
+/*
+ * These are the constant used to fake the fixed-point load-average
+ * counting. Some notes:
+ * - 11 bit fractions expand to 22 bits by the multiplies: this gives
+ * a load-average precision of 10 bits integer + 11 bits fractional
+ * - if you want to count load-averages more often, you need more
+ * precision, or rounding will get you. With 2-second counting freq,
+ * the EXP_n values would be 1981, 2034 and 2043 if still using only
+ * 11 bit fractions.
+ */
+extern unsigned long avenrun[]; /* Load averages */
+extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift);
+
+#define FSHIFT 11 /* nr of bits of precision */
+#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
+#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */
+#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */
+#define EXP_5 2014 /* 1/exp(5sec/5min) */
+#define EXP_15 2037 /* 1/exp(5sec/15min) */
+
+/*
+ * a1 = a0 * e + a * (1 - e)
+ */
+static inline unsigned long
+calc_load(unsigned long load, unsigned long exp, unsigned long active)
+{
+ unsigned long newload;
+
+ newload = load * exp + active * (FIXED_1 - exp);
+ if (active >= load)
+ newload += FIXED_1-1;
+
+ return newload / FIXED_1;
+}
+
+extern unsigned long calc_load_n(unsigned long load, unsigned long exp,
+ unsigned long active, unsigned int n);
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+extern void calc_global_load(unsigned long ticks);
+
+#endif /* _LINUX_SCHED_LOADAVG_H */
#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "missing_syscall.h"
#include "parse-util.h"
#include "proc-cmdline.h"
#include "process-util.h"
static bool show_color = false;
static bool show_location = false;
static bool show_time = false;
+static bool show_tid = false;
static bool upgrade_syslog_to_journal = false;
static bool always_reopen_console = false;
return 0;
}
- if (log_target != LOG_TARGET_AUTO || getpid_cached() == 1 || stderr_is_journal()) {
-
- if (!prohibit_ipc &&
- IN_SET(log_target, LOG_TARGET_AUTO,
- LOG_TARGET_JOURNAL_OR_KMSG,
- LOG_TARGET_JOURNAL)) {
- r = log_open_journal();
- if (r >= 0) {
- log_close_syslog();
- log_close_console();
- return r;
+ if (getpid_cached() == 1 ||
+ stderr_is_journal() ||
+ IN_SET(log_target,
+ LOG_TARGET_KMSG,
+ LOG_TARGET_JOURNAL,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_SYSLOG,
+ LOG_TARGET_SYSLOG_OR_KMSG)) {
+
+ if (!prohibit_ipc) {
+ if (IN_SET(log_target,
+ LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL)) {
+
+ r = log_open_journal();
+ if (r >= 0) {
+ log_close_syslog();
+ log_close_console();
+ return r;
+ }
}
- }
- if (!prohibit_ipc &&
- IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
- LOG_TARGET_SYSLOG)) {
- r = log_open_syslog();
- if (r >= 0) {
- log_close_journal();
- log_close_console();
- return r;
+ if (IN_SET(log_target,
+ LOG_TARGET_SYSLOG_OR_KMSG,
+ LOG_TARGET_SYSLOG)) {
+
+ r = log_open_syslog();
+ if (r >= 0) {
+ log_close_journal();
+ log_close_console();
+ return r;
+ }
}
}
char location[256],
header_time[FORMAT_TIMESTAMP_MAX],
- prefix[1 + DECIMAL_STR_MAX(int) + 2];
- struct iovec iovec[8] = {};
+ prefix[1 + DECIMAL_STR_MAX(int) + 2],
+ tid_string[3 + DECIMAL_STR_MAX(pid_t) + 1];
+ struct iovec iovec[9];
const char *on = NULL, *off = NULL;
size_t n = 0;
}
}
+ if (show_tid) {
+ xsprintf(tid_string, "(" PID_FMT ") ", gettid());
+ iovec[n++] = IOVEC_MAKE_STRING(tid_string);
+ }
+
if (show_color)
get_log_colors(LOG_PRI(level), &on, &off, NULL);
r = snprintf(header, size,
"PRIORITY=%i\n"
"SYSLOG_FACILITY=%i\n"
+ "TID=" PID_FMT "\n"
"%s%.256s%s" /* CODE_FILE */
"%s%.*i%s" /* CODE_LINE */
"%s%.256s%s" /* CODE_FUNC */
"SYSLOG_IDENTIFIER=%.256s\n",
LOG_PRI(level),
LOG_FAC(level),
+ gettid(),
isempty(file) ? "" : "CODE_FILE=",
isempty(file) ? "" : file,
isempty(file) ? "" : "\n",
if (log_show_location_from_string(value ?: "1") < 0)
log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
+ } else if (proc_cmdline_key_streq(key, "systemd.log_tid")) {
+
+ if (log_show_tid_from_string(value ?: "1") < 0)
+ log_warning("Failed to parse log tid setting '%s'. Ignoring.", value);
+
} else if (proc_cmdline_key_streq(key, "systemd.log_time")) {
if (log_show_time_from_string(value ?: "1") < 0)
e = getenv("SYSTEMD_LOG_TIME");
if (e && log_show_time_from_string(e) < 0)
log_warning("Failed to parse log time '%s'. Ignoring.", e);
+
+ e = getenv("SYSTEMD_LOG_TID");
+ if (e && log_show_tid_from_string(e) < 0)
+ log_warning("Failed to parse log tid '%s'. Ignoring.", e);
}
LogTarget log_get_target(void) {
return show_time;
}
+void log_show_tid(bool b) {
+ show_tid = b;
+}
+
+bool log_get_show_tid(void) {
+ return show_tid;
+}
+
int log_show_color_from_string(const char *e) {
int t;
return 0;
}
+int log_show_tid_from_string(const char *e) {
+ int t;
+
+ t = parse_boolean(e);
+ if (t < 0)
+ return t;
+
+ log_show_tid(t);
+ return 0;
+}
+
bool log_on_console(void) {
if (IN_SET(log_target, LOG_TARGET_CONSOLE,
LOG_TARGET_CONSOLE_PREFIXED))
LOG_TARGET_JOURNAL_OR_KMSG,
LOG_TARGET_SYSLOG,
LOG_TARGET_SYSLOG_OR_KMSG,
- LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
+ LOG_TARGET_AUTO, /* console if stderr is not journal, JOURNAL_OR_KMSG otherwise */
LOG_TARGET_NULL,
_LOG_TARGET_MAX,
_LOG_TARGET_INVALID = -1
bool log_get_show_location(void) _pure_;
void log_show_time(bool b);
bool log_get_show_time(void) _pure_;
+void log_show_tid(bool b);
+bool log_get_show_tid(void) _pure_;
int log_show_color_from_string(const char *e);
int log_show_location_from_string(const char *e);
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_;
#endif
/* Temporarily disable some warnings */
+#define DISABLE_WARNING_DEPRECATED_DECLARATIONS \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+
#define DISABLE_WARNING_FORMAT_NONLITERAL \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
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) \
#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
#define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+#define PTR_TO_UINT8(p) ((uint8_t) ((uintptr_t) (p)))
+#define UINT8_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+
#define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
#define INT32_TO_PTR(u) ((void *) ((intptr_t) (u)))
#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
-/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
-#define FOREACH_POINTER(p, x, ...) \
- for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \
- p != (typeof(p)) (void*) -1; \
+/* Pointers range from NULL to POINTER_MAX */
+#define POINTER_MAX ((void*) UINTPTR_MAX)
+
+/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses POINTER_MAX as internal marker for EOL. */
+#define FOREACH_POINTER(p, x, ...) \
+ for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, POINTER_MAX }; \
+ p != (typeof(p)) POINTER_MAX; \
p = *(++_l))
/* Define C11 thread_local attribute even on older gcc compiler
_copy; \
})
+static inline size_t size_add(size_t x, size_t y) {
+ return y >= SIZE_MAX - x ? SIZE_MAX : x + y;
+}
+
#include "log.h"
limits-util.h
linux/btrfs.h
linux/btrfs_tree.h
+ linux/can/netlink.h
linux/can/vxcan.h
linux/fib_rules.h
linux/fou.h
+ linux/hdlc/ioctl.h
linux/if.h
linux/if_addr.h
linux/if_arp.h
linux/if_tunnel.h
linux/in.h
linux/in6.h
+ linux/ipv6_route.h
linux/l2tp.h
linux/libc-compat.h
+ linux/loadavg.h
linux/netdevice.h
linux/netlink.h
linux/rtnetlink.h
dependencies : [versiondep,
threads,
libcap,
+ libseccomp,
libselinux,
libm,
libdl],
#ifdef CAP_LAST_CAP
# if CAP_LAST_CAP > SYSTEMD_CAP_LAST_CAP
-# if DEVELOPER_MODE && defined(TEST_CAPABILITY_C)
+# if BUILD_MODE == BUILD_MODE_DEVELOPER && defined(TEST_CAPABILITY_C)
# warning "The capability list here is outdated"
# endif
# else
#include <asm/sgidefs.h>
#endif
+#if defined(__x86_64__) && defined(__ILP32__)
+#define systemd_SC_arch_bias(x) ((x) | /* __X32_SYSCALL_BIT */ 0x40000000)
+#else
+#define systemd_SC_arch_bias(x) (x)
+#endif
+
#include "missing_keyctl.h"
#include "missing_stat.h"
/* ======================================================================= */
#if defined __x86_64__
-# define systemd_NR_memfd_create 319
+# define systemd_NR_memfd_create systemd_SC_arch_bias(319)
#elif defined __arm__
# define systemd_NR_memfd_create 385
#elif defined __aarch64__
/* ======================================================================= */
#if defined __x86_64__
-# define systemd_NR_getrandom 318
+# define systemd_NR_getrandom systemd_SC_arch_bias(318)
#elif defined(__i386__)
# define systemd_NR_getrandom 355
#elif defined(__arm__)
/* ======================================================================= */
#if defined(__x86_64__)
-# define systemd_NR_name_to_handle_at 303
+# define systemd_NR_name_to_handle_at systemd_SC_arch_bias(303)
#elif defined(__i386__)
# define systemd_NR_name_to_handle_at 341
#elif defined(__arm__)
#elif defined __arm__
# define systemd_NR_setns 375
#elif defined(__x86_64__)
-# define systemd_NR_setns 308
+# define systemd_NR_setns systemd_SC_arch_bias(308)
#elif defined(__i386__)
# define systemd_NR_setns 346
#elif defined(__powerpc__)
/* ======================================================================= */
#if defined __x86_64__
-# define systemd_NR_renameat2 316
+# define systemd_NR_renameat2 systemd_SC_arch_bias(316)
#elif defined __arm__
# define systemd_NR_renameat2 382
#elif defined __aarch64__
/* ======================================================================= */
#if defined(__x86_64__)
-# define systemd_NR_copy_file_range 326
+# define systemd_NR_copy_file_range systemd_SC_arch_bias(326)
#elif defined(__i386__)
# define systemd_NR_copy_file_range 377
#elif defined __s390__
#if defined __i386__
# define systemd_NR_bpf 357
#elif defined __x86_64__
-# define systemd_NR_bpf 321
+# define systemd_NR_bpf systemd_SC_arch_bias(321)
#elif defined __aarch64__
# define systemd_NR_bpf 280
#elif defined __arm__
# if defined __i386__
# define systemd_NR_pkey_mprotect 380
# elif defined __x86_64__
-# define systemd_NR_pkey_mprotect 329
+# define systemd_NR_pkey_mprotect systemd_SC_arch_bias(329)
# elif defined __aarch64__
# define systemd_NR_pkey_mprotect 288
# elif defined __arm__
#elif defined __sparc__
# define systemd_NR_statx 360
#elif defined __x86_64__
-# define systemd_NR_statx 332
+# define systemd_NR_statx systemd_SC_arch_bias(332)
#else
# warning "statx() syscall number unknown for your architecture"
#endif
/* ======================================================================= */
/* should be always defined, see kernel 39036cd2727395c3369b1051005da74059a85317 */
-#if defined(__alpha__)
+#if defined __alpha__
# define systemd_NR_pidfd_send_signal 534
+#elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
+# define systemd_NR_pidfd_send_signal (424 + 4000)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
+# define systemd_NR_pidfd_send_signal (424 + 6000)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
+# define systemd_NR_pidfd_send_signal (424 + 5000)
+# endif
+#elif defined __ia64__
+# define systemd_NR_pidfd_send_signal (424 + 1024)
#else
-# define systemd_NR_pidfd_send_signal 424
+# define systemd_NR_pidfd_send_signal systemd_SC_arch_bias(424)
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
#if !HAVE_PIDFD_SEND_SIGNAL
static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) {
-# ifdef __NR_pidfd_open
+# ifdef __NR_pidfd_send_signal
return syscall(__NR_pidfd_send_signal, fd, sig, info, flags);
# else
errno = ENOSYS;
#endif
/* should be always defined, see kernel 7615d9e1780e26e0178c93c55b73309a5dc093d7 */
-#if defined(__alpha__)
+#if defined __alpha__
# define systemd_NR_pidfd_open 544
+#elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
+# define systemd_NR_pidfd_open (434 + 4000)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
+# define systemd_NR_pidfd_open (434 + 6000)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
+# define systemd_NR_pidfd_open (434 + 5000)
+# endif
+#elif defined __ia64__
+# define systemd_NR_pidfd_open (434 + 1024)
#else
-# define systemd_NR_pidfd_open 434
+# define systemd_NR_pidfd_open systemd_SC_arch_bias(434)
#endif
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# define rt_sigqueueinfo missing_rt_sigqueueinfo
#endif
+
+/* ======================================================================= */
+
+#define systemd_NR_close_range systemd_SC_arch_bias(436)
+
+/* may be (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);
+# endif
+#else
+# if defined __NR_close_range
+# undef __NR_close_range
+# endif
+# if defined systemd_NR_close_range
+# define __NR_close_range systemd_NR_close_range
+# endif
+#endif
+
+#if !HAVE_CLOSE_RANGE
+static inline int missing_close_range(int first_fd, int end_fd, unsigned flags) {
+# ifdef __NR_close_range
+ /* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while
+ * userspace exclusively uses signed integers for fds. We don't know just yet how glibc is going to
+ * wrap this syscall, but let's assume it's going to be similar to what they do for close(),
+ * i.e. make the same unsigned → signed type change from the raw kernel syscall compared to the
+ * userspace wrapper. There's only one caveat for this: unlike for close() there's the special
+ * UINT_MAX fd value for the 'end_fd' argument. Let's safely map that to -1 here. And let's refuse
+ * any other negative values. */
+ if ((first_fd < 0) || (end_fd < 0 && end_fd != -1)) {
+ errno = -EBADF;
+ return -1;
+ }
+
+ return syscall(__NR_close_range,
+ (unsigned) first_fd,
+ end_fd == -1 ? UINT_MAX : (unsigned) end_fd, /* Of course, the compiler should figure out that this is the identity mapping IRL */
+ flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define close_range missing_close_range
+#endif
*ret = v;
return 0;
}
+
+int store_loadavg_fixed_point(unsigned long i, unsigned long f, loadavg_t *ret) {
+ assert(ret);
+
+ if (i >= (~0UL << FSHIFT))
+ return -ERANGE;
+
+ i = i << FSHIFT;
+ f = DIV_ROUND_UP((f << FSHIFT), 100);
+
+ if (f >= FIXED_1)
+ return -ERANGE;
+
+ *ret = i | f;
+ return 0;
+}
+
+int parse_loadavg_fixed_point(const char *s, loadavg_t *ret) {
+ const char *d, *f_str, *i_str;
+ unsigned long i, f;
+ int r;
+
+ assert(s);
+ assert(ret);
+
+ d = strchr(s, '.');
+ if (!d)
+ return -EINVAL;
+
+ i_str = strndupa(s, d - s);
+ f_str = d + 1;
+
+ r = safe_atolu_full(i_str, 10, &i);
+ if (r < 0)
+ return r;
+
+ r = safe_atolu_full(f_str, 10, &f);
+ if (r < 0)
+ return r;
+
+ return store_loadavg_fixed_point(i, f, ret);
+}
#include <inttypes.h>
#include <limits.h>
+#include <linux/loadavg.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "macro.h"
+typedef unsigned long loadavg_t;
+
int parse_boolean(const char *v) _pure_;
int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
}
#if LONG_MAX == INT_MAX
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
+static inline int safe_atolu_full(const char *s, unsigned base, long unsigned *ret_u) {
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
- return safe_atou(s, (unsigned*) ret_u);
+ return safe_atou_full(s, base, (unsigned*) ret_u);
}
static inline int safe_atoli(const char *s, long int *ret_u) {
assert_cc(sizeof(long int) == sizeof(int));
return safe_atoi(s, (int*) ret_u);
}
#else
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
+static inline int safe_atolu_full(const char *s, unsigned base, unsigned long *ret_u) {
assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
- return safe_atollu(s, (unsigned long long*) ret_u);
+ return safe_atollu_full(s, base, (unsigned long long*) ret_u);
}
static inline int safe_atoli(const char *s, long int *ret_u) {
assert_cc(sizeof(long int) == sizeof(long long int));
}
#endif
+static inline int safe_atolu(const char *s, unsigned long *ret_u) {
+ return safe_atolu_full(s, 0, ret_u);
+}
+
#if SIZE_MAX == UINT_MAX
static inline int safe_atozu(const char *s, size_t *ret_u) {
assert_cc(sizeof(size_t) == sizeof(unsigned));
int parse_ip_prefix_length(const char *s, int *ret);
int parse_oom_score_adjust(const char *s, int *ret);
+
+/* Given a Linux load average (e.g. decimal number 34.89 where 34 is passed as i and 89 is passed as f), convert it
+ * to a loadavg_t. */
+int store_loadavg_fixed_point(unsigned long i, unsigned long f, loadavg_t *ret);
+int parse_loadavg_fixed_point(const char *s, loadavg_t *ret);
if (strv_extend(&res, generator_early) < 0)
return NULL;
- if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
+ if (strv_extend(&res, persistent_config) < 0)
return NULL;
- if (strv_extend(&res, persistent_config) < 0)
+ if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
return NULL;
/* global config has lower priority than the user config of the same type */
sz = strlen_ptr(first);
va_start(ap, first);
- while ((p = va_arg(ap, char*)) != (const char*) -1)
+ while ((p = va_arg(ap, char*)) != POINTER_MAX)
if (!isempty(p))
sz += 1 + strlen(p);
va_end(ap);
}
va_start(ap, first);
- while ((p = va_arg(ap, char*)) != (const char*) -1) {
+ while ((p = va_arg(ap, char*)) != POINTER_MAX) {
if (isempty(p))
continue;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);
char* path_join_internal(const char *first, ...);
-#define path_join(x, ...) path_join_internal(x, __VA_ARGS__, (const char*) -1)
+#define path_join(x, ...) path_join_internal(x, __VA_ARGS__, POINTER_MAX)
char* path_simplify(char *path, bool kill_dots);
assert(r);
- if (r->interval <= 0 || r->burst <= 0)
+ if (!ratelimit_configured(r))
return true;
ts = now(CLOCK_MONOTONIC);
rl->num = rl->begin = 0;
}
+static inline bool ratelimit_configured(RateLimit *rl) {
+ return rl->interval > 0 && rl->burst > 0;
+}
+
bool ratelimit_below(RateLimit *r);
return -errno;
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- if ((st.st_mode & 0700) == 0700) /* Already set? */
+ if (FLAGS_SET(st.st_mode, 0700)) /* Already set? */
return -EACCES; /* original error */
if (st.st_uid != geteuid()) /* this only works if the UID matches ours */
return -EACCES;
}
#if HAVE_SELINUX
+# if HAVE_MALLINFO
+static struct mallinfo mallinfo_nowarn(void) {
+ /* glibc has deprecated mallinfo(), but the replacement malloc_info() returns an XML blob ;=[ */
+DISABLE_WARNING_DEPRECATED_DECLARATIONS
+ return mallinfo();
+REENABLE_WARNING
+}
+# else
+# warning "mallinfo() is missing, add mallinfo2() supported instead."
+# endif
+
static int open_label_db(void) {
struct selabel_handle *hnd;
usec_t before_timestamp, after_timestamp;
- struct mallinfo before_mallinfo, after_mallinfo;
char timespan[FORMAT_TIMESPAN_MAX];
- int l;
- before_mallinfo = mallinfo();
+# if HAVE_MALLINFO
+ struct mallinfo before_mallinfo = mallinfo_nowarn();
+# endif
before_timestamp = now(CLOCK_MONOTONIC);
hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m");
after_timestamp = now(CLOCK_MONOTONIC);
- after_mallinfo = mallinfo();
-
- l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
-
+# if HAVE_MALLINFO
+ struct mallinfo after_mallinfo = mallinfo_nowarn();
+ int l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
- (l+1023)/1024);
+ DIV_ROUND_UP(l, 1024));
+# else
+ log_debug("Successfully loaded SELinux database in %s.",
+ format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0));
+# endif
/* release memory after measurement */
if (label_hnd)
int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFixFlags flags) {
+ assert(path);
+ assert(inside_path);
+
#if HAVE_SELINUX
- char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
- _cleanup_freecon_ char* fcon = NULL;
_cleanup_close_ int fd = -1;
- struct stat st;
- int r;
-
- assert(path);
/* if mac_selinux_init() wasn't called before we are a NOOP */
if (!label_hnd)
return -errno;
}
+ return mac_selinux_fix_container_fd(fd, path, inside_path, flags);
+#endif
+
+ return 0;
+}
+
+int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_path, LabelFixFlags flags) {
+
+ assert(fd >= 0);
+ assert(inside_path);
+
+#if HAVE_SELINUX
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_freecon_ char* fcon = NULL;
+ struct stat st;
+ int r;
+
+ /* if mac_selinux_init() wasn't called before we are a NOOP */
+ if (!label_hnd)
+ return 0;
+
if (fstat(fd, &st) < 0)
return -errno;
mac_selinux_maybe_reload();
if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) < 0) {
- r = -errno;
-
/* If there's no label to set, then exit without warning */
- if (r == -ENOENT)
+ if (errno == ENOENT)
return 0;
+ r = -errno;
goto fail;
}
if (setfilecon_raw(procfs_path, fcon) < 0) {
_cleanup_freecon_ char *oldcon = NULL;
- r = -errno;
-
/* If the FS doesn't support labels, then exit without warning */
- if (r == -EOPNOTSUPP)
+ if (ERRNO_IS_NOT_SUPPORTED(errno))
return 0;
/* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
- if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
+ if (errno == EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
+ r = -errno;
+
/* If the old label is identical to the new one, suppress any kind of error */
if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
return 0;
return 0;
fail:
- return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", path, inside_path);
+ return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", strna(path), strna(inside_path));
#endif
return 0;
int mac_selinux_apply(const char *path, const char *label) {
+ assert(path);
+
#if HAVE_SELINUX
if (!mac_selinux_use())
return 0;
- assert(path);
assert(label);
if (setfilecon(path, label) < 0)
return 0;
}
+int mac_selinux_apply_fd(int fd, const char *path, const char *label) {
+
+ assert(fd >= 0);
+
+#if HAVE_SELINUX
+ if (!mac_selinux_use())
+ return 0;
+
+ assert(label);
+
+ if (fsetfilecon(fd, label) < 0)
+ return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, strna(path));
+#endif
+ return 0;
+}
+
int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
return mac_selinux_fix_container(path, path, flags);
}
+int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_path, LabelFixFlags flags);
+static inline int mac_selinux_fix_fd(int fd, const char *path, LabelFixFlags flags) {
+ return mac_selinux_fix_container_fd(fd, path, path, flags);
+}
+
int mac_selinux_apply(const char *path, const char *label);
+int mac_selinux_apply_fd(int fd, const char *path, const char *label);
int mac_selinux_get_create_label_from_exe(const char *exe, char **label);
int mac_selinux_get_our_label(char **label);
int set_consume(Set *s, void *value);
-int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS);
-#define set_put_strdup(s, p) _set_put_strdup(s, p HASHMAP_DEBUG_SRC_ARGS)
-int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS);
-#define set_put_strdupv(s, l) _set_put_strdupv(s, l HASHMAP_DEBUG_SRC_ARGS)
+int _set_put_strdup_full(Set **s, const struct hash_ops *hash_ops, const char *p HASHMAP_DEBUG_PARAMS);
+#define set_put_strdup_full(s, hash_ops, p) _set_put_strdup_full(s, hash_ops, p HASHMAP_DEBUG_SRC_ARGS)
+#define set_put_strdup(s, p) set_put_strdup_full(s, &string_hash_ops_free, p)
+int _set_put_strdupv_full(Set **s, const struct hash_ops *hash_ops, char **l HASHMAP_DEBUG_PARAMS);
+#define set_put_strdupv_full(s, hash_ops, l) _set_put_strdupv_full(s, hash_ops, l HASHMAP_DEBUG_SRC_ARGS)
+#define set_put_strdupv(s, l) set_put_strdupv_full(s, &string_hash_ops_free, l)
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
if (p)
(void) touch(p);
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
return strcmp_ptr(a, b) == 0;
}
+static inline char* strstr_ptr(const char *haystack, const char *needle) {
+ if (!haystack || !needle)
+ return NULL;
+ return strstr(haystack, needle);
+}
+
static inline const char* strempty(const char *s) {
return s ?: "";
}
return b ? "true" : "false";
}
+static inline const char* plus_minus(bool b) {
+ return b ? "+" : "-";
+}
+
static inline const char* one_zero(bool b) {
return b ? "1" : "0";
}
return (int) n;
}
-char *strv_join_prefix(char * const *l, const char *separator, const char *prefix) {
+char *strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) {
char * const *s;
char *r, *e;
size_t n, k, m;
k = strlen(separator);
m = strlen_ptr(prefix);
+ if (unescape_separators) /* If there separator is multi-char, we won't know how to escape it. */
+ assert(k == 1);
+
n = 0;
STRV_FOREACH(s, l) {
if (s != l)
n += k;
- n += m + strlen(*s);
+
+ bool needs_escaping = unescape_separators && strchr(*s, separator[0]);
+
+ n += m + strlen(*s) * (1 + needs_escaping);
}
r = new(char, n+1);
if (prefix)
e = stpcpy(e, prefix);
- e = stpcpy(e, *s);
+ bool needs_escaping = unescape_separators && strchr(*s, separator[0]);
+
+ if (needs_escaping)
+ for (size_t i = 0; (*s)[i]; i++) {
+ if ((*s)[i] == separator[0])
+ *(e++) = '\\';
+ *(e++) = (*s)[i];
+ }
+ else
+ e = stpcpy(e, *s);
}
*e = 0;
return r;
}
+int strv_prepend(char ***l, const char *value) {
+ char *v;
+
+ if (!value)
+ return 0;
+
+ v = strdup(value);
+ if (!v)
+ return -ENOMEM;
+
+ return strv_consume_prepend(l, v);
+}
+
int strv_extend(char ***l, const char *value) {
char *v;
int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates);
int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix);
+int strv_prepend(char ***l, const char *value);
int strv_extend(char ***l, const char *value);
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_extend_front(char ***l, const char *value);
char **strv_new_ap(const char *x, va_list ap);
#define strv_new(...) strv_new_internal(__VA_ARGS__, NULL)
-#define STRV_IGNORE ((const char *) -1)
+#define STRV_IGNORE ((const char *) POINTER_MAX)
static inline const char* STRV_IFNOTNULL(const char *x) {
return x ? x : STRV_IGNORE;
* string in the vector is an empty string. */
int strv_split_colon_pairs(char ***t, const char *s);
-char *strv_join_prefix(char * const *l, const char *separator, const char *prefix);
+char *strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separtor);
static inline char *strv_join(char * const *l, const char *separator) {
- return strv_join_prefix(l, separator, NULL);
+ return strv_join_full(l, separator, NULL, false);
}
char **strv_parse_nulstr(const char *s, size_t l);
void get_log_colors(int priority, const char **on, const char **off, const char **highlight) {
/* Note that this will initialize output variables only when there's something to output.
- * The caller must pre-initalize to "" or NULL as appropriate. */
+ * The caller must pre-initialize to "" or NULL as appropriate. */
if (priority <= LOG_ERR) {
if (on)
/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
* to 6. Let's rely on that. */
-#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1)
-#define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
-#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
-#define FORMAT_TIMESPAN_MAX 64
+#define FORMAT_TIMESTAMP_MAX (3U+1U+10U+1U+8U+1U+6U+1U+6U+1U)
+#define FORMAT_TIMESTAMP_WIDTH 28U /* when outputting, assume this width */
+#define FORMAT_TIMESTAMP_RELATIVE_MAX 256U
+#define FORMAT_TIMESPAN_MAX 64U
#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
#include <grp.h>
#if ENABLE_GSHADOW
-#include <gshadow.h>
+# include <gshadow.h>
#endif
#include <pwd.h>
#include <shadow.h>
#define ETC_PASSWD_LOCK_PATH "/etc/.pwd.lock"
-static inline bool uid_is_system(uid_t uid) {
- return uid <= SYSTEM_UID_MAX;
-}
-
-static inline bool gid_is_system(gid_t gid) {
- return gid <= SYSTEM_GID_MAX;
-}
-
-static inline bool uid_is_dynamic(uid_t uid) {
- return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX;
-}
-
-static inline bool gid_is_dynamic(gid_t gid) {
- return uid_is_dynamic((uid_t) gid);
-}
-
-static inline bool uid_is_container(uid_t uid) {
- return CONTAINER_UID_BASE_MIN <= uid && uid <= CONTAINER_UID_BASE_MAX;
-}
-
-static inline bool gid_is_container(gid_t gid) {
- return uid_is_container((uid_t) gid);
-}
-
/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer
* NULL is special */
#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *dent;
+ if (access("/proc/device-tree/ibm,partition-name", F_OK) == 0 &&
+ access("/proc/device-tree/hmc-managed?", F_OK) == 0 &&
+ access("/proc/device-tree/chosen/qemu,graphic-width", F_OK) != 0)
+ return VIRTUALIZATION_POWERVM;
+
dir = opendir("/proc/device-tree");
if (!dir) {
if (errno == ENOENT) {
goto translate_name;
}
if (!IN_SET(r, -ENOENT, 0))
- return log_debug_errno(r, "Failed to read /run/systemd/container: %m");
+ return log_debug_errno(r, "Failed to read /run/systemd/container-manager: %m");
if (getpid_cached() == 1) {
/* If we are PID 1 we can just check our own environment variable, and that's authoritative.
[VIRTUALIZATION_BHYVE] = "bhyve",
[VIRTUALIZATION_QNX] = "qnx",
[VIRTUALIZATION_ACRN] = "acrn",
+ [VIRTUALIZATION_POWERVM] = "powervm",
[VIRTUALIZATION_VM_OTHER] = "vm-other",
[VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
VIRTUALIZATION_BHYVE,
VIRTUALIZATION_QNX,
VIRTUALIZATION_ACRN,
+ VIRTUALIZATION_POWERVM,
VIRTUALIZATION_VM_OTHER,
VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] COMMAND ...\n"
- "\n%sInstall/update/remove the systemd-boot EFI boot manager and list/select entries.%s\n"
- "\nBoot Loader Commands:\n"
- " status Show status of installed systemd-boot and EFI variables\n"
- " install Install systemd-boot to the ESP and EFI variables\n"
- " update Update systemd-boot in the ESP and EFI variables\n"
- " remove Remove systemd-boot from the ESP and EFI variables\n"
- " is-installed Test whether systemd-boot is installed in the ESP\n"
- " random-seed Initialize random seed in ESP and EFI variables\n"
- " systemd-efi-options [STRING]\n"
- " Query or set system options string in EFI variable\n"
+ printf("%1$s [OPTIONS...] COMMAND ...\n"
+ "\n%5$sControl EFI firmware boot settings and manage boot loader.%6$s\n"
+ "\n%3$sGeneric EFI Firmware/Boot Loader Commands:%4$s\n"
+ " status Show status of installed boot loader and EFI variables\n"
" reboot-to-firmware [BOOL]\n"
" Query or set reboot-to-firmware EFI flag\n"
- "\nBoot Loader Entries Commands:\n"
+ " systemd-efi-options [STRING]\n"
+ " Query or set system options string in EFI variable\n"
+ "\n%3$sBoot Loader Specification Commands:%4$s\n"
" list List boot loader entries\n"
" set-default ID Set default boot loader entry\n"
" set-oneshot ID Set default boot loader entry, for next boot only\n"
- "\nOptions:\n"
+ "\n%3$ssystemd-boot Commands:%4$s\n"
+ " install Install systemd-boot to the ESP and EFI variables\n"
+ " update Update systemd-boot in the ESP and EFI variables\n"
+ " remove Remove systemd-boot from the ESP and EFI variables\n"
+ " is-installed Test whether systemd-boot is installed in the ESP\n"
+ " random-seed Initialize random seed in ESP and EFI variables\n"
+ "\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"
" --esp-path=PATH Path to the EFI System Partition (ESP)\n"
" --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 %s for details.\n"
+ "\nSee the %2$s for details.\n"
, program_invocation_short_name
- , ansi_highlight()
- , ansi_normal()
- , link);
+ , link
+ , ansi_underline(), ansi_normal()
+ , ansi_highlight(), ansi_normal()
+ );
return 0;
}
return EXIT_SUCCESS;
}
+static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target, size_t *ret_target_size) {
+ int r;
+ if (streq(arg1, "@current")) {
+ r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntrySelected", NULL, (void *) ret_target, ret_target_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get EFI variable 'LoaderEntrySelected': %m");
+ } else if (streq(arg1, "@oneshot")) {
+ r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, (void *) ret_target, ret_target_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryOneShot': %m");
+ } else if (streq(arg1, "@default")) {
+ r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntryDefault", NULL, (void *) ret_target, ret_target_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
+ } else {
+ char16_t *encoded = NULL;
+ encoded = utf8_to_utf16(arg1, strlen(arg1));
+ if (!encoded)
+ return log_oom();
+ *ret_target = encoded;
+ *ret_target_size = char16_strlen(encoded) * 2 + 2;
+ }
+ return 0;
+}
+
static int verb_set_default(int argc, char *argv[], void *userdata) {
const char *name;
int r;
if (isempty(argv[1])) {
r = efi_set_variable(EFI_VENDOR_LOADER, name, NULL, 0);
if (r < 0 && r != -ENOENT)
- return log_error_errno(r, "Failed to remove EFI variale: %m");
+ return log_error_errno(r, "Failed to remove EFI variable '%s': %m", name);
} else {
- _cleanup_free_ char16_t *encoded = NULL;
+ _cleanup_free_ char16_t *target = NULL;
+ size_t target_size = 0;
- encoded = utf8_to_utf16(argv[1], strlen(argv[1]));
- if (!encoded)
- return log_oom();
-
- r = efi_set_variable(EFI_VENDOR_LOADER, name, encoded, char16_strlen(encoded) * 2 + 2);
+ r = parse_loader_entry_target_arg(argv[1], &target, &target_size);
+ if (r < 0)
+ return r;
+ r = efi_set_variable(EFI_VENDOR_LOADER, name, target, target_size);
if (r < 0)
- return log_error_errno(r, "Failed to update EFI variable: %m");
+ return log_error_errno(r, "Failed to update EFI variable '%s': %m", name);
}
return 0;
return tcg;
}
-static EFI_TCG2 * tcg2_interface_check() {
+static EFI_TCG2 * tcg2_interface_check(void) {
EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
EFI_STATUS status;
EFI_TCG2 *tcg;
}
}
if (r < 0)
- return log_error_errno(r, "Failed to set address: %m");
+ return bus_log_address_error(r);
r = sd_bus_start(bus);
if (r < 0)
- return log_error_errno(r, "Failed to connect to bus: %m");
+ return bus_log_connect_error(r);
*ret = TAKE_PTR(bus);
(void) pager_open(arg_pager_flags);
- if (arg_legend) {
+ if (arg_legend)
printf("%-*s %-*s %-*s %-*s %s\n",
(int) name_width, "NAME",
(int) type_width, "TYPE",
(int) signature_width, "SIGNATURE",
(int) result_width, "RESULT/VALUE",
"FLAGS");
- }
for (j = 0; j < k; j++) {
_cleanup_free_ char *ellipsized = NULL;
return mfree(g);
}
+
+static const char *maybe_format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
+ if (arg_raw) {
+ snprintf(buf, l, USEC_FMT, t);
+ return buf;
+ }
+ return format_timespan(buf, l, t, accuracy);
+}
+
static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) {
if (!is_valid)
return "-";
Group **array;
signed path_columns;
unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */
- char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)];
+ char buffer[MAX4(21U, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX, DECIMAL_STR_MAX(usec_t))];
assert(a);
for (j = 0; j < n; j++) {
unsigned cputlen, pathtlen;
- format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0);
+ maybe_format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0);
cputlen = strlen(buffer);
maxtcpu = MAX(maxtcpu, cputlen);
else
fputs(" -", stdout);
} else
- printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0));
+ printf(" %*s", maxtcpu, maybe_format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0));
printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory));
printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps));
MOUNT_MOUNTED, MOUNT_REMOUNTING,
MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
- MOUNT_FAILED)) {
-
+ MOUNT_FAILED))
(void) automount_send_ready(a, a->expire_tokens, -ENODEV);
- }
if (MOUNT(other)->state == MOUNT_DEAD)
(void) automount_send_ready(a, a->expire_tokens, 0);
.startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID,
.tasks_max = TASKS_MAX_UNSET,
+
+ .moom_swap = MANAGED_OOM_AUTO,
+ .moom_mem_pressure = MANAGED_OOM_AUTO,
};
}
"%sTasksMax: %" PRIu64 "\n"
"%sDevicePolicy: %s\n"
"%sDisableControllers: %s\n"
- "%sDelegate: %s\n",
+ "%sDelegate: %s\n"
+ "%sManagedOOMSwap: %s\n"
+ "%sManagedOOMMemoryPressure: %s\n"
+ "%sManagedOOMMemoryPressureLimitPercent: %d%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
prefix, tasks_max_resolve(&c->tasks_max),
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, strempty(disable_controllers_str),
- prefix, yes_no(c->delegate));
+ 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);
if (c->delegate) {
_cleanup_free_ char *t = NULL;
u->in_cgroup_empty_queue = false;
}
+int unit_check_oomd_kill(Unit *u) {
+ _cleanup_free_ char *value = NULL;
+ bool increased;
+ uint64_t n = 0;
+ int r;
+
+ if (!u->cgroup_path)
+ return 0;
+
+ r = cg_all_unified();
+ if (r < 0)
+ return log_unit_debug_errno(u, r, "Couldn't determine whether we are in all unified mode: %m");
+ else if (r == 0)
+ return 0;
+
+ r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.systemd_oomd_kill", &value);
+ if (r < 0 && r != -ENODATA)
+ return r;
+
+ if (!isempty(value)) {
+ r = safe_atou64(value, &n);
+ if (r < 0)
+ return r;
+ }
+
+ increased = n > u->managed_oom_kill_last;
+ u->managed_oom_kill_last = n;
+
+ if (!increased)
+ return 0;
+
+ if (n > 0)
+ log_struct(LOG_NOTICE,
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_OOMD_KILL_STR,
+ LOG_UNIT_ID(u),
+ LOG_UNIT_INVOCATION_ID(u),
+ LOG_UNIT_MESSAGE(u, "systemd-oomd killed %"PRIu64" process(es) in this unit.", n));
+
+ return 1;
+}
+
int unit_check_oom(Unit *u) {
_cleanup_free_ char *oom_kill = NULL;
bool increased;
/* Common */
TasksMax tasks_max;
+
+ /* Settings for systemd-oomd */
+ ManagedOOMMode moom_swap;
+ ManagedOOMMode moom_mem_pressure;
+ int moom_mem_pressure_limit;
};
/* Used when querying IP accounting data */
int unit_watch_cgroup_memory(Unit *u);
void unit_add_to_cgroup_empty_queue(Unit *u);
+int unit_check_oomd_kill(Unit *u);
int unit_check_oom(Unit *u);
int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path);
#include "core-varlink.h"
#include "mkdir.h"
+#include "strv.h"
#include "user-util.h"
#include "varlink.h"
const char *service;
} LookupParameters;
+static const char* const managed_oom_mode_properties[] = {
+ "ManagedOOMSwap",
+ "ManagedOOMMemoryPressure",
+};
+
static int build_user_json(const char *user_name, uid_t uid, JsonVariant **ret) {
assert(user_name);
assert(uid_is_valid(uid));
return true;
}
+static int build_managed_oom_json_array_element(Unit *u, const char *property, JsonVariant **ret_v) {
+ bool use_limit = false;
+ CGroupContext *c;
+ const char *mode;
+
+ assert(u);
+ assert(property);
+ assert(ret_v);
+
+ if (!UNIT_VTABLE(u)->can_set_managed_oom)
+ return -EOPNOTSUPP;
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return -EINVAL;
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
+ /* systemd-oomd should always treat inactive units as though they didn't enable any action since they
+ * should not have a valid cgroup */
+ mode = managed_oom_mode_to_string(MANAGED_OOM_AUTO);
+ else if (streq(property, "ManagedOOMSwap"))
+ mode = managed_oom_mode_to_string(c->moom_swap);
+ else if (streq(property, "ManagedOOMMemoryPressure")) {
+ mode = managed_oom_mode_to_string(c->moom_mem_pressure);
+ use_limit = true;
+ } else
+ return -EINVAL;
+
+ return json_build(ret_v, JSON_BUILD_OBJECT(
+ 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))));
+}
+
+int manager_varlink_send_managed_oom_update(Unit *u) {
+ _cleanup_(json_variant_unrefp) JsonVariant *arr = NULL, *v = NULL;
+ CGroupContext *c;
+ int r;
+
+ assert(u);
+
+ if (!UNIT_VTABLE(u)->can_set_managed_oom || !u->manager || !u->manager->managed_oom_varlink_request || !u->cgroup_path)
+ return 0;
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return 0;
+
+ r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
+ if (r < 0)
+ return r;
+
+ for (size_t i = 0; i < ELEMENTSOF(managed_oom_mode_properties); i++) {
+ _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
+
+ r = build_managed_oom_json_array_element(u, managed_oom_mode_properties[i], &e);
+ if (r < 0)
+ return r;
+
+ r = json_variant_append_array(&arr, e);
+ if (r < 0)
+ return r;
+ }
+
+ r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
+ if (r < 0)
+ return r;
+
+ return varlink_notify(u->manager->managed_oom_varlink_request, v);
+}
+
+static int vl_method_subscribe_managed_oom_cgroups(
+ Varlink *link,
+ JsonVariant *parameters,
+ VarlinkMethodFlags flags,
+ void *userdata) {
+ static const UnitType supported_unit_types[] = { UNIT_SLICE, UNIT_SERVICE, UNIT_SCOPE };
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *arr = NULL;
+ Manager *m = userdata;
+ int r;
+
+ assert(link);
+ assert(m);
+
+ if (json_variant_elements(parameters) > 0)
+ return varlink_error_invalid_parameter(link, parameters);
+
+ /* We only take one subscriber for this method so return an error if there's already an existing one.
+ * This shouldn't happen since systemd-oomd is the only client of this method. */
+ if (FLAGS_SET(flags, VARLINK_METHOD_MORE) && m->managed_oom_varlink_request)
+ return varlink_error(m->managed_oom_varlink_request, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
+
+ r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
+ if (r < 0)
+ return r;
+
+ for (size_t i = 0; i < ELEMENTSOF(supported_unit_types); i++) {
+ Unit *u;
+
+ LIST_FOREACH(units_by_type, u, m->units_by_type[supported_unit_types[i]]) {
+ CGroupContext *c;
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
+ continue;
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ continue;
+
+ for (size_t j = 0; j < ELEMENTSOF(managed_oom_mode_properties); j++) {
+ _cleanup_(json_variant_unrefp) JsonVariant *e = NULL;
+
+ /* For the initial varlink call we only care about units that enabled (i.e. mode is not
+ * set to "auto") oomd properties. */
+ if (!(streq(managed_oom_mode_properties[j], "ManagedOOMSwap") && c->moom_swap == MANAGED_OOM_KILL) &&
+ !(streq(managed_oom_mode_properties[j], "ManagedOOMMemoryPressure") && c->moom_mem_pressure == MANAGED_OOM_KILL))
+ continue;
+
+ r = build_managed_oom_json_array_element(u, managed_oom_mode_properties[j], &e);
+ if (r < 0)
+ return r;
+
+ r = json_variant_append_array(&arr, e);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
+ if (r < 0)
+ return r;
+
+ if (!FLAGS_SET(flags, VARLINK_METHOD_MORE))
+ return varlink_reply(link, v);
+
+ m->managed_oom_varlink_request = varlink_ref(link);
+ return varlink_notify(m->managed_oom_varlink_request, v);
+}
+
static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
}
+static void vl_disconnect(VarlinkServer *s, Varlink *link, void *userdata) {
+ Manager *m = userdata;
+
+ assert(m);
+ assert(s);
+ assert(link);
+
+ if (link == m->managed_oom_varlink_request)
+ m->managed_oom_varlink_request = varlink_unref(link);
+}
+
int manager_varlink_init(Manager *m) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
s,
"io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,
"io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record,
- "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships);
+ "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships,
+ "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups);
if (r < 0)
return log_error_errno(r, "Failed to register varlink methods: %m");
+ r = varlink_server_bind_disconnect(s, vl_disconnect);
+ if (r < 0)
+ return log_error_errno(r, "Failed to register varlink disconnect handler: %m");
+
if (!MANAGER_IS_TEST_RUN(m)) {
(void) mkdir_p_label("/run/systemd/userdb", 0755);
r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket: %m");
+
+ r = varlink_server_listen_address(s, VARLINK_ADDR_PATH_MANAGED_OOM, 0666);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind to varlink socket: %m");
}
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
void manager_varlink_done(Manager *m) {
assert(m);
+ /* Send the final message if we still have a subscribe request open. */
+ if (m->managed_oom_varlink_request)
+ m->managed_oom_varlink_request = varlink_close_unref(m->managed_oom_varlink_request);
+
m->varlink_server = varlink_server_unref(m->varlink_server);
}
int manager_varlink_init(Manager *m);
void manager_varlink_done(Manager *m);
+
+/* The manager is expected to send an update to systemd-oomd if one of the following occurs:
+ * - The value of ManagedOOM*= properties change
+ * - A unit with ManagedOOM*= properties changes unit active state */
+int manager_varlink_send_managed_oom_update(Unit *u);
#include "bus-get-properties.h"
#include "cgroup-util.h"
#include "cgroup.h"
+#include "core-varlink.h"
#include "dbus-cgroup.h"
#include "dbus-util.h"
#include "errno-util.h"
BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
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 int property_get_cgroup_mask(
sd_bus *bus,
SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_ingress), 0),
SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_egress), 0),
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_VTABLE_END
};
LIST_PREPEND(device_allow, c->device_allow, a);
}
- a->r = !!strchr(rwm, 'r');
- a->w = !!strchr(rwm, 'w');
- a->m = !!strchr(rwm, 'm');
+ a->r = strchr(rwm, 'r');
+ a->w = strchr(rwm, 'w');
+ a->m = strchr(rwm, 'm');
}
n++;
return 1;
}
+ if (STR_IN_SET(name, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
+ ManagedOOMMode *cgroup_mode = streq(name, "ManagedOOMSwap") ? &c->moom_swap : &c->moom_mem_pressure;
+ ManagedOOMMode m;
+ const char *mode;
+
+ 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 = sd_bus_message_read(message, "s", &mode);
+ if (r < 0)
+ return r;
+
+ m = managed_oom_mode_from_string(mode);
+ if (m < 0)
+ return -EINVAL;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *cgroup_mode = m;
+ unit_write_settingf(u, flags, name, "%s=%s", name, mode);
+ }
+
+ (void) manager_varlink_send_managed_oom_update(u);
+ return 1;
+ }
+
+ if (streq(name, "ManagedOOMMemoryPressureLimitPercent")) {
+ 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);
+ if (r < 0)
+ return r;
+
+ if (c->moom_mem_pressure == MANAGED_OOM_KILL)
+ (void) manager_varlink_send_managed_oom_update(u);
+
+ 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);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
+static BUS_DEFINE_PROPERTY_GET(property_get_mount_apivfs, "b", ExecContext, exec_context_get_effective_mount_apivfs);
static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS);
static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MountAPIVFS", "b", property_get_mount_apivfs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
if (streq(name, "ProtectControlGroups"))
return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
- if (streq(name, "MountAPIVFS"))
- return bus_set_transient_bool(u, name, &c->mount_apivfs, message, flags, error);
-
if (streq(name, "CPUSchedulingResetOnFork"))
return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
return 1;
+ } else if (streq(name, "MountAPIVFS")) {
+ bool b;
+
+ r = bus_set_transient_bool(u, name, &b, message, flags, error);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ c->mount_apivfs = b;
+ c->mount_apivfs_set = true;
+ }
+
+ return 1;
+
} else if (streq(name, "WorkingDirectory")) {
const char *s;
bool missing_ok;
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,
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);
}
}
+static int device_remove_old(Manager *m, sd_device *dev) {
+ _cleanup_free_ char *syspath_old = NULL, *e = NULL;
+ const char *devpath_old;
+ int r;
+
+ r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m");
+ return 0;
+ }
+
+ syspath_old = path_join("/sys", devpath_old);
+ if (!syspath_old)
+ return log_oom();
+
+ r = unit_name_from_path(syspath_old, ".device", &e);
+ if (r < 0)
+ return log_device_error_errno(dev, r, "Failed to generate unit name from old device path: %m");
+
+ device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
+ return 0;
+}
+
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
Manager *m = userdata;
DeviceAction action;
if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_MOVE))
device_propagate_reload_by_sysfs(m, sysfs);
+ if (action == DEVICE_ACTION_MOVE)
+ (void) device_remove_old(m, dev);
+
/* A change event can signal that a device is becoming ready, in particular if the device is using
* the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for
* change events */
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "user-record.h"
#include "user-util.h"
/* Takes a value generated randomly or by hashing and turns it into a UID in the right range */
if (!pre)
return -ENOMEM;
- joined = strv_join_prefix(c->directories[t].paths, ":", pre);
+ joined = strv_join_full(c->directories[t].paths, ":", pre, true);
if (!joined)
return -ENOMEM;
return true;
if (context->root_directory) {
- if (context->mount_apivfs)
+ if (exec_context_get_effective_mount_apivfs(context))
return true;
for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
continue;
if (exec_directory_is_private(context, t) &&
- !(context->root_directory || context->root_image)) {
+ !exec_context_with_rootfs(context)) {
char *private_root;
/* So this is for a dynamic user, and we need to make sure the process can access its own
}
if (exec_directory_is_private(context, t) &&
- (context->root_directory || context->root_image))
+ exec_context_with_rootfs(context))
/* When RootDirectory= or RootImage= are set, then the symbolic link to the private
* directory is not created on the root directory. So, let's bind-mount the directory
* on the 'non-private' place. */
.protect_kernel_modules = context->protect_kernel_modules,
.protect_kernel_logs = context->protect_kernel_logs,
.protect_hostname = context->protect_hostname,
- .mount_apivfs = context->mount_apivfs,
+ .mount_apivfs = exec_context_get_effective_mount_apivfs(context),
.private_mounts = context->private_mounts,
.protect_home = context->protect_home,
.protect_system = context->protect_system,
wd = home;
- } else if (context->working_directory)
- wd = context->working_directory;
- else
- wd = "/";
+ } else
+ wd = empty_to_root(context->working_directory);
if (params->flags & EXEC_APPLY_CHROOT)
d = wd;
"%sProtectProc: %s\n"
"%sProcSubset: %s\n",
prefix, c->umask,
- prefix, c->working_directory ? c->working_directory : "/",
- prefix, c->root_directory ? c->root_directory : "/",
+ prefix, empty_to_root(c->working_directory),
+ prefix, empty_to_root(c->root_directory),
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp),
prefix, yes_no(c->private_devices),
prefix, yes_no(c->private_users),
prefix, protect_home_to_string(c->protect_home),
prefix, protect_system_to_string(c->protect_system),
- prefix, yes_no(c->mount_apivfs),
+ prefix, yes_no(exec_context_get_effective_mount_apivfs(c)),
prefix, yes_no(c->ignore_sigpipe),
prefix, yes_no(c->memory_deny_write_execute),
prefix, yes_no(c->restrict_realtime),
return p;
}
+bool exec_context_get_effective_mount_apivfs(const ExecContext *c) {
+ assert(c);
+
+ /* Explicit setting wins */
+ if (c->mount_apivfs_set)
+ return c->mount_apivfs;
+
+ /* Default to "yes" if root directory or image are specified */
+ if (exec_context_with_rootfs(c))
+ return true;
+
+ return false;
+}
+
void exec_context_free_log_extra_fields(ExecContext *c) {
assert(c);
void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status) {
assert(s);
- if (s->pid != pid) {
+ if (s->pid != pid)
*s = (ExecStatus) {
.pid = pid,
};
- }
dual_timestamp_get(&s->exit_timestamp);
return 0;
}
-static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, ExecRuntime **ret) {
+static int exec_runtime_make(
+ Manager *m,
+ const ExecContext *c,
+ const char *id,
+ ExecRuntime **ret) {
+
_cleanup_(namespace_cleanup_tmpdirp) char *tmp_dir = NULL, *var_tmp_dir = NULL;
_cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 };
int r;
assert(id);
/* It is not necessary to create ExecRuntime object. */
- if (!c->private_network && !c->private_tmp && !c->network_namespace_path)
+ if (!c->private_network && !c->private_tmp && !c->network_namespace_path) {
+ *ret = NULL;
return 0;
+ }
if (c->private_tmp &&
!(prefixed_path_strv_contains(c->inaccessible_paths, "/tmp") &&
/* We already have a ExecRuntime object, let's increase the ref count and reuse it */
goto ref;
- if (!create)
+ if (!create) {
+ *ret = NULL;
return 0;
+ }
/* If not found, then create a new object. */
r = exec_runtime_make(m, c, id, &rt);
- if (r <= 0)
- /* When r == 0, it is not necessary to create ExecRuntime object. */
+ if (r < 0)
return r;
+ if (r == 0) {
+ /* When r == 0, it is not necessary to create ExecRuntime object. */
+ *ret = NULL;
+ return 0;
+ }
ref:
/* increment reference counter. */
r = safe_atoi(buf, &fdpair[1]);
if (r < 0)
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-1=%s: %m", buf);
- if (!fdset_contains(fds, fdpair[0]))
+ if (!fdset_contains(fds, fdpair[1]))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
"exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", fdpair[1]);
fdpair[1] = fdset_remove(fds, fdpair[1]);
#include "namespace.h"
#include "nsflags.h"
#include "numa-util.h"
+#include "path-util.h"
#include "time-util.h"
#define EXEC_STDIN_DATA_MAX (64U*1024U*1024U)
dual_timestamp exit_timestamp;
pid_t pid;
int code; /* as in siginfo_t::si_code */
- int status; /* as in sigingo_t::si_status */
+ int status; /* as in siginfo_t::si_status */
};
/* Stores information about commands we execute. Covers both configuration settings as well as runtime data. */
bool nice_set:1;
bool ioprio_set:1;
bool cpu_sched_set:1;
+ bool mount_apivfs_set:1;
/* This is not exposed to the user but available internally. We need it to make sure that whenever we
* spawn /usr/bin/mount it is run in the same process group as us so that the autofs logic detects
return (c->restrict_namespaces & NAMESPACE_FLAGS_ALL) != NAMESPACE_FLAGS_ALL;
}
+static inline bool exec_context_with_rootfs(const ExecContext *c) {
+ assert(c);
+
+ /* Checks if RootDirectory= or RootImage= are used */
+
+ return !empty_or_root(c->root_directory) || c->root_image;
+}
+
typedef enum ExecFlags {
EXEC_APPLY_SANDBOXING = 1 << 0,
EXEC_APPLY_CHROOT = 1 << 1,
bool exec_context_maintains_privileges(const ExecContext *c);
int exec_context_get_effective_ioprio(const ExecContext *c);
+bool exec_context_get_effective_mount_apivfs(const ExecContext *c);
void exec_context_free_log_extra_fields(ExecContext *c);
%%
m4_dnl Define the context options only once
m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
-`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
-$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory)
-$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image)
-$1.RootImageOptions, config_parse_root_image_options, 0, offsetof($1, exec_context)
-$1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context)
-$1.RootHashSignature, config_parse_exec_root_hash_sig, 0, offsetof($1, exec_context)
-$1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity)
-$1.MountImages, config_parse_mount_images, 0, offsetof($1, exec_context)
-$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
-$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
-$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)
-$1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context)
-$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context)
-$1.CoredumpFilter, config_parse_exec_coredump_filter, 0, offsetof($1, exec_context)
-$1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context)
-$1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context)
-$1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context)
-$1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context)
-$1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork)
-$1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context)
-$1.NUMAPolicy, config_parse_numa_policy, 0, offsetof($1, exec_context.numa_policy.type)
-$1.NUMAMask, config_parse_numa_mask, 0, offsetof($1, exec_context.numa_policy)
-$1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask)
-$1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment)
-$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files)
-$1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment)
-$1.UnsetEnvironment, config_parse_unset_environ, 0, offsetof($1, exec_context.unset_environment)
-$1.DynamicUser, config_parse_bool, true, offsetof($1, exec_context.dynamic_user)
-$1.RemoveIPC, config_parse_bool, 0, offsetof($1, exec_context.remove_ipc)
-$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context)
-$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context)
-$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context)
-$1.StandardInputText, config_parse_exec_input_text, 0, offsetof($1, exec_context)
-$1.StandardInputData, config_parse_exec_input_data, 0, offsetof($1, exec_context)
-$1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path)
-$1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset)
-$1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup)
-$1.TTYVTDisallocate, config_parse_bool, 0, offsetof($1, exec_context.tty_vt_disallocate)
-$1.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.syslog_identifier)
-$1.SyslogFacility, config_parse_log_facility, 0, offsetof($1, exec_context.syslog_priority)
-$1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority)
-$1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix)
-$1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max)
-$1.LogRateLimitIntervalSec, config_parse_sec, 0, offsetof($1, exec_context.log_ratelimit_interval_usec)
-$1.LogRateLimitBurst, config_parse_unsigned, 0, offsetof($1, exec_context.log_ratelimit_burst)
-$1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context)
-$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context)
-$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits)
-$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set)
-$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set)
-$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec)
-$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
-$1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode)
-$1.ProtectProc, config_parse_protect_proc, 0, offsetof($1, exec_context.protect_proc)
-$1.ProcSubset, config_parse_proc_subset, 0, offsetof($1, exec_context.proc_subset)
+`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
+$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory)
+$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image)
+$1.RootImageOptions, config_parse_root_image_options, 0, offsetof($1, exec_context)
+$1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context)
+$1.RootHashSignature, config_parse_exec_root_hash_sig, 0, offsetof($1, exec_context)
+$1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity)
+$1.MountImages, config_parse_mount_images, 0, offsetof($1, exec_context)
+$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
+$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
+$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)
+$1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context)
+$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context)
+$1.CoredumpFilter, config_parse_exec_coredump_filter, 0, offsetof($1, exec_context)
+$1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context)
+$1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context)
+$1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context)
+$1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context)
+$1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork)
+$1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context)
+$1.NUMAPolicy, config_parse_numa_policy, 0, offsetof($1, exec_context.numa_policy.type)
+$1.NUMAMask, config_parse_numa_mask, 0, offsetof($1, exec_context.numa_policy)
+$1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask)
+$1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment)
+$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files)
+$1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment)
+$1.UnsetEnvironment, config_parse_unset_environ, 0, offsetof($1, exec_context.unset_environment)
+$1.DynamicUser, config_parse_bool, true, offsetof($1, exec_context.dynamic_user)
+$1.RemoveIPC, config_parse_bool, 0, offsetof($1, exec_context.remove_ipc)
+$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context)
+$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context)
+$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context)
+$1.StandardInputText, config_parse_exec_input_text, 0, offsetof($1, exec_context)
+$1.StandardInputData, config_parse_exec_input_data, 0, offsetof($1, exec_context)
+$1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path)
+$1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset)
+$1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup)
+$1.TTYVTDisallocate, config_parse_bool, 0, offsetof($1, exec_context.tty_vt_disallocate)
+$1.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.syslog_identifier)
+$1.SyslogFacility, config_parse_log_facility, 0, offsetof($1, exec_context.syslog_priority)
+$1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority)
+$1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix)
+$1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max)
+$1.LogRateLimitIntervalSec, config_parse_sec, 0, offsetof($1, exec_context.log_ratelimit_interval_usec)
+$1.LogRateLimitBurst, config_parse_unsigned, 0, offsetof($1, exec_context.log_ratelimit_burst)
+$1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context)
+$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context)
+$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits)
+$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set)
+$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set)
+$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec)
+$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
+$1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode)
+$1.ProtectProc, config_parse_protect_proc, 0, offsetof($1, exec_context.protect_proc)
+$1.ProcSubset, config_parse_proc_subset, 0, offsetof($1, exec_context.proc_subset)
m4_ifdef(`HAVE_SECCOMP',
-`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
-$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs)
-$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context)
-$1.SystemCallLog, config_parse_syscall_log, 0, offsetof($1, exec_context)
-$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute)
-$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context)
-$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime)
-$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid)
-$1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context)
-$1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)',
-`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.SystemCallLog, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
-$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
-$1.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
-$1.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
-$1.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
-$1.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
-$1.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
-$1.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
-$1.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
-$1.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
-$1.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
-$1.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
-$1.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
-$1.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
-$1.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
-$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths)
-$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths)
-$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths)
-$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.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.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp)
-$1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices)
-$1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables)
-$1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules)
-$1.ProtectKernelLogs, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_logs)
-$1.ProtectClock, config_parse_bool, 0, offsetof($1, exec_context.protect_clock)
-$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
-$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path)
-$1.LogNamespace, config_parse_log_namespace, 0, offsetof($1, exec_context)
-$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
-$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users)
-$1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts)
-$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.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.RuntimeDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].paths)
-$1.StateDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].mode)
-$1.StateDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].paths)
-$1.CacheDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].mode)
-$1.CacheDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].paths)
-$1.LogsDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].mode)
-$1.LogsDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths)
-$1.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode)
-$1.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths)
-$1.SetCredential, config_parse_set_credential, 0, offsetof($1, exec_context)
-$1.LoadCredential, config_parse_load_credential, 0, offsetof($1, exec_context)
-$1.TimeoutCleanSec, config_parse_sec, 0, offsetof($1, exec_context.timeout_clean_usec)
-$1.ProtectHostname, config_parse_bool, 0, offsetof($1, exec_context.protect_hostname)
+`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
+$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs)
+$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context)
+$1.SystemCallLog, config_parse_syscall_log, 0, offsetof($1, exec_context)
+$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute)
+$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context)
+$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime)
+$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid)
+$1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context)
+$1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)',
+`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.SystemCallLog, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
+$1.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
+$1.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
+$1.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
+$1.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
+$1.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
+$1.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
+$1.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
+$1.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
+$1.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
+$1.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
+$1.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
+$1.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
+$1.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
+$1.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
+$1.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
+$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths)
+$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths)
+$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths)
+$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.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.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp)
+$1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices)
+$1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables)
+$1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules)
+$1.ProtectKernelLogs, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_logs)
+$1.ProtectClock, config_parse_bool, 0, offsetof($1, exec_context.protect_clock)
+$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
+$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path)
+$1.LogNamespace, config_parse_log_namespace, 0, offsetof($1, exec_context)
+$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
+$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users)
+$1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts)
+$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.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.RuntimeDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].paths)
+$1.StateDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].mode)
+$1.StateDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].paths)
+$1.CacheDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].mode)
+$1.CacheDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].paths)
+$1.LogsDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].mode)
+$1.LogsDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths)
+$1.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode)
+$1.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths)
+$1.SetCredential, config_parse_set_credential, 0, offsetof($1, exec_context)
+$1.LoadCredential, config_parse_load_credential, 0, offsetof($1, exec_context)
+$1.TimeoutCleanSec, config_parse_sec, 0, offsetof($1, exec_context.timeout_clean_usec)
+$1.ProtectHostname, config_parse_bool, 0, offsetof($1, exec_context.protect_hostname)
m4_ifdef(`HAVE_PAM',
-`$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)',
-`$1.PAMName, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
-$1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe)
-$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)
-$1.UtmpMode, config_parse_exec_utmp_mode, 0, offsetof($1, exec_context.utmp_mode)
+`$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)',
+`$1.PAMName, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+$1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe)
+$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)
+$1.UtmpMode, config_parse_exec_utmp_mode, 0, offsetof($1, exec_context.utmp_mode)
m4_ifdef(`HAVE_SELINUX',
-`$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)',
-`$1.SELinuxContext, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+`$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)',
+`$1.SELinuxContext, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
m4_ifdef(`HAVE_APPARMOR',
-`$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)',
-`$1.AppArmorProfile, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+`$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)',
+`$1.AppArmorProfile, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
m4_ifdef(`ENABLE_SMACK',
-`$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)',
-`$1.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')'
+`$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)',
+`$1.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')'
)m4_dnl
m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
-`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
-$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
-$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
-$1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal)
-$1.RestartKillSignal, config_parse_signal, 0, offsetof($1, kill_context.restart_kill_signal)
-$1.FinalKillSignal, config_parse_signal, 0, offsetof($1, kill_context.final_kill_signal)
-$1.WatchdogSignal, config_parse_signal, 0, offsetof($1, kill_context.watchdog_signal)'
+`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
+$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
+$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
+$1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal)
+$1.RestartKillSignal, config_parse_signal, 0, offsetof($1, kill_context.restart_kill_signal)
+$1.FinalKillSignal, config_parse_signal, 0, offsetof($1, kill_context.final_kill_signal)
+$1.WatchdogSignal, config_parse_signal, 0, offsetof($1, kill_context.watchdog_signal)'
)m4_dnl
m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS',
-`$1.Slice, config_parse_unit_slice, 0, 0
-$1.AllowedCPUs, config_parse_allowed_cpus, 0, offsetof($1, cgroup_context)
-$1.AllowedMemoryNodes, config_parse_allowed_mems, 0, offsetof($1, cgroup_context)
-$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting)
-$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight)
-$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
-$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
-$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
-$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
-$1.CPUQuotaPeriodSec, config_parse_sec_def_infinity, 0, offsetof($1, cgroup_context.cpu_quota_period_usec)
-$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
-$1.MemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.DefaultMemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.DefaultMemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.MemoryMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.MemorySwapMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
-$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
-$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
-$1.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting)
-$1.IOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.io_weight)
-$1.StartupIOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
-$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context)
-$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
-$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
-$1.IOReadIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
-$1.IOWriteIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
-$1.IODeviceLatencyTargetSec, config_parse_io_device_latency, 0, offsetof($1, cgroup_context)
-$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
-$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight)
-$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight)
-$1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context)
-$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
-$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
-$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting)
-$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max)
-$1.Delegate, config_parse_delegate, 0, offsetof($1, cgroup_context)
-$1.DisableControllers, config_parse_disable_controllers, 0, offsetof($1, cgroup_context)
-$1.IPAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.ip_accounting)
-$1.IPAddressAllow, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_allow)
-$1.IPAddressDeny, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_deny)
-$1.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_ingress)
-$1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress)
-$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
+`$1.Slice, config_parse_unit_slice, 0, 0
+$1.AllowedCPUs, config_parse_allowed_cpus, 0, offsetof($1, cgroup_context)
+$1.AllowedMemoryNodes, config_parse_allowed_mems, 0, offsetof($1, cgroup_context)
+$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting)
+$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight)
+$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
+$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
+$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
+$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
+$1.CPUQuotaPeriodSec, config_parse_sec_def_infinity, 0, offsetof($1, cgroup_context.cpu_quota_period_usec)
+$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
+$1.MemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.DefaultMemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.DefaultMemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemorySwapMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
+$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
+$1.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting)
+$1.IOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.io_weight)
+$1.StartupIOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
+$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context)
+$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
+$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
+$1.IOReadIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
+$1.IOWriteIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
+$1.IODeviceLatencyTargetSec, config_parse_io_device_latency, 0, offsetof($1, cgroup_context)
+$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
+$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight)
+$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight)
+$1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context)
+$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
+$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
+$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting)
+$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max)
+$1.Delegate, config_parse_delegate, 0, offsetof($1, cgroup_context)
+$1.DisableControllers, config_parse_disable_controllers, 0, offsetof($1, cgroup_context)
+$1.IPAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.ip_accounting)
+$1.IPAddressAllow, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_allow)
+$1.IPAddressDeny, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_deny)
+$1.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_ingress)
+$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.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl
-Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
-Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
-Unit.SourcePath, config_parse_unit_path_printf, 0, offsetof(Unit, source_path)
-Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
-Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
-Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0
-Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
-Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
-Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLICTS, 0
-Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0
-Unit.After, config_parse_unit_deps, UNIT_AFTER, 0
-Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0
-Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
-Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
-Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
-Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
-Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0
-Unit.JoinsNamespaceOf, config_parse_unit_deps, UNIT_JOINS_NAMESPACE_OF, 0
-Unit.RequiresOverridable, config_parse_obsolete_unit_deps, UNIT_REQUIRES, 0
-Unit.RequisiteOverridable, config_parse_obsolete_unit_deps, UNIT_REQUISITE, 0
-Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0
-Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded)
-Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start)
-Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop)
-Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate)
-Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies)
-Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode)
+Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
+Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
+Unit.SourcePath, config_parse_unit_path_printf, 0, offsetof(Unit, source_path)
+Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
+Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
+Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0
+Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
+Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
+Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLICTS, 0
+Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0
+Unit.After, config_parse_unit_deps, UNIT_AFTER, 0
+Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0
+Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
+Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
+Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
+Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
+Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0
+Unit.JoinsNamespaceOf, config_parse_unit_deps, UNIT_JOINS_NAMESPACE_OF, 0
+Unit.RequiresOverridable, config_parse_obsolete_unit_deps, UNIT_REQUIRES, 0
+Unit.RequisiteOverridable, config_parse_obsolete_unit_deps, UNIT_REQUISITE, 0
+Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0
+Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded)
+Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start)
+Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop)
+Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate)
+Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies)
+Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode)
m4_dnl The following is a legacy alias name for compatibility
-Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode)
-Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
-Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
-Unit.JobTimeoutSec, config_parse_job_timeout_sec, 0, 0
-Unit.JobRunningTimeoutSec, config_parse_job_running_timeout_sec, 0, 0
-Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
-Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
-Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
+Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode)
+Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
+Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
+Unit.JobTimeoutSec, config_parse_job_timeout_sec, 0, 0
+Unit.JobRunningTimeoutSec, config_parse_job_running_timeout_sec, 0, 0
+Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
+Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
+Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
m4_dnl The following is a legacy alias name for compatibility
-Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
-Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst)
-Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Unit.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
-Unit.SuccessAction, config_parse_emergency_action, 0, offsetof(Unit, success_action)
-Unit.FailureActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, failure_action_exit_status)
-Unit.SuccessActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, success_action_exit_status)
-Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
-Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
-Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
-Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
-Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions)
-Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions)
-Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions)
-Unit.ConditionPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, conditions)
-Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions)
-Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions)
-Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions)
-Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions)
-Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions)
-Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions)
-Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions)
-Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions)
-Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)
-Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions)
-Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions)
-Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions)
-Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions)
-Unit.ConditionMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, conditions)
-Unit.ConditionCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, conditions)
-Unit.ConditionEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, conditions)
-Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions)
-Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions)
-Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions)
-Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts)
-Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts)
-Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts)
-Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts)
-Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts)
-Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts)
-Unit.AssertPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, asserts)
-Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts)
-Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts)
-Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts)
-Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts)
-Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts)
-Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts)
-Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts)
-Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
-Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)
-Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts)
-Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts)
-Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts)
-Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts)
-Unit.AssertMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, asserts)
-Unit.AssertCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, asserts)
-Unit.AssertEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, asserts)
-Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts)
-Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts)
-Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts)
-Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode)
+Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
+Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst)
+Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
+Unit.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
+Unit.SuccessAction, config_parse_emergency_action, 0, offsetof(Unit, success_action)
+Unit.FailureActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, failure_action_exit_status)
+Unit.SuccessActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, success_action_exit_status)
+Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
+Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
+Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
+Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
+Unit.ConditionPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK, offsetof(Unit, conditions)
+Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions)
+Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions)
+Unit.ConditionPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, conditions)
+Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions)
+Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions)
+Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions)
+Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions)
+Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions)
+Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions)
+Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions)
+Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions)
+Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)
+Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions)
+Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions)
+Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions)
+Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions)
+Unit.ConditionMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, conditions)
+Unit.ConditionCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, conditions)
+Unit.ConditionEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, conditions)
+Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions)
+Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions)
+Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions)
+Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts)
+Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts)
+Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts)
+Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK, offsetof(Unit, asserts)
+Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts)
+Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts)
+Unit.AssertPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, asserts)
+Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts)
+Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts)
+Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts)
+Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts)
+Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts)
+Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts)
+Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts)
+Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
+Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)
+Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts)
+Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts)
+Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts)
+Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts)
+Unit.AssertMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, asserts)
+Unit.AssertCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, asserts)
+Unit.AssertEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, asserts)
+Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts)
+Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts)
+Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts)
+Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode)
m4_dnl
-Service.PIDFile, config_parse_pid_file, 0, offsetof(Service, pid_file)
-Service.ExecCondition, config_parse_exec, SERVICE_EXEC_CONDITION, offsetof(Service, exec_command)
-Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
-Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command)
-Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command)
-Service.ExecReload, config_parse_exec, SERVICE_EXEC_RELOAD, offsetof(Service, exec_command)
-Service.ExecStop, config_parse_exec, SERVICE_EXEC_STOP, offsetof(Service, exec_command)
-Service.ExecStopPost, config_parse_exec, SERVICE_EXEC_STOP_POST, offsetof(Service, exec_command)
-Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec)
-Service.TimeoutSec, config_parse_service_timeout, 0, 0
-Service.TimeoutStartSec, config_parse_service_timeout, 0, 0
-Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec)
-Service.TimeoutAbortSec, config_parse_service_timeout_abort, 0, 0
-Service.TimeoutStartFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_start_failure_mode)
-Service.TimeoutStopFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_stop_failure_mode)
-Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
-Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
+Service.PIDFile, config_parse_pid_file, 0, offsetof(Service, pid_file)
+Service.ExecCondition, config_parse_exec, SERVICE_EXEC_CONDITION, offsetof(Service, exec_command)
+Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
+Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command)
+Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command)
+Service.ExecReload, config_parse_exec, SERVICE_EXEC_RELOAD, offsetof(Service, exec_command)
+Service.ExecStop, config_parse_exec, SERVICE_EXEC_STOP, offsetof(Service, exec_command)
+Service.ExecStopPost, config_parse_exec, SERVICE_EXEC_STOP_POST, offsetof(Service, exec_command)
+Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec)
+Service.TimeoutSec, config_parse_service_timeout, 0, 0
+Service.TimeoutStartSec, config_parse_service_timeout, 0, 0
+Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec)
+Service.TimeoutAbortSec, config_parse_service_timeout_abort, 0, 0
+Service.TimeoutStartFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_start_failure_mode)
+Service.TimeoutStopFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_stop_failure_mode)
+Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
+Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
m4_dnl The following five only exist for compatibility, they moved into Unit, see above
-Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
-Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst)
-Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
-Service.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
-Service.Type, config_parse_service_type, 0, offsetof(Service, type)
-Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
-Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
-Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only)
-Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit)
-Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid)
-Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_prevent_status)
-Service.RestartForceExitStatus, config_parse_set_status, 0, offsetof(Service, restart_force_status)
-Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status)
-Service.SysVStartPriority, config_parse_warn_compat, DISABLED_LEGACY, 0
-Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking)
-Service.BusName, config_parse_bus_name, 0, offsetof(Service, bus_name)
-Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max)
-Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
-Service.Sockets, config_parse_service_sockets, 0, 0
-Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
-Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors)
-Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
-Service.OOMPolicy, config_parse_oom_policy, 0, offsetof(Service, oom_policy)
+Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
+Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst)
+Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
+Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
+Service.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
+Service.Type, config_parse_service_type, 0, offsetof(Service, type)
+Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
+Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
+Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only)
+Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit)
+Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid)
+Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_prevent_status)
+Service.RestartForceExitStatus, config_parse_set_status, 0, offsetof(Service, restart_force_status)
+Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status)
+Service.SysVStartPriority, config_parse_warn_compat, DISABLED_LEGACY, 0
+Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking)
+Service.BusName, config_parse_bus_name, 0, offsetof(Service, bus_name)
+Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max)
+Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
+Service.Sockets, config_parse_service_sockets, 0, 0
+Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
+Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors)
+Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
+Service.OOMPolicy, config_parse_oom_policy, 0, offsetof(Service, oom_policy)
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
m4_dnl
-Socket.ListenStream, config_parse_socket_listen, SOCKET_SOCKET, 0
-Socket.ListenDatagram, config_parse_socket_listen, SOCKET_SOCKET, 0
-Socket.ListenSequentialPacket, config_parse_socket_listen, SOCKET_SOCKET, 0
-Socket.ListenFIFO, config_parse_socket_listen, SOCKET_FIFO, 0
-Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0
-Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
-Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
-Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0
-Socket.SocketProtocol, config_parse_socket_protocol, 0, offsetof(Socket, socket_protocol)
-Socket.BindIPv6Only, config_parse_socket_bind, 0, offsetof(Socket, bind_ipv6_only)
-Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
-Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
-Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command)
-Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC_START_POST, offsetof(Socket, exec_command)
-Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command)
-Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command)
-Socket.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Socket, timeout_usec)
-Socket.SocketUser, config_parse_user_group_compat, 0, offsetof(Socket, user)
-Socket.SocketGroup, config_parse_user_group_compat, 0, offsetof(Socket, group)
-Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
-Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
-Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
-Socket.FlushPending, config_parse_bool, 0, offsetof(Socket, flush_pending)
-Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable)
-Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
-Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source)
-Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)
-Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time)
-Socket.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Socket, keep_alive_interval)
-Socket.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Socket, keep_alive_cnt)
-Socket.DeferAcceptSec, config_parse_sec, 0, offsetof(Socket, defer_accept)
-Socket.NoDelay, config_parse_bool, 0, offsetof(Socket, no_delay)
-Socket.Priority, config_parse_int, 0, offsetof(Socket, priority)
-Socket.ReceiveBuffer, config_parse_iec_size, 0, offsetof(Socket, receive_buffer)
-Socket.SendBuffer, config_parse_iec_size, 0, offsetof(Socket, send_buffer)
-Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos)
-Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl)
-Socket.Mark, config_parse_int, 0, offsetof(Socket, mark)
-Socket.PipeSize, config_parse_iec_size, 0, offsetof(Socket, pipe_size)
-Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind)
-Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent)
-Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast)
-Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
-Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
-Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo)
-Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
-Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
-Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
-Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
-Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop)
-Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks)
-Socket.FileDescriptorName, config_parse_fdname, 0, 0
-Socket.Service, config_parse_socket_service, 0, 0
-Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
-Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
+Socket.ListenStream, config_parse_socket_listen, SOCKET_SOCKET, 0
+Socket.ListenDatagram, config_parse_socket_listen, SOCKET_SOCKET, 0
+Socket.ListenSequentialPacket, config_parse_socket_listen, SOCKET_SOCKET, 0
+Socket.ListenFIFO, config_parse_socket_listen, SOCKET_FIFO, 0
+Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0
+Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
+Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
+Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0
+Socket.SocketProtocol, config_parse_socket_protocol, 0, offsetof(Socket, socket_protocol)
+Socket.BindIPv6Only, config_parse_socket_bind, 0, offsetof(Socket, bind_ipv6_only)
+Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
+Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
+Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command)
+Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC_START_POST, offsetof(Socket, exec_command)
+Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command)
+Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command)
+Socket.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Socket, timeout_usec)
+Socket.SocketUser, config_parse_user_group_compat, 0, offsetof(Socket, user)
+Socket.SocketGroup, config_parse_user_group_compat, 0, offsetof(Socket, group)
+Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
+Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
+Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
+Socket.FlushPending, config_parse_bool, 0, offsetof(Socket, flush_pending)
+Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable)
+Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
+Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source)
+Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)
+Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time)
+Socket.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Socket, keep_alive_interval)
+Socket.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Socket, keep_alive_cnt)
+Socket.DeferAcceptSec, config_parse_sec, 0, offsetof(Socket, defer_accept)
+Socket.NoDelay, config_parse_bool, 0, offsetof(Socket, no_delay)
+Socket.Priority, config_parse_int, 0, offsetof(Socket, priority)
+Socket.ReceiveBuffer, config_parse_iec_size, 0, offsetof(Socket, receive_buffer)
+Socket.SendBuffer, config_parse_iec_size, 0, offsetof(Socket, send_buffer)
+Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos)
+Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl)
+Socket.Mark, config_parse_int, 0, offsetof(Socket, mark)
+Socket.PipeSize, config_parse_iec_size, 0, offsetof(Socket, pipe_size)
+Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind)
+Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent)
+Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast)
+Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
+Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
+Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo)
+Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
+Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
+Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
+Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
+Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop)
+Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks)
+Socket.FileDescriptorName, config_parse_fdname, 0, 0
+Socket.Service, config_parse_socket_service, 0, 0
+Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
+Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
m4_ifdef(`ENABLE_SMACK',
-`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack)
-Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in)
-Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)',
-`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack)
+Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in)
+Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)',
+`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
+Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
m4_ifdef(`HAVE_SELINUX',
-`Socket.SELinuxContextFromNet, config_parse_bool, 0, offsetof(Socket, selinux_context_from_net)',
-`Socket.SELinuxContextFromNet, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
+`Socket.SELinuxContextFromNet, config_parse_bool, 0, offsetof(Socket, selinux_context_from_net)',
+`Socket.SELinuxContextFromNet, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
m4_dnl
-Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
-Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where)
-Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
-Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype)
-Mount.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Mount, timeout_usec)
-Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
-Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options)
-Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount)
-Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount)
-Mount.ReadWriteOnly, config_parse_bool, 0, offsetof(Mount, read_write_only)
+Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
+Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where)
+Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
+Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype)
+Mount.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Mount, timeout_usec)
+Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
+Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options)
+Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount)
+Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount)
+Mount.ReadWriteOnly, config_parse_bool, 0, offsetof(Mount, read_write_only)
EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
m4_dnl
-Automount.Where, config_parse_unit_path_printf, 0, offsetof(Automount, where)
-Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
-Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec)
+Automount.Where, config_parse_unit_path_printf, 0, offsetof(Automount, where)
+Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
+Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec)
m4_dnl
-Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what)
-Swap.Priority, config_parse_swap_priority, 0, 0
-Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
-Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec)
+Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what)
+Swap.Priority, config_parse_swap_priority, 0, 0
+Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
+Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec)
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
m4_dnl
-Timer.OnCalendar, config_parse_timer, TIMER_CALENDAR, 0
-Timer.OnActiveSec, config_parse_timer, TIMER_ACTIVE, 0
-Timer.OnBootSec, config_parse_timer, TIMER_BOOT, 0
-Timer.OnStartupSec, config_parse_timer, TIMER_STARTUP, 0
-Timer.OnUnitActiveSec, config_parse_timer, TIMER_UNIT_ACTIVE, 0
-Timer.OnUnitInactiveSec, config_parse_timer, TIMER_UNIT_INACTIVE, 0
-Timer.OnClockChange, config_parse_bool, 0, offsetof(Timer, on_clock_change)
-Timer.OnTimezoneChange, config_parse_bool, 0, offsetof(Timer, on_timezone_change)
-Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
-Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
-Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
-Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
-Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
-Timer.Unit, config_parse_trigger_unit, 0, 0
+Timer.OnCalendar, config_parse_timer, TIMER_CALENDAR, 0
+Timer.OnActiveSec, config_parse_timer, TIMER_ACTIVE, 0
+Timer.OnBootSec, config_parse_timer, TIMER_BOOT, 0
+Timer.OnStartupSec, config_parse_timer, TIMER_STARTUP, 0
+Timer.OnUnitActiveSec, config_parse_timer, TIMER_UNIT_ACTIVE, 0
+Timer.OnUnitInactiveSec, config_parse_timer, TIMER_UNIT_INACTIVE, 0
+Timer.OnClockChange, config_parse_bool, 0, offsetof(Timer, on_clock_change)
+Timer.OnTimezoneChange, config_parse_bool, 0, offsetof(Timer, on_timezone_change)
+Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
+Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
+Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
+Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
+Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
+Timer.Unit, config_parse_trigger_unit, 0, 0
m4_dnl
-Path.PathExists, config_parse_path_spec, 0, 0
-Path.PathExistsGlob, config_parse_path_spec, 0, 0
-Path.PathChanged, config_parse_path_spec, 0, 0
-Path.PathModified, config_parse_path_spec, 0, 0
-Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0
-Path.Unit, config_parse_trigger_unit, 0, 0
-Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory)
-Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode)
+Path.PathExists, config_parse_path_spec, 0, 0
+Path.PathExistsGlob, config_parse_path_spec, 0, 0
+Path.PathChanged, config_parse_path_spec, 0, 0
+Path.PathModified, config_parse_path_spec, 0, 0
+Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0
+Path.Unit, config_parse_trigger_unit, 0, 0
+Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory)
+Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode)
m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Slice)m4_dnl
m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl
-Scope.RuntimeMaxSec, config_parse_sec, 0, offsetof(Scope, runtime_max_usec)
-Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec)
+Scope.RuntimeMaxSec, config_parse_sec, 0, offsetof(Scope, runtime_max_usec)
+Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec)
m4_dnl The [Install] section is ignored here.
-Install.Alias, NULL, 0, 0
-Install.WantedBy, NULL, 0, 0
-Install.RequiredBy, NULL, 0, 0
-Install.Also, NULL, 0, 0
-Install.DefaultInstance, NULL, 0, 0
+Install.Alias, NULL, 0, 0
+Install.WantedBy, NULL, 0, 0
+Install.RequiredBy, NULL, 0, 0
+Install.Also, NULL, 0, 0
+Install.DefaultInstance, NULL, 0, 0
#include "capability-util.h"
#include "cgroup-setup.h"
#include "conf-parser.h"
+#include "core-varlink.h"
#include "cpu-set-util.h"
#include "env-util.h"
#include "errno-list.h"
return 0;
}
+int config_parse_exec_mount_apivfs(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) {
+
+ ExecContext *c = data;
+ int k;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ c->mount_apivfs_set = false;
+ c->mount_apivfs = false;
+ return 0;
+ }
+
+ k = parse_boolean(rvalue);
+ if (k < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, k,
+ "Failed to parse boolean value, ignoring: %s",
+ rvalue);
+ return 0;
+ }
+
+ c->mount_apivfs_set = true;
+ c->mount_apivfs = k;
+ return 0;
+}
+
int config_parse_numa_mask(const char *unit,
const char *filename,
unsigned line,
return 0;
}
+int config_parse_managed_oom_mode(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ ManagedOOMMode *mode = data, m;
+ UnitType t;
+
+ t = unit_name_to_type(unit);
+ assert(t != _UNIT_TYPE_INVALID);
+
+ if (!unit_vtable[t]->can_set_managed_oom)
+ return log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is not supported for this unit type, ignoring.", lvalue);
+
+ if (isempty(rvalue)) {
+ *mode = MANAGED_OOM_AUTO;
+ 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);
+ return 0;
+ }
+ *mode = m;
+ return 0;
+}
+
+int config_parse_managed_oom_mem_pressure_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ int *limit = data;
+ UnitType t;
+ int r;
+
+ t = unit_name_to_type(unit);
+ assert(t != _UNIT_TYPE_INVALID);
+
+ if (!unit_vtable[t]->can_set_managed_oom)
+ return log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is not supported for this unit type, ignoring.", lvalue);
+
+ if (isempty(rvalue)) {
+ *limit = 0;
+ return 0;
+ }
+
+ r = parse_percent(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse limit percent value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *limit = r;
+ return 0;
+}
+
int config_parse_device_allow(
const char *unit,
const char *filename,
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_apivfs);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
CONFIG_PARSER_PROTOTYPE(config_parse_root_image_options);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
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_device_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);
#include "fd-util.h"
#include "fs-util.h"
#include "id128-util.h"
+#include "io-util.h"
#include "log.h"
#include "machine-id-setup.h"
#include "macro.h"
return 0;
}
-int machine_id_setup(const char *root, sd_id128_t machine_id, sd_id128_t *ret) {
+int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_id, sd_id128_t *ret) {
const char *etc_machine_id, *run_machine_id;
_cleanup_close_ int fd = -1;
bool writable;
if (ftruncate(fd, 0) < 0)
return log_error_errno(errno, "Failed to truncate %s: %m", etc_machine_id);
- if (id128_write_fd(fd, ID128_PLAIN, machine_id, true) >= 0)
- goto finish;
+ /* If the caller requested a transient machine-id, write the string "uninitialized\n" to
+ * disk and overmount it with a transient file.
+ *
+ * Otherwise write the machine-id directly to disk. */
+ if (force_transient) {
+ r = loop_write(fd, "uninitialized\n", strlen("uninitialized\n"), false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write uninitialized %s: %m", etc_machine_id);
+
+ r = fsync_full(fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sync %s: %m", etc_machine_id);
+ } else {
+ r = id128_write_fd(fd, ID128_PLAIN, machine_id, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write %s: %m", etc_machine_id);
+ else
+ goto finish;
+ }
}
fd = safe_close(fd);
- /* Hmm, we couldn't write it? So let's write it to /run/machine-id as a replacement */
+ /* Hmm, we couldn't or shouldn't write the machine-id to /etc?
+ * So let's write it to /run/machine-id as a replacement */
run_machine_id = prefix_roota(root, "/run/machine-id");
return r;
}
- log_info("Installed transient %s file.", etc_machine_id);
+ log_full(force_transient ? LOG_DEBUG : LOG_INFO, "Installed transient %s file.", etc_machine_id);
/* Mark the mount read-only */
r = mount_follow_verbose(LOG_WARNING, NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL);
int machine_id_commit(const char *root) {
_cleanup_close_ int fd = -1, initial_mntns_fd = -1;
- const char *etc_machine_id;
+ const char *etc_machine_id, *sync_path;
sd_id128_t id;
int r;
+ /* Before doing anything, sync everything to ensure any changes by first-boot units are persisted.
+ *
+ * First, explicitly sync the file systems we care about and check if it worked. */
+ FOREACH_STRING(sync_path, "/etc/", "/var/") {
+ r = syncfs_path(AT_FDCWD, sync_path);
+ if (r < 0)
+ return log_error_errno(r, "Cannot sync %s: %m", sync_path);
+ }
+
+ /* Afterwards, sync() the rest too, but we can't check the return value for these. */
+ sync();
+
/* Replaces a tmpfs bind mount of /etc/machine-id by a proper file, atomically. For this, the umount is removed
* in a mount namespace, a new file is created at the right place. Afterwards the mount is also removed in the
* original mount namespace, thus revealing the file that was just created. */
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <stdbool.h>
+
int machine_id_commit(const char *root);
-int machine_id_setup(const char *root, sd_id128_t requested, sd_id128_t *ret);
+int machine_id_setup(const char *root, bool force_transient, sd_id128_t requested, sd_id128_t *ret);
assert_not_reached("Unhandled option code.");
}
- if (optind < argc && getpid_cached() != 1) {
+ if (optind < argc && getpid_cached() != 1)
/* Hmm, when we aren't run as init system
* let's complain about excess arguments */
-
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Excess arguments.");
- }
return 0;
}
else
log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
- } else if (!in_initrd()) {
+ } else if (!in_initrd())
/*
* Do a dummy very first call to seal the kernel's time warp magic.
*
* be treated as UTC that way.
*/
(void) clock_reset_timewarp();
- }
r = clock_apply_epoch();
if (r < 0)
*ret_first_boot = false;
log_info("Running in initial RAM disk.");
} else {
- /* Let's check whether we are in first boot, i.e. whether /etc is still unpopulated. We use
- * /etc/machine-id as flag file, for this: if it exists we assume /etc is populated, if it
- * doesn't it's unpopulated. This allows container managers and installers to provision a
- * couple of files already. If the container manager wants to provision the machine ID itself
- * it should pass $container_uuid to PID 1. */
-
- *ret_first_boot = access("/etc/machine-id", F_OK) < 0;
- if (*ret_first_boot)
- log_info("Running with unpopulated /etc.");
+ int r;
+ _cleanup_free_ char *id_text = NULL;
+
+ /* Let's check whether we are in first boot. We use /etc/machine-id as flag file
+ * for this: If it is missing or contains the value "uninitialized", this is the
+ * first boot. In any other case, it is not. This allows container managers and
+ * installers to provision a couple of files already. If the container manager
+ * wants to provision the machine ID itself it should pass $container_uuid to PID 1. */
+
+ r = read_one_line_file("/etc/machine-id", &id_text);
+ if (r < 0 || streq(id_text, "uninitialized")) {
+ if (r < 0 && r != -ENOENT)
+ log_warning_errno(r, "Unexpected error while reading /etc/machine-id, ignoring: %m");
+
+ *ret_first_boot = true;
+ log_info("Detected first boot.");
+ } else {
+ *ret_first_boot = false;
+ log_debug("Detected initialized system, this is not the first boot.");
+ }
}
} else {
if (DEBUG_LOGGING) {
static int initialize_runtime(
bool skip_setup,
+ bool first_boot,
struct rlimit *saved_rlimit_nofile,
struct rlimit *saved_rlimit_memlock,
const char **ret_error_message) {
status_welcome();
hostname_setup();
- machine_id_setup(NULL, arg_machine_id, NULL);
+ /* Force transient machine-id on first boot. */
+ machine_id_setup(NULL, first_boot, arg_machine_id, NULL);
(void) loopback_setup();
bump_unix_max_dgram_qlen();
bump_file_max_and_nr_open();
log_execution_mode(&first_boot);
r = initialize_runtime(skip_setup,
+ first_boot,
&saved_rlimit_nofile,
&saved_rlimit_memlock,
&error_message);
* We only do this for the cgroup the PID belonged to. */
(void) unit_check_oom(u1);
+ /* This only logs for now. In the future when the interface for kills/notifications
+ * is more stable we can extend service results table similar to how kernel oom kills
+ * are managed. */
+ (void) unit_check_oomd_kill(u1);
+
manager_invoke_sigchld_event(m, u1, &si);
}
if (u2)
assert(m);
assert(f);
+ if (DEBUG_LOGGING) {
+ if (fdset_isempty(fds))
+ log_debug("No file descriptors passed");
+ else {
+ int fd;
+
+ FDSET_FOREACH(fd, fds) {
+ _cleanup_free_ char *fn = NULL;
+
+ r = fd_get_path(fd, &fn);
+ if (r < 0)
+ log_debug_errno(r, "Received serialized fd %i → %m", fd);
+ else
+ log_debug("Received serialized fd %i → %s", fd, strna(fn));
+ }
+ }
+ }
+
log_debug("Deserializing state...");
/* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have
bool honor_device_enumeration;
VarlinkServer *varlink_server;
+ /* Only systemd-oomd should be using this to subscribe to changes in ManagedOOM settings */
+ Varlink *managed_oom_varlink_request;
};
static inline usec_t manager_default_timeout_abort_usec(Manager *m) {
NULL, MNT_NONE, },
};
-/* These are API file systems that might be mounted by other software,
- * we just list them here so that we know that we should ignore them */
-
-static const char ignore_paths[] =
- /* SELinux file systems */
- "/sys/fs/selinux\0"
- /* Container bind mounts */
- "/proc/sys\0"
- "/dev/console\0"
- "/proc/kmsg\0";
-
bool mount_point_is_api(const char *path) {
unsigned i;
}
bool mount_point_ignore(const char *path) {
+
const char *i;
- NULSTR_FOREACH(i, ignore_paths)
+ /* These are API file systems that might be mounted by other software, we just list them here so that
+ * we know that we should ignore them. */
+ FOREACH_STRING(i,
+ /* SELinux file systems */
+ "/sys/fs/selinux",
+ /* Container bind mounts */
+ "/dev/console",
+ "/proc/kmsg",
+ "/proc/sys",
+ "/proc/sys/kernel/random/boot_id")
if (path_equal(path, i))
return true;
+ if (path_startswith(path, "/run/host")) /* All mounts passed in from the container manager are
+ * something we better ignore. */
+ return true;
+
return false;
}
if (r < 0)
goto finish;
- if (ns_info->private_dev) {
+ if (ns_info->private_dev)
*(m++) = (MountEntry) {
.path_const = "/dev",
.mode = PRIVATE_DEV,
.flags = DEV_MOUNT_OPTIONS,
};
- }
if (ns_info->protect_kernel_tunables) {
r = append_static_mounts(&m,
goto finish;
}
- if (ns_info->protect_control_groups) {
+ if (ns_info->protect_control_groups)
*(m++) = (MountEntry) {
.path_const = "/sys/fs/cgroup",
.mode = READONLY,
};
- }
r = append_protect_home(&m, ns_info->protect_home, ns_info->ignore_protect_paths);
if (r < 0)
.can_delegate = true,
.can_fail = true,
.once_only = true,
+ .can_set_managed_oom = true,
.init = scope_init,
.load = scope_load,
log_open();
if (enforce > 0) {
- if (!initialized) {
- log_emergency("Failed to load SELinux policy.");
- return -EIO;
- }
+ if (!initialized)
+ return log_emergency_errno(SYNTHETIC_ERRNO(EIO),
+ "Failed to load SELinux policy.");
log_warning("Failed to load new SELinux policy. Continuing with old policy.");
} else
else
log_unit_debug(u, "D-Bus name %s now not owned by anyone.", s->bus_name);
- s->bus_name_good = !!new_owner;
+ s->bus_name_good = new_owner;
/* Track the current owner, so we can reconstruct changes after a daemon reload */
r = free_and_strdup(&s->bus_name_owner, new_owner);
.can_transient = true,
.can_delegate = true,
.can_fail = true,
+ .can_set_managed_oom = true,
.init = service_init,
.done = service_done,
.private_section = "Slice",
.can_transient = true,
+ .can_set_managed_oom = true,
.init = slice_init,
.load = slice_load,
assert(fd >= 0);
assert(s);
- r = getpeername(fd, &sa.peer.sa, &salen);
- if (r < 0)
+ if (getpeername(fd, &sa.peer.sa, &salen) < 0)
return log_unit_error_errno(UNIT(s), errno, "getpeername failed: %m");
if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
catalog_dir=/usr/lib/systemd/catalog
catalogdir=${catalog_dir}
-system_uid_max=@systemuidmax@
+system_uid_max=@SYSTEM_UID_MAX@
systemuidmax=${system_uid_max}
-system_gid_max=@systemgidmax@
+system_gid_max=@SYSTEM_GID_MAX@
systemgidmax=${system_gid_max}
dynamic_uid_min=@dynamicuidmin@
#include "bus-util.h"
#include "cgroup-setup.h"
#include "cgroup-util.h"
+#include "core-varlink.h"
#include "dbus-unit.h"
#include "dbus.h"
#include "dropin.h"
return 0;
}
+static int unit_add_oomd_dependencies(Unit *u) {
+ CGroupContext *c;
+ bool wants_oomd;
+ int r;
+
+ assert(u);
+
+ if (!u->default_dependencies)
+ return 0;
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return 0;
+
+ wants_oomd = (c->moom_swap == MANAGED_OOM_KILL || c->moom_mem_pressure == MANAGED_OOM_KILL);
+ if (!wants_oomd)
+ return 0;
+
+ r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, "systemd-oomd.service", true, UNIT_DEPENDENCY_FILE);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static int unit_add_startup_units(Unit *u) {
CGroupContext *c;
if (r < 0)
goto fail;
+ r = unit_add_oomd_dependencies(u);
+ if (r < 0)
+ goto fail;
+
r = unit_add_startup_units(u);
if (r < 0)
goto fail;
unit_add_to_dbus_queue(unit_follow_merge(u));
unit_add_to_gc_queue(u);
+ (void) manager_varlink_send_managed_oom_update(u);
return 0;
* the bus queue, so that any job change signal queued will force out the unit change signal first. */
unit_add_to_dbus_queue(u);
+ /* Update systemd-oomd on the property/state change */
+ if (os != ns) {
+ /* Always send an update if the unit is going into an inactive state so systemd-oomd knows to stop
+ * monitoring.
+ * Also send an update whenever the unit goes active; this is to handle a case where an override file
+ * sets one of the ManagedOOM*= properties to "kill", then later removes it. systemd-oomd needs to
+ * know to stop monitoring when the unit changes from "kill" -> "auto" on daemon-reload, but we don't
+ * have the information on the property. Thus, indiscriminately send an update. */
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns) || UNIT_IS_ACTIVE_OR_RELOADING(ns))
+ (void) manager_varlink_send_managed_oom_update(u);
+ }
+
/* Update timestamps for state changes */
if (!MANAGER_IS_RELOADING(m)) {
dual_timestamp_get(&u->state_change_timestamp);
};
Unit *original_u = u, *original_other = other;
int r;
+ /* Helper to know whether sending a notification is necessary or not:
+ * if the dependency is already there, no need to notify! */
+ bool noop = true;
assert(u);
assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) {
r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
if (add_reference) {
r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
- unit_add_to_dbus_queue(u);
+ if (!noop)
+ unit_add_to_dbus_queue(u);
return 0;
}
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);
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);
return TAKE_PTR(pid_set);
}
+static int kill_common_log(pid_t pid, int signo, void *userdata) {
+ _cleanup_free_ char *comm = NULL;
+ Unit *u = userdata;
+
+ assert(u);
+
+ (void) get_process_comm(pid, &comm);
+ log_unit_info(u, "Sending signal SIG%s to process " PID_FMT " (%s) on client request.",
+ signal_to_string(signo), pid, strna(comm));
+
+ return 1;
+}
+
int unit_kill_common(
Unit *u,
KillWho who,
int r = 0;
bool killed = false;
+ /* This is the common implementation for explicit user-requested killing of unit processes, shared by
+ * various unit types. Do not confuse with unit_kill_context(), which is what we use when we want to
+ * stop a service ourselves. */
+
if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) {
if (main_pid < 0)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
- else if (main_pid == 0)
+ if (main_pid == 0)
return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
}
if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)) {
if (control_pid < 0)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
- else if (control_pid == 0)
+ if (control_pid == 0)
return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
}
if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL))
if (control_pid > 0) {
- if (kill(control_pid, signo) < 0)
- r = -errno;
- else
+ _cleanup_free_ char *comm = NULL;
+ (void) get_process_comm(control_pid, &comm);
+
+ if (kill(control_pid, signo) < 0) {
+ /* Report this failure both to the logs and to the client */
+ sd_bus_error_set_errnof(
+ error, errno,
+ "Failed to send signal SIG%s to control process " PID_FMT " (%s): %m",
+ signal_to_string(signo), control_pid, strna(comm));
+ r = log_unit_warning_errno(
+ u, errno,
+ "Failed to send signal SIG%s to control process " PID_FMT " (%s) on client request: %m",
+ signal_to_string(signo), control_pid, strna(comm));
+ } else {
+ log_unit_info(u, "Sent signal SIG%s to control process " PID_FMT " (%s) on client request.",
+ signal_to_string(signo), control_pid, strna(comm));
killed = true;
+ }
}
if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL))
if (main_pid > 0) {
- if (kill(main_pid, signo) < 0)
- r = -errno;
- else
+ _cleanup_free_ char *comm = NULL;
+ (void) get_process_comm(main_pid, &comm);
+
+ if (kill(main_pid, signo) < 0) {
+ if (r == 0)
+ sd_bus_error_set_errnof(
+ error, errno,
+ "Failed to send signal SIG%s to main process " PID_FMT " (%s): %m",
+ signal_to_string(signo), main_pid, strna(comm));
+
+ r = log_unit_warning_errno(
+ u, errno,
+ "Failed to send signal SIG%s to main process " PID_FMT " (%s) on client request: %m",
+ signal_to_string(signo), main_pid, strna(comm));
+ } else {
+ log_unit_info(u, "Sent signal SIG%s to main process " PID_FMT " (%s) on client request.",
+ signal_to_string(signo), main_pid, strna(comm));
killed = true;
+ }
}
if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path) {
/* Exclude the main/control pids from being killed via the cgroup */
pid_set = unit_pid_set(main_pid, control_pid);
if (!pid_set)
- return -ENOMEM;
+ return log_oom();
- q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, NULL, NULL);
- if (q < 0 && !IN_SET(q, -EAGAIN, -ESRCH, -ENOENT))
- r = q;
- else
+ q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, kill_common_log, u);
+ if (q < 0) {
+ if (!IN_SET(q, -ESRCH, -ENOENT)) {
+ if (r == 0)
+ sd_bus_error_set_errnof(
+ error, q,
+ "Failed to send signal SIG%s to auxiliary processes: %m",
+ signal_to_string(signo));
+
+ r = log_unit_warning_errno(
+ u, q,
+ "Failed to send signal SIG%s to auxiliary processes on client request: %m",
+ signal_to_string(signo));
+ }
+ } else
killed = true;
}
- if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL))
- return -ESRCH;
+ /* If the "fail" versions of the operation are requested, then complain if the set of processes we killed is empty */
+ if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_MAIN_FAIL))
+ return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No matching processes to kill");
return r;
}
assert(u);
assert(c);
- /* Kill the processes belonging to this unit, in preparation for shutting the unit down.
- * Returns > 0 if we killed something worth waiting for, 0 otherwise. */
+ /* Kill the processes belonging to this unit, in preparation for shutting the unit down. Returns > 0
+ * if we killed something worth waiting for, 0 otherwise. Do not confuse with unit_kill_common()
+ * which is used for user-requested killing of unit processes. */
if (c->kill_mode == KILL_NONE)
return 0;
done = true;
HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) {
- if ((di.origin_mask & ~mask) == di.origin_mask)
+ if (FLAGS_SET(~mask, di.origin_mask))
continue;
di.origin_mask &= ~mask;
unit_update_dependency_mask(u, d, other, di);
UnitDependencyInfo dj;
dj.data = hashmap_get(other->dependencies[q], u);
- if ((dj.destination_mask & ~mask) == dj.destination_mask)
+ if (FLAGS_SET(~mask, dj.destination_mask))
continue;
dj.destination_mask &= ~mask;
nsec_t cpu_usage_base;
nsec_t cpu_usage_last; /* the most recently read value */
- /* The current counter of the oom_kill field in the memory.events cgroup attribute */
+ /* The current counter of processes sent SIGKILL by systemd-oomd */
+ uint64_t managed_oom_kill_last;
+
+ /* The current counter of the oom_kill field in the memory.events cgroup attribute */
uint64_t oom_kill_last;
/* Where the io.stat data was at the time the unit was started */
/* True if queued jobs of this type should be GC'ed if no other job needs them anymore */
bool gc_jobs:1;
+
+ /* True if systemd-oomd can monitor and act on this unit's recursive children's cgroup(s) */
+ bool can_set_managed_oom:1;
} UnitVTable;
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
#include "string-util.h"
#include "strv.h"
#include "tmpfile-util.h"
+#include "user-record.h"
#include "user-util.h"
/* The maximum size up to which we process coredumps */
if (r < 0)
return log_error_errno(r, "Failed to parse resource limit '%s': %m",
context->meta[META_ARGV_RLIMIT]);
- if (rlimit < page_size()) {
+ if (rlimit < page_size())
/* Is coredumping disabled? Then don't bother saving/processing the
* coredump. Anything below PAGE_SIZE cannot give a readable coredump
* (the kernel uses ELF_EXEC_PAGESIZE which is not easily accessible, but
return log_info_errno(SYNTHETIC_ERRNO(EBADSLT),
"Resource limits disable core dumping for process %s (%s).",
context->meta[META_ARGV_PID], context->meta[META_COMM]);
- }
process_limit = MAX(arg_process_size_max, storage_size_max());
if (process_limit == 0)
if (r < 0)
return r;
- if (uid <= SYSTEM_UID_MAX) {
+ if (uid_is_system(uid)) {
const char *user = "systemd-coredump";
r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
_cleanup_fclose_ FILE *f = NULL;
int r;
- if (arg_field) {
- log_error("Option --field/-F only makes sense with list");
- return -EINVAL;
- }
+ if (arg_field)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Option --field/-F only makes sense with list");
r = acquire_journal(&j, argv + 1);
if (r < 0)
if (!debugger)
return -ENOMEM;
- if (arg_field) {
- log_error("Option --field/-F only makes sense with list");
- return -EINVAL;
- }
+ if (arg_field)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Option --field/-F only makes sense with list");
r = acquire_journal(&j, argv + 1);
if (r < 0)
if (!exe)
return log_oom();
- if (endswith(exe, " (deleted)")) {
- log_error("Binary already deleted.");
- return -ENOENT;
- }
+ if (endswith(exe, " (deleted)"))
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "Binary already deleted.");
- if (!path_is_absolute(exe)) {
- log_error("Binary is not an absolute path.");
- return -ENOENT;
- }
+ if (!path_is_absolute(exe))
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "Binary is not an absolute path.");
r = save_core(j, NULL, &path, &unlink_path);
if (r < 0)
char *uuid;
char *keyfile;
char *keydev;
+ char *headerdev;
+ char *datadev;
char *name;
char *options;
bool create;
STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep);
-static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) {
- _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
+static int split_locationspec(const char *locationspec, char **ret_file, char **ret_device) {
+ _cleanup_free_ char *file = NULL, *device = NULL;
const char *c;
- assert(ret_keyfile);
- assert(ret_keydev);
+ assert(ret_file);
+ assert(ret_device);
- if (!keyspec) {
- *ret_keyfile = *ret_keydev = NULL;
+ if (!locationspec) {
+ *ret_file = *ret_device = NULL;
return 0;
}
- c = strrchr(keyspec, ':');
+ c = strrchr(locationspec, ':');
if (c) {
- /* The keydev part has to be either an absolute path to device node (/dev/something,
+ /* The device part has to be either an absolute path to device node (/dev/something,
* /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device
- * specification starting with LABEL= or similar. The keyfile part has the same syntax.
+ * specification starting with LABEL= or similar. The file part has the same syntax.
*
- * Let's try to guess if the second part looks like a keydev specification, or just part of a
+ * Let's try to guess if the second part looks like a device specification, or just part of a
* filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to
* an absolute path. If we didn't get an absolute path, assume that it is just part of the
- * first keyfile argument. */
+ * first file argument. */
- keydev = fstab_node_to_udev_node(c + 1);
- if (!keydev)
+ device = fstab_node_to_udev_node(c + 1);
+ if (!device)
return log_oom();
- if (path_is_absolute(keydev))
- keyfile = strndup(keyspec, c-keyspec);
+ if (path_is_absolute(device))
+ file = strndup(locationspec, c-locationspec);
else {
- log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
+ log_debug("Location specification argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
"Assuming that \"%s\" is a single device specification.",
- c + 1, keyspec);
- keydev = mfree(keydev);
+ c + 1, locationspec);
+ device = mfree(device);
c = NULL;
}
}
if (!c)
- /* No keydev specified */
- keyfile = strdup(keyspec);
+ /* No device specified */
+ file = strdup(locationspec);
- if (!keyfile)
+ if (!file)
return log_oom();
- *ret_keyfile = TAKE_PTR(keyfile);
- *ret_keydev = TAKE_PTR(keydev);
+ *ret_file = TAKE_PTR(file);
+ *ret_device = TAKE_PTR(device);
return 0;
}
-static int generate_keydev_mount(
+static int generate_device_mount(
const char *name,
- const char *keydev,
- const char *keydev_timeout,
+ const char *device,
+ const char *type_prefix, /* "keydev" or "headerdev" */
+ const char *device_timeout,
bool canfail,
+ bool readonly,
char **unit,
char **mount) {
usec_t timeout_us;
assert(name);
- assert(keydev);
+ assert(device);
assert(unit);
assert(mount);
if (!name_escaped)
return -ENOMEM;
- where = strjoin(arg_runtime_directory, "/keydev-", name_escaped);
+ where = strjoin(arg_runtime_directory, "/", type_prefix, "-", name_escaped);
if (!where)
return -ENOMEM;
"[Mount]\n"
"What=%s\n"
"Where=%s\n"
- "Options=ro%s\n", keydev, where, canfail ? ",nofail" : "");
+ "Options=%s%s\n", device, where, readonly ? "ro" : "rw", canfail ? ",nofail" : "");
- if (keydev_timeout) {
- r = parse_sec_fix_0(keydev_timeout, &timeout_us);
+ if (device_timeout) {
+ r = parse_sec_fix_0(device_timeout, &timeout_us);
if (r >= 0) {
- r = unit_name_from_path(keydev, ".device", &device_unit);
+ r = unit_name_from_path(device, ".device", &device_unit);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout",
"# Automatically generated by systemd-cryptsetup-generator \n\n"
- "[Unit]\nJobRunningTimeoutSec=%s", keydev_timeout);
+ "[Unit]\nJobRunningTimeoutSec=%s", device_timeout);
if (r < 0)
return log_error_errno(r, "Failed to write device drop-in: %m");
} else
- log_warning_errno(r, "Failed to parse %s, ignoring: %m", keydev_timeout);
+ log_warning_errno(r, "Failed to parse %s, ignoring: %m", device_timeout);
}
return 0;
}
-static int generate_keydev_umount(const char *name,
- const char *keydev_mount,
+static int generate_device_umount(const char *name,
+ const char *device_mount,
+ const char *type_prefix, /* "keydev" or "headerdev" */
char **ret_umount_unit) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *u = NULL, *name_escaped = NULL, *mount = NULL;
if (!name_escaped)
return -ENOMEM;
- u = strjoin("keydev-", name_escaped, "-umount.service");
+ u = strjoin(type_prefix, "-", name_escaped, "-umount.service");
if (!u)
return -ENOMEM;
- r = unit_name_from_path(keydev_mount, ".mount", &mount);
+ r = unit_name_from_path(device_mount, ".mount", &mount);
if (r < 0)
return r;
"DefaultDependencies=no\n"
"After=%s\n\n"
"[Service]\n"
- "ExecStart=-" UMOUNT_PATH " %s\n\n", mount, keydev_mount);
+ "ExecStart=-" UMOUNT_PATH " %s\n\n", mount, device_mount);
r = fflush_and_check(f);
if (r < 0)
const char *device,
const char *password,
const char *keydev,
+ const char *headerdev,
const char *options,
const char *source) {
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*keydev_mount = NULL, *keyfile_timeout_value = NULL,
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL,
- *tmp_fstype = NULL;
+ *tmp_fstype = NULL, *filtered_header = NULL, *headerdev_mount = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *dmname;
bool noauto, nofail, swap, netdev, attach_in_initrd;
if (keyfile_can_timeout < 0)
return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m");
- detached_header = fstab_filter_options(options, "header\0", NULL, &header_path, NULL);
+ detached_header = fstab_filter_options(
+ options,
+ "header\0",
+ NULL,
+ &header_path,
+ headerdev ? &filtered_header : NULL);
if (detached_header < 0)
return log_error_errno(detached_header, "Failed to parse header= option value: %m");
if (keydev) {
_cleanup_free_ char *unit = NULL, *umount_unit = NULL;
- r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
+ r = generate_device_mount(
+ name,
+ keydev,
+ "keydev",
+ keyfile_timeout_value,
+ /* canfail = */ keyfile_can_timeout > 0,
+ /* readonly= */ true,
+ &unit,
+ &keydev_mount);
if (r < 0)
return log_error_errno(r, "Failed to generate keydev mount unit: %m");
- r = generate_keydev_umount(name, keydev_mount, &umount_unit);
+ r = generate_device_umount(name, keydev_mount, "keydev", &umount_unit);
if (r < 0)
return log_error_errno(r, "Failed to generate keydev umount unit: %m");
else
fprintf(f, "Requires=%s\n", unit);
+ if (umount_unit)
+ fprintf(f,
+ "Wants=%s\n"
+ "Before=%s\n",
+ umount_unit,
+ umount_unit
+ );
+ }
+
+ if (headerdev) {
+ _cleanup_free_ char *unit = NULL, *umount_unit = NULL, *p = NULL;
+
+ r = generate_device_mount(
+ name,
+ headerdev,
+ "headerdev",
+ NULL,
+ /* canfail= */ false, /* header is always necessary */
+ /* readonly= */ false, /* LUKS2 recovery requires rw header access */
+ &unit,
+ &headerdev_mount);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate header device mount unit: %m");
+
+ r = generate_device_umount(name, headerdev_mount, "headerdev", &umount_unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate header device umount unit: %m");
+
+ p = path_join(headerdev_mount, header_path);
+ if (!p)
+ return log_oom();
+
+ free_and_replace(header_path, p);
+
+ if (isempty(filtered_header))
+ p = strjoin("header=", header_path);
+ else
+ p = strjoin(filtered_header, ",header=", header_path);
+
+ if (!p)
+ return log_oom();
+
+ free_and_replace(filtered_header, p);
+ options = filtered_header;
+
+ fprintf(f, "After=%s\n"
+ "Requires=%s\n", unit, unit);
+
if (umount_unit) {
fprintf(f,
"Wants=%s\n"
}
}
+ const char *target;
+ if (in_initrd())
+ target = "initrd-cryptsetup.target";
+ else if (netdev)
+ target = "remote-cryptsetup.target";
+ else
+ target = "cryptsetup.target";
+
if (!nofail)
- fprintf(f,
- "Before=%s\n",
- netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
+ fprintf(f, "Before=%s\n", target);
if (password && !keydev) {
r = print_dependencies(f, password);
}
/* Check if a header option was specified */
- if (detached_header > 0) {
+ if (detached_header > 0 && !headerdev) {
r = print_dependencies(f, header_path);
if (r < 0)
return r;
return log_error_errno(r, "Failed to write unit file %s: %m", n);
if (!noauto) {
- r = generator_add_symlink(arg_dest,
- netdev ? "remote-cryptsetup.target" : "cryptsetup.target",
+ r = generator_add_symlink(arg_dest, target,
nofail ? "wants" : "requires", n);
if (r < 0)
return r;
return d;
}
+static bool warn_uuid_invalid(const char *uuid, const char *key) {
+ assert(key);
+
+ if (!id128_is_valid(uuid)) {
+ log_warning("Failed to parse %s= kernel command line switch. UUID is invalid, ignoring.", key);
+ return true;
+ }
+
+ return false;
+}
+
+static int filter_header_device(const char *options,
+ char **ret_headerdev,
+ char **ret_filtered_headerdev_options) {
+ int r;
+ _cleanup_free_ char *headerfile = NULL, *headerdev = NULL, *headerspec = NULL,
+ *filtered_headerdev = NULL, *filtered_headerspec = NULL;
+
+ assert(ret_headerdev);
+ assert(ret_filtered_headerdev_options);
+
+ r = fstab_filter_options(options, "header\0", NULL, &headerspec, &filtered_headerspec);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse header= option value: %m");
+
+ if (r > 0) {
+ r = split_locationspec(headerspec, &headerfile, &headerdev);
+ if (r < 0)
+ return r;
+
+ if (isempty(filtered_headerspec))
+ filtered_headerdev = strjoin("header=", headerfile);
+ else
+ filtered_headerdev = strjoin(filtered_headerspec, ",header=", headerfile);
+
+ if (!filtered_headerdev)
+ return log_oom();
+ } else
+ filtered_headerdev = TAKE_PTR(filtered_headerspec);
+
+ *ret_filtered_headerdev_options = TAKE_PTR(filtered_headerdev);
+ *ret_headerdev = TAKE_PTR(headerdev);
+
+ return 0;
+}
+
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
_cleanup_free_ char *uuid = NULL, *uuid_value = NULL;
crypto_device *d;
d->create = arg_allow_list = true;
} else if (streq(key, "luks.options")) {
+ _cleanup_free_ char *headerdev = NULL, *filtered_headerdev_options = NULL;
if (proc_cmdline_value_missing(key, value))
return 0;
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
- if (r == 2) {
- d = get_crypto_device(uuid);
- if (!d)
- return log_oom();
+ if (r != 2)
+ return free_and_strdup(&arg_default_options, value) < 0 ? log_oom() : 0;
- free_and_replace(d->options, uuid_value);
- } else if (free_and_strdup(&arg_default_options, value) < 0)
+ if (warn_uuid_invalid(uuid, key))
+ return 0;
+
+ d = get_crypto_device(uuid);
+ if (!d)
return log_oom();
+ r = filter_header_device(uuid_value, &headerdev, &filtered_headerdev_options);
+ if (r < 0)
+ return r;
+
+ free_and_replace(d->options, filtered_headerdev_options);
+ free_and_replace(d->headerdev, headerdev);
} else if (streq(key, "luks.key")) {
size_t n;
_cleanup_free_ char *keyfile = NULL, *keydev = NULL;
if (proc_cmdline_value_missing(key, value))
return 0;
- n = strspn(value, LETTERS DIGITS "-");
+ n = strspn(value, ALPHANUMERICAL "-");
if (value[n] != '=') {
if (free_and_strdup(&arg_default_keyfile, value) < 0)
return log_oom();
if (!uuid)
return log_oom();
- if (!id128_is_valid(uuid)) {
- log_warning("Failed to parse luks.key= kernel command line switch. UUID is invalid, ignoring.");
+ if (warn_uuid_invalid(uuid, key))
return 0;
- }
d = get_crypto_device(uuid);
if (!d)
return log_oom();
keyspec = value + n + 1;
- r = split_keyspec(keyspec, &keyfile, &keydev);
+ r = split_locationspec(keyspec, &keyfile, &keydev);
if (r < 0)
return r;
free_and_replace(d->keyfile, keyfile);
free_and_replace(d->keydev, keydev);
+ } else if (streq(key, "luks.data")) {
+ size_t n;
+ _cleanup_free_ char *datadev = NULL;
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ n = strspn(value, ALPHANUMERICAL "-");
+ if (value[n] != '=') {
+ log_warning("Failed to parse luks.data= kernel command line switch. UUID is invalid, ignoring.");
+ return 0;
+ }
+
+ uuid = strndup(value, n);
+ if (!uuid)
+ return log_oom();
+
+ if (warn_uuid_invalid(uuid, key))
+ return 0;
+
+ d = get_crypto_device(uuid);
+ if (!d)
+ return log_oom();
+
+ datadev = fstab_node_to_udev_node(value + n + 1);
+ if (!datadev)
+ return log_oom();
+ free_and_replace(d->datadev, datadev);
} else if (streq(key, "luks.name")) {
if (proc_cmdline_value_missing(key, value))
static int add_crypttab_devices(void) {
_cleanup_fclose_ FILE *f = NULL;
unsigned crypttab_line = 0;
- struct stat st;
int r;
if (!arg_read_crypttab)
return 0;
}
- if (fstat(fileno(f), &st) < 0) {
- log_error_errno(errno, "Failed to stat %s: %m", arg_crypttab);
- return 0;
- }
-
for (;;) {
- _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL, *keyfile = NULL, *keydev = NULL;
+ _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL,
+ *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
crypto_device *d = NULL;
char *l, *uuid;
int k;
continue;
}
- r = split_keyspec(keyspec, &keyfile, &keydev);
+ r = split_locationspec(keyspec, &keyfile, &keydev);
if (r < 0)
return r;
- r = create_disk(name, device, keyfile, keydev, (d && d->options) ? d->options : options, arg_crypttab);
+ if (options && (!d || !d->options)) {
+ r = filter_header_device(options, &headerdev, &filtered_header);
+ if (r < 0)
+ return r;
+ free_and_replace(options, filtered_header);
+ }
+
+ r = create_disk(name,
+ device,
+ keyfile,
+ keydev,
+ (d && d->options) ? d->headerdev : headerdev,
+ (d && d->options) ? d->options : options,
+ arg_crypttab);
if (r < 0)
return r;
return log_oom();
r = create_disk(d->name,
- device,
+ d->datadev ?: device,
d->keyfile ?: arg_default_keyfile,
d->keydev,
+ d->headerdev,
d->options ?: arg_default_options,
"/proc/cmdline");
if (r < 0)
_cleanup_free_ char *word = NULL;
int r;
- r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
+ r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
if (r < 0)
- return log_debug_errno(r, "Failed to parse options: %m");
+ return log_error_errno(r, "Failed to parse options: %m");
if (r == 0)
break;
if (argc <= 1)
return help();
- if (argc < 3) {
- log_error("This program requires at least two arguments.");
- return -EINVAL;
- }
+ if (argc < 3)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This program requires at least two arguments.");
log_setup_service();
return r;
}
+ log_debug("%s %s ← %s type=%s cipher=%s", __func__,
+ argv[2], argv[3], strempty(arg_type), strempty(arg_cipher));
+
/* A delicious drop of snake oil */
(void) mlockall(MCL_FUTURE);
log_setup_service();
- if (argc > 2) {
- log_error("This program expects one or no arguments.");
- return -EINVAL;
- }
+ if (argc > 2)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This program expects one or no arguments.");
umask(0022);
if (stat(device, &st) < 0)
return log_error_errno(errno, "Failed to stat %s: %m", device);
- if (!S_ISBLK(st.st_mode)) {
- log_error("%s is not a block device.", device);
- return -EINVAL;
- }
+ if (!S_ISBLK(st.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s is not a block device.",
+ device);
r = sd_device_new_from_devnum(&dev, 'b', st.st_rdev);
if (r < 0)
return 0;
#else
- return log_error_errno(EOPNOTSUPP, "FIDO2 tokens not supported on this build.");
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "FIDO2 tokens not supported on this build.");
#endif
}
fido_dev_info_free(&di, allocated);
return r;
#else
- return log_error_errno(EOPNOTSUPP, "FIDO2 tokens not supported on this build.");
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "FIDO2 tokens not supported on this build.");
#endif
}
r = pkcs11_find_token(uri, pkcs11_callback, &data);
if (r == -EAGAIN) /* pkcs11_find_token() doesn't log about this error, but all others */
- return log_error_errno(ENXIO, "Specified PKCS#11 token with URI '%s' not found.", uri);
+ return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
+ "Specified PKCS#11 token with URI '%s' not found.",
+ uri);
if (r < 0)
return r;
return 0;
#else
- return log_error_errno(EOPNOTSUPP, "PKCS#11 tokens not supported on this build.");
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "PKCS#11 tokens not supported on this build.");
#endif
}
return 0;
#else
- return log_error_errno(EOPNOTSUPP, "PKCS#11 tokens not supported on this build.");
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "PKCS#11 tokens not supported on this build.");
#endif
}
r = bus_connect_transport(arg_transport, arg_host, false, bus);
if (r < 0)
- return log_error_errno(r, "Failed to connect to bus: %m");
+ return bus_log_connect_error(r);
(void) sd_bus_set_allow_interactive_authorization(*bus, arg_ask_password);
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to lock home: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to lock all homes: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+static int deactivate_all_homes(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ r = bus_message_new_method_call(bus, &m, bus_mgr, "DeactivateAllHomes");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to deactivate all homes: %s", bus_error_message(&error, r));
return 0;
}
" lock USER… Temporarily lock an active home area\n"
" unlock USER… Unlock a temporarily locked home area\n"
" lock-all Lock all suitable home areas\n"
+ " deactivate-all Deactivate all active home areas\n"
" with USER [COMMAND…] Run shell or command with access to a home area\n"
"\n%4$sOptions:%5$s\n"
" -h --help Show this help\n"
static int run(int argc, char *argv[]) {
static const Verb verbs[] = {
- { "help", VERB_ANY, VERB_ANY, 0, help },
- { "list", VERB_ANY, 1, VERB_DEFAULT, list_homes },
- { "activate", 2, VERB_ANY, 0, activate_home },
- { "deactivate", 2, VERB_ANY, 0, deactivate_home },
- { "inspect", VERB_ANY, VERB_ANY, 0, inspect_home },
- { "authenticate", VERB_ANY, VERB_ANY, 0, authenticate_home },
- { "create", VERB_ANY, 2, 0, create_home },
- { "remove", 2, VERB_ANY, 0, remove_home },
- { "update", VERB_ANY, 2, 0, update_home },
- { "passwd", VERB_ANY, 2, 0, passwd_home },
- { "resize", 2, 3, 0, resize_home },
- { "lock", 2, VERB_ANY, 0, lock_home },
- { "unlock", 2, VERB_ANY, 0, unlock_home },
- { "with", 2, VERB_ANY, 0, with_home },
- { "lock-all", VERB_ANY, 1, 0, lock_all_homes },
+ { "help", VERB_ANY, VERB_ANY, 0, help },
+ { "list", VERB_ANY, 1, VERB_DEFAULT, list_homes },
+ { "activate", 2, VERB_ANY, 0, activate_home },
+ { "deactivate", 2, VERB_ANY, 0, deactivate_home },
+ { "inspect", VERB_ANY, VERB_ANY, 0, inspect_home },
+ { "authenticate", VERB_ANY, VERB_ANY, 0, authenticate_home },
+ { "create", VERB_ANY, 2, 0, create_home },
+ { "remove", 2, VERB_ANY, 0, remove_home },
+ { "update", VERB_ANY, 2, 0, update_home },
+ { "passwd", VERB_ANY, 2, 0, passwd_home },
+ { "resize", 2, 3, 0, resize_home },
+ { "lock", 2, VERB_ANY, 0, lock_home },
+ { "unlock", 2, VERB_ANY, 0, unlock_home },
+ { "with", 2, VERB_ANY, 0, with_home },
+ { "lock-all", VERB_ANY, 1, 0, lock_all_homes },
+ { "deactivate-all", VERB_ANY, 1, 0, deactivate_all_homes },
{}
};
return 1;
}
+static int home_dispatch_deactivate_all(Home *h, Operation *o) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(h);
+ assert(o);
+ assert(o->type == OPERATION_DEACTIVATE_ALL);
+
+ switch (home_get_state(h)) {
+
+ case HOME_UNFIXATED:
+ case HOME_ABSENT:
+ case HOME_INACTIVE:
+ case HOME_DIRTY:
+ log_info("Home %s is already deactivated.", h->user_name);
+ r = 1; /* done */
+ break;
+
+ case HOME_LOCKED:
+ log_info("Home %s is currently locked, not deactivating.", h->user_name);
+ r = 1; /* done */
+ break;
+
+ case HOME_ACTIVE:
+ log_info("Deactivating home %s.", h->user_name);
+ r = home_deactivate_internal(h, false, &error);
+ break;
+
+ default:
+ /* All other cases means we are currently executing an operation, which means the job remains
+ * pending. */
+ return 0;
+ }
+
+ assert(!h->current_operation);
+
+ if (r != 0) /* failure or completed */
+ operation_result(o, r, &error);
+ else /* ongoing */
+ h->current_operation = operation_ref(o);
+
+ return 1;
+}
+
static int home_dispatch_pipe_eof(Home *h, Operation *o) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
[OPERATION_ACQUIRE] = home_dispatch_acquire,
[OPERATION_RELEASE] = home_dispatch_release,
[OPERATION_LOCK_ALL] = home_dispatch_lock_all,
+ [OPERATION_DEACTIVATE_ALL] = home_dispatch_deactivate_all,
[OPERATION_PIPE_EOF] = home_dispatch_pipe_eof,
[OPERATION_DEACTIVATE_FORCE] = home_dispatch_deactivate_force,
};
}
if (waiting) /* At least one lock operation was enqeued, let's leave here without a reply: it will
- * be sent as soon as the last of the lock operations completed. */
+ * be sent as soon as the last of the lock operations completed. */
+ return 1;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_deactivate_all_homes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_(operation_unrefp) Operation *o = NULL;
+ bool waiting = false;
+ Manager *m = userdata;
+ Home *h;
+ int r;
+
+ assert(m);
+
+ /* This is called from systemd-homed-activate.service's ExecStop= command to ensure that all home
+ * directories are shutdown before the system goes down. Note that we don't do this from
+ * systemd-homed.service itself since we want to allow restarting of it without tearing down all home
+ * directories. */
+
+ HASHMAP_FOREACH(h, m->homes_by_name) {
+
+ if (!o) {
+ o = operation_new(OPERATION_DEACTIVATE_ALL, message);
+ if (!o)
+ return -ENOMEM;
+ }
+
+ log_info("Automatically deactivating home of user %s.", h->user_name);
+
+ r = home_schedule_operation(h, o, error);
+ if (r < 0)
+ return r;
+
+ waiting = true;
+ }
+
+ if (waiting) /* At least one lock operation was enqeued, let's leave here without a reply: it will be
+ * sent as soon as the last of the deactivation operations completed. */
return 1;
return sd_bus_reply_method_return(message, NULL);
/* An operation that acts on all homes that allow it */
SD_BUS_METHOD("LockAllHomes", NULL, NULL, method_lock_all_homes, 0),
+ SD_BUS_METHOD("DeactivateAllHomes", NULL, NULL, method_deactivate_all_homes, 0),
SD_BUS_VTABLE_END
};
OPERATION_ACQUIRE, /* enqueued on AcquireHome() */
OPERATION_RELEASE, /* enqueued on ReleaseHome() */
OPERATION_LOCK_ALL, /* enqueued on LockAllHomes() */
+ OPERATION_DEACTIVATE_ALL, /* enqueued on DeactivateAllHomes() */
OPERATION_PIPE_EOF, /* enqueued when we see EOF on the per-home reference pipes */
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. */
* the old literal password only (and do not care for the old PKCS#11 token) */
if (strv_isempty(h->hashed_password))
- return log_error_errno(EINVAL, "User record has no hashed passwords, refusing.");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "User record has no hashed passwords, refusing.");
/* Generates the list of plaintext passwords to propagate to LUKS/fscrypt devices, and checks whether
* we have a plaintext password for each hashed one. If we are missing one we'll fail, since we
if (r == PAM_SUCCESS && json) {
/* We determined earlier that this is not a homed user? Then exit early. (We use -1 as
* negative cache indicator) */
- if (json == (void*) -1)
+ if (json == POINTER_MAX)
return PAM_USER_UNKNOWN;
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
user_unknown:
/* Cache this, so that we don't check again */
- r = pam_set_data(handle, homed_field, (void*) -1, NULL);
+ r = pam_set_data(handle, homed_field, POINTER_MAX, NULL);
if (r != PAM_SUCCESS)
pam_syslog(handle, LOG_ERR, "Failed to set PAM user record data '%s' to invalid, ignoring: %s",
homed_field, pam_strerror(handle, r));
pam_syslog(handle, LOG_DEBUG, "pam-systemd-homed account management");
r = acquire_home(handle, /* please_authenticate = */ false, please_suspend, debug);
- if (r == PAM_USER_UNKNOWN)
- return PAM_SUCCESS; /* we don't have anything to say about users we don't manage */
if (r != PAM_SUCCESS)
return r;
if (arg_pretty || arg_static || arg_transient) {
const char *attr;
- if (!!arg_static + !!arg_pretty + !!arg_transient > 1) {
- log_error("Cannot query more than one name type at a time");
- return -EINVAL;
- }
+ if (!!arg_static + !!arg_pretty + !!arg_transient > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Cannot query more than one name type at a time");
attr = arg_pretty ? "PrettyHostname" :
arg_static ? "StaticHostname" : "Hostname";
local = empty_or_dash_to_null(local);
if (local) {
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local image name '%s' is not valid.",
+ local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
} else {
- log_error("Image '%s' already exists.", local);
- return -EEXIST;
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Image '%s' already exists.",
+ local);
}
}
} else
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local image name '%s' is not valid.",
+ local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
} else {
- log_error("Image '%s' already exists.", local);
- return -EEXIST;
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Image '%s' already exists.",
+ local);
}
}
} else
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local image name '%s' is not valid.",
+ local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
} else {
- log_error("Image '%s' already exists.", local);
- return -EEXIST;
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Image '%s' already exists.",
+ local);
}
}
} else
assert(checksum_job->state == PULL_JOB_DONE);
- if (!checksum_job->payload || checksum_job->payload_size <= 0) {
- log_error("Checksum is empty, cannot verify.");
- return -EBADMSG;
- }
+ 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)
assert(signature_job->state == PULL_JOB_DONE);
- if (!signature_job->payload || signature_job->payload_size <= 0) {
- log_error("Signature is empty, cannot verify.");
- return -EBADMSG;
- }
+ if (!signature_job->payload || signature_job->payload_size <= 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Signature is empty, cannot verify.");
r = pipe2(gpg_pipe, O_CLOEXEC);
if (r < 0)
int r;
url = argv[1];
- if (!http_url_is_valid(url)) {
- log_error("URL '%s' is not valid.", url);
- return -EINVAL;
- }
+ if (!http_url_is_valid(url))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "URL '%s' is not valid.", url);
if (argc >= 3)
local = argv[2];
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local image name '%s' is not valid.",
+ local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
} else {
- log_error("Image '%s' already exists.", local);
- return -EEXIST;
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Image '%s' already exists.",
+ local);
}
}
int r;
url = argv[1];
- if (!http_url_is_valid(url)) {
- log_error("URL '%s' is not valid.", url);
- return -EINVAL;
- }
+ if (!http_url_is_valid(url))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "URL '%s' is not valid.", url);
if (argc >= 3)
local = argv[2];
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local image name '%s' is not valid.",
+ local);
if (!arg_force) {
r = image_find(IMAGE_MACHINE, local, NULL);
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
} else {
- log_error("Image '%s' already exists.", local);
- return -EEXIST;
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Image '%s' already exists.",
+ local);
}
}
assert(fdt >= 0);
ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64);
- if (ret != LZMA_OK) {
- log_error("Failed to initialize XZ encoder: code %u", ret);
- return -EINVAL;
- }
+ if (ret != LZMA_OK)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to initialize XZ encoder: code %u",
+ ret);
for (;;) {
if (s.avail_in == 0 && action == LZMA_RUN) {
}
ret = lzma_code(&s, action);
- if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END)) {
- log_error("Compression failed: code %u", ret);
- return -EBADMSG;
- }
+ if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END))
+ return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Compression failed: code %u",
+ ret);
if (s.avail_out == 0 || ret == LZMA_STREAM_END) {
ssize_t n, k;
offset += n;
total_out += n;
- if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
- log_debug("Compressed stream longer than %"PRIu64" bytes", max_bytes);
- return -EFBIG;
- }
+ 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 (size - offset < frame_size + 4) {
k = loop_write(fdt, buf, offset, false);
assert(fdt >= 0);
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
- if (ret != LZMA_OK) {
- log_debug("Failed to initialize XZ decoder: code %u", ret);
- return -ENOMEM;
- }
+ if (ret != LZMA_OK)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOMEM),
+ "Failed to initialize XZ decoder: code %u",
+ ret);
for (;;) {
if (s.avail_in == 0 && action == LZMA_RUN) {
}
ret = lzma_code(&s, action);
- if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END)) {
- log_debug("Decompression failed: code %u", ret);
- return -EBADMSG;
- }
+ if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END))
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Decompression failed: code %u",
+ ret);
if (s.avail_out == 0 || ret == LZMA_STREAM_END) {
ssize_t n, k;
}
}
#else
- log_debug("Cannot decompress file. Compiled without XZ support.");
- return -EPROTONOSUPPORT;
+ return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
+ "Cannot decompress file. Compiled without XZ support.");
#endif
}
munmap(src, st.st_size);
return r;
#else
- log_debug("Cannot decompress file. Compiled without LZ4 support.");
- return -EPROTONOSUPPORT;
+ return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
+ "Cannot decompress file. Compiled without LZ4 support.");
#endif
}
(double) (max_bytes - left) / in_bytes * 100);
return 0;
#else
- log_debug("Cannot decompress file. Compiled without ZSTD support.");
- return -EPROTONOSUPPORT;
+ return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
+ "Cannot decompress file. Compiled without ZSTD support.");
#endif
}
if (i >= n) {
n = MAX(i*2, 4);
- c = realloc(iov, n * sizeof(struct iovec));
+ c = reallocarray(iov, n, sizeof(struct iovec));
if (!c) {
r = -ENOMEM;
goto fail;
assert(j);
assert(devpath);
- if (!path_startswith(devpath, "/dev/")) {
- log_error("Devpath does not start with /dev/");
- return -EINVAL;
- }
+ if (!path_startswith(devpath, "/dev/"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Devpath does not start with /dev/");
if (stat(devpath, &st) < 0)
return log_error_errno(errno, "Couldn't stat file: %m");
if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
arg_lines = 10;
- if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root + !!arg_image > 1) {
- log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
- return -EINVAL;
- }
+ if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root + !!arg_image > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
- if (arg_since_set && arg_until_set && arg_since > arg_until) {
- log_error("--since= must be before --until=.");
- return -EINVAL;
- }
+ if (arg_since_set && arg_until_set && arg_since > arg_until)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--since= must be before --until=.");
- if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
- log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
- return -EINVAL;
- }
+ if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Please specify only one of --since=, --cursor=, and --after-cursor.");
- if (arg_follow && arg_reverse) {
- log_error("Please specify either --reverse= or --follow=, not both.");
- return -EINVAL;
- }
+ if (arg_follow && arg_reverse)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Please specify either --reverse= or --follow=, not both.");
- if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) {
- log_error("Extraneous arguments starting with '%s'", argv[optind]);
- return -EINVAL;
- }
+ if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Extraneous arguments starting with '%s'",
+ argv[optind]);
- if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge) {
- log_error("Using --boot or --list-boots with --merge is not supported.");
- return -EINVAL;
- }
+ if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Using --boot or --list-boots with --merge is not supported.");
if (!strv_isempty(arg_system_units) && arg_journal_type == SD_JOURNAL_CURRENT_USER) {
/* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
"Please write down the following %ssecret verification key%s. It should be stored\n"
"in a safe location and should not be saved locally on disk.\n"
"\n\t%s",
- hn ?: "", hn ? "/" : "", SD_ID128_FORMAT_VAL(machine),
+ strempty(hn), hn ? "/" : "",
+ SD_ID128_FORMAT_VAL(machine),
ansi_highlight(), ansi_normal(),
p,
format_timespan(tsb, sizeof(tsb), arg_interval, 0),
after_cursor = true;
}
} else
- after_cursor = !!arg_after_cursor;
+ after_cursor = arg_after_cursor;
if (cursor) {
r = sd_journal_seek_cursor(j, cursor);
#include "string-table.h"
#include "string-util.h"
#include "syslog-util.h"
+#include "user-record.h"
#include "user-util.h"
#define USER_JOURNALS_MAX 1024
#include "alloc-util.h"
#include "chattr-util.h"
+#include "io-util.h"
#include "journal-file.h"
#include "journal-internal.h"
#include "log.h"
previous_ts = ts;
assert_se(asprintf(&p, "NUMBER=%u", i) >= 0);
- iovec[0].iov_base = p;
- iovec[0].iov_len = strlen(p);
+ iovec[0] = IOVEC_MAKE(p, strlen(p));
assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0);
- iovec[1].iov_base = q;
- iovec[1].iov_len = strlen(q);
+ iovec[1] = IOVEC_MAKE(q, strlen(q));
if (i % 10 == 0)
assert_se(journal_file_append_entry(three, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
if (duid_len > MAX_DUID_LEN)
return -EINVAL;
- if (!strict) {
+ if (!strict)
/* Strict validation is not requested. We only ensure that the
* DUID is not too long. */
return 0;
- }
switch (duid_type) {
case DUID_TYPE_LLT:
#include "io-util.h"
#include "memory-util.h"
#include "random-util.h"
+#include "set.h"
+#include "sort-util.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
union sockaddr_union link;
sd_event_source *receive_message;
bool request_broadcast;
- uint8_t *req_opts;
- size_t req_opts_allocated;
- size_t req_opts_size;
+ Set *req_opts;
bool anonymize;
be32_t last_addr;
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
}
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
- size_t i;
-
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
break;
}
- for (i = 0; i < client->req_opts_size; i++)
- if (client->req_opts[i] == option)
- return -EEXIST;
-
- if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
- client->req_opts_size + 1))
- return -ENOMEM;
-
- client->req_opts[client->req_opts_size++] = option;
-
- return 0;
+ return set_ensure_put(&client->req_opts, NULL, UINT8_TO_PTR(option));
}
int sd_dhcp_client_set_request_address(
client_initialize(client);
}
+static int cmp_uint8(const uint8_t *a, const uint8_t *b) {
+ return CMP(*a, *b);
+}
+
static int client_message_init(
sd_dhcp_client *client,
DHCPPacket **ret,
MAY contain the Parameter Request List option. */
/* NOTE: in case that there would be an option to do not send
* any PRL at all, the size should be checked before sending */
- if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
+ if (!set_isempty(client->req_opts) && type != DHCP_RELEASE) {
+ _cleanup_free_ uint8_t *opts = NULL;
+ size_t n_opts, i = 0;
+ void *val;
+
+ n_opts = set_size(client->req_opts);
+ opts = new(uint8_t, n_opts);
+ if (!opts)
+ return -ENOMEM;
+
+ SET_FOREACH(val, client->req_opts)
+ opts[i++] = PTR_TO_UINT8(val);
+ assert(i == n_opts);
+
+ /* For anonymizing the request, let's sort the options. */
+ typesafe_qsort(opts, n_opts, cmp_uint8);
+
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
- client->req_opts_size, client->req_opts);
+ n_opts, opts);
if (r < 0)
return r;
}
assert(client);
buflen = next_datagram_size_fd(fd);
- if (buflen == -ENETDOWN) {
+ if (buflen == -ENETDOWN)
/* the link is down. Don't return an error or the I/O event
source will be disconnected and we won't be able to receive
packets again when the link comes back. */
return 0;
- }
if (buflen < 0)
return buflen;
}
int sd_dhcp_client_stop(sd_dhcp_client *client) {
- DHCP_CLIENT_DONT_DESTROY(client);
+ if (!client)
+ return 0;
- assert_return(client, -EINVAL);
+ DHCP_CLIENT_DONT_DESTROY(client);
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
client->state = DHCP_STATE_STOPPED;
sd_dhcp_lease_unref(client->lease);
- free(client->req_opts);
+ set_free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
free(client->mudurl);
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
+ const uint8_t *opts;
+ size_t n_opts;
+ int r;
+
assert_return(ret, -EINVAL);
_cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1);
};
/* NOTE: this could be moved to a function. */
if (anonymize) {
- client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize);
- client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size);
+ n_opts = ELEMENTSOF(default_req_opts_anonymize);
+ opts = default_req_opts_anonymize;
} else {
- client->req_opts_size = ELEMENTSOF(default_req_opts);
- client->req_opts = memdup(default_req_opts, client->req_opts_size);
+ n_opts = ELEMENTSOF(default_req_opts);
+ opts = default_req_opts;
+ }
+
+ for (size_t i = 0; i < n_opts; i++) {
+ r = sd_dhcp_client_set_request_option(client, opts[i]);
+ if (r < 0)
+ return r;
}
- if (!client->req_opts)
- return -ENOMEM;
*ret = TAKE_PTR(client);
return r;
n += r;
- } else if ((c & 0xc0) == 0xc0) {
+ } else if (FLAGS_SET(c, 0xc0)) {
/* Pointer */
uint8_t d;
if (!a)
return -ENOMEM;
- if (!strv_isempty(a)) {
- lease->search_domains = a;
- a = NULL;
- }
+ if (!strv_isempty(a))
+ lease->search_domains = TAKE_PTR(a);
}
if (routes) {
}
int sd_dhcp_server_stop(sd_dhcp_server *server) {
- assert_return(server, -EINVAL);
+ if (!server)
+ return 0;
server->receive_message =
sd_event_source_unref(server->receive_message);
}
static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
- be32_t gateway, uint8_t chaddr[]) {
+ be32_t gateway, const uint8_t chaddr[]) {
_cleanup_free_ DHCPPacket *packet = NULL;
size_t optoffset = 0;
int r;
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
- if (duid != NULL) {
+ if (duid) {
r = dhcp_validate_duid_len(duid_type, duid_len, true);
if (r < 0) {
r = dhcp_validate_duid_len(duid_type, duid_len, false);
assert(client->event);
buflen = next_datagram_size_fd(fd);
- if (buflen == -ENETDOWN) {
+ if (buflen == -ENETDOWN)
/* the link is down. Don't return an error or the I/O event
source will be disconnected and we won't be able to receive
packets again when the link comes back. */
return 0;
- }
if (buflen < 0)
return buflen;
}
int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
- assert_return(client, -EINVAL);
+ if (!client)
+ return 0;
client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
int sd_ipv4acd_stop(sd_ipv4acd *acd) {
IPv4ACDState old_state;
- assert_return(acd, -EINVAL);
+ if (!acd)
+ return 0;
old_state = acd->state;
}
int sd_ipv4ll_stop(sd_ipv4ll *ll) {
- assert_return(ll, -EINVAL);
+ if (!ll)
+ return 0;
return sd_ipv4acd_stop(ll->acd);
}
}
_public_ int sd_lldp_stop(sd_lldp *lldp) {
- assert_return(lldp, -EINVAL);
+ if (!lldp)
+ return 0;
if (lldp->fd < 0)
return 0;
}
_public_ int sd_ndisc_stop(sd_ndisc *nd) {
- assert_return(nd, -EINVAL);
+ if (!nd)
+ return 0;
if (nd->fd < 0)
return 0;
_public_ int sd_radv_stop(sd_radv *ra) {
int r;
- assert_return(ra, -EINVAL);
+ if (!ra)
+ return 0;
if (ra->state == SD_RADV_STATE_IDLE)
return 0;
assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_ROUTER) == -EEXIST);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_SUBNET_MASK) == 0);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == 0);
/* This PRL option is not set when using Anonymize, but in this test
* Anonymize settings are not being used. */
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_HOST_NAME) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
-
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_PAD) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_END) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
- == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 0);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME) == 0);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == 0);
+
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PAD) == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_END) == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
/* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
* default PRL when using Anonymize, so it is changed to other option
* that is not set by default, to check that it was set successfully.
* Options not set by default (using or not anonymize) are option 17
* (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
+ assert_se(sd_dhcp_client_set_request_option(client, 17) == 1);
+ assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
+ assert_se(sd_dhcp_client_set_request_option(client, 42) == 1);
assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
- assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
- assert_se(sd_dhcp_client_set_request_option(client, 42) == 0);
- assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
sd_dhcp_client_unref(client);
}
r = sd_dhcp_client_attach_event(client, e, 0);
assert_se(r >= 0);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_NETBIOS_NAMESERVER) == -EEXIST);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAMESERVER) == 0);
/* This PRL option is not set when using Anonymize */
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_HOST_NAME) == 0);
- assert_se(sd_dhcp_client_set_request_option(client,
- SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
- == -EINVAL);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 1);
+ assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
/* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
* default PRL when using Anonymize, */
+ assert_se(sd_dhcp_client_set_request_option(client, 101) == 1);
assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
- assert_se(sd_dhcp_client_set_request_option(client, 101) == -EEXIST);
sd_dhcp_client_unref(client);
}
static int test_basic(sd_event *event) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
struct in_addr address_lo = {
- .s_addr = htonl(INADDR_LOOPBACK),
+ .s_addr = htobe32(INADDR_LOOPBACK),
};
struct in_addr address_any = {
- .s_addr = htonl(INADDR_ANY),
+ .s_addr = htobe32(INADDR_ANY),
};
int r;
.end = SD_DHCP_OPTION_END,
};
struct in_addr address_lo = {
- .s_addr = htonl(INADDR_LOOPBACK),
+ .s_addr = htobe32(INADDR_LOOPBACK),
};
assert_se(sd_dhcp_server_new(&server, 1) >= 0);
global:
sd_event_add_time_relative;
sd_event_source_set_time_relative;
+ sd_event_source_get_exit_on_failure;
+ sd_event_source_set_exit_on_failure;
sd_bus_error_has_names_sentinel;
#include "fd-util.h"
#include "namespace-util.h"
#include "process-util.h"
+#include "string-util.h"
#include "util.h"
int bus_container_connect_socket(sd_bus *b) {
assert(b->nspid > 0 || b->machine);
if (b->nspid <= 0) {
+ log_debug("sd-bus: connecting bus%s%s to machine %s...",
+ b->description ? " " : "", strempty(b->description), b->machine);
+
r = container_get_leader(b->machine, &b->nspid);
if (r < 0)
return r;
- }
+ } else
+ log_debug("sd-bus: connecting bus%s%s to namespace of PID "PID_FMT"...",
+ b->description ? " " : "", strempty(b->description), b->nspid);
r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
if (r < 0)
assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
- if (r <= 0)
+ if (r < 0)
return r;
+ if (r == 0) {
+ *ptr = NULL;
+ *size = 0;
+ return 0;
+ }
c = message_get_last_container(m);
assert(b->output_fd < 0);
assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *pretty = NULL;
+ (void) sockaddr_pretty(&b->sockaddr.sa, b->sockaddr_size, false, true, &pretty);
+ log_debug("sd-bus: starting bus%s%s by connecting to %s...",
+ b->description ? " " : "", strempty(b->description), strnull(pretty));
+ }
+
b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (b->input_fd < 0)
return -errno;
assert(b->exec_path);
assert(b->busexec_pid == 0);
+ log_debug("sd-bus: starting bus%s%s with %s...",
+ b->description ? " " : "", strempty(b->description), b->exec_path);
+
r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
if (r < 0)
return -errno;
assert(b->input_fd >= 0);
assert(b->output_fd >= 0);
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *pi = NULL, *po = NULL;
+ (void) fd_get_path(b->input_fd, &pi);
+ (void) fd_get_path(b->output_fd, &po);
+ log_debug("sd-bus: starting bus%s%s on fds %d/%d (%s, %s)...",
+ b->description ? " " : "", strempty(b->description),
+ b->input_fd, b->output_fd,
+ pi ?: "???", po ?: "???");
+ }
+
r = fd_nonblock(b->input_fd, true);
if (r < 0)
return r;
e = secure_getenv("XDG_RUNTIME_DIR");
if (!e)
- return -ENOENT;
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
+ "sd-bus: $XDG_RUNTIME_DIR not set, cannot connect to user bus.");
ee = bus_address_escape(e);
if (!ee)
assert(bus);
- if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
- return -ENOTCONN;
if (bus->state == BUS_RUNNING)
return 1;
for (;;) {
+ if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
+ return -ENOTCONN;
+
r = sd_bus_process(bus, NULL);
if (r < 0)
return r;
assert_se(streq(hello, "hello"));
if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
- log_error_errno(errno, "Failed to allocate pipe: %m");
- r = -errno;
+ r = log_error_errno(errno, "Failed to allocate pipe: %m");
goto finish;
}
int r;
r = sd_bus_open_user(&bus);
- if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
+ if (IN_SET(r, -ECONNREFUSED, -ENOENT, -ENOMEDIUM)) {
r = sd_bus_open_system(&bus);
if (IN_SET(r, -ECONNREFUSED, -ENOENT))
return r;
assert_se(r >= 0);
r = sd_bus_open_user(&a);
- if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
+ if (IN_SET(r, -ECONNREFUSED, -ENOENT, -ENOMEDIUM)) {
r = sd_bus_open_system(&a);
if (IN_SET(r, -ECONNREFUSED, -ENOENT))
return log_tests_skipped("Failed to connect to bus");
else
hashmap = &enumerator->nomatch_sysattr;
- r = hashmap_put_strdup(hashmap, sysattr, value);
+ r = hashmap_put_strdup_full(hashmap, &trivial_hash_ops_free_free, sysattr, value);
if (r <= 0)
return r;
assert_return(enumerator, -EINVAL);
assert_return(property, -EINVAL);
- r = hashmap_put_strdup(&enumerator->match_property, property, value);
+ r = hashmap_put_strdup_full(&enumerator->match_property, &trivial_hash_ops_free_free, property, value);
if (r <= 0)
return r;
bool pending:1;
bool dispatching:1;
bool floating:1;
+ bool exit_on_failure:1;
int64_t priority;
unsigned pending_index;
.events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0),
.data.ptr = s,
};
- int r;
- r = epoll_ctl(s->event->epoll_fd,
+ if (epoll_ctl(s->event->epoll_fd,
s->io.registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD,
s->io.fd,
- &ev);
- if (r < 0)
+ &ev) < 0)
return -errno;
s->io.registered = true;
.data.ptr = d,
};
- r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
- if (r < 0) {
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) {
r = -errno;
goto fail;
}
return s;
}
+static int io_exit_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ assert(s);
+
+ return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
+}
+
_public_ int sd_event_add_io(
sd_event *e,
sd_event_source **ret,
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(fd >= 0, -EBADF);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = io_exit_callback;
+
s = source_new(e, !ret, SOURCE_IO);
if (!s)
return -ENOMEM;
return 0;
_cleanup_close_ int fd = -1;
- int r;
fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC);
if (fd < 0)
.data.ptr = d,
};
- r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
- if (r < 0)
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
return -errno;
d->fd = TAKE_FD(fd);
return 0;
}
+static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *userdata) {
+ assert(s);
+
+ return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
+}
+
static bool shall_use_pidfd(void) {
/* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */
return getenv_bool_secure("SYSTEMD_PIDFD") != 0;
assert_return(pid > 1, -EINVAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = child_exit_callback;
+
if (e->n_enabled_child_sources == 0) {
/* Caller must block SIGCHLD before using us to watch children, even if pidfd is available,
* for compatibility with pre-pidfd and because we don't want the reap the child processes
assert_return(pidfd >= 0, -EBADF);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = child_exit_callback;
+
if (e->n_enabled_child_sources == 0) {
r = signal_is_blocked(SIGCHLD);
if (r < 0)
return 0;
}
+static int generic_exit_callback(sd_event_source *s, void *userdata) {
+ assert(s);
+
+ return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
+}
+
_public_ int sd_event_add_defer(
sd_event *e,
sd_event_source **ret,
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = generic_exit_callback;
+
s = source_new(e, !ret, SOURCE_DEFER);
if (!s)
return -ENOMEM;
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = generic_exit_callback;
+
s = source_new(e, !ret, SOURCE_POST);
if (!s)
return -ENOMEM;
return 1;
}
+static int inotify_exit_callback(sd_event_source *s, const struct inotify_event *event, void *userdata) {
+ assert(s);
+
+ return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
+}
+
_public_ int sd_event_add_inotify(
sd_event *e,
sd_event_source **ret,
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(path, -EINVAL);
- assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
+ if (!callback)
+ callback = inotify_exit_callback;
+
/* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge
* masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence
* the user can't use them for us. */
struct itimerspec its = {};
sd_event_source *a, *b;
usec_t t;
- int r;
assert(e);
assert(d);
return 0;
/* disarm */
- r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
- if (r < 0)
- return r;
+ if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0)
+ return -errno;
d->next = USEC_INFINITY;
return 0;
} else
timespec_store(&its.it_value, t);
- r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
- if (r < 0)
+ if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0)
return -errno;
d->next = t;
continue;
zero(s->child.siginfo);
- r = waitid(P_PID, s->child.pid, &s->child.siginfo,
- WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options);
- if (r < 0)
+ if (waitid(P_PID, s->child.pid, &s->child.siginfo,
+ WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options) < 0)
return -errno;
if (s->child.siginfo.si_pid != 0) {
}
static int source_dispatch(sd_event_source *s) {
+ _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
EventSourceType saved_type;
int r = 0;
assert(s);
assert(s->pending || s->type == SOURCE_EXIT);
- /* Save the event source type, here, so that we still know it after the event callback which might invalidate
- * the event. */
+ /* Save the event source type, here, so that we still know it after the event callback which might
+ * invalidate the event. */
saved_type = s->type;
+ /* Similar, store a reference to the event loop object, so that we can still access it after the
+ * callback might have invalidated/disconnected the event source. */
+ saved_event = sd_event_ref(s->event);
+
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
s->dispatching = false;
- if (r < 0)
- log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m",
- strna(s->description), event_source_type_to_string(saved_type));
+ if (r < 0) {
+ log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",
+ strna(s->description),
+ event_source_type_to_string(saved_type),
+ s->exit_on_failure ? "exiting" : "disabling");
+
+ if (s->exit_on_failure)
+ (void) sd_event_exit(saved_event, r);
+ }
if (s->n_ref == 0)
source_free(s);
r = s->prepare(s, s->userdata);
s->dispatching = false;
- if (r < 0)
- log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m",
- strna(s->description), event_source_type_to_string(s->type));
+ if (r < 0) {
+ log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, %s: %m",
+ strna(s->description),
+ event_source_type_to_string(s->type),
+ s->exit_on_failure ? "exiting" : "disabling");
+
+ if (s->exit_on_failure)
+ (void) sd_event_exit(e, r);
+ }
if (s->n_ref == 0)
source_free(s);
static int arm_watchdog(sd_event *e) {
struct itimerspec its = {};
usec_t t;
- int r;
assert(e);
assert(e->watchdog_fd >= 0);
if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
its.it_value.tv_nsec = 1;
- r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL);
- if (r < 0)
+ if (timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0)
return -errno;
return 0;
}
_public_ int sd_event_get_fd(sd_event *e) {
-
assert_return(e, -EINVAL);
assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
return -EOPNOTSUPP;
if (!triple_timestamp_is_set(&e->timestamp)) {
- /* Implicitly fall back to now() if we never ran
- * before and thus have no cached time. */
+ /* Implicitly fall back to now() if we never ran before and thus have no cached time. */
*usec = now(clock);
return 1;
}
.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG),
};
- r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
- if (r < 0) {
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev) < 0) {
r = -errno;
goto fail;
}
return 1;
}
+
+_public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) {
+ assert_return(s, -EINVAL);
+ assert_return(s->type != SOURCE_EXIT, -EDOM);
+
+ return s->exit_on_failure;
+}
+
+_public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) {
+ assert_return(s, -EINVAL);
+ assert_return(s->type != SOURCE_EXIT, -EDOM);
+
+ if (s->exit_on_failure == !!b)
+ return 0;
+
+ s->exit_on_failure = b;
+ return 1;
+}
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
pid = fork();
- if (pid == 0) {
+ if (pid == 0)
/* child */
_exit(66);
- }
assert_se(pid > 1);
}
static void trie_node_cleanup(struct trie_node *node) {
- size_t i;
-
if (!node)
return;
- for (i = 0; i < node->children_count; i++)
+ for (size_t i = 0; i < node->children_count; i++)
trie_node_cleanup(node->children[i].child);
free(node->children);
free(node->values);
static int trie_insert(struct trie *trie, struct trie_node *node, const char *search,
const char *key, const char *value,
const char *filename, uint16_t file_priority, uint32_t line_number, bool compat) {
- size_t i = 0;
int r = 0;
- for (;;) {
+ for (size_t i = 0;; i++) {
size_t p;
uint8_t c;
struct trie_node *child;
}
node = child;
- i++;
}
}
/* calculate the storage space for the nodes, children arrays, value arrays */
static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node, bool compat) {
- uint64_t i;
-
- for (i = 0; i < node->children_count; i++)
+ for (uint64_t i = 0; i < node->children_count; i++)
trie_store_nodes_size(trie, node->children[i].child, compat);
trie->strings_off += sizeof(struct trie_node_f);
- for (i = 0; i < node->children_count; i++)
+ for (uint64_t i = 0; i < node->children_count; i++)
trie->strings_off += sizeof(struct trie_child_entry_f);
- for (i = 0; i < node->values_count; i++)
+ for (uint64_t i = 0; i < node->values_count; i++)
trie->strings_off += compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f);
}
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, bool compat) {
- uint64_t i;
struct trie_node_f n = {
.prefix_off = htole64(trie->strings_off + node->prefix_off),
.children_count = node->children_count,
}
/* post-order recursion */
- for (i = 0; i < node->children_count; i++) {
+ for (uint64_t i = 0; i < node->children_count; i++) {
int64_t child_off;
child_off = trie_store_nodes(trie, node->children[i].child, compat);
}
/* append values array */
- for (i = 0; i < node->values_count; i++) {
+ for (uint64_t i = 0; i < node->values_count; i++) {
struct trie_value_entry2_f v = {
.key_off = htole64(trie->strings_off + node->values[i].key_off),
.value_off = htole64(trie->strings_off + node->values[i].value_off),
value = strchr(line, '=');
if (!value)
return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
- "Key-value pair expected but got \"%s\", ignoring", line);
+ "Key-value pair expected but got \"%s\", ignoring.", line);
value[0] = '\0';
value++;
while (isblank(line[0]) && isblank(line[1]))
line++;
- if (isempty(line + 1) || isempty(value))
+ if (isempty(line + 1))
return log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
- "Empty %s in \"%s=%s\", ignoring",
- isempty(line + 1) ? "key" : "value",
+ "Empty key in \"%s=%s\", ignoring.",
line, value);
STRV_FOREACH(entry, match_list)
if (r == 0)
break;
- ++line_number;
+ line_number ++;
/* comment line */
if (line[0] == '#')
if (line[0] == ' ') {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
- "Match expected but got indented property \"%s\", ignoring line", line);
+ "Match expected but got indented property \"%s\", ignoring line.", line);
break;
}
case HW_MATCH:
if (len == 0) {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
- "Property expected, ignoring record with no properties");
+ "Property expected, ignoring record with no properties.");
state = HW_NONE;
match_list = strv_free(match_list);
break;
if (line[0] != ' ') {
r = log_syntax(NULL, LOG_WARNING, filename, line_number, SYNTHETIC_ERRNO(EINVAL),
- "Property or empty line expected, got \"%s\", ignoring record", line);
+ "Property or empty line expected, got \"%s\", ignoring record.", line);
state = HW_NONE;
match_list = strv_free(match_list);
break;
if (state == HW_MATCH)
log_syntax(NULL, LOG_WARNING, filename, line_number, 0,
- "Property expected, ignoring record with no properties");
+ "Property expected, ignoring record with no properties.");
return r;
}
return log_debug_errno(errno, "Failed to map %s: %m", hwdb_bin_path);
if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 ||
- (size_t) hwdb->st.st_size != le64toh(hwdb->head->file_size)) {
- log_debug("Failed to recognize the format of %s", hwdb_bin_path);
- return -EINVAL;
- }
+ (size_t) hwdb->st.st_size != le64toh(hwdb->head->file_size))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to recognize the format of %s",
+ hwdb_bin_path);
log_debug("=== trie on-disk ===");
log_debug("tool version: %"PRIu64, le64toh(hwdb->head->tool_version));
#include "id128-util.h"
#include "io-util.h"
#include "stdio-util.h"
+#include "string-util.h"
char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) {
unsigned n, k = 0;
switch (l) {
+ case 13:
+ case 14:
+ /* Treat an "uninitialized" id file like an empty one */
+ return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL;
+
case 33: /* plain UUID with trailing newline */
if (buffer[32] != '\n')
return -EINVAL;
_fallthrough_;
case 36: /* RFC UUID without trailing newline */
- if (f == ID128_PLAIN)
+ if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT))
return -EINVAL;
buffer[36] = 0;
typedef enum Id128Format {
ID128_ANY,
ID128_PLAIN, /* formatted as 32 hex chars as-is */
+ ID128_PLAIN_OR_UNINIT, /* formatted as 32 hex chars as-is; allow special "uninitialized"
+ * value when reading from file (id128_read() and id128_read_fd()).
+ *
+ * This format should be used when reading a machine-id file. */
ID128_UUID, /* formatted as 36 character uuid string */
_ID128_FORMAT_MAX,
} Id128Format;
#include "sd-login.h"
#include "alloc-util.h"
+#include "errno-list.h"
#include "fd-util.h"
#include "format-util.h"
#include "log.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
-#include "util.h"
+#include "user-util.h"
static char* format_uids(char **buf, uid_t* uids, int count) {
- int pos = 0, k, inc;
+ int pos = 0, inc;
size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1;
assert_se(*buf = malloc(size));
- for (k = 0; k < count; k++) {
+ for (int k = 0; k < count; k++) {
sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc);
pos += inc;
}
return *buf;
}
+static const char *e(int r) {
+ return r == 0 ? "OK" : errno_to_name(r);
+}
+
static void test_login(void) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_free_ char *pp = NULL, *qq = NULL,
*seat = NULL, *session = NULL,
*unit = NULL, *user_unit = NULL, *slice = NULL;
int r;
- uid_t u, u2;
- char *t, **seats, **sessions;
+ uid_t u, u2 = UID_INVALID;
+ char *t, **seats = NULL, **sessions = NULL;
r = sd_pid_get_unit(0, &unit);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit));
+ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit));
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_user_unit(0, &user_unit);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit));
+ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit));
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_slice(0, &slice);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice));
+ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice));
+ assert_se(IN_SET(r, 0, -ENODATA));
+
+ r = sd_pid_get_owner_uid(0, &u2);
+ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2);
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_session(0, &session);
- if (r < 0) {
- log_warning_errno(r, "sd_pid_get_session(0, …): %m");
- if (r == -ENODATA)
- log_info("Seems we are not running in a session, skipping some tests.");
- } else {
- log_info("sd_pid_get_session(0, …) → \"%s\"", session);
-
- assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2);
-
- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup);
-
- r = sd_uid_get_display(u2, &display_session);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"",
- u2, strnull(display_session));
-
- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
- sd_peer_get_session(pair[0], &pp);
- sd_peer_get_session(pair[1], &qq);
- assert_se(streq_ptr(pp, qq));
-
- r = sd_uid_get_sessions(u2, false, &sessions);
+ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session));
+
+ r = sd_pid_get_cgroup(0, &cgroup);
+ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
+ assert_se(r == 0);
+
+ r = sd_uid_get_display(u2, &display_session);
+ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else
+ assert_se(IN_SET(r, 0, -ENODATA));
+
+ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
+ sd_peer_get_session(pair[0], &pp);
+ sd_peer_get_session(pair[1], &qq);
+ assert_se(streq_ptr(pp, qq));
+
+ r = sd_uid_get_sessions(u2, false, &sessions);
+ assert_se(t = strv_join(sessions, " "));
+ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else {
assert_se(r >= 0);
assert_se(r == (int) strv_length(sessions));
- assert_se(t = strv_join(sessions, " "));
- strv_free(sessions);
- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
- free(t);
+ }
+ sessions = strv_free(sessions);
+ free(t);
- assert_se(r == sd_uid_get_sessions(u2, false, NULL));
+ assert_se(r == sd_uid_get_sessions(u2, false, NULL));
- r = sd_uid_get_seats(u2, false, &seats);
+ r = sd_uid_get_seats(u2, false, &seats);
+ assert_se(t = strv_join(seats, " "));
+ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else {
assert_se(r >= 0);
assert_se(r == (int) strv_length(seats));
- assert_se(t = strv_join(seats, " "));
- strv_free(seats);
- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
- free(t);
-
- assert_se(r == sd_uid_get_seats(u2, false, NULL));
}
+ seats = strv_free(seats);
+ free(t);
+
+ assert_se(r == sd_uid_get_seats(u2, false, NULL));
if (session) {
r = sd_session_is_active(session);
log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
r = sd_session_get_state(session, &state);
- assert_se(r >= 0);
+ assert_se(r == 0);
log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
assert_se(sd_session_get_uid(session, &u) >= 0);
log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
r = sd_session_get_display(session, &display);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
r = sd_session_get_remote_user(session, &remote_user);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
session, strna(remote_user));
r = sd_session_get_remote_host(session, &remote_host);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
session, strna(remote_host));
assert_se(r == -ENODATA);
}
- assert_se(sd_uid_get_state(u, &state2) >= 0);
+ assert_se(sd_uid_get_state(u, &state2) == 0);
log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
}
assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
r = sd_seat_get_active(seat, &session2, &u2);
- assert_se(r >= 0);
+ assert_se(r == 0);
log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2);
r = sd_uid_is_on_seat(u, 1, seat);
- assert_se(r >= 0);
+ assert_se(IN_SET(r, 0, 1));
assert_se(!!r == streq(session, session2));
r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
assert_se(r == (int) strv_length(sessions));
assert_se(t = strv_join(sessions, " "));
strv_free(sessions);
- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}",
- seat, r, t, n, format_uids(&buf, uids, n));
+ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}",
+ seat, e(r), t, n, format_uids(&buf, uids, n));
free(t);
assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
r = sd_seat_get_active(NULL, &t, NULL);
assert_se(IN_SET(r, 0, -ENODATA));
- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t));
+ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t));
free(t);
r = sd_get_sessions(&sessions);
static void test_monitor(void) {
sd_login_monitor *m = NULL;
- unsigned n;
int r;
- r = sd_login_monitor_new("session", &m);
- assert_se(r >= 0);
+ assert_se(sd_login_monitor_new("session", &m) == 0);
- for (n = 0; n < 5; n++) {
+ for (unsigned n = 0; n < 5; n++) {
struct pollfd pollfd = {};
usec_t timeout, nw;
return r;
}
+int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
+ void *attr_data, *data;
+ int r;
+
+ assert_return(m, -EINVAL);
+
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
+ if (r < 0)
+ return r;
+
+ if (ret_data) {
+ data = memdup(attr_data, r);
+ if (!data)
+ return -ENOMEM;
+
+ *ret_data = data;
+ }
+
+ if (ret_size)
+ *ret_size = r;
+
+ return r;
+}
+
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) {
void *attr_data;
char *str;
return 0;
}
-int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
- int r;
+int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data) {
void *attr_data;
+ int r;
assert_return(m, -EINVAL);
+ assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
if (r < 0)
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
- else if ((size_t) r < sizeof(struct in_addr))
+ else if ((size_t) r < FAMILY_ADDRESS_SIZE(family))
return -EIO;
if (data)
- memcpy(data, attr_data, sizeof(struct in_addr));
+ memcpy(data, attr_data, FAMILY_ADDRESS_SIZE(family));
return 0;
}
-int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
+int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
+ union in_addr_union u;
int r;
- void *attr_data;
- assert_return(m, -EINVAL);
+ r = netlink_message_read_in_addr_union(m, type, AF_INET, &u);
+ if (r >= 0 && data)
+ *data = u.in;
- r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
- if (r < 0)
- return r;
+ return r;
+}
- r = netlink_message_read_internal(m, type, &attr_data, NULL);
- if (r < 0)
- return r;
- else if ((size_t) r < sizeof(struct in6_addr))
- return -EIO;
+int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
+ union in_addr_union u;
+ int r;
- if (data)
- memcpy(data, attr_data, sizeof(struct in6_addr));
+ r = netlink_message_read_in_addr_union(m, type, AF_INET6, &u);
+ if (r >= 0 && data)
+ *data = u.in6;
- return 0;
+ return r;
}
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
[RTA_TABLE] = { .type = NETLINK_TYPE_U32 },
[RTA_MARK] = { .type = NETLINK_TYPE_U32 },
[RTA_MFC_STATS] = { .type = NETLINK_TYPE_U64 },
- [RTA_VIA] = { .type = NETLINK_TYPE_U32 },
+ [RTA_VIA] = { /* See struct rtvia */ },
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
return 0;
}
+
+int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) {
+ _cleanup_ordered_set_free_free_ OrderedSet *set = NULL;
+ int r;
+
+ assert(rtnh);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+
+ if (size < sizeof(struct rtnexthop))
+ return -EBADMSG;
+
+ for (; size >= sizeof(struct rtnexthop); ) {
+ _cleanup_free_ MultipathRoute *m = NULL;
+
+ if (NLMSG_ALIGN(rtnh->rtnh_len) > size)
+ return -EBADMSG;
+
+ if (rtnh->rtnh_len < sizeof(struct rtnexthop))
+ return -EBADMSG;
+
+ m = new(MultipathRoute, 1);
+ if (!m)
+ return -ENOMEM;
+
+ *m = (MultipathRoute) {
+ .ifindex = rtnh->rtnh_ifindex,
+ .weight = rtnh->rtnh_hops == 0 ? 0 : rtnh->rtnh_hops + 1,
+ };
+
+ if (rtnh->rtnh_len > sizeof(struct rtnexthop)) {
+ size_t len = rtnh->rtnh_len - sizeof(struct rtnexthop);
+
+ for (struct rtattr *attr = RTNH_DATA(rtnh); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
+ if (attr->rta_type == RTA_GATEWAY) {
+ if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(family)))
+ return -EBADMSG;
+
+ m->gateway.family = family;
+ memcpy(&m->gateway.address, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(family));
+ break;
+ } else if (attr->rta_type == RTA_VIA) {
+ uint16_t gw_family;
+
+ if (family != AF_INET)
+ return -EINVAL;
+
+ if (attr->rta_len < RTA_LENGTH(sizeof(uint16_t)))
+ return -EBADMSG;
+
+ gw_family = *(uint16_t *) RTA_DATA(attr);
+
+ if (gw_family != AF_INET6)
+ return -EBADMSG;
+
+ if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family)))
+ return -EBADMSG;
+
+ memcpy(&m->gateway, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family));
+ break;
+ }
+ }
+ }
+
+ r = ordered_set_ensure_put(&set, NULL, m);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(m);
+
+ size -= NLMSG_ALIGN(rtnh->rtnh_len);
+ rtnh = RTNH_NEXT(rtnh);
+ }
+
+ if (ret)
+ *ret = TAKE_PTR(set);
+ return 0;
+}
#include "sd-netlink.h"
#include "in-addr-util.h"
+#include "ordered-set.h"
#include "socket-util.h"
#include "util.h"
+/* See struct rtvia in rtnetlink.h */
+typedef struct RouteVia {
+ uint16_t family;
+ union in_addr_union address;
+} _packed_ RouteVia;
+
+typedef struct MultipathRoute {
+ RouteVia gateway;
+ int ifindex;
+ uint32_t weight;
+} MultipathRoute;
+
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
uint32_t rtnl_message_get_serial(sd_netlink_message *m);
void rtnl_message_seal(sd_netlink_message *m);
userdata, 0, __func__); \
})
-#define netlink_add_match(nl, ret_slot, metch, callback, destroy_callback, userdata) \
+#define netlink_add_match(nl, ret_slot, match, callback, destroy_callback, userdata, description) \
({ \
int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \
void (*_destroy_)(typeof(userdata)) = destroy_callback; \
sd_netlink_add_match(nl, ret_slot, match, \
(sd_netlink_message_handler_t) _callback_, \
(sd_netlink_destroy_t) _destroy_, \
- userdata, __func__); \
+ userdata, description); \
})
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
+int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data);
+
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length);
+
+int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret);
return;
}
- addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.s_addr = htobe32(INADDR_LOOPBACK);
r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr);
if (r < 0) {
struct sockaddr_in sa = {
.sin_family = AF_INET,
- .sin_port = htons(80)
+ .sin_port = htobe16(80)
};
assert_se(sd_resolve_default(&resolve) >= 0);
r = sd_bus_default_system(&bus);
if (r < 0)
- return log_error_errno(r, "Failed to connect to bus: %m");
+ return bus_log_connect_error(r);
if (arg_action == ACTION_LIST)
return print_inhibitors(bus);
printf("\t Unit: %s\n", i.scope);
show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
- if (arg_transport == BUS_TRANSPORT_LOCAL) {
-
+ if (arg_transport == BUS_TRANSPORT_LOCAL)
show_journal_by_unit(
stdout,
i.scope,
SD_JOURNAL_LOCAL_ONLY,
true,
NULL);
- }
}
return 0;
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" -p --property=NAME Show only properties by this name\n"
+ " -P NAME Equivalent to --value --property=NAME\n"
" -a --all Show all properties, including empty ones\n"
" --value When showing properties, only print the value\n"
" -l --full Do not ellipsize output\n"
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hp:P:als:H:M:n:o:", options, NULL)) >= 0)
switch (c) {
case ARG_VERSION:
return version();
+ case 'P':
+ arg_value = true;
+ _fallthrough_;
+
case 'p': {
r = strv_extend(&arg_property, optarg);
if (r < 0)
/* If the key handling is turned off, don't do anything */
if (handle == HANDLE_IGNORE) {
- log_debug("Refusing operation, as it is turned off.");
+ log_debug("Handling of %s (%s) is disabled, taking no action.",
+ inhibit_key == 0 ? "idle timeout" : inhibit_what_to_string(inhibit_key),
+ is_edge ? "edge" : "level");
return 0;
}
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stdio-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "udev-util.h"
return -EBUSY;
}
- snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
+ xsprintf(name, "autovt@tty%u.service", vtnr);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
r = inhibitor_start(i);
if (r < 0)
return r;
+ TAKE_PTR(i);
return sd_bus_reply_method_return(message, "h", fifo_fd);
}
if (r < 0)
return r;
- /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
- * sessions). */
+ /* Let's make sure we noticed dead sessions before we process new bus requests (which might
+ * create new sessions). */
r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
if (r < 0)
return r;
name = s->controller;
- /* By resetting the controller before releasing the devices, we won't
- * send notification signals. This avoids sending useless notifications
- * if the controller is released on disconnects. */
+ /* By resetting the controller before releasing the devices, we won't send notification signals.
+ * This avoids sending useless notifications if the controller is released on disconnects. */
if (!notify)
s->controller = NULL;
static const char* const session_state_table[_SESSION_STATE_MAX] = {
[SESSION_OPENING] = "opening",
- [SESSION_ONLINE] = "online",
- [SESSION_ACTIVE] = "active",
- [SESSION_CLOSING] = "closing"
+ [SESSION_ONLINE] = "online",
+ [SESSION_ACTIVE] = "active",
+ [SESSION_CLOSING] = "closing",
};
DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
static const char* const session_type_table[_SESSION_TYPE_MAX] = {
[SESSION_UNSPECIFIED] = "unspecified",
- [SESSION_TTY] = "tty",
- [SESSION_X11] = "x11",
- [SESSION_WAYLAND] = "wayland",
- [SESSION_MIR] = "mir",
- [SESSION_WEB] = "web",
+ [SESSION_TTY] = "tty",
+ [SESSION_X11] = "x11",
+ [SESSION_WAYLAND] = "wayland",
+ [SESSION_MIR] = "mir",
+ [SESSION_WEB] = "web",
};
DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
static const char* const session_class_table[_SESSION_CLASS_MAX] = {
- [SESSION_USER] = "user",
- [SESSION_GREETER] = "greeter",
+ [SESSION_USER] = "user",
+ [SESSION_GREETER] = "greeter",
[SESSION_LOCK_SCREEN] = "lock-screen",
- [SESSION_BACKGROUND] = "background"
+ [SESSION_BACKGROUND] = "background",
};
DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
static const char* const kill_who_table[_KILL_WHO_MAX] = {
[KILL_LEADER] = "leader",
- [KILL_ALL] = "all"
+ [KILL_ALL] = "all",
};
DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
- [TTY_FROM_PAM] = "from-pam",
- [TTY_FROM_UTMP] = "from-utmp",
+ [TTY_FROM_PAM] = "from-pam",
+ [TTY_FROM_UTMP] = "from-utmp",
[TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
};
#include "bus-log-control-api.h"
#include "bus-polkit.h"
#include "cgroup-util.h"
+#include "daemon-util.h"
#include "def.h"
#include "device-util.h"
#include "dirent-util.h"
LIST_REMOVE(gc_queue, m->session_gc_queue, session);
session->in_gc_queue = false;
- /* First, if we are not closing yet, initiate stopping */
+ /* First, if we are not closing yet, initiate stopping. */
if (session_may_gc(session, drop_not_started) &&
session_get_state(session) != SESSION_CLOSING)
(void) session_stop(session, /* force = */ false);
- /* Normally, this should make the session referenced
- * again, if it doesn't then let's get rid of it
- * immediately */
+ /* Normally, this should make the session referenced again, if it doesn't then let's get rid
+ * of it immediately. */
if (session_may_gc(session, drop_not_started)) {
(void) session_finalize(session);
session_free(session);
static int run(int argc, char *argv[]) {
_cleanup_(manager_unrefp) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
int r;
log_set_facility(LOG_AUTH);
if (r < 0)
return r;
- /* Always create the directories people can create inotify watches in. Note that some applications might check
- * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make
- * sure these directories are created early on and unconditionally. */
+ /* Always create the directories people can create inotify watches in. Note that some applications
+ * might check for the existence of /run/systemd/seats/ to determine whether logind is available, so
+ * please always make sure these directories are created early on and unconditionally. */
(void) mkdir_label("/run/systemd/seats", 0755);
(void) mkdir_label("/run/systemd/users", 0755);
(void) mkdir_label("/run/systemd/sessions", 0755);
if (r < 0)
return log_error_errno(r, "Failed to fully start up daemon: %m");
- log_debug("systemd-logind running as pid "PID_FMT, getpid_cached());
- (void) sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- r = manager_run(m);
-
- log_debug("systemd-logind stopped as pid "PID_FMT, getpid_cached());
- (void) sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- return r;
+ notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
+ return manager_run(m);
}
DEFINE_MAIN_FUNCTION(run);
if (r < 0)
return log_error_errno(r, "Failed to read machine ID back: %m");
} else {
- r = machine_id_setup(arg_root, SD_ID128_NULL, &id);
+ r = machine_id_setup(arg_root, false, SD_ID128_NULL, &id);
if (r < 0)
return r;
}
assert(bus);
- if (!strv_isempty(arg_setenv) || arg_uid) {
- log_error("--setenv= and --uid= are not supported for 'login'. Use 'shell' instead.");
- return -EINVAL;
- }
+ if (!strv_isempty(arg_setenv) || arg_uid)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--setenv= and --uid= are not supported for 'login'. Use 'shell' instead.");
- if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) {
- log_error("Login only supported on local machines.");
- return -EOPNOTSUPP;
- }
+ if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE))
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Login only supported on local machines.");
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
assert(bus);
- if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) {
- log_error("Shell only supported on local machines.");
- return -EOPNOTSUPP;
- }
+ if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE))
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Shell only supported on local machines.");
/* Pass $TERM to shell session, if not explicitly specified. */
if (!strv_find_prefix(arg_setenv, "TERM=")) {
if (argc > 2) {
b = parse_boolean(argv[2]);
- if (b < 0) {
- log_error("Failed to parse boolean argument: %s", argv[2]);
- return -EINVAL;
- }
+ if (b < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse boolean argument: %s",
+ argv[2]);
}
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
r = image_exists(bus, argv[i]);
if (r < 0)
return r;
- if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[i]);
- return -ENXIO;
- }
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
+ "Machine image '%s' does not exist.",
+ argv[i]);
r = sd_bus_call_method(
bus,
r = image_exists(bus, argv[i]);
if (r < 0)
return r;
- if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[i]);
- return -ENXIO;
- }
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
+ "Machine image '%s' does not exist.",
+ argv[i]);
r = sd_bus_message_append(m, "s", unit);
if (r < 0)
local = fn;
}
- if (!local) {
- log_error("Need either path or local name.");
- return -EINVAL;
- }
+ if (!local)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Need either path or local name.");
r = tar_strip_suffixes(local, &ll);
if (r < 0)
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local name %s is not a suitable machine name.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local name %s is not a suitable machine name.",
+ local);
if (path) {
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
local = fn;
}
- if (!local) {
- log_error("Need either path or local name.");
- return -EINVAL;
- }
+ if (!local)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Need either path or local name.");
r = raw_strip_suffixes(local, &ll);
if (r < 0)
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local name %s is not a suitable machine name.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local name %s is not a suitable machine name.",
+ local);
if (path) {
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
local = fn;
}
- if (!local) {
- log_error("Need either path or local name.");
- return -EINVAL;
- }
+ if (!local)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Need either path or local name.");
- if (!machine_name_is_valid(local)) {
- log_error("Local name %s is not a suitable machine name.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local name %s is not a suitable machine name.",
+ local);
if (path) {
fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
assert(bus);
local = argv[1];
- if (!machine_name_is_valid(local)) {
- log_error("Machine name %s is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Machine name %s is not valid.", local);
if (argc >= 3)
path = argv[2];
assert(bus);
local = argv[1];
- if (!machine_name_is_valid(local)) {
- log_error("Machine name %s is not valid.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Machine name %s is not valid.", local);
if (argc >= 3)
path = argv[2];
assert(bus);
remote = argv[1];
- if (!http_url_is_valid(remote)) {
- log_error("URL '%s' is not valid.", remote);
- return -EINVAL;
- }
+ if (!http_url_is_valid(remote))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "URL '%s' is not valid.", remote);
if (argc >= 3)
local = argv[2];
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local name %s is not a suitable machine name.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local name %s is not a suitable machine name.",
+ local);
}
r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTar");
assert(bus);
remote = argv[1];
- if (!http_url_is_valid(remote)) {
- log_error("URL '%s' is not valid.", remote);
- return -EINVAL;
- }
+ if (!http_url_is_valid(remote))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "URL '%s' is not valid.", remote);
if (argc >= 3)
local = argv[2];
local = ll;
- if (!machine_name_is_valid(local)) {
- log_error("Local name %s is not a suitable machine name.", local);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(local))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Local name %s is not a suitable machine name.",
+ local);
}
r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRaw");
if (stat(what, &st) < 0)
return log_error_errno(errno, "Can't stat %s: %m", what);
- if (!S_ISBLK(st.st_mode)) {
- log_error("Not a block device: %s", what);
- return -ENOTBLK;
- }
+ if (!S_ISBLK(st.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
+ "Not a block device: %s", what);
r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
if (r < 0)
escaped = xescape(basename(arg_mount_what), "\\");
if (!escaped)
return log_oom();
- if (!filename_is_valid(escaped)) {
- log_error("Escaped name %s is not a valid filename.", escaped);
- return -EINVAL;
- }
+ if (!filename_is_valid(escaped))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Escaped name %s is not a valid filename.",
+ escaped);
arg_mount_where = path_join("/run/media/system", escaped);
if (!arg_mount_where)
if (stat(loop_dev, &st) < 0)
return log_error_errno(errno, "Can't stat %s: %m", loop_dev);
- if (!S_ISBLK(st.st_mode)) {
- log_error("Invalid file type: %s", loop_dev);
- return -EINVAL;
- }
+ if (!S_ISBLK(st.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid file type: %s", loop_dev);
r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
if (r < 0)
if (S_ISREG(st.st_mode))
return discover_loop_backing_file();
- if (!S_ISBLK(st.st_mode)) {
- log_error("Invalid file type: %s", arg_mount_what);
- return -EINVAL;
- }
+ if (!S_ISBLK(st.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid file type: %s",
+ arg_mount_what);
r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
if (r < 0)
return log_error_errno(r, "Failed to get device from device number: %m");
- if (sd_device_get_property_value(d, "ID_FS_USAGE", &v) < 0 || !streq(v, "filesystem")) {
- log_error("%s does not contain a known file system.", arg_mount_what);
- return -EINVAL;
- }
+ if (sd_device_get_property_value(d, "ID_FS_USAGE", &v) < 0 || !streq(v, "filesystem"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s does not contain a known file system.",
+ arg_mount_what);
r = acquire_mount_type(d);
if (r < 0)
return action_umount(bus, argc, argv);
if ((!arg_mount_type || fstype_is_blockdev_backed(arg_mount_type))
- && !path_is_normalized(arg_mount_what)) {
- log_error("Path contains non-normalized components: %s", arg_mount_what);
- return -EINVAL;
- }
+ && !path_is_normalized(arg_mount_what))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Path contains non-normalized components: %s",
+ arg_mount_what);
if (arg_discover) {
r = discover_device();
return r;
}
- if (!arg_mount_where) {
- log_error("Can't figure out where to mount %s.", arg_mount_what);
- return -EINVAL;
- }
+ if (!arg_mount_where)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Can't figure out where to mount %s.",
+ arg_mount_what);
- if (path_equal(arg_mount_where, "/")) {
- log_error("Refusing to operate on root directory.");
- return -EINVAL;
- }
+ if (path_equal(arg_mount_where, "/"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Refusing to operate on root directory.");
- if (!path_is_normalized(arg_mount_where)) {
- log_error("Path contains non-normalized components: %s", arg_mount_where);
- return -EINVAL;
- }
+ if (!path_is_normalized(arg_mount_where))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Path contains non-normalized components: %s",
+ arg_mount_where);
if (streq_ptr(arg_mount_type, "auto"))
arg_mount_type = mfree(arg_mount_type);
if (arg_mount_type &&
!streq(arg_mount_type, "auto") &&
arg_uid != UID_INVALID &&
- !fstype_can_uid_gid(arg_mount_type)) {
- log_error("File system type %s is not known to support uid=/gid=, refusing.",
- arg_mount_type);
- return -EOPNOTSUPP;
- }
+ !fstype_can_uid_gid(arg_mount_type))
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "File system type %s is not known to support uid=/gid=, refusing.",
+ arg_mount_type);
switch (arg_action) {
networkd-speed-meter.h
networkd-sriov.c
networkd-sriov.h
+ networkd-sysctl.c
+ networkd-sysctl.h
networkd-util.c
networkd-util.h
networkd-wifi.c
#include "memory-util.h"
#include "netlink-util.h"
#include "network-internal.h"
-#include "networkd-address.h"
#include "networkd-manager.h"
#include "path-util.h"
#include "socket-util.h"
#include <netinet/in.h>
#include <linux/if_macsec.h>
+#include "ether-addr-util.h"
#include "in-addr-util.h"
#include "netdev.h"
#include "networkd-util.h"
if (r < 0)
return table_log_add_error(r);
- if (info->port_state <= BR_STATE_BLOCKING) {
+ if (info->port_state <= BR_STATE_BLOCKING)
r = table_add_many(table,
TABLE_EMPTY,
TABLE_STRING, "Port State:",
TABLE_STRING, bridge_state_to_string(info->port_state));
- }
} else if (streq_ptr(info->netdev_kind, "bond")) {
r = table_add_many(table,
TABLE_EMPTY,
#include <linux/if_addrlabel.h>
#include "alloc-util.h"
-#include "conf-parser.h"
-#include "networkd-address-label.h"
#include "netlink-util.h"
+#include "networkd-address-label.h"
+#include "networkd-link.h"
#include "networkd-manager.h"
+#include "networkd-network.h"
#include "parse-util.h"
-#include "socket-util.h"
-void address_label_free(AddressLabel *label) {
+AddressLabel *address_label_free(AddressLabel *label) {
if (!label)
- return;
+ return NULL;
if (label->network) {
- LIST_REMOVE(labels, label->network->address_labels, label);
- assert(label->network->n_address_labels > 0);
- label->network->n_address_labels--;
-
- if (label->section) {
- hashmap_remove(label->network->address_labels_by_section, label->section);
- network_config_section_free(label->section);
- }
+ assert(label->section);
+ hashmap_remove(label->network->address_labels_by_section, label->section);
}
- free(label);
+ network_config_section_free(label->section);
+ return mfree(label);
}
+DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
+
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(address_label_freep) AddressLabel *label = NULL;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- label = hashmap_get(network->address_labels_by_section, n);
- if (label) {
- *ret = TAKE_PTR(label);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ label = hashmap_get(network->address_labels_by_section, n);
+ if (label) {
+ *ret = TAKE_PTR(label);
+ return 0;
}
label = new(AddressLabel, 1);
*label = (AddressLabel) {
.network = network,
+ .section = TAKE_PTR(n),
};
- LIST_APPEND(labels, network->address_labels, label);
- network->n_address_labels++;
-
- if (filename) {
- label->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->address_labels_by_section, label->section, label);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->address_labels_by_section, label->section, label);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(label);
-
return 0;
}
return 1;
}
-int address_label_configure(
- AddressLabel *label,
- Link *link,
- link_netlink_message_handler_t callback,
- bool update) {
-
+static int address_label_configure(AddressLabel *label, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req,
- callback ?: address_label_handler,
+ address_label_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return 0;
}
+int link_set_address_labels(Link *link) {
+ AddressLabel *label;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ HASHMAP_FOREACH(label, link->network->address_labels_by_section) {
+ r = address_label_configure(label, link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set address label: %m");
+
+ link->address_label_messages++;
+ }
+
+ return 0;
+}
+
+void network_drop_invalid_address_labels(Network *network) {
+ AddressLabel *label;
+
+ assert(network);
+
+ HASHMAP_FOREACH(label, network->address_labels_by_section)
+ if (section_is_invalid(label->section))
+ address_label_free(label);
+}
+
int config_parse_address_label_prefix(const char *unit,
const char *filename,
unsigned line,
#pragma once
#include <inttypes.h>
-#include <stdbool.h>
#include "conf-parser.h"
#include "in-addr-util.h"
-
-typedef struct AddressLabel AddressLabel;
-
-#include "networkd-link.h"
-#include "networkd-network.h"
#include "networkd-util.h"
typedef struct Network Network;
typedef struct Link Link;
-typedef struct NetworkConfigSection NetworkConfigSection;
-struct AddressLabel {
+typedef struct AddressLabel {
Network *network;
NetworkConfigSection *section;
unsigned char prefixlen;
uint32_t label;
-
union in_addr_union in_addr;
+} AddressLabel;
- LIST_FIELDS(AddressLabel, labels);
-};
-
-void address_label_free(AddressLabel *label);
+AddressLabel *address_label_free(AddressLabel *label);
-DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
+void network_drop_invalid_address_labels(Network *network);
-int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update);
+int link_set_address_labels(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
#include "alloc-util.h"
#include "networkd-address-pool.h"
+#include "networkd-address.h"
#include "networkd-manager.h"
#include "set.h"
#include "string-util.h"
static int address_pool_new(
Manager *m,
- AddressPool **ret,
int family,
const union in_addr_union *u,
unsigned prefixlen) {
- AddressPool *p;
+ _cleanup_free_ AddressPool *p = NULL;
+ int r;
assert(m);
- assert(ret);
assert(u);
p = new(AddressPool, 1);
.in_addr = *u,
};
- LIST_PREPEND(address_pools, m->address_pools, p);
+ r = ordered_set_ensure_put(&m->address_pools, NULL, p);
+ if (r < 0)
+ return r;
- *ret = p;
+ TAKE_PTR(p);
return 0;
}
-int address_pool_new_from_string(
+static int address_pool_new_from_string(
Manager *m,
- AddressPool **ret,
int family,
const char *p,
unsigned prefixlen) {
int r;
assert(m);
- assert(ret);
assert(p);
r = in_addr_from_string(family, p, &u);
if (r < 0)
return r;
- return address_pool_new(m, ret, family, &u, prefixlen);
+ return address_pool_new(m, family, &u, prefixlen);
}
-void address_pool_free(AddressPool *p) {
+int address_pool_setup_default(Manager *m) {
+ int r;
- if (!p)
- return;
+ assert(m);
- if (p->manager)
- LIST_REMOVE(address_pools, p->manager->address_pools, p);
+ /* Add in the well-known private address ranges. */
+ r = address_pool_new_from_string(m, AF_INET6, "fd00::", 8);
+ if (r < 0)
+ return r;
+
+ r = address_pool_new_from_string(m, AF_INET, "192.168.0.0", 16);
+ if (r < 0)
+ return r;
+
+ r = address_pool_new_from_string(m, AF_INET, "172.16.0.0", 12);
+ if (r < 0)
+ return r;
+
+ r = address_pool_new_from_string(m, AF_INET, "10.0.0.0", 8);
+ if (r < 0)
+ return r;
- free(p);
+ return 0;
}
static bool address_pool_prefix_is_taken(
}
/* Don't clash with addresses already pulled from the pool, but not assigned yet */
- LIST_FOREACH(addresses, a, l->pool_addresses) {
+ SET_FOREACH(a, l->pool_addresses) {
if (a->family != p->family)
continue;
ORDERED_HASHMAP_FOREACH(n, p->manager->networks) {
Address *a;
- LIST_FOREACH(addresses, a, n->static_addresses) {
+ ORDERED_HASHMAP_FOREACH(a, n->addresses_by_section) {
if (a->family != p->family)
continue;
return false;
}
-int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
+static int address_pool_acquire_one(AddressPool *p, int family, unsigned prefixlen, union in_addr_union *found) {
union in_addr_union u;
unsigned i;
int r;
assert(prefixlen > 0);
assert(found);
+ if (p->family != family)
+ return 0;
+
if (p->prefixlen >= prefixlen)
return 0;
return 0;
}
+
+int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
+ AddressPool *p;
+ int r;
+
+ assert(m);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+ assert(prefixlen > 0);
+ assert(found);
+
+ ORDERED_SET_FOREACH(p, m->address_pools) {
+ r = address_pool_acquire_one(p, family, prefixlen, found);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-typedef struct AddressPool AddressPool;
-
#include "in-addr-util.h"
-#include "list.h"
typedef struct Manager Manager;
-struct AddressPool {
+typedef struct AddressPool {
Manager *manager;
int family;
unsigned prefixlen;
-
union in_addr_union in_addr;
+} AddressPool;
- LIST_FIELDS(AddressPool, address_pools);
-};
-
-int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
-void address_pool_free(AddressPool *p);
-
-int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found);
+int address_pool_setup_default(Manager *m);
+int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
#include <net/if.h>
#include "alloc-util.h"
-#include "conf-parser.h"
#include "firewall-util.h"
#include "memory-util.h"
-#include "missing_network.h"
#include "netlink-util.h"
+#include "networkd-address-pool.h"
#include "networkd-address.h"
#include "networkd-manager.h"
-#include "networkd-ndisc.h"
+#include "networkd-network.h"
#include "parse-util.h"
-#include "set.h"
-#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
-#include "utf8.h"
#define ADDRESSES_PER_LINK_MAX 2048U
#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
-int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret) {
+int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret) {
assert(link);
assert(ret);
.cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME,
.cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME,
.duplicate_address_detection = ADDRESS_FAMILY_IPV6,
- .prefix_route = true,
};
*ret = TAKE_PTR(address);
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- address = hashmap_get(network->addresses_by_section, n);
- if (address) {
- *ret = TAKE_PTR(address);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ address = ordered_hashmap_get(network->addresses_by_section, n);
+ if (address) {
+ *ret = TAKE_PTR(address);
+ return 0;
}
- if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX)
+ if (ordered_hashmap_size(network->addresses_by_section) >= STATIC_ADDRESSES_PER_NETWORK_MAX)
return -E2BIG;
r = address_new(&address);
return r;
address->network = network;
- LIST_APPEND(addresses, network->static_addresses, address);
- network->n_static_addresses++;
+ address->section = TAKE_PTR(n);
- if (filename) {
- address->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = ordered_hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->addresses_by_section, address->section, address);
- if (r < 0)
- return r;
- }
+ r = ordered_hashmap_put(network->addresses_by_section, address->section, address);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(address);
-
return 0;
}
-void address_free(Address *address) {
+Address *address_free(Address *address) {
if (!address)
- return;
+ return NULL;
if (address->network) {
- LIST_REMOVE(addresses, address->network->static_addresses, address);
- assert(address->network->n_static_addresses > 0);
- address->network->n_static_addresses--;
-
- if (address->section)
- hashmap_remove(address->network->addresses_by_section, address->section);
+ assert(address->section);
+ ordered_hashmap_remove(address->network->addresses_by_section, address->section);
}
- if (address->link && !address->acd) {
+ if (address->link) {
NDiscAddress *n;
set_remove(address->link->addresses, address);
network_config_section_free(address->section);
free(address->label);
- free(address);
-}
-
-static uint32_t address_prefix(const Address *a) {
- assert(a);
-
- /* make sure we don't try to shift by 32.
- * See ISO/IEC 9899:TC3 § 6.5.7.3. */
- if (a->prefixlen == 0)
- return 0;
-
- if (a->in_addr_peer.in.s_addr != 0)
- return be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
- else
- return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
+ return mfree(address);
}
void address_hash_func(const Address *a, struct siphash *state) {
switch (a->family) {
case AF_INET:
- siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
-
- /* peer prefix */
- uint32_t prefix = address_prefix(a);
- siphash24_compress(&prefix, sizeof(prefix), state);
+ siphash24_compress(&a->broadcast, sizeof(a->broadcast), state);
+ siphash24_compress_string(a->label, state);
_fallthrough_;
case AF_INET6:
+ siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
/* local address */
siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
+ /* peer address */
+ siphash24_compress(&a->in_addr_peer, FAMILY_ADDRESS_SIZE(a->family), state);
break;
default:
switch (a1->family) {
/* use the same notion of equality as the kernel does */
case AF_INET:
- r = CMP(a1->prefixlen, a2->prefixlen);
+ r = CMP(a1->broadcast.s_addr, a2->broadcast.s_addr);
if (r != 0)
return r;
- uint32_t prefix1 = address_prefix(a1);
- uint32_t prefix2 = address_prefix(a2);
- r = CMP(prefix1, prefix2);
+ r = strcmp_ptr(a1->label, a2->label);
if (r != 0)
return r;
_fallthrough_;
case AF_INET6:
- return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
+ r = CMP(a1->prefixlen, a2->prefixlen);
+ if (r != 0)
+ return r;
+
+ r = memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
+ if (r != 0)
+ return r;
+
+ return memcmp(&a1->in_addr_peer, &a2->in_addr_peer, FAMILY_ADDRESS_SIZE(a1->family));
default:
/* treat any other address family as AF_UNSPEC */
return 0;
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
-bool address_equal(Address *a1, Address *a2) {
+bool address_equal(const Address *a1, const Address *a2) {
if (a1 == a2)
return true;
return address_compare_func(a1, a2) == 0;
}
-static int address_establish(Address *address, Link *link) {
- bool masq;
+static int address_copy(Address *dest, const Address *src) {
+ int r;
+
+ assert(dest);
+ assert(src);
+
+ r = free_and_strdup(&dest->label, src->label);
+ if (r < 0)
+ return r;
+
+ dest->family = src->family;
+ dest->prefixlen = src->prefixlen;
+ dest->scope = src->scope;
+ dest->flags = src->flags;
+ dest->broadcast = src->broadcast;
+ dest->cinfo = src->cinfo;
+ dest->in_addr = src->in_addr;
+ dest->in_addr_peer = src->in_addr_peer;
+ dest->duplicate_address_detection = src->duplicate_address_detection;
+
+ return 0;
+}
+
+static int address_set_masquerade(Address *address, bool add) {
+ union in_addr_union masked;
int r;
assert(address);
- assert(link);
+ assert(address->link);
+
+ if (!address->link->network)
+ return 0;
- masq = link->network &&
- link->network->ip_masquerade &&
- address->family == AF_INET &&
- address->scope < RT_SCOPE_LINK;
+ if (!address->link->network->ip_masquerade)
+ return 0;
- /* Add firewall entry if this is requested */
- if (address->ip_masquerade_done != masq) {
- union in_addr_union masked = address->in_addr;
- in_addr_mask(address->family, &masked, address->prefixlen);
+ if (address->family != AF_INET)
+ return 0;
- r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
- if (r < 0)
- return r;
+ if (address->scope >= RT_SCOPE_LINK)
+ return 0;
- address->ip_masquerade_done = masq;
- }
+ if (address->ip_masquerade_done == add)
+ return 0;
+
+ masked = address->in_addr;
+ r = in_addr_mask(address->family, &masked, address->prefixlen);
+ if (r < 0)
+ return r;
+
+ r = fw_add_masquerade(add, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
+ if (r < 0)
+ return r;
+
+ address->ip_masquerade_done = add;
return 0;
}
-static int address_add_internal(Link *link, Set **addresses,
- int family,
- const union in_addr_union *in_addr,
- unsigned char prefixlen,
- Address **ret) {
+static int address_add_internal(Link *link, Set **addresses, const Address *in, Address **ret) {
_cleanup_(address_freep) Address *address = NULL;
int r;
assert(link);
assert(addresses);
- assert(in_addr);
+ assert(in);
r = address_new(&address);
if (r < 0)
return r;
- address->family = family;
- address->in_addr = *in_addr;
- address->prefixlen = prefixlen;
+ r = address_copy(address, in);
+ if (r < 0)
+ return r;
+
/* Consider address tentative until we get the real flags from the kernel */
address->flags = IFA_F_TENTATIVE;
return 0;
}
-int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
- return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret);
+static int address_add_foreign(Link *link, const Address *in, Address **ret) {
+ return address_add_internal(link, &link->addresses_foreign, in, ret);
}
-int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
+static int address_add(Link *link, const Address *in, Address **ret) {
Address *address;
int r;
- r = address_get(link, family, in_addr, prefixlen, &address);
+ assert(link);
+ assert(in);
+
+ r = address_get(link, in, &address);
if (r == -ENOENT) {
/* Address does not exist, create a new one */
- r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address);
+ r = address_add_internal(link, &link->addresses, in, &address);
if (r < 0)
return r;
} else if (r == 0) {
return 0;
}
-static int address_release(Address *address) {
- int r;
-
- assert(address);
- assert(address->link);
-
- /* Remove masquerading firewall entry if it was added */
- if (address->ip_masquerade_done) {
- union in_addr_union masked = address->in_addr;
- in_addr_mask(address->family, &masked, address->prefixlen);
-
- r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
- if (r < 0)
- return r;
-
- address->ip_masquerade_done = false;
- }
-
- return 0;
-}
-
-int address_update(
- Address *address,
- unsigned char flags,
- unsigned char scope,
- const struct ifa_cacheinfo *cinfo) {
-
+static int address_update(Address *address, const Address *src) {
bool ready;
int r;
assert(address);
assert(address->link);
- assert(cinfo);
+ assert(src);
ready = address_is_ready(address);
- address->flags = flags;
- address->scope = scope;
- address->cinfo = *cinfo;
+ address->flags = src->flags;
+ address->scope = src->scope;
+ address->cinfo = src->cinfo;
if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
return 0;
}
-int address_drop(Address *address) {
+static int address_drop(Address *address) {
Link *link;
bool ready;
int r;
ready = address_is_ready(address);
link = address->link;
- r = address_release(address);
+ r = address_set_masquerade(address, false);
if (r < 0)
log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m");
return 0;
}
-int address_get(Link *link,
- int family,
- const union in_addr_union *in_addr,
- unsigned char prefixlen,
- Address **ret) {
-
- Address address, *existing;
+int address_get(Link *link, const Address *in, Address **ret) {
+ Address *existing;
assert(link);
- assert(in_addr);
-
- address = (Address) {
- .family = family,
- .in_addr = *in_addr,
- .prefixlen = prefixlen,
- };
+ assert(in);
- existing = set_get(link->addresses, &address);
+ existing = set_get(link->addresses, in);
if (existing) {
if (ret)
*ret = existing;
return 1;
}
- existing = set_get(link->addresses_foreign, &address);
+ existing = set_get(link->addresses_foreign, in);
if (existing) {
if (ret)
*ret = existing;
}
int address_remove(
- Address *address,
+ const Address *address,
Link *link,
link_netlink_message_handler_t callback) {
return 0;
}
-static int address_acquire(Link *link, Address *original, Address **ret) {
+static bool link_is_static_address_configured(const Link *link, const Address *address) {
+ Address *net_address;
+
+ assert(link);
+ assert(address);
+
+ if (!link->network)
+ return false;
+
+ ORDERED_HASHMAP_FOREACH(net_address, link->network->addresses_by_section)
+ if (address_equal(net_address, address))
+ return true;
+
+ return false;
+}
+
+static bool link_address_is_dynamic(const Link *link, const Address *address) {
+ Route *route;
+
+ assert(link);
+ assert(address);
+
+ if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
+ return true;
+
+ /* Even when the address is leased from a DHCP server, networkd assign the address
+ * without lifetime when KeepConfiguration=dhcp. So, let's check that we have
+ * corresponding routes with RTPROT_DHCP. */
+ SET_FOREACH(route, link->routes_foreign) {
+ if (route->protocol != RTPROT_DHCP)
+ continue;
+
+ if (address->family != route->family)
+ continue;
+
+ if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc))
+ return true;
+ }
+
+ return false;
+}
+
+static int link_enumerate_ipv6_tentative_addresses(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+ sd_netlink_message *addr;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, 0, AF_INET6);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_call(link->manager->rtnl, req, 0, &reply);
+ if (r < 0)
+ return r;
+
+ for (addr = reply; addr; addr = sd_netlink_message_next(addr)) {
+ unsigned char flags;
+ int ifindex;
+
+ r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: invalid ifindex, ignoring: %m");
+ continue;
+ } else if (link->ifindex != ifindex)
+ continue;
+
+ r = sd_rtnl_message_addr_get_flags(addr, &flags);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m");
+ continue;
+ } else if (!(flags & IFA_F_TENTATIVE))
+ continue;
+
+ log_link_debug(link, "Found tentative ipv6 link-local address");
+ (void) manager_rtnl_process_address(link->manager->rtnl, addr, link->manager);
+ }
+
+ return 0;
+}
+
+int link_drop_foreign_addresses(Link *link) {
+ Address *address;
+ int k, r = 0;
+
+ assert(link);
+
+ /* The kernel doesn't notify us about tentative addresses;
+ * so if ipv6ll is disabled, we need to enumerate them now so we can drop them below */
+ if (!link_ipv6ll_enabled(link)) {
+ r = link_enumerate_ipv6_tentative_addresses(link);
+ if (r < 0)
+ return r;
+ }
+
+ SET_FOREACH(address, link->addresses_foreign) {
+ /* we consider IPv6LL addresses to be managed by the kernel */
+ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
+ continue;
+
+ if (link_address_is_dynamic(link, address)) {
+ if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
+ continue;
+ } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC))
+ continue;
+
+ if (link_is_static_address_configured(link, address)) {
+ k = address_add(link, address, NULL);
+ if (k < 0) {
+ log_link_error_errno(link, k, "Failed to add address: %m");
+ if (r >= 0)
+ r = k;
+ }
+ } else {
+ k = address_remove(address, link, NULL);
+ if (k < 0 && r >= 0)
+ r = k;
+ }
+ }
+
+ return r;
+}
+
+static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(m);
+ assert(link);
+ assert(link->ifname);
+ assert(link->address_remove_messages > 0);
+
+ link->address_remove_messages--;
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EADDRNOTAVAIL)
+ log_link_message_warning_errno(link, m, r, "Could not drop address");
+ else if (r >= 0)
+ (void) manager_rtnl_process_address(rtnl, m, link->manager);
+
+ if (link->address_remove_messages == 0 && link->request_static_addresses) {
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ r = link_set_addresses(link);
+ if (r < 0)
+ link_enter_failed(link);
+ }
+
+ return 1;
+}
+
+int link_drop_addresses(Link *link) {
+ Address *address, *pool_address;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(address, link->addresses) {
+ /* we consider IPv6LL addresses to be managed by the kernel */
+ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
+ continue;
+
+ k = address_remove(address, link, remove_static_address_handler);
+ if (k < 0 && r >= 0) {
+ r = k;
+ continue;
+ }
+
+ link->address_remove_messages++;
+
+ SET_FOREACH(pool_address, link->pool_addresses)
+ if (address_equal(address, pool_address))
+ address_free(set_remove(link->pool_addresses, pool_address));
+ }
+
+ return r;
+}
+
+static int address_acquire(Link *link, const Address *original, Address **ret) {
union in_addr_union in_addr = IN_ADDR_NULL;
struct in_addr broadcast = {};
_cleanup_(address_freep) Address *na = NULL;
/* Something useful was configured? just use it */
r = in_addr_is_null(original->family, &original->in_addr);
- if (r <= 0)
+ if (r < 0)
return r;
+ if (r == 0) {
+ *ret = NULL;
+ return 0;
+ }
/* The address is configured to be 0.0.0.0 or [::] by the user?
* Then let's acquire something more useful from the pool. */
- r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
+ r = address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
if (r < 0)
return r;
if (r == 0)
if (r < 0)
return r;
- na->family = original->family;
- na->prefixlen = original->prefixlen;
- na->scope = original->scope;
- na->cinfo = original->cinfo;
-
- if (original->label) {
- na->label = strdup(original->label);
- if (!na->label)
- return -ENOMEM;
- }
+ r = address_copy(na, original);
+ if (r < 0)
+ return r;
na->broadcast = broadcast;
na->in_addr = in_addr;
- LIST_PREPEND(addresses, link->pool_addresses, na);
+ r = set_ensure_put(&link->pool_addresses, &address_hash_ops, na);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EEXIST;
*ret = TAKE_PTR(na);
-
- return 0;
+ return 1;
}
+static int ipv4_dad_configure(Address *address);
+
int address_configure(
- Address *address,
+ 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 *a;
+ Address *acquired_address, *a;
+ uint32_t flags;
int r;
assert(address);
assert(callback);
/* If this is a new address, then refuse adding more than the limit */
- if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
+ if (address_get(link, address, NULL) <= 0 &&
set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
"Too many addresses are configured, refusing: %m");
- r = address_acquire(link, address, &address);
+ r = address_acquire(link, address, &acquired_address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
+ if (acquired_address)
+ address = acquired_address;
if (DEBUG_LOGGING) {
_cleanup_free_ char *str = NULL;
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefixlen: %m");
- address->flags |= IFA_F_PERMANENT;
-
- if (address->home_address)
- address->flags |= IFA_F_HOMEADDRESS;
-
- if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6))
- address->flags |= IFA_F_NODAD;
-
- if (address->manage_temporary_address)
- address->flags |= IFA_F_MANAGETEMPADDR;
-
- if (!address->prefix_route)
- address->flags |= IFA_F_NOPREFIXROUTE;
-
- if (address->autojoin)
- address->flags |= IFA_F_MCAUTOJOIN;
-
- r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
+ flags = address->flags | IFA_F_PERMANENT;
+ r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
- if (address->flags & ~0xff) {
- r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
+ 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");
}
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
- r = address_establish(address, link);
+ r = address_add(link, address, &a);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not add address: %m");
+
+ r = address_set_masquerade(a, true);
if (r < 0)
log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
if (r < 0) {
- address_release(address);
+ (void) address_set_masquerade(a, false);
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
}
link_ref(link);
- if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
- r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a);
- else
- r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a);
- if (r < 0) {
- address_release(address);
- return log_link_error_errno(link, r, "Could not add address: %m");
- }
-
- if (address->acd) {
- assert(address->family == AF_INET);
- if (DEBUG_LOGGING) {
- _cleanup_free_ char *pretty = NULL;
-
- (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
- log_link_debug(link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
- }
-
- r = sd_ipv4acd_start(address->acd, true);
+ if (FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) {
+ r = ipv4_dad_configure(a);
if (r < 0)
log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
}
return 1;
}
-static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
- _cleanup_free_ char *pretty = NULL;
- Address *address;
+static int static_address_ready_callback(Address *address) {
+ Address *a;
Link *link;
- int r;
- assert(acd);
- assert(userdata);
+ assert(address);
+ assert(address->link);
- address = (Address *) userdata;
link = address->link;
- (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
- switch (event) {
- case SD_IPV4ACD_EVENT_STOP:
- log_link_debug(link, "Stopping ACD client...");
- return;
+ if (!link->addresses_configured)
+ return 0;
- case SD_IPV4ACD_EVENT_BIND:
- log_link_debug(link, "Successfully claimed address %s", strna(pretty));
- link_check_ready(link);
+ SET_FOREACH(a, link->static_addresses)
+ if (!address_is_ready(a)) {
+ _cleanup_free_ char *str = NULL;
+
+ (void) in_addr_to_string(a->family, &a->in_addr, &str);
+ log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen);
+ return 0;
+ }
+
+ /* This should not be called again */
+ SET_FOREACH(a, link->static_addresses)
+ a->callback = NULL;
+
+ link->addresses_ready = true;
+
+ return link_set_routes(link);
+}
+
+static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(rtnl);
+ assert(m);
+ assert(link);
+ assert(link->ifname);
+ assert(link->address_messages > 0);
+ assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
+ LINK_STATE_FAILED, LINK_STATE_LINGER));
+
+ link->address_messages--;
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST) {
+ log_link_message_warning_errno(link, m, r, "Could not set address");
+ link_enter_failed(link);
+ return 1;
+ } else if (r >= 0)
+ (void) manager_rtnl_process_address(rtnl, m, link->manager);
+
+ if (link->address_messages == 0) {
+ Address *a;
+
+ log_link_debug(link, "Addresses set");
+ link->addresses_configured = true;
+
+ /* When all static addresses are already ready, then static_address_ready_callback()
+ * will not be called automatically. So, call it here. */
+ a = set_first(link->static_addresses);
+ if (!a) {
+ log_link_warning(link, "No static address is stored.");
+ link_enter_failed(link);
+ return 1;
+ }
+ if (!a->callback) {
+ log_link_warning(link, "Address ready callback is not set.");
+ link_enter_failed(link);
+ return 1;
+ }
+ r = a->callback(a);
+ if (r < 0)
+ link_enter_failed(link);
+ }
+
+ return 1;
+}
+
+static int static_address_configure(const Address *address, Link *link, bool update) {
+ Address *ret;
+ int r;
+
+ assert(address);
+ assert(link);
+
+ r = address_configure(address, link, address_handler, update, &ret);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not configure static address: %m");
+
+ link->address_messages++;
+
+ r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to store static address: %m");
+
+ ret->callback = static_address_ready_callback;
+
+ return 0;
+}
+
+int link_set_addresses(Link *link) {
+ Address *ad;
+ Prefix *p;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ if (link->address_remove_messages != 0) {
+ log_link_debug(link, "Removing old addresses, new addresses will be configured later.");
+ link->request_static_addresses = true;
+ return 0;
+ }
+
+ 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);
+ if (r < 0)
+ return r;
+ }
+
+ HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
+ _cleanup_(address_freep) Address *address = NULL;
+
+ if (!p->assign)
+ continue;
+
+ r = address_new(&address);
+ if (r < 0)
+ return log_oom();
+
+ r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not get RA prefix: %m");
+
+ r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
+
+ address->family = AF_INET6;
+ r = static_address_configure(address, link, true);
+ if (r < 0)
+ return r;
+ }
+
+ if (link->address_messages == 0) {
+ link->addresses_configured = true;
+ link->addresses_ready = true;
+ r = link_set_routes(link);
+ if (r < 0)
+ return r;
+ } else {
+ log_link_debug(link, "Setting addresses");
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ }
+
+ return 0;
+}
+
+int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
+ _cleanup_(address_freep) Address *tmp = NULL;
+ _cleanup_free_ char *buf = NULL, *buf_peer = NULL;
+ Link *link = NULL;
+ uint16_t type;
+ unsigned char flags;
+ Address *address = NULL;
+ char valid_buf[FORMAT_TIMESPAN_MAX];
+ const char *valid_str = NULL;
+ int ifindex, r;
+ bool has_peer = false;
+
+ assert(rtnl);
+ assert(message);
+ assert(m);
+
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring");
+
+ return 0;
+ }
+
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) {
+ log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type);
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex);
+ return 0;
+ }
+
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ /* when enumerating we might be out of sync, but we will get the address again, so just
+ * ignore it */
+ if (!m->enumerating)
+ log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex);
+ return 0;
+ }
+
+ r = address_new(&tmp);
+ if (r < 0)
+ return log_oom();
+
+ r = sd_rtnl_message_addr_get_family(message, &tmp->family);
+ if (r < 0) {
+ log_link_warning(link, "rtnl: received address message without family, ignoring.");
+ return 0;
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+ log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", tmp->family);
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_prefixlen(message, &tmp->prefixlen);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message without prefixlen, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_scope(message, &tmp->scope);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message without scope, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_flags(message, &flags);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message without flags, ignoring: %m");
+ return 0;
+ }
+ tmp->flags = flags;
+
+ switch (tmp->family) {
+ case AF_INET:
+ r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &tmp->in_addr.in);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_in_addr(message, IFA_ADDRESS, &tmp->in_addr_peer.in);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: could not get peer address from address message, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ if (in4_addr_equal(&tmp->in_addr.in, &tmp->in_addr_peer.in))
+ tmp->in_addr_peer = IN_ADDR_NULL;
+ else
+ has_peer = true;
+ }
+
+ r = sd_netlink_message_read_in_addr(message, IFA_BROADCAST, &tmp->broadcast);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: could not get broadcast from address message, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_string_strdup(message, IFA_LABEL, &tmp->label);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: could not get label from address message, ignoring: %m");
+ return 0;
+ } else if (r >= 0 && streq_ptr(tmp->label, link->ifname))
+ tmp->label = mfree(tmp->label);
+
+ break;
+
+ case AF_INET6:
+ r = sd_netlink_message_read_in6_addr(message, IFA_LOCAL, &tmp->in_addr.in6);
+ if (r >= 0) {
+ /* Have peer address. */
+ r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &tmp->in_addr_peer.in6);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: could not get peer address from address message, ignoring: %m");
+ return 0;
+ }
+ has_peer = true;
+ } else if (r == -ENODATA) {
+ /* Does not have peer address. */
+ r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &tmp->in_addr.in6);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m");
+ return 0;
+ }
+ } else {
+ log_link_warning_errno(link, r, "rtnl: could not get local address from address message, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Received unsupported address family");
+ }
+
+ (void) in_addr_to_string(tmp->family, &tmp->in_addr, &buf);
+ (void) in_addr_to_string(tmp->family, &tmp->in_addr_peer, &buf_peer);
+
+ r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &tmp->cinfo);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0 && tmp->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
+ valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+ tmp->cinfo.ifa_valid * USEC_PER_SEC,
+ USEC_PER_SEC);
+
+ (void) address_get(link, tmp, &address);
+
+ switch (type) {
+ case RTM_NEWADDR:
+ if (address)
+ log_link_debug(link, "Remembering updated address: %s%s%s/%u (valid %s%s)",
+ strnull(buf), has_peer ? " peer " : "",
+ has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
+ valid_str ? "for " : "forever", strempty(valid_str));
+ else {
+ /* An address appeared that we did not request */
+ r = address_add_foreign(link, tmp, &address);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m",
+ strnull(buf), tmp->prefixlen);
+ return 0;
+ } else
+ log_link_debug(link, "Remembering foreign address: %s%s%s/%u (valid %s%s)",
+ strnull(buf), has_peer ? " peer " : "",
+ has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
+ valid_str ? "for " : "forever", strempty(valid_str));
+ }
+
+ /* address_update() logs internally, so we don't need to here. */
+ r = address_update(address, tmp);
+ if (r < 0)
+ link_enter_failed(link);
+
+ break;
+
+ case RTM_DELADDR:
+ if (address) {
+ log_link_debug(link, "Forgetting address: %s%s%s/%u (valid %s%s)",
+ strnull(buf), has_peer ? " peer " : "",
+ has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
+ valid_str ? "for " : "forever", strempty(valid_str));
+ (void) address_drop(address);
+ } else
+ log_link_debug(link, "Kernel removed an address we don't remember: %s%s%s/%u (valid %s%s), ignoring.",
+ strnull(buf), has_peer ? " peer " : "",
+ has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
+ valid_str ? "for " : "forever", strempty(valid_str));
+
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type");
+ }
+
+ return 1;
+}
+
+int link_serialize_addresses(Link *link, FILE *f) {
+ bool space = false;
+ Address *a;
+
+ assert(link);
+
+ fputs("ADDRESSES=", f);
+ SET_FOREACH(a, link->addresses) {
+ _cleanup_free_ char *address_str = NULL;
+
+ if (in_addr_to_string(a->family, &a->in_addr, &address_str) < 0)
+ continue;
+
+ fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
+ space = true;
+ }
+ fputc('\n', f);
+
+ return 0;
+}
+
+int link_deserialize_addresses(Link *link, const char *addresses) {
+ int r;
+
+ assert(link);
+
+ for (const char *p = addresses;; ) {
+ _cleanup_(address_freep) Address *tmp = NULL;
+ _cleanup_free_ char *address_str = NULL;
+
+ r = extract_first_word(&p, &address_str, NULL, 0);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to parse ADDRESSES=: %m");
+ if (r == 0)
+ return 0;
+
+ r = address_new(&tmp);
+ if (r < 0)
+ return log_oom();
+
+ r = in_addr_prefix_from_string_auto(address_str, &tmp->family, &tmp->in_addr, &tmp->prefixlen);
+ if (r < 0) {
+ log_link_debug_errno(link, r, "Failed to parse address, ignoring: %s", address_str);
+ continue;
+ }
+
+ r = address_add(link, tmp, NULL);
+ if (r < 0)
+ log_link_debug_errno(link, r, "Failed to add address %s, ignoring: %m", address_str);
+ }
+
+ return 0;
+}
+
+static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
+ _cleanup_free_ char *pretty = NULL;
+ Address *address;
+ Link *link;
+ int r;
+
+ assert(acd);
+ assert(userdata);
+
+ address = (Address *) userdata;
+ link = address->link;
+
+ (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
+ switch (event) {
+ case SD_IPV4ACD_EVENT_STOP:
+ log_link_debug(link, "Stopping ACD client...");
+ return;
+
+ case SD_IPV4ACD_EVENT_BIND:
+ log_link_debug(link, "Successfully claimed address %s", strna(pretty));
+ link_check_ready(link);
break;
case SD_IPV4ACD_EVENT_CONFLICT:
assert_not_reached("Invalid IPv4ACD event.");
}
- sd_ipv4acd_stop(acd);
+ (void) sd_ipv4acd_stop(acd);
return;
}
-int configure_ipv4_duplicate_address_detection(Link *link, Address *address) {
+static int ipv4_dad_configure(Address *address) {
int r;
- assert(link);
assert(address);
- assert(address->family == AF_INET);
- assert(!address->link && address->network);
+ assert(address->link);
- address->link = link;
+ if (address->family != AF_INET)
+ return 0;
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *pretty = NULL;
+
+ (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
+ log_link_debug(address->link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
+ }
- r = sd_ipv4acd_new(&address->acd);
+ if (!address->acd) {
+ r = sd_ipv4acd_new(&address->acd);
+ if (r < 0)
+ return r;
+
+ r = sd_ipv4acd_attach_event(address->acd, address->link->manager->event, 0);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_ipv4acd_set_ifindex(address->acd, address->link->ifindex);
if (r < 0)
return r;
- r = sd_ipv4acd_attach_event(address->acd, NULL, 0);
+ r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
if (r < 0)
return r;
- r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex);
+ r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in);
if (r < 0)
return r;
- r = sd_ipv4acd_set_mac(address->acd, &link->mac);
+ r = sd_ipv4acd_set_callback(address->acd, static_address_on_acd, address);
if (r < 0)
return r;
- r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in);
+ return sd_ipv4acd_start(address->acd, true);
+}
+
+static int ipv4_dad_update_mac_one(Address *address) {
+ bool running;
+ int r;
+
+ assert(address);
+
+ if (!address->acd)
+ return 0;
+
+ running = sd_ipv4acd_is_running(address->acd);
+
+ r = sd_ipv4acd_stop(address->acd);
if (r < 0)
return r;
- r = sd_ipv4acd_set_callback(address->acd, static_address_on_acd, address);
+ r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
if (r < 0)
return r;
+ if (running) {
+ r = sd_ipv4acd_start(address->acd, true);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
+int ipv4_dad_update_mac(Link *link) {
+ Address *address;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(address, link->addresses) {
+ k = ipv4_dad_update_mac_one(address);
+ if (k < 0 && r >= 0)
+ r = k;
+ }
+
+ return r;
+}
+
+int ipv4_dad_stop(Link *link) {
+ Address *address;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(address, link->addresses) {
+ k = sd_ipv4acd_stop(address->acd);
+ if (k < 0 && r >= 0)
+ r = k;
+ }
+
+ return r;
+}
+
+void ipv4_dad_unref(Link *link) {
+ Address *address;
+
+ assert(link);
+
+ SET_FOREACH(address, link->addresses)
+ address->acd = sd_ipv4acd_unref(address->acd);
+}
+
int config_parse_broadcast(
const char *unit,
const char *filename,
return 0;
}
-int config_parse_address(const char *unit,
+int config_parse_address(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
assert(rvalue);
assert(data);
- if (streq(section, "Network")) {
- /* we are not in an Address section, so treat
- * this as the special '0' section */
- r = address_new_static(network, NULL, 0, &n);
- } else
+ if (streq(section, "Network"))
+ /* we are not in an Address section, so use line number instead. */
+ r = address_new_static(network, filename, line, &n);
+ else
r = address_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
else
n->in_addr_peer = buffer;
- if (n->family == AF_INET && n->broadcast.s_addr == 0 && n->prefixlen <= 30)
- n->broadcast.s_addr = n->in_addr.in.s_addr | htobe32(0xfffffffflu >> n->prefixlen);
-
n = NULL;
return 0;
return 0;
}
-int config_parse_lifetime(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_lifetime(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
uint32_t k;
return 0;
}
-int config_parse_address_flags(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_address_flags(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
int r;
return 0;
}
- if (streq(lvalue, "HomeAddress"))
- n->home_address = r;
- else if (streq(lvalue, "ManageTemporaryAddress"))
- n->manage_temporary_address = r;
- else if (streq(lvalue, "PrefixRoute"))
- n->prefix_route = !r;
- else if (streq(lvalue, "AddPrefixRoute"))
- n->prefix_route = r;
- else if (streq(lvalue, "AutoJoin"))
- n->autojoin = r;
- else
- assert_not_reached("Invalid address flag type.");
+ if (streq(lvalue, "AddPrefixRoute"))
+ r = !r;
+
+ SET_FLAG(n->flags, ltype, r);
n = NULL;
return 0;
}
-int config_parse_address_scope(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_address_scope(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
int r;
const char *rvalue,
void *data,
void *userdata) {
+
Network *network = userdata;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
AddressFamily a;
return !(a->flags & IFA_F_TENTATIVE);
}
-int address_section_verify(Address *address) {
+static int address_section_verify(Address *address) {
if (section_is_invalid(address->section))
return -EINVAL;
address->section->filename, address->section->line);
}
- if (!address->scope_set && in_addr_is_localhost(address->family, &address->in_addr) > 0)
+ if (address->family == AF_INET && in_addr_is_null(address->family, &address->in_addr_peer) &&
+ address->broadcast.s_addr == 0 && address->prefixlen <= 30)
+ address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
+ else if (address->broadcast.s_addr != 0) {
+ log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "
+ "Ignoring Broadcast= setting in the [Address] section from line %u.",
+ address->section->filename, address->section->line);
+
+ address->broadcast.s_addr = 0;
+ }
+
+ if (address->family == AF_INET6 && address->label) {
+ log_warning("%s: address label is set for IPv6 address in the [Address] section from line %u. "
+ "Ignoring Label= setting.",
+ address->section->filename, address->section->line);
+
+ address->label = mfree(address->label);
+ }
+
+ if (in_addr_is_localhost(address->family, &address->in_addr) > 0 &&
+ (address->family == AF_INET || !address->scope_set)) {
+ /* For IPv4, scope must be always RT_SCOPE_HOST.
+ * For IPv6, use RT_SCOPE_HOST only when it is not explicitly specified. */
+
+ if (address->scope_set && address->scope != RT_SCOPE_HOST)
+ log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: non-host scope is set in the [Address] section from line %u. "
+ "Ignoring Scope= setting.",
+ address->section->filename, address->section->line);
+
address->scope = RT_SCOPE_HOST;
+ }
+
+ if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6))
+ address->flags |= IFA_F_NODAD;
return 0;
}
+
+void network_drop_invalid_addresses(Network *network) {
+ Address *address;
+
+ assert(network);
+
+ ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
+ if (address_section_verify(address) < 0)
+ address_free(address);
+}
#include <inttypes.h>
#include <stdbool.h>
+#include <stdio.h>
+
+#include "sd-ipv4acd.h"
#include "conf-parser.h"
#include "in-addr-util.h"
-
-typedef struct Address Address;
-
#include "networkd-link.h"
-#include "networkd-network.h"
#include "networkd-util.h"
-#include "sd-ipv4acd.h"
-
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
+typedef struct Manager Manager;
typedef struct Network Network;
-typedef struct Link Link;
-typedef struct NetworkConfigSection NetworkConfigSection;
typedef int (*address_ready_callback_t)(Address *address);
-struct Address {
+typedef struct Address {
Network *network;
NetworkConfigSection *section;
bool scope_set:1;
bool ip_masquerade_done:1;
- bool manage_temporary_address:1;
- bool home_address:1;
- bool prefix_route:1;
- bool autojoin:1;
AddressFamily duplicate_address_detection;
/* Called when address become ready */
address_ready_callback_t callback;
sd_ipv4acd *acd;
-
- LIST_FIELDS(Address, addresses);
-};
+} Address;
int address_new(Address **ret);
-void address_free(Address *address);
-int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
-int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
-int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
+Address *address_free(Address *address);
+int address_get(Link *link, const Address *in, Address **ret);
bool address_exists(Link *link, int family, const union in_addr_union *in_addr);
-int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo);
-int address_drop(Address *address);
-int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret);
-int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback);
-bool address_equal(Address *a1, Address *a2);
+int address_configure(const Address *address, Link *link, link_netlink_message_handler_t callback, bool update, 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);
-int address_section_verify(Address *a);
-int configure_ipv4_duplicate_address_detection(Link *link, Address *address);
-int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret);
+int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret);
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
+int link_set_addresses(Link *link);
+int link_drop_addresses(Link *link);
+int link_drop_foreign_addresses(Link *link);
+int link_serialize_addresses(Link *link, FILE *f);
+int link_deserialize_addresses(Link *link, const char *addresses);
+
+void ipv4_dad_unref(Link *link);
+int ipv4_dad_stop(Link *link);
+int ipv4_dad_update_mac(Link *link);
+
+int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
+
+void network_drop_invalid_addresses(Network *network);
+
void address_hash_func(const Address *a, struct siphash *state);
int address_compare_func(const Address *a1, const Address *a2);
extern const struct hash_ops address_hash_ops;
CONFIG_PARSER_PROTOTYPE(config_parse_address_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_address_scope);
CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection);
+
+#define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u"
+#define IPV4_ADDRESS_FMT_VAL(address) \
+ be32toh((address).s_addr) >> 24, \
+ (be32toh((address).s_addr) >> 16) & 0xFFu, \
+ (be32toh((address).s_addr) >> 8) & 0xFFu, \
+ be32toh((address).s_addr) & 0xFFu
return 1;
}
-int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) {
+int link_set_bridge_vlan(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- sd_netlink *rtnl;
- uint16_t flags;
int r;
assert(link);
assert(link->manager);
- assert(br_vid_bitmap);
- assert(br_untagged_bitmap);
assert(link->network);
- /* pvid might not be in br_vid_bitmap yet */
- if (pvid)
- set_bit(pvid, br_vid_bitmap);
+ if (!link->network->use_br_vlan)
+ return 0;
- rtnl = link->manager->rtnl;
+ if (!link->network->bridge && !streq_ptr(link->kind, "bridge"))
+ return 0;
+
+ /* pvid might not be in br_vid_bitmap yet */
+ if (link->network->pvid)
+ set_bit(link->network->pvid, link->network->br_vid_bitmap);
/* create new RTM message */
- r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex);
+ 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");
/* master needs flag self */
if (!link->network->bridge) {
- flags = BRIDGE_FLAGS_SELF;
- r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t));
+ uint16_t flags = BRIDGE_FLAGS_SELF;
+ r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(flags));
if (r < 0)
return log_link_error_errno(link, r, "Could not open IFLA_BRIDGE_FLAGS: %m");
}
/* add vlan info */
- r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap);
+ r = append_vlan_info_data(link, req, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
if (r < 0)
return log_link_error_errno(link, r, "Could not append VLANs: %m");
return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
/* send message to the kernel */
- r = netlink_call_async(rtnl, NULL, req, set_brvlan_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, set_brvlan_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
Copyright © 2016 BISDN GmbH. All rights reserved.
***/
-#include <stdint.h>
-
#include "conf-parser.h"
#define BRIDGE_VLAN_BITMAP_MAX 4096
typedef struct Link Link;
-int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
+int link_set_bridge_vlan(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid);
CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan);
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <netinet/in.h>
+#include <linux/if_arp.h>
+
#include "dhcp-internal.h"
#include "dhcp6-internal.h"
#include "escape.h"
#include "in-addr-util.h"
#include "networkd-dhcp-common.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
#include "networkd-network.h"
#include "parse-util.h"
+#include "socket-util.h"
#include "string-table.h"
#include "strv.h"
+bool link_dhcp_enabled(Link *link, int family) {
+ assert(link);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+
+ if (family == AF_INET6 && !socket_ipv6_is_supported())
+ return false;
+
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (link->iftype == ARPHRD_CAN)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6);
+}
+
+void network_adjust_dhcp(Network *network) {
+ assert(network);
+ assert(network->dhcp >= 0);
+
+ if (network->dhcp == ADDRESS_FAMILY_NO)
+ return;
+
+ /* Bonding slave does not support addressing. */
+ if (network->bond) {
+ log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
+ network->filename);
+ network->dhcp = ADDRESS_FAMILY_NO;
+ return;
+ }
+
+ if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) &&
+ FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
+ log_warning("%s: DHCPv6 client is enabled but IPv6 link local addressing is disabled. "
+ "Disabling DHCPv6 client.", network->filename);
+ SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
+ }
+}
+
+DUID* link_get_duid(Link *link) {
+ if (link->network->duid.type != _DUID_TYPE_INVALID)
+ return &link->network->duid;
+ else
+ return &link->manager->duid;
+}
+
+static int duid_set_uuid(DUID *duid, sd_id128_t uuid) {
+ assert(duid);
+
+ if (duid->raw_data_len > 0)
+ return 0;
+
+ if (duid->type != DUID_TYPE_UUID)
+ return -EINVAL;
+
+ memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t));
+ duid->raw_data_len = sizeof(sd_id128_t);
+
+ return 1;
+}
+
+static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ Manager *manager = userdata;
+ const sd_bus_error *e;
+ const void *a;
+ size_t sz;
+ DUID *duid;
+ Link *link;
+ int r;
+
+ assert(m);
+ assert(manager);
+
+ e = sd_bus_message_get_error(m);
+ if (e) {
+ log_error_errno(sd_bus_error_get_errno(e),
+ "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s",
+ e->message);
+ goto configure;
+ }
+
+ r = sd_bus_message_read_array(m, 'y', &a, &sz);
+ if (r < 0)
+ goto configure;
+
+ if (sz != sizeof(sd_id128_t)) {
+ log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID.");
+ goto configure;
+ }
+
+ memcpy(&manager->product_uuid, a, sz);
+ while ((duid = set_steal_first(manager->duids_requesting_uuid)))
+ (void) duid_set_uuid(duid, manager->product_uuid);
+
+ manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid);
+
+configure:
+ while ((link = set_steal_first(manager->links_requesting_uuid))) {
+ link_unref(link);
+
+ r = link_configure(link);
+ if (r < 0)
+ link_enter_failed(link);
+ }
+
+ manager->links_requesting_uuid = set_free(manager->links_requesting_uuid);
+
+ /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
+ * even if the method fails. */
+ manager->has_product_uuid = true;
+
+ return 1;
+}
+
+int manager_request_product_uuid(Manager *m, Link *link) {
+ int r;
+
+ assert(m);
+
+ if (m->has_product_uuid)
+ return 0;
+
+ log_debug("Requesting product UUID");
+
+ if (link) {
+ DUID *duid;
+
+ assert_se(duid = link_get_duid(link));
+
+ r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
+ if (r < 0)
+ return log_oom();
+ if (r > 0)
+ link_ref(link);
+
+ r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
+ if (r < 0)
+ return log_oom();
+ }
+
+ if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
+ log_debug("Not connected to system bus, requesting product UUID later.");
+ return 0;
+ }
+
+ r = sd_bus_call_method_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ "GetProductUUID",
+ get_product_uuid_handler,
+ m,
+ "b",
+ false);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to get product UUID: %m");
+
+ return 0;
+}
+
+static bool link_requires_uuid(Link *link) {
+ const DUID *duid;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->network);
+
+ duid = link_get_duid(link);
+ if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
+ return false;
+
+ if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
+ return true;
+
+ if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link))
+ return true;
+
+ return false;
+}
+
+int link_configure_duid(Link *link) {
+ Manager *m;
+ DUID *duid;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->network);
+
+ m = link->manager;
+ duid = link_get_duid(link);
+
+ if (!link_requires_uuid(link))
+ return 1;
+
+ if (m->has_product_uuid) {
+ (void) duid_set_uuid(duid, m->product_uuid);
+ return 1;
+ }
+
+ if (!m->links_requesting_uuid) {
+ r = manager_request_product_uuid(m, link);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ return r;
+
+ log_link_warning_errno(link, r,
+ "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
+ return 1;
+ }
+ } else {
+ r = set_put(m->links_requesting_uuid, link);
+ if (r < 0)
+ return log_oom();
+ if (r > 0)
+ link_ref(link);
+
+ r = set_put(m->duids_requesting_uuid, duid);
+ if (r < 0)
+ return log_oom();
+ }
+
+ return 0;
+}
+
int config_parse_dhcp(
const char* unit,
const char *filename,
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, UNESCAPE_ACCEPT_NUL, &q);
- if (sz < 0) {
+ if (sz < 0)
log_syntax(unit, LOG_WARNING, filename, line, sz,
"Failed to decode DHCP option data, ignoring assignment: %s", p);
- }
udata = q;
break;
#define DHCP_ROUTE_METRIC 1024
+typedef struct Link Link;
+typedef struct Manager Manager;
+typedef struct Network Network;
+
typedef enum DHCPUseDomains {
DHCP_USE_DOMAINS_NO,
DHCP_USE_DOMAINS_YES,
usec_t llt_time;
} DUID;
+bool link_dhcp_enabled(Link *link, int family);
+static inline bool link_dhcp4_enabled(Link *link) {
+ return link_dhcp_enabled(link, AF_INET);
+}
+static inline bool link_dhcp6_enabled(Link *link) {
+ return link_dhcp_enabled(link, AF_INET6);
+}
+
+void network_adjust_dhcp(Network *network);
+
+DUID* link_get_duid(Link *link);
+int link_configure_duid(Link *link);
+int manager_request_product_uuid(Manager *m, Link *link);
+
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <netinet/in.h>
+#include <linux/if_arp.h>
+#include <linux/if.h>
+
#include "sd-dhcp-server.h"
#include "fd-util.h"
#include "fileio.h"
+#include "networkd-address.h"
#include "networkd-dhcp-server.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "string-util.h"
#include "strv.h"
+static bool link_dhcp4_server_enabled(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ if (link->network->bond)
+ return false;
+
+ if (link->iftype == ARPHRD_CAN)
+ return false;
+
+ return link->network->dhcp_server;
+}
+
static Address* link_find_dhcp_server_address(Link *link) {
Address *address;
assert(link->network);
/* The first statically configured address if there is any */
- LIST_FOREACH(addresses, address, link->network->static_addresses)
+ ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section)
if (address->family == AF_INET &&
!in_addr_is_null(address->family, &address->in_addr))
return address;
/* If that didn't work, find a suitable address we got from the pool */
- LIST_FOREACH(addresses, address, link->pool_addresses)
+ SET_FOREACH(address, link->pool_addresses)
if (address->family == AF_INET)
return address;
Address *address;
int r;
+ assert(link);
+
+ if (!link_dhcp4_server_enabled(link))
+ return 0;
+
+ if (!(link->flags & IFF_UP))
+ return 0;
+
+ if (!link->dhcp_server) {
+ r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp_server_attach_event(link->dhcp_server, link->manager->event, 0);
+ if (r < 0)
+ return r;
+ }
+
address = link_find_dhcp_server_address(link);
if (!address)
return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY),
r = sd_dhcp_server_start(link->dhcp_server);
if (r < 0)
return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
+
+ log_link_debug(link, "Offering DHCPv4 leases");
}
return 0;
#include "hostname-util.h"
#include "parse-util.h"
#include "network-internal.h"
+#include "networkd-address.h"
#include "networkd-dhcp4.h"
#include "networkd-link.h"
#include "networkd-manager.h"
link_dirty(link);
SET_FOREACH(route, link->dhcp_routes_old) {
- k = route_remove(route, link, NULL);
+ k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = k;
}
route->family = AF_INET;
route->protocol = RTPROT_DHCP;
+ route->gw_family = AF_INET;
assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
return log_link_error_errno(link, r, "Could not allocate route: %m");
route->family = AF_INET;
+ route->gw_family = AF_INET;
route->gw.in = router[0];
route->prefsrc.in = address;
route->protocol = RTPROT_DHCP;
if (r < 0)
return log_link_error_errno(link, r, "Could not set router: %m");
- LIST_FOREACH(routes, rt, link->network->static_routes) {
- if (!rt->gateway_from_dhcp)
+ HASHMAP_FOREACH(rt, link->network->routes_by_section) {
+ if (!rt->gateway_from_dhcp_or_ra)
continue;
- if (rt->family != AF_INET)
+ if (rt->gw_family != AF_INET)
continue;
rt->gw.in = router[0];
+ if (!rt->protocol_set)
+ rt->protocol = RTPROT_DHCP;
+ if (!rt->priority_set)
+ rt->priority = link->network->dhcp_route_metric;
+ if (!rt->table_set)
+ rt->table = table;
+ if (rt->mtu == 0)
+ rt->mtu = link->network->dhcp_route_mtu;
r = dhcp_route_configure(rt, link);
if (r < 0)
assert(link);
SET_FOREACH(route, link->dhcp_routes) {
- k = route_remove(route, link, dhcp4_remove_route_handler);
+ k = route_remove(route, NULL, link, dhcp4_remove_route_handler);
if (k < 0)
r = k;
else
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link_dirty(link);
+ (void) sd_ipv4acd_stop(link->dhcp_acd);
+
return r;
}
return;
}
-static int configure_dhcpv4_duplicate_address_detection(Link *link) {
+static int dhcp4_configure_dad(Link *link) {
int r;
assert(link);
+ assert(link->manager);
+ assert(link->network);
+
+ if (!link->network->dhcp_send_decline)
+ return 0;
- r = sd_ipv4acd_new(&link->network->dhcp_acd);
+ if (!link->dhcp_acd) {
+ r = sd_ipv4acd_new(&link->dhcp_acd);
+ if (r < 0)
+ return r;
+
+ r = sd_ipv4acd_attach_event(link->dhcp_acd, link->manager->event, 0);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_ipv4acd_set_ifindex(link->dhcp_acd, link->ifindex);
if (r < 0)
return r;
- r = sd_ipv4acd_attach_event(link->network->dhcp_acd, NULL, 0);
+ r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->mac);
if (r < 0)
return r;
- r = sd_ipv4acd_set_ifindex(link->network->dhcp_acd, link->ifindex);
+ return 0;
+}
+
+static int dhcp4_dad_update_mac(Link *link) {
+ bool running;
+ int r;
+
+ assert(link);
+
+ if (!link->dhcp_acd)
+ return 0;
+
+ running = sd_ipv4acd_is_running(link->dhcp_acd);
+
+ r = sd_ipv4acd_stop(link->dhcp_acd);
if (r < 0)
return r;
- r = sd_ipv4acd_set_mac(link->network->dhcp_acd, &link->mac);
+ r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->mac);
if (r < 0)
return r;
+ if (running) {
+ r = sd_ipv4acd_start(link->dhcp_acd, true);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
if (!link->dhcp_lease)
return 0;
- (void) sd_ipv4acd_stop(link->network->dhcp_acd);
+ (void) sd_ipv4acd_stop(link->dhcp_acd);
link->dhcp4_address_bind = false;
if (r < 0)
return r;
- r = sd_ipv4acd_get_address(link->network->dhcp_acd, &old);
+ r = sd_ipv4acd_get_address(link->dhcp_acd, &old);
if (r < 0)
return r;
- r = sd_ipv4acd_set_address(link->network->dhcp_acd, &addr.in);
+ r = sd_ipv4acd_set_address(link->dhcp_acd, &addr.in);
if (r < 0)
return r;
- r = sd_ipv4acd_set_callback(link->network->dhcp_acd, dhcp_address_on_acd, link);
+ r = sd_ipv4acd_set_callback(link->dhcp_acd, dhcp_address_on_acd, link);
if (r < 0)
return r;
log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty));
}
- r = sd_ipv4acd_start(link->network->dhcp_acd, !in4_addr_equal(&addr.in, &old));
+ r = sd_ipv4acd_start(link->dhcp_acd, !in4_addr_equal(&addr.in, &old));
if (r < 0)
return r;
return r;
/* Reconfigure static routes as kernel may remove some routes when lease expires. */
- r = link_request_set_routes(link);
+ r = link_set_routes(link);
if (r < 0)
return r;
link_set_state(link, LINK_STATE_CONFIGURING);
link->dhcp4_configured = false;
- /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they
- * are called, the related flags must be cleared. Otherwise, the link becomes configured state
- * before routes are configured. */
+ /* 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 (r > 0 && !in4_addr_is_null(&router[0]))
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
- LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
- ADDRESS_FMT_VAL(address),
+ LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u via "IPV4_ADDRESS_FMT_STR,
+ IPV4_ADDRESS_FMT_VAL(address),
prefixlen,
- ADDRESS_FMT_VAL(router[0])),
- "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
+ IPV4_ADDRESS_FMT_VAL(router[0])),
+ "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen,
- "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0]));
+ "GATEWAY="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(router[0]));
else
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
- LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
- ADDRESS_FMT_VAL(address),
+ LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u",
+ IPV4_ADDRESS_FMT_VAL(address),
prefixlen),
- "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
+ "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen);
}
addr->cinfo.ifa_valid = lifetime;
addr->prefixlen = prefixlen;
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
- addr->prefix_route = link_prefixroute(link);
+ SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
/* allow reusing an existing address and simply update its lifetime
* in case it already exists */
if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
- LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in deny-listed IP addresses, ignoring offer",
- ADDRESS_FMT_VAL(addr)));
+ LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in deny-list, ignoring offer",
+ IPV4_ADDRESS_FMT_VAL(addr)));
return true;
}
if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
- LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in allow-listed IP addresses, accepting offer",
- ADDRESS_FMT_VAL(addr)));
+ LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in allow-list, accepting offer",
+ IPV4_ADDRESS_FMT_VAL(addr)));
return true;
}
* the primary one expires it relies on the kernel to promote the
* secondary IP. See also https://github.com/systemd/systemd/issues/7163
*/
-int dhcp4_set_promote_secondaries(Link *link) {
+static int dhcp4_set_promote_secondaries(Link *link) {
int r;
assert(link);
- assert(link->network);
- assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
/* check if the kernel has promote_secondaries enabled for our
* interface. If it is not globally enabled or enabled for the
return 0;
}
-int dhcp4_set_client_identifier(Link *link) {
+static int dhcp4_set_client_identifier(Link *link) {
int r;
assert(link);
return 0;
}
+static int dhcp4_init(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (link->dhcp_client)
+ return 0;
+
+ r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int dhcp4_configure(Link *link) {
sd_dhcp_option *send_option;
void *request_options;
assert(link);
assert(link->network);
- assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
- if (!link->dhcp_client) {
- r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m");
+ if (!link_dhcp4_enabled(link))
+ return 0;
- r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m");
- }
+ r = dhcp4_set_promote_secondaries(link);
+ if (r < 0)
+ return r;
+
+ r = dhcp4_init(link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to initialize DHCP4 client: %m");
r = sd_dhcp_client_set_mac(link->dhcp_client,
(const uint8_t *) &link->mac,
uint32_t option = PTR_TO_UINT32(request_options);
r = sd_dhcp_client_set_request_option(link->dhcp_client, option);
- if (r == -EEXIST) {
- log_link_debug(link, "DHCP4 CLIENT: Failed to set request flag for '%u' already exists, ignoring.", option);
- continue;
- }
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
}
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
}
- if (link->network->ip_service_type > 0) {
- r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type);
+ if (link->network->dhcp_ip_service_type > 0) {
+ r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->dhcp_ip_service_type);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m");
}
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed set to lease lifetime: %m");
}
- if (link->network->dhcp_send_decline) {
- r = configure_dhcpv4_duplicate_address_detection(link);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to configure service type: %m");
- }
+ r = dhcp4_configure_dad(link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to configure service type: %m");
return dhcp4_set_client_identifier(link);
}
+int dhcp4_update_mac(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (!link->dhcp_client)
+ return 0;
+
+ r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
+ if (r < 0)
+ return r;
+
+ r = dhcp4_set_client_identifier(link);
+ if (r < 0)
+ return r;
+
+ r = dhcp4_dad_update_mac(link);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int link_deserialize_dhcp4(Link *link, const char *dhcp4_address) {
+ union in_addr_union address;
+ int r;
+
+ assert(link);
+
+ if (isempty(dhcp4_address))
+ return 0;
+
+ r = in_addr_from_string(AF_INET, dhcp4_address, &address);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to parse DHCPv4 address: %s", dhcp4_address);
+
+ r = dhcp4_init(link);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to initialize DHCPv4 client: %m");
+
+ r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address);
+
+ return 0;
+}
+
int config_parse_dhcp_max_attempts(
const char *unit,
const char *filename,
} DHCPClientIdentifier;
int dhcp4_configure(Link *link);
-int dhcp4_set_client_identifier(Link *link);
-int dhcp4_set_promote_secondaries(Link *link);
+int dhcp4_update_mac(Link *link);
+
+int link_deserialize_dhcp4(Link *link, const char *dhcp4_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address);
#include "hostname-util.h"
#include "missing_network.h"
#include "network-internal.h"
+#include "networkd-address.h"
#include "networkd-dhcp6.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "radv-internal.h"
#include "web-util.h"
+bool link_dhcp6_pd_is_enabled(Link *link) {
+ assert(link);
+
+ if (!link->network)
+ return false;
+
+ return link->network->dhcp6_pd;
+}
+
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
uint32_t lifetime_preferred, lifetime_valid;
union in_addr_union pd_prefix;
link_dirty(link);
SET_FOREACH(route, link->dhcp6_pd_routes_old) {
- k = route_remove(route, link, NULL);
+ k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = k;
assert(link);
assert(link->manager);
+ if (!link_dhcp6_pd_is_enabled(link))
+ return 0;
+
link->dhcp6_pd_address_configured = false;
link->dhcp6_pd_route_configured = false;
link_dirty(link);
SET_FOREACH(route, link->dhcp6_pd_routes) {
- k = route_remove(route, link, NULL);
+ k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = k;
return 1;
}
- r = link_request_set_routes(link);
+ r = link_set_routes(link);
if (r < 0) {
link_enter_failed(link);
return 1;
int r;
assert(link);
+ assert(link->network);
assert(prefix);
- r = radv_add_prefix(link, &prefix->in6, prefix_len, lifetime_preferred, lifetime_valid);
- if (r < 0)
- return r;
+ if (link->network->dhcp6_pd_announce) {
+ r = radv_add_prefix(link, &prefix->in6, prefix_len, lifetime_preferred, lifetime_valid);
+ if (r < 0)
+ return r;
+ }
r = dhcp6_set_pd_route(link, prefix, pd_prefix);
if (r < 0)
return 0;
}
-bool link_dhcp6_pd_is_enabled(Link *link) {
- if (!link->network)
- return false;
-
- return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6;
-}
-
static bool link_has_preferred_subnet_id(Link *link) {
if (!link->network)
return false;
link->dhcp6_pd_address_configured = true;
} else {
log_link_debug(link, "Setting DHCPv6 PD addresses");
- /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
- * Before they are called, the related flags must be cleared. Otherwise, the link
- * becomes configured state before routes are configured. */
+ /* 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_link)
continue;
- if (!link_dhcp6_pd_is_enabled(link))
- continue;
-
r = dhcp6_pd_remove(link);
if (r < 0)
link_enter_failed(link);
link_dirty(link);
SET_FOREACH(route, link->dhcp6_routes_old) {
- k = route_remove(route, link, NULL);
+ k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = k;
}
link_dirty(link);
SET_FOREACH(route, link->dhcp6_routes) {
- k = route_remove(route, link, NULL);
+ k = route_remove(route, NULL, link, NULL);
if (k < 0)
r = k;
}
return 1;
}
- r = link_request_set_routes(link);
+ r = link_set_routes(link);
if (r < 0) {
link_enter_failed(link);
return 1;
link->dhcp6_address_configured = true;
else {
log_link_debug(link, "Setting DHCPv6 addresses");
- /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
- * Before they are called, the related flags must be cleared. Otherwise, the link
- * becomes configured state before routes are configured. */
+ /* 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;
}
return false;
}
+static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) {
+ const DUID *duid;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(client);
+
+ r = sd_dhcp6_client_set_mac(client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
+ if (r < 0)
+ return r;
+
+ if (link->network->iaid_set) {
+ r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
+ if (r < 0)
+ return r;
+ }
+
+ duid = link_get_duid(link);
+ if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
+ r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time);
+ else
+ r = sd_dhcp6_client_set_duid(client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int dhcp6_configure(Link *link) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
sd_dhcp6_option *vendor_option;
sd_dhcp6_option *send_option;
void *request_options;
- const DUID *duid;
int r;
assert(link);
assert(link->network);
+ if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link))
+ return 0;
+
if (link->dhcp6_client)
return 0;
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to create DHCP6 client: %m");
- r = sd_dhcp6_client_attach_event(client, NULL, 0);
+ r = sd_dhcp6_client_attach_event(client, link->manager->event, 0);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m");
- r = sd_dhcp6_client_set_mac(client,
- (const uint8_t *) &link->mac,
- sizeof (link->mac), ARPHRD_ETHER);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MAC address: %m");
-
- if (link->network->iaid_set) {
- r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m");
- }
-
- duid = link_get_duid(link);
- if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
- r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time);
- else
- r = sd_dhcp6_client_set_duid(client,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
+ r = dhcp6_set_identifier(link, client);
if (r < 0)
- return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m");
+ return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set identifier: %m");
ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options) {
r = sd_dhcp6_client_add_option(client, send_option);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set ifindex: %m");
- if (link->network->rapid_commit) {
+ if (link->network->dhcp6_rapid_commit) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_RAPID_COMMIT);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for rapid commit: %m");
return 0;
}
+int dhcp6_update_mac(Link *link) {
+ bool restart;
+ int r;
+
+ assert(link);
+
+ if (!link->dhcp6_client)
+ return 0;
+
+ restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0;
+
+ if (restart) {
+ r = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (r < 0)
+ return r;
+ }
+
+ r = dhcp6_set_identifier(link, link->dhcp6_client);
+ if (r < 0)
+ return r;
+
+ if (restart) {
+ r = sd_dhcp6_client_start(link->dhcp6_client);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m");
+ }
+
+ return 0;
+}
+
+int link_serialize_dhcp6_client(Link *link, FILE *f) {
+ _cleanup_free_ char *duid = NULL;
+ uint32_t iaid;
+ int r;
+
+ assert(link);
+
+ if (!link->dhcp6_client)
+ return 0;
+
+ r = sd_dhcp6_client_get_iaid(link->dhcp6_client, &iaid);
+ if (r >= 0)
+ fprintf(f, "DHCP6_CLIENT_IAID=0x%x\n", iaid);
+
+ r = sd_dhcp6_client_duid_as_string(link->dhcp6_client, &duid);
+ if (r >= 0)
+ fprintf(f, "DHCP6_CLIENT_DUID=%s\n", duid);
+
+ return 0;
+}
+
int config_parse_dhcp6_pd_hint(
const char* unit,
const char *filename,
bool link_dhcp6_pd_is_enabled(Link *link);
int dhcp6_pd_remove(Link *link);
int dhcp6_configure(Link *link);
+int dhcp6_update_mac(Link *link);
int dhcp6_request_address(Link *link, int ir);
int dhcp6_request_prefix_delegation(Link *link);
+int link_serialize_dhcp6_client(Link *link, FILE *f);
+
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode);
#include "alloc-util.h"
#include "bridge.h"
-#include "conf-parser.h"
#include "netlink-util.h"
#include "networkd-fdb.h"
+#include "networkd-link.h"
#include "networkd-manager.h"
+#include "networkd-network.h"
#include "parse-util.h"
-#include "string-util.h"
#include "string-table.h"
-#include "util.h"
#include "vlan-util.h"
#include "vxlan.h"
#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
-static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = {
- [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use",
- [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self",
- [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master",
- [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router",
-};
+/* remove and FDB entry. */
+FdbEntry *fdb_entry_free(FdbEntry *fdb_entry) {
+ if (!fdb_entry)
+ return NULL;
+
+ if (fdb_entry->network) {
+ assert(fdb_entry->section);
+ hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section);
+ }
+
+ network_config_section_free(fdb_entry->section);
+ return mfree(fdb_entry);
+}
-DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags);
+DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
/* create a new FDB entry or get an existing one. */
static int fdb_entry_new_static(
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- /* search entry in hashmap first. */
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- fdb_entry = hashmap_get(network->fdb_entries_by_section, n);
- if (fdb_entry) {
- *ret = TAKE_PTR(fdb_entry);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ /* search entry in hashmap first. */
+ fdb_entry = hashmap_get(network->fdb_entries_by_section, n);
+ if (fdb_entry) {
+ *ret = TAKE_PTR(fdb_entry);
+ return 0;
}
- if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
+ if (hashmap_size(network->fdb_entries_by_section) >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
return -E2BIG;
/* allocate space for and FDB entry. */
/* init FDB structure. */
*fdb_entry = (FdbEntry) {
.network = network,
+ .section = TAKE_PTR(n),
.vni = VXLAN_VID_MAX + 1,
.fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
};
- LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
- network->n_static_fdb_entries++;
-
- if (filename) {
- fdb_entry->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry);
+ if (r < 0)
+ return r;
/* return allocated FDB structure. */
*ret = TAKE_PTR(fdb_entry);
}
/* send a request to the kernel to add a FDB entry in its static MAC table. */
-int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
+static int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
return 1;
}
-/* remove and FDB entry. */
-void fdb_entry_free(FdbEntry *fdb_entry) {
- if (!fdb_entry)
- return;
+int link_set_bridge_fdb(Link *link) {
+ FdbEntry *fdb_entry;
+ int r;
- if (fdb_entry->network) {
- LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry);
- assert(fdb_entry->network->n_static_fdb_entries > 0);
- fdb_entry->network->n_static_fdb_entries--;
+ assert(link);
+ assert(link->network);
- if (fdb_entry->section)
- hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section);
+ HASHMAP_FOREACH(fdb_entry, link->network->fdb_entries_by_section) {
+ r = fdb_entry_configure(link, fdb_entry);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
}
- network_config_section_free(fdb_entry->section);
- free(fdb_entry);
+ return 0;
+}
+
+void network_drop_invalid_fdb_entries(Network *network) {
+ FdbEntry *fdb_entry;
+
+ assert(network);
+
+ HASHMAP_FOREACH(fdb_entry, network->fdb_entries_by_section)
+ if (section_is_invalid(fdb_entry->section))
+ fdb_entry_free(fdb_entry);
}
/* parse the HW address from config files. */
return 0;
}
+static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = {
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fdb_ntf_flags, NeighborCacheEntryFlags);
+
int config_parse_fdb_ntf_flags(
const char *unit,
const char *filename,
Copyright © 2014 Intel Corporation. All rights reserved.
***/
+#include <inttypes.h>
#include <linux/neighbour.h>
#include "conf-parser.h"
-#include "list.h"
-#include "macro.h"
+#include "ether-addr-util.h"
+#include "in-addr-util.h"
#include "networkd-util.h"
typedef struct Network Network;
-typedef struct FdbEntry FdbEntry;
typedef struct Link Link;
-typedef struct NetworkConfigSection NetworkConfigSection;
typedef enum NeighborCacheEntryFlags {
NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE,
_NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1,
} NeighborCacheEntryFlags;
-struct FdbEntry {
+typedef struct FdbEntry {
Network *network;
NetworkConfigSection *section;
struct ether_addr mac_addr;
union in_addr_union destination_addr;
NeighborCacheEntryFlags fdb_ntf_flags;
+} FdbEntry;
- LIST_FIELDS(FdbEntry, static_fdb_entries);
-};
+FdbEntry *fdb_entry_free(FdbEntry *fdb_entry);
-void fdb_entry_free(FdbEntry *fdb_entry);
-int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
+void network_drop_invalid_fdb_entries(Network *network);
-DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
-
-const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_;
-NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_;
+int link_set_bridge_fdb(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
if (r < 0)
return 0;
- log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));
+ log_link_debug(link, "IPv4 link-local release "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(addr));
r = address_new(&address);
if (r < 0)
else if (r < 0)
return r;
- log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u",
- ADDRESS_FMT_VAL(address));
+ log_link_debug(link, "IPv4 link-local claim "IPV4_ADDRESS_FMT_STR,
+ IPV4_ADDRESS_FMT_VAL(address));
r = address_new(&ll_addr);
if (r < 0)
}
}
+static int ipv4ll_init(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (link->ipv4ll)
+ return 0;
+
+ r = sd_ipv4ll_new(&link->ipv4ll);
+ if (r < 0)
+ return r;
+
+ r = sd_ipv4ll_attach_event(link->ipv4ll, link->manager->event, 0);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int ipv4ll_configure(Link *link) {
uint64_t seed;
int r;
assert(link);
- assert(link->network);
- assert(link->network->link_local & (ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4));
- if (!link->ipv4ll) {
- r = sd_ipv4ll_new(&link->ipv4ll);
- if (r < 0)
- return r;
+ if (!link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4))
+ return 0;
- r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
- if (r < 0)
- return r;
- }
+ r = ipv4ll_init(link);
+ if (r < 0)
+ return r;
if (link->sd_device &&
net_get_unique_predictable_data(link->sd_device, true, &seed) >= 0) {
return 0;
}
+int ipv4ll_update_mac(Link *link) {
+ bool restart;
+ int r;
+
+ assert(link);
+
+ if (!link->ipv4ll)
+ return 0;
+
+ restart = sd_ipv4ll_is_running(link->ipv4ll) > 0;
+
+ r = sd_ipv4ll_stop(link->ipv4ll);
+ if (r < 0)
+ return r;
+
+ r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
+ if (r < 0)
+ return r;
+
+ if (restart) {
+ r = sd_ipv4ll_start(link->ipv4ll);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int link_serialize_ipv4ll(Link *link, FILE *f) {
+ struct in_addr address;
+ int r;
+
+ assert(link);
+
+ if (!link->ipv4ll)
+ return 0;
+
+ r = sd_ipv4ll_get_address(link->ipv4ll, &address);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return r;
+
+ fputs("IPV4LL_ADDRESS=", f);
+ serialize_in_addrs(f, &address, 1, false, NULL);
+ fputc('\n', f);
+
+ return 0;
+}
+
+int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address) {
+ union in_addr_union address;
+ int r;
+
+ assert(link);
+
+ if (isempty(ipv4ll_address))
+ return 0;
+
+ r = in_addr_from_string(AF_INET, ipv4ll_address, &address);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to parse IPv4LL address: %s", ipv4ll_address);
+
+ r = ipv4ll_init(link);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to initialize IPv4LL client: %m");
+
+ r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address);
+
+ return 0;
+}
+
int config_parse_ipv4ll(
const char* unit,
const char *filename,
typedef struct Link Link;
int ipv4ll_configure(Link *link);
+int ipv4ll_update_mac(Link *link);
+int link_serialize_ipv4ll(Link *link, FILE *f);
+int link_deserialize_ipv4ll(Link *link, const char *ipv4ll_address);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
#include <netinet/in.h>
#include <linux/if.h>
-#include <unistd.h>
-#include "fileio.h"
#include "netlink-util.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-link.h"
#include "string-util.h"
#include "sysctl-util.h"
+static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST)
+ log_link_message_warning_errno(link, m, r, "Could not add IPv6 proxy ndp address entry, ignoring");
+
+ return 1;
+}
+
+/* send a request to the kernel to add a IPv6 Proxy entry to the neighbour table */
+static int ipv6_proxy_ndp_address_configure(Link *link, const struct in6_addr *address) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(address);
+
+ /* create new netlink message */
+ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6);
+ 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);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set neighbor flags: %m");
+
+ r = sd_netlink_message_append_in6_addr(req, NDA_DST, address);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler,
+ 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 bool ipv6_proxy_ndp_is_needed(Link *link) {
assert(link);
if (link->network->ipv6_proxy_ndp >= 0)
return link->network->ipv6_proxy_ndp;
- if (link->network->n_ipv6_proxy_ndp_addresses == 0)
- return false;
-
- return true;
+ return !set_isempty(link->network->ipv6_proxy_ndp_addresses);
}
static int ipv6_proxy_ndp_set(Link *link) {
r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m");
+ return log_link_warning_errno(link, r, "Cannot configure proxy NDP for the interface: %m");
- return 0;
+ return v;
}
-static int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress **ret) {
- _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL;
-
- assert(network);
- assert(ret);
-
- /* allocate space for IPv6ProxyNDPAddress entry */
- ipv6_proxy_ndp_address = new(IPv6ProxyNDPAddress, 1);
- if (!ipv6_proxy_ndp_address)
- return -ENOMEM;
-
- *ipv6_proxy_ndp_address = (IPv6ProxyNDPAddress) {
- .network = network,
- };
-
- LIST_PREPEND(ipv6_proxy_ndp_addresses, network->ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address);
- network->n_ipv6_proxy_ndp_addresses++;
-
- *ret = TAKE_PTR(ipv6_proxy_ndp_address);
-
- return 0;
-}
+/* configure all ipv6 proxy ndp addresses */
+int link_set_ipv6_proxy_ndp_addresses(Link *link) {
+ struct in6_addr *address;
+ int r;
-void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) {
- if (!ipv6_proxy_ndp_address)
- return;
+ assert(link);
+ assert(link->network);
- if (ipv6_proxy_ndp_address->network) {
- LIST_REMOVE(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address->network->ipv6_proxy_ndp_addresses,
- ipv6_proxy_ndp_address);
+ /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */
+ r = ipv6_proxy_ndp_set(link);
+ if (r <= 0)
+ return r;
- assert(ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses > 0);
- ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses--;
+ SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) {
+ r = ipv6_proxy_ndp_address_configure(link, address);
+ if (r < 0)
+ return r;
}
- free(ipv6_proxy_ndp_address);
+ return 0;
}
int config_parse_ipv6_proxy_ndp_address(
void *data,
void *userdata) {
+ _cleanup_free_ struct in6_addr *address = NULL;
Network *network = userdata;
- _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL;
- int r;
union in_addr_union buffer;
+ int r;
assert(filename);
- assert(section);
- assert(lvalue);
assert(rvalue);
- assert(data);
+ assert(network);
- r = ipv6_proxy_ndp_address_new_static(network, &ipv6_proxy_ndp_address);
- if (r < 0)
- return log_oom();
+ if (isempty(rvalue)) {
+ network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
+ return 0;
+ }
r = in_addr_from_string(AF_INET6, rvalue, &buffer);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse IPv6 proxy NDP address, ignoring: %s",
- rvalue);
+ "Failed to parse IPv6 proxy NDP address, ignoring: %s", rvalue);
return 0;
}
return 0;
}
- ipv6_proxy_ndp_address->in_addr = buffer.in6;
- ipv6_proxy_ndp_address = NULL;
-
- return 0;
-}
-
-static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(link);
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST)
- log_link_message_warning_errno(link, m, r, "Could not add IPv6 proxy ndp address entry, ignoring");
-
- return 1;
-}
-
-/* send a request to the kernel to add a IPv6 Proxy entry to the neighbour table */
-int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- sd_netlink *rtnl;
- int r;
-
- assert(link);
- assert(link->network);
- assert(link->manager);
- assert(ipv6_proxy_ndp_address);
-
- rtnl = link->manager->rtnl;
-
- /* create new netlink message */
- r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6);
- 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);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set neighbor flags: %m");
-
- r = sd_netlink_message_append_in6_addr(req, NDA_DST, &ipv6_proxy_ndp_address->in_addr);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
+ address = newdup(struct in6_addr, &buffer.in6, 1);
+ if (!address)
+ return log_oom();
- r = netlink_call_async(rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler,
- link_netlink_destroy_callback, link);
+ r = set_ensure_put(&network->ipv6_proxy_ndp_addresses, &in6_addr_hash_ops, address);
if (r < 0)
- return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
- link_ref(link);
-
- return 0;
-}
-
-/* configure all ipv6 proxy ndp addresses */
-int ipv6_proxy_ndp_addresses_configure(Link *link) {
- IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
- int r;
-
- assert(link);
-
- /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */
- r = ipv6_proxy_ndp_set(link);
- if (r != 0)
- return r;
+ return log_oom();
+ if (r > 0)
+ TAKE_PTR(address);
- LIST_FOREACH(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address, link->network->ipv6_proxy_ndp_addresses) {
- r = ipv6_proxy_ndp_address_configure(link, ipv6_proxy_ndp_address);
- if (r != 0)
- return r;
- }
return 0;
}
#pragma once
#include "conf-parser.h"
-#include "list.h"
-#include "macro.h"
-typedef struct Network Network;
-typedef struct IPv6ProxyNDPAddress IPv6ProxyNDPAddress;
typedef struct Link Link;
-struct IPv6ProxyNDPAddress {
- Network *network;
- struct in6_addr in_addr;
-
- LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
-};
-
-void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
-int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
-int ipv6_proxy_ndp_addresses_configure(Link *link);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6ProxyNDPAddress*, ipv6_proxy_ndp_address_free);
+int link_set_ipv6_proxy_ndp_addresses(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address);
#include "missing_network.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "networkd-address-label.h"
+#include "networkd-address.h"
#include "networkd-can.h"
#include "networkd-dhcp-server.h"
#include "networkd-dhcp4.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"
#include "networkd-manager.h"
+#include "networkd-mdb.h"
#include "networkd-ndisc.h"
#include "networkd-neighbor.h"
+#include "networkd-nexthop.h"
#include "networkd-sriov.h"
+#include "networkd-sysctl.h"
#include "networkd-radv.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-wifi.h"
#include "util.h"
#include "vrf.h"
-uint32_t link_get_vrf_table(Link *link) {
- return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN;
-}
-
-uint32_t link_get_dhcp_route_table(Link *link) {
- /* When the interface is part of an VRF use the VRFs routing table, unless
- * another table is explicitly specified. */
- if (link->network->dhcp_route_table_set)
- return link->network->dhcp_route_table;
- return link_get_vrf_table(link);
-}
-
-uint32_t link_get_ipv6_accept_ra_route_table(Link *link) {
- if (link->network->ipv6_accept_ra_route_table_set)
- return link->network->ipv6_accept_ra_route_table;
- return link_get_vrf_table(link);
-}
-
-DUID* link_get_duid(Link *link) {
- if (link->network->duid.type != _DUID_TYPE_INVALID)
- return &link->network->duid;
- else
- return &link->manager->duid;
-}
-
-static bool link_dhcp6_enabled(Link *link) {
- assert(link);
-
- if (!socket_ipv6_is_supported())
- return false;
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->bond)
- return false;
-
- if (link->iftype == ARPHRD_CAN)
- return false;
-
- return link->network->dhcp & ADDRESS_FAMILY_IPV6;
-}
-
-static bool link_dhcp4_enabled(Link *link) {
- assert(link);
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->bond)
- return false;
-
- if (link->iftype == ARPHRD_CAN)
- return false;
-
- return link->network->dhcp & ADDRESS_FAMILY_IPV4;
-}
-
-static bool link_dhcp4_server_enabled(Link *link) {
- assert(link);
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->bond)
- return false;
-
- if (link->iftype == ARPHRD_CAN)
- return false;
-
- return link->network->dhcp_server;
-}
-
bool link_ipv4ll_enabled(Link *link, AddressFamily mask) {
assert(link);
assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0);
return link->network->link_local & mask;
}
-static bool link_ipv6ll_enabled(Link *link) {
+bool link_ipv6ll_enabled(Link *link) {
assert(link);
if (!socket_ipv6_is_supported())
return link->network->link_local & ADDRESS_FAMILY_IPV6;
}
-static bool link_ipv6_enabled(Link *link) {
+bool link_ipv6_enabled(Link *link) {
assert(link);
if (!socket_ipv6_is_supported())
return false;
}
-static bool link_radv_enabled(Link *link) {
- assert(link);
-
- if (!link_ipv6ll_enabled(link))
- return false;
-
- return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE;
-}
-
-static bool link_ipv4_forward_enabled(Link *link) {
- assert(link);
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
- return false;
-
- return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
-}
-
-static bool link_ipv6_forward_enabled(Link *link) {
- assert(link);
-
- if (!socket_ipv6_is_supported())
- return false;
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
- return false;
-
- return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
-}
-
-static bool link_proxy_arp_enabled(Link *link) {
- assert(link);
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (link->network->proxy_arp < 0)
- return false;
-
- return true;
-}
-
-static bool link_ipv6_accept_ra_enabled(Link *link) {
- assert(link);
-
- if (!socket_ipv6_is_supported())
- return false;
-
- if (link->flags & IFF_LOOPBACK)
- return false;
-
- if (!link->network)
- return false;
-
- if (!link_ipv6ll_enabled(link))
- return false;
-
- /* If unset use system default (enabled if local forwarding is disabled.
- * disabled if local forwarding is enabled).
- * If set, ignore or enforce RA independent of local forwarding state.
- */
- if (link->network->ipv6_accept_ra < 0)
- /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
- return !link_ipv6_forward_enabled(link);
- else if (link->network->ipv6_accept_ra > 0)
- /* accept RA even if ip_forward is enabled */
- return true;
- else
- /* ignore RA */
- return false;
-}
-
-static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
- assert(link);
-
- if (!socket_ipv6_is_supported())
- return _IPV6_PRIVACY_EXTENSIONS_INVALID;
-
- if (link->flags & IFF_LOOPBACK)
- return _IPV6_PRIVACY_EXTENSIONS_INVALID;
-
- if (!link->network)
- return _IPV6_PRIVACY_EXTENSIONS_INVALID;
-
- return link->network->ipv6_privacy_extensions;
-}
-
-static int link_update_ipv6_sysctl(Link *link) {
- bool enabled;
- int r;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- enabled = link_ipv6_enabled(link);
- if (enabled) {
- r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false);
- if (r < 0)
- return log_link_warning_errno(link, r, "Cannot enable IPv6: %m");
-
- log_link_info(link, "IPv6 successfully enabled");
- }
-
- return 0;
-}
-
static bool link_is_enslaved(Link *link) {
if (link->flags & IFF_SLAVE)
/* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */
link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server);
link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client);
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
+ link->dhcp_acd = sd_ipv4acd_unref(link->dhcp_acd);
link->lldp = sd_lldp_unref(link->lldp);
+ link_lldp_emit_stop(link);
ndisc_flush(link);
link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);
link->ndisc = sd_ndisc_unref(link->ndisc);
link->radv = sd_radv_unref(link->radv);
+
+ ipv4_dad_unref(link);
}
static Link *link_free(Link *link) {
- Address *address;
-
assert(link);
link_ntp_settings_clear(link);
link->addresses = set_free(link->addresses);
link->addresses_foreign = set_free(link->addresses_foreign);
+ link->pool_addresses = set_free(link->pool_addresses);
link->static_addresses = set_free(link->static_addresses);
link->dhcp6_addresses = set_free(link->dhcp6_addresses);
link->dhcp6_addresses_old = set_free(link->dhcp6_addresses_old);
link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
link->ndisc_addresses = set_free(link->ndisc_addresses);
- while ((address = link->pool_addresses)) {
- LIST_REMOVE(addresses, link->pool_addresses, address);
- address_free(address);
- }
-
- link_lldp_emit_stop(link);
link_free_engines(link);
free(link->lease_file);
free(link->lldp_file);
link_dirty(link);
}
-int link_stop_clients(Link *link, bool may_keep_dhcp) {
+int link_stop_engines(Link *link, bool may_keep_dhcp) {
int r = 0, k;
- Address *ad;
assert(link);
assert(link->manager);
(link->manager->restarting ||
FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP));
- if (link->dhcp_client && !keep_dhcp) {
+ if (!keep_dhcp) {
k = sd_dhcp_client_stop(link->dhcp_client);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m");
}
- if (link->ipv4ll) {
- k = sd_ipv4ll_stop(link->ipv4ll);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m");
- }
+ k = sd_ipv4acd_stop(link->dhcp_acd);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client for DHCPv4: %m");
- if (link->network)
- LIST_FOREACH(addresses, ad, link->network->static_addresses)
- if (ad->acd && sd_ipv4acd_is_running(ad->acd) == 0) {
- k = sd_ipv4acd_stop(ad->acd);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m");
- }
+ k = sd_dhcp_server_stop(link->dhcp_server);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop DHCPv4 server: %m");
- if (link->dhcp6_client) {
- k = sd_dhcp6_client_stop(link->dhcp6_client);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
- }
+ k = sd_lldp_stop(link->lldp);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop LLDP: %m");
- if (link_dhcp6_pd_is_enabled(link)) {
- k = dhcp6_pd_remove(link);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
- }
+ k = sd_ipv4ll_stop(link->ipv4ll);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m");
- if (link->ndisc) {
- k = sd_ndisc_stop(link->ndisc);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
- }
+ k = ipv4_dad_stop(link);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m");
- if (link->radv) {
- k = sd_radv_stop(link->radv);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
- }
+ k = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
+
+ k = dhcp6_pd_remove(link);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
+
+ k = sd_ndisc_stop(link->ndisc);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
+
+ k = sd_radv_stop(link->radv);
+ if (k < 0)
+ r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
link_lldp_emit_stop(link);
return r;
link_set_state(link, LINK_STATE_FAILED);
- link_stop_clients(link, false);
+ (void) link_stop_engines(link, false);
link_dirty(link);
}
link_dirty(link);
}
-static int link_request_set_routing_policy_rule(Link *link) {
- RoutingPolicyRule *rule, *rrule = NULL;
- int r;
+void link_check_ready(Link *link) {
+ Address *a;
assert(link);
- assert(link->network);
-
- link->routing_policy_rules_configured = false;
-
- LIST_FOREACH(rules, rule, link->network->rules) {
- r = routing_policy_rule_get(link->manager, rule, &rrule);
- if (r >= 0) {
- if (r == 0)
- (void) routing_policy_rule_make_local(link->manager, rrule);
- continue;
- }
- r = routing_policy_rule_configure(rule, link, NULL);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set routing policy rules: %m");
- if (r > 0)
- link->routing_policy_rule_messages++;
- }
+ if (link->state == LINK_STATE_CONFIGURED)
+ return;
- routing_policy_rule_purge(link->manager, link);
- if (link->routing_policy_rule_messages == 0)
- link->routing_policy_rules_configured = true;
- else {
- log_link_debug(link, "Setting routing policy rules");
- link_set_state(link, LINK_STATE_CONFIGURING);
+ if (link->state != LINK_STATE_CONFIGURING) {
+ log_link_debug(link, "%s(): link is in %s state.", __func__, link_state_to_string(link->state));
+ return;
}
- return 0;
-}
+ if (!link->network)
+ return;
-static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
+ if (!link->addresses_configured) {
+ log_link_debug(link, "%s(): static addresses are not configured.", __func__);
+ return;
+ }
- assert(link);
- assert(link->nexthop_messages > 0);
- assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
- LINK_STATE_FAILED, LINK_STATE_LINGER));
+ if (!link->neighbors_configured) {
+ log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
+ return;
+ }
- link->nexthop_messages--;
+ SET_FOREACH(a, link->addresses)
+ if (!address_is_ready(a)) {
+ _cleanup_free_ char *str = NULL;
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
+ (void) in_addr_to_string(a->family, &a->in_addr, &str);
+ log_link_debug(link, "%s(): an address %s/%d is not ready.", __func__, strnull(str), a->prefixlen);
+ return;
+ }
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST) {
- log_link_message_warning_errno(link, m, r, "Could not set nexthop");
- link_enter_failed(link);
- return 1;
+ if (!link->static_routes_configured) {
+ log_link_debug(link, "%s(): static routes are not configured.", __func__);
+ return;
}
- if (link->nexthop_messages == 0) {
- log_link_debug(link, "Nexthop set");
- link->static_nexthops_configured = true;
- link_check_ready(link);
+ if (!link->static_nexthops_configured) {
+ log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
+ return;
}
- return 1;
-}
-
-static int link_request_set_nexthop(Link *link) {
- NextHop *nh;
- int r;
+ if (!link->routing_policy_rules_configured) {
+ log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
+ return;
+ }
- link->static_nexthops_configured = false;
+ if (!link->tc_configured) {
+ log_link_debug(link, "%s(): traffic controls are not configured.", __func__);
+ return;
+ }
- LIST_FOREACH(nexthops, nh, link->network->static_nexthops) {
- r = nexthop_configure(nh, link, nexthop_handler);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set nexthop: %m");
- if (r > 0)
- link->nexthop_messages++;
+ if (!link->sr_iov_configured) {
+ log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
+ return;
}
- if (link->nexthop_messages == 0) {
- link->static_nexthops_configured = true;
- link_check_ready(link);
- } else {
- log_link_debug(link, "Setting nexthop");
- link_set_state(link, LINK_STATE_CONFIGURING);
+ if (!link->bridge_mdb_configured) {
+ log_link_debug(link, "%s(): Bridge MDB is not configured.", __func__);
+ return;
}
- return 1;
-}
+ if (link_has_carrier(link) || !link->network->configure_without_carrier) {
+ bool has_ndisc_address = false;
+ NDiscAddress *n;
-static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(link);
- assert(link->route_messages > 0);
- assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
- LINK_STATE_FAILED, LINK_STATE_LINGER));
-
- link->route_messages--;
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST) {
- log_link_message_warning_errno(link, m, r, "Could not set route");
- link_enter_failed(link);
- return 1;
- }
-
- if (link->route_messages == 0) {
- log_link_debug(link, "Routes set");
- link->static_routes_configured = true;
- link_request_set_nexthop(link);
- }
-
- return 1;
-}
-
-int link_request_set_routes(Link *link) {
- enum {
- PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
- PHASE_GATEWAY, /* Second phase: Routes with a gateway */
- _PHASE_MAX
- } phase;
- Route *rt;
- int r;
-
- assert(link);
- assert(link->network);
- assert(link->state != _LINK_STATE_INVALID);
-
- link->static_routes_configured = false;
-
- if (!link->addresses_ready)
- return 0;
-
- if (!link_has_carrier(link) && !link->network->configure_without_carrier)
- /* During configuring addresses, the link lost its carrier. As networkd is dropping
- * the addresses now, let's not configure the routes either. */
- return 0;
-
- r = link_request_set_routing_policy_rule(link);
- if (r < 0)
- return r;
-
- /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
- for (phase = 0; phase < _PHASE_MAX; phase++)
- LIST_FOREACH(routes, rt, link->network->static_routes) {
- if (rt->gateway_from_dhcp)
- continue;
-
- if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
- continue;
-
- r = route_configure(rt, link, route_handler, NULL);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set routes: %m");
- if (r > 0)
- link->route_messages++;
- }
-
- if (link->route_messages == 0) {
- link->static_routes_configured = true;
- link_request_set_nexthop(link);
- } else {
- log_link_debug(link, "Setting routes");
- link_set_state(link, LINK_STATE_CONFIGURING);
- }
-
- return 0;
-}
-
-void link_check_ready(Link *link) {
- Address *a;
-
- assert(link);
-
- if (link->state == LINK_STATE_CONFIGURED)
- return;
-
- if (link->state != LINK_STATE_CONFIGURING) {
- log_link_debug(link, "%s(): link is in %s state.", __func__, link_state_to_string(link->state));
- return;
- }
-
- if (!link->network)
- return;
-
- if (!link->addresses_configured) {
- log_link_debug(link, "%s(): static addresses are not configured.", __func__);
- return;
- }
-
- if (!link->neighbors_configured) {
- log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
- return;
- }
-
- SET_FOREACH(a, link->addresses)
- if (!address_is_ready(a)) {
- _cleanup_free_ char *str = NULL;
-
- (void) in_addr_to_string(a->family, &a->in_addr, &str);
- log_link_debug(link, "%s(): an address %s/%d is not ready.", __func__, strnull(str), a->prefixlen);
- return;
- }
-
- if (!link->static_routes_configured) {
- log_link_debug(link, "%s(): static routes are not configured.", __func__);
- return;
- }
-
- if (!link->static_nexthops_configured) {
- log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
- return;
- }
-
- if (!link->routing_policy_rules_configured) {
- log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
- return;
- }
-
- if (!link->tc_configured) {
- log_link_debug(link, "%s(): traffic controls are not configured.", __func__);
- return;
- }
-
- if (!link->sr_iov_configured) {
- log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
- return;
- }
-
- if (!link->bridge_mdb_configured) {
- log_link_debug(link, "%s(): Bridge MDB is not configured.", __func__);
- return;
- }
-
- if (link_has_carrier(link) || !link->network->configure_without_carrier) {
- bool has_ndisc_address = false;
- NDiscAddress *n;
-
- if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
- log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
- return;
- }
+ if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
+ log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
+ return;
+ }
if (link_ipv6ll_enabled(link) &&
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) {
return;
}
-static int link_request_set_neighbors(Link *link) {
- Neighbor *neighbor;
+static int link_set_static_configs(Link *link) {
int r;
assert(link);
assert(link->network);
assert(link->state != _LINK_STATE_INVALID);
+ /* Reset all *_configured flags we are configuring. */
+ link->request_static_addresses = false;
+ link->addresses_configured = false;
+ link->addresses_ready = false;
link->neighbors_configured = false;
+ link->static_routes_configured = false;
+ link->static_nexthops_configured = false;
+ link->routing_policy_rules_configured = false;
- LIST_FOREACH(neighbors, neighbor, link->network->neighbors) {
- r = neighbor_configure(neighbor, link, NULL);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set neighbor: %m");
- }
+ r = link_set_bridge_fdb(link);
+ if (r < 0)
+ return r;
- if (link->neighbor_messages == 0) {
- link->neighbors_configured = true;
- link_check_ready(link);
- } else {
- log_link_debug(link, "Setting neighbors");
- link_set_state(link, LINK_STATE_CONFIGURING);
- }
+ r = link_set_bridge_mdb(link);
+ if (r < 0)
+ return r;
- return 0;
-}
+ r = link_set_neighbors(link);
+ if (r < 0)
+ return r;
-static int link_set_bridge_fdb(Link *link) {
- FdbEntry *fdb_entry;
- int r;
+ r = link_set_addresses(link);
+ if (r < 0)
+ return r;
- LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
- r = fdb_entry_configure(link, fdb_entry);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
- }
+ r = link_set_address_labels(link);
+ if (r < 0)
+ return r;
+
+ /* now that we can figure out a default address for the dhcp server, start it */
+ r = dhcp4_server_configure(link);
+ if (r < 0)
+ return r;
return 0;
}
-static int static_address_ready_callback(Address *address) {
- Address *a;
- Link *link;
-
- assert(address);
- assert(address->link);
-
- link = address->link;
-
- if (!link->addresses_configured)
- return 0;
+static int link_configure_continue(Link *link);
- SET_FOREACH(a, link->static_addresses)
- if (!address_is_ready(a)) {
- _cleanup_free_ char *str = NULL;
+static int link_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
- (void) in_addr_to_string(a->family, &a->in_addr, &str);
- log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen);
- return 0;
- }
+ assert(link);
- /* This should not be called again */
- SET_FOREACH(a, link->static_addresses)
- a->callback = NULL;
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
- link->addresses_ready = true;
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0)
+ log_link_message_warning_errno(link, m, r, "Could not set MAC address, ignoring");
+ else
+ log_link_debug(link, "Setting MAC address done.");
- return link_request_set_routes(link);
+ return 1;
}
-static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_set_mac(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
- assert(rtnl);
- assert(m);
assert(link);
- assert(link->ifname);
- assert(link->address_messages > 0);
- assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
- LINK_STATE_FAILED, LINK_STATE_LINGER));
+ assert(link->network);
+ assert(link->manager);
+ assert(link->manager->rtnl);
- link->address_messages--;
+ if (!link->network->mac)
+ return 0;
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
+ log_link_debug(link, "Setting MAC address");
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST) {
- log_link_message_warning_errno(link, m, r, "Could not set address");
- link_enter_failed(link);
- return 1;
- } else if (r >= 0)
- (void) manager_rtnl_process_address(rtnl, m, link->manager);
+ 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->address_messages == 0) {
- Address *a;
+ r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set MAC address: %m");
- log_link_debug(link, "Addresses set");
- link->addresses_configured = true;
+ r = netlink_call_async(link->manager->rtnl, NULL, req, link_mac_handler,
+ link_netlink_destroy_callback, link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
- /* When all static addresses are already ready, then static_address_ready_callback()
- * will not be called automatically. So, call it here. */
- a = set_first(link->static_addresses);
- if (!a) {
- log_link_warning(link, "No static address is stored.");
- link_enter_failed(link);
- return 1;
- }
- if (!a->callback) {
- log_link_warning(link, "Address ready callback is not set.");
- link_enter_failed(link);
- return 1;
- }
- r = a->callback(a);
- if (r < 0)
- link_enter_failed(link);
- }
+ link_ref(link);
- return 1;
+ return 0;
}
-static int static_address_configure(Address *address, Link *link, bool update) {
- Address *ret;
+static int link_nomaster_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
- assert(address);
assert(link);
- r = address_configure(address, link, address_handler, update, &ret);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not configure static address: %m");
-
- link->address_messages++;
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
- r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret);
+ r = sd_netlink_message_get_errno(m);
if (r < 0)
- return log_link_warning_errno(link, r, "Failed to store static address: %m");
-
- ret->callback = static_address_ready_callback;
+ log_link_message_warning_errno(link, m, r, "Could not set nomaster, ignoring");
+ else
+ log_link_debug(link, "Setting nomaster done.");
- return 0;
+ return 1;
}
-static int link_request_set_addresses(Link *link) {
- AddressLabel *label;
- Address *ad;
- Prefix *p;
+static int link_set_nomaster(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(link->network);
- assert(link->state != _LINK_STATE_INVALID);
+ assert(link->manager);
+ assert(link->manager->rtnl);
- if (link->address_remove_messages != 0) {
- log_link_debug(link, "Removing old addresses, new addresses will be configured later.");
- link->request_static_addresses = true;
+ /* set it free if not enslaved with networkd */
+ if (link->network->bridge || link->network->bond || link->network->vrf)
return 0;
- }
- /* Reset all *_configured flags we are configuring. */
- link->request_static_addresses = false;
- link->addresses_configured = false;
- link->addresses_ready = false;
- link->neighbors_configured = false;
- link->static_routes_configured = false;
- link->static_nexthops_configured = false;
- link->routing_policy_rules_configured = false;
+ log_link_debug(link, "Setting nomaster");
- r = link_set_bridge_fdb(link);
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
- return r;
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
- r = link_set_bridge_mdb(link);
+ r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0);
if (r < 0)
- return r;
+ return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m");
- r = link_request_set_neighbors(link);
+ r = netlink_call_async(link->manager->rtnl, NULL, req, link_nomaster_handler,
+ link_netlink_destroy_callback, link);
if (r < 0)
- return r;
-
- LIST_FOREACH(addresses, ad, link->network->static_addresses) {
- bool update;
-
- if (ad->family == AF_INET6 && !in_addr_is_null(ad->family, &ad->in_addr_peer))
- update = address_get(link, ad->family, &ad->in_addr_peer, ad->prefixlen, NULL) > 0;
- else
- update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0;
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
- r = static_address_configure(ad, link, update);
- if (r < 0)
- return r;
- }
+ link_ref(link);
- if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC)
- LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
- _cleanup_(address_freep) Address *address = NULL;
+ return 0;
+}
- if (!p->assign)
- continue;
+static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
- r = address_new(&address);
- if (r < 0)
- return log_oom();
+ assert(m);
+ assert(link);
+ assert(link->ifname);
- r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not get RA prefix: %m");
+ link->setting_mtu = false;
- r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
-
- address->family = AF_INET6;
- r = static_address_configure(address, link, true);
- if (r < 0)
- return r;
- }
-
- LIST_FOREACH(labels, label, link->network->address_labels) {
- r = address_label_configure(label, link, NULL, false);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set address label: %m");
-
- link->address_label_messages++;
- }
-
- /* now that we can figure out a default address for the dhcp server, start it */
- if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) {
- r = dhcp4_server_configure(link);
- if (r < 0)
- return r;
- log_link_debug(link, "Offering DHCPv4 leases");
- }
-
- if (link->address_messages == 0) {
- link->addresses_configured = true;
- link->addresses_ready = true;
- r = link_request_set_routes(link);
- if (r < 0)
- return r;
- } else {
- log_link_debug(link, "Setting addresses");
- link_set_state(link, LINK_STATE_CONFIGURING);
- }
-
- return 0;
-}
-
-static int link_set_bridge_vlan(Link *link) {
- int r;
-
- r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
- if (r < 0)
- log_link_error_errno(link, r, "Failed to assign VLANs to bridge port: %m");
-
- return r;
-}
-
-static int link_set_proxy_arp(Link *link) {
- int r;
-
- if (!link_proxy_arp_enabled(link))
- return 0;
-
- r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0);
- if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m");
-
- return 0;
-}
-
-static int link_configure_continue(Link *link);
-
-static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(m);
- assert(link);
- assert(link->ifname);
-
- link->setting_mtu = false;
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0)
assert(link);
- if (link_ipv6_accept_ra_enabled(link)) {
- assert(link->ndisc);
-
+ if (link->ndisc) {
log_link_debug(link, "Discovering IPv6 routers");
r = sd_ndisc_start(link->ndisc);
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
}
- if (link_radv_enabled(link)) {
+ if (link->radv) {
assert(link->radv);
assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
- if (link_dhcp4_enabled(link)) {
- assert(link->dhcp_client);
-
+ if (link->dhcp_client) {
log_link_debug(link, "Acquiring DHCPv4 lease");
r = sd_dhcp_client_start(link->dhcp_client);
return r;
}
- if (link_lldp_emit_enabled(link)) {
- r = link_lldp_emit_start(link);
- if (r < 0)
- return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
- }
+ r = link_lldp_emit_start(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
return 0;
}
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
- /* set it free if not enslaved with networkd */
- if (!link->network->bridge && !link->network->bond && !link->network->vrf) {
- r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m");
- }
-
r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
if (r < 0)
return log_link_error_errno(link, r, "Could not set link flags: %m");
- if (link->network->mac) {
- r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set MAC address: %m");
- }
-
r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
link_netlink_destroy_callback, link);
if (r < 0)
log_link_error_errno(link, r, "Failed to add to bond master's slave list: %m");
}
- if (link->network->use_br_vlan &&
- (link->network->bridge || streq_ptr("bridge", link->kind))) {
- r = link_set_bridge_vlan(link);
- if (r < 0)
- log_link_error_errno(link, r, "Could not set bridge vlan: %m");
- }
+ r = link_set_bridge_vlan(link);
+ if (r < 0)
+ log_link_error_errno(link, r, "Could not set bridge vlan: %m");
/* Skip setting up addresses until it gets carrier,
or it would try to set addresses twice,
return 0;
link_set_state(link, LINK_STATE_CONFIGURING);
- return link_request_set_addresses(link);
+
+ r = link_acquire_conf(link);
+ if (r < 0)
+ return r;
+
+ return link_set_static_configs(link);
}
static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return 0;
}
-static int link_set_ipv4_forward(Link *link) {
- int r;
-
- if (!link_ipv4_forward_enabled(link))
- return 0;
-
- /* We propagate the forwarding flag from one interface to the
- * global setting one way. This means: as long as at least one
- * interface was configured at any time that had IP forwarding
- * enabled the setting will stay on for good. We do this
- * primarily to keep IPv4 and IPv6 packet forwarding behaviour
- * somewhat in sync (see below). */
-
- r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1");
- if (r < 0)
- log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_forward(Link *link) {
- int r;
-
- if (!link_ipv6_forward_enabled(link))
- return 0;
-
- /* On Linux, the IPv6 stack does not know a per-interface
- * packet forwarding setting: either packet forwarding is on
- * for all, or off for all. We hence don't bother with a
- * per-interface setting, but simply propagate the interface
- * flag, if it is set, to the global flag, one-way. Note that
- * while IPv4 would allow a per-interface flag, we expose the
- * same behaviour there and also propagate the setting from
- * one to all, to keep things simple (see above). */
-
- r = sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
- if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_privacy_extensions(Link *link) {
- IPv6PrivacyExtensions s;
- int r;
-
- s = link_ipv6_privacy_extensions(link);
- if (s < 0)
- return 0;
-
- r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions);
- if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_accept_ra(Link *link) {
- int r;
-
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (!link->network)
- return 0;
-
- r = sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0");
- if (r < 0)
- log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_dad_transmits(Link *link) {
+static int link_drop_foreign_config(Link *link) {
int r;
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (!link->network)
- return 0;
-
- if (link->network->ipv6_dad_transmits < 0)
- return 0;
-
- r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits);
+ r = link_drop_foreign_addresses(link);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_hop_limit(Link *link) {
- int r;
-
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (!link->network)
- return 0;
-
- if (link->network->ipv6_hop_limit < 0)
- return 0;
+ return r;
- r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit);
+ r = link_drop_foreign_neighbors(link);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
-
- return 0;
-}
-
-static int link_set_ipv6_mtu(Link *link) {
- int r;
-
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ipv6_mtu == 0)
- return 0;
-
- /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
- * on the interface. Bump up IPv6 MTU bytes to IPV6_MTU_MIN. */
- if (link->network->ipv6_mtu < IPV6_MIN_MTU) {
- log_link_notice(link, "Bumping IPv6 MTU to "STRINGIFY(IPV6_MIN_MTU)" byte minimum required");
- link->network->ipv6_mtu = IPV6_MIN_MTU;
- }
-
- r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu);
- if (r < 0) {
- if (link->mtu < link->network->ipv6_mtu)
- log_link_warning(link, "Cannot set IPv6 MTU %"PRIu32" higher than device MTU %"PRIu32,
- link->network->ipv6_mtu, link->mtu);
- else
- log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
- }
-
- link->ipv6_mtu_set = true;
+ return r;
- return 0;
+ return link_drop_foreign_routes(link);
}
-static int link_set_ipv4_accept_local(Link *link) {
+static int link_drop_config(Link *link) {
int r;
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ipv4_accept_local < 0)
- return 0;
-
- r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local);
+ r = link_drop_addresses(link);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface: %m");
-
- return 0;
-}
-
-static bool link_is_static_address_configured(Link *link, Address *address) {
- Address *net_address;
-
- assert(link);
- assert(address);
-
- if (!link->network)
- return false;
-
- LIST_FOREACH(addresses, net_address, link->network->static_addresses)
- if (address_equal(net_address, address))
- return true;
- else if (address->family == AF_INET6 && net_address->family == AF_INET6 &&
- in_addr_equal(AF_INET6, &address->in_addr, &net_address->in_addr_peer) > 0)
- return true;
-
- return false;
-}
-
-static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) {
- Neighbor *net_neighbor;
-
- assert(link);
- assert(neighbor);
-
- if (!link->network)
- return false;
-
- LIST_FOREACH(neighbors, net_neighbor, link->network->neighbors)
- if (neighbor_equal(net_neighbor, neighbor))
- return true;
-
- return false;
-}
-
-static bool link_is_static_route_configured(Link *link, Route *route) {
- Route *net_route;
-
- assert(link);
- assert(route);
-
- if (!link->network)
- return false;
-
- LIST_FOREACH(routes, net_route, link->network->static_routes)
- if (route_equal(net_route, route))
- return true;
-
- return false;
-}
-
-static bool link_address_is_dynamic(Link *link, Address *address) {
- Route *route;
-
- assert(link);
- assert(address);
-
- if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
- return true;
-
- /* Even when the address is leased from a DHCP server, networkd assign the address
- * without lifetime when KeepConfiguration=dhcp. So, let's check that we have
- * corresponding routes with RTPROT_DHCP. */
- SET_FOREACH(route, link->routes_foreign) {
- if (route->protocol != RTPROT_DHCP)
- continue;
-
- if (address->family != route->family)
- continue;
-
- if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc))
- return true;
- }
-
- return false;
-}
-
-static int link_enumerate_ipv6_tentative_addresses(Link *link) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *addr;
- int r;
-
- assert(link);
- assert(link->manager);
- assert(link->manager->rtnl);
+ return r;
- r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, 0, AF_INET6);
+ r = link_drop_neighbors(link);
if (r < 0)
return r;
- r = sd_netlink_call(link->manager->rtnl, req, 0, &reply);
+ r = link_drop_routes(link);
if (r < 0)
return r;
- for (addr = reply; addr; addr = sd_netlink_message_next(addr)) {
- unsigned char flags;
- int ifindex;
-
- r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: invalid ifindex, ignoring: %m");
- continue;
- } else if (link->ifindex != ifindex)
- continue;
-
- r = sd_rtnl_message_addr_get_flags(addr, &flags);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m");
- continue;
- } else if (!(flags & IFA_F_TENTATIVE))
- continue;
-
- log_link_debug(link, "Found tentative ipv6 link-local address");
- (void) manager_rtnl_process_address(link->manager->rtnl, addr, link->manager);
- }
-
- return 0;
-}
-
-static int link_drop_foreign_config(Link *link) {
- Address *address;
- Neighbor *neighbor;
- Route *route;
- int r;
-
- /* The kernel doesn't notify us about tentative addresses;
- * so if ipv6ll is disabled, we need to enumerate them now so we can drop them below */
- if (!link_ipv6ll_enabled(link)) {
- r = link_enumerate_ipv6_tentative_addresses(link);
- if (r < 0)
- return r;
- }
-
- SET_FOREACH(address, link->addresses_foreign) {
- /* we consider IPv6LL addresses to be managed by the kernel */
- if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
- continue;
-
- if (link_address_is_dynamic(link, address)) {
- if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
- continue;
- } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC))
- continue;
-
- if (link_is_static_address_configured(link, address)) {
- r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to add address: %m");
- } else {
- r = address_remove(address, link, NULL);
- if (r < 0)
- return r;
- }
- }
-
- SET_FOREACH(neighbor, link->neighbors_foreign) {
- if (link_is_neighbor_configured(link, neighbor)) {
- r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL);
- if (r < 0)
- return r;
- } else {
- r = neighbor_remove(neighbor, link, NULL);
- if (r < 0)
- return r;
- }
- }
-
- SET_FOREACH(route, link->routes_foreign) {
- /* do not touch routes managed by the kernel */
- if (route->protocol == RTPROT_KERNEL)
- continue;
-
- /* do not touch multicast route added by kernel */
- /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that.
- * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */
- if (route->protocol == RTPROT_BOOT &&
- route->family == AF_INET6 &&
- route->dst_prefixlen == 8 &&
- in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} }))
- continue;
-
- if (route->protocol == RTPROT_STATIC && link->network &&
- FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC))
- continue;
-
- if (route->protocol == RTPROT_DHCP && link->network &&
- FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
- continue;
-
- if (link_is_static_route_configured(link, route)) {
- r = route_add(link, route, NULL);
- if (r < 0)
- return r;
- } else {
- r = route_remove(route, link, NULL);
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
-
-static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(m);
- assert(link);
- assert(link->ifname);
- assert(link->address_remove_messages > 0);
-
- link->address_remove_messages--;
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EADDRNOTAVAIL)
- log_link_message_warning_errno(link, m, r, "Could not drop address");
- else if (r >= 0)
- (void) manager_rtnl_process_address(rtnl, m, link->manager);
-
- if (link->address_remove_messages == 0 && link->request_static_addresses) {
- link_set_state(link, LINK_STATE_CONFIGURING);
- r = link_request_set_addresses(link);
- if (r < 0)
- link_enter_failed(link);
- }
-
- return 1;
-}
-
-static int link_drop_config(Link *link) {
- Address *address, *pool_address;
- Neighbor *neighbor;
- Route *route;
- int r;
-
- SET_FOREACH(address, link->addresses) {
- /* we consider IPv6LL addresses to be managed by the kernel */
- if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
- continue;
-
- r = address_remove(address, link, remove_static_address_handler);
- if (r < 0)
- return r;
-
- link->address_remove_messages++;
-
- /* If this address came from an address pool, clean up the pool */
- LIST_FOREACH(addresses, pool_address, link->pool_addresses)
- if (address_equal(address, pool_address)) {
- LIST_REMOVE(addresses, link->pool_addresses, pool_address);
- address_free(pool_address);
- break;
- }
- }
-
- SET_FOREACH(neighbor, link->neighbors) {
- r = neighbor_remove(neighbor, link, NULL);
- if (r < 0)
- return r;
- }
-
- SET_FOREACH(route, link->routes) {
- /* do not touch routes managed by the kernel */
- if (route->protocol == RTPROT_KERNEL)
- continue;
-
- r = route_remove(route, link, NULL);
- if (r < 0)
- return r;
- }
-
- ndisc_flush(link);
-
- return 0;
-}
-
-static int link_configure_ipv4_dad(Link *link) {
- Address *address;
- int r;
-
- assert(link);
- assert(link->network);
-
- LIST_FOREACH(addresses, address, link->network->static_addresses)
- if (address->family == AF_INET &&
- FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) {
- r = configure_ipv4_duplicate_address_detection(link, address);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to configure IPv4ACD: %m");
- }
-
- return 0;
-}
-
-static int link_configure_traffic_control(Link *link) {
- TrafficControl *tc;
- int r;
-
- link->tc_configured = false;
- link->tc_messages = 0;
-
- ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) {
- r = traffic_control_configure(link, tc);
- if (r < 0)
- return r;
- }
-
- if (link->tc_messages == 0)
- link->tc_configured = true;
- else
- log_link_debug(link, "Configuring traffic control");
-
- return 0;
-}
-
-static int link_configure_sr_iov(Link *link) {
- SRIOV *sr_iov;
- int r;
-
- link->sr_iov_configured = false;
- link->sr_iov_messages = 0;
-
- ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
- r = sr_iov_configure(link, sr_iov);
- if (r < 0)
- return r;
- }
-
- if (link->sr_iov_messages == 0)
- link->sr_iov_configured = true;
- else
- log_link_debug(link, "Configuring SR-IOV");
+ ndisc_flush(link);
return 0;
}
-static int link_configure(Link *link) {
+int link_configure(Link *link) {
int r;
assert(link);
if (link->iftype == ARPHRD_CAN)
return link_configure_can(link);
- /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled
- * for this interface, then enable IPv6 */
- (void) link_update_ipv6_sysctl(link);
-
- r = link_set_proxy_arp(link);
+ r = link_set_sysctl(link);
if (r < 0)
- return r;
+ return r;
- r = ipv6_proxy_ndp_addresses_configure(link);
+ r = link_set_ipv6_proxy_ndp_addresses(link);
if (r < 0)
return r;
- r = link_set_ipv4_forward(link);
+ r = link_set_mac(link);
if (r < 0)
return r;
- r = link_set_ipv6_forward(link);
+ r = link_set_nomaster(link);
if (r < 0)
return r;
- r = link_set_ipv6_privacy_extensions(link);
+ r = link_set_flags(link);
if (r < 0)
return r;
- r = link_set_ipv6_accept_ra(link);
+ r = link_set_group(link);
if (r < 0)
return r;
- r = link_set_ipv6_dad_transmits(link);
+ r = ipv4ll_configure(link);
if (r < 0)
return r;
- r = link_set_ipv6_hop_limit(link);
+ r = dhcp4_configure(link);
if (r < 0)
return r;
- r = link_set_ipv4_accept_local(link);
+ r = dhcp6_configure(link);
if (r < 0)
return r;
- r = link_set_flags(link);
+ r = ndisc_configure(link);
if (r < 0)
return r;
- r = link_set_group(link);
+ r = radv_configure(link);
if (r < 0)
return r;
- if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) {
- r = ipv4ll_configure(link);
- if (r < 0)
- return r;
- }
-
- if (link_dhcp4_enabled(link)) {
- r = dhcp4_set_promote_secondaries(link);
- if (r < 0)
- return r;
-
- r = dhcp4_configure(link);
- if (r < 0)
- return r;
- }
-
- if (link_dhcp4_server_enabled(link)) {
- r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
- if (r < 0)
- return r;
-
- r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
- if (r < 0)
- return r;
- }
-
- if (link_dhcp6_enabled(link) ||
- link_ipv6_accept_ra_enabled(link)) {
- r = dhcp6_configure(link);
- if (r < 0)
- return r;
- }
-
- if (link_ipv6_accept_ra_enabled(link)) {
- r = ndisc_configure(link);
- if (r < 0)
- return r;
- }
-
- if (link_radv_enabled(link)) {
- r = radv_configure(link);
- if (r < 0)
- return r;
- }
-
- if (link_lldp_rx_enabled(link)) {
- r = link_lldp_rx_configure(link);
- if (r < 0)
- return r;
- }
-
- r = link_configure_mtu(link);
+ r = link_lldp_rx_configure(link);
if (r < 0)
return r;
- r = link_configure_addrgen_mode(link);
+ r = link_configure_mtu(link);
if (r < 0)
return r;
- r = link_configure_ipv4_dad(link);
+ r = link_configure_addrgen_mode(link);
if (r < 0)
return r;
* we must set this here, after we've set device mtu */
r = link_set_ipv6_mtu(link);
if (r < 0)
- return r;
-
- if (link_has_carrier(link) || link->network->configure_without_carrier) {
- r = link_acquire_conf(link);
- if (r < 0)
- return r;
- }
+ log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface, ignoring: %m");
return link_enter_join_netdev(link);
}
-static int duid_set_uuid(DUID *duid, sd_id128_t uuid) {
- assert(duid);
-
- if (duid->raw_data_len > 0)
- return 0;
-
- if (duid->type != DUID_TYPE_UUID)
- return -EINVAL;
-
- memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t));
- duid->raw_data_len = sizeof(sd_id128_t);
-
- return 1;
-}
-
-int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- Manager *manager = userdata;
- const sd_bus_error *e;
- const void *a;
- size_t sz;
- DUID *duid;
- Link *link;
- int r;
-
- assert(m);
- assert(manager);
-
- e = sd_bus_message_get_error(m);
- if (e) {
- log_error_errno(sd_bus_error_get_errno(e),
- "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s",
- e->message);
- goto configure;
- }
-
- r = sd_bus_message_read_array(m, 'y', &a, &sz);
- if (r < 0)
- goto configure;
-
- if (sz != sizeof(sd_id128_t)) {
- log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID.");
- goto configure;
- }
-
- memcpy(&manager->product_uuid, a, sz);
- while ((duid = set_steal_first(manager->duids_requesting_uuid)))
- (void) duid_set_uuid(duid, manager->product_uuid);
-
- manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid);
-
-configure:
- while ((link = set_steal_first(manager->links_requesting_uuid))) {
- link_unref(link);
-
- r = link_configure(link);
- if (r < 0)
- link_enter_failed(link);
- }
-
- manager->links_requesting_uuid = set_free(manager->links_requesting_uuid);
-
- /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
- * even if the method fails. */
- manager->has_product_uuid = true;
-
- return 1;
-}
-
-static bool link_requires_uuid(Link *link) {
- const DUID *duid;
-
- assert(link);
- assert(link->manager);
- assert(link->network);
-
- duid = link_get_duid(link);
- if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
- return false;
-
- if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
- return true;
-
- if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link))
- return true;
-
- return false;
-}
-
-static int link_configure_duid(Link *link) {
- Manager *m;
- DUID *duid;
- int r;
-
- assert(link);
- assert(link->manager);
- assert(link->network);
-
- m = link->manager;
- duid = link_get_duid(link);
-
- if (!link_requires_uuid(link))
- return 1;
-
- if (m->has_product_uuid) {
- (void) duid_set_uuid(duid, m->product_uuid);
- return 1;
- }
-
- if (!m->links_requesting_uuid) {
- r = manager_request_product_uuid(m, link);
- if (r < 0) {
- if (r == -ENOMEM)
- return r;
-
- log_link_warning_errno(link, r,
- "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
- return 1;
- }
- } else {
- r = set_put(m->links_requesting_uuid, link);
- if (r < 0)
- return log_oom();
- if (r > 0)
- link_ref(link);
-
- r = set_put(m->duids_requesting_uuid, duid);
- if (r < 0)
- return log_oom();
- }
-
- return 0;
-}
-
static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) {
Network *network;
int r;
log_link_info(link, "Re-configuring with %s", network->filename);
/* Dropping old .network file */
- r = link_stop_clients(link, false);
+ r = link_stop_engines(link, false);
if (r < 0)
return r;
- if (link_dhcp4_server_enabled(link))
- (void) sd_dhcp_server_stop(link->dhcp_server);
-
r = link_drop_config(link);
if (r < 0)
return r;
*routes = NULL,
*dhcp4_address = NULL,
*ipv4ll_address = NULL;
- union in_addr_union address;
int r;
assert(link);
network_file_fail:
- for (const char *p = addresses; p; ) {
- _cleanup_free_ char *address_str = NULL;
- char *prefixlen_str;
- int family;
- unsigned char prefixlen;
-
- r = extract_first_word(&p, &address_str, NULL, 0);
- if (r < 0)
- log_link_warning_errno(link, r, "failed to parse ADDRESSES: %m");
- if (r <= 0)
- break;
-
- prefixlen_str = strchr(address_str, '/');
- if (!prefixlen_str) {
- log_link_debug(link, "Failed to parse address and prefix length %s", address_str);
- continue;
- }
- *prefixlen_str++ = '\0';
-
- r = sscanf(prefixlen_str, "%hhu", &prefixlen);
- if (r != 1) {
- log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str);
- continue;
- }
-
- r = in_addr_from_string_auto(address_str, &family, &address);
- if (r < 0) {
- log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str);
- continue;
- }
-
- r = address_add(link, family, &address, prefixlen, NULL);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to add address: %m");
- }
-
- for (const char *p = routes; p; ) {
- _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
- _cleanup_(route_freep) Route *tmp = NULL;
- _cleanup_free_ char *route_str = NULL;
- char *prefixlen_str;
- Route *route;
-
- r = extract_first_word(&p, &route_str, NULL, 0);
- if (r < 0)
- log_link_debug_errno(link, r, "failed to parse ROUTES: %m");
- if (r <= 0)
- break;
-
- prefixlen_str = strchr(route_str, '/');
- if (!prefixlen_str) {
- log_link_debug(link, "Failed to parse route %s", route_str);
- continue;
- }
- *prefixlen_str++ = '\0';
-
- r = route_new(&tmp);
- if (r < 0)
- return log_oom();
-
- r = sscanf(prefixlen_str,
- "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT,
- &tmp->dst_prefixlen,
- &tmp->tos,
- &tmp->priority,
- &tmp->table,
- &tmp->lifetime);
- if (r != 5) {
- log_link_debug(link,
- "Failed to parse destination prefix length, tos, priority, table or expiration %s",
- prefixlen_str);
- continue;
- }
-
- r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst);
- if (r < 0) {
- log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str);
- continue;
- }
-
- r = route_add(link, tmp, &route);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to add route: %m");
-
- if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
- r = sd_event_add_time(link->manager->event, &expire,
- clock_boottime_or_monotonic(),
- route->lifetime, 0, route_expire_handler, route);
- if (r < 0)
- log_link_warning_errno(link, r, "Could not arm route expiration handler: %m");
- }
-
- sd_event_source_unref(route->expire);
- route->expire = TAKE_PTR(expire);
- }
-
- if (dhcp4_address) {
- r = in_addr_from_string(AF_INET, dhcp4_address, &address);
- if (r < 0) {
- log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address);
- goto dhcp4_address_fail;
- }
-
- r = sd_dhcp_client_new(&link->dhcp_client, link->network ? link->network->dhcp_anonymize : 0);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m");
-
- r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to attach DHCPv4 event: %m");
-
- r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address);
- }
-
-dhcp4_address_fail:
-
- if (ipv4ll_address) {
- r = in_addr_from_string(AF_INET, ipv4ll_address, &address);
- if (r < 0) {
- log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address);
- goto ipv4ll_address_fail;
- }
-
- r = sd_ipv4ll_new(&link->ipv4ll);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m");
+ r = link_deserialize_addresses(link, addresses);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to load addresses from %s, ignoring: %m", link->state_file);
- r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to attach IPv4LL event: %m");
+ r = link_deserialize_routes(link, routes);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to load routes from %s, ignoring: %m", link->state_file);
- r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
- if (r < 0)
- return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address);
- }
+ r = link_deserialize_dhcp4(link, dhcp4_address);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to load DHCPv4 address from %s, ignoring: %m", link->state_file);
-ipv4ll_address_fail:
+ r = link_deserialize_ipv4ll(link, ipv4ll_address);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to load IPv4LL address from %s, ignoring: %m", link->state_file);
return 0;
}
}
link_set_state(link, LINK_STATE_CONFIGURING);
- r = link_request_set_addresses(link);
+ r = link_set_static_configs(link);
if (r < 0)
return r;
}
if (link->setting_mtu)
return 0;
- r = link_stop_clients(link, false);
+ r = link_stop_engines(link, false);
if (r < 0) {
link_enter_failed(link);
return r;
}
- if (link_dhcp4_server_enabled(link))
- (void) sd_dhcp_server_stop(link->dhcp_server);
-
r = link_drop_config(link);
if (r < 0)
return r;
mac.ether_addr_octet[4],
mac.ether_addr_octet[5]);
- if (link->ipv4ll) {
- bool restart = sd_ipv4ll_is_running(link->ipv4ll) > 0;
-
- if (restart) {
- r = sd_ipv4ll_stop(link->ipv4ll);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not stop IPv4LL client: %m");
- }
-
- r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
-
- if (restart) {
- r = sd_ipv4ll_start(link->ipv4ll);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not restart IPv4LL client: %m");
- }
- }
-
- if (link->dhcp_client) {
- r = sd_dhcp_client_set_mac(link->dhcp_client,
- (const uint8_t *) &link->mac,
- sizeof (link->mac),
- ARPHRD_ETHER);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
-
- r = dhcp4_set_client_identifier(link);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not set DHCP client identifier: %m");
- }
-
- if (link->dhcp6_client) {
- const DUID* duid = link_get_duid(link);
- bool restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0;
-
- if (restart) {
- r = sd_dhcp6_client_stop(link->dhcp6_client);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
- }
-
- r = sd_dhcp6_client_set_mac(link->dhcp6_client,
- (const uint8_t *) &link->mac,
- sizeof (link->mac),
- ARPHRD_ETHER);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
-
- if (link->network->iaid_set) {
- r = sd_dhcp6_client_set_iaid(link->dhcp6_client, link->network->iaid);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
- }
-
- r = sd_dhcp6_client_set_duid(link->dhcp6_client,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
-
- if (restart) {
- r = sd_dhcp6_client_start(link->dhcp6_client);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m");
- }
- }
-
- if (link->radv) {
- bool restart = sd_radv_is_running(link->radv);
+ r = ipv4ll_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
- if (restart) {
- r = sd_radv_stop(link->radv);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not stop Router Advertisement: %m");
- }
+ r = dhcp4_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
- r = sd_radv_set_mac(link->radv, &link->mac);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m");
+ r = dhcp6_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
- if (restart) {
- r = sd_radv_start(link->radv);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not restart Router Advertisement: %m");
- }
- }
+ r = dhcp6_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address for Router Advertisement: %m");
if (link->ndisc) {
r = sd_ndisc_set_mac(link->ndisc, &link->mac);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m");
}
+
+ r = ipv4_dad_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m");
}
old_master = link->master_ifindex;
const char *admin_state, *oper_state, *carrier_state, *address_state;
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
- Route *route;
- Address *a;
int r;
assert(link);
/************************************************************/
- fputs("ADDRESSES=", f);
- space = false;
- SET_FOREACH(a, link->addresses) {
- _cleanup_free_ char *address_str = NULL;
-
- r = in_addr_to_string(a->family, &a->in_addr, &address_str);
- if (r < 0)
- goto fail;
-
- fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
- space = true;
- }
- fputc('\n', f);
+ r = link_serialize_addresses(link, f);
+ if (r < 0)
+ goto fail;
/************************************************************/
- fputs("ROUTES=", f);
- space = false;
- SET_FOREACH(route, link->routes) {
- _cleanup_free_ char *route_str = NULL;
-
- r = in_addr_to_string(route->family, &route->dst, &route_str);
- if (r < 0)
- goto fail;
-
- fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT,
- space ? " " : "", route_str,
- route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
- space = true;
- }
-
- fputc('\n', f);
+ r = link_serialize_routes(link, f);
+ if (r < 0)
+ goto fail;
}
print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links);
} else
(void) unlink(link->lease_file);
- if (link->ipv4ll) {
- struct in_addr address;
-
- r = sd_ipv4ll_get_address(link->ipv4ll, &address);
- if (r >= 0) {
- fputs("IPV4LL_ADDRESS=", f);
- serialize_in_addrs(f, &address, 1, false, NULL);
- fputc('\n', f);
- }
- }
-
- if (link->dhcp6_client) {
- _cleanup_free_ char *duid = NULL;
- uint32_t iaid;
-
- r = sd_dhcp6_client_get_iaid(link->dhcp6_client, &iaid);
- if (r >= 0)
- fprintf(f, "DHCP6_CLIENT_IAID=0x%x\n", iaid);
+ r = link_serialize_ipv4ll(link, f);
+ if (r < 0)
+ goto fail;
- r = sd_dhcp6_client_duid_as_string(link->dhcp6_client, &duid);
- if (r >= 0)
- fprintf(f, "DHCP6_CLIENT_DUID=%s\n", duid);
- }
+ r = link_serialize_dhcp6_client(link, f);
+ if (r < 0)
+ goto fail;
r = fflush_and_check(f);
if (r < 0)
#include "sd-dhcp-client.h"
#include "sd-dhcp-server.h"
#include "sd-dhcp6-client.h"
+#include "sd-ipv4acd.h"
#include "sd-ipv4ll.h"
#include "sd-lldp.h"
#include "sd-ndisc.h"
#include "sd-radv.h"
#include "sd-netlink.h"
-#include "list.h"
#include "log-link.h"
#include "network-util.h"
#include "networkd-util.h"
Set *addresses;
Set *addresses_foreign;
+ Set *pool_addresses;
Set *static_addresses;
Set *neighbors;
Set *neighbors_foreign;
uint32_t original_mtu;
unsigned dhcp4_messages;
unsigned dhcp4_remove_messages;
+ sd_ipv4acd *dhcp_acd;
bool dhcp4_route_failed:1;
bool dhcp4_route_retrying:1;
bool dhcp4_configured:1;
bool ipv6_mtu_set:1;
bool bridge_mdb_configured:1;
- LIST_HEAD(Address, pool_addresses);
-
sd_dhcp_server *dhcp_server;
sd_ndisc *ndisc;
typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
-DUID *link_get_duid(Link *link);
-int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error);
-
void link_ntp_settings_clear(Link *link);
void link_dns_settings_clear(Link *link);
Link *link_unref(Link *link);
int link_carrier_reset(Link *link);
bool link_has_carrier(Link *link);
+bool link_ipv6_enabled(Link *link);
+bool link_ipv6ll_enabled(Link *link);
int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
int link_set_mtu(Link *link, uint32_t mtu);
bool link_ipv4ll_enabled(Link *link, AddressFamily mask);
-int link_stop_clients(Link *link, bool may_keep_dhcp);
+int link_stop_engines(Link *link, bool may_keep_dhcp);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
-uint32_t link_get_vrf_table(Link *link);
-uint32_t link_get_dhcp_route_table(Link *link);
-uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
-int link_request_set_routes(Link *link);
-
+int link_configure(Link *link);
int link_reconfigure(Link *link, bool force);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_notice_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
#define log_link_message_info_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_INFO, err, msg)
#define log_link_message_debug_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)
-
-#define ADDRESS_FMT_VAL(address) \
- be32toh((address).s_addr) >> 24, \
- (be32toh((address).s_addr) >> 16) & 0xFFu, \
- (be32toh((address).s_addr) >> 8) & 0xFFu, \
- be32toh((address).s_addr) & 0xFFu
#include "networkd-link.h"
#include "networkd-lldp-rx.h"
#include "networkd-lldp-tx.h"
+#include "networkd-manager.h"
#include "networkd-network.h"
#include "string-table.h"
#include "string-util.h"
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
-bool link_lldp_rx_enabled(Link *link) {
+static bool link_lldp_rx_enabled(Link *link) {
assert(link);
if (link->flags & IFF_LOOPBACK)
int link_lldp_rx_configure(Link *link) {
int r;
- r = sd_lldp_new(&link->lldp);
- if (r < 0)
- return r;
+ if (!link_lldp_rx_enabled(link))
+ return 0;
+
+ if (!link->lldp) {
+ r = sd_lldp_new(&link->lldp);
+ if (r < 0)
+ return r;
+
+ r = sd_lldp_attach_event(link->lldp, link->manager->event, 0);
+ if (r < 0)
+ return r;
+ }
r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
if (r < 0)
if (r < 0)
return r;
- r = sd_lldp_attach_event(link->lldp, NULL, 0);
- if (r < 0)
- return r;
-
r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include <stdbool.h>
-
#include "conf-parser.h"
typedef struct Link Link;
_LLDP_MODE_INVALID = -1,
} LLDPMode;
-bool link_lldp_rx_enabled(Link *link);
int link_lldp_rx_configure(Link *link);
int link_update_lldp(Link *link);
int link_lldp_save(Link *link);
assert(link);
- if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) {
+ if (!link_lldp_emit_enabled(link)) {
link_lldp_emit_stop(link);
return 0;
}
#include "local-addresses.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "networkd-address-pool.h"
#include "networkd-dhcp-server-bus.h"
#include "networkd-dhcp6.h"
#include "networkd-link-bus.h"
#include "networkd-manager-bus.h"
#include "networkd-manager.h"
+#include "networkd-neighbor.h"
#include "networkd-network-bus.h"
+#include "networkd-nexthop.h"
+#include "networkd-routing-policy-rule.h"
#include "networkd-speed-meter.h"
#include "ordered-set.h"
#include "path-lookup.h"
/* use 128 MB for receive socket kernel queue. */
#define RCVBUF_SIZE (128*1024*1024)
-static int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) {
- const char *err_msg = NULL;
-
- (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
- return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : "");
-}
-
-static int setup_default_address_pool(Manager *m) {
- AddressPool *p;
- int r;
-
- assert(m);
-
- /* Add in the well-known private address ranges. */
-
- r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8);
- if (r < 0)
- return r;
-
- r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
- if (r < 0)
- return r;
-
- r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12);
- if (r < 0)
- return r;
-
- r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
- if (r < 0)
- return r;
-
- return 0;
-}
-
static int manager_reset_all(Manager *m) {
Link *link;
int r;
static int manager_connect_udev(Manager *m) {
int r;
- /* udev does not initialize devices inside containers, so we rely on them being already
- * initialized before entering the container. */
- if (path_is_read_only_fs("/sys") > 0)
- return 0;
-
- r = sd_device_monitor_new(&m->device_monitor);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize device monitor: %m");
-
- r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
- if (r < 0)
- log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
-
- r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
- if (r < 0)
- return log_error_errno(r, "Could not add device monitor filter: %m");
-
- r = sd_device_monitor_attach_event(m->device_monitor, m->event);
- if (r < 0)
- return log_error_errno(r, "Failed to attach event to device monitor: %m");
-
- r = sd_device_monitor_start(m->device_monitor, manager_udev_process_link, m);
- if (r < 0)
- return log_error_errno(r, "Failed to start device monitor: %m");
-
- return 0;
-}
-
-int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- _cleanup_(route_freep) Route *tmp = NULL;
- Route *route = NULL;
- Manager *m = userdata;
- Link *link = NULL;
- uint32_t ifindex;
- uint16_t type;
- unsigned char table;
- int r;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
- return 0;
- } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) {
- log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type);
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex);
- if (r == -ENODATA) {
- log_debug("rtnl: received route message without ifindex, ignoring");
- return 0;
- } else if (r < 0) {
- log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m");
- return 0;
- } else if (ifindex <= 0) {
- log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex);
- return 0;
- }
-
- r = link_get(m, ifindex, &link);
- if (r < 0 || !link) {
- /* when enumerating we might be out of sync, but we will
- * get the route again, so just ignore it */
- if (!m->enumerating)
- log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex);
- return 0;
- }
-
- r = route_new(&tmp);
- if (r < 0)
- return log_oom();
-
- r = sd_rtnl_message_route_get_family(message, &tmp->family);
- if (r < 0) {
- log_link_warning(link, "rtnl: received route message without family, ignoring");
- return 0;
- } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
- log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family);
- return 0;
- }
-
- r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received route message without route protocol: %m");
- return 0;
- }
-
- switch (tmp->family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
- return 0;
- }
-
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
- return 0;
- }
-
- break;
-
- default:
- assert_not_reached("Received route message with unsupported address family");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_scope(message, &tmp->scope);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_tos(message, &tmp->tos);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_type(message, &tmp->type);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_route_get_table(message, &table);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m");
- return 0;
- }
- tmp->table = table;
-
- r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_enter_container(message, RTA_METRICS);
- if (r < 0 && r != -ENODATA) {
- log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m");
- return 0;
- }
- if (r >= 0) {
- r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_exit_container(message);
- if (r < 0) {
- log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m");
- return 0;
- }
- }
-
- (void) route_get(link, tmp, &route);
-
- if (DEBUG_LOGGING) {
- _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL,
- *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL;
- char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX],
- buf_protocol[ROUTE_PROTOCOL_STR_MAX];
-
- if (!in_addr_is_null(tmp->family, &tmp->dst)) {
- (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst);
- (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen);
- }
- if (!in_addr_is_null(tmp->family, &tmp->src))
- (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src);
- if (!in_addr_is_null(tmp->family, &tmp->gw))
- (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw);
- if (!in_addr_is_null(tmp->family, &tmp->prefsrc))
- (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc);
-
- log_link_debug(link,
- "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
- (!route && !link->manager->manage_foreign_routes) ? "Ignoring received foreign" :
- type == RTM_DELROUTE ? "Forgetting" :
- route ? "Received remembered" : "Remembering",
- strna(buf_dst), strempty(buf_dst_prefixlen),
- strna(buf_src), strna(buf_gw), strna(buf_prefsrc),
- format_route_scope(tmp->scope, buf_scope, sizeof buf_scope),
- format_route_table(tmp->table, buf_table, sizeof buf_table),
- format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol),
- strna(route_type_to_string(tmp->type)));
- }
-
- switch (type) {
- case RTM_NEWROUTE:
- if (!route && link->manager->manage_foreign_routes) {
- /* A route appeared that we did not request */
- r = route_add_foreign(link, tmp, &route);
- if (r < 0) {
- log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
- return 0;
- }
- }
-
- break;
-
- case RTM_DELROUTE:
- route_free(route);
- break;
-
- default:
- assert_not_reached("Received route message with invalid RTNL message type");
- }
-
- return 1;
-}
-
-static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
- int r;
-
- assert(message);
- assert(lladdr);
- assert(size);
- assert(str);
-
- *str = NULL;
-
- r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
- if (r >= 0) {
- *size = sizeof(lladdr->ip.in6);
- if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
- log_warning_errno(r, "Could not print lower address: %m");
- return r;
- }
-
- r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
- if (r >= 0) {
- *size = sizeof(lladdr->mac);
- *str = new(char, ETHER_ADDR_TO_STRING_MAX);
- if (!*str) {
- log_oom();
- return r;
- }
- ether_addr_to_string(&lladdr->mac, *str);
- return r;
- }
-
- r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
- if (r >= 0) {
- *size = sizeof(lladdr->ip.in);
- if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
- log_warning_errno(r, "Could not print lower address: %m");
- return r;
- }
-
- return r;
-}
-
-int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- Manager *m = userdata;
- Link *link = NULL;
- Neighbor *neighbor = NULL;
- int ifindex, family, r;
- uint16_t type, state;
- union in_addr_union in_addr = IN_ADDR_NULL;
- _cleanup_free_ char *addr_str = NULL;
- union lladdr_union lladdr;
- size_t lladdr_size = 0;
- _cleanup_free_ char *lladdr_str = NULL;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
- return 0;
- } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) {
- log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type);
- return 0;
- }
-
- r = sd_rtnl_message_neigh_get_state(message, &state);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m");
- return 0;
- } else if (!FLAGS_SET(state, NUD_PERMANENT)) {
- log_debug("rtnl: received non-static neighbor, ignoring.");
- return 0;
- }
-
- r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
- return 0;
- } else if (ifindex <= 0) {
- log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex);
- return 0;
- }
-
- r = link_get(m, ifindex, &link);
- if (r < 0 || !link) {
- /* when enumerating we might be out of sync, but we will get the neighbor again, so just
- * ignore it */
- if (!m->enumerating)
- log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
- return 0;
- }
-
- r = sd_rtnl_message_neigh_get_family(message, &family);
- if (r < 0) {
- log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
- return 0;
- } else if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family);
- return 0;
- }
-
- switch (family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- default:
- assert_not_reached("Received unsupported address family");
- }
-
- if (in_addr_to_string(family, &in_addr, &addr_str) < 0)
- log_link_warning_errno(link, r, "Could not print address: %m");
-
- r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
- return 0;
- }
-
- (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
-
- switch (type) {
- case RTM_NEWNEIGH:
- if (neighbor)
- log_link_debug(link, "Received remembered neighbor: %s->%s",
- strnull(addr_str), strnull(lladdr_str));
- else {
- /* A neighbor appeared that we did not request */
- r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
- if (r < 0) {
- log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
- strnull(addr_str), strnull(lladdr_str));
- return 0;
- } else
- log_link_debug(link, "Remembering foreign neighbor: %s->%s",
- strnull(addr_str), strnull(lladdr_str));
- }
-
- break;
-
- case RTM_DELNEIGH:
- if (neighbor) {
- log_link_debug(link, "Forgetting neighbor: %s->%s",
- strnull(addr_str), strnull(lladdr_str));
- (void) neighbor_free(neighbor);
- } else
- log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
- strnull(addr_str), strnull(lladdr_str));
-
- break;
-
- default:
- assert_not_reached("Received invalid RTNL message type");
- }
-
- return 1;
-}
-
-int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- _cleanup_free_ char *buf = NULL;
- Manager *m = userdata;
- Link *link = NULL;
- uint16_t type;
- unsigned char flags, prefixlen, scope;
- union in_addr_union in_addr = IN_ADDR_NULL;
- struct ifa_cacheinfo cinfo;
- Address *address = NULL;
- char valid_buf[FORMAT_TIMESPAN_MAX];
- const char *valid_str = NULL;
- int ifindex, family, r;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
- return 0;
- } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) {
- log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type);
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
- return 0;
- } else if (ifindex <= 0) {
- log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex);
- return 0;
- }
-
- r = link_get(m, ifindex, &link);
- if (r < 0 || !link) {
- /* when enumerating we might be out of sync, but we will get the address again, so just
- * ignore it */
- if (!m->enumerating)
- log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex);
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_family(message, &family);
- if (r < 0) {
- log_link_warning(link, "rtnl: received address message without family, ignoring.");
- return 0;
- } else if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", family);
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_scope(message, &scope);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_flags(message, &flags);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m");
- return 0;
- }
-
- switch (family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- default:
- assert_not_reached("Received unsupported address family");
- }
-
- r = in_addr_to_string(family, &in_addr, &buf);
- if (r < 0)
- log_link_warning_errno(link, r, "Could not print address: %m");
-
- r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
- if (r < 0 && r != -ENODATA) {
- log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
- return 0;
- } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
- valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
- cinfo.ifa_valid * USEC_PER_SEC,
- USEC_PER_SEC);
-
- (void) address_get(link, family, &in_addr, prefixlen, &address);
-
- switch (type) {
- case RTM_NEWADDR:
- if (address)
- log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)",
- strnull(buf), prefixlen,
- valid_str ? "for " : "forever", strempty(valid_str));
- else {
- /* An address appeared that we did not request */
- r = address_add_foreign(link, family, &in_addr, prefixlen, &address);
- if (r < 0) {
- log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m",
- strnull(buf), prefixlen);
- return 0;
- } else
- log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)",
- strnull(buf), prefixlen,
- valid_str ? "for " : "forever", strempty(valid_str));
- }
-
- /* address_update() logs internally, so we don't need to here. */
- r = address_update(address, flags, scope, &cinfo);
- if (r < 0)
- link_enter_failed(link);
-
- break;
-
- case RTM_DELADDR:
- if (address) {
- log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)",
- strnull(buf), prefixlen,
- valid_str ? "for " : "forever", strempty(valid_str));
- (void) address_drop(address);
- } else
- log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.",
- strnull(buf), prefixlen,
- valid_str ? "for " : "forever", strempty(valid_str));
-
- break;
-
- default:
- assert_not_reached("Received invalid RTNL message type");
- }
-
- return 1;
-}
-
-static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- Manager *m = userdata;
- Link *link = NULL;
- NetDev *netdev = NULL;
- uint16_t type;
- const char *name;
- int r, ifindex;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
- return 0;
- } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) {
- log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type);
- return 0;
- }
-
- r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
- if (r < 0) {
- log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m");
- return 0;
- } else if (ifindex <= 0) {
- log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex);
- return 0;
- }
-
- r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
- if (r < 0) {
- log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
- return 0;
- }
-
- (void) link_get(m, ifindex, &link);
- (void) netdev_get(m, name, &netdev);
-
- switch (type) {
- case RTM_NEWLINK:
- if (!link) {
- /* link is new, so add it */
- r = link_add(m, message, &link);
- if (r < 0) {
- log_warning_errno(r, "Could not process new link message, ignoring: %m");
- return 0;
- }
- }
-
- if (netdev) {
- /* netdev exists, so make sure the ifindex matches */
- r = netdev_set_ifindex(netdev, message);
- if (r < 0) {
- log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m");
- return 0;
- }
- }
-
- r = link_update(link, message);
- if (r < 0) {
- log_warning_errno(r, "Could not process link message, ignoring: %m");
- return 0;
- }
-
- break;
-
- case RTM_DELLINK:
- link_drop(link);
- netdev_drop(netdev);
-
- break;
-
- default:
- assert_not_reached("Received link message with invalid RTNL message type.");
- }
-
- return 1;
-}
-
-int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
- _cleanup_free_ char *from = NULL, *to = NULL;
- RoutingPolicyRule *rule = NULL;
- const char *iif = NULL, *oif = NULL;
- uint32_t suppress_prefixlen;
- Manager *m = userdata;
- unsigned flags;
- uint16_t type;
- int r;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
- return 0;
- } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) {
- log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type);
- return 0;
- }
-
- r = routing_policy_rule_new(&tmp);
- if (r < 0) {
- log_oom();
- return 0;
- }
-
- r = sd_rtnl_message_get_family(message, &tmp->family);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m");
- return 0;
- } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
- log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family);
- return 0;
- }
-
- switch (tmp->family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
- return 0;
- } else if (r >= 0) {
- r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
- return 0;
- }
- }
-
- r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
- return 0;
- } else if (r >= 0) {
- r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
- return 0;
- }
- }
-
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
- return 0;
- } else if (r >= 0) {
- r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
- return 0;
- }
- }
-
- r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
- return 0;
- } else if (r >= 0) {
- r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
- return 0;
- }
- }
-
- break;
-
- default:
- assert_not_reached("Received rule message with unsupported address family");
- }
-
- r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
- if (r < 0) {
- log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m");
- return 0;
- }
- tmp->invert_rule = flags & FIB_RULE_INVERT;
-
- r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
- return 0;
- }
- r = free_and_strdup(&tmp->iif, iif);
- if (r < 0)
- return log_oom();
-
- r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
- return 0;
- }
- r = free_and_strdup(&tmp->oif, oif);
- if (r < 0)
- return log_oom();
-
- r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read(message, FRA_UID_RANGE, sizeof(tmp->uid_range), &tmp->uid_range);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_PREFIXLEN, &suppress_prefixlen);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
+ /* udev does not initialize devices inside containers, so we rely on them being already
+ * initialized before entering the container. */
+ if (path_is_read_only_fs("/sys") > 0)
return 0;
- }
- if (r >= 0)
- tmp->suppress_prefixlen = (int) suppress_prefixlen;
- (void) routing_policy_rule_get(m, tmp, &rule);
+ r = sd_device_monitor_new(&m->device_monitor);
+ if (r < 0)
+ return log_error_errno(r, "Failed to initialize device monitor: %m");
- if (DEBUG_LOGGING) {
- (void) in_addr_to_string(tmp->family, &tmp->from, &from);
- (void) in_addr_to_string(tmp->family, &tmp->to, &to);
- }
+ r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
+ if (r < 0)
+ log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
- switch (type) {
- case RTM_NEWRULE:
- if (rule)
- log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
- tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
- else {
- log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
- tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
- r = routing_policy_rule_add_foreign(m, tmp, &rule);
- if (r < 0) {
- log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
- return 0;
- }
- }
- break;
- case RTM_DELRULE:
- if (rule) {
- log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
- tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
- routing_policy_rule_free(rule);
- } else
- log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.",
- tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
- break;
+ r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
+ if (r < 0)
+ return log_error_errno(r, "Could not add device monitor filter: %m");
- default:
- assert_not_reached("Received invalid RTNL message type");
- }
+ r = sd_device_monitor_attach_event(m->device_monitor, m->event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach event to device monitor: %m");
- return 1;
+ r = sd_device_monitor_start(m->device_monitor, manager_udev_process_link, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start device monitor: %m");
+
+ return 0;
}
-int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- _cleanup_(nexthop_freep) NextHop *tmp = NULL;
- _cleanup_free_ char *gateway = NULL;
- NextHop *nexthop = NULL;
- Manager *m = userdata;
+static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
Link *link = NULL;
+ NetDev *netdev = NULL;
uint16_t type;
- int r;
+ const char *name;
+ int r, ifindex;
assert(rtnl);
assert(message);
if (sd_netlink_message_is_error(message)) {
r = sd_netlink_message_get_errno(message);
if (r < 0)
- log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring");
+ log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring");
return 0;
}
r = sd_netlink_message_get_type(message, &type);
if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
return 0;
- } else if (!IN_SET(type, RTM_NEWNEXTHOP, RTM_DELNEXTHOP)) {
- log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type);
+ } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) {
+ log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type);
return 0;
}
- r = nexthop_new(&tmp);
- if (r < 0)
- return log_oom();
-
- r = sd_rtnl_message_get_family(message, &tmp->family);
+ r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0) {
- log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m");
- return 0;
- } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
- log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family);
- return 0;
- }
-
- switch (tmp->family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
- return 0;
- }
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
- return 0;
- }
- break;
-
- default:
- assert_not_reached("Received rule message with unsupported address family");
- }
-
- r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m");
- return 0;
- }
-
- r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif);
- if (r < 0 && r != -ENODATA) {
- log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m");
+ log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m");
return 0;
- } else if (tmp->oif <= 0) {
- log_warning("rtnl: received nexthop message with invalid ifindex %d, ignoring.", tmp->oif);
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex);
return 0;
}
- r = link_get(m, tmp->oif, &link);
- if (r < 0 || !link) {
- if (!m->enumerating)
- log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif);
+ r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
return 0;
}
- (void) nexthop_get(link, tmp, &nexthop);
-
- if (DEBUG_LOGGING)
- (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway);
+ (void) link_get(m, ifindex, &link);
+ (void) netdev_get(m, name, &netdev);
switch (type) {
- case RTM_NEWNEXTHOP:
- if (nexthop)
- log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
- else {
- log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
- r = nexthop_add_foreign(link, tmp, &nexthop);
+ case RTM_NEWLINK:
+ if (!link) {
+ /* link is new, so add it */
+ r = link_add(m, message, &link);
+ if (r < 0) {
+ log_warning_errno(r, "Could not process new link message, ignoring: %m");
+ return 0;
+ }
+ }
+
+ if (netdev) {
+ /* netdev exists, so make sure the ifindex matches */
+ r = netdev_set_ifindex(netdev, message);
if (r < 0) {
- log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
+ log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m");
return 0;
}
}
+
+ r = link_update(link, message);
+ if (r < 0) {
+ log_warning_errno(r, "Could not process link message, ignoring: %m");
+ return 0;
+ }
+
break;
- case RTM_DELNEXTHOP:
- if (nexthop) {
- log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id);
- nexthop_free(nexthop);
- } else
- log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.",
- strna(gateway), tmp->oif, tmp->id);
+
+ case RTM_DELLINK:
+ link_drop(link);
+ netdev_drop(netdev);
+
break;
default:
- assert_not_reached("Received invalid RTNL message type");
+ assert_not_reached("Received link message with invalid RTNL message type.");
}
return 1;
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
+ r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
+ r = netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
if (r < 0)
return r;
if (r < 0)
return r;
- r = setup_default_address_pool(m);
+ r = address_pool_setup_default(m);
if (r < 0)
return r;
}
void manager_free(Manager *m) {
- AddressPool *pool;
Link *link;
if (!m)
free(m->state_file);
HASHMAP_FOREACH(link, m->links)
- (void) link_stop_clients(link, true);
+ (void) link_stop_engines(link, true);
m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
- while ((pool = m->address_pools))
- address_pool_free(pool);
+ ordered_set_free_free(m->address_pools);
/* 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_foreign = set_free(m->rules_foreign);
set_free(m->rules_saved);
+ m->routes = set_free(m->routes);
+ m->routes_foreign = set_free(m->routes_foreign);
+
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
sd_resolve_unref(m->resolve);
return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false);
}
-int manager_rtnl_enumerate_links(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *link;
+static int manager_enumerate_internal(
+ Manager *m,
+ sd_netlink_message *req,
+ int (*process)(sd_netlink *, sd_netlink_message *, Manager *),
+ const char *name) {
+
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
int r;
assert(m);
assert(m->rtnl);
-
- r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
- if (r < 0)
- return r;
+ assert(req);
+ assert(process);
r = sd_netlink_message_request_dump(req, true);
if (r < 0)
return r;
r = sd_netlink_call(m->rtnl, req, 0, &reply);
- if (r < 0)
+ if (r < 0) {
+ if (r == -EOPNOTSUPP && name) {
+ log_debug_errno(r, "%s are not supported by the kernel. Ignoring.", name);
+ return 0;
+ }
+
return r;
+ }
- for (link = reply; link; link = sd_netlink_message_next(link)) {
+ for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
int k;
m->enumerating = true;
- k = manager_rtnl_process_link(m->rtnl, link, m);
- if (k < 0)
+ k = process(m->rtnl, reply_one, m);
+ if (k < 0 && r >= 0)
r = k;
m->enumerating = false;
return r;
}
-int manager_rtnl_enumerate_addresses(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *addr;
+static int manager_enumerate_links(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
assert(m->rtnl);
- r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
- if (r < 0)
- return r;
-
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_netlink_call(m->rtnl, req, 0, &reply);
+ r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
return r;
- for (addr = reply; addr; addr = sd_netlink_message_next(addr)) {
- int k;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_link, NULL);
+}
- m->enumerating = true;
+static int manager_enumerate_addresses(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
- k = manager_rtnl_process_address(m->rtnl, addr, m);
- if (k < 0)
- r = k;
+ assert(m);
+ assert(m->rtnl);
- m->enumerating = false;
- }
+ r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
+ if (r < 0)
+ return r;
- return r;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_address, NULL);
}
-int manager_rtnl_enumerate_neighbors(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *neigh;
+static int manager_enumerate_neighbors(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
if (r < 0)
return r;
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_netlink_call(m->rtnl, req, 0, &reply);
- if (r < 0)
- return r;
-
- for (neigh = reply; neigh; neigh = sd_netlink_message_next(neigh)) {
- int k;
-
- m->enumerating = true;
-
- k = manager_rtnl_process_neighbor(m->rtnl, neigh, m);
- if (k < 0)
- r = k;
-
- m->enumerating = false;
- }
-
- return r;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_neighbor, NULL);
}
-int manager_rtnl_enumerate_routes(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *route;
+static int manager_enumerate_routes(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
if (r < 0)
return r;
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_netlink_call(m->rtnl, req, 0, &reply);
- if (r < 0)
- return r;
-
- for (route = reply; route; route = sd_netlink_message_next(route)) {
- int k;
-
- m->enumerating = true;
-
- k = manager_rtnl_process_route(m->rtnl, route, m);
- if (k < 0)
- r = k;
-
- m->enumerating = false;
- }
-
- return r;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_route, NULL);
}
-int manager_rtnl_enumerate_rules(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *rule;
+static int manager_enumerate_rules(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
if (r < 0)
return r;
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_netlink_call(m->rtnl, req, 0, &reply);
- if (r < 0) {
- if (r == -EOPNOTSUPP) {
- log_debug("FIB Rules are not supported by the kernel. Ignoring.");
- return 0;
- }
-
- return r;
- }
-
- for (rule = reply; rule; rule = sd_netlink_message_next(rule)) {
- int k;
-
- m->enumerating = true;
-
- k = manager_rtnl_process_rule(m->rtnl, rule, m);
- if (k < 0)
- r = k;
-
- m->enumerating = false;
- }
-
- return r;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_rule, "Routing policy rules");
}
-int manager_rtnl_enumerate_nexthop(Manager *m) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *nexthop;
+static int manager_enumerate_nexthop(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
if (r < 0)
return r;
- r = sd_netlink_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_netlink_call(m->rtnl, req, 0, &reply);
- if (r < 0) {
- if (r == -EOPNOTSUPP) {
- log_debug("Nexthop are not supported by the kernel. Ignoring.");
- return 0;
- }
-
- return r;
- }
-
- for (nexthop = reply; nexthop; nexthop = sd_netlink_message_next(nexthop)) {
- int k;
-
- m->enumerating = true;
+ return manager_enumerate_internal(m, req, manager_rtnl_process_nexthop, "Nexthop rules");
+}
- k = manager_rtnl_process_nexthop(m->rtnl, nexthop, m);
- if (k < 0)
- r = k;
+int manager_enumerate(Manager *m) {
+ int r;
- m->enumerating = false;
- }
+ r = manager_enumerate_links(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate links: %m");
- return r;
-}
+ r = manager_enumerate_addresses(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate addresses: %m");
-int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
- AddressPool *p;
- int r;
+ r = manager_enumerate_neighbors(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate neighbors: %m");
- assert(m);
- assert(prefixlen > 0);
- assert(found);
+ r = manager_enumerate_routes(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate routes: %m");
- LIST_FOREACH(address_pools, p, m->address_pools) {
- if (p->family != family)
- continue;
+ r = manager_enumerate_rules(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate routing policy rules: %m");
- r = address_pool_acquire(p, prefixlen, found);
- if (r != 0)
- return r;
- }
+ r = manager_enumerate_nexthop(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate nexthop rules: %m");
return 0;
}
return 0;
}
-
-int manager_request_product_uuid(Manager *m, Link *link) {
- int r;
-
- assert(m);
-
- if (m->has_product_uuid)
- return 0;
-
- log_debug("Requesting product UUID");
-
- if (link) {
- DUID *duid;
-
- assert_se(duid = link_get_duid(link));
-
- r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
- if (r < 0)
- return log_oom();
- if (r > 0)
- link_ref(link);
-
- r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
- if (r < 0)
- return log_oom();
- }
-
- if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
- log_debug("Not connected to system bus, requesting product UUID later.");
- return 0;
- }
-
- r = sd_bus_call_method_async(
- m->bus,
- NULL,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "GetProductUUID",
- get_product_uuid_handler,
- m,
- "b",
- false);
- if (r < 0)
- return log_warning_errno(r, "Failed to get product UUID: %m");
-
- return 0;
-}
#include "dhcp-identifier.h"
#include "hashmap.h"
-#include "list.h"
-#include "time-util.h"
-
-#include "networkd-address-pool.h"
#include "networkd-link.h"
#include "networkd-network.h"
+#include "ordered-set.h"
+#include "set.h"
+#include "time-util.h"
struct Manager {
sd_netlink *rtnl;
OrderedHashmap *networks;
Hashmap *dhcp6_prefixes;
Set *dhcp6_pd_prefixes;
- LIST_HEAD(AddressPool, address_pools);
+ OrderedSet *address_pools;
usec_t network_dirs_ts_usec;
Set *rules_foreign;
Set *rules_saved;
+ /* Manager stores routes without RTA_OIF attribute. */
+ Set *routes;
+ Set *routes_foreign;
+
/* For link speed meter*/
bool use_speed_meter;
sd_event_source *speed_meter_event_source;
int manager_load_config(Manager *m);
bool manager_should_reload(Manager *m);
-int manager_rtnl_enumerate_links(Manager *m);
-int manager_rtnl_enumerate_addresses(Manager *m);
-int manager_rtnl_enumerate_neighbors(Manager *m);
-int manager_rtnl_enumerate_routes(Manager *m);
-int manager_rtnl_enumerate_rules(Manager *m);
-int manager_rtnl_enumerate_nexthop(Manager *m);
-
-int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata);
-int manager_rtnl_process_neighbor(sd_netlink *nl, sd_netlink_message *message, void *userdata);
-int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata);
-int manager_rtnl_process_rule(sd_netlink *nl, sd_netlink_message *message, void *userdata);
-int manager_rtnl_process_nexthop(sd_netlink *nl, sd_netlink_message *message, void *userdata);
+int manager_enumerate(Manager *m);
void manager_dirty(Manager *m);
-int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
-
Link* manager_find_uplink(Manager *m, Link *exclude);
int manager_set_hostname(Manager *m, const char *hostname);
int manager_set_timezone(Manager *m, const char *timezone);
-int manager_request_product_uuid(Manager *m, Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
#include <net/if.h>
#include "netlink-util.h"
+#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-mdb.h"
+#include "networkd-network.h"
#include "string-util.h"
#include "vlan-util.h"
#define STATIC_MDB_ENTRIES_PER_NETWORK_MAX 1024U
+/* remove MDB entry. */
+MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) {
+ if (!mdb_entry)
+ return NULL;
+
+ if (mdb_entry->network) {
+ assert(mdb_entry->section);
+ hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section);
+ }
+
+ network_config_section_free(mdb_entry->section);
+
+ return mfree(mdb_entry);
+}
+
+DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free);
+
/* create a new MDB entry or get an existing one. */
static int mdb_entry_new_static(
Network *network,
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
+ assert(filename);
+ assert(section_line > 0);
- /* search entry in hashmap first. */
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- mdb_entry = hashmap_get(network->mdb_entries_by_section, n);
- if (mdb_entry) {
- *ret = TAKE_PTR(mdb_entry);
- return 0;
- }
+ /* search entry in hashmap first. */
+ mdb_entry = hashmap_get(network->mdb_entries_by_section, n);
+ if (mdb_entry) {
+ *ret = TAKE_PTR(mdb_entry);
+ return 0;
}
- if (network->n_static_mdb_entries >= STATIC_MDB_ENTRIES_PER_NETWORK_MAX)
+ if (hashmap_size(network->mdb_entries_by_section) >= STATIC_MDB_ENTRIES_PER_NETWORK_MAX)
return -E2BIG;
/* allocate space for an MDB entry. */
/* init MDB structure. */
*mdb_entry = (MdbEntry) {
.network = network,
+ .section = TAKE_PTR(n),
};
- LIST_PREPEND(static_mdb_entries, network->static_mdb_entries, mdb_entry);
- network->n_static_mdb_entries++;
-
- if (filename) {
- mdb_entry->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->mdb_entries_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->mdb_entries_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->mdb_entries_by_section, mdb_entry->section, mdb_entry);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->mdb_entries_by_section, mdb_entry->section, mdb_entry);
+ if (r < 0)
+ return r;
/* return allocated MDB structure. */
*ret = TAKE_PTR(mdb_entry);
-
return 0;
}
-/* remove and MDB entry. */
-MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) {
- if (!mdb_entry)
- return NULL;
-
- if (mdb_entry->network) {
- LIST_REMOVE(static_mdb_entries, mdb_entry->network->static_mdb_entries, mdb_entry);
- assert(mdb_entry->network->n_static_mdb_entries > 0);
- mdb_entry->network->n_static_mdb_entries--;
-
- if (mdb_entry->section)
- hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section);
- }
-
- network_config_section_free(mdb_entry->section);
-
- return mfree(mdb_entry);
-}
-
static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
if (!link->network)
return 0;
- if (LIST_IS_EMPTY(link->network->static_mdb_entries))
+ if (hashmap_isempty(link->network->mdb_entries_by_section))
goto finish;
if (!link_has_carrier(link))
goto finish;
}
- LIST_FOREACH(static_mdb_entries, mdb_entry, link->network->static_mdb_entries) {
+ HASHMAP_FOREACH(mdb_entry, link->network->mdb_entries_by_section) {
r = mdb_entry_configure(link, mdb_entry);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add MDB entry to multicast group database: %m");
return 0;
}
+static int mdb_entry_verify(MdbEntry *mdb_entry) {
+ if (section_is_invalid(mdb_entry->section))
+ return -EINVAL;
+
+ if (mdb_entry->family == AF_UNSPEC)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: [BridgeMDB] section without MulticastGroupAddress= field configured. "
+ "Ignoring [BridgeMDB] section from line %u.",
+ mdb_entry->section->filename, mdb_entry->section->line);
+
+ if (!in_addr_is_multicast(mdb_entry->family, &mdb_entry->group_addr))
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: MulticastGroupAddress= is not a multicast address. "
+ "Ignoring [BridgeMDB] section from line %u.",
+ mdb_entry->section->filename, mdb_entry->section->line);
+
+ if (mdb_entry->family == AF_INET) {
+ if (in4_addr_is_local_multicast(&mdb_entry->group_addr.in))
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: MulticastGroupAddress= is a local multicast address. "
+ "Ignoring [BridgeMDB] section from line %u.",
+ mdb_entry->section->filename, mdb_entry->section->line);
+ } else {
+ if (in6_addr_is_link_local_all_nodes(&mdb_entry->group_addr.in6))
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: MulticastGroupAddress= is the multicast all nodes address. "
+ "Ignoring [BridgeMDB] section from line %u.",
+ mdb_entry->section->filename, mdb_entry->section->line);
+ }
+
+ return 0;
+}
+
+void network_drop_invalid_mdb_entries(Network *network) {
+ MdbEntry *mdb_entry;
+
+ assert(network);
+
+ HASHMAP_FOREACH(mdb_entry, network->mdb_entries_by_section)
+ if (mdb_entry_verify(mdb_entry) < 0)
+ mdb_entry_free(mdb_entry);
+}
+
/* parse the VLAN Id from config files. */
int config_parse_mdb_vlan_id(
const char *unit,
return 0;
}
-
-int mdb_entry_verify(MdbEntry *mdb_entry) {
- if (section_is_invalid(mdb_entry->section))
- return -EINVAL;
-
- if (mdb_entry->family == AF_UNSPEC)
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: [BridgeMDB] section without MulticastGroupAddress= field configured. "
- "Ignoring [BridgeMDB] section from line %u.",
- mdb_entry->section->filename, mdb_entry->section->line);
-
- if (!in_addr_is_multicast(mdb_entry->family, &mdb_entry->group_addr))
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: MulticastGroupAddress= is not a multicast address. "
- "Ignoring [BridgeMDB] section from line %u.",
- mdb_entry->section->filename, mdb_entry->section->line);
-
- if (mdb_entry->family == AF_INET) {
- if (in4_addr_is_local_multicast(&mdb_entry->group_addr.in))
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: MulticastGroupAddress= is a local multicast address. "
- "Ignoring [BridgeMDB] section from line %u.",
- mdb_entry->section->filename, mdb_entry->section->line);
- } else {
- if (in6_addr_is_link_local_all_nodes(&mdb_entry->group_addr.in6))
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: MulticastGroupAddress= is the multicast all nodes address. "
- "Ignoring [BridgeMDB] section from line %u.",
- mdb_entry->section->filename, mdb_entry->section->line);
- }
-
- return 0;
-}
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <inttypes.h>
+
#include "conf-parser.h"
-#include "list.h"
-#include "macro.h"
+#include "in-addr-util.h"
#include "networkd-util.h"
typedef struct Network Network;
-typedef struct MdbEntry MdbEntry;
typedef struct Link Link;
-typedef struct NetworkConfigSection NetworkConfigSection;
-struct MdbEntry {
+typedef struct MdbEntry {
Network *network;
NetworkConfigSection *section;
int family;
union in_addr_union group_addr;
uint16_t vlan_id;
+} MdbEntry;
- LIST_FIELDS(MdbEntry, static_mdb_entries);
-};
-
-int mdb_entry_verify(MdbEntry *mdb_entry);
MdbEntry *mdb_entry_free(MdbEntry *mdb_entry);
-int link_set_bridge_mdb(Link *link);
-DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free);
+void network_drop_invalid_mdb_entries(Network *network);
+
+int link_set_bridge_mdb(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address);
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id);
Copyright © 2014 Intel Corporation. All rights reserved.
***/
-#include <netinet/icmp6.h>
#include <arpa/inet.h>
+#include <netinet/icmp6.h>
+#include <linux/if.h>
#include "sd-ndisc.h"
#include "missing_network.h"
+#include "networkd-address.h"
#include "networkd-dhcp6.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
-#include "networkd-route.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
+bool link_ipv6_accept_ra_enabled(Link *link) {
+ assert(link);
+
+ if (!socket_ipv6_is_supported())
+ return false;
+
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ if (!link_ipv6ll_enabled(link))
+ return false;
+
+ assert(link->network->ipv6_accept_ra >= 0);
+ return link->network->ipv6_accept_ra;
+}
+
+void network_adjust_ipv6_accept_ra(Network *network) {
+ assert(network);
+
+ if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
+ if (network->ipv6_accept_ra > 0)
+ log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
+ "Disabling IPv6AcceptRA=.", network->filename);
+ network->ipv6_accept_ra = false;
+ }
+
+ if (network->ipv6_accept_ra < 0)
+ /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
+ network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
+}
+
static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force);
static int ndisc_address_callback(Address *address) {
SET_FOREACH(nr, link->ndisc_routes)
if (nr->marked && IN6_ARE_ADDR_EQUAL(&nr->router, router)) {
- k = route_remove(nr->route, link, NULL);
+ k = route_remove(nr->route, NULL, link, NULL);
if (k < 0)
r = k;
}
return 1;
}
- r = link_request_set_routes(link);
+ r = link_set_routes(link);
if (r < 0) {
link_enter_failed(link);
return 1;
union in_addr_union gateway;
uint16_t lifetime;
unsigned preference;
- uint32_t mtu;
+ uint32_t table, mtu;
usec_t time_now;
int r;
else if (r < 0)
return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
+ table = link_get_ipv6_accept_ra_route_table(link);
+
r = route_new(&route);
if (r < 0)
return log_oom();
route->family = AF_INET6;
- route->table = link_get_ipv6_accept_ra_route_table(link);
+ route->table = table;
route->priority = link->network->dhcp6_route_metric;
route->protocol = RTPROT_RA;
route->pref = preference;
+ route->gw_family = AF_INET6;
route->gw = gateway;
route->lifetime = time_now + lifetime * USEC_PER_SEC;
route->mtu = mtu;
return log_link_error_errno(link, r, "Could not set default route: %m");
Route *route_gw;
- LIST_FOREACH(routes, route_gw, link->network->static_routes) {
- if (!route_gw->gateway_from_dhcp)
+ HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
+ if (!route_gw->gateway_from_dhcp_or_ra)
continue;
- if (route_gw->family != AF_INET6)
+ if (route_gw->gw_family != AF_INET6)
continue;
route_gw->gw = gateway;
+ if (!route_gw->table_set)
+ route_gw->table = table;
+ if (!route_gw->priority_set)
+ route_gw->priority = link->network->dhcp6_route_metric;
+ if (!route_gw->protocol_set)
+ route_gw->protocol = RTPROT_RA;
+ if (!route_gw->pref_set)
+ route->pref = preference;
+ route_gw->lifetime = time_now + lifetime * USEC_PER_SEC;
+ if (route_gw->mtu == 0)
+ route_gw->mtu = mtu;
r = ndisc_route_configure(route_gw, link, rt);
if (r < 0)
SET_FOREACH(a, addresses) {
Address *existing_address;
+ address->in_addr.in6 = *a;
+
/* see RFC4862 section 5.5.3.e */
- r = address_get(link, AF_INET6, (union in_addr_union *) a, prefixlen, &existing_address);
+ r = address_get(link, address, &existing_address);
if (r > 0) {
lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
if (address->cinfo.ifa_valid == 0)
continue;
- address->in_addr.in6 = *a;
-
r = ndisc_address_configure(address, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
route->protocol = RTPROT_RA;
route->pref = preference;
route->gw.in6 = gateway;
+ route->gw_family = AF_INET6;
route->dst_prefixlen = prefixlen;
route->lifetime = time_now + lifetime * USEC_PER_SEC;
else {
log_link_debug(link, "Setting SLAAC addresses.");
- /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
- * Before they are called, the related flags must be cleared. Otherwise, the link
- * becomes configured state before routes are configured. */
+ /* 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;
}
assert(link);
- r = sd_ndisc_new(&link->ndisc);
- if (r < 0)
- return r;
+ if (!link_ipv6_accept_ra_enabled(link))
+ return 0;
- r = sd_ndisc_attach_event(link->ndisc, NULL, 0);
- if (r < 0)
- return r;
+ if (!link->ndisc) {
+ r = sd_ndisc_new(&link->ndisc);
+ if (r < 0)
+ return r;
+
+ r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
+ if (r < 0)
+ return r;
+ }
r = sd_ndisc_set_mac(link->ndisc, &link->mac);
if (r < 0)
return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));
}
+bool link_ipv6_accept_ra_enabled(Link *link);
+
+void network_adjust_ipv6_accept_ra(Network *network);
+
int ndisc_configure(Link *link);
void ndisc_vacuum(Link *link);
void ndisc_flush(Link *link);
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include "sd-netlink.h"
-
#include "alloc-util.h"
-#include "conf-parser.h"
-#include "ether-addr-util.h"
#include "hashmap.h"
-#include "in-addr-util.h"
#include "netlink-util.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-neighbor.h"
+#include "networkd-network.h"
#include "set.h"
-void neighbor_free(Neighbor *neighbor) {
+Neighbor *neighbor_free(Neighbor *neighbor) {
if (!neighbor)
- return;
+ return NULL;
if (neighbor->network) {
- LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor);
- assert(neighbor->network->n_neighbors > 0);
- neighbor->network->n_neighbors--;
-
- if (neighbor->section)
- hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
+ assert(neighbor->section);
+ hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
}
network_config_section_free(neighbor->section);
set_remove(neighbor->link->neighbors_foreign, neighbor);
}
- free(neighbor);
+ return mfree(neighbor);
}
+DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
+
static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- neighbor = hashmap_get(network->neighbors_by_section, n);
- if (neighbor) {
- *ret = TAKE_PTR(neighbor);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ neighbor = hashmap_get(network->neighbors_by_section, n);
+ if (neighbor) {
+ *ret = TAKE_PTR(neighbor);
+ return 0;
}
neighbor = new(Neighbor, 1);
*neighbor = (Neighbor) {
.network = network,
.family = AF_UNSPEC,
+ .section = TAKE_PTR(n),
};
- LIST_APPEND(neighbors, network->neighbors, neighbor);
- network->n_neighbors++;
+ r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- if (filename) {
- neighbor->section = TAKE_PTR(n);
+ r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor);
+ if (r < 0)
+ return r;
- r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops);
- if (r < 0)
+ *ret = TAKE_PTR(neighbor);
+ return 0;
+}
+
+static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
+ assert(neighbor);
+
+ siphash24_compress(&neighbor->family, sizeof(neighbor->family), state);
+ siphash24_compress(&neighbor->lladdr_size, sizeof(neighbor->lladdr_size), state);
+
+ switch (neighbor->family) {
+ case AF_INET:
+ case AF_INET6:
+ /* Equality of neighbors are given by the pair (addr,lladdr) */
+ siphash24_compress(&neighbor->in_addr, FAMILY_ADDRESS_SIZE(neighbor->family), state);
+ break;
+ default:
+ /* treat any other address family as AF_UNSPEC */
+ break;
+ }
+
+ siphash24_compress(&neighbor->lladdr, neighbor->lladdr_size, state);
+}
+
+static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
+ int r;
+
+ r = CMP(a->family, b->family);
+ if (r != 0)
+ return r;
+
+ r = CMP(a->lladdr_size, b->lladdr_size);
+ if (r != 0)
+ return r;
+
+ switch (a->family) {
+ case AF_INET:
+ case AF_INET6:
+ r = memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family));
+ if (r != 0)
return r;
+ }
+
+ return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size);
+}
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free);
+
+static int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) {
+ Neighbor *existing;
+
+ assert(link);
+ assert(in);
+
+ existing = set_get(link->neighbors, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 1;
+ }
+
+ existing = set_get(link->neighbors_foreign, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int neighbor_add_internal(Link *link, Set **neighbors, const Neighbor *in, Neighbor **ret) {
+ _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
+ int r;
+
+ assert(link);
+ assert(neighbors);
+ assert(in);
- r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor);
+ neighbor = new(Neighbor, 1);
+ if (!neighbor)
+ return -ENOMEM;
+
+ *neighbor = (Neighbor) {
+ .family = in->family,
+ .in_addr = in->in_addr,
+ .lladdr = in->lladdr,
+ .lladdr_size = in->lladdr_size,
+ };
+
+ r = set_ensure_put(neighbors, &neighbor_hash_ops, neighbor);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EEXIST;
+
+ neighbor->link = link;
+
+ if (ret)
+ *ret = neighbor;
+
+ TAKE_PTR(neighbor);
+ return 0;
+}
+
+static int neighbor_add(Link *link, const Neighbor *in, Neighbor **ret) {
+ Neighbor *neighbor;
+ int r;
+
+ r = neighbor_get(link, in, &neighbor);
+ if (r == -ENOENT) {
+ /* Neighbor doesn't exist, make a new one */
+ r = neighbor_add_internal(link, &link->neighbors, in, &neighbor);
+ if (r < 0)
+ return r;
+ } else if (r == 0) {
+ /* Neighbor is foreign, claim it as recognized */
+ r = set_ensure_put(&link->neighbors, &neighbor_hash_ops, neighbor);
if (r < 0)
return r;
- }
- *ret = TAKE_PTR(neighbor);
+ set_remove(link->neighbors_foreign, neighbor);
+ } else if (r == 1) {
+ /* Neighbor already exists */
+ } else
+ return r;
+ if (ret)
+ *ret = neighbor;
return 0;
}
+static int neighbor_add_foreign(Link *link, const Neighbor *in, Neighbor **ret) {
+ return neighbor_add_internal(link, &link->neighbors_foreign, in, ret);
+}
+
+static bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) {
+ if (n1 == n2)
+ return true;
+
+ if (!n1 || !n2)
+ return false;
+
+ return neighbor_compare_func(n1, n2) == 0;
+}
+
static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
return 1;
}
-int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
+static int neighbor_configure(Neighbor *neighbor, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link->manager->rtnl);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
- link->ifindex, neighbor->family);
+ link->ifindex, neighbor->family);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWNEIGH message: %m");
if (r < 0)
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, neighbor_configure_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link->neighbor_messages++;
link_ref(link);
- r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL);
+ r = neighbor_add(link, neighbor, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not add neighbor: %m");
return 0;
}
+int link_set_neighbors(Link *link) {
+ Neighbor *neighbor;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->state != _LINK_STATE_INVALID);
+
+ link->neighbors_configured = false;
+
+ HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) {
+ r = neighbor_configure(neighbor, link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set neighbor: %m");
+ }
+
+ if (link->neighbor_messages == 0) {
+ link->neighbors_configured = true;
+ link_check_ready(link);
+ } else {
+ log_link_debug(link, "Setting neighbors");
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ }
+
+ return 0;
+}
+
static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
return 1;
}
-int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
+static int neighbor_remove(Neighbor *neighbor, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link->manager->rtnl);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH,
- link->ifindex, neighbor->family);
+ link->ifindex, neighbor->family);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELNEIGH message: %m");
if (r < 0)
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, neighbor_remove_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return 0;
}
-static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
+static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) {
+ Neighbor *net_neighbor;
+
+ assert(link);
assert(neighbor);
- siphash24_compress(&neighbor->family, sizeof(neighbor->family), state);
- siphash24_compress(&neighbor->lladdr_size, sizeof(neighbor->lladdr_size), state);
+ if (!link->network)
+ return false;
- switch (neighbor->family) {
- case AF_INET:
- case AF_INET6:
- /* Equality of neighbors are given by the pair (addr,lladdr) */
- siphash24_compress(&neighbor->in_addr, FAMILY_ADDRESS_SIZE(neighbor->family), state);
- break;
- default:
- /* treat any other address family as AF_UNSPEC */
- break;
- }
+ HASHMAP_FOREACH(net_neighbor, link->network->neighbors_by_section)
+ if (neighbor_equal(net_neighbor, neighbor))
+ return true;
- siphash24_compress(&neighbor->lladdr, neighbor->lladdr_size, state);
+ return false;
}
-static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
+int link_drop_foreign_neighbors(Link *link) {
+ Neighbor *neighbor;
int r;
- r = CMP(a->family, b->family);
- if (r != 0)
- return r;
+ assert(link);
- r = CMP(a->lladdr_size, b->lladdr_size);
- if (r != 0)
- return r;
+ SET_FOREACH(neighbor, link->neighbors_foreign)
+ if (link_is_neighbor_configured(link, neighbor)) {
+ r = neighbor_add(link, neighbor, NULL);
+ if (r < 0)
+ return r;
+ } else {
+ r = neighbor_remove(neighbor, link);
+ if (r < 0)
+ return r;
+ }
- switch (a->family) {
- case AF_INET:
- case AF_INET6:
- r = memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family));
- if (r != 0)
- return r;
+ return 0;
+}
+
+int link_drop_neighbors(Link *link) {
+ Neighbor *neighbor;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(neighbor, link->neighbors) {
+ k = neighbor_remove(neighbor, link);
+ if (k < 0 && r >= 0)
+ r = k;
}
- return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size);
+ return r;
}
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free);
-
-int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
- Neighbor neighbor, *existing;
+static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
+ int r;
- assert(link);
- assert(addr);
+ assert(message);
assert(lladdr);
+ assert(size);
+ assert(str);
- neighbor = (Neighbor) {
- .family = family,
- .in_addr = *addr,
- .lladdr = *lladdr,
- .lladdr_size = lladdr_size,
- };
+ *str = NULL;
- existing = set_get(link->neighbors, &neighbor);
- if (existing) {
- if (ret)
- *ret = existing;
- return 1;
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
+ if (r >= 0) {
+ *size = sizeof(lladdr->ip.in6);
+ if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
+ log_warning_errno(r, "Could not print lower address: %m");
+ return r;
}
- existing = set_get(link->neighbors_foreign, &neighbor);
- if (existing) {
- if (ret)
- *ret = existing;
- return 0;
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
+ if (r >= 0) {
+ *size = sizeof(lladdr->mac);
+ *str = new(char, ETHER_ADDR_TO_STRING_MAX);
+ if (!*str) {
+ log_oom();
+ return r;
+ }
+ ether_addr_to_string(&lladdr->mac, *str);
+ return r;
}
- return -ENOENT;
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
+ if (r >= 0) {
+ *size = sizeof(lladdr->ip.in);
+ if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
+ log_warning_errno(r, "Could not print lower address: %m");
+ return r;
+ }
+
+ return r;
}
-static int neighbor_add_internal(Link *link, Set **neighbors, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
- _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
- int r;
+int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
+ _cleanup_(neighbor_freep) Neighbor *tmp = NULL;
+ _cleanup_free_ char *addr_str = NULL, *lladdr_str = NULL;
+ Neighbor *neighbor = NULL;
+ uint16_t type, state;
+ int ifindex, r;
+ Link *link;
- assert(link);
- assert(neighbors);
- assert(addr);
- assert(lladdr);
+ assert(rtnl);
+ assert(message);
+ assert(m);
- neighbor = new(Neighbor, 1);
- if (!neighbor)
- return -ENOMEM;
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring");
- *neighbor = (Neighbor) {
- .family = family,
- .in_addr = *addr,
- .lladdr = *lladdr,
- .lladdr_size = lladdr_size,
- };
+ return 0;
+ }
- r = set_ensure_put(neighbors, &neighbor_hash_ops, neighbor);
- if (r < 0)
- return r;
- if (r == 0)
- return -EEXIST;
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) {
+ log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type);
+ return 0;
+ }
- neighbor->link = link;
+ r = sd_rtnl_message_neigh_get_state(message, &state);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received neighbor message with invalid state, ignoring: %m");
+ return 0;
+ } else if (!FLAGS_SET(state, NUD_PERMANENT)) {
+ log_debug("rtnl: received non-static neighbor, ignoring.");
+ return 0;
+ }
- if (ret)
- *ret = neighbor;
- TAKE_PTR(neighbor);
+ r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex);
+ return 0;
+ }
- return 0;
-}
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ /* when enumerating we might be out of sync, but we will get the neighbor again, so just
+ * ignore it */
+ if (!m->enumerating)
+ log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
+ return 0;
+ }
-int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
- Neighbor *neighbor;
- int r;
+ tmp = new0(Neighbor, 1);
- r = neighbor_get(link, family, addr, lladdr, lladdr_size, &neighbor);
- if (r == -ENOENT) {
- /* Neighbor doesn't exist, make a new one */
- r = neighbor_add_internal(link, &link->neighbors, family, addr, lladdr, lladdr_size, &neighbor);
- if (r < 0)
- return r;
- } else if (r == 0) {
- /* Neighbor is foreign, claim it as recognized */
- r = set_ensure_put(&link->neighbors, &neighbor_hash_ops, neighbor);
- if (r < 0)
- return r;
+ r = sd_rtnl_message_neigh_get_family(message, &tmp->family);
+ if (r < 0) {
+ log_link_warning(link, "rtnl: received neighbor message without family, ignoring.");
+ return 0;
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+ log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", tmp->family);
+ return 0;
+ }
- set_remove(link->neighbors_foreign, neighbor);
- } else if (r == 1) {
- /* Neighbor already exists */
- } else
- return r;
+ r = netlink_message_read_in_addr_union(message, NDA_DST, tmp->family, &tmp->in_addr);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
+ return 0;
+ }
- if (ret)
- *ret = neighbor;
- return 0;
-}
+ if (in_addr_to_string(tmp->family, &tmp->in_addr, &addr_str) < 0)
+ log_link_warning_errno(link, r, "Could not print address: %m");
-int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
- return neighbor_add_internal(link, &link->neighbors_foreign, family, addr, lladdr, lladdr_size, ret);
-}
+ r = manager_rtnl_process_neighbor_lladdr(message, &tmp->lladdr, &tmp->lladdr_size, &lladdr_str);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
+ return 0;
+ }
-bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) {
- if (n1 == n2)
- return true;
+ (void) neighbor_get(link, tmp, &neighbor);
+
+ switch (type) {
+ case RTM_NEWNEIGH:
+ if (neighbor)
+ log_link_debug(link, "Received remembered neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ else {
+ /* A neighbor appeared that we did not request */
+ r = neighbor_add_foreign(link, tmp, NULL);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
+ strnull(addr_str), strnull(lladdr_str));
+ return 0;
+ } else
+ log_link_debug(link, "Remembering foreign neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ }
- if (!n1 || !n2)
- return false;
+ break;
- return neighbor_compare_func(n1, n2) == 0;
+ case RTM_DELNEIGH:
+ if (neighbor) {
+ log_link_debug(link, "Forgetting neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ (void) neighbor_free(neighbor);
+ } else
+ log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
+ strnull(addr_str), strnull(lladdr_str));
+
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type");
+ }
+
+ return 1;
}
-int neighbor_section_verify(Neighbor *neighbor) {
+static int neighbor_section_verify(Neighbor *neighbor) {
if (section_is_invalid(neighbor->section))
return -EINVAL;
return 0;
}
+void network_drop_invalid_neighbors(Network *network) {
+ Neighbor *neighbor;
+
+ assert(network);
+
+ HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
+ if (neighbor_section_verify(neighbor) < 0)
+ neighbor_free(neighbor);
+}
+
+
int config_parse_neighbor_address(
const char *unit,
const char *filename,
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <stdbool.h>
+
#include "sd-netlink.h"
#include "conf-parser.h"
#include "ether-addr-util.h"
#include "in-addr-util.h"
-#include "list.h"
-#include "macro.h"
-
-typedef struct Neighbor Neighbor;
-
-#include "networkd-link.h"
-#include "networkd-network.h"
#include "networkd-util.h"
+typedef Manager Manager;
+typedef Network Network;
+typedef Link Link;
+
union lladdr_union {
struct ether_addr mac;
union in_addr_union ip;
};
-struct Neighbor {
+typedef struct Neighbor {
Network *network;
Link *link;
NetworkConfigSection *section;
union in_addr_union in_addr;
union lladdr_union lladdr;
size_t lladdr_size;
+} Neighbor;
- LIST_FIELDS(Neighbor, neighbors);
-};
-
-void neighbor_free(Neighbor *neighbor);
-
-DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
+Neighbor *neighbor_free(Neighbor *neighbor);
-int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
-int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+void network_drop_invalid_neighbors(Network *network);
-int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
-int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
-int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
-bool neighbor_equal(const Neighbor *n1, const Neighbor *n2);
+int link_set_neighbors(Link *link);
+int link_drop_neighbors(Link *link);
+int link_drop_foreign_neighbors(Link *link);
-int neighbor_section_verify(Neighbor *neighbor);
+int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
#include "conf-parser.h"
#include "netem.h"
#include "network-internal.h"
+#include "networkd-address-label.h"
+#include "networkd-address.h"
#include "networkd-can.h"
#include "networkd-conf.h"
#include "networkd-dhcp-common.h"
#include "networkd-dhcp-server.h"
#include "networkd-dhcp4.h"
#include "networkd-dhcp6.h"
+#include "networkd-fdb.h"
#include "networkd-ipv4ll.h"
+#include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-mdb.h"
#include "networkd-ndisc.h"
#include "networkd-network.h"
+#include "networkd-neighbor.h"
+#include "networkd-nexthop.h"
+#include "networkd-radv.h"
+#include "networkd-route.h"
+#include "networkd-routing-policy-rule.h"
#include "networkd-sriov.h"
#include "qdisc.h"
#include "tclass.h"
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
Network.IgnoreCarrierLoss, config_parse_tristate, 0, offsetof(Network, ignore_carrier_loss)
Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration)
+Network.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
+Network.DHCPv6PrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp6_pd)
Address.Address, config_parse_address, 0, 0
Address.Peer, config_parse_address, 0, 0
Address.Broadcast, config_parse_broadcast, 0, 0
Address.Label, config_parse_label, 0, 0
Address.PreferredLifetime, config_parse_lifetime, 0, 0
-Address.HomeAddress, config_parse_address_flags, 0, 0
-Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0
-Address.PrefixRoute, config_parse_address_flags, 0, 0 /* deprecated */
-Address.AddPrefixRoute, config_parse_address_flags, 0, 0
-Address.AutoJoin, config_parse_address_flags, 0, 0
+Address.HomeAddress, config_parse_address_flags, IFA_F_HOMEADDRESS, 0
+Address.ManageTemporaryAddress, config_parse_address_flags, IFA_F_MANAGETEMPADDR, 0
+Address.PrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 /* deprecated */
+Address.AddPrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0
+Address.AutoJoin, config_parse_address_flags, IFA_F_MCAUTOJOIN, 0
Address.DuplicateAddressDetection, config_parse_duplicate_address_detection, 0, 0
Address.Scope, config_parse_address_scope, 0, 0
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0
DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline)
DHCPv4.DenyList, config_parse_dhcp_acl_ip_address, 0, 0
DHCPv4.AllowList, config_parse_dhcp_acl_ip_address, 0, 0
-DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, ip_service_type)
+DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type)
DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options)
DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options)
DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0
-DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
+DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0
BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
-Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id, 0, offsetof(Network, dhcp6_pd_subnet_id)
+DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp6_pd_announce)
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign)
DHCPv6PrefixDelegation.Token, config_parse_dhcp6_pd_token, 0, offsetof(Network, dhcp6_pd_token)
-IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
-IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
-IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
-IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0
-IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns)
-IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0
-IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
-IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0
-IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
+IPv6SendRA.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
+IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
+IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
+IPv6SendRA.RouterPreference, config_parse_router_preference, 0, 0
+IPv6SendRA.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns)
+IPv6SendRA.DNS, config_parse_radv_dns, 0, 0
+IPv6SendRA.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
+IPv6SendRA.Domains, config_parse_radv_search_domains, 0, 0
+IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
IPv6Prefix.Prefix, config_parse_prefix, 0, 0
IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0
TrivialLinkEqualizer.Id, config_parse_trivial_link_equalizer_id, QDISC_KIND_TEQL, 0
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
+Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
+IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
+IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
+IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
+IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0
+IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns)
+IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0
+IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
+IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0
+IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
DHCPv4.BlackList, config_parse_dhcp_acl_ip_address, 0, 0
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.IAID, config_parse_iaid, 0, 0
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
-DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
+DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
#include "in-addr-util.h"
#include "networkd-dhcp-server.h"
#include "network-internal.h"
+#include "networkd-address-label.h"
+#include "networkd-address.h"
+#include "networkd-dhcp-common.h"
+#include "networkd-fdb.h"
#include "networkd-manager.h"
+#include "networkd-mdb.h"
+#include "networkd-ndisc.h"
+#include "networkd-neighbor.h"
#include "networkd-network.h"
+#include "networkd-nexthop.h"
+#include "networkd-radv.h"
+#include "networkd-routing-policy-rule.h"
#include "networkd-sriov.h"
#include "parse-util.h"
#include "path-lookup.h"
}
int network_verify(Network *network) {
- RoutePrefix *route_prefix, *route_prefix_next;
- RoutingPolicyRule *rule, *rule_next;
- Neighbor *neighbor, *neighbor_next;
- AddressLabel *label, *label_next;
- NextHop *nexthop, *nextnop_next;
- Address *address, *address_next;
- Prefix *prefix, *prefix_next;
- Route *route, *route_next;
- FdbEntry *fdb, *fdb_next;
- MdbEntry *mdb, *mdb_next;
- TrafficControl *tc;
- SRIOV *sr_iov;
-
assert(network);
assert(network->filename);
if (network->bond) {
/* Bonding slave does not support addressing. */
- if (network->ipv6_accept_ra > 0) {
- log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
- network->filename);
- network->ipv6_accept_ra = 0;
- }
if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
network->filename);
network->link_local = ADDRESS_FAMILY_NO;
}
- if (network->dhcp != ADDRESS_FAMILY_NO) {
- log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
- network->filename);
- network->dhcp = ADDRESS_FAMILY_NO;
- }
if (network->dhcp_server) {
log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
network->filename);
network->dhcp_server = false;
}
- if (network->n_static_addresses > 0) {
+ if (!ordered_hashmap_isempty(network->addresses_by_section))
log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
network->filename);
- while ((address = network->static_addresses))
- address_free(address);
- }
- if (network->n_static_routes > 0) {
+ if (!hashmap_isempty(network->routes_by_section))
log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
network->filename);
- while ((route = network->static_routes))
- route_free(route);
- }
+
+ network->addresses_by_section = ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
+ network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free);
}
if (network->link_local < 0)
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
- if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
- if (network->ipv6_accept_ra > 0) {
- log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
- "Disabling IPv6AcceptRA=.", network->filename);
- network->ipv6_accept_ra = false;
- }
-
- if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
- log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
- "Disabling DHCPv6 client.", network->filename);
- SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
- }
-
- if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
- log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
- "Disabling IPv6PrefixDelegation=.", network->filename);
- network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
- }
- }
-
if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
!FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
}
- if (network->ipv6_accept_ra < 0 && network->bridge)
- network->ipv6_accept_ra = false;
-
/* IPMasquerade=yes implies IPForward=yes */
if (network->ip_masquerade)
network->ip_forward |= ADDRESS_FAMILY_IPV4;
+ network_adjust_ipv6_accept_ra(network);
+ network_adjust_dhcp(network);
+ network_adjust_radv(network);
+
if (network->mtu > 0 && network->dhcp_use_mtu) {
log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
"Disabling UseMTU=.", network->filename);
if (network->keep_configuration < 0)
network->keep_configuration = KEEP_CONFIGURATION_NO;
- LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
- if (address_section_verify(address) < 0)
- address_free(address);
-
- LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
- if (route_section_verify(route, network) < 0)
- route_free(route);
-
- LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops)
- if (nexthop_section_verify(nexthop) < 0)
- nexthop_free(nexthop);
-
- LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
- if (section_is_invalid(fdb->section))
- fdb_entry_free(fdb);
-
- LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries)
- if (mdb_entry_verify(mdb) < 0)
- mdb_entry_free(mdb);
-
- LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
- if (neighbor_section_verify(neighbor) < 0)
- neighbor_free(neighbor);
-
- LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
- if (section_is_invalid(label->section))
- address_label_free(label);
-
- LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
- if (section_is_invalid(prefix->section))
- prefix_free(prefix);
-
- LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes)
- if (section_is_invalid(route_prefix->section))
- route_prefix_free(route_prefix);
-
- LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
- if (routing_policy_rule_section_verify(rule) < 0)
- routing_policy_rule_free(rule);
-
- bool has_root = false, has_clsact = false;
- ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section)
- if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
- traffic_control_free(tc);
+ if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) {
+ log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
+ network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
+ }
- ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
- if (sr_iov_section_verify(sr_iov) < 0)
- sr_iov_free(sr_iov);
+ network_drop_invalid_addresses(network);
+ network_drop_invalid_routes(network);
+ network_drop_invalid_nexthops(network);
+ network_drop_invalid_fdb_entries(network);
+ network_drop_invalid_mdb_entries(network);
+ network_drop_invalid_neighbors(network);
+ network_drop_invalid_address_labels(network);
+ network_drop_invalid_prefixes(network);
+ network_drop_invalid_route_prefixes(network);
+ network_drop_invalid_routing_policy_rules(network);
+ network_drop_invalid_traffic_control(network);
+ network_drop_invalid_sr_iov(network);
return 0;
}
.required_for_online = true,
.required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
+ .arp = -1,
+ .multicast = -1,
+ .allmulticast = -1,
+
+ .configure_without_carrier = false,
+ .ignore_carrier_loss = -1,
+ .keep_configuration = _KEEP_CONFIGURATION_INVALID,
+
.dhcp = ADDRESS_FAMILY_NO,
+ .duid.type = _DUID_TYPE_INVALID,
.dhcp_critical = -1,
.dhcp_use_ntp = true,
.dhcp_use_sip = true,
.dhcp_use_mtu = false,
/* NOTE: from man: UseTimezone=... Defaults to "no".*/
.dhcp_use_timezone = false,
- .rapid_commit = true,
+ .dhcp_ip_service_type = -1,
+ .dhcp6_rapid_commit = true,
.dhcp6_route_metric = DHCP_ROUTE_METRIC,
.dhcp6_use_ntp = true,
.dhcp6_use_dns = true,
- .dhcp6_pd_subnet_id = -1,
+ .dhcp6_pd = -1,
+ .dhcp6_pd_announce = true,
.dhcp6_pd_assign = true,
+ .dhcp6_pd_subnet_id = -1,
.dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
.dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
.ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
.ipv4_accept_local = -1,
-
.ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
.ipv6_accept_ra = -1,
.ipv6_dad_transmits = -1,
.ipv6_hop_limit = -1,
.ipv6_proxy_ndp = -1,
- .duid.type = _DUID_TYPE_INVALID,
.proxy_arp = -1,
- .arp = -1,
- .multicast = -1,
- .allmulticast = -1,
+
.ipv6_accept_ra_use_dns = true,
.ipv6_accept_ra_use_autonomous_prefix = true,
.ipv6_accept_ra_use_onlink_prefix = true,
.ipv6_accept_ra_route_table_set = false,
.ipv6_accept_ra_start_dhcp6_client = true,
- .configure_without_carrier = false,
- .ignore_carrier_loss = -1,
- .keep_configuration = _KEEP_CONFIGURATION_INVALID,
.can_triple_sampling = -1,
.can_termination = -1,
.can_listen_only = -1,
.can_fd_mode = -1,
.can_non_iso = -1,
- .ip_service_type = -1,
};
r = config_parse_many(
"BridgeFDB\0"
"BridgeMDB\0"
"BridgeVLAN\0"
+ "IPv6SendRA\0"
"IPv6PrefixDelegation\0"
"IPv6Prefix\0"
"IPv6RoutePrefix\0"
}
static Network *network_free(Network *network) {
- IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
- RoutePrefix *route_prefix;
- RoutingPolicyRule *rule;
- AddressLabel *label;
- FdbEntry *fdb_entry;
- MdbEntry *mdb_entry;
- Neighbor *neighbor;
- Address *address;
- NextHop *nexthop;
- Prefix *prefix;
- Route *route;
-
if (!network)
return NULL;
strv_free(network->dhcp6_user_class);
strv_free(network->dhcp6_vendor_class);
- if (network->dhcp_acd)
- sd_ipv4acd_unref(network->dhcp_acd);
-
strv_free(network->ntp);
for (unsigned i = 0; i < network->n_dns; i++)
in_addr_full_free(network->dns[i]);
free(network->dns);
- ordered_set_free_free(network->search_domains);
- ordered_set_free_free(network->route_domains);
+ ordered_set_free(network->search_domains);
+ ordered_set_free(network->route_domains);
strv_free(network->bind_carrier);
- ordered_set_free_free(network->router_search_domains);
+ ordered_set_free(network->router_search_domains);
free(network->router_dns);
set_free_free(network->ndisc_deny_listed_prefix);
netdev_unref(network->vrf);
hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
- while ((route = network->static_routes))
- route_free(route);
-
- while ((nexthop = network->static_nexthops))
- nexthop_free(nexthop);
-
- while ((address = network->static_addresses))
- address_free(address);
-
- while ((fdb_entry = network->static_fdb_entries))
- fdb_entry_free(fdb_entry);
-
- while ((mdb_entry = network->static_mdb_entries))
- mdb_entry_free(mdb_entry);
-
- while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
- ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
-
- while ((neighbor = network->neighbors))
- neighbor_free(neighbor);
-
- while ((label = network->address_labels))
- address_label_free(label);
-
- while ((prefix = network->static_prefixes))
- prefix_free(prefix);
-
- while ((route_prefix = network->static_route_prefixes))
- route_prefix_free(route_prefix);
-
- while ((rule = network->rules))
- routing_policy_rule_free(rule);
-
- hashmap_free(network->addresses_by_section);
- hashmap_free(network->routes_by_section);
- hashmap_free(network->nexthops_by_section);
- hashmap_free(network->fdb_entries_by_section);
- hashmap_free(network->mdb_entries_by_section);
- hashmap_free(network->neighbors_by_section);
- hashmap_free(network->address_labels_by_section);
- hashmap_free(network->prefixes_by_section);
- hashmap_free(network->route_prefixes_by_section);
- hashmap_free(network->rules_by_section);
+ set_free_free(network->ipv6_proxy_ndp_addresses);
+ ordered_hashmap_free_with_destructor(network->addresses_by_section, address_free);
+ hashmap_free_with_destructor(network->routes_by_section, route_free);
+ hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
+ hashmap_free_with_destructor(network->fdb_entries_by_section, fdb_entry_free);
+ hashmap_free_with_destructor(network->mdb_entries_by_section, mdb_entry_free);
+ hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free);
+ hashmap_free_with_destructor(network->address_labels_by_section, address_label_free);
+ hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
+ hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
+ hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
assert(network);
- LIST_FOREACH(addresses, address, network->static_addresses)
+ ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
if (address->family == AF_INET6)
return true;
- LIST_FOREACH(routes, route, network->static_routes)
+ HASHMAP_FOREACH(route, network->routes_by_section)
if (route->family == AF_INET6)
return true;
- LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries)
+ HASHMAP_FOREACH(fdb, network->fdb_entries_by_section)
if (fdb->family == AF_INET6)
return true;
- LIST_FOREACH(static_mdb_entries, mdb, network->static_mdb_entries)
+ HASHMAP_FOREACH(mdb, network->mdb_entries_by_section)
if (mdb->family == AF_INET6)
return true;
- LIST_FOREACH(neighbors, neighbor, network->neighbors)
+ HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
if (neighbor->family == AF_INET6)
return true;
- if (!LIST_IS_EMPTY(network->address_labels))
+ if (!hashmap_isempty(network->address_labels_by_section))
+ return true;
+
+ if (!hashmap_isempty(network->prefixes_by_section))
return true;
- if (!LIST_IS_EMPTY(network->static_prefixes))
+ if (!hashmap_isempty(network->route_prefixes_by_section))
return true;
return false;
assert(rvalue);
if (isempty(rvalue)) {
- n->search_domains = ordered_set_free_free(n->search_domains);
- n->route_domains = ordered_set_free_free(n->route_domains);
+ n->search_domains = ordered_set_free(n->search_domains);
+ n->route_domains = ordered_set_free(n->route_domains);
return 0;
}
}
OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
- r = ordered_set_ensure_allocated(set, &string_hash_ops);
+ r = ordered_set_ensure_allocated(set, &string_hash_ops_free);
if (r < 0)
return log_oom();
}
}
-int config_parse_ipv6token(
- 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) {
-
- union in_addr_union buffer;
- struct in6_addr *token = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(token);
-
- r = in_addr_from_string(AF_INET6, rvalue, &buffer);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse IPv6 token, ignoring: %s", rvalue);
- return 0;
- }
-
- if (in_addr_is_null(AF_INET6, &buffer)) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
- return 0;
- }
-
- if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
- return 0;
- }
-
- *token = buffer.in6;
-
- return 0;
-}
-
-static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
- [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
- [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
- [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
- IPV6_PRIVACY_EXTENSIONS_YES);
-
-int config_parse_ipv6_privacy_extensions(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(ipv6_privacy_extensions);
-
- s = ipv6_privacy_extensions_from_string(rvalue);
- if (s < 0) {
- if (streq(rvalue, "kernel"))
- s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
- else {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
- return 0;
- }
- }
-
- *ipv6_privacy_extensions = s;
-
- return 0;
-}
-
int config_parse_hostname(
const char *unit,
const char *filename,
#include "sd-bus.h"
#include "sd-device.h"
-#include "sd-ipv4acd.h"
#include "bridge.h"
#include "condition.h"
#include "conf-parser.h"
#include "hashmap.h"
#include "netdev.h"
-#include "networkd-address-label.h"
-#include "networkd-address.h"
#include "networkd-brvlan.h"
#include "networkd-dhcp-common.h"
#include "networkd-dhcp4.h"
#include "networkd-dhcp6.h"
#include "networkd-dhcp-server.h"
-#include "networkd-fdb.h"
-#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-lldp-rx.h"
#include "networkd-lldp-tx.h"
-#include "networkd-mdb.h"
#include "networkd-ndisc.h"
-#include "networkd-neighbor.h"
-#include "networkd-nexthop.h"
#include "networkd-radv.h"
-#include "networkd-route.h"
-#include "networkd-routing-policy-rule.h"
+#include "networkd-sysctl.h"
#include "networkd-util.h"
#include "ordered-set.h"
#include "resolve-util.h"
#include "socket-netlink.h"
-typedef enum IPv6PrivacyExtensions {
- /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
- IPV6_PRIVACY_EXTENSIONS_NO,
- IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
- IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
- _IPV6_PRIVACY_EXTENSIONS_MAX,
- _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
-} IPv6PrivacyExtensions;
-
typedef enum KeepConfiguration {
KEEP_CONFIGURATION_NO = 0,
KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0,
struct Network {
Manager *manager;
- char *filename;
+ unsigned n_ref;
+
char *name;
+ char *filename;
usec_t timestamp;
+ char *description;
- unsigned n_ref;
-
+ /* [Match] section */
Set *match_mac;
Set *match_permanent_mac;
char **match_path;
Set *match_bssid;
LIST_HEAD(Condition, conditions);
- char *description;
-
+ /* Master or stacked netdevs */
NetDev *bridge;
NetDev *bond;
NetDev *vrf;
char *vrf_name;
Hashmap *stacked_netdev_names;
+ /* [Link] section */
+ struct ether_addr *mac;
+ uint32_t mtu;
+ uint32_t group;
+ 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;
+
+ /* misc settings */
+ bool configure_without_carrier;
+ int ignore_carrier_loss;
+ KeepConfiguration keep_configuration;
+ char **bind_carrier;
+ bool default_route_on_device;
+ bool ip_masquerade;
+
/* DHCP Client Support */
AddressFamily dhcp;
DHCPClientIdentifier dhcp_client_identifier;
+ DUID duid;
+ uint32_t iaid;
+ bool iaid_set;
char *dhcp_vendor_class_identifier;
char *dhcp_mudurl;
char **dhcp_user_class;
uint32_t dhcp_route_mtu;
uint16_t dhcp_client_port;
int dhcp_critical;
- int ip_service_type;
+ int dhcp_ip_service_type;
bool dhcp_anonymize;
bool dhcp_send_hostname;
bool dhcp_broadcast;
bool dhcp_use_routes;
int dhcp_use_gateway;
bool dhcp_use_timezone;
- bool rapid_commit;
bool dhcp_use_hostname;
bool dhcp_route_table_set;
bool dhcp_send_release;
bool dhcp_send_decline;
DHCPUseDomains dhcp_use_domains;
- sd_ipv4acd *dhcp_acd;
Set *dhcp_deny_listed_ip;
Set *dhcp_allow_listed_ip;
Set *dhcp_request_options;
OrderedHashmap *dhcp_client_send_options;
OrderedHashmap *dhcp_client_send_vendor_options;
- OrderedHashmap *dhcp_server_send_options;
- OrderedHashmap *dhcp_server_send_vendor_options;
/* DHCPv6 Client support*/
bool dhcp6_use_dns;
bool dhcp6_use_dns_set;
bool dhcp6_use_ntp;
bool dhcp6_use_ntp_set;
+ bool dhcp6_rapid_commit;
uint8_t dhcp6_pd_length;
uint32_t dhcp6_route_metric;
bool dhcp6_route_metric_set;
OrderedHashmap *dhcp6_client_send_options;
OrderedHashmap *dhcp6_client_send_vendor_options;
Set *dhcp6_request_options;
+ /* Start DHCPv6 PD also when 'O' RA flag is set, see RFC 7084, WPD-4 */
+ bool dhcp6_force_pd_other_information;
/* DHCP Server Support */
bool dhcp_server;
usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec;
uint32_t dhcp_server_pool_offset;
uint32_t dhcp_server_pool_size;
+ OrderedHashmap *dhcp_server_send_options;
+ OrderedHashmap *dhcp_server_send_vendor_options;
/* link local addressing support */
AddressFamily link_local;
IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode;
bool ipv4ll_route;
- bool default_route_on_device;
-
- /* IPv6 prefix delegation support */
+ /* IPv6 RA support */
RADVPrefixDelegation router_prefix_delegation;
usec_t router_lifetime_usec;
uint8_t router_preference;
struct in6_addr *router_dns;
unsigned n_router_dns;
OrderedSet *router_search_domains;
- bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
- RA flag is set, see RFC 7084,
- WPD-4 */
/* DHCPv6 Prefix Delegation support */
- int64_t dhcp6_pd_subnet_id;
+ int dhcp6_pd;
+ bool dhcp6_pd_announce;
bool dhcp6_pd_assign;
+ int64_t dhcp6_pd_subnet_id;
union in_addr_union dhcp6_pd_token;
/* Bridge Support */
uint16_t priority;
MulticastRouter multicast_router;
+ /* Bridge VLAN */
bool use_br_vlan;
uint16_t pvid;
uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN];
int can_fd_mode;
int can_non_iso;
+ /* sysctl settings */
AddressFamily ip_forward;
- bool ip_masquerade;
int ipv4_accept_local;
-
- int ipv6_accept_ra;
int ipv6_dad_transmits;
int ipv6_hop_limit;
- int ipv6_proxy_ndp;
int proxy_arp;
uint32_t ipv6_mtu;
+ IPv6PrivacyExtensions ipv6_privacy_extensions;
+ int ipv6_proxy_ndp;
+ Set *ipv6_proxy_ndp_addresses;
+ /* IPv6 accept RA */
+ int ipv6_accept_ra;
bool ipv6_accept_ra_use_dns;
bool ipv6_accept_ra_use_autonomous_prefix;
bool ipv6_accept_ra_use_onlink_prefix;
Set *ndisc_deny_listed_prefix;
OrderedSet *ipv6_tokens;
- IPv6PrivacyExtensions ipv6_privacy_extensions;
-
- struct ether_addr *mac;
- uint32_t mtu;
- uint32_t group;
- int arp;
- int multicast;
- int allmulticast;
- bool unmanaged;
- bool configure_without_carrier;
- int ignore_carrier_loss;
- KeepConfiguration keep_configuration;
- uint32_t iaid;
- DUID duid;
-
- bool iaid_set;
-
- bool required_for_online; /* Is this network required to be considered online? */
- LinkOperationalStateRange required_operstate_for_online;
-
/* LLDP support */
LLDPMode lldp_mode; /* LLDP reception */
LLDPEmit lldp_emit; /* LLDP transmission */
char *lldp_mud; /* LLDP MUD URL */
- LIST_HEAD(Address, static_addresses);
- LIST_HEAD(Route, static_routes);
- LIST_HEAD(NextHop, static_nexthops);
- LIST_HEAD(FdbEntry, static_fdb_entries);
- LIST_HEAD(MdbEntry, static_mdb_entries);
- LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
- LIST_HEAD(Neighbor, neighbors);
- LIST_HEAD(AddressLabel, address_labels);
- LIST_HEAD(Prefix, static_prefixes);
- LIST_HEAD(RoutePrefix, static_route_prefixes);
- LIST_HEAD(RoutingPolicyRule, rules);
-
- unsigned n_static_addresses;
- unsigned n_static_routes;
- unsigned n_static_nexthops;
- unsigned n_static_fdb_entries;
- unsigned n_static_mdb_entries;
- unsigned n_ipv6_proxy_ndp_addresses;
- unsigned n_neighbors;
- unsigned n_address_labels;
- unsigned n_static_prefixes;
- unsigned n_static_route_prefixes;
- unsigned n_rules;
-
- Hashmap *addresses_by_section;
+ OrderedHashmap *addresses_by_section;
Hashmap *routes_by_section;
Hashmap *nexthops_by_section;
Hashmap *fdb_entries_by_section;
struct in_addr_full **dns;
unsigned n_dns;
OrderedSet *search_domains, *route_domains;
-
int dns_default_route;
ResolveSupport llmnr;
ResolveSupport mdns;
DnsOverTlsMode dns_over_tls_mode;
Set *dnssec_negative_trust_anchors;
+ /* NTP */
char **ntp;
- char **bind_carrier;
};
Network *network_ref(Network *network);
CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token);
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
CONFIG_PARSER_PROTOTYPE(config_parse_domains);
CONFIG_PARSER_PROTOTYPE(config_parse_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
-IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
-
const char* keep_configuration_to_string(KeepConfiguration i) _const_;
KeepConfiguration keep_configuration_from_string(const char *s) _pure_;
#include <linux/nexthop.h>
#include "alloc-util.h"
-#include "conf-parser.h"
-#include "in-addr-util.h"
#include "netlink-util.h"
+#include "networkd-link.h"
#include "networkd-manager.h"
+#include "networkd-network.h"
#include "networkd-nexthop.h"
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
-#include "util.h"
-int nexthop_new(NextHop **ret) {
+NextHop *nexthop_free(NextHop *nexthop) {
+ if (!nexthop)
+ return NULL;
+
+ if (nexthop->network) {
+ assert(nexthop->section);
+ hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
+ }
+
+ network_config_section_free(nexthop->section);
+
+ if (nexthop->link) {
+ set_remove(nexthop->link->nexthops, nexthop);
+ set_remove(nexthop->link->nexthops_foreign, nexthop);
+ }
+
+ return mfree(nexthop);
+}
+
+DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free);
+
+static int nexthop_new(NextHop **ret) {
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
nexthop = new(NextHop, 1);
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- nexthop = hashmap_get(network->nexthops_by_section, n);
- if (nexthop) {
- *ret = TAKE_PTR(nexthop);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ nexthop = hashmap_get(network->nexthops_by_section, n);
+ if (nexthop) {
+ *ret = TAKE_PTR(nexthop);
+ return 0;
}
r = nexthop_new(&nexthop);
nexthop->protocol = RTPROT_STATIC;
nexthop->network = network;
- LIST_PREPEND(nexthops, network->static_nexthops, nexthop);
- network->n_static_nexthops++;
+ nexthop->section = TAKE_PTR(n);
- if (filename) {
- nexthop->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->nexthops_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->nexthops_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->nexthops_by_section, nexthop->section, nexthop);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->nexthops_by_section, nexthop->section, nexthop);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(nexthop);
-
return 0;
}
-void nexthop_free(NextHop *nexthop) {
- if (!nexthop)
- return;
-
- if (nexthop->network) {
- LIST_REMOVE(nexthops, nexthop->network->static_nexthops, nexthop);
-
- assert(nexthop->network->n_static_nexthops > 0);
- nexthop->network->n_static_nexthops--;
-
- if (nexthop->section)
- hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
- }
-
- network_config_section_free(nexthop->section);
-
- if (nexthop->link) {
- set_remove(nexthop->link->nexthops, nexthop);
- set_remove(nexthop->link->nexthops_foreign, nexthop);
- }
-
- free(nexthop);
-}
-
static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
assert(nexthop);
siphash24_compress(&nexthop->id, sizeof(nexthop->id), state);
- siphash24_compress(&nexthop->oif, sizeof(nexthop->oif), state);
siphash24_compress(&nexthop->family, sizeof(nexthop->family), state);
switch (nexthop->family) {
if (r != 0)
return r;
- r = CMP(a->oif, b->oif);
- if (r != 0)
- return r;
-
r = CMP(a->family, b->family);
if (r != 0)
return r;
- switch (a->family) {
- case AF_INET:
- case AF_INET6:
-
- r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
- if (r != 0)
- return r;
+ if (IN_SET(a->family, AF_INET, AF_INET6))
+ return memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
- return 0;
- default:
- /* treat any other address family as AF_UNSPEC */
- return 0;
- }
+ return 0;
}
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
nexthop_compare_func,
nexthop_free);
-bool nexthop_equal(NextHop *r1, NextHop *r2) {
- if (r1 == r2)
- return true;
-
- if (!r1 || !r2)
- return false;
-
- return nexthop_compare_func(r1, r2) == 0;
-}
-
-int nexthop_get(Link *link, NextHop *in, NextHop **ret) {
+static int nexthop_get(Link *link, NextHop *in, NextHop **ret) {
NextHop *existing;
assert(link);
return r;
nexthop->id = in->id;
- nexthop->oif = in->oif;
nexthop->family = in->family;
nexthop->gw = in->gw;
return 0;
}
-int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) {
+static int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) {
return nexthop_add_internal(link, &link->nexthops_foreign, in, ret);
}
-int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
+static int nexthop_add(Link *link, NextHop *in, NextHop **ret) {
NextHop *nexthop;
int r;
return 0;
}
-static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
- assert(m);
assert(link);
- assert(link->ifname);
+ assert(link->nexthop_messages > 0);
+
+ link->nexthop_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -ESRCH)
- log_link_message_warning_errno(link, m, r, "Could not drop nexthop, ignoring");
-
- return 1;
-}
-
-int nexthop_remove(NextHop *nexthop, Link *link,
- link_netlink_message_handler_t callback) {
-
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- int r;
-
- assert(link);
- assert(link->manager);
- assert(link->manager->rtnl);
- assert(link->ifindex > 0);
- assert(IN_SET(nexthop->family, AF_INET, AF_INET6));
-
- r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req,
- RTM_DELNEXTHOP, nexthop->family,
- nexthop->protocol);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not create RTM_DELNEXTHOP message: %m");
-
- if (DEBUG_LOGGING) {
- _cleanup_free_ char *gw = NULL;
-
- if (!in_addr_is_null(nexthop->family, &nexthop->gw))
- (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw);
-
- log_link_debug(link, "Removing nexthop: gw: %s", strna(gw));
+ if (r < 0 && r != -EEXIST) {
+ log_link_message_warning_errno(link, m, r, "Could not set nexthop");
+ link_enter_failed(link);
+ return 1;
}
- if (in_addr_is_null(nexthop->family, &nexthop->gw) == 0) {
- r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, nexthop->family, &nexthop->gw);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
+ if (link->nexthop_messages == 0) {
+ log_link_debug(link, "Nexthop set");
+ link->static_nexthops_configured = true;
+ link_check_ready(link);
}
- r = netlink_call_async(link->manager->rtnl, NULL, req,
- callback ?: nexthop_remove_handler,
- 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;
+ return 1;
}
-int nexthop_configure(
- NextHop *nexthop,
- Link *link,
- link_netlink_message_handler_t callback) {
+static int nexthop_configure(NextHop *nexthop, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link->manager->rtnl);
assert(link->ifindex > 0);
assert(IN_SET(nexthop->family, AF_INET, AF_INET6));
- assert(callback);
if (DEBUG_LOGGING) {
_cleanup_free_ char *gw = NULL;
return log_link_error_errno(link, r, "Could not set nexthop family: %m");
}
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return 1;
}
-int nexthop_section_verify(NextHop *nh) {
+int link_set_nexthop(Link *link) {
+ NextHop *nh;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ link->static_nexthops_configured = false;
+
+ HASHMAP_FOREACH(nh, link->network->nexthops_by_section) {
+ r = nexthop_configure(nh, link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set nexthop: %m");
+
+ link->nexthop_messages++;
+ }
+
+ if (link->nexthop_messages == 0) {
+ link->static_nexthops_configured = true;
+ link_check_ready(link);
+ } else {
+ log_link_debug(link, "Setting nexthop");
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ }
+
+ return 1;
+}
+
+int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
+ _cleanup_(nexthop_freep) NextHop *tmp = NULL;
+ _cleanup_free_ char *gateway = NULL;
+ NextHop *nexthop = NULL;
+ uint32_t ifindex;
+ uint16_t type;
+ Link *link;
+ int r;
+
+ assert(rtnl);
+ assert(message);
+ assert(m);
+
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring");
+
+ return 0;
+ }
+
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWNEXTHOP, RTM_DELNEXTHOP)) {
+ log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type);
+ return 0;
+ }
+
+ r = sd_netlink_message_read_u32(message, NHA_OIF, &ifindex);
+ if (r == -ENODATA) {
+ log_warning_errno(r, "rtnl: received nexthop message without NHA_OIF attribute, ignoring: %m");
+ return 0;
+ } else if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received nexthop message with invalid ifindex %"PRIu32", ignoring.", ifindex);
+ return 0;
+ }
+
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ if (!m->enumerating)
+ log_warning("rtnl: received nexthop message for link (%"PRIu32") we do not know about, ignoring", ifindex);
+ return 0;
+ }
+
+ r = nexthop_new(&tmp);
+ if (r < 0)
+ return log_oom();
+
+ r = sd_rtnl_message_get_family(message, &tmp->family);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: could not get nexthop family, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6))
+ return log_link_debug(link, "rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family);
+
+ r = netlink_message_read_in_addr_union(message, NHA_GATEWAY, tmp->family, &tmp->gw);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: could not get NHA_ID attribute, ignoring: %m");
+ return 0;
+ }
+
+ (void) nexthop_get(link, tmp, &nexthop);
+
+ if (DEBUG_LOGGING)
+ (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway);
+
+ switch (type) {
+ case RTM_NEWNEXTHOP:
+ if (nexthop)
+ log_link_debug(link, "Received remembered nexthop: %s, id: %d", strna(gateway), tmp->id);
+ else {
+ log_link_debug(link, "Remembering foreign nexthop: %s, id: %d", strna(gateway), tmp->id);
+ r = nexthop_add_foreign(link, tmp, &nexthop);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m");
+ return 0;
+ }
+ }
+ break;
+ case RTM_DELNEXTHOP:
+ if (nexthop) {
+ log_link_debug(link, "Forgetting nexthop: %s, id: %d", strna(gateway), tmp->id);
+ nexthop_free(nexthop);
+ } else
+ log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, id: %d, ignoring.",
+ strna(gateway), tmp->id);
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type");
+ }
+
+ return 1;
+}
+
+static int nexthop_section_verify(NextHop *nh) {
if (section_is_invalid(nh->section))
return -EINVAL;
return 0;
}
+void network_drop_invalid_nexthops(Network *network) {
+ NextHop *nh;
+
+ assert(network);
+
+ HASHMAP_FOREACH(nh, network->nexthops_by_section)
+ if (nexthop_section_verify(nh) < 0)
+ nexthop_free(nh);
+}
+
int config_parse_nexthop_id(
const char *unit,
const char *filename,
#pragma once
-#include "conf-parser.h"
-#include "macro.h"
+#include <inttypes.h>
-typedef struct NextHop NextHop;
-typedef struct NetworkConfigSection NetworkConfigSection;
+#include "sd-netlink.h"
-#include "networkd-network.h"
+#include "conf-parser.h"
+#include "in-addr-util.h"
#include "networkd-util.h"
-struct NextHop {
+typedef struct Link Link;
+typedef struct Manager Manager;
+typedef struct Network Network;
+
+typedef struct NextHop {
Network *network;
NetworkConfigSection *section;
unsigned char protocol;
- int family;
- uint32_t oif;
uint32_t id;
-
+ int family;
union in_addr_union gw;
+} NextHop;
- LIST_FIELDS(NextHop, nexthops);
-};
-
-extern const struct hash_ops nexthop_hash_ops;
-
-int nexthop_new(NextHop **ret);
-void nexthop_free(NextHop *nexthop);
-int nexthop_configure(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback);
-int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback);
+NextHop *nexthop_free(NextHop *nexthop);
-int nexthop_get(Link *link, NextHop *in, NextHop **ret);
-int nexthop_add(Link *link, NextHop *in, NextHop **ret);
-int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret);
-bool nexthop_equal(NextHop *r1, NextHop *r2);
+void network_drop_invalid_nexthops(Network *network);
-int nexthop_section_verify(NextHop *nexthop);
+int link_set_nexthop(Link *link);
-DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free);
+int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway);
#include <arpa/inet.h>
#include "dns-domain.h"
-#include "networkd-address.h"
+#include "networkd-link.h"
#include "networkd-manager.h"
+#include "networkd-network.h"
#include "networkd-radv.h"
#include "parse-util.h"
-#include "sd-radv.h"
#include "string-util.h"
#include "string-table.h"
#include "strv.h"
-void prefix_free(Prefix *prefix) {
+Prefix *prefix_free(Prefix *prefix) {
if (!prefix)
- return;
+ return NULL;
if (prefix->network) {
- LIST_REMOVE(prefixes, prefix->network->static_prefixes, prefix);
- assert(prefix->network->n_static_prefixes > 0);
- prefix->network->n_static_prefixes--;
-
- if (prefix->section)
- hashmap_remove(prefix->network->prefixes_by_section,
- prefix->section);
+ assert(prefix->section);
+ hashmap_remove(prefix->network->prefixes_by_section, prefix->section);
}
network_config_section_free(prefix->section);
sd_radv_prefix_unref(prefix->radv_prefix);
- free(prefix);
+ return mfree(prefix);
}
+DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
+
static int prefix_new(Prefix **ret) {
_cleanup_(prefix_freep) Prefix *prefix = NULL;
return 0;
}
-static int prefix_new_static(Network *network, const char *filename,
- unsigned section_line, Prefix **ret) {
+static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(prefix_freep) Prefix *prefix = NULL;
int r;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- if (section_line) {
- prefix = hashmap_get(network->prefixes_by_section, n);
- if (prefix) {
- *ret = TAKE_PTR(prefix);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
- }
+ prefix = hashmap_get(network->prefixes_by_section, n);
+ if (prefix) {
+ *ret = TAKE_PTR(prefix);
+ return 0;
}
r = prefix_new(&prefix);
return r;
prefix->network = network;
- LIST_APPEND(prefixes, network->static_prefixes, prefix);
- network->n_static_prefixes++;
-
- if (filename) {
- prefix->section = TAKE_PTR(n);
+ prefix->section = TAKE_PTR(n);
- r = hashmap_ensure_allocated(&network->prefixes_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->prefixes_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->prefixes_by_section, prefix->section, prefix);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->prefixes_by_section, prefix->section, prefix);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(prefix);
return 0;
}
+RoutePrefix *route_prefix_free(RoutePrefix *prefix) {
+ if (!prefix)
+ return NULL;
+
+ if (prefix->network) {
+ assert(prefix->section);
+ hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section);
+ }
+
+ network_config_section_free(prefix->section);
+ sd_radv_route_prefix_unref(prefix->radv_route_prefix);
+
+ return mfree(prefix);
+}
+
+DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
+
static int route_prefix_new(RoutePrefix **ret) {
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
return 0;
}
-void route_prefix_free(RoutePrefix *prefix) {
- if (!prefix)
- return;
-
- if (prefix->network) {
- LIST_REMOVE(route_prefixes, prefix->network->static_route_prefixes, prefix);
- assert(prefix->network->n_static_route_prefixes > 0);
- prefix->network->n_static_route_prefixes--;
-
- if (prefix->section)
- hashmap_remove(prefix->network->route_prefixes_by_section,
- prefix->section);
- }
-
- network_config_section_free(prefix->section);
- sd_radv_route_prefix_unref(prefix->radv_route_prefix);
-
- free(prefix);
-}
-
-static int route_prefix_new_static(Network *network, const char *filename,
- unsigned section_line, RoutePrefix **ret) {
+static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
int r;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- if (section_line) {
- prefix = hashmap_get(network->route_prefixes_by_section, n);
- if (prefix) {
- *ret = TAKE_PTR(prefix);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
- }
+ prefix = hashmap_get(network->route_prefixes_by_section, n);
+ if (prefix) {
+ *ret = TAKE_PTR(prefix);
+ return 0;
}
r = route_prefix_new(&prefix);
return r;
prefix->network = network;
- LIST_APPEND(route_prefixes, network->static_route_prefixes, prefix);
- network->n_static_route_prefixes++;
-
- if (filename) {
- prefix->section = TAKE_PTR(n);
+ prefix->section = TAKE_PTR(n);
- r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(prefix);
return 0;
}
-int config_parse_prefix(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+void network_drop_invalid_prefixes(Network *network) {
+ Prefix *prefix;
+
+ assert(network);
+
+ HASHMAP_FOREACH(prefix, network->prefixes_by_section)
+ if (section_is_invalid(prefix->section))
+ prefix_free(prefix);
+}
+
+void network_drop_invalid_route_prefixes(Network *network) {
+ RoutePrefix *prefix;
+
+ assert(network);
+
+ HASHMAP_FOREACH(prefix, network->route_prefixes_by_section)
+ if (section_is_invalid(prefix->section))
+ route_prefix_free(prefix);
+}
+
+void network_adjust_radv(Network *network) {
+ assert(network);
+
+ /* After this function is called, network->router_prefix_delegation can be treated as a boolean. */
+
+ if (network->dhcp6_pd < 0)
+ /* For backward compatibility. */
+ network->dhcp6_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6);
+
+ if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
+ if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE)
+ log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
+ "Disabling IPv6PrefixDelegation=.", network->filename);
+
+ network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
+ }
+
+ if (network->router_prefix_delegation == RADV_PREFIX_DELEGATION_NONE) {
+ network->n_router_dns = 0;
+ network->router_dns = mfree(network->router_dns);
+ network->router_search_domains = ordered_set_free(network->router_search_domains);
+ }
+
+ if (!FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_STATIC)) {
+ network->prefixes_by_section = hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
+ network->route_prefixes_by_section = hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
+ }
+}
+
+int config_parse_prefix(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
return 0;
}
-int config_parse_prefix_flags(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_prefix_flags(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
int r;
return 0;
}
-int config_parse_prefix_lifetime(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_prefix_lifetime(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
usec_t usec;
return 0;
}
-int config_parse_route_prefix(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_prefix(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
Network *network = userdata;
_cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
return 0;
}
-int config_parse_route_prefix_lifetime(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_prefix_lifetime(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
usec_t usec;
return 0;
}
-static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
- size_t *n_dns) {
+static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresses, size_t *ret_size) {
_cleanup_free_ struct in6_addr *addresses = NULL;
- size_t i, n_addresses = 0, n_allocated = 0;
+ size_t n_addresses = 0, n_allocated = 0;
assert(network);
- assert(dns);
- assert(n_dns);
+ assert(ret_addresses);
+ assert(ret_size);
- for (i = 0; i < network->n_dns; i++) {
+ for (size_t i = 0; i < network->n_dns; i++) {
union in_addr_union *addr;
if (network->dns[i]->family != AF_INET6)
addresses[n_addresses++] = addr->in6;
}
- if (addresses) {
- *dns = TAKE_PTR(addresses);
-
- *n_dns = n_addresses;
- }
+ *ret_addresses = TAKE_PTR(addresses);
+ *ret_size = n_addresses;
return n_addresses;
}
lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC;
- r = radv_get_ip6dns(link->network, &dns, &n_dns);
+ r = network_get_ipv6_dns(link->network, &dns, &n_dns);
if (r > 0)
goto set_dns;
return 0;
}
- r = radv_get_ip6dns(uplink->network, &dns, &n_dns);
+ r = network_get_ipv6_dns(uplink->network, &dns, &n_dns);
if (r > 0)
goto set_dns;
}
return 0;
}
+static bool link_radv_enabled(Link *link) {
+ assert(link);
+
+ if (!link_ipv6ll_enabled(link))
+ return false;
+
+ return link->network->router_prefix_delegation;
+}
+
int radv_configure(Link *link) {
RoutePrefix *q;
Prefix *p;
assert(link);
assert(link->network);
+ if (!link_radv_enabled(link))
+ return 0;
+
r = sd_radv_new(&link->radv);
if (r < 0)
return r;
- r = sd_radv_attach_event(link->radv, NULL, 0);
+ r = sd_radv_attach_event(link->radv, link->manager->event, 0);
if (r < 0)
return r;
return r;
}
- if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) {
- LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
- r = sd_radv_add_prefix(link->radv, p->radv_prefix, false);
- if (r == -EEXIST)
- continue;
- if (r == -ENOEXEC) {
- log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section.");
- continue;
- }
- if (r < 0)
- return r;
+ HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
+ r = sd_radv_add_prefix(link->radv, p->radv_prefix, false);
+ if (r == -EEXIST)
+ continue;
+ if (r == -ENOEXEC) {
+ log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section.");
+ continue;
}
+ if (r < 0)
+ return r;
+ }
- LIST_FOREACH(route_prefixes, q, link->network->static_route_prefixes) {
- r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
+ HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) {
+ r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false);
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int radv_update_mac(Link *link) {
+ bool restart;
+ int r;
+
+ assert(link);
+
+ if (!link->radv)
+ return 0;
+
+ restart = sd_radv_is_running(link->radv);
+
+ r = sd_radv_stop(link->radv);
+ if (r < 0)
+ return r;
+
+ r = sd_radv_set_mac(link->radv, &link->mac);
+ if (r < 0)
+ return r;
+
+ if (restart) {
+ r = sd_radv_start(link->radv);
+ if (r < 0)
+ return r;
}
return 0;
}
-int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
- uint32_t lifetime_preferred, uint32_t lifetime_valid) {
+int radv_add_prefix(
+ Link *link,
+ const struct in6_addr *prefix,
+ uint8_t prefix_len,
+ uint32_t lifetime_preferred,
+ uint32_t lifetime_valid) {
+
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
int r;
assert(lvalue);
assert(rvalue);
+ if (isempty(rvalue)) {
+ n->n_router_dns = 0;
+ n->router_dns = mfree(n->router_dns);
+ return 0;
+ }
+
for (const char *p = rvalue;;) {
_cleanup_free_ char *w = NULL;
union in_addr_union a;
assert(lvalue);
assert(rvalue);
+ if (isempty(rvalue)) {
+ n->router_search_domains = ordered_set_free(n->router_search_domains);
+ return 0;
+ }
+
for (const char *p = rvalue;;) {
_cleanup_free_ char *w = NULL, *idna = NULL;
/* transfer ownership to simplify subsequent operations */
idna = TAKE_PTR(w);
- r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
+ r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops_free);
if (r < 0)
return log_oom();
}
static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
- [RADV_PREFIX_DELEGATION_NONE] = "no",
+ [RADV_PREFIX_DELEGATION_NONE] = "no",
[RADV_PREFIX_DELEGATION_STATIC] = "static",
- [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
- [RADV_PREFIX_DELEGATION_BOTH] = "yes",
+ [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
+ [RADV_PREFIX_DELEGATION_BOTH] = "yes",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
RADVPrefixDelegation,
RADV_PREFIX_DELEGATION_BOTH);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_router_prefix_delegation,
- radv_prefix_delegation,
- RADVPrefixDelegation,
- "Invalid router prefix delegation");
-
-int config_parse_router_preference(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_router_prefix_delegation(
+ 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) {
+
+ RADVPrefixDelegation val, *ra = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (streq(lvalue, "IPv6SendRA")) {
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users
+ * need to explicitly enable DHCPv6PrefixDelegation=. */
+ *ra = r ? RADV_PREFIX_DELEGATION_STATIC : RADV_PREFIX_DELEGATION_NONE;
+ return 0;
+ }
+
+ /* For backward compatibility */
+ val = radv_prefix_delegation_from_string(rvalue);
+ if (val < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ *ra = val;
+ return 0;
+}
+
+int config_parse_router_preference(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
assert(filename);
Copyright © 2017 Intel Corporation. All rights reserved.
***/
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "sd-radv.h"
+
+#include "in-addr-util.h"
#include "conf-parser.h"
-#include "networkd-address.h"
-#include "networkd-link.h"
#include "networkd-util.h"
-typedef struct Prefix Prefix;
-typedef struct RoutePrefix RoutePrefix;
+typedef struct Network Network;
+typedef struct Link Link;
typedef enum RADVPrefixDelegation {
RADV_PREFIX_DELEGATION_NONE = 0,
_RADV_PREFIX_DELEGATION_INVALID = -1,
} RADVPrefixDelegation;
-struct Prefix {
+typedef struct Prefix {
Network *network;
NetworkConfigSection *section;
sd_radv_prefix *radv_prefix;
bool assign;
+} Prefix;
- LIST_FIELDS(Prefix, prefixes);
-};
-
-struct RoutePrefix {
+typedef struct RoutePrefix {
Network *network;
NetworkConfigSection *section;
sd_radv_route_prefix *radv_route_prefix;
+} RoutePrefix;
- LIST_FIELDS(RoutePrefix, route_prefixes);
-};
-
-void prefix_free(Prefix *prefix);
-
-DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
-
-void route_prefix_free(RoutePrefix *prefix);
+Prefix *prefix_free(Prefix *prefix);
+RoutePrefix *route_prefix_free(RoutePrefix *prefix);
-DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
+void network_drop_invalid_prefixes(Network *network);
+void network_drop_invalid_route_prefixes(Network *network);
+void network_adjust_radv(Network *network);
int radv_emit_dns(Link *link);
int radv_configure(Link *link);
+int radv_update_mac(Link *link);
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid);
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <linux/icmpv6.h>
+#include <linux/ipv6_route.h>
#include "alloc-util.h"
-#include "conf-parser.h"
-#include "in-addr-util.h"
-#include "missing_network.h"
#include "netlink-util.h"
#include "networkd-ipv4ll.h"
#include "networkd-manager.h"
-#include "networkd-ndisc.h"
+#include "networkd-network.h"
+#include "networkd-nexthop.h"
#include "networkd-route.h"
+#include "networkd-routing-policy-rule.h"
#include "parse-util.h"
-#include "set.h"
#include "socket-netlink.h"
#include "string-table.h"
#include "string-util.h"
#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
+static uint32_t link_get_vrf_table(const Link *link) {
+ return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN;
+}
+
+uint32_t link_get_dhcp_route_table(const Link *link) {
+ /* When the interface is part of an VRF use the VRFs routing table, unless
+ * another table is explicitly specified. */
+ if (link->network->dhcp_route_table_set)
+ return link->network->dhcp_route_table;
+ return link_get_vrf_table(link);
+}
+
+uint32_t link_get_ipv6_accept_ra_route_table(const Link *link) {
+ if (link->network->ipv6_accept_ra_route_table_set)
+ return link->network->ipv6_accept_ra_route_table;
+ return link_get_vrf_table(link);
+}
+
+static const char * const route_type_table[__RTN_MAX] = {
+ [RTN_UNICAST] = "unicast",
+ [RTN_LOCAL] = "local",
+ [RTN_BROADCAST] = "broadcast",
+ [RTN_ANYCAST] = "anycast",
+ [RTN_MULTICAST] = "multicast",
+ [RTN_BLACKHOLE] = "blackhole",
+ [RTN_UNREACHABLE] = "unreachable",
+ [RTN_PROHIBIT] = "prohibit",
+ [RTN_THROW] = "throw",
+ [RTN_NAT] = "nat",
+ [RTN_XRESOLVE] = "xresolve",
+};
+
+assert_cc(__RTN_MAX <= UCHAR_MAX);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_type, int);
+
+static const char * const route_scope_table[] = {
+ [RT_SCOPE_UNIVERSE] = "global",
+ [RT_SCOPE_SITE] = "site",
+ [RT_SCOPE_LINK] = "link",
+ [RT_SCOPE_HOST] = "host",
+ [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;
+}
+
+static const char * const route_table_table[] = {
+ [RT_TABLE_DEFAULT] = "default",
+ [RT_TABLE_MAIN] = "main",
+ [RT_TABLE_LOCAL] = "local",
+};
+
+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) {
+ const char *s;
+ char *p = buf;
+
+ s = route_table_to_string(table);
+ if (s)
+ strpcpy(&p, size, s);
+ else
+ strpcpyf(&p, size, "%d", table);
+
+ return buf;
+}
+
+static const char * const route_protocol_table[] = {
+ [RTPROT_KERNEL] = "kernel",
+ [RTPROT_BOOT] = "boot",
+ [RTPROT_STATIC] = "static",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int);
+
+static const char * const route_protocol_full_table[] = {
+ [RTPROT_REDIRECT] = "redirect",
+ [RTPROT_KERNEL] = "kernel",
+ [RTPROT_BOOT] = "boot",
+ [RTPROT_STATIC] = "static",
+ [RTPROT_GATED] = "gated",
+ [RTPROT_RA] = "ra",
+ [RTPROT_MRT] = "mrt",
+ [RTPROT_ZEBRA] = "zebra",
+ [RTPROT_BIRD] = "bird",
+ [RTPROT_DNROUTED] = "dnrouted",
+ [RTPROT_XORP] = "xorp",
+ [RTPROT_NTK] = "ntk",
+ [RTPROT_DHCP] = "dhcp",
+ [RTPROT_MROUTED] = "mrouted",
+ [RTPROT_BABEL] = "babel",
+ [RTPROT_BGP] = "bgp",
+ [RTPROT_ISIS] = "isis",
+ [RTPROT_OSPF] = "ospf",
+ [RTPROT_RIP] = "rip",
+ [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;
+}
+
static unsigned routes_max(void) {
static thread_local unsigned cached = 0;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ assert(filename);
+ assert(section_line > 0);
- route = hashmap_get(network->routes_by_section, n);
- if (route) {
- *ret = TAKE_PTR(route);
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- return 0;
- }
+ route = hashmap_get(network->routes_by_section, n);
+ if (route) {
+ *ret = TAKE_PTR(route);
+ return 0;
}
- if (network->n_static_routes >= routes_max())
+ if (hashmap_size(network->routes_by_section) >= routes_max())
return -E2BIG;
r = route_new(&route);
route->protocol = RTPROT_STATIC;
route->network = network;
- LIST_PREPEND(routes, network->static_routes, route);
- network->n_static_routes++;
-
- if (filename) {
- route->section = TAKE_PTR(n);
+ route->section = TAKE_PTR(n);
- r = hashmap_ensure_allocated(&network->routes_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ r = hashmap_ensure_allocated(&network->routes_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- r = hashmap_put(network->routes_by_section, route->section, route);
- if (r < 0)
- return r;
- }
+ r = hashmap_put(network->routes_by_section, route->section, route);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(route);
-
return 0;
}
-void route_free(Route *route) {
+Route *route_free(Route *route) {
if (!route)
- return;
+ return NULL;
if (route->network) {
- LIST_REMOVE(routes, route->network->static_routes, route);
-
- assert(route->network->n_static_routes > 0);
- route->network->n_static_routes--;
-
- if (route->section)
- hashmap_remove(route->network->routes_by_section, route->section);
+ assert(route->section);
+ hashmap_remove(route->network->routes_by_section, route->section);
}
network_config_section_free(route->section);
free(set_remove(route->link->ndisc_routes, n));
}
+ if (route->manager) {
+ set_remove(route->manager->routes, route);
+ set_remove(route->manager->routes_foreign, route);
+ }
+
ordered_set_free_free(route->multipath_routes);
sd_event_source_unref(route->expire);
- free(route);
+ return mfree(route);
}
void route_hash_func(const Route *route, struct siphash *state) {
siphash24_compress(&route->src_prefixlen, sizeof(route->src_prefixlen), state);
siphash24_compress(&route->src, FAMILY_ADDRESS_SIZE(route->family), state);
- siphash24_compress(&route->gw, FAMILY_ADDRESS_SIZE(route->family), state);
+ siphash24_compress(&route->gw_family, sizeof(route->gw_family), state);
+ if (IN_SET(route->gw_family, AF_INET, AF_INET6)) {
+ siphash24_compress(&route->gw, FAMILY_ADDRESS_SIZE(route->gw_family), state);
+ siphash24_compress(&route->gw_weight, sizeof(route->gw_weight), state);
+ }
siphash24_compress(&route->prefsrc, FAMILY_ADDRESS_SIZE(route->family), state);
if (r != 0)
return r;
- r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
+ r = CMP(a->gw_family, b->gw_family);
if (r != 0)
return r;
+ if (IN_SET(a->gw_family, AF_INET, AF_INET6)) {
+ r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
+ if (r != 0)
+ return r;
+
+ r = CMP(a->gw_weight, b->gw_weight);
+ if (r != 0)
+ return r;
+ }
+
r = memcmp(&a->prefsrc, &b->prefsrc, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
return r;
route_compare_func,
route_free);
-bool route_equal(Route *r1, Route *r2) {
+static bool route_equal(const Route *r1, const Route *r2) {
if (r1 == r2)
return true;
return route_compare_func(r1, r2) == 0;
}
-int route_get(Link *link, Route *in, Route **ret) {
-
+static int route_get(const Manager *manager, const Link *link, const Route *in, Route **ret) {
Route *existing;
- assert(link);
+ assert(manager || link);
assert(in);
- existing = set_get(link->routes, in);
- if (existing) {
- if (ret)
- *ret = existing;
- return 1;
- }
+ if (link) {
+ existing = set_get(link->routes, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 1;
+ }
- existing = set_get(link->routes_foreign, in);
- if (existing) {
- if (ret)
- *ret = existing;
- return 0;
+ existing = set_get(link->routes_foreign, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
+ } else {
+ existing = set_get(manager->routes, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 1;
+ }
+
+ existing = set_get(manager->routes_foreign, in);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
}
return -ENOENT;
}
-static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret) {
+static void route_copy(Route *dest, const Route *src, const MultipathRoute *m) {
+ assert(dest);
+ assert(src);
+
+ dest->family = src->family;
+ dest->src = src->src;
+ dest->src_prefixlen = src->src_prefixlen;
+ dest->dst = src->dst;
+ dest->dst_prefixlen = src->dst_prefixlen;
+ dest->prefsrc = src->prefsrc;
+ dest->scope = src->scope;
+ dest->protocol = src->protocol;
+ dest->type = src->type;
+ dest->tos = src->tos;
+ dest->priority = src->priority;
+ dest->table = src->table;
+ dest->initcwnd = src->initcwnd;
+ dest->initrwnd = src->initrwnd;
+ dest->lifetime = src->lifetime;
+
+ if (m) {
+ dest->gw_family = m->gateway.family;
+ dest->gw = m->gateway.address;
+ dest->gw_weight = m->weight;
+ } else {
+ dest->gw_family = src->gw_family;
+ dest->gw = src->gw;
+ dest->gw_weight = src->gw_weight;
+ }
+}
+static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, Route **ret) {
_cleanup_(route_freep) Route *route = NULL;
int r;
- assert(link);
+ assert(manager || link);
assert(routes);
assert(in);
if (r < 0)
return r;
- route->family = in->family;
- route->src = in->src;
- route->src_prefixlen = in->src_prefixlen;
- route->dst = in->dst;
- route->dst_prefixlen = in->dst_prefixlen;
- route->gw = in->gw;
- route->prefsrc = in->prefsrc;
- route->scope = in->scope;
- route->protocol = in->protocol;
- route->type = in->type;
- route->tos = in->tos;
- route->priority = in->priority;
- route->table = in->table;
- route->initcwnd = in->initcwnd;
- route->initrwnd = in->initrwnd;
- route->lifetime = in->lifetime;
+ route_copy(route, in, NULL);
r = set_ensure_put(routes, &route_hash_ops, route);
if (r < 0)
return -EEXIST;
route->link = link;
+ route->manager = manager;
if (ret)
*ret = route;
return 0;
}
-int route_add_foreign(Link *link, Route *in, Route **ret) {
- return route_add_internal(link, &link->routes_foreign, in, ret);
+static int route_add_foreign(Manager *manager, Link *link, const Route *in, Route **ret) {
+ assert(manager || link);
+ return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, ret);
}
-int route_add(Link *link, Route *in, Route **ret) {
-
+static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) {
+ _cleanup_(route_freep) Route *tmp = NULL;
Route *route;
int r;
- r = route_get(link, in, &route);
+ assert(manager || link);
+ assert(in);
+
+ if (m) {
+ assert(link && (m->ifindex == 0 || m->ifindex == link->ifindex));
+
+ r = route_new(&tmp);
+ if (r < 0)
+ return r;
+
+ route_copy(tmp, in, m);
+ in = tmp;
+ }
+
+ r = route_get(manager, link, in, &route);
if (r == -ENOENT) {
/* Route does not exist, create a new one */
- r = route_add_internal(link, &link->routes, in, &route);
+ r = route_add_internal(manager, link, link ? &link->routes : &manager->routes, in, &route);
if (r < 0)
return r;
} else if (r == 0) {
/* Take over a foreign route */
- r = set_ensure_put(&link->routes, &route_hash_ops, route);
- if (r < 0)
- return r;
+ if (link) {
+ r = set_ensure_put(&link->routes, &route_hash_ops, route);
+ if (r < 0)
+ return r;
+
+ set_remove(link->routes_foreign, route);
+ } else {
+ r = set_ensure_put(&manager->routes, &route_hash_ops, route);
+ if (r < 0)
+ return r;
- set_remove(link->routes_foreign, route);
+ set_remove(manager->routes_foreign, route);
+ }
} else if (r == 1) {
/* Route exists, do nothing */
;
int r;
assert(m);
- assert(link);
- assert(link->ifname);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ /* Note that link may be NULL. */
+ if (link && IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
return 1;
}
-int route_remove(Route *route, Link *link,
- link_netlink_message_handler_t callback) {
+int route_remove(
+ const Route *route,
+ Manager *manager,
+ Link *link,
+ link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
- assert(link);
- assert(link->manager);
- assert(link->manager->rtnl);
- assert(link->ifindex > 0);
+ assert(link || manager);
assert(IN_SET(route->family, AF_INET, AF_INET6));
- r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
+ if (!manager)
+ manager = link->manager;
+ /* link may be NULL! */
+
+ r = sd_rtnl_message_new_route(manager->rtnl, &req,
RTM_DELROUTE, route->family,
route->protocol);
if (r < 0)
}
if (!in_addr_is_null(route->family, &route->src))
(void) in_addr_to_string(route->family, &route->src, &src);
- if (!in_addr_is_null(route->family, &route->gw))
- (void) in_addr_to_string(route->family, &route->gw, &gw);
+ if (!in_addr_is_null(route->gw_family, &route->gw))
+ (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);
strna(route_type_to_string(route->type)));
}
- if (in_addr_is_null(route->family, &route->gw) == 0) {
- r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
+ if (in_addr_is_null(route->gw_family, &route->gw) == 0) {
+ if (route->gw_family == route->family) {
+ r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
+ } else {
+ RouteVia rtvia = {
+ .family = route->gw_family,
+ .address = route->gw,
+ };
+
+ r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
+ }
}
if (route->dst_prefixlen) {
return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
+ assert(link); /* Those routes must be attached to a specific link */
+
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
- link_ref(link);
+ link_ref(link); /* link may be NULL, link_ref() is OK with that */
return 0;
}
-int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
+static bool link_is_static_route_configured(const Link *link, const Route *route) {
+ Route *net_route;
+
+ assert(link);
+ assert(route);
+
+ if (!link->network)
+ return false;
+
+ HASHMAP_FOREACH(net_route, link->network->routes_by_section)
+ if (route_equal(net_route, route))
+ return true;
+
+ return false;
+}
+
+int link_drop_foreign_routes(Link *link) {
+ Route *route;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(route, link->routes_foreign) {
+ /* do not touch routes managed by the kernel */
+ if (route->protocol == RTPROT_KERNEL)
+ continue;
+
+ /* do not touch multicast route added by kernel */
+ /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that.
+ * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */
+ if (route->protocol == RTPROT_BOOT &&
+ route->family == AF_INET6 &&
+ route->dst_prefixlen == 8 &&
+ in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} }))
+ continue;
+
+ if (route->protocol == RTPROT_STATIC && link->network &&
+ FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC))
+ continue;
+
+ if (route->protocol == RTPROT_DHCP && link->network &&
+ FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
+ continue;
+
+ if (link_is_static_route_configured(link, route))
+ k = route_add(NULL, link, route, NULL, NULL);
+ else
+ k = route_remove(route, NULL, link, NULL);
+ if (k < 0 && r >= 0)
+ r = k;
+ }
+
+ return r;
+}
+
+int link_drop_routes(Link *link) {
+ Route *route;
+ int k, r = 0;
+
+ assert(link);
+
+ SET_FOREACH(route, link->routes) {
+ /* do not touch routes managed by the kernel */
+ if (route->protocol == RTPROT_KERNEL)
+ continue;
+
+ k = route_remove(route, NULL, link, NULL);
+ if (k < 0 && r >= 0)
+ r = k;
+ }
+
+ return r;
+}
+
+static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
Route *route = userdata;
int r;
assert(route);
- r = route_remove(route, route->link, NULL);
- if (r < 0)
+ r = route_remove(route, route->manager, route->link, NULL);
+ if (r < 0) {
log_link_warning_errno(route->link, r, "Could not remove route: %m");
- else
route_free(route);
+ }
return 1;
}
-static int append_nexthop_one(Route *route, MultipathRoute *m, struct rtattr **rta, size_t offset) {
+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;
+
+ assert(link);
+ assert(route);
+
+ if (IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW))
+ r = 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);
+ else {
+ Link *link_gw;
+
+ r = link_get(link->manager, m->ifindex, &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);
+ }
+ if (r < 0)
+ return log_link_error_errno(link, r, "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()) {
+ r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
+ nr->lifetime, 0, route_expire_handler, nr);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not arm expiration timer: %m");
+ }
+
+ sd_event_source_unref(nr->expire);
+ nr->expire = TAKE_PTR(expire);
+
+ if (ret)
+ *ret = nr;
+
+ return 0;
+}
+
+static int append_nexthop_one(const Route *route, const MultipathRoute *m, struct rtattr **rta, size_t offset) {
struct rtnexthop *rtnh;
struct rtattr *new_rta;
int r;
return r;
}
-static int append_nexthops(Route *route, sd_netlink_message *req) {
+static int append_nexthops(const Route *route, sd_netlink_message *req) {
_cleanup_free_ struct rtattr *rta = NULL;
struct rtnexthop *rtnh;
MultipathRoute *m;
}
int route_configure(
- Route *route,
+ const Route *route,
Link *link,
link_netlink_message_handler_t callback,
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
+ unsigned flags;
int r;
assert(link);
assert(IN_SET(route->family, AF_INET, AF_INET6));
assert(callback);
- if (route_get(link, route, NULL) <= 0 &&
+ if (route_get(link->manager, link, route, NULL) <= 0 &&
set_size(link->routes) >= routes_max())
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
"Too many routes are configured, refusing: %m");
}
if (!in_addr_is_null(route->family, &route->src))
(void) in_addr_to_string(route->family, &route->src, &src);
- if (!in_addr_is_null(route->family, &route->gw))
- (void) in_addr_to_string(route->family, &route->gw, &gw);
+ if (!in_addr_is_null(route->gw_family, &route->gw))
+ (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);
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
- if (in_addr_is_null(route->family, &route->gw) == 0) {
- r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
+ if (in_addr_is_null(route->gw_family, &route->gw) == 0) {
+ if (route->gw_family == route->family) {
+ r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
+ } else {
+ RouteVia rtvia = {
+ .family = route->gw_family,
+ .address = route->gw,
+ };
- r = sd_rtnl_message_route_set_family(req, route->family);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set route family: %m");
+ r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
+ }
}
if (route->dst_prefixlen > 0) {
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
+ flags = route->flags;
if (route->gateway_onlink >= 0)
- SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
+ SET_FLAG(flags, RTNH_F_ONLINK, route->gateway_onlink);
- r = sd_rtnl_message_route_set_flags(req, route->flags);
+ r = sd_rtnl_message_route_set_flags(req, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
}
}
- r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
+ r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
+
+ r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
+
+ if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
+ r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
+ DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
+ }
+
+ r = sd_rtnl_message_route_set_type(req, route->type);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set route type: %m");
+
+ if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
+ r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
+ }
+
+ if (route->ttl_propagate >= 0) {
+ r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m");
+ }
+
+ r = sd_netlink_message_open_container(req, RTA_METRICS);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
+
+ if (route->mtu > 0) {
+ r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
+ }
+
+ if (route->initcwnd > 0) {
+ r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
+ }
+
+ if (route->initrwnd > 0) {
+ r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
+ }
+
+ if (route->quickack >= 0) {
+ r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
+ }
+
+ if (route->fast_open_no_cookie >= 0) {
+ r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
+
+ r = append_nexthops(route, req);
+ if (r < 0)
+ 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;
+ } else {
+ MultipathRoute *m;
+
+ assert(!ret);
+
+ ORDERED_SET_FOREACH(m, route->multipath_routes) {
+ r = route_add_and_setup_timer(link, route, m, NULL);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
+ 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 route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+ assert(link->route_messages > 0);
+ assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
+ LINK_STATE_FAILED, LINK_STATE_LINGER));
+
+ link->route_messages--;
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST) {
+ log_link_message_warning_errno(link, m, r, "Could not set route");
+ link_enter_failed(link);
+ return 1;
+ }
+
+ if (link->route_messages == 0) {
+ log_link_debug(link, "Routes set");
+ link->static_routes_configured = true;
+ link_set_nexthop(link);
+ }
+
+ return 1;
+}
+
+int link_set_routes(Link *link) {
+ enum {
+ PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
+ PHASE_GATEWAY, /* Second phase: Routes with a gateway */
+ _PHASE_MAX
+ } phase;
+ Route *rt;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->state != _LINK_STATE_INVALID);
+
+ link->static_routes_configured = false;
+
+ if (!link->addresses_ready)
+ return 0;
+
+ if (!link_has_carrier(link) && !link->network->configure_without_carrier)
+ /* During configuring addresses, the link lost its carrier. As networkd is dropping
+ * the addresses now, let's not configure the routes either. */
+ return 0;
+
+ r = link_set_routing_policy_rules(link);
+ if (r < 0)
+ return r;
+
+ /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
+ for (phase = 0; phase < _PHASE_MAX; phase++)
+ HASHMAP_FOREACH(rt, link->network->routes_by_section) {
+ if (rt->gateway_from_dhcp_or_ra)
+ continue;
+
+ if ((in_addr_is_null(rt->gw_family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
+ continue;
+
+ r = route_configure(rt, link, route_handler, NULL);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set routes: %m");
+
+ link->route_messages++;
+ }
+
+ if (link->route_messages == 0) {
+ link->static_routes_configured = true;
+ link_set_nexthop(link);
+ } else {
+ log_link_debug(link, "Setting routes");
+ link_set_state(link, LINK_STATE_CONFIGURING);
+ }
+
+ return 0;
+}
+
+static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) {
+ _cleanup_(route_freep) Route *nr = NULL;
+ Route *route = NULL;
+ int r;
+
+ assert(manager);
+ assert(tmp);
+ assert(IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE));
+
+ if (m) {
+ if (link)
+ return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL),
+ "rtnl: received route contains both RTA_OIF and RTA_MULTIPATH, ignoring.");
+
+ if (m->ifindex <= 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "rtnl: received multipath route with invalid ifindex, ignoring.");
+
+ r = link_get(manager, m->ifindex, &link);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received multipath route for link (%d) we do not know, ignoring: %m", m->ifindex);
+ return 0;
+ }
+
+ r = route_new(&nr);
+ if (r < 0)
+ return log_oom();
+
+ route_copy(nr, tmp, m);
+
+ tmp = nr;
+ }
+
+ (void) route_get(manager, link, tmp, &route);
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL,
+ *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL;
+ char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX],
+ buf_protocol[ROUTE_PROTOCOL_STR_MAX];
+
+ if (!in_addr_is_null(tmp->family, &tmp->dst)) {
+ (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst);
+ (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen);
+ }
+ if (!in_addr_is_null(tmp->family, &tmp->src))
+ (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src);
+ if (!in_addr_is_null(tmp->gw_family, &tmp->gw))
+ (void) in_addr_to_string(tmp->gw_family, &tmp->gw, &buf_gw);
+ if (!in_addr_is_null(tmp->family, &tmp->prefsrc))
+ (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc);
+
+ log_link_debug(link,
+ "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
+ (!route && !manager->manage_foreign_routes) ? "Ignoring received foreign" :
+ type == RTM_DELROUTE ? "Forgetting" :
+ route ? "Received remembered" : "Remembering",
+ strna(buf_dst), strempty(buf_dst_prefixlen),
+ strna(buf_src), strna(buf_gw), strna(buf_prefsrc),
+ format_route_scope(tmp->scope, buf_scope, sizeof buf_scope),
+ format_route_table(tmp->table, buf_table, sizeof buf_table),
+ format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol),
+ strna(route_type_to_string(tmp->type)));
+ }
+
+ switch (type) {
+ case RTM_NEWROUTE:
+ if (!route && manager->manage_foreign_routes) {
+ /* A route appeared that we did not request */
+ r = route_add_foreign(manager, link, tmp, NULL);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
+ return 0;
+ }
+ }
+
+ break;
+
+ case RTM_DELROUTE:
+ route_free(route);
+ break;
+
+ default:
+ assert_not_reached("Received route message with invalid RTNL message type");
+ }
+
+ return 1;
+}
+
+int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
+ _cleanup_ordered_set_free_free_ OrderedSet *multipath_routes = NULL;
+ _cleanup_(route_freep) Route *tmp = NULL;
+ _cleanup_free_ void *rta_multipath = NULL;
+ Link *link = NULL;
+ uint32_t ifindex;
+ uint16_t type;
+ unsigned char table;
+ RouteVia via;
+ size_t rta_len;
+ int r;
+
+ assert(rtnl);
+ assert(message);
+ assert(m);
+
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring");
+
+ return 0;
+ }
+
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) {
+ log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type);
+ return 0;
+ }
+
+ r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ if (ifindex <= 0) {
+ log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex);
+ return 0;
+ }
+
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ /* when enumerating we might be out of sync, but we will
+ * get the route again, so just ignore it */
+ if (!m->enumerating)
+ log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex);
+ return 0;
+ }
+ }
+
+ r = route_new(&tmp);
+ if (r < 0)
+ return log_oom();
+
+ r = sd_rtnl_message_route_get_family(message, &tmp->family);
+ if (r < 0) {
+ log_link_warning(link, "rtnl: received route message without family, ignoring");
+ return 0;
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+ log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family);
+ return 0;
+ }
+
+ r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received route message without route protocol: %m");
+ return 0;
+ }
+
+ switch (tmp->family) {
+ case AF_INET:
+ r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
+ return 0;
+ } else if (r >= 0)
+ tmp->gw_family = AF_INET;
+
+ r = sd_netlink_message_read(message, RTA_VIA, sizeof(via), &via);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ tmp->gw_family = via.family;
+ tmp->gw = via.address;
+ }
+
+ r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ case AF_INET6:
+ r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
+ return 0;
+ } else if (r >= 0)
+ tmp->gw_family = AF_INET6;
+
+ r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Received route message with unsupported address family");
+ return 0;
+ }
+
+ r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_route_get_scope(message, &tmp->scope);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m");
+ return 0;
+ }
- r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
+ r = sd_rtnl_message_route_get_tos(message, &tmp->tos);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m");
+ return 0;
+ }
- if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
- r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
- DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
+ r = sd_rtnl_message_route_get_type(message, &tmp->type);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m");
+ return 0;
}
- r = sd_rtnl_message_route_set_type(req, route->type);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set route type: %m");
+ r = sd_rtnl_message_route_get_table(message, &table);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m");
+ return 0;
+ }
+ tmp->table = table;
- if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
- r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
+ r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m");
+ return 0;
}
- if (route->ttl_propagate >= 0) {
- r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m");
+ r = sd_netlink_message_enter_container(message, RTA_METRICS);
+ if (r < 0 && r != -ENODATA) {
+ log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m");
+ return 0;
}
+ if (r >= 0) {
+ r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m");
+ return 0;
+ }
- r = sd_netlink_message_open_container(req, RTA_METRICS);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
+ r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m");
+ return 0;
+ }
- if (route->mtu > 0) {
- r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
+ r = sd_netlink_message_exit_container(message);
+ if (r < 0) {
+ log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m");
+ return 0;
+ }
}
- if (route->initcwnd > 0) {
- r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
+ r = sd_netlink_message_read_data(message, RTA_MULTIPATH, &rta_len, &rta_multipath);
+ if (r < 0 && r != -ENODATA) {
+ log_link_warning_errno(link, r, "rtnl: failed to read RTA_MULTIPATH attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ r = rtattr_read_nexthop(rta_multipath, rta_len, tmp->family, &multipath_routes);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: failed to parse RTA_MULTIPATH attribute, ignoring: %m");
+ return 0;
+ }
}
- if (route->initrwnd > 0) {
- r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
- }
+ if (ordered_set_isempty(multipath_routes))
+ (void) process_route_one(m, link, type, tmp, NULL);
+ else {
+ MultipathRoute *mr;
- if (route->quickack >= 0) {
- r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
+ ORDERED_SET_FOREACH(mr, multipath_routes) {
+ r = process_route_one(m, link, type, tmp, mr);
+ if (r < 0)
+ break;
+ }
}
- if (route->fast_open_no_cookie >= 0) {
- r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
+ return 1;
+}
+
+int link_serialize_routes(const Link *link, FILE *f) {
+ bool space = false;
+ Route *route;
+
+ assert(link);
+ assert(link->network);
+ assert(f);
+
+ fputs("ROUTES=", f);
+ SET_FOREACH(route, link->routes) {
+ _cleanup_free_ char *route_str = NULL;
+
+ if (in_addr_to_string(route->family, &route->dst, &route_str) < 0)
+ continue;
+
+ fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT,
+ space ? " " : "", route_str,
+ route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
+ space = true;
}
+ fputc('\n', f);
- r = sd_netlink_message_close_container(req);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
+ return 0;
+}
- r = append_nexthops(route, req);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
+int link_deserialize_routes(Link *link, const char *routes) {
+ int r;
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
- link_netlink_destroy_callback, link);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+ assert(link);
- link_ref(link);
+ for (const char *p = routes;; ) {
+ _cleanup_(route_freep) Route *tmp = NULL;
+ _cleanup_free_ char *route_str = NULL;
+ char *prefixlen_str;
- r = route_add(link, route, &route);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not add route: %m");
+ r = extract_first_word(&p, &route_str, NULL, 0);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to parse ROUTES=: %m");
+ if (r == 0)
+ return 0;
- /* TODO: drop expiration handling once it can be pushed into the kernel */
- if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
- r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
- route->lifetime, 0, route_expire_handler, route);
+ prefixlen_str = strchr(route_str, '/');
+ if (!prefixlen_str) {
+ log_link_debug(link, "Failed to parse route, ignoring: %s", route_str);
+ continue;
+ }
+ *prefixlen_str++ = '\0';
+
+ r = route_new(&tmp);
if (r < 0)
- return log_link_error_errno(link, r, "Could not arm expiration timer: %m");
- }
+ return log_oom();
- sd_event_source_unref(route->expire);
- route->expire = TAKE_PTR(expire);
+ r = sscanf(prefixlen_str,
+ "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT,
+ &tmp->dst_prefixlen,
+ &tmp->tos,
+ &tmp->priority,
+ &tmp->table,
+ &tmp->lifetime);
+ if (r != 5) {
+ log_link_debug(link,
+ "Failed to parse destination prefix length, tos, priority, table or expiration: %s",
+ prefixlen_str);
+ continue;
+ }
- if (ret)
- *ret = route;
+ r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst);
+ if (r < 0) {
+ log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str);
+ continue;
+ }
- return 1;
+ r = route_add_and_setup_timer(link, tmp, NULL, NULL);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to add route: %m");
+ }
}
int network_add_ipv4ll_route(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+ unsigned section_line;
int r;
assert(network);
if (!network->ipv4ll_route)
return 0;
+ section_line = hashmap_find_free_section_line(network->routes_by_section);
+
/* IPv4LLRoute= is in [Network] section. */
- r = route_new_static(network, NULL, 0, &n);
+ r = route_new_static(network, network->filename, section_line, &n);
if (r < 0)
return r;
int network_add_default_route_on_device(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+ unsigned section_line;
int r;
assert(network);
if (!network->default_route_on_device)
return 0;
+ section_line = hashmap_find_free_section_line(network->routes_by_section);
+
/* DefaultRouteOnDevice= is in [Network] section. */
- r = route_new_static(network, NULL, 0, &n);
+ r = route_new_static(network, network->filename, section_line, &n);
if (r < 0)
return r;
return 0;
}
-static const char * const route_type_table[__RTN_MAX] = {
- [RTN_UNICAST] = "unicast",
- [RTN_LOCAL] = "local",
- [RTN_BROADCAST] = "broadcast",
- [RTN_ANYCAST] = "anycast",
- [RTN_MULTICAST] = "multicast",
- [RTN_BLACKHOLE] = "blackhole",
- [RTN_UNREACHABLE] = "unreachable",
- [RTN_PROHIBIT] = "prohibit",
- [RTN_THROW] = "throw",
- [RTN_NAT] = "nat",
- [RTN_XRESOLVE] = "xresolve",
-};
-
-assert_cc(__RTN_MAX <= UCHAR_MAX);
-DEFINE_STRING_TABLE_LOOKUP(route_type, int);
-
-static const char * const route_scope_table[] = {
- [RT_SCOPE_UNIVERSE] = "global",
- [RT_SCOPE_SITE] = "site",
- [RT_SCOPE_LINK] = "link",
- [RT_SCOPE_HOST] = "host",
- [RT_SCOPE_NOWHERE] = "nowhere",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int);
-
-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;
-}
-
-static const char * const route_table_table[] = {
- [RT_TABLE_DEFAULT] = "default",
- [RT_TABLE_MAIN] = "main",
- [RT_TABLE_LOCAL] = "local",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int);
-
-const char *format_route_table(int table, char *buf, size_t size) {
- const char *s;
- char *p = buf;
-
- s = route_table_to_string(table);
- if (s)
- strpcpy(&p, size, s);
- else
- strpcpyf(&p, size, "%d", table);
-
- return buf;
-}
-
-static const char * const route_protocol_table[] = {
- [RTPROT_KERNEL] = "kernel",
- [RTPROT_BOOT] = "boot",
- [RTPROT_STATIC] = "static",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int);
-
-static const char * const route_protocol_full_table[] = {
- [RTPROT_REDIRECT] = "redirect",
- [RTPROT_KERNEL] = "kernel",
- [RTPROT_BOOT] = "boot",
- [RTPROT_STATIC] = "static",
- [RTPROT_GATED] = "gated",
- [RTPROT_RA] = "ra",
- [RTPROT_MRT] = "mrt",
- [RTPROT_ZEBRA] = "zebra",
- [RTPROT_BIRD] = "bird",
- [RTPROT_DNROUTED] = "dnrouted",
- [RTPROT_XORP] = "xorp",
- [RTPROT_NTK] = "ntk",
- [RTPROT_DHCP] = "dhcp",
- [RTPROT_MROUTED] = "mrouted",
- [RTPROT_BABEL] = "babel",
- [RTPROT_BGP] = "bgp",
- [RTPROT_ISIS] = "isis",
- [RTPROT_OSPF] = "ospf",
- [RTPROT_RIP] = "rip",
- [RTPROT_EIGRP] = "eigrp",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int);
-
-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;
-}
-
int config_parse_gateway(
const char *unit,
const char *filename,
assert(data);
if (streq(section, "Network")) {
- /* we are not in an Route section, so treat
- * this as the special '0' section */
- r = route_new_static(network, NULL, 0, &n);
+ /* we are not in an Route section, so use line number instead */
+ r = route_new_static(network, filename, line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
return 0;
}
+ if (isempty(rvalue)) {
+ n->gateway_from_dhcp_or_ra = false;
+ n->gw_family = AF_UNSPEC;
+ n->gw = IN_ADDR_NULL;
+ TAKE_PTR(n);
+ return 0;
+ }
+
if (streq(rvalue, "_dhcp")) {
- n->gateway_from_dhcp = true;
+ n->gateway_from_dhcp_or_ra = true;
+ TAKE_PTR(n);
+ return 0;
+ }
+
+ if (streq(rvalue, "_dhcp4")) {
+ n->gw_family = AF_INET;
+ n->gateway_from_dhcp_or_ra = true;
+ TAKE_PTR(n);
+ return 0;
+ }
+
+ if (streq(rvalue, "_ipv6ra")) {
+ n->gw_family = AF_INET6;
+ n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
return 0;
}
}
- if (n->family == AF_UNSPEC)
- r = in_addr_from_string_auto(rvalue, &n->family, &n->gw);
- else
- r = in_addr_from_string(n->family, rvalue, &n->gw);
+ r = in_addr_from_string_auto(rvalue, &n->gw_family, &n->gw);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
+ n->gateway_from_dhcp_or_ra = false;
TAKE_PTR(n);
return 0;
}
return 0;
}
+ n->priority_set = true;
TAKE_PTR(n);
return 0;
}
return 0;
}
+ n->pref_set = true;
TAKE_PTR(n);
return 0;
}
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
- uint64_t k;
+ uint32_t k;
int r;
assert(filename);
return 0;
}
- r = parse_size(rvalue, 1024, &k);
+ r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
- if (k > UINT32_MAX) {
+ if (k >= 1024) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
return 0;
return 0;
}
-int route_section_verify(Route *route, Network *network) {
+static int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;
+ if (route->gateway_from_dhcp_or_ra) {
+ if (route->gw_family == AF_UNSPEC) {
+ /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
+ switch (route->family) {
+ case AF_UNSPEC:
+ log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
+ "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
+ route->section->filename, route->section->line);
+ route->family = AF_INET;
+ break;
+ case AF_INET:
+ case AF_INET6:
+ log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
+ "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
+ route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
+ break;
+ default:
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Invalid route family. Ignoring [Route] section from line %u.",
+ route->section->filename, route->section->line);
+ }
+ route->gw_family = route->family;
+ }
+
+ if (route->gw_family == AF_INET && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4))
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
+ "Ignoring [Route] section from line %u.",
+ route->section->filename, route->section->line);
+
+ if (route->gw_family == AF_INET6 && !network->ipv6_accept_ra)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
+ "Ignoring [Route] section from line %u.",
+ route->section->filename, route->section->line);
+ }
+
+ /* When only Gateway= is specified, assume the route family based on the Gateway address. */
+ if (route->family == AF_UNSPEC)
+ route->family = route->gw_family;
+
if (route->family == AF_UNSPEC) {
assert(route->section);
route->section->filename, route->section->line);
}
+ if (route->family == AF_INET6 && route->gw_family == AF_INET)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: IPv4 gateway is configured for IPv6 route. "
+ "Ignoring [Route] section from line %u.",
+ route->section->filename, route->section->line);
+
if (!route->table_set && network->vrf) {
route->table = VRF(network->vrf)->table;
route->table_set = true;
route->scope = RT_SCOPE_LINK;
}
- if (network->n_static_addresses == 0 &&
- in_addr_is_null(route->family, &route->gw) == 0 &&
+ if (route->scope != RT_SCOPE_UNIVERSE && route->family == AF_INET6) {
+ log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route->section->filename);
+ route->scope = RT_SCOPE_UNIVERSE;
+ }
+
+ if (route->family == AF_INET6 && route->priority == 0)
+ route->priority = IP6_RT_PRIO_USER;
+
+ if (ordered_hashmap_isempty(network->addresses_by_section) &&
+ in_addr_is_null(route->gw_family, &route->gw) == 0 &&
route->gateway_onlink < 0) {
log_warning("%s: Gateway= without static address configured. "
"Enabling GatewayOnLink= option.",
return 0;
}
+
+void network_drop_invalid_routes(Network *network) {
+ Route *route;
+
+ assert(network);
+
+ HASHMAP_FOREACH(route, network->routes_by_section)
+ if (route_section_verify(route, network) < 0)
+ route_free(route);
+}
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include "conf-parser.h"
-#include "macro.h"
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
-typedef struct Route Route;
-typedef struct NetworkConfigSection NetworkConfigSection;
+#include "sd-netlink.h"
-#include "networkd-network.h"
+#include "conf-parser.h"
+#include "in-addr-util.h"
+#include "networkd-link.h"
#include "networkd-util.h"
-typedef struct MultipathRouteVia {
- uint16_t family;
- union in_addr_union address;
-} _packed_ MultipathRouteVia;
-
-typedef struct MultipathRoute {
- MultipathRouteVia gateway;
- int ifindex;
- uint32_t weight;
-} MultipathRoute;
+typedef struct Manager Manager;
+typedef struct Network Network;
-struct Route {
+typedef struct Route {
Network *network;
NetworkConfigSection *section;
Link *link;
+ Manager *manager;
int family;
+ int gw_family;
+ uint32_t gw_weight;
int quickack;
int fast_open_no_cookie;
int ttl_propagate;
unsigned char dst_prefixlen;
unsigned char src_prefixlen;
unsigned char scope;
- bool scope_set;
unsigned char protocol; /* RTPROT_* */
unsigned char type; /* RTN_* */
unsigned char tos;
uint32_t priority; /* note that ip(8) calls this 'metric' */
uint32_t table;
- bool table_set;
uint32_t mtu;
uint32_t initcwnd;
uint32_t initrwnd;
unsigned char pref;
unsigned flags;
int gateway_onlink;
- bool gateway_from_dhcp;
+
+ bool scope_set:1;
+ bool table_set:1;
+ bool priority_set:1;
+ bool protocol_set:1;
+ bool pref_set:1;
+ bool gateway_from_dhcp_or_ra:1;
union in_addr_union gw;
union in_addr_union dst;
usec_t lifetime;
sd_event_source *expire;
-
- LIST_FIELDS(Route, routes);
-};
+} Route;
void route_hash_func(const Route *route, struct siphash *state);
int route_compare_func(const Route *a, const Route *b);
extern const struct hash_ops route_hash_ops;
int route_new(Route **ret);
-void route_free(Route *route);
-int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret);
-int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback);
-
-int route_get(Link *link, Route *in, Route **ret);
-int route_add(Link *link, Route *in, Route **ret);
-int route_add_foreign(Link *link, Route *in, Route **ret);
-bool route_equal(Route *r1, Route *r2);
-
-int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
-int route_section_verify(Route *route, Network *network);
-
+Route *route_free(Route *route);
DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
-int network_add_ipv4ll_route(Network *network);
-int network_add_default_route_on_device(Network *network);
+int route_configure(const Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret);
+int route_remove(const Route *route, Manager *manager, Link *link, link_netlink_message_handler_t callback);
-const char* route_type_to_string(int t) _const_;
-int route_type_from_string(const char *s) _pure_;
+int link_set_routes(Link *link);
+int link_drop_routes(Link *link);
+int link_drop_foreign_routes(Link *link);
+int link_serialize_routes(const Link *link, FILE *f);
+int link_deserialize_routes(Link *link, const char *routes);
-#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1)
-const char *format_route_scope(int scope, char *buf, size_t size);
+uint32_t link_get_dhcp_route_table(const Link *link);
+uint32_t link_get_ipv6_accept_ra_route_table(const Link *link);
-#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1)
-const char *format_route_table(int table, char *buf, size_t size);
+int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
-#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1)
-const char *format_route_protocol(int protocol, char *buf, size_t size);
+int network_add_ipv4ll_route(Network *network);
+int network_add_default_route_on_device(Network *network);
+void network_drop_invalid_routes(Network *network);
CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
#include "fileio.h"
#include "format-util.h"
#include "ip-protocol-list.h"
-#include "networkd-routing-policy-rule.h"
#include "netlink-util.h"
#include "networkd-manager.h"
+#include "networkd-routing-policy-rule.h"
#include "networkd-util.h"
#include "parse-util.h"
#include "socket-util.h"
#include "strv.h"
#include "user-util.h"
-int routing_policy_rule_new(RoutingPolicyRule **ret) {
+RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
+ if (!rule)
+ return NULL;
+
+ if (rule->network) {
+ assert(rule->section);
+ hashmap_remove(rule->network->rules_by_section, rule->section);
+ }
+
+ if (rule->manager) {
+ if (set_get(rule->manager->rules, rule) == rule)
+ set_remove(rule->manager->rules, rule);
+ if (set_get(rule->manager->rules_foreign, rule) == rule)
+ set_remove(rule->manager->rules_foreign, rule);
+ }
+
+ network_config_section_free(rule->section);
+ free(rule->iif);
+ free(rule->oif);
+
+ return mfree(rule);
+}
+
+DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
+
+static int routing_policy_rule_new(RoutingPolicyRule **ret) {
RoutingPolicyRule *rule;
rule = new(RoutingPolicyRule, 1);
return 0;
}
-void routing_policy_rule_free(RoutingPolicyRule *rule) {
+static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ int r;
- if (!rule)
- return;
+ assert(network);
+ assert(ret);
+ assert(filename);
+ assert(section_line > 0);
- if (rule->network) {
- LIST_REMOVE(rules, rule->network->rules, rule);
- assert(rule->network->n_rules > 0);
- rule->network->n_rules--;
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- if (rule->section)
- hashmap_remove(rule->network->rules_by_section, rule->section);
+ rule = hashmap_get(network->rules_by_section, n);
+ if (rule) {
+ *ret = TAKE_PTR(rule);
+ return 0;
}
- if (rule->manager) {
- if (set_get(rule->manager->rules, rule) == rule)
- set_remove(rule->manager->rules, rule);
- if (set_get(rule->manager->rules_foreign, rule) == rule)
- set_remove(rule->manager->rules_foreign, rule);
- }
+ r = routing_policy_rule_new(&rule);
+ if (r < 0)
+ return r;
- network_config_section_free(rule->section);
- free(rule->iif);
- free(rule->oif);
- free(rule);
+ rule->network = network;
+ rule->section = TAKE_PTR(n);
+
+ r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(network->rules_by_section, rule->section, rule);
+ if (r < 0)
+ return r;
+
+ *ret = TAKE_PTR(rule);
+ return 0;
}
static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *src) {
routing_policy_rule_compare_func,
routing_policy_rule_free);
-int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
+static int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
RoutingPolicyRule *existing;
return -ENOENT;
}
-int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) {
- int r;
-
- assert(m);
-
- if (set_contains(m->rules_foreign, rule)) {
- set_remove(m->rules_foreign, rule);
-
- r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, rule);
- if (r < 0)
- return r;
- if (r == 0)
- routing_policy_rule_free(rule);
- }
-
- return -ENOENT;
-}
-
-static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, RoutingPolicyRule **ret) {
+static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
int r;
assert(m);
assert(rules);
assert(in);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+ assert(in->family == AF_UNSPEC || in->family == family);
r = routing_policy_rule_new(&rule);
if (r < 0)
if (r < 0)
return r;
+ rule->family = family;
+
r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule);
if (r < 0)
return r;
return 0;
}
-static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
- return routing_policy_rule_add_internal(m, &m->rules, rule, ret);
+static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, int family, RoutingPolicyRule **ret) {
+ return routing_policy_rule_add_internal(m, &m->rules, rule, family, ret);
}
-int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
- return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, ret);
+static int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
+ return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret);
+}
+
+static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(rule);
+ assert(m);
+ assert(link);
+
+ if (in_addr_is_null(rule->family, &rule->from) == 0) {
+ r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m");
+
+ r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set source prefix length: %m");
+ }
+
+ if (in_addr_is_null(rule->family, &rule->to) == 0) {
+ r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m");
+
+ r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
+ }
+
+ r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_PRIORITY attribute: %m");
+
+ if (rule->tos > 0) {
+ r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set IP rule TOS: %m");
+ }
+
+ if (rule->table < 256) {
+ r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set IP rule table: %m");
+ } else {
+ r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set IP rule table: %m");
+
+ r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_TABLE attribute: %m");
+ }
+
+ if (rule->fwmark > 0) {
+ r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_FWMARK attribute: %m");
+
+ r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_FWMASK attribute: %m");
+ }
+
+ if (rule->iif) {
+ r = sd_netlink_message_append_string(m, FRA_IIFNAME, rule->iif);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_IIFNAME attribute: %m");
+ }
+
+ if (rule->oif) {
+ r = sd_netlink_message_append_string(m, FRA_OIFNAME, rule->oif);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_OIFNAME attribute: %m");
+ }
+
+ r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_IP_PROTO attribute: %m");
+
+ if (rule->sport.start != 0 || rule->sport.end != 0) {
+ r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_SPORT_RANGE attribute: %m");
+ }
+
+ if (rule->dport.start != 0 || rule->dport.end != 0) {
+ r = sd_netlink_message_append_data(m, FRA_DPORT_RANGE, &rule->dport, sizeof(rule->dport));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_DPORT_RANGE attribute: %m");
+ }
+
+ if (rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID) {
+ r = sd_netlink_message_append_data(m, FRA_UID_RANGE, &rule->uid_range, sizeof(rule->uid_range));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_UID_RANGE attribute: %m");
+ }
+
+ if (rule->invert_rule) {
+ r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FIB_RULE_INVERT attribute: %m");
+ }
+
+ if (rule->suppress_prefixlen >= 0) {
+ r = sd_netlink_message_append_u32(m, FRA_SUPPRESS_PREFIXLEN, (uint32_t) rule->suppress_prefixlen);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
+ }
+
+ return 0;
}
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return 1;
}
-int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) {
+static int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m");
- if (in_addr_is_null(rule->family, &rule->from) == 0) {
- r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m");
-
- r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set source prefix length: %m");
- }
-
- if (in_addr_is_null(rule->family, &rule->to) == 0) {
- r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m");
-
- r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
- }
+ r = routing_policy_rule_set_netlink_message(rule, m, link);
+ if (r < 0)
+ return r;
r = netlink_call_async(link->manager->rtnl, NULL, m,
- callback ?: routing_policy_rule_remove_handler,
+ routing_policy_rule_remove_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return 0;
}
-static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
- _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
- _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
- int r;
-
- assert(network);
- assert(ret);
- assert(!!filename == (section_line > 0));
-
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
-
- rule = hashmap_get(network->rules_by_section, n);
- if (rule) {
- *ret = TAKE_PTR(rule);
-
- return 0;
- }
- }
-
- r = routing_policy_rule_new(&rule);
- if (r < 0)
- return r;
-
- rule->network = network;
- LIST_APPEND(rules, network->rules, rule);
- network->n_rules++;
-
- if (filename) {
- rule->section = TAKE_PTR(n);
-
- r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_put(network->rules_by_section, rule->section, rule);
- if (r < 0)
- return r;
- }
-
- *ret = TAKE_PTR(rule);
-
- return 0;
-}
-
static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
return 1;
}
-int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) {
+static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int family, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
if (DEBUG_LOGGING) {
_cleanup_free_ char *from = NULL, *to = NULL;
- (void) in_addr_to_string(rule->family, &rule->from, &from);
- (void) in_addr_to_string(rule->family, &rule->to, &to);
+ (void) in_addr_to_string(family, &rule->from, &from);
+ (void) in_addr_to_string(family, &rule->to, &to);
log_link_debug(link,
"Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
}
- r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
+ r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m");
- if (in_addr_is_null(rule->family, &rule->from) == 0) {
- r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
+ r = routing_policy_rule_set_netlink_message(rule, m, link);
+ if (r < 0)
+ return r;
+
+ r = netlink_call_async(link->manager->rtnl, NULL, m,
+ routing_policy_rule_handler,
+ link_netlink_destroy_callback, link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+ link->routing_policy_rule_messages++;
+
+ r = routing_policy_rule_add(link->manager, rule, family, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not add rule: %m");
+
+ return 1;
+}
+
+static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link) {
+ int r;
+
+ if (IN_SET(rule->family, AF_INET, AF_INET6))
+ return routing_policy_rule_configure_internal(rule, rule->family, link);
+
+ if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) {
+ r = routing_policy_rule_configure_internal(rule, AF_INET, link);
if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m");
+ return r;
+ }
+
+ if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) {
+ r = routing_policy_rule_configure_internal(rule, AF_INET6, link);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) {
+ Link *link;
+
+ assert(m);
+ assert(rule);
+
+ HASHMAP_FOREACH(link, m->links) {
+ RoutingPolicyRule *link_rule;
+
+ if (!link->network)
+ continue;
+
+ HASHMAP_FOREACH(link_rule, link->network->rules_by_section)
+ if (routing_policy_rule_compare_func(link_rule, rule) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+static void routing_policy_rule_purge(Manager *m, Link *link) {
+ RoutingPolicyRule *rule;
+ int r;
+
+ assert(m);
+ assert(link);
+
+ SET_FOREACH(rule, m->rules_saved) {
+ RoutingPolicyRule *existing;
+
+ existing = set_get(m->rules_foreign, rule);
+ if (!existing)
+ continue; /* Saved rule does not exist anymore. */
+
+ if (manager_links_have_routing_policy_rule(m, existing))
+ continue; /* Existing links have the saved rule. */
+
+ /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
+ * later when it is requested. */
+
+ r = routing_policy_rule_remove(existing, link);
+ if (r < 0) {
+ log_warning_errno(r, "Could not remove routing policy rules: %m");
+ continue;
+ }
+
+ link->routing_policy_rule_remove_messages++;
+
+ assert_se(set_remove(m->rules_foreign, existing) == existing);
+ routing_policy_rule_free(existing);
+ }
+}
+
+int link_set_routing_policy_rules(Link *link) {
+ RoutingPolicyRule *rule;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ link->routing_policy_rules_configured = false;
+
+ HASHMAP_FOREACH(rule, link->network->rules_by_section) {
+ RoutingPolicyRule *existing;
+
+ r = routing_policy_rule_get(link->manager, rule, &existing);
+ if (r > 0)
+ continue;
+ if (r == 0) {
+ r = set_ensure_put(&link->manager->rules, &routing_policy_rule_hash_ops, existing);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not store existing routing policy rule: %m");
+
+ set_remove(link->manager->rules_foreign, existing);
+ continue;
+ }
- r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen);
+ r = routing_policy_rule_configure(rule, link);
if (r < 0)
- return log_link_error_errno(link, r, "Could not set source prefix length: %m");
+ return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
}
- if (in_addr_is_null(rule->family, &rule->to) == 0) {
- r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m");
-
- r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
+ routing_policy_rule_purge(link->manager, link);
+ if (link->routing_policy_rule_messages == 0)
+ link->routing_policy_rules_configured = true;
+ else {
+ log_link_debug(link, "Setting routing policy rules");
+ link_set_state(link, LINK_STATE_CONFIGURING);
}
- r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_PRIORITY attribute: %m");
+ return 0;
+}
- if (rule->tos > 0) {
- r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set IP rule TOS: %m");
- }
+int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
+ _cleanup_free_ char *from = NULL, *to = NULL;
+ RoutingPolicyRule *rule = NULL;
+ const char *iif = NULL, *oif = NULL;
+ uint32_t suppress_prefixlen;
+ unsigned flags;
+ uint16_t type;
+ int r;
- if (rule->table < 256) {
- r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set IP rule table: %m");
- } else {
- r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set IP rule table: %m");
+ assert(rtnl);
+ assert(message);
- r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_TABLE attribute: %m");
- }
+ log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring");
- if (rule->fwmark > 0) {
- r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_FWMARK attribute: %m");
+ return 0;
+ }
- r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_FWMASK attribute: %m");
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) {
+ log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type);
+ return 0;
}
- if (rule->iif) {
- r = sd_netlink_message_append_string(m, FRA_IIFNAME, rule->iif);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_IIFNAME attribute: %m");
+ r = routing_policy_rule_new(&tmp);
+ if (r < 0) {
+ log_oom();
+ return 0;
}
- if (rule->oif) {
- r = sd_netlink_message_append_string(m, FRA_OIFNAME, rule->oif);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_OIFNAME attribute: %m");
+ r = sd_rtnl_message_get_family(message, &tmp->family);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+ log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family);
+ return 0;
}
- r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_IP_PROTO attribute: %m");
+ switch (tmp->family) {
+ case AF_INET:
+ r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
+ return 0;
+ }
+ }
- if (rule->sport.start != 0 || rule->sport.end != 0) {
- r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport));
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_SPORT_RANGE attribute: %m");
- }
+ r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
+ return 0;
+ }
+ }
- if (rule->dport.start != 0 || rule->dport.end != 0) {
- r = sd_netlink_message_append_data(m, FRA_DPORT_RANGE, &rule->dport, sizeof(rule->dport));
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_DPORT_RANGE attribute: %m");
+ break;
+
+ case AF_INET6:
+ r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
+ return 0;
+ }
+ }
+
+ r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
+ return 0;
+ } else if (r >= 0) {
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
+ return 0;
+ }
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Received rule message with unsupported address family");
}
- if (rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID) {
- r = sd_netlink_message_append_data(m, FRA_UID_RANGE, &rule->uid_range, sizeof(rule->uid_range));
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_UID_RANGE attribute: %m");
+ r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m");
+ return 0;
}
+ tmp->invert_rule = flags & FIB_RULE_INVERT;
- if (rule->invert_rule) {
- r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FIB_RULE_INVERT attribute: %m");
+ r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
+ return 0;
}
- if (rule->suppress_prefixlen >= 0) {
- r = sd_netlink_message_append_u32(m, FRA_SUPPRESS_PREFIXLEN, (uint32_t) rule->suppress_prefixlen);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
+ r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
+ return 0;
}
- rule->link = link;
+ r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
+ return 0;
+ }
- r = netlink_call_async(link->manager->rtnl, NULL, m,
- callback ?: routing_policy_rule_handler,
- link_netlink_destroy_callback, link);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+ r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
+ return 0;
+ }
- link_ref(link);
+ r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m");
+ return 0;
+ }
- r = routing_policy_rule_add(link->manager, rule, NULL);
+ r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
+ return 0;
+ }
+ r = free_and_strdup(&tmp->iif, iif);
if (r < 0)
- return log_link_error_errno(link, r, "Could not add rule: %m");
-
- return 1;
-}
-
-int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
- int r;
-
- if (section_is_invalid(rule->section))
- return -EINVAL;
+ return log_oom();
- if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
- (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: address family specified by Family= conflicts with the address "
- "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
- rule->section->filename, rule->section->line);
+ r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
+ return 0;
+ }
+ r = free_and_strdup(&tmp->oif, oif);
+ if (r < 0)
+ return log_oom();
- if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) {
- _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL;
+ r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
+ return 0;
+ }
- assert(rule->family == AF_UNSPEC);
+ r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
+ return 0;
+ }
- /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */
+ r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
+ return 0;
+ }
- r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6);
- if (r < 0)
- return r;
+ r = sd_netlink_message_read(message, FRA_UID_RANGE, sizeof(tmp->uid_range), &tmp->uid_range);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
+ return 0;
+ }
- r = routing_policy_rule_copy(rule6, rule);
- if (r < 0)
- return r;
+ r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_PREFIXLEN, &suppress_prefixlen);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
+ return 0;
+ }
+ if (r >= 0)
+ tmp->suppress_prefixlen = (int) suppress_prefixlen;
- rule->family = AF_INET;
- rule6->family = AF_INET6;
+ (void) routing_policy_rule_get(m, tmp, &rule);
- TAKE_PTR(rule6);
+ if (DEBUG_LOGGING) {
+ (void) in_addr_to_string(tmp->family, &tmp->from, &from);
+ (void) in_addr_to_string(tmp->family, &tmp->to, &to);
}
- if (rule->family == AF_UNSPEC) {
- if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6))
- rule->family = AF_INET6;
- else
- rule->family = AF_INET;
+ switch (type) {
+ case RTM_NEWRULE:
+ if (rule)
+ log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
+ else {
+ log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
+ r = routing_policy_rule_add_foreign(m, tmp, &rule);
+ if (r < 0) {
+ log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
+ return 0;
+ }
+ }
+ break;
+ case RTM_DELRULE:
+ if (rule) {
+ log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
+ routing_policy_rule_free(rule);
+ } else
+ log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.",
+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type");
}
- return 0;
+ return 1;
}
static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) {
return 0;
}
+static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
+ if (section_is_invalid(rule->section))
+ return -EINVAL;
+
+ if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
+ (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: address family specified by Family= conflicts with the address "
+ "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
+ rule->section->filename, rule->section->line);
+
+ if (rule->family == AF_UNSPEC && rule->address_family == ADDRESS_FAMILY_NO)
+ rule->family = AF_INET;
+
+ return 0;
+}
+
+void network_drop_invalid_routing_policy_rules(Network *network) {
+ RoutingPolicyRule *rule;
+
+ assert(network);
+
+ HASHMAP_FOREACH(rule, network->rules_by_section)
+ if (routing_policy_rule_section_verify(rule) < 0)
+ routing_policy_rule_free(rule);
+}
+
int routing_policy_serialize_rules(Set *rules, FILE *f) {
- RoutingPolicyRule *rule = NULL;
+ RoutingPolicyRule *rule;
int r;
assert(f);
SET_FOREACH(rule, rules) {
- _cleanup_free_ char *from_str = NULL, *to_str = NULL;
const char *family_str;
bool space = false;
}
if (!in_addr_is_null(rule->family, &rule->from)) {
- r = in_addr_to_string(rule->family, &rule->from, &from_str);
+ _cleanup_free_ char *str = NULL;
+
+ r = in_addr_to_string(rule->family, &rule->from, &str);
if (r < 0)
return r;
fprintf(f, "%sfrom=%s/%hhu",
space ? " " : "",
- from_str, rule->from_prefixlen);
+ str, rule->from_prefixlen);
space = true;
}
if (!in_addr_is_null(rule->family, &rule->to)) {
- r = in_addr_to_string(rule->family, &rule->to, &to_str);
+ _cleanup_free_ char *str = NULL;
+
+ r = in_addr_to_string(rule->family, &rule->to, &str);
if (r < 0)
return r;
fprintf(f, "%sto=%s/%hhu",
space ? " " : "",
- to_str, rule->to_prefixlen);
+ str, rule->to_prefixlen);
space = true;
}
return 0;
}
-static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
+static int routing_policy_rule_read_full_file(const char *state_file, char ***ret) {
+ _cleanup_strv_free_ char **lines = NULL;
_cleanup_free_ char *s = NULL;
- size_t size;
int r;
assert(state_file);
- r = read_full_file(state_file, &s, &size);
- if (r == -ENOENT)
- return -ENODATA;
+ r = read_full_file(state_file, &s, NULL);
+ if (r == -ENOENT) {
+ *ret = NULL;
+ return 0;
+ }
if (r < 0)
return r;
- if (size <= 0)
- return -ENODATA;
- *ret = TAKE_PTR(s);
+ lines = strv_split_newlines(s);
+ if (!lines)
+ return -ENOMEM;
- return size;
+ *ret = TAKE_PTR(lines);
+ return 0;
}
int routing_policy_load_rules(const char *state_file, Set **rules) {
- _cleanup_strv_free_ char **l = NULL;
- _cleanup_free_ char *data = NULL;
- uint16_t low = 0, high = 0;
- const char *p;
+ _cleanup_strv_free_ char **data = NULL;
char **i;
int r;
assert(rules);
r = routing_policy_rule_read_full_file(state_file, &data);
- if (r <= 0)
- return r;
-
- l = strv_split_newlines(data);
- if (!l)
- return -ENOMEM;
+ if (r < 0)
+ return log_warning_errno(r, "Failed to read %s, ignoring: %m", state_file);
- STRV_FOREACH(i, l) {
+ STRV_FOREACH(i, data) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
+ const char *p;
p = startswith(*i, "RULE=");
if (!p)
r = routing_policy_rule_new(&rule);
if (r < 0)
- return r;
+ return log_oom();
for (;;) {
_cleanup_free_ char *a = NULL;
r = extract_first_word(&p, &a, NULL, 0);
if (r < 0)
- return r;
+ return log_oom();
if (r == 0)
break;
continue;
}
rule->family = r;
- } if (STR_IN_SET(a, "from", "to")) {
+ } else if (STR_IN_SET(a, "from", "to")) {
union in_addr_union *buffer;
uint8_t *prefixlen;
continue;
}
} else if (streq(a, "sourceport")) {
+ uint16_t low, high;
+
r = parse_ip_port_range(b, &low, &high);
if (r < 0) {
log_warning_errno(r, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b);
rule->sport.start = low;
rule->sport.end = high;
} else if (streq(a, "destinationport")) {
+ uint16_t low, high;
+
r = parse_ip_port_range(b, &low, &high);
if (r < 0) {
log_warning_errno(r, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b);
r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule);
if (r < 0) {
- log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", p);
+ log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", *i);
continue;
}
if (r > 0)
return 0;
}
-
-static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) {
- RoutingPolicyRule *link_rule;
- Link *link;
-
- assert(m);
- assert(rule);
-
- HASHMAP_FOREACH(link, m->links) {
- if (!link->network)
- continue;
-
- LIST_FOREACH(rules, link_rule, link->network->rules)
- if (routing_policy_rule_compare_func(link_rule, rule) == 0)
- return true;
- }
-
- return false;
-}
-
-void routing_policy_rule_purge(Manager *m, Link *link) {
- RoutingPolicyRule *rule, *existing;
- int r;
-
- assert(m);
- assert(link);
-
- SET_FOREACH(rule, m->rules_saved) {
- existing = set_get(m->rules_foreign, rule);
- if (!existing)
- continue; /* Saved rule does not exist anymore. */
-
- if (manager_links_have_routing_policy_rule(m, existing))
- continue; /* Existing links have the saved rule. */
-
- /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
- * later when it is requested. */
-
- r = routing_policy_rule_remove(existing, link, NULL);
- if (r < 0) {
- log_warning_errno(r, "Could not remove routing policy rules: %m");
- continue;
- }
-
- link->routing_policy_rule_remove_messages++;
-
- assert_se(set_remove(m->rules_foreign, existing) == existing);
- routing_policy_rule_free(existing);
- }
-}
#pragma once
#include <inttypes.h>
-#include <netinet/in.h>
#include <linux/fib_rules.h>
#include <stdbool.h>
+#include <stdio.h>
-#include "in-addr-util.h"
#include "conf-parser.h"
-
-typedef struct RoutingPolicyRule RoutingPolicyRule;
-
-#include "networkd-link.h"
-#include "networkd-network.h"
+#include "in-addr-util.h"
#include "networkd-util.h"
+#include "set.h"
typedef struct Network Network;
typedef struct Link Link;
-typedef struct NetworkConfigSection NetworkConfigSection;
typedef struct Manager Manager;
-struct RoutingPolicyRule {
+typedef struct RoutingPolicyRule {
Manager *manager;
Network *network;
- Link *link;
NetworkConfigSection *section;
bool invert_rule;
struct fib_rule_uid_range uid_range;
int suppress_prefixlen;
+} RoutingPolicyRule;
- LIST_FIELDS(RoutingPolicyRule, rules);
-};
+RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule);
-int routing_policy_rule_new(RoutingPolicyRule **ret);
-void routing_policy_rule_free(RoutingPolicyRule *rule);
+void network_drop_invalid_routing_policy_rules(Network *network);
-DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
-int routing_policy_rule_section_verify(RoutingPolicyRule *rule);
+int link_set_routing_policy_rules(Link *link);
-int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback);
-int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback);
+int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
-int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret);
-int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret);
-int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule);
int routing_policy_serialize_rules(Set *rules, FILE *f);
int routing_policy_load_rules(const char *state_file, Set **rules);
-void routing_policy_rule_purge(Manager *m, Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table);
return 1;
}
-int sr_iov_configure(Link *link, SRIOV *sr_iov) {
+static int sr_iov_configure(Link *link, SRIOV *sr_iov) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
return 0;
}
-int sr_iov_section_verify(SRIOV *sr_iov) {
+int link_configure_sr_iov(Link *link) {
+ SRIOV *sr_iov;
+ int r;
+
+ link->sr_iov_configured = false;
+ link->sr_iov_messages = 0;
+
+ ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
+ r = sr_iov_configure(link, sr_iov);
+ if (r < 0)
+ return r;
+ }
+
+ if (link->sr_iov_messages == 0)
+ link->sr_iov_configured = true;
+ else
+ log_link_debug(link, "Configuring SR-IOV");
+
+ return 0;
+}
+
+static int sr_iov_section_verify(SRIOV *sr_iov) {
assert(sr_iov);
if (section_is_invalid(sr_iov->section))
return 0;
}
+void network_drop_invalid_sr_iov(Network *network) {
+ SRIOV *sr_iov;
+
+ assert(network);
+
+ ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
+ if (sr_iov_section_verify(sr_iov) < 0)
+ sr_iov_free(sr_iov);
+}
+
int config_parse_sr_iov_uint32(
const char *unit,
const char *filename,
#include <linux/if_link.h>
#include "conf-parser.h"
+#include "ether-addr-util.h"
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
} SRIOV;
SRIOV *sr_iov_free(SRIOV *sr_iov);
-
-int sr_iov_configure(Link *link, SRIOV *sr_iov);
-int sr_iov_section_verify(SRIOV *sr_iov);
+int link_configure_sr_iov(Link *link);
+void network_drop_invalid_sr_iov(Network *network);
DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <netinet/in.h>
+#include <linux/if.h>
+
+#include "missing_network.h"
+#include "networkd-link.h"
+#include "networkd-network.h"
+#include "networkd-sysctl.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "sysctl-util.h"
+
+static int link_update_ipv6_sysctl(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link_ipv6_enabled(link))
+ return 0;
+
+ return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false);
+}
+
+static int link_set_proxy_arp(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->proxy_arp < 0)
+ return 0;
+
+ return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0);
+}
+
+static bool link_ip_forward_enabled(Link *link, int family) {
+ assert(link);
+ assert(IN_SET(family, AF_INET, AF_INET6));
+
+ if (family == AF_INET6 && !socket_ipv6_is_supported())
+ return false;
+
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6);
+}
+
+static int link_set_ipv4_forward(Link *link) {
+ assert(link);
+
+ if (!link_ip_forward_enabled(link, AF_INET))
+ return 0;
+
+ /* We propagate the forwarding flag from one interface to the
+ * global setting one way. This means: as long as at least one
+ * interface was configured at any time that had IP forwarding
+ * enabled the setting will stay on for good. We do this
+ * primarily to keep IPv4 and IPv6 packet forwarding behaviour
+ * somewhat in sync (see below). */
+
+ return sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1");
+}
+
+static int link_set_ipv6_forward(Link *link) {
+ assert(link);
+
+ if (!link_ip_forward_enabled(link, AF_INET6))
+ return 0;
+
+ /* On Linux, the IPv6 stack does not know a per-interface
+ * packet forwarding setting: either packet forwarding is on
+ * for all, or off for all. We hence don't bother with a
+ * per-interface setting, but simply propagate the interface
+ * flag, if it is set, to the global flag, one-way. Note that
+ * while IPv4 would allow a per-interface flag, we expose the
+ * same behaviour there and also propagate the setting from
+ * one to all, to keep things simple (see above). */
+
+ return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
+}
+
+static int link_set_ipv6_privacy_extensions(Link *link) {
+ assert(link);
+
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions);
+}
+
+static int link_set_ipv6_accept_ra(Link *link) {
+ assert(link);
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0");
+}
+
+static int link_set_ipv6_dad_transmits(Link *link) {
+ assert(link);
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->ipv6_dad_transmits < 0)
+ return 0;
+
+ return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits);
+}
+
+static int link_set_ipv6_hop_limit(Link *link) {
+ assert(link);
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->ipv6_hop_limit < 0)
+ return 0;
+
+ return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit);
+}
+
+static int link_set_ipv4_accept_local(Link *link) {
+ assert(link);
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (link->network->ipv4_accept_local < 0)
+ return 0;
+
+ return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0);
+}
+
+int link_set_sysctl(Link *link) {
+ int r;
+
+ assert(link);
+
+ /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled
+ * for this interface, then enable IPv6 */
+ r = link_update_ipv6_sysctl(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot enable IPv6, ignoring: %m");
+
+ r = link_set_proxy_arp(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface, ignoring: %m");
+
+ r = link_set_ipv4_forward(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
+
+ r = link_set_ipv6_forward(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");;
+
+ r = link_set_ipv6_privacy_extensions(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignorign: %m");
+
+ r = link_set_ipv6_accept_ra(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface, ignoring: %m");
+
+ r = link_set_ipv6_dad_transmits(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface, ignoring: %m");
+
+ r = link_set_ipv6_hop_limit(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface, ignoring: %m");
+
+ r = link_set_ipv4_accept_local(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface, ignoring: %m");
+
+ return 0;
+}
+
+int link_set_ipv6_mtu(Link *link) {
+ int r;
+
+ assert(link);
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (link->network->ipv6_mtu == 0)
+ return 0;
+
+ r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu);
+ if (r < 0)
+ return r;
+
+ link->ipv6_mtu_set = true;
+
+ return 0;
+}
+
+static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
+ [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
+ [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
+ [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
+ IPV6_PRIVACY_EXTENSIONS_YES);
+
+int config_parse_ipv6_privacy_extensions(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ipv6_privacy_extensions);
+
+ s = ipv6_privacy_extensions_from_string(rvalue);
+ if (s < 0) {
+ if (streq(rvalue, "kernel"))
+ s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
+ else {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
+ return 0;
+ }
+ }
+
+ *ipv6_privacy_extensions = s;
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+typedef enum IPv6PrivacyExtensions {
+ /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
+ IPV6_PRIVACY_EXTENSIONS_NO,
+ IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
+ IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
+ _IPV6_PRIVACY_EXTENSIONS_MAX,
+ _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
+} IPv6PrivacyExtensions;
+
+int link_set_sysctl(Link *link);
+int link_set_ipv6_mtu(Link *link);
+
+const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
+IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
void network_config_section_free(NetworkConfigSection *cs) {
free(cs);
}
+
+unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
+ NetworkConfigSection *cs;
+ unsigned n = 0;
+ void *entry;
+
+ HASHMAP_FOREACH_KEY(entry, cs, hashmap)
+ if (n < cs->line)
+ n = cs->line;
+
+ return n + 1;
+}
#pragma once
#include "sd-dhcp-lease.h"
+#include "sd-netlink.h"
#include "conf-parser.h"
-#include "hash-funcs.h"
+#include "hashmap.h"
+#include "log.h"
#include "macro.h"
+#include "string-util.h"
typedef enum AddressFamily {
/* This is a bitmask, though it usually doesn't feel that way! */
void network_config_section_free(NetworkConfigSection *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
extern const struct hash_ops network_config_hash_ops;
+unsigned hashmap_find_free_section_line(Hashmap *hashmap);
static inline bool section_is_invalid(NetworkConfigSection *section) {
/* If this returns false, then it does _not_ mean the section is valid. */
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
+
+static inline int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) {
+ const char *err_msg = NULL;
+
+ (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
+ return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : "");
+}
#include "sd-bus.h"
#include "bus-util.h"
+#include "ether-addr-util.h"
#include "netlink-internal.h"
#include "netlink-util.h"
#include "networkd-link.h"
if (r < 0)
return log_error_errno(r, "Could not load configuration files: %m");
- r = manager_rtnl_enumerate_links(m);
+ r = manager_enumerate(m);
if (r < 0)
- return log_error_errno(r, "Could not enumerate links: %m");
-
- r = manager_rtnl_enumerate_addresses(m);
- if (r < 0)
- return log_error_errno(r, "Could not enumerate addresses: %m");
-
- r = manager_rtnl_enumerate_neighbors(m);
- if (r < 0)
- return log_error_errno(r, "Could not enumerate neighbors: %m");
-
- r = manager_rtnl_enumerate_routes(m);
- if (r < 0)
- return log_error_errno(r, "Could not enumerate routes: %m");
-
- r = manager_rtnl_enumerate_rules(m);
- if (r < 0)
- return log_error_errno(r, "Could not enumerate rules: %m");
-
- r = manager_rtnl_enumerate_nexthop(m);
- if (r < 0)
- return log_error_errno(r, "Could not enumerate nexthop: %m");
+ return r;
r = manager_start(m);
if (r < 0)
return 0;
}
- if (v > MAX_DPs) {
+ if (v > MAX_DPs)
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
- }
*p = v;
qdisc = NULL;
}
}
-int traffic_control_configure(Link *link, TrafficControl *tc) {
+static int traffic_control_configure(Link *link, TrafficControl *tc) {
assert(link);
assert(tc);
}
}
-int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) {
+int link_configure_traffic_control(Link *link) {
+ TrafficControl *tc;
+ int r;
+
+ link->tc_configured = false;
+ link->tc_messages = 0;
+
+ ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) {
+ r = traffic_control_configure(link, tc);
+ if (r < 0)
+ return r;
+ }
+
+ if (link->tc_messages == 0)
+ link->tc_configured = true;
+ else
+ log_link_debug(link, "Configuring traffic control");
+
+ return 0;
+}
+
+static int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) {
assert(tc);
switch(tc->kind) {
assert_not_reached("Invalid traffic control type");
}
}
+
+void network_drop_invalid_traffic_control(Network *network) {
+ bool has_root = false, has_clsact = false;
+ TrafficControl *tc;
+
+ assert(network);
+
+ ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section)
+ if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
+ traffic_control_free(tc);
+}
#define TC(tc) (&(tc)->meta)
void traffic_control_free(TrafficControl *tc);
-int traffic_control_configure(Link *link, TrafficControl *tc);
-int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact);
+int link_configure_traffic_control(Link *link);
+void network_drop_invalid_traffic_control(Network *network);
lvalue, rvalue);
return 0;
}
- if (id > INT_MAX) {
+ if (id > INT_MAX)
log_syntax(unit, LOG_WARNING, filename, line, 0,
"'%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
- }
teql->id = id;
#include "alloc-util.h"
#include "dhcp-lease-internal.h"
+#include "ether-addr-util.h"
#include "hostname-util.h"
#include "network-internal.h"
#include "networkd-manager.h"
assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a2->in_addr) >= 0);
assert_se(address_equal(a1, a2));
assert_se(in_addr_from_string(AF_INET, "192.168.3.10", &a1->in_addr_peer) >= 0);
- assert_se(address_equal(a1, a2));
+ assert_se(!address_equal(a1, a2));
assert_se(in_addr_from_string(AF_INET, "192.168.3.11", &a2->in_addr_peer) >= 0);
+ assert_se(!address_equal(a1, a2));
+ a2->in_addr_peer = a1->in_addr_peer;
assert_se(address_equal(a1, a2));
a1->prefixlen = 10;
assert_se(!address_equal(a1, a2));
assert_se(!address_equal(a1, a2));
a2->family = AF_INET6;
+ a1->in_addr_peer = a2->in_addr_peer = IN_ADDR_NULL;
assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr) >= 0);
assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr) >= 0);
assert_se(address_equal(a1, a2));
+ a1->prefixlen = 8;
+ assert_se(!address_equal(a1, a2));
a2->prefixlen = 8;
assert_se(address_equal(a1, a2));
test_network_get(manager, loopback);
- assert_se(manager_rtnl_enumerate_links(manager) >= 0);
+ assert_se(manager_enumerate(manager) >= 0);
return 0;
}
assert_se(network->filename = strdup("hogehoge.network"));
assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
- assert_se(network->n_static_addresses == 1);
+ assert_se(ordered_hashmap_size(network->addresses_by_section) == 1);
assert_se(network_verify(network) >= 0);
- assert_se(network->n_static_addresses == n_addresses);
+ assert_se(ordered_hashmap_size(network->addresses_by_section) == n_addresses);
if (n_addresses > 0) {
- assert_se(network->static_addresses);
- assert_se(network->static_addresses->prefixlen == prefixlen);
- assert_se(network->static_addresses->family == family);
- assert_se(in_addr_equal(family, &network->static_addresses->in_addr, u));
+ Address *a;
+
+ assert_se(a = ordered_hashmap_first(network->addresses_by_section));
+ assert_se(a->prefixlen == prefixlen);
+ assert_se(a->family == family);
+ assert_se(in_addr_equal(family, &a->in_addr, u));
/* TODO: check Address.in_addr and Address.broadcast */
}
}
-/***
- SPDX-License-Identifier: LGPL-2.1+
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "fd-util.h"
#include "fileio.h"
-#include "log.h"
-#include "macro.h"
-#include "network-internal.h"
-#include "networkd-manager.h"
+#include "networkd-routing-policy-rule.h"
#include "string-util.h"
#include "tests.h"
#include "tmpfile-util.h"
s->network_namespace_path = data.path;
}
- if (FLAGS_SET(n, data.type)) {
+ if (FLAGS_SET(n, data.type))
return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL),
"Duplicate namespace specification, refusing.");
- }
n |= data.type;
}
}
v = json_variant_by_key(oci, "ociVersion");
- if (!v) {
- log_error("JSON file '%s' is not an OCI bundle configuration file. Refusing.", path);
- return -EINVAL;
- }
- if (!streq_ptr(json_variant_string(v), "1.0.0")) {
- log_error("OCI bundle version not supported: %s", strna(json_variant_string(v)));
- return -EINVAL;
- }
+ if (!v)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "JSON file '%s' is not an OCI bundle configuration file. Refusing.",
+ path);
+ if (!streq_ptr(json_variant_string(v), "1.0.0"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "OCI bundle version not supported: %s",
+ strna(json_variant_string(v)));
// {
// _cleanup_free_ char *formatted = NULL;
uid_t uid,
gid_t gid,
const gid_t *supplementary_gids,
- size_t n_supplementary_gids) {
+ size_t n_supplementary_gids,
+ bool chown_stdio) {
if (!uid_is_valid(uid))
uid = 0;
if (!gid_is_valid(gid))
gid = 0;
- (void) fchown(STDIN_FILENO, uid, gid);
- (void) fchown(STDOUT_FILENO, uid, gid);
- (void) fchown(STDERR_FILENO, uid, gid);
+ if (chown_stdio) {
+ (void) fchown(STDIN_FILENO, uid, gid);
+ (void) fchown(STDOUT_FILENO, uid, gid);
+ (void) fchown(STDERR_FILENO, uid, gid);
+ }
if (setgroups(n_supplementary_gids, supplementary_gids) < 0)
return log_error_errno(errno, "Failed to set auxiliary groups: %m");
return 0;
}
-int change_uid_gid(const char *user, char **_home) {
+int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
char *x, *u, *g, *h;
_cleanup_free_ gid_t *gids = NULL;
_cleanup_free_ char *home = NULL, *line = NULL;
pid_t pid;
int r;
- assert(_home);
+ assert(ret_home);
if (!user || STR_IN_SET(user, "root", "0")) {
/* Reset everything fully to 0, just in case */
if (r < 0)
return log_error_errno(r, "Failed to become root: %m");
- *_home = NULL;
+ *ret_home = NULL;
return 0;
}
if (r < 0 && !IN_SET(r, -EEXIST, -ENOTDIR))
return log_error_errno(r, "Failed to make home directory: %m");
- r = change_uid_gid_raw(uid, gid, gids, n_gids);
+ r = change_uid_gid_raw(uid, gid, gids, n_gids, chown_stdio);
if (r < 0)
return r;
- if (_home)
- *_home = TAKE_PTR(home);
+ if (ret_home)
+ *ret_home = TAKE_PTR(home);
return 0;
}
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-int change_uid_gid_raw(uid_t uid, gid_t gid, const gid_t *supplementary_gids, size_t n_supplementary_gids);
-int change_uid_gid(const char *user, char **ret_home);
+int change_uid_gid_raw(uid_t uid, gid_t gid, const gid_t *supplementary_gids, size_t n_supplementary_gids, bool chown_stdio);
+int change_uid_gid(const char *user, bool chown_stdio, char **ret_home);
etc_machine_id = prefix_roota(directory, "/etc/machine-id");
- r = id128_read(etc_machine_id, ID128_PLAIN, &id);
+ r = id128_read(etc_machine_id, ID128_PLAIN_OR_UNINIT, &id);
if (r < 0) {
if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */
return log_error_errno(r, "Failed to read machine ID from container image: %m");
return log_error_errno(errno, "Failed to set PR_SET_KEEPCAPS: %m");
if (uid_is_valid(arg_uid) || gid_is_valid(arg_gid))
- r = change_uid_gid_raw(arg_uid, arg_gid, arg_supplementary_gids, arg_n_supplementary_gids);
+ r = change_uid_gid_raw(arg_uid, arg_gid, arg_supplementary_gids, arg_n_supplementary_gids, arg_console_mode != CONSOLE_PIPE);
else
- r = change_uid_gid(arg_user, &home);
+ r = change_uid_gid(arg_user, arg_console_mode != CONSOLE_PIPE, &home);
if (r < 0)
return r;
/* If all settings are masked, there's no point in looking for
* the settings file */
- if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL)
+ if (FLAGS_SET(arg_settings_mask, _SETTINGS_MASK_ALL))
return 0;
fn = strjoina(arg_machine, ".nspawn");
if (r <= 0)
goto finish;
- r = must_be_root();
- if (r < 0)
+ if (geteuid() != 0) {
+ r = log_warning_errno(SYNTHETIC_ERRNO(EPERM),
+ argc >= 2 ? "Need to be root." :
+ "Need to be root (and some arguments are usually required).\nHint: try --help");
goto finish;
+ }
r = cant_be_in_netns();
if (r < 0)
new_size = limit;
/* Enlarge buffer */
- new_groups = realloc(*groupsp, new_size * sizeof(**groupsp));
+ new_groups = reallocarray(*groupsp, new_size, sizeof(**groupsp));
if (!new_groups) {
UNPROTECT_ERRNO;
*errnop = ENOMEM;
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+
+systemd_oomd_sources = files('''
+ oomd-manager-bus.c
+ oomd-manager-bus.h
+ oomd-manager.c
+ oomd-manager.h
+ oomd-util.c
+ oomd-util.h
+ oomd.c
+'''.split())
+
+oomctl_sources = files('''
+ oomctl.c
+'''.split())
+
+if conf.get('ENABLE_OOMD') == 1
+ tests += [
+ [['src/oom/test-oomd-util.c',
+ 'src/oom/oomd-util.c',
+ 'src/oom/oomd-util.h'],
+ [],
+ []]
+ ]
+
+ install_data('org.freedesktop.oom1.conf',
+ install_dir : dbuspolicydir)
+
+ install_data('org.freedesktop.oom1.service',
+ install_dir : dbussystemservicedir)
+
+ install_data('oomd.conf',
+ install_dir : pkgsysconfdir)
+endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "bus-error.h"
+#include "copy.h"
+#include "main-func.h"
+#include "pretty-print.h"
+#include "terminal-util.h"
+#include "verbs.h"
+
+static PagerFlags arg_pager_flags = 0;
+
+static int help(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = terminal_urlify_man("oomctl", "1", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%1$s [OPTIONS...] COMMAND ...\n\n"
+ "%2$sManage or inspect the userspace OOM killer.%3$s\n"
+ "\n%4$sCommands:%5$s\n"
+ " dump Output the current state of systemd-oomd\n"
+ "\n%4$sOptions:%5$s\n"
+ " -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
+ );
+
+ return 0;
+}
+
+static int dump_state(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int fd = -1;
+ int r;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect system bus: %m");
+
+ (void) pager_open(arg_pager_flags);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.oom1",
+ "/org/freedesktop/oom1",
+ "org.freedesktop.oom1.Manager",
+ "DumpByFileDescriptor",
+ &error,
+ &reply,
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to dump context: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "h", &fd);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ fflush(stdout);
+ return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
+}
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_NO_PAGER,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+
+ switch (c) {
+
+ case 'h':
+ return help(0, NULL, NULL);
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_NO_PAGER:
+ arg_pager_flags |= PAGER_DISABLE;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Invalid option passed.");
+ }
+
+ return 1;
+}
+
+static int run(int argc, char* argv[]) {
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, help },
+ { "dump", VERB_ANY, 1, VERB_DEFAULT, dump_state },
+ {}
+ };
+
+ int r;
+
+ log_show_color(true);
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ return dispatch_verb(argc, argv, verbs, NULL);
+}
+
+DEFINE_MAIN_FUNCTION(run);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <linux/capability.h>
+
+#include "bus-common-errors.h"
+#include "bus-polkit.h"
+#include "fd-util.h"
+#include "oomd-manager-bus.h"
+#include "oomd-manager.h"
+#include "user-util.h"
+
+static int bus_method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_free_ char *dump = NULL;
+ _cleanup_close_ int fd = -1;
+ Manager *m = userdata;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = manager_get_dump_string(m, &dump);
+ if (r < 0)
+ return r;
+
+ fd = acquire_data_fd(dump, strlen(dump), 0);
+ if (fd < 0)
+ return fd;
+
+ return sd_bus_reply_method_return(message, "h", fd);
+}
+
+static const sd_bus_vtable manager_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+ SD_BUS_METHOD_WITH_NAMES("DumpByFileDescriptor",
+ NULL,,
+ "h",
+ SD_BUS_PARAM(fd),
+ bus_method_dump_by_fd,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_VTABLE_END
+};
+
+const BusObjectImplementation manager_object = {
+ "/org/freedesktop/oom1",
+ "org.freedesktop.oom1.Manager",
+ .vtables = BUS_VTABLES(manager_vtable),
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "bus-object.h"
+
+typedef struct Manager Manager;
+
+extern const BusObjectImplementation manager_object;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-log-control-api.h"
+#include "bus-util.h"
+#include "bus-polkit.h"
+#include "cgroup-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "oomd-manager-bus.h"
+#include "oomd-manager.h"
+#include "path-util.h"
+
+typedef struct ManagedOOMReply {
+ ManagedOOMMode mode;
+ char *path;
+ char *property;
+ unsigned limit;
+} ManagedOOMReply;
+
+static void managed_oom_reply_destroy(ManagedOOMReply *reply) {
+ assert(reply);
+ free(reply->path);
+ free(reply->property);
+}
+
+static int managed_oom_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
+ ManagedOOMMode *mode = userdata, m;
+ const char *s;
+
+ assert(mode);
+ assert_se(s = json_variant_string(v));
+
+ 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);
+
+ *mode = m;
+ return 0;
+}
+
+static int process_managed_oom_reply(
+ Varlink *link,
+ JsonVariant *parameters,
+ const char *error_id,
+ VarlinkReplyFlags flags,
+ void *userdata) {
+ JsonVariant *c, *cgroups;
+ Manager *m = userdata;
+ int r = 0;
+
+ assert(m);
+
+ static const JsonDispatch dispatch_table[] = {
+ { "mode", JSON_VARIANT_STRING, managed_oom_mode, offsetof(ManagedOOMReply, mode), JSON_MANDATORY },
+ { "path", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMReply, path), JSON_MANDATORY },
+ { "property", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMReply, property), JSON_MANDATORY },
+ { "limit", JSON_VARIANT_UNSIGNED, json_dispatch_unsigned, offsetof(ManagedOOMReply, limit), 0 },
+ {},
+ };
+
+ if (error_id) {
+ r = -EIO;
+ log_debug("Error getting ManagedOOM cgroups: %s", error_id);
+ goto finish;
+ }
+
+ cgroups = json_variant_by_key(parameters, "cgroups");
+ if (!cgroups) {
+ r = -EINVAL;
+ goto finish;
+ }
+
+ /* Skip malformed elements and keep processing in case the others are good */
+ JSON_VARIANT_ARRAY_FOREACH(c, cgroups) {
+ _cleanup_(managed_oom_reply_destroy) ManagedOOMReply reply = {};
+ OomdCGroupContext *ctx;
+ Hashmap *monitor_hm;
+ loadavg_t limit;
+ int ret;
+
+ if (!json_variant_is_object(c))
+ continue;
+
+ ret = json_dispatch(c, dispatch_table, NULL, 0, &reply);
+ if (ret == -ENOMEM) {
+ r = ret;
+ goto finish;
+ } else if (ret < 0)
+ continue;
+
+ monitor_hm = streq(reply.property, "ManagedOOMSwap") ?
+ 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));
+ continue;
+ }
+
+ limit = m->default_mem_pressure_limit;
+
+ if (streq(reply.property, "ManagedOOMMemoryPressure")) {
+ if (reply.limit > 100)
+ continue;
+ else if (reply.limit != 0) {
+ ret = store_loadavg_fixed_point((unsigned long) reply.limit, 0, &limit);
+ if (ret < 0)
+ continue;
+ }
+ }
+
+ ret = oomd_insert_cgroup_context(NULL, monitor_hm, 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);
+ if (ctx)
+ ctx->mem_pressure_limit = limit;
+ }
+
+finish:
+ if (!FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+ m->varlink = varlink_close_unref(link);
+
+ return r;
+}
+
+/* Fill `new_h` with `path`'s descendent OomdCGroupContexts. Only include descendent cgroups that are possible
+ * candidates for action. That is, only leaf cgroups or cgroups with memory.oom.group set to "1".
+ *
+ * This function ignores most errors in order to handle cgroups that may have been cleaned up while populating
+ * the hashmap.
+ *
+ * `new_h` is of the form { key: cgroup paths -> value: OomdCGroupContext } */
+static int recursively_get_cgroup_context(Hashmap *new_h, const char *path) {
+ _cleanup_free_ char *subpath = NULL;
+ _cleanup_closedir_ DIR *d = NULL;
+ int r;
+
+ assert(new_h);
+ assert(path);
+
+ r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
+ if (r < 0)
+ return r;
+
+ r = cg_read_subgroup(d, &subpath);
+ if (r < 0)
+ return r;
+ else if (r == 0) { /* No subgroups? We're a leaf node */
+ r = oomd_insert_cgroup_context(NULL, new_h, path);
+ return (r == -ENOMEM) ? r : 0;
+ }
+
+ do {
+ _cleanup_free_ char *cg_path = NULL;
+ bool oom_group;
+
+ cg_path = path_join(empty_to_root(path), subpath);
+ if (!cg_path)
+ return -ENOMEM;
+
+ subpath = mfree(subpath);
+
+ r = cg_get_attribute_as_bool("memory", cg_path, "memory.oom.group", &oom_group);
+ /* The cgroup might be gone. Skip it as a candidate since we can't get information on it. */
+ if (r < 0)
+ return (r == -ENOMEM) ? r : 0;
+
+ if (oom_group)
+ r = oomd_insert_cgroup_context(NULL, new_h, cg_path);
+ else
+ r = recursively_get_cgroup_context(new_h, cg_path);
+ if (r == -ENOMEM)
+ return r;
+ } while ((r = cg_read_subgroup(d, &subpath)) > 0);
+
+ return 0;
+}
+
+static int update_monitored_cgroup_contexts(Hashmap **monitored_cgroups) {
+ _cleanup_hashmap_free_ Hashmap *new_base = NULL;
+ OomdCGroupContext *ctx;
+ int r;
+
+ assert(monitored_cgroups);
+
+ new_base = hashmap_new(&oomd_cgroup_ctx_hash_ops);
+ if (!new_base)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH(ctx, *monitored_cgroups) {
+ /* Skip most errors since the cgroup we're trying to update might not exist anymore. */
+ r = oomd_insert_cgroup_context(*monitored_cgroups, new_base, ctx->path);
+ if (r == -ENOMEM)
+ return r;
+ }
+
+ hashmap_free(*monitored_cgroups);
+ *monitored_cgroups = TAKE_PTR(new_base);
+
+ return 0;
+}
+
+static int get_monitored_cgroup_contexts_candidates(Hashmap *monitored_cgroups, Hashmap **ret_candidates) {
+ _cleanup_hashmap_free_ Hashmap *candidates = NULL;
+ OomdCGroupContext *ctx;
+ int r;
+
+ assert(monitored_cgroups);
+ assert(ret_candidates);
+
+ candidates = hashmap_new(&oomd_cgroup_ctx_hash_ops);
+ if (!candidates)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH(ctx, monitored_cgroups) {
+ r = recursively_get_cgroup_context(candidates, ctx->path);
+ if (r == -ENOMEM)
+ return r;
+ }
+
+ *ret_candidates = TAKE_PTR(candidates);
+
+ return 0;
+}
+
+static int acquire_managed_oom_connect(Manager *m) {
+ _cleanup_(varlink_close_unrefp) Varlink *link = NULL;
+ int r;
+
+ assert(m);
+ assert(m->event);
+
+ r = varlink_connect_address(&link, VARLINK_ADDR_PATH_MANAGED_OOM);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to %s: %m", VARLINK_ADDR_PATH_MANAGED_OOM);
+
+ (void) varlink_set_userdata(link, m);
+ (void) varlink_set_description(link, "oomd");
+ (void) varlink_set_relative_timeout(link, USEC_INFINITY);
+
+ r = varlink_attach_event(link, m->event, SD_EVENT_PRIORITY_NORMAL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
+
+ r = varlink_bind_reply(link, process_managed_oom_reply);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind reply callback: %m");
+
+ r = varlink_observe(link, "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to observe varlink call: %m");
+
+ m->varlink = TAKE_PTR(link);
+ return 0;
+}
+
+static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, void *userdata) {
+ _cleanup_set_free_ Set *targets = NULL;
+ Manager *m = userdata;
+ usec_t usec_now;
+ int r;
+
+ assert(s);
+ assert(userdata);
+
+ /* Reset timer */
+ r = sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &usec_now);
+ if (r < 0)
+ return log_error_errno(r, "Failed to reset event timer");
+
+ r = sd_event_source_set_time_relative(s, INTERVAL_USEC);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set relative time for timer");
+
+ /* Reconnect if our connection dropped */
+ if (!m->varlink) {
+ r = acquire_managed_oom_connect(m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to acquire varlink connection");
+ }
+
+ /* Update the cgroups used for detection/action */
+ r = update_monitored_cgroup_contexts(&m->monitored_swap_cgroup_contexts);
+ if (r == -ENOMEM)
+ return log_error_errno(r, "Failed to update monitored swap cgroup contexts");
+
+ r = update_monitored_cgroup_contexts(&m->monitored_mem_pressure_cgroup_contexts);
+ if (r == -ENOMEM)
+ 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)))
+ return log_error_errno(r, "Failed to acquire system context");
+
+ /* If we're still recovering from a kill, don't try to kill again yet */
+ if (m->post_action_delay_start > 0) {
+ if (m->post_action_delay_start + POST_ACTION_DELAY_USEC > usec_now)
+ return 0;
+ else
+ m->post_action_delay_start = 0;
+ }
+
+ r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, 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:
+ * 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)) {
+ _cleanup_hashmap_free_ Hashmap *candidates = NULL;
+ OomdCGroupContext *t;
+
+ r = get_monitored_cgroup_contexts_candidates(m->monitored_mem_pressure_cgroup_contexts, &candidates);
+ if (r == -ENOMEM)
+ return log_error_errno(r, "Failed to get monitored memory pressure cgroup candidates");
+
+ 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);
+
+ r = oomd_kill_by_pgscan(candidates, t->path, m->dry_run);
+ if (r == -ENOMEM)
+ return log_error_errno(r, "Failed to kill cgroup processes by pgscan");
+ if (r < 0)
+ log_info("Failed to kill any cgroup(s) under %s based on pressure", t->path);
+ else {
+ /* Don't act on all the high pressure cgroups at once; return as soon as we kill one */
+ m->post_action_delay_start = usec_now;
+ return 0;
+ }
+ }
+ }
+ }
+
+ if (oomd_swap_free_below(&m->system_context, (100 - m->swap_used_limit))) {
+ _cleanup_hashmap_free_ Hashmap *candidates = NULL;
+
+ log_notice("Swap used (%"PRIu64") / total (%"PRIu64") is more than %u%%",
+ m->system_context.swap_used, m->system_context.swap_total, m->swap_used_limit);
+
+ r = get_monitored_cgroup_contexts_candidates(m->monitored_swap_cgroup_contexts, &candidates);
+ if (r == -ENOMEM)
+ return log_error_errno(r, "Failed to get monitored swap cgroup candidates");
+
+ r = oomd_kill_by_swap_usage(candidates, m->dry_run);
+ if (r == -ENOMEM)
+ return log_error_errno(r, "Failed to kill cgroup processes by swap usage");
+ if (r < 0)
+ log_info("Failed to kill any cgroup(s) based on swap");
+ else {
+ m->post_action_delay_start = usec_now;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int monitor_cgroup_contexts(Manager *m) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+ int r;
+
+ assert(m);
+ assert(m->event);
+
+ r = sd_event_add_time(m->event, &s, CLOCK_MONOTONIC, 0, 0, monitor_cgroup_contexts_handler, m);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_exit_on_failure(s, true);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_enabled(s, SD_EVENT_ON);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_source_set_description(s, "oomd-timer");
+
+ m->cgroup_context_event_source = TAKE_PTR(s);
+ return 0;
+}
+
+void manager_free(Manager *m) {
+ assert(m);
+
+ varlink_close_unref(m->varlink);
+ sd_event_source_unref(m->cgroup_context_event_source);
+ sd_event_unref(m->event);
+
+ bus_verify_polkit_async_registry_free(m->polkit_registry);
+ sd_bus_flush_close_unref(m->bus);
+
+ hashmap_free(m->monitored_swap_cgroup_contexts);
+ hashmap_free(m->monitored_mem_pressure_cgroup_contexts);
+
+ free(m);
+}
+
+int manager_new(Manager **ret) {
+ _cleanup_(manager_freep) Manager *m = NULL;
+ int r;
+
+ assert(ret);
+
+ m = new0(Manager, 1);
+ if (!m)
+ return -ENOMEM;
+
+ r = sd_event_default(&m->event);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_set_watchdog(m->event, true);
+
+ r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ m->monitored_swap_cgroup_contexts = hashmap_new(&oomd_cgroup_ctx_hash_ops);
+ if (!m->monitored_swap_cgroup_contexts)
+ return -ENOMEM;
+
+ m->monitored_mem_pressure_cgroup_contexts = hashmap_new(&oomd_cgroup_ctx_hash_ops);
+ if (!m->monitored_mem_pressure_cgroup_contexts)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(m);
+ return 0;
+}
+
+static int manager_connect_bus(Manager *m) {
+ int r;
+
+ assert(m);
+ assert(!m->bus);
+
+ r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-oom");
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to bus: %m");
+
+ r = bus_add_implementation(m->bus, &manager_object, m);
+ if (r < 0)
+ return r;
+
+ r = bus_log_control_api_register(m->bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.oom1", 0, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to request name: %m");
+
+ r = sd_bus_attach_event(m->bus, m->event, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
+ return 0;
+}
+
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit) {
+ unsigned long l;
+ int r;
+
+ assert(m);
+
+ m->dry_run = dry_run;
+
+ 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 (r < 0)
+ return r;
+
+ r = manager_connect_bus(m);
+ if (r < 0)
+ return r;
+
+ r = acquire_managed_oom_connect(m);
+ if (r < 0)
+ return r;
+
+ r = monitor_cgroup_contexts(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int manager_get_dump_string(Manager *m, char **ret) {
+ _cleanup_free_ char *dump = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ OomdCGroupContext *c;
+ size_t size;
+ char *key;
+ int r;
+
+ assert(m);
+ assert(ret);
+
+ f = open_memstream_unlocked(&dump, &size);
+ if (!f)
+ return -errno;
+
+ fprintf(f,
+ "Dry Run: %s\n"
+ "Swap Used Limit: %u%%\n"
+ "Default Memory Pressure Limit: %lu%%\n"
+ "System Context:\n",
+ yes_no(m->dry_run),
+ m->swap_used_limit,
+ LOAD_INT(m->default_mem_pressure_limit));
+ oomd_dump_system_context(&m->system_context, f, "\t");
+
+ fprintf(f, "Swap Monitored CGroups:\n");
+ HASHMAP_FOREACH_KEY(c, key, m->monitored_swap_cgroup_contexts)
+ oomd_dump_swap_cgroup_context(c, f, "\t");
+
+ fprintf(f, "Memory Pressure Monitored CGroups:\n");
+ HASHMAP_FOREACH_KEY(c, key, m->monitored_mem_pressure_cgroup_contexts)
+ oomd_dump_memory_pressure_cgroup_context(c, f, "\t");
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
+
+ f = safe_fclose(f);
+
+ *ret = TAKE_PTR(dump);
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+#include "oomd-util.h"
+#include "sd-event.h"
+#include "varlink.h"
+
+/* Polling interval for monitoring stats */
+#define INTERVAL_USEC (1 * USEC_PER_SEC)
+
+/* Used to weight the averages */
+#define AVERAGE_SIZE_DECAY 4
+
+/* Take action if 10s of memory pressure > 60 for more than 30s. We use the "full" value from PSI so this is the
+ * 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_SWAP_USED_LIMIT 90
+
+#define POST_ACTION_DELAY_USEC (15 * USEC_PER_SEC)
+
+typedef struct Manager Manager;
+
+struct Manager {
+ sd_bus *bus;
+ sd_event *event;
+
+ Hashmap *polkit_registry;
+
+ bool dry_run;
+ unsigned swap_used_limit;
+ loadavg_t default_mem_pressure_limit;
+
+ /* k: cgroup paths -> v: OomdCGroupContext
+ * Used to detect when to take action. */
+ Hashmap *monitored_swap_cgroup_contexts;
+ Hashmap *monitored_mem_pressure_cgroup_contexts;
+
+ OomdSystemContext system_context;
+
+ usec_t post_action_delay_start;
+
+ sd_event_source *cgroup_context_event_source;
+
+ Varlink *varlink;
+};
+
+void 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_get_dump_string(Manager *m, char **ret);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_oomd_default);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "cgroup-util.h"
+#include "fd-util.h"
+#include "format-util.h"
+#include "oomd-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "procfs-util.h"
+#include "signal-util.h"
+#include "sort-util.h"
+#include "stat-util.h"
+#include "stdio-util.h"
+
+DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ oomd_cgroup_ctx_hash_ops,
+ char,
+ string_hash_func,
+ string_compare_func,
+ OomdCGroupContext,
+ oomd_cgroup_context_free);
+
+static int log_kill(pid_t pid, int sig, void *userdata) {
+ log_debug("oomd attempting to kill " PID_FMT " with %s", pid, signal_to_string(sig));
+ return 0;
+}
+
+static int increment_oomd_xattr(const char *path, const char *xattr, uint64_t num_procs_killed) {
+ _cleanup_free_ char *value = NULL;
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+ uint64_t curr_count = 0;
+ int r;
+
+ assert(path);
+ assert(xattr);
+
+ r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, path, xattr, &value);
+ if (r < 0 && r != -ENODATA)
+ return r;
+
+ if (!isempty(value)) {
+ r = safe_atou64(value, &curr_count);
+ if (r < 0)
+ return r;
+ }
+
+ if (curr_count > UINT64_MAX - num_procs_killed)
+ return -EOVERFLOW;
+
+ xsprintf(buf, "%"PRIu64, curr_count + num_procs_killed);
+ r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, path, xattr, buf, strlen(buf), 0);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+OomdCGroupContext *oomd_cgroup_context_free(OomdCGroupContext *ctx) {
+ if (!ctx)
+ return NULL;
+
+ free(ctx->path);
+ return mfree(ctx);
+}
+
+int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret) {
+ _cleanup_set_free_ Set *targets = NULL;
+ OomdCGroupContext *ctx;
+ char *key;
+ int r;
+
+ assert(h);
+ assert(ret);
+
+ targets = set_new(NULL);
+ if (!targets)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH_KEY(ctx, key, h) {
+ if (ctx->memory_pressure.avg10 > ctx->mem_pressure_limit) {
+ usec_t diff;
+
+ if (ctx->last_hit_mem_pressure_limit == 0)
+ ctx->last_hit_mem_pressure_limit = now(CLOCK_MONOTONIC);
+
+ diff = now(CLOCK_MONOTONIC) - ctx->last_hit_mem_pressure_limit;
+ if (diff >= duration) {
+ r = set_put(targets, ctx);
+ if (r < 0)
+ return -ENOMEM;
+ }
+ } else
+ ctx->last_hit_mem_pressure_limit = 0;
+ }
+
+ if (!set_isempty(targets)) {
+ *ret = TAKE_PTR(targets);
+ return 1;
+ }
+
+ *ret = NULL;
+ return 0;
+}
+
+bool oomd_memory_reclaim(Hashmap *h) {
+ uint64_t pgscan = 0, pgscan_of = 0, last_pgscan = 0, last_pgscan_of = 0;
+ OomdCGroupContext *ctx;
+
+ assert(h);
+
+ /* If sum of all the current pgscan values are greater than the sum of all the last_pgscan values,
+ * there was reclaim activity. Used along with pressure checks to decide whether to take action. */
+
+ HASHMAP_FOREACH(ctx, h) {
+ uint64_t sum;
+
+ sum = pgscan + ctx->pgscan;
+ if (sum < pgscan || sum < ctx->pgscan)
+ pgscan_of++; /* count overflows */
+ pgscan = sum;
+
+ sum = last_pgscan + ctx->last_pgscan;
+ if (sum < last_pgscan || sum < ctx->last_pgscan)
+ last_pgscan_of++; /* count overflows */
+ last_pgscan = sum;
+ }
+
+ /* overflow counts are the same, return sums comparison */
+ if (last_pgscan_of == pgscan_of)
+ return pgscan > last_pgscan;
+
+ return pgscan_of > last_pgscan_of;
+}
+
+bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent) {
+ uint64_t swap_threshold;
+
+ assert(ctx);
+ assert(threshold_percent <= 100);
+
+ swap_threshold = ctx->swap_total * threshold_percent / ((uint64_t) 100);
+ return (ctx->swap_total - ctx->swap_used) < swap_threshold;
+}
+
+int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const char *prefix, OomdCGroupContext ***ret) {
+ _cleanup_free_ OomdCGroupContext **sorted = NULL;
+ OomdCGroupContext *item;
+ size_t k = 0;
+
+ assert(h);
+ assert(compare_func);
+ assert(ret);
+
+ sorted = new0(OomdCGroupContext*, hashmap_size(h));
+ if (!sorted)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH(item, h) {
+ if (item->path && prefix && !path_startswith(item->path, prefix))
+ continue;
+
+ sorted[k++] = item;
+ }
+
+ typesafe_qsort(sorted, k, compare_func);
+
+ *ret = TAKE_PTR(sorted);
+
+ assert(k <= INT_MAX);
+ return (int) k;
+}
+
+int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run) {
+ _cleanup_set_free_ Set *pids_killed = NULL;
+ int r;
+
+ assert(path);
+
+ if (dry_run) {
+ _cleanup_free_ char *cg_path = NULL;
+
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &cg_path);
+ if (r < 0)
+ return r;
+
+ log_debug("oomd dry-run: Would have tried to kill %s with recurse=%s", cg_path, true_false(recurse));
+ return 0;
+ }
+
+ pids_killed = set_new(NULL);
+ if (!pids_killed)
+ return -ENOMEM;
+
+ if (recurse)
+ r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL);
+ else
+ r = cg_kill(SYSTEMD_CGROUP_CONTROLLER, path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL);
+ if (r < 0)
+ return r;
+
+ r = increment_oomd_xattr(path, "user.systemd_oomd_kill", set_size(pids_killed));
+ if (r < 0)
+ log_debug_errno(r, "Failed to set user.systemd_oomd_kill on kill: %m");
+
+ return set_size(pids_killed) != 0;
+}
+
+int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run) {
+ _cleanup_free_ OomdCGroupContext **sorted = NULL;
+ int r;
+
+ assert(h);
+
+ r = oomd_sort_cgroup_contexts(h, compare_pgscan, prefix, &sorted);
+ if (r < 0)
+ return r;
+
+ for (int i = 0; i < r; i++) {
+ if (sorted[i]->pgscan == 0)
+ break;
+
+ r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
+ if (r > 0 || r == -ENOMEM)
+ break;
+ }
+
+ return r;
+}
+
+int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run) {
+ _cleanup_free_ OomdCGroupContext **sorted = NULL;
+ int r;
+
+ assert(h);
+
+ r = oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted);
+ if (r < 0)
+ return r;
+
+ /* 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++) {
+ if (sorted[i]->swap_usage == 0)
+ break;
+
+ r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
+ if (r > 0 || r == -ENOMEM)
+ break;
+ }
+
+ return r;
+}
+
+int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
+ _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
+ _cleanup_free_ char *p = NULL, *val = NULL;
+ bool is_root;
+ int r;
+
+ assert(path);
+ assert(ret);
+
+ ctx = new0(OomdCGroupContext, 1);
+ if (!ctx)
+ return -ENOMEM;
+
+ is_root = empty_or_root(path);
+
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "memory.pressure", &p);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting cgroup memory pressure path from %s: %m", path);
+
+ r = read_resource_pressure(p, PRESSURE_TYPE_FULL, &ctx->memory_pressure);
+ if (r < 0)
+ return log_debug_errno(r, "Error parsing memory pressure from %s: %m", p);
+
+ if (is_root) {
+ r = procfs_memory_get_used(&ctx->current_memory_usage);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting memory used from procfs: %m");
+ } else {
+ r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.current", &ctx->current_memory_usage);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting memory.current from %s: %m", path);
+
+ r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.min", &ctx->memory_min);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting memory.min from %s: %m", path);
+
+ r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.low", &ctx->memory_low);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting memory.low from %s: %m", path);
+
+ r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.swap.current", &ctx->swap_usage);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting memory.swap.current from %s: %m", path);
+
+ r = cg_get_keyed_attribute(SYSTEMD_CGROUP_CONTROLLER, path, "memory.stat", STRV_MAKE("pgscan"), &val);
+ if (r < 0)
+ return log_debug_errno(r, "Error getting pgscan from memory.stat under %s: %m", path);
+
+ r = safe_atou64(val, &ctx->pgscan);
+ if (r < 0)
+ return log_debug_errno(r, "Error converting pgscan value to uint64_t: %m");
+ }
+
+ ctx->path = strdup(empty_to_root(path));
+ if (!ctx->path)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(ctx);
+ return 0;
+}
+
+int oomd_system_context_acquire(const char *proc_swaps_path, OomdSystemContext *ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ OomdSystemContext ctx = {};
+ int r;
+
+ assert(proc_swaps_path);
+ assert(ret);
+
+ f = fopen(proc_swaps_path, "re");
+ if (!f)
+ return -errno;
+
+ (void) fscanf(f, "%*s %*s %*s %*s %*s\n");
+
+ for (;;) {
+ uint64_t total, used;
+
+ r = fscanf(f,
+ "%*s " /* device/file */
+ "%*s " /* type of swap */
+ "%" PRIu64 " " /* swap size */
+ "%" PRIu64 " " /* used */
+ "%*s\n", /* priority */
+ &total, &used);
+
+ if (r == EOF && feof(f))
+ break;
+
+ if (r != 2) {
+ if (ferror(f))
+ return log_debug_errno(errno, "Error reading from %s: %m", proc_swaps_path);
+
+ return log_debug_errno(SYNTHETIC_ERRNO(EIO),
+ "Failed to parse values from %s: %m", proc_swaps_path);
+ }
+
+ ctx.swap_total += total * 1024U;
+ ctx.swap_used += used * 1024U;
+ }
+
+ *ret = ctx;
+ return 0;
+}
+
+int oomd_insert_cgroup_context(Hashmap *old_h, Hashmap *new_h, const char *path) {
+ _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *curr_ctx = NULL;
+ OomdCGroupContext *old_ctx, *ctx;
+ int r;
+
+ assert(new_h);
+ assert(path);
+
+ r = oomd_cgroup_context_acquire(path, &curr_ctx);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get OomdCGroupContext for %s: %m", path);
+
+ old_ctx = hashmap_get(old_h, path);
+ if (old_ctx) {
+ curr_ctx->last_pgscan = old_ctx->pgscan;
+ curr_ctx->mem_pressure_limit = old_ctx->mem_pressure_limit;
+ curr_ctx->last_hit_mem_pressure_limit = old_ctx->last_hit_mem_pressure_limit;
+ }
+
+ ctx = TAKE_PTR(curr_ctx);
+ r = hashmap_put(new_h, ctx->path, ctx);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+void oomd_dump_swap_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix) {
+ char swap[FORMAT_BYTES_MAX];
+
+ assert(ctx);
+ assert(f);
+
+ if (!empty_or_root(ctx->path))
+ fprintf(f,
+ "%sPath: %s\n"
+ "%s\tSwap Usage: %s\n",
+ strempty(prefix), ctx->path,
+ strempty(prefix), format_bytes(swap, sizeof(swap), ctx->swap_usage));
+ else
+ fprintf(f,
+ "%sPath: %s\n"
+ "%s\tSwap Usage: (see System Context)\n",
+ strempty(prefix), ctx->path,
+ strempty(prefix));
+}
+
+void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix) {
+ char tbuf[FORMAT_TIMESPAN_MAX], mem_use[FORMAT_BYTES_MAX];
+ char mem_min[FORMAT_BYTES_MAX], mem_low[FORMAT_BYTES_MAX];
+
+ assert(ctx);
+ assert(f);
+
+ fprintf(f,
+ "%sPath: %s\n"
+ "%s\tMemory Pressure Limit: %lu%%\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->memory_pressure.avg10), LOAD_FRAC(ctx->memory_pressure.avg10),
+ LOAD_INT(ctx->memory_pressure.avg60), LOAD_FRAC(ctx->memory_pressure.avg60),
+ LOAD_INT(ctx->memory_pressure.avg300), LOAD_FRAC(ctx->memory_pressure.avg300),
+ format_timespan(tbuf, sizeof(tbuf), ctx->memory_pressure.total, USEC_PER_SEC),
+ strempty(prefix), format_bytes(mem_use, sizeof(mem_use), ctx->current_memory_usage));
+
+ if (!empty_or_root(ctx->path))
+ fprintf(f,
+ "%s\tMemory Min: %s\n"
+ "%s\tMemory Low: %s\n"
+ "%s\tPgscan: %" PRIu64 "\n",
+ strempty(prefix), format_bytes_cgroup_protection(mem_min, sizeof(mem_min), ctx->memory_min),
+ strempty(prefix), format_bytes_cgroup_protection(mem_low, sizeof(mem_low), ctx->memory_low),
+ strempty(prefix), ctx->pgscan);
+}
+
+void oomd_dump_system_context(const OomdSystemContext *ctx, FILE *f, const char *prefix) {
+ char used[FORMAT_BYTES_MAX], total[FORMAT_BYTES_MAX];
+
+ assert(ctx);
+ assert(f);
+
+ fprintf(f,
+ "%sSwap: Used: %s Total: %s\n",
+ strempty(prefix),
+ format_bytes(used, sizeof(used), ctx->swap_used),
+ format_bytes(total, sizeof(total), ctx->swap_total));
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "hashmap.h"
+#include "psi-util.h"
+
+#define GROWING_SIZE_PERCENTILE 80
+
+extern const struct hash_ops oomd_cgroup_ctx_hash_ops;
+
+typedef struct OomdCGroupContext OomdCGroupContext;
+typedef struct OomdSystemContext OomdSystemContext;
+
+typedef int (oomd_compare_t)(OomdCGroupContext * const *, OomdCGroupContext * const *);
+
+struct OomdCGroupContext {
+ char *path;
+
+ ResourcePressure memory_pressure;
+
+ uint64_t current_memory_usage;
+
+ uint64_t memory_min;
+ uint64_t memory_low;
+ uint64_t swap_usage;
+
+ uint64_t last_pgscan;
+ uint64_t pgscan;
+
+ /* These are only used by oomd_pressure_above for acting on high memory pressure. */
+ loadavg_t mem_pressure_limit;
+ usec_t last_hit_mem_pressure_limit;
+};
+
+struct OomdSystemContext {
+ uint64_t swap_total;
+ uint64_t swap_used;
+};
+
+OomdCGroupContext *oomd_cgroup_context_free(OomdCGroupContext *ctx);
+DEFINE_TRIVIAL_CLEANUP_FUNC(OomdCGroupContext*, oomd_cgroup_context_free);
+
+/* All hashmaps used with these functions are expected to be of the form
+ * key: cgroup paths -> value: OomdCGroupContext. */
+
+/* Scans all the OomdCGroupContexts in `h` and returns 1 and a set of pointers to those OomdCGroupContexts in `ret`
+ * if any of them have exceeded their supplied memory pressure limits for the `duration` length of time.
+ * `last_hit_mem_pressure_limit` is updated accordingly for each entry when the limit is exceeded, and when it returns
+ * below the limit.
+ * Returns 0 and sets `ret` to an empty set if no entries exceeded limits for `duration`.
+ * Returns -ENOMEM for allocation errors. */
+int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret);
+
+/* Sum up current OomdCGroupContexts' pgscan values and last interval's pgscan values in `h`. Returns true if the
+ * current sum is higher than the last interval's sum (there was some reclaim activity). */
+bool oomd_memory_reclaim(Hashmap *h);
+
+/* 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) {
+ assert(c1);
+ assert(c2);
+
+ if ((*c1)->pgscan > (*c2)->pgscan)
+ return -1;
+ else if ((*c1)->pgscan < (*c2)->pgscan)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
+ assert(c1);
+ assert(c2);
+
+ if ((*c1)->swap_usage > (*c2)->swap_usage)
+ return -1;
+ else if ((*c1)->swap_usage < (*c2)->swap_usage)
+ return 1;
+ else
+ return 0;
+}
+
+/* Get an array of OomdCGroupContexts from `h`, qsorted from largest to smallest values according to `compare_func`.
+ * If `prefix` is not NULL, only include OomdCGroupContexts whose paths start with prefix. Otherwise all paths are sorted.
+ * Returns the number of sorted items; negative on error. */
+int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const char *prefix, OomdCGroupContext ***ret);
+
+/* Returns a negative value on error, 0 if no processes were killed, or 1 if processes were killed. */
+int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run);
+
+/* The following oomd_kill_by_* functions return 1 if processes were killed, or negative otherwise. */
+/* If `prefix` is supplied, only cgroups whose paths start with `prefix` are eligible candidates. Otherwise,
+ * everything in `h` is a candidate. */
+int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run);
+int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run);
+
+int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret);
+int oomd_system_context_acquire(const char *proc_swaps_path, OomdSystemContext *ret);
+
+/* Get the OomdCGroupContext of `path` and insert it into `new_h`. The key for the inserted context will be `path`.
+ *
+ * `old_h` is used to get data used to calculate prior interval information. `old_h` can be NULL in which case there
+ * was no prior data to reference. */
+int oomd_insert_cgroup_context(Hashmap *old_h, Hashmap *new_h, const char *path);
+
+void oomd_dump_swap_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix);
+void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE *f, const char *prefix);
+void oomd_dump_system_context(const OomdSystemContext *ctx, FILE *f, const char *prefix);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+
+#include "bus-log-control-api.h"
+#include "bus-object.h"
+#include "cgroup-util.h"
+#include "conf-parser.h"
+#include "daemon-util.h"
+#include "log.h"
+#include "main-func.h"
+#include "oomd-manager.h"
+#include "oomd-manager-bus.h"
+#include "parse-util.h"
+#include "pretty-print.c"
+#include "psi-util.h"
+#include "signal-util.h"
+
+static bool arg_dry_run = false;
+static int arg_swap_used_limit = -1;
+static int arg_mem_pressure_limit = -1;
+
+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 },
+ {}
+ };
+
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/oomd.conf",
+ CONF_PATHS_NULSTR("systemd/oomd.conf.d"),
+ "OOM\0",
+ config_item_table_lookup,
+ items,
+ CONFIG_PARSE_WARN,
+ NULL,
+ NULL);
+}
+
+static int help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("systemd-oomd", "1", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...]\n\n"
+ "Run the userspace out-of-memory (OOM) killer.\n\n"
+ " -h --help Show this help\n"
+ " --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
+ );
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_DRY_RUN,
+ ARG_BUS_INTROSPECT,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "dry-run", no_argument, NULL, ARG_DRY_RUN },
+ { "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+
+ switch (c) {
+
+ case 'h':
+ return help();
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_DRY_RUN:
+ arg_dry_run = true;
+ break;
+
+ case ARG_BUS_INTROSPECT:
+ return bus_introspect_implementations(
+ stdout,
+ optarg,
+ BUS_IMPLEMENTATIONS(&manager_object,
+ &log_control_object));
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unknown option code.");
+ }
+
+ if (optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This program takes no arguments.");
+
+ return 1;
+}
+
+static int run(int argc, char *argv[]) {
+ _cleanup_(notify_on_cleanup) const char *notify_msg = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ int r;
+
+ log_setup_service();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ r = parse_config();
+ if (r < 0)
+ return r;
+
+ /* Do some basic requirement checks for running systemd-oomd. It's not exhaustive as some of the other
+ * requirements do not have a reliable means to check for in code. */
+ if (access("/proc/swaps", F_OK) < 0)
+ return log_error_errno(errno, "Swap not enabled: %m");
+
+ if (!is_pressure_supported())
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Pressure Stall Information (PSI) is not supported");
+
+ r = cg_all_unified();
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Requires the unified cgroups hierarchy");
+
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
+ r = manager_new(&m);
+ 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);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start up daemon: %m");
+
+ notify_msg = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
+
+ log_info("systemd-oomd starting%s!", arg_dry_run ? " in dry run mode" : "");
+
+ r = sd_event_loop(m->event);
+ if (r < 0)
+ return log_error_errno(r, "Event loop failed: %m");
+
+ return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
--- /dev/null
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# Entries in this file show the compile time defaults.
+# You can change settings by editing this file.
+# Defaults can be restored by simply deleting this file.
+#
+# See oomd.conf(5) for details
+
+[OOM]
+#SwapUsedLimitPercent=90%
+#DefaultMemoryPressureLimitPercent=60%
--- /dev/null
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<busconfig>
+
+ <policy user="systemd-oom">
+ <allow own="org.freedesktop.oom1"/>
+ <allow send_destination="org.freedesktop.oom1"/>
+ <allow receive_sender="org.freedesktop.oom1"/>
+ </policy>
+
+ <policy user="root">
+ <allow send_destination="org.freedesktop.oom1"/>
+ </policy>
+
+ <policy context="default">
+ <deny send_destination="org.freedesktop.oom1"/>
+
+ <!-- Generic interfaces -->
+
+ <allow send_destination="org.freedesktop.oom1"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+
+ <allow send_destination="org.freedesktop.oom1"
+ send_interface="org.freedesktop.DBus.Peer"/>
+
+ <allow send_destination="org.freedesktop.oom1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.oom1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="GetAll"/>
+
+ <!-- Manager interface -->
+
+ <allow send_destination="org.freedesktop.oom1"
+ send_interface="org.freedesktop.oom1.Manager"
+ send_member="DumpByFileDescriptor"/>
+
+ <allow receive_sender="org.freedesktop.oom1"/>
+ </policy>
+
+</busconfig>
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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.
+
+[D-BUS Service]
+Name=org.freedesktop.oom1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.oom1.service
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "cgroup-setup.h"
+#include "cgroup-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "oomd-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "tests.h"
+
+static int fork_and_sleep(unsigned sleep_min) {
+ usec_t n, timeout, ts;
+
+ pid_t pid = fork();
+ assert_se(pid >= 0);
+
+ if (pid == 0) {
+ timeout = sleep_min * USEC_PER_MINUTE;
+ ts = now(CLOCK_MONOTONIC);
+ while (true) {
+ n = now(CLOCK_MONOTONIC);
+ if (ts + timeout < n) {
+ log_error("Child timed out waiting to be killed");
+ abort();
+ }
+ sleep(1);
+ }
+ }
+
+ return pid;
+}
+
+static void test_oomd_cgroup_kill(void) {
+ _cleanup_free_ char *cgroup_root = NULL, *cgroup = NULL;
+ int pid[2];
+ int r;
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ if (cg_all_unified() <= 0)
+ return (void) log_tests_skipped("cgroups are not running in unified mode");
+
+ assert_se(cg_pid_get_path(NULL, 0, &cgroup_root) >= 0);
+
+ /* Create another cgroup below this one for the pids we forked off. We need this to be managed
+ * by the test so that pid1 doesn't delete it before we can read the xattrs. */
+ cgroup = path_join(cgroup_root, "oomdkilltest");
+ assert(cgroup);
+ assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, cgroup) >= 0);
+
+ /* If we don't have permissions to set xattrs we're likely in a userns or missing capabilities */
+ r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_test", "test", 4, 0);
+ if (IN_SET(r, -EPERM, -ENOTSUP))
+ return (void) log_tests_skipped("Cannot set user xattrs");
+
+ /* Do this twice to also check the increment behavior on the xattrs */
+ for (int i = 0; i < 2; i++) {
+ _cleanup_free_ char *v = NULL;
+
+ for (int j = 0; j < 2; j++) {
+ pid[j] = fork_and_sleep(5);
+ assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup, pid[j]) >= 0);
+ }
+
+ r = oomd_cgroup_kill(cgroup, false /* recurse */, false /* dry run */);
+ if (r <= 0) {
+ log_debug_errno(r, "Failed to kill processes under %s: %m", cgroup);
+ abort();
+ }
+
+ /* Wait a bit since processes may take some time to be cleaned up. */
+ 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(memcmp(v, i == 0 ? "2" : "4", 2) == 0);
+ }
+}
+
+static void test_oomd_cgroup_context_acquire_and_insert(void) {
+ _cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL;
+ _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
+ _cleanup_free_ char *cgroup = NULL;
+ OomdCGroupContext *c1, *c2;
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ if (!is_pressure_supported())
+ return (void) log_tests_skipped("system does not support pressure");
+
+ if (cg_all_unified() <= 0)
+ return (void) log_tests_skipped("cgroups are not running in unified mode");
+
+ assert_se(cg_pid_get_path(NULL, 0, &cgroup) >= 0);
+
+ assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
+
+ assert_se(streq(ctx->path, cgroup));
+ assert_se(ctx->memory_pressure.avg10 == 0);
+ assert_se(ctx->memory_pressure.avg60 == 0);
+ assert_se(ctx->memory_pressure.avg300 == 0);
+ assert_se(ctx->memory_pressure.total == 0);
+ assert_se(ctx->current_memory_usage > 0);
+ assert_se(ctx->memory_min == 0);
+ assert_se(ctx->memory_low == 0);
+ assert_se(ctx->swap_usage == 0);
+ assert_se(ctx->last_pgscan == 0);
+ assert_se(ctx->pgscan == 0);
+ 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);
+
+ /* Test hashmap inserts */
+ assert_se(h1 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
+ assert_se(oomd_insert_cgroup_context(NULL, h1, cgroup) == 0);
+ c1 = hashmap_get(h1, cgroup);
+ assert_se(c1);
+
+ /* make sure certain values from h1 get updated in h2 */
+ c1->pgscan = 5555;
+ c1->mem_pressure_limit = 6789;
+ c1->last_hit_mem_pressure_limit = 42;
+ assert_se(h2 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
+ assert_se(oomd_insert_cgroup_context(h1, h2, cgroup) == 0);
+ c1 = hashmap_get(h1, cgroup);
+ c2 = hashmap_get(h2, cgroup);
+ assert_se(c1);
+ assert_se(c2);
+ assert_se(c1 != c2);
+ assert_se(c2->last_pgscan == 5555);
+ assert_se(c2->mem_pressure_limit == 6789);
+ assert_se(c2->last_hit_mem_pressure_limit == 42);
+}
+
+static void test_oomd_system_context_acquire(void) {
+ _cleanup_(unlink_tempfilep) char path[] = "/oomdgetsysctxtestXXXXXX";
+ OomdSystemContext ctx;
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ assert_se(mkstemp(path));
+
+ assert_se(oomd_system_context_acquire("/verylikelynonexistentpath", &ctx) == -ENOENT);
+
+ 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, "some\nwords\nacross\nmultiple\nlines", 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);
+ assert_se(oomd_system_context_acquire(path, &ctx) == 0);
+ assert_se(ctx.swap_total == 21474828288);
+ assert_se(ctx.swap_used == 1017630720);
+}
+
+static void test_oomd_pressure_above(void) {
+ _cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL;
+ _cleanup_set_free_ Set *t1 = NULL, *t2 = NULL, *t3 = NULL;
+ OomdCGroupContext ctx[2], *c;
+ loadavg_t threshold;
+
+ assert_se(store_loadavg_fixed_point(80, 0, &threshold) == 0);
+
+ /* /herp.slice */
+ assert_se(store_loadavg_fixed_point(99, 99, &(ctx[0].memory_pressure.avg10)) == 0);
+ assert_se(store_loadavg_fixed_point(99, 99, &(ctx[0].memory_pressure.avg60)) == 0);
+ assert_se(store_loadavg_fixed_point(99, 99, &(ctx[0].memory_pressure.avg300)) == 0);
+ ctx[0].mem_pressure_limit = threshold;
+
+ /* /derp.slice */
+ assert_se(store_loadavg_fixed_point(1, 11, &(ctx[1].memory_pressure.avg10)) == 0);
+ assert_se(store_loadavg_fixed_point(1, 11, &(ctx[1].memory_pressure.avg60)) == 0);
+ assert_se(store_loadavg_fixed_point(1, 11, &(ctx[1].memory_pressure.avg300)) == 0);
+ ctx[1].mem_pressure_limit = threshold;
+
+
+ /* High memory pressure */
+ assert_se(h1 = hashmap_new(&string_hash_ops));
+ assert_se(hashmap_put(h1, "/herp.slice", &ctx[0]) >= 0);
+ assert_se(oomd_pressure_above(h1, 0 /* duration */, &t1) == 1);
+ assert_se(set_contains(t1, &ctx[0]) == true);
+ assert_se(c = hashmap_get(h1, "/herp.slice"));
+ assert_se(c->last_hit_mem_pressure_limit > 0);
+
+ /* Low memory pressure */
+ assert_se(h2 = hashmap_new(&string_hash_ops));
+ assert_se(hashmap_put(h2, "/derp.slice", &ctx[1]) >= 0);
+ assert_se(oomd_pressure_above(h2, 0 /* duration */, &t2) == 0);
+ assert_se(t2 == NULL);
+ assert_se(c = hashmap_get(h2, "/derp.slice"));
+ assert_se(c->last_hit_mem_pressure_limit == 0);
+
+ /* High memory pressure w/ multiple cgroups */
+ assert_se(hashmap_put(h1, "/derp.slice", &ctx[1]) >= 0);
+ assert_se(oomd_pressure_above(h1, 0 /* duration */, &t3) == 1);
+ assert_se(set_contains(t3, &ctx[0]) == true);
+ assert_se(set_size(t3) == 1);
+ assert_se(c = hashmap_get(h1, "/herp.slice"));
+ assert_se(c->last_hit_mem_pressure_limit > 0);
+ assert_se(c = hashmap_get(h1, "/derp.slice"));
+ assert_se(c->last_hit_mem_pressure_limit == 0);
+}
+
+static void test_oomd_memory_reclaim(void) {
+ _cleanup_hashmap_free_ Hashmap *h1 = NULL;
+ char **paths = STRV_MAKE("/0.slice",
+ "/1.slice",
+ "/2.slice",
+ "/3.slice",
+ "/4.slice");
+
+ OomdCGroupContext ctx[5] = {
+ { .path = paths[0],
+ .last_pgscan = 100,
+ .pgscan = 100 },
+ { .path = paths[1],
+ .last_pgscan = 100,
+ .pgscan = 100 },
+ { .path = paths[2],
+ .last_pgscan = 77,
+ .pgscan = 33 },
+ { .path = paths[3],
+ .last_pgscan = UINT64_MAX,
+ .pgscan = 100 },
+ { .path = paths[4],
+ .last_pgscan = 100,
+ .pgscan = UINT64_MAX },
+ };
+
+ assert_se(h1 = hashmap_new(&string_hash_ops));
+ assert_se(hashmap_put(h1, paths[0], &ctx[0]) >= 0);
+ assert_se(hashmap_put(h1, paths[1], &ctx[1]) >= 0);
+ assert_se(oomd_memory_reclaim(h1) == false);
+
+ assert_se(hashmap_put(h1, paths[2], &ctx[2]) >= 0);
+ assert_se(oomd_memory_reclaim(h1) == false);
+
+ assert_se(hashmap_put(h1, paths[4], &ctx[4]) >= 0);
+ assert_se(oomd_memory_reclaim(h1) == true);
+
+ assert_se(hashmap_put(h1, paths[3], &ctx[3]) >= 0);
+ assert_se(oomd_memory_reclaim(h1) == false);
+}
+
+static void test_oomd_swap_free_below(void) {
+ OomdSystemContext ctx = (OomdSystemContext) {
+ .swap_total = 20971512 * 1024U,
+ .swap_used = 20971440 * 1024U,
+ };
+ assert_se(oomd_swap_free_below(&ctx, 20) == true);
+
+ ctx = (OomdSystemContext) {
+ .swap_total = 20971512 * 1024U,
+ .swap_used = 3310136 * 1024U,
+ };
+ assert_se(oomd_swap_free_below(&ctx, 20) == false);
+}
+
+static void test_oomd_sort_cgroups(void) {
+ _cleanup_hashmap_free_ Hashmap *h = NULL;
+ _cleanup_free_ OomdCGroupContext **sorted_cgroups;
+ char **paths = STRV_MAKE("/herp.slice",
+ "/herp.slice/derp.scope",
+ "/herp.slice/derp.scope/sheep.service",
+ "/zupa.slice");
+
+ OomdCGroupContext ctx[4] = {
+ { .path = paths[0],
+ .swap_usage = 20,
+ .pgscan = 60 },
+ { .path = paths[1],
+ .swap_usage = 60,
+ .pgscan = 40 },
+ { .path = paths[2],
+ .swap_usage = 40,
+ .pgscan = 20 },
+ { .path = paths[3],
+ .swap_usage = 10,
+ .pgscan = 80 },
+ };
+
+ assert_se(h = hashmap_new(&string_hash_ops));
+
+ assert_se(hashmap_put(h, "/herp.slice", &ctx[0]) >= 0);
+ 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(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 4);
+ 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]);
+ sorted_cgroups = mfree(sorted_cgroups);
+
+ assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, NULL, &sorted_cgroups) == 4);
+ 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]);
+ 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(sorted_cgroups[2] == 0);
+ assert_se(sorted_cgroups[3] == 0);
+ sorted_cgroups = mfree(sorted_cgroups);
+}
+
+int main(void) {
+ int r;
+
+ test_setup_logging(LOG_DEBUG);
+
+ test_oomd_system_context_acquire();
+ test_oomd_pressure_above();
+ test_oomd_memory_reclaim();
+ test_oomd_swap_free_below();
+ test_oomd_sort_cgroups();
+
+ /* The following tests operate on live cgroups */
+
+ r = enter_cgroup_root(NULL);
+ if (r < 0)
+ return log_tests_skipped_errno(r, "failed to enter a test cgroup scope");
+
+ test_oomd_cgroup_kill();
+ test_oomd_cgroup_context_acquire_and_insert();
+
+ return 0;
+}
else if (fd < 0)
return log_error_errno(fd, "Failed to determine machine ID of image: %m");
else {
- r = id128_read_fd(fd, ID128_PLAIN, &context->seed);
+ r = id128_read_fd(fd, ID128_PLAIN_OR_UNINIT, &context->seed);
if (r == -ENOMEDIUM)
log_info("No machine ID set, using randomized partition UUIDs.");
else if (r < 0)
repart=$1
test -x $repart
-D=$(mktemp --directory)
+D=$(mktemp --tmpdir --directory "test-repart.XXXXXXXXXX")
trap "rm -rf '$D'" EXIT INT QUIT PIPE
mkdir -p $D/definitions
if (isempty(name) && fd < 0)
break;
- if (isempty(name) || fd < 0) {
- log_debug("Invalid item sent from child.");
- return -EINVAL;
- }
+ if (isempty(name) || fd < 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid item sent from child.");
add = portable_metadata_new(name, fd);
if (!add)
r = bus_connect_transport(arg_transport, arg_host, false, bus);
if (r < 0)
- return log_error_errno(r, "Failed to connect to bus: %m");
+ return bus_log_connect_error(r);
(void) sd_bus_set_allow_interactive_authorization(*bus, arg_ask_password);
systemd_resolved_sources += [resolved_gperf_c, resolved_dnssd_gperf_c]
-systemd_resolved_dependencies = [threads, libgpg_error, libm, libidn]
+systemd_resolved_dependencies = [threads, libgpg_error, libm]
if conf.get('ENABLE_DNS_OVER_TLS') == 1
if conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1
systemd_resolved_sources += files('resolved-dnstls-gnutls.c',
nameserver 127.0.0.53
options edns0 trust-ad
+search .
#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
+#include "utf8.h"
#include "verbs.h"
static int arg_family = AF_UNSPEC;
(int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
canonical);
- if (c == 0) {
- log_error("%s: no addresses found", name);
- return -ESRCH;
- }
+ if (c == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
+ "%s: no addresses found", name);
print_source(flags, ts);
if (r < 0)
return bus_log_parse_error(r);
- if (c == 0) {
- log_error("%s: no names found", pretty);
- return -ESRCH;
- }
+ if (c == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
+ "%s: no names found", pretty);
print_source(flags, ts);
if (r < 0)
return r;
+ strv_sort(*l);
+
return 0;
}
static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) {
+ const unsigned indent = strlen("Global: "); /* Use the same indentation everywhere to make things nice */
+ int pos1, pos2;
+
+ if (ifname)
+ printf("%s%nLink %i (%s)%n%s:", ansi_highlight(), &pos1, ifindex, ifname, &pos2, ansi_normal());
+ else
+ printf("%s%nGlobal%n%s:", ansi_highlight(), &pos1, &pos2, ansi_normal());
+
+ size_t cols = columns(), position = pos2 - pos1 + 2;
char **i;
- printf("%sLink %i (%s)%s:",
- ansi_highlight(), ifindex, ifname, ansi_normal());
+ STRV_FOREACH(i, p) {
+ size_t our_len = utf8_console_width(*i); /* This returns -1 on invalid utf-8 (which shouldn't happen).
+ * If that happens, we'll just print one item per line. */
- STRV_FOREACH(i, p)
- printf(" %s", *i);
+ if (position <= indent || size_add(size_add(position, 1), our_len) < cols) {
+ printf(" %s", *i);
+ position = size_add(size_add(position, 1), our_len);
+ } else {
+ printf("\n%*s%s", indent, "", *i);
+ position = size_add(our_len, indent);
+ }
+ }
printf("\n");
return 0;
}
-struct link_info {
+static int status_print_strv_global(char **p) {
+ return status_print_strv_ifindex(0, NULL, p);
+}
+
+typedef struct LinkInfo {
uint64_t scopes_mask;
const char *llmnr;
const char *mdns;
char **ntas;
bool dnssec_supported;
bool default_route;
-};
+} LinkInfo;
-static void link_info_clear(struct link_info *p) {
+typedef struct GlobalInfo {
+ char *current_dns;
+ char *current_dns_ex;
+ char **dns;
+ char **dns_ex;
+ char **fallback_dns;
+ char **fallback_dns_ex;
+ char **domains;
+ char **ntas;
+ const char *llmnr;
+ const char *mdns;
+ const char *dns_over_tls;
+ const char *dnssec;
+ const char *resolv_conf_mode;
+ bool dnssec_supported;
+} GlobalInfo;
+
+static void link_info_clear(LinkInfo *p) {
free(p->current_dns);
free(p->current_dns_ex);
strv_free(p->dns);
strv_free(p->ntas);
}
+static void global_info_clear(GlobalInfo *p) {
+ free(p->current_dns);
+ free(p->current_dns_ex);
+ strv_free(p->dns);
+ strv_free(p->dns_ex);
+ strv_free(p->fallback_dns);
+ strv_free(p->fallback_dns_ex);
+ strv_free(p->domains);
+ strv_free(p->ntas);
+}
+
static int dump_list(Table *table, const char *prefix, char * const *l) {
int r;
r = table_add_many(table,
TABLE_STRING, prefix,
- TABLE_STRV, l);
+ TABLE_STRV_WRAPPED, l);
if (r < 0)
return table_log_add_error(r);
return 0;
}
+static int strv_extend_extended_bool(char ***strv, const char *name, const char *value) {
+ int r;
+
+ if (value) {
+ r = parse_boolean(value);
+ if (r >= 0)
+ return strv_extendf(strv, "%s%s", plus_minus(r), name);
+ }
+
+ return strv_extendf(strv, "%s=%s", name, value ?: "???");
+}
+
+static char** link_protocol_status(const LinkInfo *info) {
+ _cleanup_strv_free_ char **s = NULL;
+
+ if (strv_extendf(&s, "%sDefaultRoute", plus_minus(info->default_route)) < 0)
+ return NULL;
+
+ if (strv_extend_extended_bool(&s, "LLMNR", info->llmnr) < 0)
+ return NULL;
+
+ if (strv_extend_extended_bool(&s, "mDNS", info->mdns) < 0)
+ return NULL;
+
+ if (strv_extend_extended_bool(&s, "DNSOverTLS", info->dns_over_tls) < 0)
+ return NULL;
+
+ if (strv_extendf(&s, "DNSSEC=%s/%s",
+ info->dnssec ?: "???",
+ info->dnssec_supported ? "supported" : "unsupported") < 0)
+ return NULL;
+
+ return TAKE_PTR(s);
+}
+
+static char** global_protocol_status(const GlobalInfo *info) {
+ _cleanup_strv_free_ char **s = NULL;
+
+ if (strv_extend_extended_bool(&s, "LLMNR", info->llmnr) < 0)
+ return NULL;
+
+ if (strv_extend_extended_bool(&s, "mDNS", info->mdns) < 0)
+ return NULL;
+
+ if (strv_extend_extended_bool(&s, "DNSOverTLS", info->dns_over_tls) < 0)
+ return NULL;
+
+ if (strv_extendf(&s, "DNSSEC=%s/%s",
+ info->dnssec ?: "???",
+ info->dnssec_supported ? "supported" : "unsupported") < 0)
+ return NULL;
+
+ return TAKE_PTR(s);
+}
+
static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) {
static const struct bus_properties_map property_map[] = {
- { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
- { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) },
- { "DNSEx", "a(iayqs)", map_link_dns_servers_ex, offsetof(struct link_info, dns_ex) },
- { "CurrentDNSServer", "(iay)", map_link_current_dns_server, offsetof(struct link_info, current_dns) },
- { "CurrentDNSServerEx", "(iayqs)", map_link_current_dns_server_ex, offsetof(struct link_info, current_dns_ex) },
- { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) },
- { "DefaultRoute", "b", NULL, offsetof(struct link_info, default_route) },
- { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) },
- { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) },
- { "DNSOverTLS", "s", NULL, offsetof(struct link_info, dns_over_tls) },
- { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) },
- { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) },
- { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) },
+ { "ScopesMask", "t", NULL, offsetof(LinkInfo, scopes_mask) },
+ { "DNS", "a(iay)", map_link_dns_servers, offsetof(LinkInfo, dns) },
+ { "DNSEx", "a(iayqs)", map_link_dns_servers_ex, offsetof(LinkInfo, dns_ex) },
+ { "CurrentDNSServer", "(iay)", map_link_current_dns_server, offsetof(LinkInfo, current_dns) },
+ { "CurrentDNSServerEx", "(iayqs)", map_link_current_dns_server_ex, offsetof(LinkInfo, current_dns_ex) },
+ { "Domains", "a(sb)", map_link_domains, offsetof(LinkInfo, domains) },
+ { "DefaultRoute", "b", NULL, offsetof(LinkInfo, default_route) },
+ { "LLMNR", "s", NULL, offsetof(LinkInfo, llmnr) },
+ { "MulticastDNS", "s", NULL, offsetof(LinkInfo, mdns) },
+ { "DNSOverTLS", "s", NULL, offsetof(LinkInfo, dns_over_tls) },
+ { "DNSSEC", "s", NULL, offsetof(LinkInfo, dnssec) },
+ { "DNSSECNegativeTrustAnchors", "as", bus_map_strv_sort, offsetof(LinkInfo, ntas) },
+ { "DNSSECSupported", "b", NULL, offsetof(LinkInfo, dnssec_supported) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(link_info_clear) struct link_info link_info = {};
+ _cleanup_(link_info_clear) LinkInfo link_info = {};
_cleanup_(table_unrefp) Table *table = NULL;
_cleanup_free_ char *p = NULL;
char ifi[DECIMAL_STR_MAX(int)], ifname[IF_NAMESIZE + 1] = "";
if (r < 0)
return table_log_add_error(r);
+ _cleanup_strv_free_ char **pstatus = link_protocol_status(&link_info);
+ if (!pstatus)
+ return log_oom();
+
r = table_add_many(table,
- TABLE_STRING, "DefaultRoute setting:",
- TABLE_BOOLEAN, link_info.default_route,
- TABLE_STRING, "LLMNR setting:",
- TABLE_STRING, strna(link_info.llmnr),
- TABLE_STRING, "MulticastDNS setting:",
- TABLE_STRING, strna(link_info.mdns),
- TABLE_STRING, "DNSOverTLS setting:",
- TABLE_STRING, strna(link_info.dns_over_tls),
- TABLE_STRING, "DNSSEC setting:",
- TABLE_STRING, strna(link_info.dnssec),
- TABLE_STRING, "DNSSEC supported:",
- TABLE_BOOLEAN, link_info.dnssec_supported);
+ TABLE_STRING, "Protocols:",
+ TABLE_STRV_WRAPPED, pstatus);
if (r < 0)
return table_log_add_error(r);
if (r < 0)
return r;
- return 0;
-}
-
-static int status_print_strv_global(char **p) {
- char **i;
-
- printf("%sGlobal%s:", ansi_highlight(), ansi_normal());
-
- STRV_FOREACH(i, p)
- printf(" %s", *i);
-
- printf("\n");
+ strv_sort(*l);
return 0;
}
-struct global_info {
- char *current_dns;
- char *current_dns_ex;
- char **dns;
- char **dns_ex;
- char **fallback_dns;
- char **fallback_dns_ex;
- char **domains;
- char **ntas;
- const char *llmnr;
- const char *mdns;
- const char *dns_over_tls;
- const char *dnssec;
- bool dnssec_supported;
-};
-
-static void global_info_clear(struct global_info *p) {
- free(p->current_dns);
- free(p->current_dns_ex);
- strv_free(p->dns);
- strv_free(p->dns_ex);
- strv_free(p->fallback_dns);
- strv_free(p->fallback_dns_ex);
- strv_free(p->domains);
- strv_free(p->ntas);
-}
-
static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
static const struct bus_properties_map property_map[] = {
- { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
- { "DNSEx", "a(iiayqs)", map_global_dns_servers_ex, offsetof(struct global_info, dns_ex) },
- { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, fallback_dns) },
- { "FallbackDNSEx", "a(iiayqs)", map_global_dns_servers_ex, offsetof(struct global_info, fallback_dns_ex) },
- { "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(struct global_info, current_dns) },
- { "CurrentDNSServerEx", "(iiayqs)", map_global_current_dns_server_ex, offsetof(struct global_info, current_dns_ex) },
- { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
- { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
- { "LLMNR", "s", NULL, offsetof(struct global_info, llmnr) },
- { "MulticastDNS", "s", NULL, offsetof(struct global_info, mdns) },
- { "DNSOverTLS", "s", NULL, offsetof(struct global_info, dns_over_tls) },
- { "DNSSEC", "s", NULL, offsetof(struct global_info, dnssec) },
- { "DNSSECSupported", "b", NULL, offsetof(struct global_info, dnssec_supported) },
+ { "DNS", "a(iiay)", map_global_dns_servers, offsetof(GlobalInfo, dns) },
+ { "DNSEx", "a(iiayqs)", map_global_dns_servers_ex, offsetof(GlobalInfo, dns_ex) },
+ { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(GlobalInfo, fallback_dns) },
+ { "FallbackDNSEx", "a(iiayqs)", map_global_dns_servers_ex, offsetof(GlobalInfo, fallback_dns_ex) },
+ { "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(GlobalInfo, current_dns) },
+ { "CurrentDNSServerEx", "(iiayqs)", map_global_current_dns_server_ex, offsetof(GlobalInfo, current_dns_ex) },
+ { "Domains", "a(isb)", map_global_domains, offsetof(GlobalInfo, domains) },
+ { "DNSSECNegativeTrustAnchors", "as", bus_map_strv_sort, offsetof(GlobalInfo, ntas) },
+ { "LLMNR", "s", NULL, offsetof(GlobalInfo, llmnr) },
+ { "MulticastDNS", "s", NULL, offsetof(GlobalInfo, mdns) },
+ { "DNSOverTLS", "s", NULL, offsetof(GlobalInfo, dns_over_tls) },
+ { "DNSSEC", "s", NULL, offsetof(GlobalInfo, dnssec) },
+ { "DNSSECSupported", "b", NULL, offsetof(GlobalInfo, dnssec_supported) },
+ { "ResolvConfMode", "s", NULL, offsetof(GlobalInfo, resolv_conf_mode) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(global_info_clear) struct global_info global_info = {};
+ _cleanup_(global_info_clear) GlobalInfo global_info = {};
_cleanup_(table_unrefp) Table *table = NULL;
int r;
table_set_header(table, false);
+ _cleanup_strv_free_ char **pstatus = global_protocol_status(&global_info);
+ if (!pstatus)
+ return log_oom();
+
r = table_add_many(table,
- TABLE_STRING, "LLMNR setting:",
+ TABLE_STRING, "Protocols:",
TABLE_SET_ALIGN_PERCENT, 100,
- TABLE_STRING, strna(global_info.llmnr),
- TABLE_STRING, "MulticastDNS setting:",
- TABLE_STRING, strna(global_info.mdns),
- TABLE_STRING, "DNSOverTLS setting:",
- TABLE_STRING, strna(global_info.dns_over_tls),
- TABLE_STRING, "DNSSEC setting:",
- TABLE_STRING, strna(global_info.dnssec),
- TABLE_STRING, "DNSSEC supported:",
- TABLE_BOOLEAN, global_info.dnssec_supported);
+ TABLE_STRV_WRAPPED, pstatus);
if (r < 0)
return table_log_add_error(r);
+ if (global_info.resolv_conf_mode) {
+ r = table_add_many(table,
+ TABLE_STRING, "resolv.conf mode:",
+ TABLE_STRING, global_info.resolv_conf_mode);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
if (global_info.current_dns) {
r = table_add_many(table,
TABLE_STRING, "Current DNS Server:",
r = dns_name_is_valid(n);
if (r < 0)
return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
- if (r == 0) {
- log_error("Domain not valid: %s", n);
- return -EINVAL;
- }
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Domain not valid: %s",
+ n);
r = sd_bus_message_append(req, "(sb)", n, **p == '~');
if (r < 0)
r = dns_name_is_valid(*p);
if (r < 0)
return log_error_errno(r, "Failed to validate specified domain %s: %m", *p);
- if (r == 0) {
- log_error("Domain not valid: %s", *p);
- return -EINVAL;
- }
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Domain not valid: %s",
+ *p);
}
r = call_nta(bus, clear ? NULL : argv + 2, bus_resolve_mgr, &error);
#include "resolved-dnssd-bus.h"
#include "resolved-dnssd.h"
#include "resolved-link-bus.h"
+#include "resolved-resolv-conf.h"
#include "socket-netlink.h"
#include "stdio-util.h"
#include "strv.h"
dns_query_free(q);
}
-static int validate_and_mangle_ifindex_and_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
+static int validate_and_mangle_flags(
+ const char *name,
+ uint64_t *flags,
+ uint64_t ok,
+ sd_bus_error *error) {
+
assert(flags);
/* Checks that the client supplied interface index and flags parameter actually are valid and make
* to mean "all supported protocols".
*/
- if (ifindex < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
-
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
*flags |= SD_RESOLVED_PROTOCOLS_ALL;
+ /* Imply SD_RESOLVED_NO_SEARCH if permitted and name is dot suffixed. */
+ if (name && FLAGS_SET(ok, SD_RESOLVED_NO_SEARCH) && dns_name_dot_suffixed(name) > 0)
+ *flags |= SD_RESOLVED_NO_SEARCH;
+
return 0;
}
if (r < 0)
return r;
+ if (ifindex < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
- r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
+ r = validate_and_mangle_flags(hostname, &flags, SD_RESOLVED_NO_SEARCH, error);
if (r < 0)
return r;
if (r < 0)
return r;
- r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, 0, error);
+ if (ifindex < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
+ r = validate_and_mangle_flags(NULL, &flags, 0, error);
if (r < 0)
return r;
if (r < 0)
return r;
+ if (ifindex < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
r = dns_name_is_valid(name);
if (r < 0)
return r;
if (dns_type_is_obsolete(type))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
- r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, 0, error);
+ r = validate_and_mangle_flags(name, &flags, 0, error);
if (r < 0)
return r;
if (r < 0)
return r;
+ if (ifindex < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
if (name && !type)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
- r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
+ r = validate_and_mangle_flags(name, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
if (r < 0)
return r;
static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string);
+static int bus_property_get_resolv_conf_mode(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int r;
+
+ assert(reply);
+
+ r = resolv_conf_mode();
+ if (r < 0) {
+ log_warning_errno(r, "Failed to test /etc/resolv.conf mode, ignoring: %m");
+ return sd_bus_message_append(reply, "s", NULL);
+ }
+
+ return sd_bus_message_append(reply, "s", resolv_conf_mode_to_string(r));
+}
+
static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
DnsScope *s;
SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
+ SD_BUS_PROPERTY("ResolvConfMode", "s", bus_property_get_resolv_conf_mode, 0, 0),
SD_BUS_METHOD_WITH_ARGS("ResolveHostname",
SD_BUS_ARGS("i", ifindex, "s", name, "i", family, "t", flags),
}
/* Append the OPT pseudo-RR described in RFC6891 */
-int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, int rcode, size_t *start) {
+int dns_packet_append_opt(
+ DnsPacket *p,
+ uint16_t max_udp_size,
+ bool edns0_do,
+ bool include_rfc6975,
+ int rcode,
+ size_t *start) {
+
size_t saved_size;
int r;
goto fail;
/* RDLENGTH */
- if (edns0_do && !DNS_PACKET_QR(p)) {
- /* If DO is on and this is not a reply, also append RFC6975 Algorithm data */
+ if (edns0_do && include_rfc6975) {
+ /* If DO is on and this is requested, also append RFC6975 Algorithm data. This is supposed to
+ * be done on queries, not on replies, hencer callers should turn this off when finishing off
+ * replies. */
static const uint8_t rfc6975[] = {
n += r;
continue;
- } else if (allow_compression && (c & 0xc0) == 0xc0) {
+ } else if (allow_compression && FLAGS_SET(c, 0xc0)) {
uint16_t ptr;
/* Pointer */
if (DNS_PACKET_QR(p)) {
/* Additional checks for responses */
- if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr)) {
+ if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr))
/* If this is a reply and we don't know the EDNS version
* then something is weird... */
- log_debug("EDNS version newer that our request, bad server.");
- return -EBADMSG;
- }
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "EDNS version newer that our request, bad server.");
if (has_rfc6975) {
/* If the OPT RR contains RFC6975 algorithm data, then this
int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start);
int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, const DnsAnswerFlags flags, size_t *start);
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, int rcode, size_t *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);
if (r == 0 && k == 0) /* No actual cname happened? */
return -ELOOP;
- if (q->answer_protocol == DNS_PROTOCOL_DNS) {
+ if (q->answer_protocol == DNS_PROTOCOL_DNS)
/* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
* cannot invade the local namespace. The opposite way we permit: local names may redirect to global
* ones. */
-
q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */
- }
/* Turn off searching for the new name */
q->flags |= SD_RESOLVED_NO_SEARCH;
else
packet_size = server->received_udp_packet_max;
- return dns_packet_append_opt(packet, packet_size, edns_do, 0, NULL);
+ return dns_packet_append_opt(packet, packet_size, edns_do, /* include_rfc6975 = */ true, 0, NULL);
}
int dns_server_ifindex(const DnsServer *s) {
assert(p);
if (add_opt) {
- r = dns_packet_append_opt(p, ADVERTISE_DATAGRAM_SIZE_MAX, edns0_do, rcode, NULL);
+ r = dns_packet_append_opt(p, ADVERTISE_DATAGRAM_SIZE_MAX, edns0_do, /* include_rfc6975 = */ false, rcode, NULL);
if (r == -EMSGSIZE) /* Hit the size limit? then indicate truncation */
tc = true;
else if (r < 0)
if (r < 0)
return r;
- if (!service->name_template) {
- log_error("%s doesn't define service instance name", service->name);
- return -EINVAL;
- }
-
- if (!service->type) {
- log_error("%s doesn't define service type", service->name);
- return -EINVAL;
- }
+ if (!service->name_template)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s doesn't define service instance name",
+ service->name);
+
+ if (!service->type)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s doesn't define service type",
+ service->name);
if (LIST_IS_EMPTY(service->txt_data_items)) {
txt_data = new0(DnssdTxtData, 1);
#include <sys/types.h>
#include <unistd.h>
-#if HAVE_LIBIDN2
-#include <idn2.h>
-#endif
-
#include "af-list.h"
#include "alloc-util.h"
#include "bus-polkit.h"
#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
+#include "idn-util.h"
#include "io-util.h"
#include "missing_network.h"
#include "netlink-util.h"
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Couldn't find a single label in hostname.");
+#if HAVE_LIBIDN || HAVE_LIBIDN2
+ r = dlopen_idn();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to initialize IDN support, ignoring: %m");
+ decoded = label; /* no decoding */
+ } else
+#endif
+ {
#if HAVE_LIBIDN2
- r = idn2_to_unicode_8z8z(label, &utf8, 0);
- if (r != IDN2_OK)
- return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "Failed to undo IDNA: %s", idn2_strerror(r));
- assert(utf8_is_valid(utf8));
-
- r = strlen(utf8);
- decoded = utf8;
+ r = sym_idn2_to_unicode_8z8z(label, &utf8, 0);
+ if (r != IDN2_OK)
+ return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Failed to undo IDNA: %s", sym_idn2_strerror(r));
+ assert(utf8_is_valid(utf8));
+
+ r = strlen(utf8);
+ decoded = utf8;
#elif HAVE_LIBIDN
- k = dns_label_undo_idna(label, r, label, sizeof label);
- if (k < 0)
- return log_error_errno(k, "Failed to undo IDNA: %m");
- if (k > 0)
- r = k;
-
- if (!utf8_is_valid(label))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "System hostname is not UTF-8 clean.");
- decoded = label;
+ k = dns_label_undo_idna(label, r, label, sizeof label);
+ if (k < 0)
+ return log_error_errno(k, "Failed to undo IDNA: %m");
+ if (k > 0)
+ r = k;
+
+ if (!utf8_is_valid(label))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "System hostname is not UTF-8 clean.");
+ decoded = label;
#else
- decoded = label; /* no decoding */
+ decoded = label; /* no decoding */
#endif
+ }
r = dns_label_escape_new(decoded, r, &n);
if (r < 0)
l = recvmsg_safe(fd, &mh, 0);
if (IN_SET(l, -EAGAIN, -EINTR))
return 0;
- if (l < 0)
+ if (l <= 0)
return l;
- if (l == 0)
- return 0;
assert(!(mh.msg_flags & MSG_TRUNC));
#include "resolved-dns-server.h"
#include "resolved-resolv-conf.h"
#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "tmpfile-util-label.h"
write_resolv_conf_server(s, f, &count);
}
- if (!ordered_set_isempty(domains))
+ if (ordered_set_isempty(domains))
+ fputs("search .\n", f); /* Make sure that if the local hostname is chosen as fqdn this does not
+ * imply a search domain */
+ else
write_resolv_conf_search(domains, f);
return fflush_and_check(f);
"nameserver 127.0.0.53\n"
"options edns0 trust-ad\n", f);
- if (!ordered_set_isempty(domains))
+ if (ordered_set_isempty(domains))
+ fputs("search .\n", f); /* Make sure that if the local hostname is chosen as fqdn this does not
+ * imply a search domain */
+ else
write_resolv_conf_search(domains, f);
return fflush_and_check(f);
return r;
}
+
+int resolv_conf_mode(void) {
+ static const char * const table[_RESOLV_CONF_MODE_MAX] = {
+ [RESOLV_CONF_UPLINK] = PRIVATE_UPLINK_RESOLV_CONF,
+ [RESOLV_CONF_STUB] = PRIVATE_STUB_RESOLV_CONF,
+ [RESOLV_CONF_STATIC] = PRIVATE_STATIC_RESOLV_CONF,
+ };
+
+ struct stat system_st;
+
+ if (stat("/etc/resolv.conf", &system_st) < 0) {
+ if (errno == ENOENT)
+ return RESOLV_CONF_MISSING;
+
+ return -errno;
+ }
+
+ for (ResolvConfMode m = 0; m < _RESOLV_CONF_MODE_MAX; m++) {
+ struct stat our_st;
+
+ if (!table[m])
+ continue;
+
+ if (stat(table[m], &our_st) < 0) {
+ if (errno != ENOENT)
+ log_debug_errno(errno, "Failed to stat() %s, ignoring: %m", table[m]);
+
+ continue;
+ }
+
+ if (system_st.st_dev == our_st.st_dev &&
+ system_st.st_ino == our_st.st_ino)
+ return m;
+ }
+
+ return RESOLV_CONF_FOREIGN;
+}
+
+static const char* const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = {
+ [RESOLV_CONF_UPLINK] = "uplink",
+ [RESOLV_CONF_STUB] = "stub",
+ [RESOLV_CONF_STATIC] = "static",
+ [RESOLV_CONF_MISSING] = "missing",
+ [RESOLV_CONF_FOREIGN] = "foreign",
+};
+DEFINE_STRING_TABLE_LOOKUP(resolv_conf_mode, ResolvConfMode);
int manager_check_resolv_conf(const Manager *m);
int manager_read_resolv_conf(Manager *m);
int manager_write_resolv_conf(Manager *m);
+
+typedef enum ResolvConfMode {
+ RESOLV_CONF_UPLINK,
+ RESOLV_CONF_STUB,
+ RESOLV_CONF_STATIC,
+ RESOLV_CONF_FOREIGN,
+ RESOLV_CONF_MISSING,
+ _RESOLV_CONF_MODE_MAX,
+ _RESOLV_CONF_MODE_INVALID = -1,
+} ResolvConfMode;
+
+int resolv_conf_mode(void);
+
+const char* resolv_conf_mode_to_string(ResolvConfMode m) _const_;
+ResolvConfMode resolv_conf_mode_from_string(const char *s) _pure_;
dns_query_complete(q, DNS_TRANSACTION_ABORTED);
}
-static bool validate_and_mangle_flags(uint64_t *flags, uint64_t ok) {
+static bool validate_and_mangle_flags(
+ const char *name,
+ uint64_t *flags,
+ uint64_t ok) {
+
assert(flags);
/* This checks that the specified client-provided flags parameter actually makes sense, and mangles
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
*flags |= SD_RESOLVED_PROTOCOLS_ALL;
+ /* If the SD_RESOLVED_NO_SEARCH flag is acceptable, and the query name is dot-suffixed, turn off
+ * search domains. Note that DNS name normalization drops the dot suffix, hence we propagate this
+ * into the flags field as early as we can. */
+ if (name && FLAGS_SET(ok, SD_RESOLVED_NO_SEARCH) && dns_name_dot_suffixed(name) > 0)
+ *flags |= SD_RESOLVED_NO_SEARCH;
+
return true;
}
if (!IN_SET(p.family, AF_UNSPEC, AF_INET, AF_INET6))
return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family"));
- if (!validate_and_mangle_flags(&p.flags, SD_RESOLVED_NO_SEARCH))
+ if (!validate_and_mangle_flags(p.name, &p.flags, SD_RESOLVED_NO_SEARCH))
return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
r = parse_as_address(link, &p);
if (FAMILY_ADDRESS_SIZE(p.family) != p.address_size)
return varlink_error(link, "io.systemd.UserDatabase.BadAddressSize", NULL);
- if (!validate_and_mangle_flags(&p.flags, 0))
+ if (!validate_and_mangle_flags(NULL, &p.flags, 0))
return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
r = dns_question_new_reverse(&question, p.family, &p.address);
# See resolved.conf(5) for details
[Resolve]
+# Some examples of DNS servers which may be used for DNS= and FallbackDNS=:
+# Cloudflare: 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001
+# Google: 8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
+# Quad9: 9.9.9.9 2620:fe::fe
#DNS=
#FallbackDNS=@DNS_SERVERS@
#Domains=
#LLMNR=@DEFAULT_LLMNR_MODE@
#Cache=yes
#DNSStubListener=yes
+#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no
arg_aggressive_gc = true;
}
- if (arg_stdio == ARG_STDIO_AUTO) {
+ if (arg_stdio == ARG_STDIO_AUTO)
/* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
* to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
* pipeline, but we are neatly interactive with tty-level isolation otherwise. */
arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
ARG_STDIO_PTY :
ARG_STDIO_DIRECT;
- }
if (argc > optind) {
char **l;
if (c.cpu_usage_nsec != NSEC_INFINITY) {
char ts[FORMAT_TIMESPAN_MAX];
log_info("CPU time consumed: %s",
- format_timespan(ts, sizeof ts, (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC));
+ format_timespan(ts, sizeof ts, DIV_ROUND_UP(c.cpu_usage_nsec, NSEC_PER_USEC), USEC_PER_MSEC));
}
if (c.ip_ingress_bytes != UINT64_MAX) {
return log_oom();
if (!efi_loader_entry_name_valid(tmp.id))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id);
tmp.path = strdup(path);
if (!tmp.path)
return log_oom();
if (!efi_loader_entry_name_valid(tmp.id))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id);
tmp.path = strdup(path);
if (!tmp.path)
else if (r != 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe file system \"%s\": %m", node);
- errno = 0;
r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
if (r != 0)
- return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe file system type of \"%s\": %m", node);
+ return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+ SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+ "No filesystem found on \"%s\": %m", node);
if (!streq(v, "vfat"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" is not FAT.", node);
- errno = 0;
r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
if (r != 0)
- return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition scheme of \"%s\": %m", node);
+ return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+ SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+ "File system \"%s\" is not located on a partitioned block device.", node);
if (!streq(v, "gpt"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
#include "bus-get-properties.h"
#include "rlimit-util.h"
+#include "stdio-util.h"
#include "string-util.h"
int bus_property_get_bool(
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)
return 0;
}
+int bus_map_strv_sort(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ _cleanup_strv_free_ char **l = NULL;
+ char ***p = userdata;
+ int r;
+
+ r = bus_message_read_strv_extend(m, &l);
+ if (r < 0)
+ return r;
+
+ r = strv_extend_strv(p, l, false);
+ if (r < 0)
+ return r;
+
+ strv_sort(*p);
+ return 0;
+}
+
static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
char type;
int r;
};
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
+int bus_map_strv_sort(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata);
int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map,
static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
int r;
- if (STR_IN_SET(field, "DevicePolicy", "Slice"))
+ if (STR_IN_SET(field, "DevicePolicy",
+ "Slice",
+ "ManagedOOMSwap",
+ "ManagedOOMMemoryPressure",
+ "ManagedOOMMemoryPressureLimitPercent"))
return bus_append_string(m, field, eq);
if (STR_IN_SET(field, "CPUAccounting",
return 0;
}
+
+int unit_info_compare(const UnitInfo *a, const UnitInfo *b) {
+ int r;
+
+ /* First, order by machine */
+ r = strcasecmp_ptr(a->machine, b->machine);
+ if (r != 0)
+ return r;
+
+ /* Second, order by unit type */
+ r = strcasecmp_ptr(strrchr(a->id, '.'), strrchr(b->id, '.'));
+ if (r != 0)
+ return r;
+
+ /* Third, order by name */
+ return strcasecmp(a->id, b->id);
+}
int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes);
int unit_load_state(sd_bus *bus, const char *name, char **load_state);
+
+int unit_info_compare(const UnitInfo *a, const UnitInfo *b);
if (user)
r = sd_bus_default_user(&bus);
else {
- if (sd_booted() <= 0) {
+ if (sd_booted() <= 0)
/* Print a friendly message when the local system is actually not running systemd as PID 1. */
- log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
-
- return -EHOSTDOWN;
- }
+ return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
+ "System has not been booted with systemd as init system (PID 1). Can't operate.");
r = sd_bus_default_system(&bus);
}
break;
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
-#define bus_log_connect_error(r) \
- log_error_errno(r, "Failed to create bus connection: %m")
-
-#define bus_log_parse_error(r) \
+#define bus_log_address_error(r) \
+ log_error_errno(r, \
+ r == -ENOMEDIUM ? "Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
+ "Failed to set bus address: %m")
+#define bus_log_connect_error(r) \
+ log_error_errno(r, \
+ r == -ENOMEDIUM ? "Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
+ "Failed to connect to bus: %m")
+
+#define bus_log_parse_error(r) \
log_error_errno(r, "Failed to parse bus message: %m")
-#define bus_log_create_error(r) \
+#define bus_log_create_error(r) \
log_error_errno(r, "Failed to create bus message: %m")
int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path);
if (c->utc)
fputs(" UTC", f);
- else if (c->timezone != NULL) {
+ else if (c->timezone) {
fputc(' ', f);
fputs(c->timezone, f);
} else if (IN_SET(c->dst, 0, 1)) {
if (fd < 0)
return -errno;
- if (!uid_is_valid(uid) && !gid_is_valid(gid) && (mask & 07777) == 07777)
+ if (!uid_is_valid(uid) && !gid_is_valid(gid) && FLAGS_SET(mask, 07777))
return 0; /* nothing to do */
if (fstat(fd, &st) < 0)
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- if (!uid_is_valid(uid) && !gid_is_valid(gid) && (mask & 07777) == 07777)
+ if (!uid_is_valid(uid) && !gid_is_valid(gid) && FLAGS_SET(mask, 07777))
return 0; /* nothing to do */
/* Shortcut, as above */
return ret;
}
-static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid, bool rm) {
+static int clean_posix_shm_internal(const char *dirname, DIR *dir, uid_t uid, gid_t gid, bool rm) {
struct dirent *de;
int ret = 0, r;
if (errno == ENOENT)
continue;
- ret = log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name);
+ ret = log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s/%s: %m",
+ dirname, de->d_name);
continue;
}
kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME);
if (!kid) {
if (errno != ENOENT)
- ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name);
+ ret = log_warning_errno(errno, "Failed to enter shared memory directory %s/%s: %m",
+ dirname, de->d_name);
} else {
- r = clean_posix_shm_internal(kid, uid, gid, rm);
+ r = clean_posix_shm_internal(de->d_name, kid, uid, gid, rm);
if (r < 0)
ret = r;
}
if (errno == ENOENT)
continue;
- ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name);
+ ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s/%s: %m",
+ dirname, de->d_name);
} else {
log_debug("Removed POSIX shared memory directory %s", de->d_name);
if (ret == 0)
return log_warning_errno(errno, "Failed to open /dev/shm: %m");
}
- return clean_posix_shm_internal(dir, uid, gid, rm);
+ return clean_posix_shm_internal("/dev/shm", dir, uid, gid, rm);
}
static int clean_posix_mq(uid_t uid, gid_t gid, bool rm) {
if (stat(EPOCH_FILE, &st) < 0) {
if (errno != ENOENT)
- log_warning_errno(errno, "Cannot stat %s: %m\n", EPOCH_FILE);
+ log_warning_errno(errno, "Cannot stat " EPOCH_FILE ": %m");
- epoch_usec = ((usec_t) TIME_EPOCH * USEC_PER_SEC);
+ epoch_usec = (usec_t) TIME_EPOCH * USEC_PER_SEC;
} else
epoch_usec = timespec_load(&st.st_mtim);
#include "string-table.h"
#include "string-util.h"
#include "tomoyo-util.h"
+#include "user-record.h"
#include "user-util.h"
#include "util.h"
#include "virt.h"
return 0;
}
+
+DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");
CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
CONFIG_PARSER_PROTOTYPE(config_parse_vlanprotocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_percent);
typedef enum Disabled {
DISABLED_CONFIGURATION,
/* This is intended to be used with _cleanup_ attribute. */
static inline void notify_on_cleanup(const char **p) {
- if (p)
+ if (*p)
(void) sd_notify(false, *p);
}
if (r < 0)
return r;
if (r == 0)
- return log_debug_errno(EPROTONOSUPPORT,
+ return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
"Device is a loop device and partition scanning is off!");
return -EINVAL; /* original error */
log_debug_errno(r, "Image contains invalid /etc/machine-id: %s", line);
} else if (r == 0)
log_debug("/etc/machine-id file is empty.");
+ else if (streq(line, "uninitialized"))
+ log_debug("/etc/machine-id file is uninitialized (likely aborted first boot).");
else
log_debug("/etc/machine-id has unexpected length %i.", r);
/* SPDX-License-Identifier: LGPL-2.1+ */
-#if HAVE_LIBIDN2
-# include <idn2.h>
-#elif HAVE_LIBIDN
-# include <idna.h>
-# include <stringprep.h>
-#endif
-
#include <endian.h>
#include <netinet/in.h>
#include <stdio.h>
#include "hashmap.h"
#include "hexdecoct.h"
#include "hostname-util.h"
+#include "idn-util.h"
#include "in-addr-util.h"
#include "macro.h"
#include "parse-util.h"
/* Trailing dash */
return -EINVAL;
- if (*n == '.')
+ if (n[0] == '.' && (n[1] != 0 || !FLAGS_SET(flags, DNS_LABEL_LEAVE_TRAILING_DOT)))
n++;
+
break;
}
return -EINVAL;
/* More than one trailing dot? */
- if (*n == '.')
+ if (n[0] == '.' && !FLAGS_SET(flags, DNS_LABEL_LEAVE_TRAILING_DOT))
return -EINVAL;
if (sz >= 1 && d)
const char *p;
bool contains_8bit = false;
char buffer[DNS_LABEL_MAX+1];
+ int r;
assert(encoded);
assert(decoded);
/* Converts an U-label into an A-label */
+ r = dlopen_idn();
+ if (r < 0)
+ return r;
+
if (encoded_size <= 0)
return -EINVAL;
return 0;
}
- input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+ input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
- if (idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
+ if (sym_idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
return -EINVAL;
l = strlen(buffer);
_cleanup_free_ char *result = NULL;
uint32_t *output = NULL;
size_t w;
+ int r;
/* To be invoked after unescaping. Converts an A-label into an U-label. */
assert(encoded);
assert(decoded);
+ r = dlopen_idn();
+ if (r < 0)
+ return r;
+
if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
return -EINVAL;
if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
return 0;
- input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
+ input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
output_size = input_size;
output = newa(uint32_t, output_size);
- idna_to_unicode_44i(input, input_size, output, &output_size, 0);
+ sym_idna_to_unicode_44i(input, input_size, output, &output_size, 0);
- result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
+ result = sym_stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
if (!result)
return -ENOMEM;
if (w <= 0)
}
int dns_name_apply_idna(const char *name, char **ret) {
+
/* Return negative on error, 0 if not implemented, positive on success. */
-#if HAVE_LIBIDN2
+#if HAVE_LIBIDN2 || HAVE_LIBIDN2
int r;
+
+ r = dlopen_idn();
+ if (r == EOPNOTSUPP) {
+ *ret = NULL;
+ return 0;
+ }
+ if (r < 0)
+ return r;
+#endif
+
+#if HAVE_LIBIDN2
_cleanup_free_ char *t = NULL;
assert(name);
assert(ret);
- r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) &t,
- IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
+ r = sym_idn2_lookup_u8((uint8_t*) name, (uint8_t**) &t,
+ IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
log_debug("idn2_lookup_u8: %s → %s", name, t);
if (r == IDN2_OK) {
if (!startswith(name, "xn--")) {
_cleanup_free_ char *s = NULL;
- r = idn2_to_unicode_8z8z(t, &s, 0);
+ r = sym_idn2_to_unicode_8z8z(t, &s, 0);
if (r != IDN2_OK) {
log_debug("idn2_to_unicode_8z8z(\"%s\") failed: %d/%s",
- t, r, idn2_strerror(r));
+ t, r, sym_idn2_strerror(r));
return 0;
}
return 1; /* *ret has been written */
}
- log_debug("idn2_lookup_u8(\"%s\") failed: %d/%s", name, r, idn2_strerror(r));
+ log_debug("idn2_lookup_u8(\"%s\") failed: %d/%s", name, r, sym_idn2_strerror(r));
if (r == IDN2_2HYPHEN)
/* The name has two hyphens — forbidden by IDNA2008 in some cases */
return 0;
return 1;
#else
+ *ret = NULL;
return 0;
#endif
}
return dns_name_is_valid(name);
}
+
+int dns_name_dot_suffixed(const char *name) {
+ const char *p = name;
+ int r;
+
+ for (;;) {
+ if (streq(p, "."))
+ return true;
+
+ r = dns_label_unescape(&p, NULL, DNS_LABEL_MAX, DNS_LABEL_LEAVE_TRAILING_DOT);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return false;
+ }
+}
#define DNS_N_LABELS_MAX 127
typedef enum DNSLabelFlags {
- DNS_LABEL_LDH = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */
- DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */
+ DNS_LABEL_LDH = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */
+ DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */
+ DNS_LABEL_LEAVE_TRAILING_DOT = 1 << 2, /* Leave trailing dot in place */
} DNSLabelFlags;
int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags);
int dns_name_apply_idna(const char *name, char **ret);
int dns_name_is_valid_or_address(const char *name);
+
+int dns_name_dot_suffixed(const char *name);
return 0;
}
-int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, netdev_ring_param *ring) {
+int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring) {
struct ethtool_ringparam ecmd = {
.cmd = ETHTOOL_GRINGPARAM
};
return found ? 0 : -ENODATA;
}
-int ethtool_set_features(int *ethtool_fd, const char *ifname, int *features) {
+int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features) {
_cleanup_free_ struct ethtool_gstrings *strings = NULL;
struct ethtool_sfeatures *sfeatures;
struct ifreq ifr = {};
int *fd,
const char *ifname,
int autonegotiation,
- uint32_t advertise[static N_ADVERTISE],
+ const uint32_t advertise[static N_ADVERTISE],
uint64_t speed,
Duplex duplex,
NetDevPort port) {
return r;
}
-int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) {
+int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *channels) {
struct ethtool_channels ecmd = {
.cmd = ETHTOOL_GCHANNELS
};
int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct ether_addr *ret);
int ethtool_set_speed(int *ethtool_fd, const char *ifname, unsigned speed, Duplex duplex);
int ethtool_set_wol(int *ethtool_fd, const char *ifname, WakeOnLan wol);
-int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, netdev_ring_param *ring);
-int ethtool_set_features(int *ethtool_fd, const char *ifname, int *features);
+int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring);
+int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features);
int ethtool_set_glinksettings(int *ethtool_fd, const char *ifname,
- int autonegotiation, uint32_t advertise[static N_ADVERTISE],
+ int autonegotiation, const uint32_t advertise[static N_ADVERTISE],
uint64_t speed, Duplex duplex, NetDevPort port);
-int ethtool_set_channels(int *ethtool_fd, const char *ifname, netdev_channels *channels);
+int ethtool_set_channels(int *ethtool_fd, const char *ifname, const netdev_channels *channels);
int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg);
const char *duplex_to_string(Duplex d) _const_;
size_t minimum_width; /* minimum width for the column */
size_t maximum_width; /* maximum width for the column */
+ size_t formatted_for_width; /* the width we tried to format for */
unsigned weight; /* the horizontal weight for this column, in case the table is expanded/compressed */
unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */
unsigned align_percent; /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */
Table *table_new_internal(const char *first_header, ...) {
_cleanup_(table_unrefp) Table *t = NULL;
size_t n_columns = 1;
- const char *h;
va_list ap;
int r;
va_start(ap, first_header);
for (;;) {
- h = va_arg(ap, const char*);
- if (!h)
+ if (!va_arg(ap, const char*))
break;
n_columns++;
return NULL;
va_start(ap, first_header);
- for (h = first_header; h; h = va_arg(ap, const char*)) {
+ for (const char *h = first_header; h; h = va_arg(ap, const char*)) {
TableCell *cell;
r = table_add_cell(t, &cell, TABLE_STRING, h);
free(d->formatted);
free(d->url);
- if (d->type == TABLE_STRV)
+ if (IN_SET(d->type, TABLE_STRV, TABLE_STRV_WRAPPED))
strv_free(d->strv);
return mfree(d);
DEFINE_TRIVIAL_CLEANUP_FUNC(TableData*, table_data_unref);
Table *table_unref(Table *t) {
- size_t i;
-
if (!t)
return NULL;
- for (i = 0; i < t->n_cells; i++)
+ for (size_t i = 0; i < t->n_cells; i++)
table_data_unref(t->data[i]);
free(t->data);
return strlen(data) + 1;
case TABLE_STRV:
+ case TABLE_STRV_WRAPPED:
return sizeof(char **);
case TABLE_BOOLEAN:
d->align_percent = align_percent;
d->ellipsize_percent = ellipsize_percent;
- if (type == TABLE_STRV) {
+ if (IN_SET(type, TABLE_STRV, TABLE_STRV_WRAPPED)) {
d->strv = strv_copy(data);
if (!d->strv)
return NULL;
break;
case TABLE_STRV:
+ case TABLE_STRV_WRAPPED:
data = va_arg(ap, char * const *);
break;
}
int table_set_display_all(Table *t) {
- size_t allocated;
-
assert(t);
- allocated = t->n_display_map;
+ size_t allocated = t->n_display_map;
if (!GREEDY_REALLOC(t->display_map, allocated, MAX(t->n_columns, allocated)))
return -ENOMEM;
}
int table_hide_column_from_display(Table *t, size_t column) {
- size_t allocated, cur = 0;
int r;
assert(t);
return r;
}
- allocated = t->n_display_map;
+ size_t allocated = t->n_display_map, cur = 0;
for (size_t i = 0; i < allocated; i++) {
if (t->display_map[i] == column)
return path_compare(a->string, b->string);
case TABLE_STRV:
+ case TABLE_STRV_WRAPPED:
return strv_compare(a->strv, b->strv);
case TABLE_BOOLEAN:
}
static int table_data_compare(const size_t *a, const size_t *b, Table *t) {
- size_t i;
int r;
assert(t);
return 1;
/* Order other lines by the sorting map */
- for (i = 0; i < t->n_sort_map; i++) {
+ for (size_t i = 0; i < t->n_sort_map; i++) {
TableData *d, *dd;
d = t->data[*a + t->sort_map[i]];
return CMP(*a, *b);
}
-static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercasing) {
+static char* format_strv_width(char **strv, size_t column_width) {
+ _cleanup_fclose_ FILE *f = NULL;
+ size_t sz = 0;
+ _cleanup_free_ char *buf = NULL;
+
+ f = open_memstream_unlocked(&buf, &sz);
+ if (!f)
+ return NULL;
+
+ size_t position = 0;
+ char **p;
+ STRV_FOREACH(p, strv) {
+ size_t our_len = utf8_console_width(*p); /* This returns -1 on invalid utf-8 (which shouldn't happen).
+ * If that happens, we'll just print one item per line. */
+
+ if (position == 0) {
+ fputs(*p, f);
+ position = our_len;
+ } else if (size_add(size_add(position, 1), our_len) <= column_width) {
+ fprintf(f, " %s", *p);
+ position = size_add(size_add(position, 1), our_len);
+ } else {
+ fprintf(f, "\n%s", *p);
+ position = our_len;
+ }
+ }
+
+ if (fflush_and_check(f) < 0)
+ return NULL;
+
+ f = safe_fclose(f);
+ return TAKE_PTR(buf);
+}
+
+static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercasing, size_t column_width, bool *have_soft) {
assert(d);
- if (d->formatted)
+ if (d->formatted &&
+ /* Only TABLE_STRV_WRAPPED adjust based on column_width so far… */
+ (d->type != TABLE_STRV_WRAPPED || d->formatted_for_width == column_width))
return d->formatted;
switch (d->type) {
case TABLE_STRING:
case TABLE_PATH:
if (d->uppercase && !avoid_uppercasing) {
- char *p, *q;
-
d->formatted = new(char, strlen(d->string) + 1);
if (!d->formatted)
return NULL;
- for (p = d->string, q = d->formatted; *p; p++, q++)
+ char *q = d->formatted;
+ for (char *p = d->string; *p; p++, q++)
*q = (char) toupper((unsigned char) *p);
*q = 0;
return d->string;
- case TABLE_STRV: {
- char *p;
+ case TABLE_STRV:
+ if (strv_isempty(d->strv))
+ return strempty(t->empty_string);
+
+ d->formatted = strv_join(d->strv, "\n");
+ if (!d->formatted)
+ return NULL;
+ break;
+ case TABLE_STRV_WRAPPED: {
if (strv_isempty(d->strv))
return strempty(t->empty_string);
- p = strv_join(d->strv, "\n");
- if (!p)
+ char *buf = format_strv_width(d->strv, column_width);
+ if (!buf)
return NULL;
- d->formatted = p;
+ free_and_replace(d->formatted, buf);
+ d->formatted_for_width = column_width;
+ if (have_soft)
+ *have_soft = true;
+
break;
}
static int table_data_requested_width_height(
Table *table,
TableData *d,
+ size_t available_width,
size_t *ret_width,
- size_t *ret_height) {
+ size_t *ret_height,
+ bool *have_soft) {
_cleanup_free_ char *truncated = NULL;
bool truncation_applied = false;
size_t width, height;
const char *t;
int r;
+ bool soft = false;
- t = table_data_format(table, d, false);
+ t = table_data_format(table, d, false, available_width, &soft);
if (!t)
return -ENOMEM;
*ret_width = width;
if (ret_height)
*ret_height = height;
+ if (have_soft && soft)
+ *have_soft = true;
return truncation_applied;
}
_cleanup_free_ char *clickable = NULL;
const char *p;
char *ret;
- size_t i;
int r;
/* As with ellipsize_mem(), 'old_length' is a byte size while 'new_length' is a width in character cells */
if (!ret)
return NULL;
- for (i = 0; i < lspace; i++)
+ for (size_t i = 0; i < lspace; i++)
ret[i] = ' ';
memcpy(ret + lspace, clickable ?: str, clickable_length);
- for (i = lspace + clickable_length; i < space + clickable_length; i++)
+ for (size_t i = lspace + clickable_length; i < space + clickable_length; i++)
ret[i] = ' ';
ret[space + clickable_length] = 0;
return true;
/* Let's also consider an empty strv as truly empty. */
- if (d->type == TABLE_STRV)
+ if (IN_SET(d->type, TABLE_STRV, TABLE_STRV_WRAPPED))
return strv_isempty(d->strv);
/* Note that an empty string we do not consider empty here! */
int table_print(Table *t, FILE *f) {
size_t n_rows, *minimum_width, *maximum_width, display_columns, *requested_width,
- i, j, table_minimum_width, table_maximum_width, table_requested_width, table_effective_width,
- *width;
+ table_minimum_width, table_maximum_width, table_requested_width, table_effective_width,
+ *width = NULL;
_cleanup_free_ size_t *sorted = NULL;
uint64_t *column_weight, weight_sum;
int r;
if (!sorted)
return -ENOMEM;
- for (i = 0; i < n_rows; i++)
+ for (size_t i = 0; i < n_rows; i++)
sorted[i] = i * t->n_columns;
typesafe_qsort_r(sorted, n_rows, table_data_compare, t);
minimum_width = newa(size_t, display_columns);
maximum_width = newa(size_t, display_columns);
requested_width = newa(size_t, display_columns);
- width = newa(size_t, display_columns);
column_weight = newa0(uint64_t, display_columns);
- for (j = 0; j < display_columns; j++) {
+ for (size_t j = 0; j < display_columns; j++) {
minimum_width[j] = 1;
maximum_width[j] = (size_t) -1;
- requested_width[j] = (size_t) -1;
}
- /* First pass: determine column sizes */
- for (i = t->header ? 0 : 1; i < n_rows; i++) {
- TableData **row;
+ for (unsigned pass = 0; pass < 2; pass++) {
+ /* First pass: determine column sizes */
- /* Note that we don't care about ordering at this time, as we just want to determine column sizes,
- * hence we don't care for sorted[] during the first pass. */
- row = t->data + i * t->n_columns;
+ for (size_t j = 0; j < display_columns; j++)
+ requested_width[j] = (size_t) -1;
- for (j = 0; j < display_columns; j++) {
- TableData *d;
- size_t req_width, req_height;
+ bool any_soft = false;
- assert_se(d = row[t->display_map ? t->display_map[j] : j]);
+ for (size_t i = t->header ? 0 : 1; i < n_rows; i++) {
+ TableData **row;
- r = table_data_requested_width_height(t, d, &req_width, &req_height);
- if (r < 0)
- return r;
- if (r > 0) { /* Truncated because too many lines? */
- _cleanup_free_ char *last = NULL;
- const char *field;
+ /* Note that we don't care about ordering at this time, as we just want to determine column sizes,
+ * hence we don't care for sorted[] during the first pass. */
+ row = t->data + i * t->n_columns;
- /* If we are going to show only the first few lines of a cell that has
- * multiple make sure that we have enough space horizontally to show an
- * ellipsis. Hence, let's figure out the last line, and account for its
- * length plus ellipsis. */
+ for (size_t j = 0; j < display_columns; j++) {
+ TableData *d;
+ size_t req_width, req_height;
- field = table_data_format(t, d, false);
- if (!field)
- return -ENOMEM;
+ assert_se(d = row[t->display_map ? t->display_map[j] : j]);
- assert_se(t->cell_height_max > 0);
- r = string_extract_line(field, t->cell_height_max-1, &last);
+ r = table_data_requested_width_height(t, d,
+ width ? width[j] : SIZE_MAX,
+ &req_width, &req_height, &any_soft);
if (r < 0)
return r;
+ if (r > 0) { /* Truncated because too many lines? */
+ _cleanup_free_ char *last = NULL;
+ const char *field;
+
+ /* If we are going to show only the first few lines of a cell that has
+ * multiple make sure that we have enough space horizontally to show an
+ * ellipsis. Hence, let's figure out the last line, and account for its
+ * length plus ellipsis. */
+
+ field = table_data_format(t, d, false,
+ width ? width[j] : SIZE_MAX,
+ &any_soft);
+ if (!field)
+ return -ENOMEM;
- req_width = MAX(req_width,
- utf8_console_width(last) +
- utf8_console_width(special_glyph(SPECIAL_GLYPH_ELLIPSIS)));
- }
+ assert_se(t->cell_height_max > 0);
+ r = string_extract_line(field, t->cell_height_max-1, &last);
+ if (r < 0)
+ return r;
- /* Determine the biggest width that any cell in this column would like to have */
- if (requested_width[j] == (size_t) -1 ||
- requested_width[j] < req_width)
- requested_width[j] = req_width;
+ req_width = MAX(req_width,
+ utf8_console_width(last) +
+ utf8_console_width(special_glyph(SPECIAL_GLYPH_ELLIPSIS)));
+ }
- /* Determine the minimum width any cell in this column needs */
- if (minimum_width[j] < d->minimum_width)
- minimum_width[j] = d->minimum_width;
+ /* Determine the biggest width that any cell in this column would like to have */
+ if (requested_width[j] == (size_t) -1 ||
+ requested_width[j] < req_width)
+ requested_width[j] = req_width;
- /* Determine the maximum width any cell in this column needs */
- if (d->maximum_width != (size_t) -1 &&
- (maximum_width[j] == (size_t) -1 ||
- maximum_width[j] > d->maximum_width))
- maximum_width[j] = d->maximum_width;
+ /* Determine the minimum width any cell in this column needs */
+ if (minimum_width[j] < d->minimum_width)
+ minimum_width[j] = d->minimum_width;
- /* Determine the full columns weight */
- column_weight[j] += d->weight;
+ /* Determine the maximum width any cell in this column needs */
+ if (d->maximum_width != (size_t) -1 &&
+ (maximum_width[j] == (size_t) -1 ||
+ maximum_width[j] > d->maximum_width))
+ maximum_width[j] = d->maximum_width;
+
+ /* Determine the full columns weight */
+ column_weight[j] += d->weight;
+ }
}
- }
- /* One space between each column */
- table_requested_width = table_minimum_width = table_maximum_width = display_columns - 1;
+ /* One space between each column */
+ table_requested_width = table_minimum_width = table_maximum_width = display_columns - 1;
- /* Calculate the total weight for all columns, plus the minimum, maximum and requested width for the table. */
- weight_sum = 0;
- for (j = 0; j < display_columns; j++) {
- weight_sum += column_weight[j];
+ /* Calculate the total weight for all columns, plus the minimum, maximum and requested width for the table. */
+ weight_sum = 0;
+ for (size_t j = 0; j < display_columns; j++) {
+ weight_sum += column_weight[j];
- table_minimum_width += minimum_width[j];
+ table_minimum_width += minimum_width[j];
+
+ if (maximum_width[j] == (size_t) -1)
+ table_maximum_width = (size_t) -1;
+ else
+ table_maximum_width += maximum_width[j];
- if (maximum_width[j] == (size_t) -1)
- table_maximum_width = (size_t) -1;
+ table_requested_width += requested_width[j];
+ }
+
+ /* Calculate effective table width */
+ if (t->width != 0 && t->width != (size_t) -1)
+ table_effective_width = t->width;
+ else if (t->width == 0 ||
+ ((pass > 0 || !any_soft) && (pager_have() || !isatty(STDOUT_FILENO))))
+ table_effective_width = table_requested_width;
else
- table_maximum_width += maximum_width[j];
+ table_effective_width = MIN(table_requested_width, columns());
- table_requested_width += requested_width[j];
- }
+ if (table_maximum_width != (size_t) -1 && table_effective_width > table_maximum_width)
+ table_effective_width = table_maximum_width;
- /* Calculate effective table width */
- if (t->width != 0 && t->width != (size_t) -1)
- table_effective_width = t->width;
- else if (t->width == 0 || pager_have() || !isatty(STDOUT_FILENO))
- table_effective_width = table_requested_width;
- else
- table_effective_width = MIN(table_requested_width, columns());
+ if (table_effective_width < table_minimum_width)
+ table_effective_width = table_minimum_width;
- if (table_maximum_width != (size_t) -1 && table_effective_width > table_maximum_width)
- table_effective_width = table_maximum_width;
+ if (!width)
+ width = newa(size_t, display_columns);
- if (table_effective_width < table_minimum_width)
- table_effective_width = table_minimum_width;
+ if (table_effective_width >= table_requested_width) {
+ size_t extra;
- if (table_effective_width >= table_requested_width) {
- size_t extra;
+ /* We have extra room, let's distribute it among columns according to their weights. We first provide
+ * each column with what it asked for and the distribute the rest. */
- /* We have extra room, let's distribute it among columns according to their weights. We first provide
- * each column with what it asked for and the distribute the rest. */
+ extra = table_effective_width - table_requested_width;
- extra = table_effective_width - table_requested_width;
+ for (size_t j = 0; j < display_columns; j++) {
+ size_t delta;
- for (j = 0; j < display_columns; j++) {
- size_t delta;
+ if (weight_sum == 0)
+ width[j] = requested_width[j] + extra / (display_columns - j); /* Avoid division by zero */
+ else
+ width[j] = requested_width[j] + (extra * column_weight[j]) / weight_sum;
- if (weight_sum == 0)
- width[j] = requested_width[j] + extra / (display_columns - j); /* Avoid division by zero */
- else
- width[j] = requested_width[j] + (extra * column_weight[j]) / weight_sum;
+ if (maximum_width[j] != (size_t) -1 && width[j] > maximum_width[j])
+ width[j] = maximum_width[j];
- if (maximum_width[j] != (size_t) -1 && width[j] > maximum_width[j])
- width[j] = maximum_width[j];
+ if (width[j] < minimum_width[j])
+ width[j] = minimum_width[j];
- if (width[j] < minimum_width[j])
- width[j] = minimum_width[j];
+ assert(width[j] >= requested_width[j]);
+ delta = width[j] - requested_width[j];
- assert(width[j] >= requested_width[j]);
- delta = width[j] - requested_width[j];
+ /* Subtract what we just added from the rest */
+ if (extra > delta)
+ extra -= delta;
+ else
+ extra = 0;
- /* Subtract what we just added from the rest */
- if (extra > delta)
- extra -= delta;
- else
- extra = 0;
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
+ }
- assert(weight_sum >= column_weight[j]);
- weight_sum -= column_weight[j];
- }
+ break; /* Every column should be happy, no need to repeat calculations. */
+ } else {
+ /* We need to compress the table, columns can't get what they asked for. We first provide each column
+ * with the minimum they need, and then distribute anything left. */
+ bool finalize = false;
+ size_t extra;
- } else {
- /* We need to compress the table, columns can't get what they asked for. We first provide each column
- * with the minimum they need, and then distribute anything left. */
- bool finalize = false;
- size_t extra;
+ extra = table_effective_width - table_minimum_width;
- extra = table_effective_width - table_minimum_width;
+ for (size_t j = 0; j < display_columns; j++)
+ width[j] = (size_t) -1;
- for (j = 0; j < display_columns; j++)
- width[j] = (size_t) -1;
+ for (;;) {
+ bool restart = false;
- for (;;) {
- bool restart = false;
+ for (size_t j = 0; j < display_columns; j++) {
+ size_t delta, w;
- for (j = 0; j < display_columns; j++) {
- size_t delta, w;
+ /* Did this column already get something assigned? If so, let's skip to the next */
+ if (width[j] != (size_t) -1)
+ continue;
- /* Did this column already get something assigned? If so, let's skip to the next */
- if (width[j] != (size_t) -1)
- continue;
+ if (weight_sum == 0)
+ w = minimum_width[j] + extra / (display_columns - j); /* avoid division by zero */
+ else
+ w = minimum_width[j] + (extra * column_weight[j]) / weight_sum;
- if (weight_sum == 0)
- w = minimum_width[j] + extra / (display_columns - j); /* avoid division by zero */
- else
- w = minimum_width[j] + (extra * column_weight[j]) / weight_sum;
+ if (w >= requested_width[j]) {
+ /* Never give more than requested. If we hit a column like this, there's more
+ * space to allocate to other columns which means we need to restart the
+ * iteration. However, if we hit a column like this, let's assign it the space
+ * it wanted for good early.*/
- if (w >= requested_width[j]) {
- /* Never give more than requested. If we hit a column like this, there's more
- * space to allocate to other columns which means we need to restart the
- * iteration. However, if we hit a column like this, let's assign it the space
- * it wanted for good early.*/
+ w = requested_width[j];
+ restart = true;
- w = requested_width[j];
- restart = true;
+ } else if (!finalize)
+ continue;
- } else if (!finalize)
- continue;
+ width[j] = w;
- width[j] = w;
+ assert(w >= minimum_width[j]);
+ delta = w - minimum_width[j];
- assert(w >= minimum_width[j]);
- delta = w - minimum_width[j];
+ assert(delta <= extra);
+ extra -= delta;
- assert(delta <= extra);
- extra -= delta;
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
- assert(weight_sum >= column_weight[j]);
- weight_sum -= column_weight[j];
+ if (restart && !finalize)
+ break;
+ }
- if (restart && !finalize)
+ if (finalize)
break;
+
+ if (!restart)
+ finalize = true;
}
- if (finalize)
+ if (!any_soft) /* Some columns got less than requested. If some cells were "soft",
+ * let's try to reformat them with the new widths. Otherwise, let's
+ * move on. */
break;
-
- if (!restart)
- finalize = true;
}
}
/* Second pass: show output */
- for (i = t->header ? 0 : 1; i < n_rows; i++) {
+ for (size_t i = t->header ? 0 : 1; i < n_rows; i++) {
size_t n_subline = 0;
bool more_sublines;
TableData **row;
const char *gap_color = NULL;
more_sublines = false;
- for (j = 0; j < display_columns; j++) {
+ for (size_t j = 0; j < display_columns; j++) {
_cleanup_free_ char *buffer = NULL, *extracted = NULL;
bool lines_truncated = false;
const char *field, *color = NULL;
assert_se(d = row[t->display_map ? t->display_map[j] : j]);
- field = table_data_format(t, d, false);
+ field = table_data_format(t, d, false, width[j], NULL);
if (!field)
return -ENOMEM;
return json_variant_new_string(ret, d->string);
case TABLE_STRV:
+ case TABLE_STRV_WRAPPED:
return json_variant_new_array_strv(ret, d->strv);
case TABLE_BOOLEAN:
}
static char* string_to_json_field_name(const char *f) {
- char *c, *x;
-
/* Tries to make a string more suitable as JSON field name. There are no strict rules defined what a
* field name can be hence this is a bit vague and black magic. Right now we only convert spaces to
* underscores and leave everything as is. */
- c = strdup(f);
+ char *c = strdup(f);
if (!c)
return NULL;
- for (x = c; *x; x++)
+ for (char *x = c; *x; x++)
if (isspace(*x))
*x = '_';
int table_to_json(Table *t, JsonVariant **ret) {
JsonVariant **rows = NULL, **elements = NULL;
_cleanup_free_ size_t *sorted = NULL;
- size_t n_rows, i, j, display_columns;
+ size_t n_rows, display_columns;
int r;
assert(t);
goto finish;
}
- for (i = 0; i < n_rows; i++)
+ for (size_t i = 0; i < n_rows; i++)
sorted[i] = i * t->n_columns;
typesafe_qsort_r(sorted, n_rows, table_data_compare, t);
goto finish;
}
- for (j = 0; j < display_columns; j++) {
+ for (size_t j = 0; j < display_columns; j++) {
_cleanup_free_ char *mangled = NULL;
const char *formatted;
TableData *d;
assert_se(d = t->data[t->display_map ? t->display_map[j] : j]);
/* Field names must be strings, hence format whatever we got here as a string first */
- formatted = table_data_format(t, d, true);
+ formatted = table_data_format(t, d, true, SIZE_MAX, NULL);
if (!formatted) {
r = -ENOMEM;
goto finish;
goto finish;
}
- for (i = 1; i < n_rows; i++) {
+ for (size_t i = 1; i < n_rows; i++) {
TableData **row;
if (sorted)
else
row = t->data + i * t->n_columns;
- for (j = 0; j < display_columns; j++) {
+ for (size_t j = 0; j < display_columns; j++) {
TableData *d;
size_t k;
TABLE_EMPTY,
TABLE_STRING,
TABLE_STRV,
+ TABLE_STRV_WRAPPED,
TABLE_PATH,
TABLE_BOOLEAN,
TABLE_TIMESTAMP,
if (!ret_filtered) {
for (const char *word = opts;;) {
- const char *end = word + strcspn(word, ",");
+ const char *end = word;
+
+ /* Look for an *non-escaped* comma separator. Only commas can be escaped, so "\," is
+ * the only valid escape sequence, so we can do a very simple test here. */
+ for (;;) {
+ size_t n = strcspn(end, ",");
+
+ end += n;
+ if (n > 0 && end[-1] == '\\')
+ end++;
+ else
+ break;
+ }
NULSTR_FOREACH(name, names) {
if (end < word + strlen(name))
break;
}
} else {
- stor = strv_split(opts, ",");
- if (!stor)
- return -ENOMEM;
+ r = strv_split_full(&stor, opts, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
+ if (r < 0)
+ return r;
+
strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
if (!strv)
return -ENOMEM;
if (ret_filtered) {
char *f;
- f = strv_join(strv, ",");
+ f = strv_join_full(strv, ",", NULL, true);
if (!f)
return -ENOMEM;
#include <unistd.h>
#include "alloc-util.h"
+#include "cgroup-util.h"
#include "dropin.h"
#include "escape.h"
#include "fd-util.h"
}
void log_setup_generator(void) {
- log_set_prohibit_ipc(true);
- log_setup_service();
+ /* Disable talking to syslog/journal (i.e. the two IPC-based loggers) if we run in system context. */
+ if (cg_pid_get_owner_uid(0, NULL) == -ENXIO /* not running in a per-user slice */)
+ log_set_prohibit_ipc(true);
+
+ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); /* This effectively means: journal for per-user generators, kmsg otherwise */
+ log_parse_environment();
+ (void) log_open();
}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#if HAVE_LIBIDN2
+# include <idn2.h>
+#elif HAVE_LIBIDN
+# include <idna.h>
+# include <stringprep.h>
+#endif
+
+#include "alloc-util.h"
+#include "dlfcn-util.h"
+#include "idn-util.h"
+
+#if HAVE_LIBIDN || HAVE_LIBIDN2
+static void* idn_dl = NULL;
+#endif
+
+#if HAVE_LIBIDN2
+int (*sym_idn2_lookup_u8)(const uint8_t* src, uint8_t** lookupname, int flags) = NULL;
+const char *(*sym_idn2_strerror)(int rc) = NULL;
+int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL;
+
+int dlopen_idn(void) {
+ _cleanup_(dlclosep) void *dl = NULL;
+ int r;
+
+ if (idn_dl)
+ return 0; /* Already loaded */
+
+ dl = dlopen("libidn2.so.0", RTLD_LAZY);
+ if (!dl)
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libidn2 support is not installed: %s", dlerror());
+
+ r = dlsym_many_and_warn(
+ dl,
+ LOG_DEBUG,
+ &sym_idn2_lookup_u8, "idn2_lookup_u8",
+ &sym_idn2_strerror, "idn2_strerror",
+ &sym_idn2_to_unicode_8z8z, "idn2_to_unicode_8z8z",
+ NULL);
+ if (r < 0)
+ return r;
+
+ /* Note that we never release the reference here, because there's no real reason to, after all this
+ * was traditionally a regular shared library dependency which lives forever too. */
+ idn_dl = TAKE_PTR(dl);
+
+ return 1;
+}
+#endif
+
+#if HAVE_LIBIDN
+int (*sym_idna_to_ascii_4i)(const uint32_t * in, size_t inlen, char *out, int flags);
+int (*sym_idna_to_unicode_44i)(const uint32_t * in, size_t inlen,uint32_t * out, size_t * outlen, int flags);
+char* (*sym_stringprep_ucs4_to_utf8)(const uint32_t * str, ssize_t len, size_t * items_read, size_t * items_written);
+uint32_t* (*sym_stringprep_utf8_to_ucs4)(const char *str, ssize_t len, size_t *items_written);
+
+int dlopen_idn(void) {
+ _cleanup_(dlclosep) void *dl = NULL;
+ int r;
+
+ if (idn_dl)
+ return 0; /* Already loaded */
+
+ dl = dlopen("libidn.so.12", RTLD_LAZY);
+ if (!dl) {
+ /* libidn broke ABI in 1.34, but not in a way we care about (a new field got added to an
+ * open-coded struct we do not use), hence support both versions. */
+ dl = dlopen("libidn.so.11", RTLD_LAZY);
+ if (!dl)
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libidn support is not installed: %s", dlerror());
+ }
+
+ r = dlsym_many_and_warn(
+ dl,
+ LOG_DEBUG,
+ &sym_idna_to_ascii_4i, "idna_to_ascii_4i",
+ &sym_idna_to_unicode_44i, "idna_to_unicode_44i",
+ &sym_stringprep_ucs4_to_utf8, "stringprep_ucs4_to_utf8",
+ &sym_stringprep_utf8_to_ucs4, "stringprep_utf8_to_ucs4",
+ NULL);
+ if (r < 0)
+ return r;
+
+ idn_dl = TAKE_PTR(dl);
+
+ return 1;
+}
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#if HAVE_LIBIDN2
+# include <idn2.h>
+#elif HAVE_LIBIDN
+# include <idna.h>
+# include <stringprep.h>
+#endif
+
+#include <inttypes.h>
+
+#if HAVE_LIBIDN2 || HAVE_LIBIDN
+int dlopen_idn(void);
+#else
+static inline int dlopen_idn(void) {
+ return -EOPNOTSUPP;
+}
+#endif
+
+#if HAVE_LIBIDN2
+extern int (*sym_idn2_lookup_u8)(const uint8_t* src, uint8_t** lookupname, int flags);
+extern const char *(*sym_idn2_strerror)(int rc);
+extern int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags);
+#endif
+
+#if HAVE_LIBIDN
+extern int (*sym_idna_to_ascii_4i)(const uint32_t * in, size_t inlen, char *out, int flags);
+extern int (*sym_idna_to_unicode_44i)(const uint32_t * in, size_t inlen,uint32_t * out, size_t * outlen, int flags);
+extern char* (*sym_stringprep_ucs4_to_utf8)(const uint32_t * str, ssize_t len, size_t * items_read, size_t * items_written);
+extern uint32_t* (*sym_stringprep_utf8_to_ucs4)(const char *str, ssize_t len, size_t *items_written);
+#endif
assert_se(value = json_variant_by_index(v, i+1));
for (p = table; p->name; p++)
- if (p->name == (const char*) -1 ||
+ if (p->name == POINTER_MAX ||
streq_ptr(json_variant_string(key), p->name))
break;
return (int) n_list;
}
+static int add_local_gateway(
+ struct local_address **list,
+ size_t *n_list,
+ size_t *n_allocated,
+ int af,
+ int ifindex,
+ uint32_t metric,
+ const RouteVia *via) {
+
+ assert(list);
+ assert(n_list);
+ assert(n_allocated);
+ assert(via);
+
+ if (af != AF_UNSPEC && af != via->family)
+ return 0;
+
+ if (!GREEDY_REALLOC(*list, *n_allocated, *n_list + 1))
+ return -ENOMEM;
+
+ (*list)[(*n_list)++] = (struct local_address) {
+ .ifindex = ifindex,
+ .metric = metric,
+ .family = via->family,
+ .address = via->address,
+ };
+
+ return 0;
+}
+
int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_free_ struct local_address *list = NULL;
- sd_netlink_message *m = NULL;
size_t n_list = 0, n_allocated = 0;
int r;
if (r < 0)
return r;
- for (m = reply; m; m = sd_netlink_message_next(m)) {
- struct local_address *a;
+ for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
+ _cleanup_ordered_set_free_free_ OrderedSet *multipath_routes = NULL;
+ _cleanup_free_ void *rta_multipath = NULL;
+ union in_addr_union gateway;
uint16_t type;
unsigned char dst_len, src_len, table;
- uint32_t ifi;
+ uint32_t ifi, metric = 0;
+ size_t rta_len;
int family;
+ RouteVia via;
r = sd_netlink_message_get_errno(m);
if (r < 0)
if (table != RT_TABLE_MAIN)
continue;
- r = sd_netlink_message_read_u32(m, RTA_OIF, &ifi);
- if (r == -ENODATA) /* Not all routes have an RTA_OIF attribute (for example nexthop ones) */
- continue;
- if (r < 0)
+ r = sd_netlink_message_read_u32(m, RTA_PRIORITY, &metric);
+ if (r < 0 && r != -ENODATA)
return r;
- if (ifindex > 0 && (int) ifi != ifindex)
- continue;
r = sd_rtnl_message_route_get_family(m, &family);
if (r < 0)
return r;
- if (af != AF_UNSPEC && af != family)
+ if (!IN_SET(family, AF_INET, AF_INET6))
continue;
- if (!GREEDY_REALLOC0(list, n_allocated, n_list + 1))
- return -ENOMEM;
+ r = sd_netlink_message_read_u32(m, RTA_OIF, &ifi);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ if (r >= 0) {
+ if (ifi <= 0)
+ return -EINVAL;
+ if (ifindex > 0 && (int) ifi != ifindex)
+ continue;
- a = list + n_list;
+ r = netlink_message_read_in_addr_union(m, RTA_GATEWAY, family, &gateway);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ if (r >= 0) {
+ via.family = family;
+ via.address = gateway;
+ r = add_local_gateway(&list, &n_list, &n_allocated, af, ifi, metric, &via);
+ if (r < 0)
+ return r;
- switch (family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(m, RTA_GATEWAY, &a->address.in);
- if (r < 0)
continue;
+ }
- break;
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6);
- if (r < 0)
+ if (family != AF_INET)
continue;
- break;
- default:
- continue;
+ r = sd_netlink_message_read(m, RTA_VIA, sizeof(via), &via);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ if (r >= 0) {
+ r = add_local_gateway(&list, &n_list, &n_allocated, af, ifi, metric, &via);
+ if (r < 0)
+ return r;
+
+ continue;
+ }
}
- sd_netlink_message_read_u32(m, RTA_PRIORITY, &a->metric);
+ r = sd_netlink_message_read_data(m, RTA_MULTIPATH, &rta_len, &rta_multipath);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ if (r >= 0) {
+ MultipathRoute *mr;
- a->ifindex = ifi;
- a->family = family;
+ r = rtattr_read_nexthop(rta_multipath, rta_len, family, &multipath_routes);
+ if (r < 0)
+ return r;
- n_list++;
+ ORDERED_SET_FOREACH(mr, multipath_routes) {
+ if (ifindex > 0 && mr->ifindex != ifindex)
+ continue;
+
+ r = add_local_gateway(&list, &n_list, &n_allocated, af, ifi, metric, &mr->gateway);
+ if (r < 0)
+ return r;
+ }
+ }
}
typesafe_qsort(list, n_list, address_compare);
}
static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, OutputFlags flags, const char *realtime) {
- char buf[MAX(FORMAT_TIMESTAMP_MAX, 64)];
+ char buf[MAX(FORMAT_TIMESTAMP_MAX, 64U)];
struct tm *(*gettime_r)(const time_t *, struct tm *);
struct tm tm;
uint64_t x;
group-record.h
id128-print.c
id128-print.h
+ idn-util.c
+ idn-util.h
ima-util.c
ima-util.h
import-util.c
pkcs11-util.h
pretty-print.c
pretty-print.h
+ psi-util.c
+ psi-util.h
ptyfwd.c
ptyfwd.h
pwquality-util.c
libcap,
libcrypt,
libgcrypt,
- libidn,
libiptc,
libkmod,
liblz4,
{ "v241", NAMING_V241 },
{ "v243", NAMING_V243 },
{ "v245", NAMING_V245 },
+ { "v247", NAMING_V247 },
/* … add more schemes here, as the logic to name devices is updated … */
};
NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */
NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
NAMING_NSPAWN_LONG_HASH = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation */
+ NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS,
NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
NAMING_V245 = NAMING_V243 | NAMING_NSPAWN_LONG_HASH,
+ NAMING_V247 = NAMING_V245 | NAMING_BRIDGE_NO_SLOT,
_NAMING_SCHEME_FLAGS_INVALID = -1,
} NamingSchemeFlags;
#include <sys/prctl.h>
#include <unistd.h>
+#include "sd-login.h"
+
#include "copy.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
_exit(EXIT_FAILURE);
}
- /* Initialize a good charset for less. This is
- * particularly important if we output UTF-8
+ /* Initialize a good charset for less. This is particularly important if we output UTF-8
* characters. */
less_charset = getenv("SYSTEMD_LESSCHARSET");
if (!less_charset && is_locale_utf8())
_exit(EXIT_FAILURE);
}
- if (pager_args) {
+ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out
+ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the
+ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE
+ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we
+ * know to be good. */
+ int use_secure_mode = getenv_bool_secure("SYSTEMD_PAGERSECURE");
+ bool trust_pager = use_secure_mode >= 0;
+ if (use_secure_mode == -ENXIO) {
+ uid_t uid;
+
+ r = sd_pid_get_owner_uid(0, &uid);
+ if (r < 0)
+ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m");
+
+ use_secure_mode = r < 0 || uid != geteuid();
+
+ } else if (use_secure_mode < 0) {
+ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m");
+ use_secure_mode = true;
+ }
+
+ /* We generally always set variables used by less, even if we end up using a different pager.
+ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */
+ if (use_secure_mode)
+ r = setenv("LESSSECURE", "1", 1);
+ else
+ r = unsetenv("LESSSECURE");
+ if (r < 0) {
+ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (trust_pager && pager_args) { /* The pager config might be set globally, and we cannot
+ * know if the user adjusted it to be appropriate for the
+ * secure mode. Thus, start the pager specified through
+ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set
+ * as well. */
r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false);
if (r < 0) {
log_error_errno(r, "Failed to write pager name to socket: %m");
"Failed to execute '%s', using fallback pagers: %m", pager_args[0]);
}
- /* Debian's alternatives command for pagers is
- * called 'pager'. Note that we do not call
- * sensible-pagers here, since that is just a
- * shell script that implements a logic that
- * is similar to this one anyway, but is
- * Debian-specific. */
+ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call
+ * sensible-pagers here, since that is just a shell script that implements a logic that is
+ * similar to this one anyway, but is Debian-specific. */
FOREACH_STRING(exe, "pager", "less", "more") {
+ /* Only less implements secure mode right now. */
+ if (use_secure_mode && !streq(exe, "less"))
+ continue;
+
r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false);
if (r < 0) {
log_error_errno(r, "Failed to write pager name to socket: %m");
"Failed to execute '%s', using next fallback pager: %m", exe);
}
+ /* Our builtin is also very secure. */
r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in)") + 1, false);
if (r < 0) {
log_error_errno(r, "Failed to write pager name to socket: %m");
rv = m->C_GetTokenInfo(slotid, &token_info);
if (rv == CKR_TOKEN_NOT_PRESENT) {
- log_debug("Token not present in slot, ignoring.");
- return -EAGAIN;
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "Token not present in slot, ignoring.");
} else if (rv != CKR_OK) {
log_warning("Failed to acquire token info for slot %lu, ignoring slot: %s", slotid, p11_kit_strerror(rv));
return -EAGAIN;
return -EAGAIN;
}
- if (search_uri && !p11_kit_uri_match_token_info(search_uri, &token_info)) {
- log_debug("Found non-matching token with URI %s.", token_uri_string);
- return -EAGAIN;
- }
+ if (search_uri && !p11_kit_uri_match_token_info(search_uri, &token_info))
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "Found non-matching token with URI %s.",
+ token_uri_string);
log_debug("Found matching token with URI %s.", token_uri_string);
log_warning("Failed to get slot list, ignoring module: %s", p11_kit_strerror(rv));
return -EAGAIN;
}
- if (n_slotids == 0) {
- log_debug("This module has no slots? Ignoring module.");
- return -EAGAIN;
- }
+ if (n_slotids == 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+ "This module has no slots? Ignoring module.");
for (k = 0; k < n_slotids; k++) {
r = slot_process(
if (file) {
r = cat_file(file, false);
if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL))
- printf("%s# config file %s not found%s\n",
+ printf("%s# Configuration file %s not found%s\n",
ansi_highlight_magenta(),
file,
ansi_normal());
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "extract-word.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "psi-util.h"
+#include "string-util.h"
+#include "stat-util.h"
+#include "strv.h"
+
+int read_resource_pressure(const char *path, PressureType type, ResourcePressure *ret) {
+ _cleanup_free_ char *line = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ unsigned field_filled = 0;
+ ResourcePressure rp = {};
+ const char *t, *cline;
+ char *word;
+ int r;
+
+ assert(path);
+ assert(IN_SET(type, PRESSURE_TYPE_SOME, PRESSURE_TYPE_FULL));
+ assert(ret);
+
+ if (type == PRESSURE_TYPE_SOME)
+ t = "some";
+ else if (type == PRESSURE_TYPE_FULL)
+ t = "full";
+ else
+ return -EINVAL;
+
+ r = fopen_unlocked(path, "re", &f);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ _cleanup_free_ char *l = NULL;
+ char *w;
+
+ r = read_line(f, LONG_LINE_MAX, &l);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ w = first_word(l, t);
+ if (w) {
+ line = TAKE_PTR(l);
+ cline = w;
+ break;
+ }
+ }
+
+ if (!line)
+ return -ENODATA;
+
+ /* extracts either avgX=Y.Z or total=X */
+ while ((r = extract_first_word(&cline, &word, NULL, 0)) > 0) {
+ _cleanup_free_ char *w = word;
+ const char *v;
+
+ if ((v = startswith(w, "avg10="))) {
+ if (field_filled & (1U << 0))
+ return -EINVAL;
+
+ field_filled |= 1U << 0;
+ r = parse_loadavg_fixed_point(v, &rp.avg10);
+ } else if ((v = startswith(w, "avg60="))) {
+ if (field_filled & (1U << 1))
+ return -EINVAL;
+
+ field_filled |= 1U << 1;
+ r = parse_loadavg_fixed_point(v, &rp.avg60);
+ } else if ((v = startswith(w, "avg300="))) {
+ if (field_filled & (1U << 2))
+ return -EINVAL;
+
+ field_filled |= 1U << 2;
+ r = parse_loadavg_fixed_point(v, &rp.avg300);
+ } else if ((v = startswith(w, "total="))) {
+ if (field_filled & (1U << 3))
+ return -EINVAL;
+
+ field_filled |= 1U << 3;
+ r = safe_atou64(v, &rp.total);
+ } else
+ continue;
+
+ if (r < 0)
+ return r;
+ }
+
+ if (r < 0)
+ return r;
+
+ if (field_filled != 15U)
+ return -EINVAL;
+
+ *ret = rp;
+ return 0;
+}
+
+int is_pressure_supported(void) {
+ const char *p;
+
+ FOREACH_STRING(p, "/proc/pressure/cpu", "/proc/pressure/io", "/proc/pressure/memory")
+ if (access(p, F_OK) < 0) {
+ if (errno == ENOENT)
+ return 0;
+ return -errno;
+ }
+
+ return 1;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "parse-util.h"
+#include "time-util.h"
+
+typedef enum PressureType {
+ PRESSURE_TYPE_SOME,
+ PRESSURE_TYPE_FULL,
+} PressureType;
+
+/* Averages are stored in fixed-point with 11 bit fractions */
+typedef struct ResourcePressure {
+ loadavg_t avg10;
+ loadavg_t avg60;
+ loadavg_t avg300;
+ usec_t total;
+} ResourcePressure;
+
+/** Upstream 4.20+ format
+ *
+ * some avg10=0.22 avg60=0.17 avg300=1.11 total=58761459
+ * full avg10=0.23 avg60=0.16 avg300=1.08 total=58464525
+ */
+int read_resource_pressure(const char *path, PressureType type, ResourcePressure *ret);
+
+/* Was the kernel compiled with CONFIG_PSI=y? 1 if yes, 0 if not, negative on error. */
+int is_pressure_supported(void);
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
struct PTYForward {
sd_event *event;
+ int input_fd;
+ int output_fd;
int master;
PTYForwardFlags flags;
struct termios saved_stdin_attr;
struct termios saved_stdout_attr;
+ bool close_input_fd:1;
+ bool close_output_fd:1;
+
bool saved_stdin:1;
bool saved_stdout:1;
static void pty_forward_disconnect(PTYForward *f) {
- if (f) {
- f->stdin_event_source = sd_event_source_unref(f->stdin_event_source);
- f->stdout_event_source = sd_event_source_unref(f->stdout_event_source);
+ if (!f)
+ return;
- f->master_event_source = sd_event_source_unref(f->master_event_source);
- f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source);
- f->event = sd_event_unref(f->event);
+ f->stdin_event_source = sd_event_source_unref(f->stdin_event_source);
+ f->stdout_event_source = sd_event_source_unref(f->stdout_event_source);
+ f->master_event_source = sd_event_source_unref(f->master_event_source);
+ f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source);
+ f->event = sd_event_unref(f->event);
+
+ if (f->output_fd >= 0) {
if (f->saved_stdout)
- tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr);
+ (void) tcsetattr(f->output_fd, TCSANOW, &f->saved_stdout_attr);
+
+ /* STDIN/STDOUT should not be non-blocking normally, so let's reset it */
+ (void) fd_nonblock(f->output_fd, false);
+ if (f->close_output_fd)
+ f->output_fd = safe_close(f->output_fd);
+ }
+
+ if (f->input_fd >= 0) {
if (f->saved_stdin)
- tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr);
+ (void) tcsetattr(f->input_fd, TCSANOW, &f->saved_stdin_attr);
- f->saved_stdout = f->saved_stdin = false;
+ (void) fd_nonblock(f->input_fd, false);
+ if (f->close_input_fd)
+ f->input_fd = safe_close(f->input_fd);
}
- /* STDIN/STDOUT should not be nonblocking normally, so let's unconditionally reset it */
- (void) fd_nonblock(STDIN_FILENO, false);
- (void) fd_nonblock(STDOUT_FILENO, false);
+ f->saved_stdout = f->saved_stdin = false;
}
static int pty_forward_done(PTYForward *f, int rcode) {
if (f->stdin_readable && f->in_buffer_full < LINE_MAX) {
- k = read(STDIN_FILENO, f->in_buffer + f->in_buffer_full, LINE_MAX - f->in_buffer_full);
+ k = read(f->input_fd, f->in_buffer + f->in_buffer_full, LINE_MAX - f->in_buffer_full);
if (k < 0) {
if (errno == EAGAIN)
if (f->stdout_writable && f->out_buffer_full > 0) {
- k = write(STDOUT_FILENO, f->out_buffer, f->out_buffer_full);
+ k = write(f->output_fd, f->out_buffer, f->out_buffer_full);
if (k < 0) {
if (errno == EAGAIN)
assert(e);
assert(e == f->stdin_event_source);
assert(fd >= 0);
- assert(fd == STDIN_FILENO);
+ assert(fd == f->input_fd);
if (revents & (EPOLLIN|EPOLLHUP))
f->stdin_readable = true;
assert(e);
assert(e == f->stdout_event_source);
assert(fd >= 0);
- assert(fd == STDOUT_FILENO);
+ assert(fd == f->output_fd);
if (revents & (EPOLLOUT|EPOLLHUP))
f->stdout_writable = true;
assert(e == f->sigwinch_event_source);
/* The window size changed, let's forward that. */
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
+ if (ioctl(f->output_fd, TIOCGWINSZ, &ws) >= 0)
(void) ioctl(f->master, TIOCSWINSZ, &ws);
return 0;
*f = (struct PTYForward) {
.flags = flags,
.master = -1,
+ .input_fd = -1,
+ .output_fd = -1,
};
if (event)
return r;
}
- if (!(flags & PTY_FORWARD_READ_ONLY)) {
- r = fd_nonblock(STDIN_FILENO, true);
- if (r < 0)
- return r;
-
- r = fd_nonblock(STDOUT_FILENO, true);
- if (r < 0)
- return r;
+ if (FLAGS_SET(flags, PTY_FORWARD_READ_ONLY))
+ f->output_fd = STDOUT_FILENO;
+ else {
+ /* If we shall be invoked in interactive mode, let's switch on non-blocking mode, so that we
+ * never end up staving one direction while we block on the other. However, let's be careful
+ * here and not turn on O_NONBLOCK for stdin/stdout directly, but of re-opened copies of
+ * them. This has two advantages: when we are killed abruptly the stdin/stdout fds won't be
+ * left in O_NONBLOCK state for the next process using them. In addition, if some process
+ * running in the background wants to continue writing to our stdout it can do so without
+ * being confused by O_NONBLOCK. */
+
+ f->input_fd = fd_reopen(STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+ if (f->input_fd < 0) {
+ /* Handle failures gracefully, after all certain fd types cannot be reopened
+ * (sockets, …) */
+ log_debug_errno(f->input_fd, "Failed to reopen stdin, using original fd: %m");
+
+ r = fd_nonblock(STDIN_FILENO, true);
+ if (r < 0)
+ return r;
+
+ f->input_fd = STDIN_FILENO;
+ } else
+ f->close_input_fd = true;
+
+ f->output_fd = fd_reopen(STDOUT_FILENO, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+ if (f->output_fd < 0) {
+ log_debug_errno(f->output_fd, "Failed to reopen stdout, using original fd: %m");
+
+ r = fd_nonblock(STDOUT_FILENO, true);
+ if (r < 0)
+ return r;
+
+ f->output_fd = STDOUT_FILENO;
+ } else
+ f->close_output_fd = true;
}
r = fd_nonblock(master, true);
f->master = master;
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {
+ if (ioctl(f->output_fd, TIOCGWINSZ, &ws) < 0)
/* If we can't get the resolution from the output fd, then use our internal, regular width/height,
* i.e. something derived from $COLUMNS and $LINES if set. */
-
ws = (struct winsize) {
.ws_row = lines(),
.ws_col = columns(),
};
- }
(void) ioctl(master, TIOCSWINSZ, &ws);
if (!(flags & PTY_FORWARD_READ_ONLY)) {
- if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
+ assert(f->input_fd >= 0);
+
+ if (tcgetattr(f->input_fd, &f->saved_stdin_attr) >= 0) {
struct termios raw_stdin_attr;
f->saved_stdin = true;
raw_stdin_attr = f->saved_stdin_attr;
cfmakeraw(&raw_stdin_attr);
raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
- tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
+ tcsetattr(f->input_fd, TCSANOW, &raw_stdin_attr);
}
- if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
+ if (tcgetattr(f->output_fd, &f->saved_stdout_attr) >= 0) {
struct termios raw_stdout_attr;
f->saved_stdout = true;
cfmakeraw(&raw_stdout_attr);
raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
- tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
+ tcsetattr(f->output_fd, TCSANOW, &raw_stdout_attr);
}
- r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
+ r = sd_event_add_io(f->event, &f->stdin_event_source, f->input_fd, EPOLLIN|EPOLLET, on_stdin_event, f);
if (r < 0 && r != -EPERM)
return r;
(void) sd_event_source_set_description(f->stdin_event_source, "ptyfwd-stdin");
}
- r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f);
+ r = sd_event_add_io(f->event, &f->stdout_event_source, f->output_fd, EPOLLOUT|EPOLLET, on_stdout_event, f);
if (r == -EPERM)
/* stdout without epoll support. Likely redirected to regular file. */
f->stdout_writable = true;
.name = "@default",
.help = "System calls that are always permitted",
.value =
+ "cacheflush\0"
"clock_getres\0"
"clock_getres_time64\0"
"clock_gettime\0"
.value =
"_llseek\0"
"close\0"
+ "close_range\0"
"dup\0"
"dup2\0"
"dup3\0"
},
[SYSCALL_FILTER_SET_PROCESS] = {
.name = "@process",
- .help = "Process control, execution, namespaceing operations",
+ .help = "Process control, execution, namespacing operations",
.value =
"arch_prctl\0"
"capget\0" /* Able to query arbitrary processes */
}
/* NOOP? */
- if ((retain & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
+ if (FLAGS_SET(retain, NAMESPACE_FLAGS_ALL))
return 0;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
unsigned long f;
f = namespace_flag_map[i].flag;
- if ((retain & f) == f) {
+ if (FLAGS_SET(retain, f)) {
log_debug("Permitting %s.", namespace_flag_map[i].name);
continue;
}
return 0;
}
-int enter_cgroup_subroot(char **ret_cgroup) {
+static int enter_cgroup(char **ret_cgroup, bool enter_subroot) {
_cleanup_free_ char *cgroup_root = NULL, *cgroup_subroot = NULL;
CGroupMask supported;
int r;
return log_warning_errno(r, "cg_pid_get_path(NULL, 0, ...) failed: %m");
assert(r >= 0);
- assert_se(asprintf(&cgroup_subroot, "%s/%" PRIx64, cgroup_root, random_u64()) >= 0);
+ if (enter_subroot)
+ assert_se(asprintf(&cgroup_subroot, "%s/%" PRIx64, cgroup_root, random_u64()) >= 0);
+ else {
+ cgroup_subroot = strdup(cgroup_root);
+ assert_se(cgroup_subroot != NULL);
+ }
+
assert_se(cg_mask_supported(&supported) >= 0);
/* If this fails, then we don't mind as the later cgroup operations will fail too, and it's fine if
return 0;
}
+
+int enter_cgroup_subroot(char **ret_cgroup) {
+ return enter_cgroup(ret_cgroup, true);
+}
+
+int enter_cgroup_root(char **ret_cgroup) {
+ return enter_cgroup(ret_cgroup, false);
+}
+
+const char *ci_environment(void) {
+ /* We return a string because we might want to provide multiple bits of information later on: not
+ * just the general CI environment type, but also whether we're sanitizing or not, etc. The caller is
+ * expected to use strstr on the returned value. */
+ static const char *ans = POINTER_MAX;
+ const char *p;
+ int r;
+
+ if (ans != POINTER_MAX)
+ return ans;
+
+ /* We allow specifying the environment with $CITYPE. Nobody uses this so far, but we are ready. */
+ p = getenv("CITYPE");
+ if (!isempty(p))
+ return (ans = p);
+
+ if (getenv_bool("TRAVIS") > 0)
+ return (ans = "travis");
+ if (getenv_bool("SEMAPHORE") > 0)
+ return (ans = "semaphore");
+ if (getenv_bool("GITHUB_ACTIONS") > 0)
+ return (ans = "github-actions");
+ if (getenv("AUTOPKGTEST_ARTIFACTS") || getenv("AUTOPKGTEST_TMP"))
+ return (ans = "autopkgtest");
+
+ FOREACH_STRING(p, "CI", "CONTINOUS_INTEGRATION") {
+ /* Those vars are booleans according to Semaphore and Travis docs:
+ * https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
+ * https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#ci
+ */
+ r = getenv_bool(p);
+ if (r > 0)
+ return (ans = "unknown"); /* Some other unknown thing */
+ if (r == 0)
+ return (ans = NULL);
+ }
+
+ return (ans = NULL);
+}
char* setup_fake_runtime_dir(void);
int enter_cgroup_subroot(char **ret_cgroup);
+int enter_cgroup_root(char **ret_cgroup);
int get_testdata_dir(const char *suffix, char **ret);
const char* get_catalog_dir(void);
bool slow_tests_enabled(void);
} else { \
printf("systemd not booted skipping '%s'\n", #x); \
}
+
+/* Provide a convenient way to check if we're running in CI. */
+const char *ci_environment(void);
assert(devlink);
- r = stat(devlink, &st);
- if (r < 0)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to stat() %s: %m", devlink);
+ if (stat(devlink, &st) < 0)
+ return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
+ "Failed to stat() %s: %m", devlink);
if (!S_ISBLK(st.st_mode))
- return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "%s does not point to a block device: %m", devlink);
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
+ "%s does not point to a block device: %m", devlink);
r = sd_device_new_from_devnum(ret_device, 'b', st.st_rdev);
if (r < 0)
assert(data->sysname || data->devlink);
assert(!data->device);
+ /* Ignore REMOVE events here. We are waiting for initialization after all, not de-initialization. We
+ * might see a REMOVE event from an earlier use of the device (devices by the same name are recycled
+ * by the kernel after all), which we should not get confused by. After all we cannot distinguish use
+ * cycles of the devices, as the udev queue is entirely asynchronous.
+ *
+ * If we see a REMOVE event here for the use cycle we actually care about then we won't notice of
+ * course, but that should be OK, given the timeout logic used on the wait loop: this will be noticed
+ * by means of -ETIMEDOUT. Thus we won't notice immediately, but eventually, and that should be
+ * sufficient for an error path that should regularly not happen.
+ *
+ * (And yes, we only need to special case REMOVE. It's the only "negative" event type, where a device
+ * ceases to exist. All other event types are "positive": the device exists and is registered in the
+ * udev database, thus whenever we see the event, we can consider it initialized.) */
+ if (device_for_action(device, DEVICE_ACTION_REMOVE))
+ return 0;
+
if (data->sysname && sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname))
goto found;
return sd_event_exit(sd_device_monitor_get_event(monitor), 0);
}
-static int device_timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) {
- return sd_event_exit(sd_event_source_get_event(s), -ETIMEDOUT);
-}
-
static int device_wait_for_initialization_internal(
sd_device *_device,
const char *devlink,
r = sd_event_add_time_relative(
event, &timeout_source,
CLOCK_MONOTONIC, timeout, 0,
- device_timeout_handler, NULL);
+ NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0)
return log_error_errno(r, "Failed to add timeout event source: %m");
}
assert(dev);
r = sd_device_get_property_value(dev, "ID_RENAMING", NULL);
- if (r < 0 && r != -ENOENT)
+ if (r == -ENOENT)
+ return false;
+ if (r < 0)
return r;
- return r >= 0;
+ return true;
}
bool device_for_action(sd_device *dev, DeviceAction action) {
}
static void uid_range_coalesce(UidRange **p, unsigned *n) {
- unsigned i, j;
-
assert(p);
assert(n);
- for (i = 0; i < *n; i++) {
- for (j = i + 1; j < *n; j++) {
+ for (unsigned i = 0; i < *n; i++) {
+ for (unsigned j = i + 1; j < *n; j++) {
UidRange *x = (*p)+i, *y = (*p)+j;
if (uid_range_intersect(x, y->start, y->nr)) {
int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr) {
bool found = false;
UidRange *x;
- unsigned i;
assert(p);
assert(n);
if (nr <= 0)
return 0;
- for (i = 0; i < *n; i++) {
+ for (unsigned i = 0; i < *n; i++) {
x = (*p) + i;
if (uid_range_intersect(x, start, nr)) {
found = true;
int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid) {
uid_t closest = UID_INVALID, candidate;
- unsigned i;
assert(p);
assert(uid);
candidate = *uid - 1;
- for (i = 0; i < n; i++) {
+ for (unsigned i = 0; i < n; i++) {
uid_t begin, end;
begin = p[i].start;
}
bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid) {
- unsigned i;
-
assert(p);
assert(uid);
- for (i = 0; i < n; i++)
+ for (unsigned i = 0; i < n; i++)
if (uid >= p[i].start && uid < p[i].start + p[i].nr)
return true;
#include "cgroup-util.h"
#include "dns-domain.h"
#include "env-util.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#define DEFAULT_RATELIMIT_BURST 30
#define DEFAULT_RATELIMIT_INTERVAL_USEC (1*USEC_PER_MINUTE)
+#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
+static int parse_alloc_uid(const char *path, const char *name, const char *t, uid_t *ret_uid) {
+ uid_t uid;
+ int r;
+
+ r = parse_uid(t, &uid);
+ if (r < 0)
+ return log_debug_errno(r, "%s: failed to parse %s %s, ignoring: %m", path, name, t);
+ if (uid == 0)
+ uid = 1;
+
+ *ret_uid = uid;
+ return 0;
+}
+#endif
+
+int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char *root) {
+ UGIDAllocationRange defs = {
+ .system_alloc_uid_min = SYSTEM_ALLOC_UID_MIN,
+ .system_uid_max = SYSTEM_UID_MAX,
+ .system_alloc_gid_min = SYSTEM_ALLOC_GID_MIN,
+ .system_gid_max = SYSTEM_GID_MAX,
+ };
+
+#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ if (!path)
+ path = "/etc/login.defs";
+
+ r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT, "re", &f, NULL);
+ if (r == -ENOENT)
+ goto assign;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to open %s: %m", path);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ char *t;
+
+ r = read_line(f, LINE_MAX, &line);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read %s: %m", path);
+ if (r == 0)
+ break;
+
+ if ((t = first_word(line, "SYS_UID_MIN")))
+ (void) parse_alloc_uid(path, "SYS_UID_MIN", t, &defs.system_alloc_uid_min);
+ else if ((t = first_word(line, "SYS_UID_MAX")))
+ (void) parse_alloc_uid(path, "SYS_UID_MAX", t, &defs.system_uid_max);
+ else if ((t = first_word(line, "SYS_GID_MIN")))
+ (void) parse_alloc_uid(path, "SYS_GID_MIN", t, &defs.system_alloc_gid_min);
+ else if ((t = first_word(line, "SYS_GID_MAX")))
+ (void) parse_alloc_uid(path, "SYS_GID_MAX", t, &defs.system_gid_max);
+ }
+
+ assign:
+ if (defs.system_alloc_uid_min > defs.system_uid_max) {
+ log_debug("%s: SYS_UID_MIN > SYS_UID_MAX, resetting.", path);
+ defs.system_alloc_uid_min = MIN(defs.system_uid_max - 1, (uid_t) SYSTEM_ALLOC_UID_MIN);
+ /* Look at sys_uid_max to make sure sys_uid_min..sys_uid_max remains a valid range. */
+ }
+ if (defs.system_alloc_gid_min > defs.system_gid_max) {
+ log_debug("%s: SYS_GID_MIN > SYS_GID_MAX, resetting.", path);
+ defs.system_alloc_gid_min = MIN(defs.system_gid_max - 1, (gid_t) SYSTEM_ALLOC_GID_MIN);
+ /* Look at sys_gid_max to make sure sys_gid_min..sys_gid_max remains a valid range. */
+ }
+#endif
+
+ *ret_defs = defs;
+ return 0;
+}
+
+const UGIDAllocationRange *acquire_ugid_allocation_range(void) {
+#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
+ static thread_local UGIDAllocationRange defs = {
+#else
+ static const UGIDAllocationRange defs = {
+#endif
+ .system_alloc_uid_min = SYSTEM_ALLOC_UID_MIN,
+ .system_uid_max = SYSTEM_UID_MAX,
+ .system_alloc_gid_min = SYSTEM_ALLOC_GID_MIN,
+ .system_gid_max = SYSTEM_GID_MAX,
+ };
+
+#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
+ /* This function will ignore failure to read the file, so it should only be called from places where
+ * we don't crucially depend on the answer. In other words, it's appropriate for journald, but
+ * probably not for sysusers. */
+
+ static thread_local bool initialized = false;
+
+ if (!initialized) {
+ (void) read_login_defs(&defs, NULL, NULL);
+ initialized = true;
+ }
+#endif
+
+ return &defs;
+}
+
+bool uid_is_system(uid_t uid) {
+ const UGIDAllocationRange *defs;
+ assert_se(defs = acquire_ugid_allocation_range());
+
+ return uid <= defs->system_uid_max;
+}
+
+bool gid_is_system(gid_t gid) {
+ const UGIDAllocationRange *defs;
+ assert_se(defs = acquire_ugid_allocation_range());
+
+ return gid <= defs->system_gid_max;
+}
+
UserRecord* user_record_new(void) {
UserRecord *h;
/* The default disk size to use when nothing else is specified, relative to free disk space */
#define USER_DISK_SIZE_DEFAULT_PERCENT 85
+bool uid_is_system(uid_t uid);
+bool gid_is_system(gid_t gid);
+
+static inline bool uid_is_dynamic(uid_t uid) {
+ return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX;
+}
+
+static inline bool gid_is_dynamic(gid_t gid) {
+ return uid_is_dynamic((uid_t) gid);
+}
+
+static inline bool uid_is_container(uid_t uid) {
+ return CONTAINER_UID_BASE_MIN <= uid && uid <= CONTAINER_UID_BASE_MAX;
+}
+
+static inline bool gid_is_container(gid_t gid) {
+ return uid_is_container((uid_t) gid);
+}
+
+typedef struct UGIDAllocationRange {
+ uid_t system_alloc_uid_min;
+ uid_t system_uid_max;
+ gid_t system_alloc_gid_min;
+ gid_t system_gid_max;
+} UGIDAllocationRange;
+
+int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char *root);
+const UGIDAllocationRange *acquire_ugid_allocation_range(void);
+
typedef enum UserDisposition {
USER_INTRINSIC, /* root and nobody */
USER_SYSTEM, /* statically allocated users for system services */
if (IN_SET(v->state, VARLINK_IDLE_CLIENT) && (v->write_disconnected || v->got_pollhup))
goto disconnect;
+ /* The server is still expecting to write more, but its write end is disconnected and it got a POLLHUP
+ * (i.e. from a disconnected client), so disconnect. */
+ if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE) && v->write_disconnected && v->got_pollhup)
+ goto disconnect;
+
return 0;
disconnect:
#define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
#define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
#define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
+#define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken"
r = add_connection_socket(context, nfd);
if (r < 0) {
- log_error_errno(r, "Failed to accept connection, ignoring: %m");
- safe_close(fd);
+ log_warning_errno(r, "Failed to accept connection, ignoring: %m");
+ safe_close(nfd);
}
}
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
- if (r < 0) {
- log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
- sd_event_exit(context->event, r);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m");
return 1;
}
r = set_ensure_put(&context->listen, NULL, source);
if (r < 0) {
- log_error_errno(r, "Failed to add source to set: %m");
sd_event_source_unref(source);
- return r;
+ return log_error_errno(r, "Failed to add source to set: %m");
}
+ r = sd_event_source_set_exit_on_failure(source, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable exit-on-failure logic: %m");
+
/* Set the watcher to oneshot in case other processes are also
* watching to accept(). */
r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-add-dependency.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int add_dependency(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **names = NULL;
+ _cleanup_free_ char *target = NULL;
+ const char *verb = argv[0];
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0;
+ UnitDependency dep;
+ int r;
+
+ if (!argv[1])
+ return 0;
+
+ r = unit_name_mangle_with_suffix(argv[1], "as target",
+ arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
+ ".target", &target);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ r = mangle_names("as dependency", strv_skip(argv, 2), &names);
+ if (r < 0)
+ return r;
+
+ if (streq(verb, "add-wants"))
+ dep = UNIT_WANTS;
+ else if (streq(verb, "add-requires"))
+ dep = UNIT_REQUIRES;
+ else
+ assert_not_reached("Unknown verb");
+
+ if (install_client_side()) {
+ r = unit_file_add_dependency(arg_scope, unit_file_flags_from_args(), arg_root, names, target, dep, &changes, &n_changes);
+ unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
+
+ if (r > 0)
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "AddDependencyUnitFiles");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, names);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
+ 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 add dependency: %s", bus_error_message(&error, r));
+
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
+ if (r < 0)
+ goto finish;
+
+ if (arg_no_reload) {
+ r = 0;
+ goto finish;
+ }
+
+ r = daemon_reload(argc, argv, userdata);
+ }
+
+finish:
+ unit_file_changes_free(changes, n_changes);
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int add_dependency(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "parse-util.h"
+#include "systemctl-cancel-job.h"
+#include "systemctl-trivial-method.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int cancel_job(int argc, char *argv[], void *userdata) {
+ sd_bus *bus;
+ char **name;
+ int r;
+
+ if (argc <= 1) /* Shortcut to trivial_method() if no argument is given */
+ return trivial_method(argc, argv, userdata);
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ STRV_FOREACH(name, strv_skip(argv, 1)) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ uint32_t id;
+ int q;
+
+ q = safe_atou32(*name, &id);
+ if (q < 0)
+ return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
+
+ q = bus_call_method(bus, bus_systemd_mgr, "CancelJob", &error, NULL, "u", id);
+ if (q < 0) {
+ log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
+ if (r == 0)
+ r = q;
+ }
+ }
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int cancel_job(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "bus-wait-for-units.h"
+#include "systemctl-clean-or-freeze.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int clean_or_freeze_unit(int argc, char *argv[], void *userdata) {
+ _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *w = NULL;
+ _cleanup_strv_free_ char **names = NULL;
+ int r, ret = EXIT_SUCCESS;
+ char **name;
+ const char *method;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ if (!arg_clean_what) {
+ arg_clean_what = strv_new("cache", "runtime");
+ if (!arg_clean_what)
+ return log_oom();
+ }
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ if (!arg_no_block) {
+ r = bus_wait_for_units_new(bus, &w);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate unit waiter: %m");
+ }
+
+ if (streq(argv[0], "clean"))
+ method = "CleanUnit";
+ else if (streq(argv[0], "freeze"))
+ method = "FreezeUnit";
+ else if (streq(argv[0], "thaw"))
+ method = "ThawUnit";
+ else
+ assert_not_reached("Unhandled method");
+
+ STRV_FOREACH(name, names) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+
+ if (w) {
+ /* If we shall wait for the cleaning to complete, let's add a ref on the unit first */
+ r = bus_call_method(bus, bus_systemd_mgr, "RefUnit", &error, NULL, "s", *name);
+ if (r < 0) {
+ log_error_errno(r, "Failed to add reference to unit %s: %s", *name, bus_error_message(&error, r));
+ if (ret == EXIT_SUCCESS)
+ ret = r;
+ continue;
+ }
+ }
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "s", *name);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (streq(method, "CleanUnit")) {
+ r = sd_bus_message_append_strv(m, arg_clean_what);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_call(bus, m, 0, &error, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to %s unit %s: %s", argv[0], *name, bus_error_message(&error, r));
+ if (ret == EXIT_SUCCESS) {
+ ret = r;
+ continue;
+ }
+ }
+
+ if (w) {
+ r = bus_wait_for_units_add_unit(w, *name, BUS_WAIT_REFFED|BUS_WAIT_FOR_MAINTENANCE_END, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch unit %s: %m", *name);
+ }
+ }
+
+ r = bus_wait_for_units_run(w);
+ if (r < 0)
+ return log_error_errno(r, "Failed to wait for units: %m");
+ if (r == BUS_WAIT_FAILURE)
+ ret = EXIT_FAILURE;
+
+ return ret;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int clean_or_freeze_unit(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "sd-daemon.h"
+
+#include "alloc-util.h"
+#include "pretty-print.h"
+#include "process-util.h"
+#include "reboot-util.h"
+#include "systemctl-compat-halt.h"
+#include "systemctl-compat-telinit.h"
+#include "systemctl-logind.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "utmp-wtmp.h"
+
+static int halt_help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("halt", "8", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...]%s\n"
+ "\n%s%s the system.%s\n"
+ "\nOptions:\n"
+ " --help Show this help\n"
+ " --halt Halt the machine\n"
+ " -p --poweroff Switch off the machine\n"
+ " --reboot Reboot the machine\n"
+ " -f --force Force immediate halt/power-off/reboot\n"
+ " -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
+ );
+
+ return 0;
+}
+
+int halt_parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_HELP = 0x100,
+ ARG_HALT,
+ ARG_REBOOT,
+ ARG_NO_WALL
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, ARG_HELP },
+ { "halt", no_argument, NULL, ARG_HALT },
+ { "poweroff", no_argument, NULL, 'p' },
+ { "reboot", no_argument, NULL, ARG_REBOOT },
+ { "force", no_argument, NULL, 'f' },
+ { "wtmp-only", no_argument, NULL, 'w' },
+ { "no-wtmp", no_argument, NULL, 'd' },
+ { "no-sync", no_argument, NULL, 'n' },
+ { "no-wall", no_argument, NULL, ARG_NO_WALL },
+ {}
+ };
+
+ int c, r, runlevel;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ if (utmp_get_runlevel(&runlevel, NULL) >= 0)
+ if (IN_SET(runlevel, '0', '6'))
+ arg_force = 2;
+
+ while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
+ switch (c) {
+
+ case ARG_HELP:
+ return halt_help();
+
+ case ARG_HALT:
+ arg_action = ACTION_HALT;
+ break;
+
+ case 'p':
+ if (arg_action != ACTION_REBOOT)
+ arg_action = ACTION_POWEROFF;
+ break;
+
+ case ARG_REBOOT:
+ arg_action = ACTION_REBOOT;
+ break;
+
+ case 'f':
+ arg_force = 2;
+ break;
+
+ case 'w':
+ arg_dry_run = true;
+ break;
+
+ case 'd':
+ arg_no_wtmp = true;
+ break;
+
+ case 'n':
+ arg_no_sync = true;
+ break;
+
+ case ARG_NO_WALL:
+ arg_no_wall = true;
+ break;
+
+ case 'i':
+ case 'h':
+ /* Compatibility nops */
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
+ r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL, false);
+ if (r < 0)
+ return r;
+ } else if (optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Too many arguments.");
+
+ return 1;
+}
+
+int halt_main(void) {
+ int r;
+
+ r = logind_check_inhibitors(arg_action);
+ if (r < 0)
+ return r;
+
+ /* Delayed shutdown requested, and was successful */
+ if (arg_when > 0 && logind_schedule_shutdown() == 0)
+ return 0;
+
+ /* No delay, or logind failed or is not at all available */
+ if (geteuid() != 0) {
+ if (arg_dry_run || arg_force > 0) {
+ (void) must_be_root();
+ return -EPERM;
+ }
+
+ /* Try logind if we are a normal user and no special mode applies. Maybe polkit allows us to
+ * shutdown the machine. */
+ if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
+ r = logind_reboot(arg_action);
+ if (r >= 0)
+ return r;
+ if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+ /* Requested operation is not supported on the local system or already in
+ * progress */
+ return r;
+
+ /* on all other errors, try low-level operation */
+ }
+ }
+
+ /* In order to minimize the difference between operation with and without logind, we explicitly
+ * enable non-blocking mode for this, as logind's shutdown operations are always non-blocking. */
+ arg_no_block = true;
+
+ if (!arg_dry_run && !arg_force)
+ return start_with_fallback();
+
+ assert(geteuid() == 0);
+
+ if (!arg_no_wtmp) {
+ if (sd_booted() > 0)
+ log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
+ else {
+ r = utmp_put_shutdown();
+ if (r < 0)
+ log_warning_errno(r, "Failed to write utmp record: %m");
+ }
+ }
+
+ if (arg_dry_run)
+ return 0;
+
+ r = halt_now(arg_action);
+ return log_error_errno(r, "Failed to reboot: %m");
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int halt_parse_argv(int argc, char *argv[]);
+
+int halt_main(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+
+#include "alloc-util.h"
+#include "pretty-print.h"
+#include "systemctl-compat-runlevel.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "utmp-wtmp.h"
+
+static int runlevel_help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("runlevel", "8", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...]\n"
+ "\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
+ );
+
+ return 0;
+}
+
+int runlevel_parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_HELP = 0x100,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, ARG_HELP },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
+ switch (c) {
+
+ case ARG_HELP:
+ return runlevel_help();
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (optind < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Too many arguments.");
+
+ return 1;
+}
+
+int runlevel_main(void) {
+ int r, runlevel, previous;
+
+ r = utmp_get_runlevel(&runlevel, &previous);
+ if (r < 0) {
+ puts("unknown");
+ return r;
+ }
+
+ printf("%c %c\n",
+ previous <= 0 ? 'N' : previous,
+ runlevel <= 0 ? 'N' : runlevel);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int runlevel_parse_argv(int argc, char *argv[]);
+
+int runlevel_main(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+
+#include "alloc-util.h"
+#include "pretty-print.h"
+#include "systemctl-compat-shutdown.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static int shutdown_help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("shutdown", "8", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...] [TIME] [WALL...]\n"
+ "\n%sShut down the system.%s\n"
+ "\nOptions:\n"
+ " --help Show this help\n"
+ " -H --halt Halt the machine\n"
+ " -P --poweroff Power-off the machine\n"
+ " -r --reboot Reboot the machine\n"
+ " -h Equivalent to --poweroff, overridden by --halt\n"
+ " -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
+ );
+
+ return 0;
+}
+
+int shutdown_parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_HELP = 0x100,
+ ARG_NO_WALL
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, ARG_HELP },
+ { "halt", no_argument, NULL, 'H' },
+ { "poweroff", no_argument, NULL, 'P' },
+ { "reboot", no_argument, NULL, 'r' },
+ { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
+ { "no-wall", no_argument, NULL, ARG_NO_WALL },
+ {}
+ };
+
+ char **wall = NULL;
+ int c, r;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0)
+ switch (c) {
+
+ case ARG_HELP:
+ return shutdown_help();
+
+ case 'H':
+ arg_action = ACTION_HALT;
+ break;
+
+ case 'P':
+ arg_action = ACTION_POWEROFF;
+ break;
+
+ case 'r':
+ if (kexec_loaded())
+ arg_action = ACTION_KEXEC;
+ else
+ arg_action = ACTION_REBOOT;
+ break;
+
+ case 'K':
+ arg_action = ACTION_KEXEC;
+ break;
+
+ case 'h':
+ if (arg_action != ACTION_HALT)
+ arg_action = ACTION_POWEROFF;
+ break;
+
+ case 'k':
+ arg_dry_run = true;
+ break;
+
+ case ARG_NO_WALL:
+ arg_no_wall = true;
+ break;
+
+ case 'a':
+ case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
+ case 'f':
+ case 'F':
+ /* Compatibility nops */
+ break;
+
+ case 'c':
+ arg_action = ACTION_CANCEL_SHUTDOWN;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
+ r = parse_shutdown_time_spec(argv[optind], &arg_when);
+ if (r < 0) {
+ log_error("Failed to parse time specification: %s", argv[optind]);
+ return r;
+ }
+ } else
+ arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
+
+ if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
+ /* No time argument for shutdown cancel */
+ wall = argv + optind;
+ else if (argc > optind + 1)
+ /* We skip the time argument */
+ wall = argv + optind + 1;
+
+ if (wall) {
+ arg_wall = strv_copy(wall);
+ if (!arg_wall)
+ return log_oom();
+ }
+
+ optind = argc;
+
+ return 1;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int shutdown_parse_argv(int argc, char *argv[]);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+
+#include "alloc-util.h"
+#include "pretty-print.h"
+#include "systemctl-compat-telinit.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static int telinit_help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("telinit", "8", &link);
+ if (r < 0)
+ return log_oom();
+
+ printf("%s [OPTIONS...] COMMAND\n\n"
+ "%sSend control commands to the init daemon.%s\n"
+ "\nCommands:\n"
+ " 0 Power-off the machine\n"
+ " 6 Reboot the machine\n"
+ " 2, 3, 4, 5 Start runlevelX.target unit\n"
+ " 1, s, S Enter rescue mode\n"
+ " q, Q Reload init daemon configuration\n"
+ " u, U Reexecute init daemon\n"
+ "\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
+ );
+
+ return 0;
+}
+
+int telinit_parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_HELP = 0x100,
+ ARG_NO_WALL
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, ARG_HELP },
+ { "no-wall", no_argument, NULL, ARG_NO_WALL },
+ {}
+ };
+
+ static const struct {
+ char from;
+ enum action to;
+ } table[] = {
+ { '0', ACTION_POWEROFF },
+ { '6', ACTION_REBOOT },
+ { '1', ACTION_RESCUE },
+ { '2', ACTION_RUNLEVEL2 },
+ { '3', ACTION_RUNLEVEL3 },
+ { '4', ACTION_RUNLEVEL4 },
+ { '5', ACTION_RUNLEVEL5 },
+ { 's', ACTION_RESCUE },
+ { 'S', ACTION_RESCUE },
+ { 'q', ACTION_RELOAD },
+ { 'Q', ACTION_RELOAD },
+ { 'u', ACTION_REEXEC },
+ { 'U', ACTION_REEXEC }
+ };
+
+ unsigned i;
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
+ switch (c) {
+
+ case ARG_HELP:
+ return telinit_help();
+
+ case ARG_NO_WALL:
+ arg_no_wall = true;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (optind >= argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: required argument missing.",
+ program_invocation_short_name);
+
+ if (optind + 1 < argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Too many arguments.");
+
+ if (strlen(argv[optind]) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Expected single character argument.");
+
+ for (i = 0; i < ELEMENTSOF(table); i++)
+ if (table[i].from == argv[optind][0])
+ break;
+
+ if (i >= ELEMENTSOF(table))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown command '%s'.", argv[optind]);
+
+ arg_action = table[i].to;
+
+ optind++;
+
+ return 1;
+}
+
+int start_with_fallback(void) {
+ /* First, try systemd via D-Bus. */
+ if (start_unit(0, NULL, NULL) == 0)
+ return 0;
+
+#if HAVE_SYSV_COMPAT
+ /* Nothing else worked, so let's try /dev/initctl */
+ if (talk_initctl(action_to_runlevel()) > 0)
+ return 0;
+#endif
+
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Failed to talk to init daemon.");
+}
+
+int reload_with_fallback(void) {
+ /* First, try systemd via D-Bus. */
+ if (daemon_reload(0, NULL, NULL) >= 0)
+ return 0;
+
+ /* Nothing else worked, so let's try signals */
+ assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
+
+ if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
+ return log_error_errno(errno, "kill() failed: %m");
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int telinit_parse_argv(int argc, char *argv[]);
+int start_with_fallback(void);
+int reload_with_fallback(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int daemon_reload(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ const char *method;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ switch (arg_action) {
+
+ case ACTION_RELOAD:
+ method = "Reload";
+ break;
+
+ case ACTION_REEXEC:
+ method = "Reexecute";
+ break;
+
+ case ACTION_SYSTEMCTL:
+ method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
+ /* "daemon-reload" */ "Reload";
+ break;
+
+ default:
+ assert_not_reached("Unexpected action");
+ }
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are
+ * rerun which are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the
+ * generators can have their timeout, and for everything else there's the same time budget in
+ * place. */
+
+ r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+
+ /* On reexecution, we expect a disconnect, not a reply */
+ if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
+ r = 0;
+
+ if (r < 0 && arg_action == ACTION_SYSTEMCTL)
+ return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
+
+ /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support
+ * fallbacks to the old ways of doing things, hence don't log any error in that case here. */
+
+ return r < 0 ? r : 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int daemon_reload(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "copy.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "mkdir.h"
+#include "pager.h"
+#include "path-util.h"
+#include "pretty-print.h"
+#include "process-util.h"
+#include "selinux-util.h"
+#include "stat-util.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-edit.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "tmpfile-util.h"
+
+#define EDIT_MARKER_START "### Anything between here and the comment below will become the new contents of the file"
+#define EDIT_MARKER_END "### Lines below this comment will be discarded"
+
+int cat(int argc, char *argv[], void *userdata) {
+ _cleanup_(hashmap_freep) Hashmap *cached_name_map = NULL, *cached_id_map = NULL;
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
+ _cleanup_strv_free_ char **names = NULL;
+ char **name;
+ sd_bus *bus;
+ bool first = true;
+ int r, rc = 0;
+
+ /* Include all units by default — i.e. continue as if the --all option was used */
+ if (strv_isempty(arg_states))
+ arg_all = true;
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot remotely cat units.");
+
+ r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine unit paths: %m");
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ r = maybe_extend_with_unit_dependencies(bus, &names);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ STRV_FOREACH(name, names) {
+ _cleanup_free_ char *fragment_path = NULL;
+ _cleanup_strv_free_ char **dropin_paths = NULL;
+
+ r = unit_find_paths(bus, *name, &lp, false, &cached_name_map, &cached_id_map, &fragment_path, &dropin_paths);
+ if (r == -ERFKILL) {
+ printf("%s# Unit %s is masked%s.\n",
+ ansi_highlight_magenta(),
+ *name,
+ ansi_normal());
+ continue;
+ }
+ if (r == -EKEYREJECTED) {
+ printf("%s# Unit %s could not be loaded.%s\n",
+ ansi_highlight_magenta(),
+ *name,
+ ansi_normal());
+ continue;
+ }
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ /* Skip units which have no on-disk counterpart, but propagate the error to the
+ * user */
+ rc = -ENOENT;
+ continue;
+ }
+
+ if (first)
+ first = false;
+ else
+ puts("");
+
+ if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
+ fprintf(stderr,
+ "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
+ "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
+ "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
+ "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
+ ansi_highlight_red(),
+ *name,
+ ansi_highlight_red(),
+ ansi_highlight_red(),
+ ansi_highlight_red(),
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ ansi_normal());
+
+ r = cat_files(fragment_path, dropin_paths, 0);
+ if (r < 0)
+ return r;
+ }
+
+ return rc;
+}
+
+static int create_edit_temp_file(const char *new_path, const char *original_path, char ** const original_unit_paths, char **ret_tmp_fn) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(new_path);
+ assert(ret_tmp_fn);
+
+ r = tempfn_random(new_path, NULL, &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
+
+ r = mkdir_parents_label(new_path, 0755);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
+
+ if (original_path) {
+ r = mac_selinux_create_file_prepare(new_path, S_IFREG);
+ if (r < 0)
+ return r;
+
+ r = copy_file(original_path, t, 0, 0644, 0, 0, COPY_REFLINK);
+ if (r == -ENOENT) {
+ r = touch(t);
+ mac_selinux_create_file_clear();
+ if (r < 0)
+ return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
+ } else {
+ mac_selinux_create_file_clear();
+ if (r < 0)
+ return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
+ }
+ } else if (original_unit_paths) {
+ _cleanup_free_ char *new_contents = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ char **path;
+ size_t size;
+
+ r = mac_selinux_create_file_prepare(new_path, S_IFREG);
+ if (r < 0)
+ return r;
+
+ f = fopen(t, "we");
+ mac_selinux_create_file_clear();
+ if (!f)
+ return log_error_errno(errno, "Failed to open \"%s\": %m", t);
+
+ r = fchmod(fileno(f), 0644);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to change mode of \"%s\": %m", t);
+
+ r = read_full_file(new_path, &new_contents, &size);
+ if (r < 0 && r != -ENOENT)
+ return log_error_errno(r, "Failed to read \"%s\": %m", new_path);
+
+ fprintf(f,
+ "### Editing %s\n"
+ EDIT_MARKER_START
+ "\n\n%s%s\n"
+ EDIT_MARKER_END,
+ new_path,
+ strempty(new_contents),
+ new_contents && endswith(new_contents, "\n") ? "" : "\n");
+
+ /* Add a comment with the contents of the original unit files */
+ STRV_FOREACH(path, original_unit_paths) {
+ _cleanup_free_ char *contents = NULL;
+
+ /* Skip the file that's being edited */
+ if (path_equal(*path, new_path))
+ continue;
+
+ r = read_full_file(*path, &contents, &size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read \"%s\": %m", *path);
+
+ fprintf(f, "\n\n### %s", *path);
+ if (!isempty(contents)) {
+ contents = strreplace(strstrip(contents), "\n", "\n# ");
+ if (!contents)
+ return log_oom();
+ fprintf(f, "\n# %s", contents);
+ }
+ }
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
+ }
+
+ *ret_tmp_fn = TAKE_PTR(t);
+
+ return 0;
+}
+
+static int get_file_to_edit(
+ const LookupPaths *paths,
+ const char *name,
+ char **ret_path) {
+
+ _cleanup_free_ char *path = NULL, *run = NULL;
+
+ assert(name);
+ assert(ret_path);
+
+ path = path_join(paths->persistent_config, name);
+ if (!path)
+ return log_oom();
+
+ if (arg_runtime) {
+ run = path_join(paths->runtime_config, name);
+ if (!run)
+ return log_oom();
+ }
+
+ if (arg_runtime) {
+ if (access(path, F_OK) >= 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
+ run, path);
+
+ *ret_path = TAKE_PTR(run);
+ } else
+ *ret_path = TAKE_PTR(path);
+
+ return 0;
+}
+
+static int unit_file_create_new(
+ const LookupPaths *paths,
+ const char *unit_name,
+ const char *suffix,
+ char ** const original_unit_paths,
+ char **ret_new_path,
+ char **ret_tmp_path) {
+
+ _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
+ const char *ending;
+ int r;
+
+ assert(unit_name);
+ assert(ret_new_path);
+ assert(ret_tmp_path);
+
+ ending = strjoina(unit_name, suffix);
+ r = get_file_to_edit(paths, ending, &new_path);
+ if (r < 0)
+ return r;
+
+ r = create_edit_temp_file(new_path, NULL, original_unit_paths, &tmp_path);
+ if (r < 0)
+ return r;
+
+ *ret_new_path = TAKE_PTR(new_path);
+ *ret_tmp_path = TAKE_PTR(tmp_path);
+
+ return 0;
+}
+
+static int unit_file_create_copy(
+ const LookupPaths *paths,
+ const char *unit_name,
+ const char *fragment_path,
+ char **ret_new_path,
+ char **ret_tmp_path) {
+
+ _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
+ int r;
+
+ assert(fragment_path);
+ assert(unit_name);
+ assert(ret_new_path);
+ assert(ret_tmp_path);
+
+ r = get_file_to_edit(paths, unit_name, &new_path);
+ if (r < 0)
+ return r;
+
+ if (!path_equal(fragment_path, new_path) && access(new_path, F_OK) >= 0) {
+ char response;
+
+ r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", new_path, fragment_path);
+ if (r < 0)
+ return r;
+ if (response != 'y')
+ return log_warning_errno(SYNTHETIC_ERRNO(EKEYREJECTED), "%s skipped.", unit_name);
+ }
+
+ r = create_edit_temp_file(new_path, fragment_path, NULL, &tmp_path);
+ if (r < 0)
+ return r;
+
+ *ret_new_path = TAKE_PTR(new_path);
+ *ret_tmp_path = TAKE_PTR(tmp_path);
+
+ return 0;
+}
+
+static int run_editor(char **paths) {
+ int r;
+
+ assert(paths);
+
+ r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ char **editor_args = NULL, **tmp_path, **original_path;
+ size_t n_editor_args = 0, i = 1, argc;
+ const char **args, *editor, *p;
+
+ argc = strv_length(paths)/2 + 1;
+
+ /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL. If
+ * neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present, we try to execute well known
+ * editors. */
+ editor = getenv("SYSTEMD_EDITOR");
+ if (!editor)
+ editor = getenv("EDITOR");
+ if (!editor)
+ editor = getenv("VISUAL");
+
+ if (!isempty(editor)) {
+ editor_args = strv_split(editor, WHITESPACE);
+ if (!editor_args) {
+ (void) log_oom();
+ _exit(EXIT_FAILURE);
+ }
+ n_editor_args = strv_length(editor_args);
+ argc += n_editor_args - 1;
+ }
+
+ args = newa(const char*, argc + 1);
+
+ if (n_editor_args > 0) {
+ args[0] = editor_args[0];
+ for (; i < n_editor_args; i++)
+ args[i] = editor_args[i];
+ }
+
+ STRV_FOREACH_PAIR(original_path, tmp_path, paths)
+ args[i++] = *tmp_path;
+ args[i] = NULL;
+
+ if (n_editor_args > 0)
+ execvp(args[0], (char* const*) args);
+
+ FOREACH_STRING(p, "editor", "nano", "vim", "vi") {
+ args[0] = p;
+ execvp(p, (char* const*) args);
+ /* We do not fail if the editor doesn't exist because we want to try each one of them
+ * before failing. */
+ if (errno != ENOENT) {
+ log_error_errno(errno, "Failed to execute %s: %m", editor);
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
+ _exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
+
+static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
+ _cleanup_(hashmap_freep) Hashmap *cached_name_map = NULL, *cached_id_map = NULL;
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
+ char **name;
+ int r;
+
+ assert(names);
+ assert(paths);
+
+ r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(name, names) {
+ _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL;
+ _cleanup_strv_free_ char **unit_paths = NULL;
+ const char *unit_name;
+
+ r = unit_find_paths(bus, *name, &lp, false, &cached_name_map, &cached_id_map, &path, &unit_paths);
+ if (r == -EKEYREJECTED) {
+ /* If loading of the unit failed server side complete, then the server won't tell us
+ * the unit file path. In that case, find the file client side. */
+ log_debug_errno(r, "Unit '%s' was not loaded correctly, retrying client-side.", *name);
+ r = unit_find_paths(bus, *name, &lp, true, &cached_name_map, &cached_id_map, &path, NULL);
+ }
+ if (r == -ERFKILL)
+ return log_error_errno(r, "Unit '%s' masked, cannot edit.", *name);
+ if (r < 0)
+ return r;
+
+ if (r == 0) {
+ assert(!path);
+
+ if (!arg_force) {
+ log_info("Run 'systemctl edit%s --force --full %s' to create a new unit.",
+ arg_scope == UNIT_FILE_GLOBAL ? " --global" :
+ arg_scope == UNIT_FILE_USER ? " --user" : "",
+ *name);
+ return -ENOENT;
+ }
+
+ /* Create a new unit from scratch */
+ unit_name = *name;
+ r = unit_file_create_new(&lp, unit_name,
+ arg_full ? NULL : ".d/override.conf",
+ NULL, &new_path, &tmp_path);
+ } else {
+ assert(path);
+
+ unit_name = basename(path);
+ /* We follow unit aliases, but we need to propagate the instance */
+ if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) &&
+ unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
+ _cleanup_free_ char *instance = NULL;
+
+ r = unit_name_to_instance(*name, &instance);
+ if (r < 0)
+ return r;
+
+ r = unit_name_replace_instance(unit_name, instance, &tmp_name);
+ if (r < 0)
+ return r;
+
+ unit_name = tmp_name;
+ }
+
+ if (arg_full)
+ r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path);
+ else {
+ r = strv_prepend(&unit_paths, path);
+ if (r < 0)
+ return log_oom();
+
+ r = unit_file_create_new(&lp, unit_name, ".d/override.conf", unit_paths, &new_path, &tmp_path);
+ }
+ }
+ if (r < 0)
+ return r;
+
+ r = strv_push_pair(paths, new_path, tmp_path);
+ if (r < 0)
+ return log_oom();
+
+ new_path = tmp_path = NULL;
+ }
+
+ return 0;
+}
+
+static int trim_edit_markers(const char *path) {
+ _cleanup_free_ char *contents = NULL;
+ char *contents_start = NULL;
+ const char *contents_end = NULL;
+ size_t size;
+ int r;
+
+ /* Trim out the lines between the two markers */
+ r = read_full_file(path, &contents, &size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read temporary file \"%s\": %m", path);
+
+ contents_start = strstr(contents, EDIT_MARKER_START);
+ if (contents_start)
+ contents_start += strlen(EDIT_MARKER_START);
+ else
+ contents_start = contents;
+
+ contents_end = strstr(contents_start, EDIT_MARKER_END);
+ if (contents_end)
+ strshorten(contents_start, contents_end - contents_start);
+
+ contents_start = strstrip(contents_start);
+
+ /* Write new contents if the trimming actually changed anything */
+ if (strlen(contents) != size) {
+ r = write_string_file(path, contents_start, WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_TRUNCATE | WRITE_STRING_FILE_AVOID_NEWLINE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to modify temporary file \"%s\": %m", path);
+ }
+
+ return 0;
+}
+
+int edit(int argc, char *argv[], void *userdata) {
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
+ _cleanup_strv_free_ char **names = NULL;
+ _cleanup_strv_free_ char **paths = NULL;
+ char **original, **tmp;
+ sd_bus *bus;
+ int r;
+
+ if (!on_tty())
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units if not on a tty.");
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units remotely.");
+
+ r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine unit paths: %m");
+
+ r = mac_selinux_init();
+ if (r < 0)
+ return r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ STRV_FOREACH(tmp, names) {
+ r = unit_is_masked(bus, &lp, *tmp);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit %s: unit is masked.", *tmp);
+ }
+
+ r = find_paths_to_edit(bus, names, &paths);
+ if (r < 0)
+ return r;
+
+ if (strv_isempty(paths))
+ return -ENOENT;
+
+ r = run_editor(paths);
+ if (r < 0)
+ goto end;
+
+ STRV_FOREACH_PAIR(original, tmp, paths) {
+ /* If the temporary file is empty we ignore it. This allows the user to cancel the
+ * modification. */
+ r = trim_edit_markers(*tmp);
+ if (r < 0)
+ continue;
+
+ if (null_or_empty_path(*tmp)) {
+ log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
+ continue;
+ }
+
+ r = rename(*tmp, *original);
+ if (r < 0) {
+ r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
+ goto end;
+ }
+ }
+
+ r = 0;
+
+ if (!arg_no_reload && !install_client_side())
+ r = daemon_reload(argc, argv, userdata);
+
+end:
+ STRV_FOREACH_PAIR(original, tmp, paths) {
+ (void) unlink(*tmp);
+
+ /* Removing empty dropin dirs */
+ if (!arg_full) {
+ _cleanup_free_ char *dir;
+
+ dir = dirname_malloc(*original);
+ if (!dir)
+ return log_oom();
+
+ /* No need to check if the dir is empty, rmdir does nothing if it is not the case. */
+ (void) rmdir(dir);
+ }
+ }
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int cat(int argc, char *argv[], void *userdata);
+int edit(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "locale-util.h"
+#include "path-util.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-enable.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int normalize_filenames(char **names) {
+ char **u;
+ int r;
+
+ STRV_FOREACH(u, names)
+ if (!path_is_absolute(*u)) {
+ char* normalized_path;
+
+ if (!isempty(arg_root))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Non-absolute paths are not allowed when --root is used: %s",
+ *u);
+
+ if (!strchr(*u,'/'))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Link argument does contain at least one directory separator: %s",
+ *u);
+
+ r = path_make_absolute_cwd(*u, &normalized_path);
+ if (r < 0)
+ return r;
+
+ free_and_replace(*u, normalized_path);
+ }
+
+ return 0;
+}
+
+static int normalize_names(char **names, bool warn_if_path) {
+ char **u;
+ bool was_path = false;
+
+ STRV_FOREACH(u, names) {
+ int r;
+
+ if (!is_path(*u))
+ continue;
+
+ r = free_and_strdup(u, basename(*u));
+ if (r < 0)
+ return log_error_errno(r, "Failed to normalize unit file path: %m");
+
+ was_path = true;
+ }
+
+ if (warn_if_path && was_path)
+ log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
+
+ return 0;
+}
+
+int enable_unit(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **names = NULL;
+ const char *verb = argv[0];
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0;
+ int carries_install_info = -1;
+ bool ignore_carries_install_info = arg_quiet;
+ int r;
+
+ if (!argv[1])
+ return 0;
+
+ r = mangle_names("to enable", strv_skip(argv, 1), &names);
+ if (r < 0)
+ return r;
+
+ r = enable_sysv_units(verb, names);
+ if (r < 0)
+ return r;
+
+ /* If the operation was fully executed by the SysV compat, let's finish early */
+ if (strv_isempty(names)) {
+ if (arg_no_reload || install_client_side())
+ return 0;
+ return daemon_reload(argc, argv, userdata);
+ }
+
+ if (streq(verb, "disable")) {
+ r = normalize_names(names, true);
+ if (r < 0)
+ return r;
+ }
+
+ if (streq(verb, "link")) {
+ r = normalize_filenames(names);
+ if (r < 0)
+ return r;
+ }
+
+ if (install_client_side()) {
+ UnitFileFlags flags;
+
+ flags = unit_file_flags_from_args();
+ if (streq(verb, "enable")) {
+ r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ carries_install_info = r;
+ } else if (streq(verb, "disable"))
+ r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ else if (streq(verb, "reenable")) {
+ r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ carries_install_info = r;
+ } else if (streq(verb, "link"))
+ r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ else if (streq(verb, "preset")) {
+ r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
+ } else if (streq(verb, "mask"))
+ r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ else if (streq(verb, "unmask"))
+ r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
+ else if (streq(verb, "revert"))
+ r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
+ else
+ assert_not_reached("Unknown verb");
+
+ unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
+ if (r < 0)
+ goto finish;
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ bool expect_carries_install_info = false;
+ bool send_runtime = true, send_force = true, send_preset_mode = false;
+ const char *method;
+ sd_bus *bus;
+
+ if (STR_IN_SET(verb, "mask", "unmask")) {
+ char **name;
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
+
+ r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(name, names) {
+ r = unit_exists(&lp, *name);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ log_notice("Unit %s does not exist, proceeding anyway.", *name);
+ }
+ }
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ if (streq(verb, "enable")) {
+ method = "EnableUnitFiles";
+ expect_carries_install_info = true;
+ } else if (streq(verb, "disable")) {
+ method = "DisableUnitFiles";
+ send_force = false;
+ } else if (streq(verb, "reenable")) {
+ method = "ReenableUnitFiles";
+ expect_carries_install_info = true;
+ } else if (streq(verb, "link"))
+ method = "LinkUnitFiles";
+ else if (streq(verb, "preset")) {
+
+ if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
+ method = "PresetUnitFilesWithMode";
+ send_preset_mode = true;
+ } else
+ method = "PresetUnitFiles";
+
+ expect_carries_install_info = true;
+ ignore_carries_install_info = true;
+ } else if (streq(verb, "mask"))
+ method = "MaskUnitFiles";
+ else if (streq(verb, "unmask")) {
+ method = "UnmaskUnitFiles";
+ send_force = false;
+ } else if (streq(verb, "revert")) {
+ method = "RevertUnitFiles";
+ send_runtime = send_force = false;
+ } else
+ assert_not_reached("Unknown verb");
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, names);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (send_preset_mode) {
+ r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ if (send_runtime) {
+ r = sd_bus_message_append(m, "b", arg_runtime);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ if (send_force) {
+ r = sd_bus_message_append(m, "b", arg_force);
+ 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 %s unit: %s", verb, bus_error_message(&error, r));
+
+ if (expect_carries_install_info) {
+ r = sd_bus_message_read(reply, "b", &carries_install_info);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
+ if (r < 0)
+ goto finish;
+
+ /* Try to reload if enabled */
+ if (!arg_no_reload)
+ r = daemon_reload(argc, argv, userdata);
+ else
+ r = 0;
+ }
+
+ if (carries_install_info == 0 && !ignore_carries_install_info)
+ log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n"
+ "Alias= settings in the [Install] section, and DefaultInstance= for template\n"
+ "units). This means they are not meant to be enabled using systemctl.\n"
+ " \n" /* trick: the space is needed so that the line does not get stripped from output */
+ "Possible reasons for having this kind of units are:\n"
+ "%1$s A unit may be statically enabled by being symlinked from another unit's\n"
+ " .wants/ or .requires/ directory.\n"
+ "%1$s A unit's purpose may be to act as a helper for some other unit which has\n"
+ " a requirement dependency on it.\n"
+ "%1$s A unit may be started when needed via activation (socket, path, timer,\n"
+ " D-Bus, udev, scripted systemctl call, ...).\n"
+ "%1$s In case of template units, the unit is meant to be enabled with some\n"
+ " instance name specified.",
+ special_glyph(SPECIAL_GLYPH_BULLET));
+
+ if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
+ sd_bus *bus;
+ size_t len, i;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ goto finish;
+
+ len = strv_length(names);
+ {
+ char *new_args[len + 2];
+
+ new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
+ for (i = 0; i < len; i++)
+ new_args[i + 1] = basename(names[i]);
+ new_args[i + 1] = NULL;
+
+ r = start_unit(len + 1, new_args, userdata);
+ }
+ }
+
+finish:
+ unit_file_changes_free(changes, n_changes);
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int enable_unit(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "pretty-print.h"
+#include "syslog-util.h"
+#include "systemctl-is-active.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
+ _cleanup_strv_free_ char **names = NULL;
+ UnitActiveState active_state;
+ sd_bus *bus;
+ char **name;
+ int r, i;
+ bool found = false;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = expand_unit_names(bus, args, NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ STRV_FOREACH(name, names) {
+ r = get_state_one_unit(bus, *name, &active_state);
+ if (r < 0)
+ return r;
+
+ if (!arg_quiet)
+ puts(unit_active_state_to_string(active_state));
+
+ for (i = 0; i < nb_states; ++i)
+ if (good_states[i] == active_state)
+ found = true;
+ }
+
+ /* use the given return code for the case that we won't find
+ * any unit which matches the list */
+ return found ? 0 : code;
+}
+
+int check_unit_active(int argc, char *argv[], void *userdata) {
+ static const UnitActiveState states[] = {
+ UNIT_ACTIVE,
+ UNIT_RELOADING,
+ };
+
+ /* According to LSB: 3, "program is not running" */
+ return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
+}
+
+int check_unit_failed(int argc, char *argv[], void *userdata) {
+ static const UnitActiveState states[] = {
+ UNIT_FAILED,
+ };
+
+ return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int check_unit_active(int argc, char *argv[], void *userdata);
+int check_unit_failed(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-is-enabled.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int show_installation_targets_client_side(const char *name) {
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0, i;
+ UnitFileFlags flags;
+ char **p;
+ int r;
+
+ p = STRV_MAKE(name);
+ flags = UNIT_FILE_DRY_RUN |
+ (arg_runtime ? UNIT_FILE_RUNTIME : 0);
+
+ r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get file links for %s: %m", name);
+
+ for (i = 0; i < n_changes; i++)
+ if (changes[i].type == UNIT_FILE_UNLINK)
+ printf(" %s\n", changes[i].path);
+
+ return 0;
+}
+
+static int show_installation_targets(sd_bus *bus, const char *name) {
+ _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 *link;
+ int r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileLinks", &error, &reply, "sb", name, arg_runtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
+ printf(" %s\n", link);
+
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+int unit_is_enabled(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **names = NULL;
+ bool enabled;
+ char **name;
+ int r;
+
+ r = mangle_names("to check", strv_skip(argv, 1), &names);
+ if (r < 0)
+ return r;
+
+ r = enable_sysv_units(argv[0], names);
+ if (r < 0)
+ return r;
+
+ enabled = r > 0;
+
+ if (install_client_side()) {
+ STRV_FOREACH(name, names) {
+ UnitFileState state;
+
+ r = unit_file_get_state(arg_scope, arg_root, *name, &state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
+
+ if (IN_SET(state,
+ UNIT_FILE_ENABLED,
+ UNIT_FILE_ENABLED_RUNTIME,
+ UNIT_FILE_STATIC,
+ UNIT_FILE_ALIAS,
+ UNIT_FILE_INDIRECT,
+ UNIT_FILE_GENERATED))
+ enabled = true;
+
+ if (!arg_quiet) {
+ puts(unit_file_state_to_string(state));
+ if (arg_full) {
+ r = show_installation_targets_client_side(*name);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(name, names) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *s;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileState", &error, &reply, "s", *name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "s", &s);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
+ enabled = true;
+
+ if (!arg_quiet) {
+ puts(s);
+ if (arg_full) {
+ r = show_installation_targets(bus, *name);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+ }
+
+ return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int unit_is_enabled(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-event.h"
+#include "sd-daemon.h"
+
+#include "systemctl-util.h"
+#include "systemctl-is-system-running.h"
+#include "virt.h"
+#include "systemctl.h"
+#include "bus-util.h"
+#include "bus-locator.h"
+#include "bus-error.h"
+
+static int match_startup_finished(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ char **state = userdata;
+ int r;
+
+ assert(state);
+
+ r = bus_get_property_string(sd_bus_message_get_bus(m), bus_systemd_mgr, "SystemState", NULL, state);
+
+ sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), r);
+ return 0;
+}
+
+int is_system_running(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_startup_finished = NULL;
+ _cleanup_(sd_event_unrefp) sd_event* event = NULL;
+ _cleanup_free_ char *state = NULL;
+ sd_bus *bus;
+ int r;
+
+ if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
+ if (!arg_quiet)
+ puts("offline");
+ return EXIT_FAILURE;
+ }
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ if (arg_wait) {
+ r = sd_event_default(&event);
+ if (r >= 0)
+ r = sd_bus_attach_event(bus, event, 0);
+ if (r >= 0)
+ r = bus_match_signal_async(
+ bus,
+ &slot_startup_finished,
+ bus_systemd_mgr,
+ "StartupFinished",
+ match_startup_finished, NULL, &state);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to request match for StartupFinished: %m");
+ arg_wait = false;
+ }
+ }
+
+ r = bus_get_property_string(bus, bus_systemd_mgr, "SystemState", &error, &state);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to query system state: %s", bus_error_message(&error, r));
+
+ if (!arg_quiet)
+ puts("unknown");
+ return EXIT_FAILURE;
+ }
+
+ if (arg_wait && STR_IN_SET(state, "initializing", "starting")) {
+ r = sd_event_loop(event);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to get property from event loop: %m");
+ if (!arg_quiet)
+ puts("unknown");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (!arg_quiet)
+ puts(state);
+
+ return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int is_system_running(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-kill.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int kill_unit(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **names = NULL;
+ char *kill_who = NULL, **name;
+ sd_bus *bus;
+ int r, q;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ if (!arg_kill_who)
+ arg_kill_who = "all";
+
+ /* --fail was specified */
+ if (streq(arg_job_mode, "fail"))
+ kill_who = strjoina(arg_kill_who, "-fail");
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ STRV_FOREACH(name, names) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ q = bus_call_method(
+ bus,
+ bus_systemd_mgr,
+ "KillUnit",
+ &error,
+ NULL,
+ "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
+ if (q < 0) {
+ log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
+ if (r == 0)
+ r = q;
+ }
+ }
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int kill_unit(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "locale-util.h"
+#include "sort-util.h"
+#include "special.h"
+#include "systemctl-list-dependencies.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static int list_dependencies_print(const char *name, int level, unsigned branches, bool last) {
+ _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--) {
+ len += 2;
+ if (len > max_len - 3 && !arg_full) {
+ printf("%s...\n",max_len % 2 ? "" : " ");
+ return 0;
+ }
+ printf("%s", special_glyph(branches & (1 << i) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
+ }
+ len += 2;
+
+ if (len > max_len - 3 && !arg_full) {
+ printf("%s...\n",max_len % 2 ? "" : " ");
+ return 0;
+ }
+
+ printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
+ }
+
+ if (arg_full) {
+ printf("%s\n", name);
+ return 0;
+ }
+
+ n = ellipsize(name, max_len-len, 100);
+ if (!n)
+ return log_oom();
+
+ printf("%s\n", n);
+ return 0;
+}
+
+static int list_dependencies_compare(char * const *a, char * const *b) {
+ if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
+ return 1;
+ if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
+ return -1;
+
+ return strcasecmp(*a, *b);
+}
+
+static int list_dependencies_one(
+ sd_bus *bus,
+ const char *name,
+ int level,
+ char ***units,
+ unsigned branches) {
+
+ _cleanup_strv_free_ char **deps = NULL;
+ char **c;
+ int r;
+
+ assert(bus);
+ assert(name);
+ assert(units);
+
+ r = strv_extend(units, name);
+ if (r < 0)
+ return log_oom();
+
+ r = unit_get_dependencies(bus, name, &deps);
+ if (r < 0)
+ return r;
+
+ typesafe_qsort(deps, strv_length(deps), list_dependencies_compare);
+
+ STRV_FOREACH(c, deps) {
+ if (strv_contains(*units, *c)) {
+ if (!arg_plain) {
+ printf(" ");
+ r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
+ if (r < 0)
+ return r;
+ }
+ continue;
+ }
+
+ if (arg_plain)
+ printf(" ");
+ else {
+ UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
+ const char *on;
+
+ (void) get_state_one_unit(bus, *c, &active_state);
+
+ switch (active_state) {
+ case UNIT_ACTIVE:
+ case UNIT_RELOADING:
+ case UNIT_ACTIVATING:
+ on = ansi_highlight_green();
+ break;
+
+ case UNIT_INACTIVE:
+ case UNIT_DEACTIVATING:
+ on = ansi_normal();
+ break;
+
+ default:
+ on = ansi_highlight_red();
+ break;
+ }
+
+ printf("%s%s%s ", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), ansi_normal());
+ }
+
+ r = list_dependencies_print(*c, level, branches, c[1] == NULL);
+ if (r < 0)
+ return r;
+
+ if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
+ r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
+ if (r < 0)
+ return r;
+ }
+ }
+
+ if (!arg_plain)
+ strv_remove(*units, name);
+
+ return 0;
+}
+
+int list_dependencies(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **units = NULL, **done = NULL;
+ char **u, **patterns;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ patterns = strv_skip(argv, 1);
+ if (strv_isempty(patterns)) {
+ units = strv_new(SPECIAL_DEFAULT_TARGET);
+ if (!units)
+ return log_oom();
+ } else {
+ r = expand_unit_names(bus, patterns, NULL, &units, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+ }
+
+ (void) pager_open(arg_pager_flags);
+
+ STRV_FOREACH(u, units) {
+ if (u != units)
+ puts("");
+
+ puts(*u);
+ r = list_dependencies_one(bus, *u, 0, &done, 0);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int list_dependencies(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "locale-util.h"
+#include "systemctl-list-jobs.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static int output_waiting_jobs(sd_bus *bus, Table *table, uint32_t id, const char *method, const char *prefix) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *name, *type;
+ uint32_t other_id;
+ int r;
+
+ assert(bus);
+
+ r = bus_call_method(bus, bus_systemd_mgr, method, &error, &reply, "u", id);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id);
+
+ r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0) {
+ _cleanup_free_ char *row = NULL;
+ int rc;
+
+ if (asprintf(&row, "%s %u (%s/%s)", prefix, other_id, name, type) < 0)
+ return log_oom();
+
+ rc = table_add_many(table,
+ TABLE_STRING, special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
+ TABLE_STRING, row,
+ TABLE_EMPTY,
+ TABLE_EMPTY);
+ if (rc < 0)
+ return table_log_add_error(r);
+ }
+
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+struct job_info {
+ uint32_t id;
+ const char *name, *type, *state;
+};
+
+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;
+
+ assert(n == 0 || jobs);
+
+ if (n == 0) {
+ if (!arg_no_legend) {
+ on = ansi_highlight_green();
+ off = ansi_normal();
+
+ printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
+ }
+ return 0;
+ }
+
+ (void) pager_open(arg_pager_flags);
+
+ table = table_new("job", "unit", "type", "state");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (void) table_set_empty_string(table, "-");
+
+ for (j = jobs; j < jobs + n; j++) {
+ if (streq(j->state, "running"))
+ on = ansi_highlight();
+ else
+ on = "";
+
+ r = table_add_many(table,
+ TABLE_UINT, j->id,
+ TABLE_STRING, j->name,
+ TABLE_SET_COLOR, on,
+ TABLE_STRING, j->type,
+ TABLE_STRING, j->state,
+ TABLE_SET_COLOR, on);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ if (arg_jobs_after)
+ output_waiting_jobs(bus, table, j->id, "GetJobAfter", "\twaiting for job");
+ if (arg_jobs_before)
+ output_waiting_jobs(bus, table, j->id, "GetJobBefore", "\tblocking job");
+ }
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to print the table: %m");
+
+ if (!arg_no_legend) {
+ on = ansi_highlight();
+ off = ansi_normal();
+
+ printf("\n%s%u jobs listed%s.\n", on, n, off);
+ }
+
+ return 0;
+}
+
+static bool output_show_job(struct job_info *job, char **patterns) {
+ return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
+}
+
+int list_jobs(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_free_ struct job_info *jobs = NULL;
+ const char *name, *type, *state;
+ bool skipped = false;
+ size_t size = 0;
+ unsigned c = 0;
+ sd_bus *bus;
+ uint32_t id;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "ListJobs", &error, &reply, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, NULL, NULL)) > 0) {
+ struct job_info job = { id, name, type, state };
+
+ if (!output_show_job(&job, strv_skip(argv, 1))) {
+ skipped = true;
+ continue;
+ }
+
+ if (!GREEDY_REALLOC(jobs, size, c + 1))
+ return log_oom();
+
+ jobs[c++] = job;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ (void) pager_open(arg_pager_flags);
+
+ return output_jobs_list(bus, jobs, c, skipped);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int list_jobs(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "sd-login.h"
+
+#include "bus-map-properties.h"
+#include "hostname-util.h"
+#include "locale-util.h"
+#include "memory-util.h"
+#include "sort-util.h"
+#include "systemctl-list-machines.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+const struct bus_properties_map machine_info_property_map[] = {
+ { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
+ { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
+ { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
+ { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
+ { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
+ {}
+};
+
+void machine_info_clear(struct machine_info *info) {
+ assert(info);
+
+ free(info->name);
+ free(info->state);
+ free(info->control_group);
+ zero(*info);
+}
+
+static void free_machines_list(struct machine_info *machine_infos, int n) {
+ int i;
+
+ if (!machine_infos)
+ return;
+
+ for (i = 0; i < n; i++)
+ machine_info_clear(&machine_infos[i]);
+
+ free(machine_infos);
+}
+
+static int compare_machine_info(const struct machine_info *a, const struct machine_info *b) {
+ int r;
+
+ r = CMP(b->is_host, a->is_host);
+ if (r != 0)
+ return r;
+
+ return strcasecmp(a->name, b->name);
+}
+
+static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
+ int r;
+
+ assert(mi);
+
+ if (!bus) {
+ r = sd_bus_open_system_machine(&container, mi->name);
+ if (r < 0)
+ return r;
+
+ bus = container;
+ }
+
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ machine_info_property_map,
+ BUS_MAP_STRDUP,
+ NULL,
+ NULL,
+ mi);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static bool output_show_machine(const char *name, char **patterns) {
+ return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
+}
+
+static int get_machine_list(
+ sd_bus *bus,
+ struct machine_info **_machine_infos,
+ char **patterns) {
+
+ struct machine_info *machine_infos = NULL;
+ _cleanup_strv_free_ char **m = NULL;
+ _cleanup_free_ char *hn = NULL;
+ size_t sz = 0;
+ char **i;
+ int c = 0, r;
+
+ hn = gethostname_malloc();
+ if (!hn)
+ return log_oom();
+
+ if (output_show_machine(hn, patterns)) {
+ if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
+ return log_oom();
+
+ machine_infos[c].is_host = true;
+ machine_infos[c].name = TAKE_PTR(hn);
+
+ (void) get_machine_properties(bus, &machine_infos[c]);
+ c++;
+ }
+
+ r = sd_get_machine_names(&m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get machine list: %m");
+
+ STRV_FOREACH(i, m) {
+ _cleanup_free_ char *class = NULL;
+
+ if (!output_show_machine(*i, patterns))
+ continue;
+
+ sd_machine_get_class(*i, &class);
+ if (!streq_ptr(class, "container"))
+ continue;
+
+ if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
+ free_machines_list(machine_infos, c);
+ return log_oom();
+ }
+
+ machine_infos[c].is_host = false;
+ machine_infos[c].name = strdup(*i);
+ if (!machine_infos[c].name) {
+ free_machines_list(machine_infos, c);
+ return log_oom();
+ }
+
+ (void) get_machine_properties(NULL, &machine_infos[c]);
+ c++;
+ }
+
+ *_machine_infos = machine_infos;
+ return c;
+}
+
+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;
+
+ assert(machine_infos || n == 0);
+
+ table = table_new("", "name", "state", "failed", "jobs");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_plain) {
+ /* Hide the 'glyph' column when --plain is requested */
+ r = table_hide_column_from_display(table, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to hide column: %m");
+ }
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (void) table_set_empty_string(table, "-");
+
+ for (m = machine_infos; m < machine_infos + n; m++) {
+ _cleanup_free_ char *mname = NULL;
+ const char *on_state = "", *on_failed = "";
+ bool circle = false;
+
+ if (streq_ptr(m->state, "degraded")) {
+ on_state = ansi_highlight_red();
+ circle = true;
+ } else if (!streq_ptr(m->state, "running")) {
+ on_state = ansi_highlight_yellow();
+ circle = true;
+ }
+
+ if (m->n_failed_units > 0)
+ on_failed = ansi_highlight_red();
+ else
+ on_failed = "";
+
+ if (!m->state)
+ state_missing = true;
+
+ if (m->is_host)
+ mname = strjoin(strna(m->name), " (host)");
+
+ r = table_add_many(table,
+ TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
+ TABLE_SET_COLOR, on_state,
+ TABLE_STRING, m->is_host ? mname : strna(m->name),
+ TABLE_STRING, strna(m->state),
+ TABLE_SET_COLOR, on_state,
+ TABLE_UINT32, m->n_failed_units,
+ TABLE_SET_COLOR, on_failed,
+ TABLE_UINT32, m->n_jobs);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_legend) {
+ printf("\n");
+ if (state_missing && geteuid() != 0)
+ printf("Notice: some information only available to privileged users was not shown.\n");
+ printf("%u machines listed.\n", n);
+ }
+
+ return 0;
+}
+
+int list_machines(int argc, char *argv[], void *userdata) {
+ struct machine_info *machine_infos = NULL;
+ sd_bus *bus;
+ int r, rc;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1));
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ typesafe_qsort(machine_infos, r, compare_machine_info);
+ rc = output_machines_list(machine_infos, r);
+ free_machines_list(machine_infos, r);
+
+ return rc;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "bus-map-properties.h"
+#include "time-util.h"
+
+int list_machines(int argc, char *argv[], void *userdata);
+
+struct machine_info {
+ bool is_host;
+ char *name;
+ char *state;
+ char *control_group;
+ uint32_t n_failed_units;
+ uint32_t n_jobs;
+ usec_t timestamp;
+};
+
+void machine_info_clear(struct machine_info *info);
+
+extern const struct bus_properties_map machine_info_property_map[];
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "sort-util.h"
+#include "systemctl-list-unit-files.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static int compare_unit_file_list(const UnitFileList *a, const UnitFileList *b) {
+ const char *d1, *d2;
+
+ d1 = strrchr(a->path, '.');
+ d2 = strrchr(b->path, '.');
+
+ if (d1 && d2) {
+ int r;
+
+ r = strcasecmp(d1, d2);
+ if (r != 0)
+ return r;
+ }
+
+ return strcasecmp(basename(a->path), basename(b->path));
+}
+
+static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) {
+ assert(u);
+
+ if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
+ return false;
+
+ if (!strv_isempty(arg_types)) {
+ const char *dot;
+
+ dot = strrchr(u->path, '.');
+ if (!dot)
+ return false;
+
+ if (!strv_find(arg_types, dot+1))
+ return false;
+ }
+
+ if (!strv_isempty(states) &&
+ !strv_find(states, unit_file_state_to_string(u->state)))
+ return false;
+
+ return true;
+}
+
+static int output_unit_file_list(const UnitFileList *units, unsigned c) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ _cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
+ int r;
+
+ table = table_new("unit file", "state", "vendor preset");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (void) table_set_empty_string(table, "-");
+
+ for (const UnitFileList *u = units; u < units + c; u++) {
+ const char *on_underline = NULL, *on_unit_color = NULL, *id;
+ bool underline;
+
+ underline = u + 1 < units + c &&
+ !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path));
+
+ if (underline)
+ on_underline = ansi_underline();
+
+ if (IN_SET(u->state,
+ UNIT_FILE_MASKED,
+ UNIT_FILE_MASKED_RUNTIME,
+ UNIT_FILE_DISABLED,
+ UNIT_FILE_BAD))
+ on_unit_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ else if (IN_SET(u->state,
+ UNIT_FILE_ENABLED,
+ UNIT_FILE_ALIAS))
+ on_unit_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
+ else
+ on_unit_color = on_underline;
+
+ id = basename(u->path);
+
+ r = table_add_many(table,
+ TABLE_STRING, id,
+ TABLE_SET_BOTH_COLORS, strempty(on_underline),
+ TABLE_STRING, unit_file_state_to_string(u->state),
+ TABLE_SET_BOTH_COLORS, strempty(on_unit_color));
+ if (r < 0)
+ return table_log_add_error(r);
+
+ if (show_preset_for_state(u->state)) {
+ const char *unit_preset_str, *on_preset_color;
+
+ r = unit_file_query_preset(arg_scope, arg_root, id, &presets);
+ if (r < 0) {
+ unit_preset_str = "n/a";
+ on_preset_color = underline ? on_underline : ansi_normal();
+ } else if (r == 0) {
+ unit_preset_str = "disabled";
+ on_preset_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ } else {
+ unit_preset_str = "enabled";
+ on_preset_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
+ }
+
+ r = table_add_many(table,
+ TABLE_STRING, unit_preset_str,
+ TABLE_SET_BOTH_COLORS, strempty(on_preset_color));
+ } else
+ r = table_add_many(table,
+ TABLE_EMPTY,
+ TABLE_SET_BOTH_COLORS, underline ? ansi_grey_underline() : ansi_grey());
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_legend)
+ printf("\n%u unit files listed.\n", c);
+
+ return 0;
+}
+
+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;
+ char *path;
+ int r;
+ bool fallback = false;
+
+ if (install_client_side()) {
+ Hashmap *h;
+ UnitFileList *u;
+ unsigned n_units;
+
+ h = hashmap_new(&string_hash_ops);
+ if (!h)
+ return log_oom();
+
+ r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1));
+ if (r < 0) {
+ unit_file_list_free(h);
+ return log_error_errno(r, "Failed to get unit file list: %m");
+ }
+
+ n_units = hashmap_size(h);
+
+ units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */
+ if (!units) {
+ unit_file_list_free(h);
+ return log_oom();
+ }
+
+ HASHMAP_FOREACH(u, h) {
+ if (!output_show_unit_file(u, NULL, NULL))
+ continue;
+
+ units[c++] = *u;
+ free(u);
+ }
+
+ assert(c <= n_units);
+ hashmap_free(h);
+
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitFilesByPatterns");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, arg_states);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (arg_with_dependencies) {
+ _cleanup_strv_free_ char **names_with_deps = NULL;
+
+ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names_with_deps);
+ if (r < 0)
+ return log_error_errno(r, "Failed to append unit dependencies: %m");
+
+ r = sd_bus_message_append_strv(m, names_with_deps);
+ if (r < 0)
+ return bus_log_create_error(r);
+ } else {
+ r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_call(bus, m, 0, &error, &reply);
+ if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
+ /* Fallback to legacy ListUnitFiles method */
+ fallback = true;
+ log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
+ m = sd_bus_message_unref(m);
+ sd_bus_error_free(&error);
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitFiles");
+ 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 list unit files: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
+
+ if (!GREEDY_REALLOC(units, size, c + 1))
+ return log_oom();
+
+ units[c] = (struct UnitFileList) {
+ path,
+ unit_file_state_from_string(state)
+ };
+
+ if (output_show_unit_file(&units[c],
+ fallback ? arg_states : NULL,
+ fallback ? strv_skip(argv, 1) : NULL))
+ c++;
+
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+
+ (void) pager_open(arg_pager_flags);
+
+ typesafe_qsort(units, c, compare_unit_file_list);
+ r = output_unit_file_list(units, c);
+ if (r < 0)
+ return r;
+
+ if (install_client_side())
+ for (unit = units; unit < units + c; unit++)
+ free(unit->path);
+
+ if (c == 0)
+ return -ENOENT;
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int list_unit_files(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-login.h"
+
+#include "bus-error.h"
+#include "format-table.h"
+#include "locale-util.h"
+#include "set.h"
+#include "sort-util.h"
+#include "systemctl-list-units.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static void message_set_freep(Set **set) {
+ set_free_with_destructor(*set, sd_bus_message_unref);
+}
+
+static int get_unit_list_recursive(
+ sd_bus *bus,
+ char **patterns,
+ UnitInfo **ret_unit_infos,
+ Set **ret_replies,
+ char ***ret_machines) {
+
+ _cleanup_free_ UnitInfo *unit_infos = NULL;
+ _cleanup_(message_set_freep) Set *replies;
+ sd_bus_message *reply;
+ int c, r;
+
+ assert(bus);
+ assert(ret_replies);
+ assert(ret_unit_infos);
+ assert(ret_machines);
+
+ replies = set_new(NULL);
+ if (!replies)
+ return log_oom();
+
+ c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
+ if (c < 0)
+ return c;
+
+ r = set_put(replies, reply);
+ if (r < 0) {
+ sd_bus_message_unref(reply);
+ return log_oom();
+ }
+
+ if (arg_recursive) {
+ _cleanup_strv_free_ char **machines = NULL;
+ char **i;
+
+ r = sd_get_machine_names(&machines);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get machine names: %m");
+
+ STRV_FOREACH(i, machines) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
+ int k;
+
+ r = sd_bus_open_system_machine(&container, *i);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
+ continue;
+ }
+
+ k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
+ if (k < 0)
+ return k;
+
+ c = k;
+
+ r = set_put(replies, reply);
+ if (r < 0) {
+ sd_bus_message_unref(reply);
+ return log_oom();
+ }
+ }
+
+ *ret_machines = TAKE_PTR(machines);
+ } else
+ *ret_machines = NULL;
+
+ *ret_unit_infos = TAKE_PTR(unit_infos);
+ *ret_replies = TAKE_PTR(replies);
+
+ return c;
+}
+
+static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ int r;
+
+ table = table_new("", "unit", "load", "active", "sub", "job", "description");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_plain) {
+ /* Hide the 'glyph' column when --plain is requested */
+ r = table_hide_column_from_display(table, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to hide column: %m");
+ }
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (void) table_set_empty_string(table, "-");
+
+ int job_count = 0;
+ for (const UnitInfo *u = unit_infos; unit_infos && u < unit_infos + c; u++) {
+ _cleanup_free_ char *j = NULL;
+ const char *on_underline = "", *on_loaded = "", *on_active = "";
+ const char *on_circle = "", *id;
+ bool circle = false, underline = false;
+
+ if (u + 1 < unit_infos + c &&
+ !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
+ on_underline = ansi_underline();
+ underline = true;
+ }
+
+ if (STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked") && !arg_plain) {
+ on_circle = underline ? ansi_highlight_yellow_underline() : ansi_highlight_yellow();
+ circle = true;
+ on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ } else if (streq(u->active_state, "failed") && !arg_plain) {
+ on_circle = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ circle = true;
+ on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ } else {
+ on_circle = on_underline;
+ on_active = on_underline;
+ on_loaded = on_underline;
+ }
+
+ if (u->machine) {
+ j = strjoin(u->machine, ":", u->id);
+ if (!j)
+ return log_oom();
+
+ id = j;
+ } else
+ id = u->id;
+
+ r = table_add_many(table,
+ TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
+ TABLE_SET_BOTH_COLORS, on_circle,
+ TABLE_STRING, id,
+ TABLE_SET_BOTH_COLORS, on_active,
+ TABLE_STRING, u->load_state,
+ TABLE_SET_BOTH_COLORS, on_loaded,
+ TABLE_STRING, u->active_state,
+ TABLE_SET_BOTH_COLORS, on_active,
+ TABLE_STRING, u->sub_state,
+ TABLE_SET_BOTH_COLORS, on_active,
+ TABLE_STRING, u->job_id ? u->job_type: "",
+ TABLE_SET_BOTH_COLORS, u->job_id ? on_underline : "",
+ TABLE_STRING, u->description,
+ TABLE_SET_BOTH_COLORS, on_underline);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ if (u->job_id != 0)
+ job_count++;
+ }
+
+ if (job_count == 0) {
+ /* There's no data in the JOB column, so let's hide it */
+ r = table_hide_column_from_display(table, 5);
+ if (r < 0)
+ return log_error_errno(r, "Failed to hide column: %m");
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_legend) {
+ const char *on, *off;
+ size_t records = table_get_rows(table) - 1;
+
+ if (records > 0) {
+ puts("\n"
+ "LOAD = Reflects whether the unit definition was properly loaded.\n"
+ "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
+ "SUB = The low-level unit activation state, values depend on unit type.");
+ puts(job_count ? "JOB = Pending job for the unit.\n" : "");
+ on = ansi_highlight();
+ off = ansi_normal();
+ } else {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ }
+
+ if (arg_all || strv_contains(arg_states, "inactive"))
+ printf("%s%zu loaded units listed.%s\n"
+ "To show all installed unit files use 'systemctl list-unit-files'.\n",
+ on, records, off);
+ else if (!arg_states)
+ printf("%s%zu loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
+ "To show all installed unit files use 'systemctl list-unit-files'.\n",
+ on, records, off);
+ else
+ printf("%zu loaded units listed.\n", records);
+ }
+
+ return 0;
+}
+
+int list_units(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ UnitInfo *unit_infos = NULL;
+ _cleanup_(message_set_freep) Set *replies = NULL;
+ _cleanup_strv_free_ char **machines = NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ if (arg_with_dependencies) {
+ _cleanup_strv_free_ char **names = NULL;
+
+ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names);
+ if (r < 0)
+ return r;
+
+ r = get_unit_list_recursive(bus, names, &unit_infos, &replies, &machines);
+ if (r < 0)
+ return r;
+ } else {
+ r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
+ if (r < 0)
+ return r;
+ }
+
+ typesafe_qsort(unit_infos, r, unit_info_compare);
+ return output_units_list(unit_infos, r);
+}
+
+static int get_triggered_units(
+ sd_bus *bus,
+ const char* path,
+ char*** ret) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(ret);
+
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Unit",
+ "Triggers",
+ &error,
+ ret);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+static int get_listening(
+ sd_bus *bus,
+ const char* unit_path,
+ char*** listening) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *type, *path;
+ int r, n = 0;
+
+ r = sd_bus_get_property(
+ bus,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.systemd1.Socket",
+ "Listen",
+ &error,
+ &reply,
+ "a(ss)");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
+
+ r = strv_extend(listening, type);
+ if (r < 0)
+ return log_oom();
+
+ r = strv_extend(listening, path);
+ if (r < 0)
+ return log_oom();
+
+ n++;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return n;
+}
+
+struct socket_info {
+ const char *machine;
+ const char* id;
+
+ char* type;
+ char* path;
+
+ /* Note: triggered is a list here, although it almost certainly will always be one
+ * unit. Nevertheless, dbus API allows for multiple values, so let's follow that. */
+ char** triggered;
+
+ /* The strv above is shared. free is set only in the first one. */
+ bool own_triggered;
+};
+
+static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = strcasecmp_ptr(a->machine, b->machine);
+ if (r != 0)
+ return r;
+
+ r = strcmp(a->path, b->path);
+ if (r != 0)
+ return r;
+
+ return strcmp(a->type, b->type);
+}
+
+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;
+
+ table = table_new("listen", "type", "unit", "activates");
+ if (!table)
+ return log_oom();
+
+ if (!arg_show_types) {
+ /* Hide the second (TYPE) column */
+ r = table_set_display(table, (size_t) 0, (size_t) 2, (size_t) 3, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set columns to display: %m");
+ }
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (void) table_set_empty_string(table, "-");
+
+ if (cs) {
+ for (s = socket_infos; s < socket_infos + cs; s++) {
+ _cleanup_free_ char *j = NULL;
+ const char *path;
+
+ if (s->machine) {
+ j = strjoin(s->machine, ":", s->path);
+ if (!j)
+ return log_oom();
+ path = j;
+ } else
+ path = s->path;
+
+ r = table_add_many(table,
+ TABLE_STRING, path,
+ TABLE_STRING, s->type,
+ TABLE_STRING, s->id);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ if (strv_isempty(s->triggered))
+ r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
+ else if (strv_length(s->triggered) == 1)
+ r = table_add_cell(table, NULL, TABLE_STRING, s->triggered[0]);
+ else
+ /* This should never happen, currently our socket units can only trigger a
+ * single unit. But let's handle this anyway, who knows what the future
+ * brings? */
+ r = table_add_cell(table, NULL, TABLE_STRV, s->triggered);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ }
+
+ on = ansi_highlight();
+ off = ansi_normal();
+ } else {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_legend) {
+ printf("\n%s%u sockets listed.%s\n", on, cs, off);
+ if (!arg_all)
+ printf("Pass --all to see loaded but inactive sockets, too.\n");
+ }
+
+ return 0;
+}
+
+int list_sockets(int argc, char *argv[], void *userdata) {
+ _cleanup_(message_set_freep) Set *replies = NULL;
+ _cleanup_strv_free_ char **machines = NULL;
+ _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;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), ".socket", &sockets_with_suffix, NULL);
+ if (r < 0)
+ return r;
+
+ if (argc == 1 || sockets_with_suffix) {
+ n = get_unit_list_recursive(bus, sockets_with_suffix, &unit_infos, &replies, &machines);
+ if (n < 0)
+ return n;
+
+ for (u = unit_infos; u < unit_infos + n; u++) {
+ _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
+ int i, c;
+
+ if (!endswith(u->id, ".socket"))
+ continue;
+
+ r = get_triggered_units(bus, u->unit_path, &triggered);
+ if (r < 0)
+ goto cleanup;
+
+ c = get_listening(bus, u->unit_path, &listening);
+ if (c < 0) {
+ r = c;
+ goto cleanup;
+ }
+
+ if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
+ r = log_oom();
+ goto cleanup;
+ }
+
+ for (i = 0; i < c; i++)
+ socket_infos[cs + i] = (struct socket_info) {
+ .machine = u->machine,
+ .id = u->id,
+ .type = listening[i*2],
+ .path = listening[i*2 + 1],
+ .triggered = triggered,
+ .own_triggered = i==0,
+ };
+
+ /* from this point on we will cleanup those socket_infos */
+ cs += c;
+ free(listening);
+ listening = triggered = NULL; /* avoid cleanup */
+ }
+
+ typesafe_qsort(socket_infos, cs, socket_info_compare);
+ }
+
+ output_sockets_list(socket_infos, cs);
+
+ cleanup:
+ assert(cs == 0 || socket_infos);
+ for (s = socket_infos; s < socket_infos + cs; s++) {
+ free(s->type);
+ free(s->path);
+ if (s->own_triggered)
+ strv_free(s->triggered);
+ }
+
+ return r;
+}
+
+static int get_next_elapse(
+ sd_bus *bus,
+ const char *path,
+ dual_timestamp *next) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ dual_timestamp t;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(next);
+
+ r = sd_bus_get_property_trivial(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Timer",
+ "NextElapseUSecMonotonic",
+ &error,
+ 't',
+ &t.monotonic);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
+
+ r = sd_bus_get_property_trivial(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Timer",
+ "NextElapseUSecRealtime",
+ &error,
+ 't',
+ &t.realtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
+
+ *next = t;
+ return 0;
+}
+
+static int get_last_trigger(
+ sd_bus *bus,
+ const char *path,
+ usec_t *last) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(last);
+
+ r = sd_bus_get_property_trivial(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Timer",
+ "LastTriggerUSec",
+ &error,
+ 't',
+ last);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+struct timer_info {
+ const char* machine;
+ const char* id;
+ usec_t next_elapse;
+ usec_t last_trigger;
+ char** triggered;
+};
+
+static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = strcasecmp_ptr(a->machine, b->machine);
+ if (r != 0)
+ return r;
+
+ r = CMP(a->next_elapse, b->next_elapse);
+ if (r != 0)
+ return r;
+
+ return strcmp(a->id, b->id);
+}
+
+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;
+
+ assert(timer_infos || n == 0);
+
+ table = table_new("next", "left", "last", "passed", "unit", "activates");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, !arg_no_legend);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ (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;
+
+ 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);
+ }
+
+ on = ansi_highlight();
+ off = ansi_normal();
+ } else {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (!arg_no_legend) {
+ printf("\n%s%u timers listed.%s\n", on, n, off);
+ if (!arg_all)
+ printf("Pass --all to see loaded but inactive timers, too.\n");
+ }
+
+ return 0;
+}
+
+usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
+ usec_t next_elapse;
+
+ assert(nw);
+ assert(next);
+
+ if (timestamp_is_set(next->monotonic)) {
+ usec_t converted;
+
+ if (next->monotonic > nw->monotonic)
+ converted = nw->realtime + (next->monotonic - nw->monotonic);
+ else
+ converted = nw->realtime - (nw->monotonic - next->monotonic);
+
+ if (timestamp_is_set(next->realtime))
+ next_elapse = MIN(converted, next->realtime);
+ else
+ next_elapse = converted;
+
+ } else
+ next_elapse = next->realtime;
+
+ return next_elapse;
+}
+
+int list_timers(int argc, char *argv[], void *userdata) {
+ _cleanup_(message_set_freep) Set *replies = NULL;
+ _cleanup_strv_free_ char **machines = NULL;
+ _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;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), ".timer", &timers_with_suffix, NULL);
+ if (r < 0)
+ return r;
+
+ if (argc == 1 || timers_with_suffix) {
+ n = get_unit_list_recursive(bus, timers_with_suffix, &unit_infos, &replies, &machines);
+ if (n < 0)
+ return n;
+
+ dual_timestamp_get(&nw);
+
+ for (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;
+
+ if (!endswith(u->id, ".timer"))
+ continue;
+
+ r = get_triggered_units(bus, u->unit_path, &triggered);
+ if (r < 0)
+ goto cleanup;
+
+ r = get_next_elapse(bus, u->unit_path, &next);
+ if (r < 0)
+ goto cleanup;
+
+ get_last_trigger(bus, u->unit_path, &last);
+
+ if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
+ r = log_oom();
+ goto cleanup;
+ }
+
+ m = calc_next_elapse(&nw, &next);
+
+ timer_infos[c++] = (struct timer_info) {
+ .machine = u->machine,
+ .id = u->id,
+ .next_elapse = m,
+ .last_trigger = last,
+ .triggered = TAKE_PTR(triggered),
+ };
+ }
+
+ typesafe_qsort(timer_infos, c, timer_info_compare);
+ }
+
+ output_timers_list(timer_infos, c);
+
+ cleanup:
+ for (t = timer_infos; t < timer_infos + c; t++)
+ strv_free(t->triggered);
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int list_units(int argc, char *argv[], void *userdata);
+int list_sockets(int argc, char *argv[], void *userdata);
+int list_timers(int argc, char *argv[], void *userdata);
+
+usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "pretty-print.h"
+#include "syslog-util.h"
+#include "systemctl-log-setting.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static void give_log_control1_hint(const char *name) {
+ _cleanup_free_ char *link = NULL;
+
+ if (arg_quiet)
+ return;
+
+ (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link);
+
+ log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n"
+ " See the %s for details.", link ?: "org.freedesktop.LogControl1(5) man page");
+}
+
+static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) {
+ assert(bus);
+ assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target"));
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ bool level = endswith(verb, "log-level");
+ int 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 = bus_set_property(bus, bloc,
+ level ? "LogLevel" : "LogTarget",
+ &error, "s", value);
+ if (r >= 0)
+ return 0;
+
+ log_error_errno(r, "Failed to set log %s of %s to %s: %s",
+ level ? "level" : "target",
+ bloc->destination, value, bus_error_message(&error, r));
+ } else {
+ _cleanup_free_ char *t = NULL;
+
+ r = bus_get_property_string(bus, bloc,
+ level ? "LogLevel" : "LogTarget",
+ &error, &t);
+ if (r >= 0) {
+ puts(t);
+ return 0;
+ }
+
+ log_error_errno(r, "Failed to get log %s of %s: %s",
+ level ? "level" : "target",
+ bloc->destination, bus_error_message(&error, r));
+ }
+
+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD,
+ SD_BUS_ERROR_UNKNOWN_OBJECT,
+ SD_BUS_ERROR_UNKNOWN_INTERFACE,
+ SD_BUS_ERROR_UNKNOWN_PROPERTY))
+ give_log_control1_hint(bloc->destination);
+ return r;
+}
+
+int log_setting(int argc, char *argv[], void *userdata) {
+ sd_bus *bus;
+ int r;
+
+ assert(argc >= 1 && argc <= 2);
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]);
+}
+
+static int service_name_to_dbus(sd_bus *bus, const char *name, char **ret_dbus_name) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *bus_name = NULL;
+ int r;
+
+ /* First, look for the BusName= property */
+ _cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name);
+ if (!dbus_path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Service",
+ "BusName",
+ &error,
+ &bus_name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to obtain BusName= property of %s: %s",
+ name, bus_error_message(&error, r));
+
+ if (isempty(bus_name)) {
+ log_error("Unit %s doesn't declare BusName=.", name);
+ give_log_control1_hint(name);
+ return -ENOLINK;
+ }
+
+ *ret_dbus_name = TAKE_PTR(bus_name);
+ return 0;
+}
+
+int service_log_setting(int argc, char *argv[], void *userdata) {
+ sd_bus *bus;
+ _cleanup_free_ char *unit = NULL, *dbus_name = NULL;
+ int r;
+
+ assert(argc >= 2 && argc <= 3);
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = unit_name_mangle_with_suffix(argv[1], argv[0],
+ arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
+ ".service", &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ r = service_name_to_dbus(bus, unit, &dbus_name);
+ if (r < 0)
+ return r;
+
+ const BusLocator bloc = {
+ .destination = dbus_name,
+ .path = "/org/freedesktop/LogControl1",
+ .interface = "org.freedesktop.LogControl1",
+ };
+
+ return log_setting_internal(bus, &bloc, argv[0], argv[2]);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int log_setting(int argc, char *argv[], void *userdata);
+int service_log_setting(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "sd-login.h"
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "process-util.h"
+#include "systemctl-logind.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "user-util.h"
+
+int logind_set_wall_message(void) {
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ _cleanup_free_ char *m = NULL;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ m = strv_join(arg_wall, " ");
+ if (!m)
+ return log_oom();
+
+ log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
+ if (arg_dry_run)
+ return 0;
+
+ r = bus_call_method(bus, bus_login_mgr, "SetWallMessage", &error, NULL, "sb", m, !arg_no_wall);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
+#endif
+ return 0;
+}
+
+/* Ask systemd-logind, which might grant access to unprivileged users through polkit */
+int logind_reboot(enum action a) {
+#if ENABLE_LOGIND
+ static const struct {
+ const char *method;
+ const char *description;
+ } actions[_ACTION_MAX] = {
+ [ACTION_POWEROFF] = { "PowerOff", "power off system" },
+ [ACTION_REBOOT] = { "Reboot", "reboot system" },
+ [ACTION_HALT] = { "Halt", "halt system" },
+ [ACTION_SUSPEND] = { "Suspend", "suspend system" },
+ [ACTION_HIBERNATE] = { "Hibernate", "hibernate system" },
+ [ACTION_HYBRID_SLEEP] = { "HybridSleep", "put system into hybrid sleep" },
+ [ACTION_SUSPEND_THEN_HIBERNATE] = { "SuspendThenHibernate", "suspend system, hibernate later" },
+ };
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ if (a < 0 || a >= _ACTION_MAX || !actions[a].method)
+ return -EINVAL;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+ (void) logind_set_wall_message();
+
+ log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", actions[a].method);
+
+ if (arg_dry_run)
+ return 0;
+
+ 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));
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
+}
+
+int logind_check_inhibitors(enum action a) {
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_strv_free_ char **sessions = NULL;
+ const char *what, *who, *why, *mode;
+ uint32_t uid, pid;
+ sd_bus *bus;
+ unsigned c = 0;
+ char **s;
+ int r;
+
+ if (arg_ignore_inhibitors || arg_force > 0)
+ return 0;
+
+ if (arg_when > 0)
+ return 0;
+
+ if (geteuid() == 0)
+ return 0;
+
+ if (!on_tty())
+ return 0;
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return 0;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_login_mgr, "ListInhibitors", NULL, &reply, NULL);
+ if (r < 0)
+ /* If logind is not around, then there are no inhibitors... */
+ return 0;
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
+ _cleanup_free_ char *comm = NULL, *user = NULL;
+ _cleanup_strv_free_ char **sv = NULL;
+
+ if (!streq(mode, "block"))
+ continue;
+
+ sv = strv_split(what, ":");
+ if (!sv)
+ return log_oom();
+
+ if (!pid_is_valid((pid_t) pid))
+ return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid PID "PID_FMT".", (pid_t) pid);
+
+ if (!strv_contains(sv,
+ IN_SET(a,
+ ACTION_HALT,
+ ACTION_POWEROFF,
+ ACTION_REBOOT,
+ ACTION_KEXEC) ? "shutdown" : "sleep"))
+ continue;
+
+ get_process_comm(pid, &comm);
+ user = uid_to_name(uid);
+
+ log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
+ who, (pid_t) pid, strna(comm), strna(user), why);
+
+ c++;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ /* Check for current sessions */
+ sd_get_sessions(&sessions);
+ STRV_FOREACH(s, sessions) {
+ _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
+
+ if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
+ continue;
+
+ if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
+ continue;
+
+ if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
+ continue;
+
+ sd_session_get_tty(*s, &tty);
+ sd_session_get_seat(*s, &seat);
+ sd_session_get_service(*s, &service);
+ user = uid_to_name(uid);
+
+ log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
+ c++;
+ }
+
+ if (c <= 0)
+ return 0;
+
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+ "Please retry operation after closing inhibitors and logging out other users.\n"
+ "Alternatively, ignore inhibitors and users with 'systemctl %s -i'.",
+ action_table[a].verb);
+#else
+ return 0;
+#endif
+}
+
+int prepare_firmware_setup(void) {
+
+ if (!arg_firmware_setup)
+ return 0;
+
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_login_mgr, "SetRebootToFirmwareSetup", &error, NULL, "b", true);
+ if (r < 0)
+ return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
+
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Booting into firmware setup not supported.");
+#endif
+}
+
+int prepare_boot_loader_menu(void) {
+
+ if (arg_boot_loader_menu == USEC_INFINITY)
+ return 0;
+
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderMenu", &error, NULL, "t", arg_boot_loader_menu);
+ if (r < 0)
+ return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
+
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Booting into boot loader menu not supported.");
+#endif
+}
+
+int prepare_boot_loader_entry(void) {
+
+ if (!arg_boot_loader_entry)
+ return 0;
+
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderEntry", &error, NULL, "s", arg_boot_loader_entry);
+ if (r < 0)
+ return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
+
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Booting into boot loader entry not supported.");
+#endif
+}
+
+int logind_schedule_shutdown(void) {
+
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ char date[FORMAT_TIMESTAMP_MAX];
+ const char *action;
+ const char *log_action;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ switch (arg_action) {
+ case ACTION_HALT:
+ action = "halt";
+ log_action = "Shutdown";
+ break;
+ case ACTION_POWEROFF:
+ action = "poweroff";
+ log_action = "Shutdown";
+ break;
+ case ACTION_KEXEC:
+ action = "kexec";
+ log_action = "Reboot via kexec";
+ break;
+ case ACTION_EXIT:
+ action = "exit";
+ log_action = "Shutdown";
+ break;
+ case ACTION_REBOOT:
+ default:
+ action = "reboot";
+ log_action = "Reboot";
+ break;
+ }
+
+ if (arg_dry_run)
+ action = strjoina("dry-", action);
+
+ (void) logind_set_wall_message();
+
+ r = bus_call_method(bus, bus_login_mgr, "ScheduleShutdown", &error, NULL, "st", action, arg_when);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
+
+ if (!arg_quiet)
+ log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp_style(date, sizeof(date), arg_when, arg_timestamp_style));
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
+#endif
+}
+
+int logind_cancel_shutdown(void) {
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ (void) logind_set_wall_message();
+
+ r = bus_call_method(bus, bus_login_mgr, "CancelScheduledShutdown", &error, NULL, NULL);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
+
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Not compiled with logind support, cannot cancel scheduled shutdowns.");
+#endif
+}
+
+int help_boot_loader_entry(void) {
+#if ENABLE_LOGIND
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_strv_free_ char **l = NULL;
+ sd_bus *bus;
+ char **i;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_get_property_strv(bus, bus_login_mgr, "BootLoaderEntries", &error, &l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
+
+ if (strv_isempty(l))
+ return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No boot loader entries discovered.");
+
+ STRV_FOREACH(i, l)
+ puts(*i);
+
+ return 0;
+#else
+ return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
+ "Not compiled with logind support, cannot display boot loader entries.");
+#endif
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "systemctl.h"
+
+int logind_set_wall_message(void);
+
+int logind_reboot(enum action a);
+int logind_check_inhibitors(enum action a);
+
+int prepare_firmware_setup(void);
+int prepare_boot_loader_menu(void);
+int prepare_boot_loader_entry(void);
+
+int logind_schedule_shutdown(void);
+int logind_cancel_shutdown(void);
+
+int help_boot_loader_entry(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-preset-all.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int preset_all(int argc, char *argv[], void *userdata) {
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0;
+ int r;
+
+ if (install_client_side()) {
+ r = unit_file_preset_all(arg_scope, unit_file_flags_from_args(), arg_root, arg_preset_mode, &changes, &n_changes);
+ unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
+
+ if (r > 0)
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = bus_call_method(
+ bus,
+ bus_systemd_mgr,
+ "PresetAllUnitFiles",
+ &error,
+ &reply,
+ "sbb",
+ unit_file_preset_mode_to_string(arg_preset_mode),
+ arg_runtime,
+ arg_force);
+ if (r < 0)
+ return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
+
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
+ if (r < 0)
+ goto finish;
+
+ if (arg_no_reload) {
+ r = 0;
+ goto finish;
+ }
+
+ r = daemon_reload(argc, argv, userdata);
+ }
+
+finish:
+ unit_file_changes_free(changes, n_changes);
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int preset_all(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-reset-failed.h"
+#include "systemctl-trivial-method.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int reset_failed(int argc, char *argv[], void *userdata) {
+ _cleanup_strv_free_ char **names = NULL;
+ sd_bus *bus;
+ char **name;
+ int r, q;
+
+ if (argc <= 1) /* Shortcut to trivial_method() if no argument is given */
+ return trivial_method(argc, argv, userdata);
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ STRV_FOREACH(name, names) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ q = bus_call_method(bus, bus_systemd_mgr, "ResetFailedUnit", &error, NULL, "s", *name);
+ if (q < 0) {
+ log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
+ if (r == 0)
+ r = q;
+ }
+ }
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int reset_failed(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "parse-util.h"
+#include "systemctl-service-watchdogs.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int service_watchdogs(int argc, char *argv[], void *userdata) {
+ sd_bus *bus;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int b, r;
+
+ assert(argv);
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ if (argc == 1) {
+ /* get ServiceWatchdogs */
+ r = bus_get_property_trivial(bus, bus_systemd_mgr, "ServiceWatchdogs", &error, 'b', &b);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get service-watchdog state: %s", bus_error_message(&error, r));
+
+ printf("%s\n", yes_no(!!b));
+
+ } else {
+ /* set ServiceWatchdogs */
+ assert(argc == 2);
+
+ b = parse_boolean(argv[1]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
+
+ r = bus_set_property(bus, bus_systemd_mgr, "ServiceWatchdogs", &error, "b", b);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int service_watchdogs(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "proc-cmdline.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-set-default.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
+ char **ret = data;
+
+ if (streq(key, "systemd.unit")) {
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+ if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
+ return 0;
+ }
+
+ return free_and_strdup_warn(ret, key);
+
+ } else if (!value) {
+ if (runlevel_to_target(key))
+ return free_and_strdup_warn(ret, key);
+ }
+
+ return 0;
+}
+
+static void emit_cmdline_warning(void) {
+ if (arg_quiet || arg_root)
+ /* don't bother checking the commandline if we're operating on a container */
+ return;
+
+ _cleanup_free_ char *override = NULL;
+ int r;
+
+ r = proc_cmdline_parse(parse_proc_cmdline_item, &override, 0);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse kernel command line, ignoring: %m");
+ if (override)
+ log_notice("Note: found \"%s\" on the kernel commandline, which overrides the default unit.",
+ override);
+}
+
+static int determine_default(char **ret_name) {
+ int r;
+
+ if (install_client_side()) {
+ r = unit_file_get_default(arg_scope, arg_root, ret_name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get default target: %m");
+ return 0;
+
+ } else {
+ sd_bus *bus;
+ _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 *name;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetDefaultTarget", &error, &reply, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "s", &name);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return free_and_strdup_warn(ret_name, name);
+ }
+}
+
+int get_default(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *name = NULL;
+ int r;
+
+ r = determine_default(&name);
+ if (r < 0)
+ return r;
+
+ printf("%s\n", name);
+
+ emit_cmdline_warning();
+
+ return 0;
+}
+
+int set_default(int argc, char *argv[], void *userdata) {
+ _cleanup_free_ char *unit = NULL;
+ UnitFileChange *changes = NULL;
+ size_t n_changes = 0;
+ int r;
+
+ assert(argc >= 2);
+ assert(argv);
+
+ r = unit_name_mangle_with_suffix(argv[1], "set-default",
+ arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
+ ".target", &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ if (install_client_side()) {
+ r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
+ unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
+
+ if (r > 0)
+ r = 0;
+ } else {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ sd_bus *bus;
+
+ polkit_agent_open_maybe();
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "SetDefaultTarget", &error, &reply, "sb", unit, 1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
+
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
+ if (r < 0)
+ goto finish;
+
+ /* Try to reload if enabled */
+ if (!arg_no_reload)
+ r = daemon_reload(argc, argv, userdata);
+ else
+ r = 0;
+ }
+
+ emit_cmdline_warning();
+
+ if (!arg_quiet) {
+ _cleanup_free_ char *final = NULL;
+
+ r = determine_default(&final);
+ if (r < 0)
+ return r;
+
+ if (!streq(final, unit))
+ log_notice("Note: \"%s\" is the default unit (possibly a runtime override).", final);
+ }
+
+finish:
+ unit_file_changes_free(changes, n_changes);
+
+ return r;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int get_default(int argc, char *argv[], void *userdata);
+int set_default(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "env-util.h"
+#include "escape.h"
+#include "systemctl-set-environment.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int print_variable(const char *s) {
+ const char *sep;
+ _cleanup_free_ char *esc = NULL;
+
+ sep = strchr(s, '=');
+ if (!sep)
+ return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Invalid environment block");
+
+ esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
+ if (!esc)
+ return log_oom();
+
+ printf("%.*s=%s\n", (int)(sep-s), s, esc);
+ return 0;
+}
+
+int show_environment(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *text;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = bus_get_property(bus, bus_systemd_mgr, "Environment", &error, &reply, "as");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
+ r = print_variable(text);
+ if (r < 0)
+ return r;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+static void invalid_callback(const char *p, void *userdata) {
+ _cleanup_free_ char *t = cescape(p);
+
+ log_debug("Ignoring invalid environment assignment \"%s\".", strnull(t));
+}
+
+int set_environment(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ const char *method;
+ sd_bus *bus;
+ int r;
+
+ assert(argc > 1);
+ assert(argv);
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ method = streq(argv[0], "set-environment")
+ ? "SetEnvironment"
+ : "UnsetEnvironment";
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+int import_environment(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetEnvironment");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (argc < 2) {
+ _cleanup_strv_free_ char **copy = NULL;
+
+ copy = strv_copy(environ);
+ if (!copy)
+ return log_oom();
+
+ strv_env_clean_with_callback(copy, invalid_callback, NULL);
+
+ r = sd_bus_message_append_strv(m, copy);
+
+ } else {
+ char **a, **b;
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ STRV_FOREACH(a, strv_skip(argv, 1)) {
+
+ if (!env_name_is_valid(*a))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid environment variable name: %s", *a);
+
+ STRV_FOREACH(b, environ) {
+ const char *eq;
+
+ eq = startswith(*b, *a);
+ if (eq && *eq == '=') {
+
+ r = sd_bus_message_append(m, "s", *b);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ break;
+ }
+ }
+ }
+
+ r = sd_bus_message_close_container(m);
+ }
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int show_environment(int argc, char *argv[], void *userdata);
+int set_environment(int argc, char *argv[], void *userdata);
+int import_environment(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-set-property.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int set_property(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *n = NULL;
+ UnitType t;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetUnitProperties");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ t = unit_name_to_type(n);
+ if (t < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit type: %s", n);
+
+ r = sd_bus_message_append(m, "sb", n, arg_runtime);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = bus_append_unit_property_assignment_many(m, t, strv_skip(argv, 2));
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int set_property(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/mount.h>
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "bus-map-properties.h"
+#include "bus-print-properties.h"
+#include "bus-unit-procs.h"
+#include "cgroup-show.h"
+#include "cpu-set-util.h"
+#include "errno-util.h"
+#include "exec-util.h"
+#include "exit-status.h"
+#include "format-util.h"
+#include "hexdecoct.h"
+#include "hostname-util.h"
+#include "in-addr-util.h"
+#include "journal-util.h"
+#include "list.h"
+#include "locale-util.h"
+#include "memory-util.h"
+#include "numa-util.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-table.h"
+#include "systemctl-list-machines.h"
+#include "systemctl-list-units.h"
+#include "systemctl-show.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "utf8.h"
+
+static OutputFlags get_output_flags(void) {
+ return
+ arg_all * OUTPUT_SHOW_ALL |
+ (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ colors_enabled() * OUTPUT_COLOR |
+ !arg_quiet * OUTPUT_WARN_CUTOFF;
+}
+
+typedef struct ExecStatusInfo {
+ char *name;
+
+ char *path;
+ char **argv;
+
+ bool ignore;
+
+ usec_t start_timestamp;
+ usec_t exit_timestamp;
+ pid_t pid;
+ int code;
+ int status;
+
+ ExecCommandFlags flags;
+
+ LIST_FIELDS(struct ExecStatusInfo, exec);
+} ExecStatusInfo;
+
+static void exec_status_info_free(ExecStatusInfo *i) {
+ assert(i);
+
+ free(i->name);
+ free(i->path);
+ strv_free(i->argv);
+ free(i);
+}
+
+static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i, bool is_ex_prop) {
+ _cleanup_strv_free_ char **ex_opts = NULL;
+ uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
+ const char *path;
+ uint32_t pid;
+ int32_t code, status;
+ int ignore, r;
+
+ assert(m);
+ assert(i);
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, is_ex_prop ? "sasasttttuii" : "sasbttttuii");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ else if (r == 0)
+ return 0;
+
+ r = sd_bus_message_read(m, "s", &path);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ i->path = strdup(path);
+ if (!i->path)
+ return log_oom();
+
+ r = sd_bus_message_read_strv(m, &i->argv);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = is_ex_prop ? sd_bus_message_read_strv(m, &ex_opts) : sd_bus_message_read(m, "b", &ignore);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read(m,
+ "ttttuii",
+ &start_timestamp, &start_timestamp_monotonic,
+ &exit_timestamp, &exit_timestamp_monotonic,
+ &pid,
+ &code, &status);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (is_ex_prop) {
+ r = exec_command_flags_from_strv(ex_opts, &i->flags);
+ if (r < 0)
+ return log_error_errno(r, "Failed to convert strv to ExecCommandFlags: %m");
+
+ i->ignore = FLAGS_SET(i->flags, EXEC_COMMAND_IGNORE_FAILURE);
+ } else
+ i->ignore = ignore;
+
+ i->start_timestamp = (usec_t) start_timestamp;
+ i->exit_timestamp = (usec_t) exit_timestamp;
+ i->pid = (pid_t) pid;
+ i->code = code;
+ i->status = status;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+}
+
+typedef struct UnitCondition {
+ char *name;
+ char *param;
+ bool trigger;
+ bool negate;
+ int tristate;
+
+ LIST_FIELDS(struct UnitCondition, conditions);
+} UnitCondition;
+
+static void unit_condition_free(UnitCondition *c) {
+ if (!c)
+ return;
+
+ free(c->name);
+ free(c->param);
+ free(c);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
+
+typedef struct UnitStatusInfo {
+ const char *id;
+ const char *load_state;
+ const char *active_state;
+ const char *freezer_state;
+ const char *sub_state;
+ const char *unit_file_state;
+ const char *unit_file_preset;
+
+ const char *description;
+ const char *following;
+
+ char **documentation;
+
+ const char *fragment_path;
+ const char *source_path;
+ const char *control_group;
+
+ char **dropin_paths;
+
+ char **triggered_by;
+ char **triggers;
+
+ const char *load_error;
+ const char *result;
+
+ usec_t inactive_exit_timestamp;
+ usec_t inactive_exit_timestamp_monotonic;
+ usec_t active_enter_timestamp;
+ usec_t active_exit_timestamp;
+ usec_t inactive_enter_timestamp;
+
+ bool need_daemon_reload;
+ bool transient;
+
+ /* Service */
+ pid_t main_pid;
+ pid_t control_pid;
+ const char *status_text;
+ const char *pid_file;
+ bool running:1;
+ int status_errno;
+
+ usec_t start_timestamp;
+ usec_t exit_timestamp;
+
+ int exit_code, exit_status;
+
+ const char *log_namespace;
+
+ usec_t condition_timestamp;
+ bool condition_result;
+ LIST_HEAD(UnitCondition, conditions);
+
+ usec_t assert_timestamp;
+ bool assert_result;
+ bool failed_assert_trigger;
+ bool failed_assert_negate;
+ const char *failed_assert;
+ const char *failed_assert_parameter;
+ usec_t next_elapse_real;
+ usec_t next_elapse_monotonic;
+
+ /* Socket */
+ unsigned n_accepted;
+ unsigned n_connections;
+ unsigned n_refused;
+ bool accept;
+
+ /* Pairs of type, path */
+ char **listen;
+
+ /* Device */
+ const char *sysfs_path;
+
+ /* Mount, Automount */
+ const char *where;
+
+ /* Swap */
+ const char *what;
+
+ /* CGroup */
+ uint64_t memory_current;
+ uint64_t memory_min;
+ uint64_t memory_low;
+ uint64_t memory_high;
+ uint64_t memory_max;
+ uint64_t memory_swap_max;
+ uint64_t memory_limit;
+ uint64_t cpu_usage_nsec;
+ uint64_t tasks_current;
+ uint64_t tasks_max;
+ uint64_t ip_ingress_bytes;
+ uint64_t ip_egress_bytes;
+ uint64_t io_read_bytes;
+ uint64_t io_write_bytes;
+
+ uint64_t default_memory_min;
+ uint64_t default_memory_low;
+
+ LIST_HEAD(ExecStatusInfo, exec);
+} UnitStatusInfo;
+
+static void unit_status_info_free(UnitStatusInfo *info) {
+ ExecStatusInfo *p;
+ UnitCondition *c;
+
+ strv_free(info->documentation);
+ strv_free(info->dropin_paths);
+ strv_free(info->triggered_by);
+ strv_free(info->triggers);
+ strv_free(info->listen);
+
+ while ((c = info->conditions)) {
+ LIST_REMOVE(conditions, info->conditions, c);
+ unit_condition_free(c);
+ }
+
+ while ((p = info->exec)) {
+ LIST_REMOVE(exec, info->exec, p);
+ exec_status_info_free(p);
+ }
+}
+
+static void format_active_state(const char *active_state, const char **active_on, const char **active_off) {
+ if (streq_ptr(active_state, "failed")) {
+ *active_on = ansi_highlight_red();
+ *active_off = ansi_normal();
+ } else if (STRPTR_IN_SET(active_state, "active", "reloading")) {
+ *active_on = ansi_highlight_green();
+ *active_off = ansi_normal();
+ } else
+ *active_on = *active_off = "";
+}
+
+static void print_status_info(
+ sd_bus *bus,
+ UnitStatusInfo *i,
+ bool *ellipsized) {
+
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2, *active_on, *active_off, *on, *off, *ss, *fs;
+ _cleanup_free_ char *formatted_path = NULL;
+ ExecStatusInfo *p;
+ usec_t timestamp;
+ const char *path;
+ char **t, **t2;
+ int r;
+
+ assert(i);
+
+ /* This shows pretty information about a unit. See print_property() for a low-level property
+ * printer */
+
+ 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));
+
+ if (i->description && !streq_ptr(i->id, i->description))
+ printf(" - %s", i->description);
+
+ printf("\n");
+
+ if (i->following)
+ printf(" Follow: unit currently follows state of %s\n", i->following);
+
+ if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ } else
+ on = off = "";
+
+ path = i->source_path ?: i->fragment_path;
+ if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0)
+ path = formatted_path;
+
+ if (!isempty(i->load_error))
+ printf(" Loaded: %s%s%s (Reason: %s)\n",
+ on, strna(i->load_state), off, i->load_error);
+ else if (path && !isempty(i->unit_file_state)) {
+ bool show_preset = !isempty(i->unit_file_preset) &&
+ show_preset_for_state(unit_file_state_from_string(i->unit_file_state));
+
+ printf(" Loaded: %s%s%s (%s; %s%s%s)\n",
+ on, strna(i->load_state), off,
+ path,
+ i->unit_file_state,
+ show_preset ? "; vendor preset: " : "",
+ show_preset ? i->unit_file_preset : "");
+
+ } else if (path)
+ printf(" Loaded: %s%s%s (%s)\n",
+ on, strna(i->load_state), off, path);
+ else
+ printf(" Loaded: %s%s%s\n",
+ on, strna(i->load_state), off);
+
+ if (i->transient)
+ printf(" Transient: yes\n");
+
+ if (!strv_isempty(i->dropin_paths)) {
+ _cleanup_free_ char *dir = NULL;
+ bool last = false;
+ char ** dropin;
+
+ STRV_FOREACH(dropin, i->dropin_paths) {
+ _cleanup_free_ char *dropin_formatted = NULL;
+ const char *df;
+
+ if (!dir || last) {
+ printf(dir ? " " :
+ " Drop-In: ");
+
+ dir = mfree(dir);
+
+ dir = dirname_malloc(*dropin);
+ if (!dir) {
+ log_oom();
+ return;
+ }
+
+ printf("%s\n"
+ " %s", dir,
+ special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
+ }
+
+ last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
+
+ if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0)
+ df = dropin_formatted;
+ else
+ df = *dropin;
+
+ printf("%s%s", df, last ? "\n" : ", ");
+ }
+ }
+
+ ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
+ if (ss)
+ printf(" Active: %s%s (%s)%s",
+ active_on, strna(i->active_state), ss, active_off);
+ else
+ printf(" Active: %s%s%s",
+ active_on, strna(i->active_state), active_off);
+
+ fs = !isempty(i->freezer_state) && !streq(i->freezer_state, "running") ? i->freezer_state : NULL;
+ if (fs)
+ printf(" %s(%s)%s", ansi_highlight_yellow(), fs, ansi_normal());
+
+ if (!isempty(i->result) && !streq(i->result, "success"))
+ printf(" (Result: %s)", i->result);
+
+ timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
+ STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
+ STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
+ i->active_exit_timestamp;
+
+ s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
+ s2 = format_timestamp_style(since2, sizeof(since2), timestamp, arg_timestamp_style);
+
+ if (s1)
+ printf(" since %s; %s\n", s2, s1);
+ else if (s2)
+ printf(" since %s\n", s2);
+ else
+ printf("\n");
+
+ STRV_FOREACH(t, i->triggered_by) {
+ UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
+
+ (void) get_state_one_unit(bus, *t, &state);
+ format_active_state(unit_active_state_to_string(state), &on, &off);
+
+ printf("%s %s%s%s %s\n",
+ t == i->triggered_by ? "TriggeredBy:" : " ",
+ on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
+ *t);
+ }
+
+ if (endswith(i->id, ".timer")) {
+ char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
+ tstamp2[FORMAT_TIMESTAMP_MAX];
+ const char *next_rel_time, *next_time;
+ dual_timestamp nw, next = {i->next_elapse_real,
+ i->next_elapse_monotonic};
+ usec_t next_elapse;
+
+ printf(" Trigger: ");
+
+ dual_timestamp_get(&nw);
+ next_elapse = calc_next_elapse(&nw, &next);
+ next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
+ next_time = format_timestamp_style(tstamp2, sizeof tstamp2, next_elapse, arg_timestamp_style);
+
+ if (next_time && next_rel_time)
+ printf("%s; %s\n", next_time, next_rel_time);
+ else
+ printf("n/a\n");
+ }
+
+ STRV_FOREACH(t, i->triggers) {
+ UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
+
+ (void) get_state_one_unit(bus, *t, &state);
+ format_active_state(unit_active_state_to_string(state), &on, &off);
+
+ printf("%s %s%s%s %s\n",
+ t == i->triggers ? " Triggers:" : " ",
+ on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
+ *t);
+ }
+
+ if (!i->condition_result && i->condition_timestamp > 0) {
+ UnitCondition *c;
+ int n = 0;
+
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
+ s2 = format_timestamp_style(since2, sizeof(since2), i->condition_timestamp, arg_timestamp_style);
+
+ printf(" Condition: start %scondition failed%s at %s%s%s\n",
+ ansi_highlight_yellow(), ansi_normal(),
+ s2, s1 ? "; " : "", strempty(s1));
+
+ LIST_FOREACH(conditions, c, i->conditions)
+ if (c->tristate < 0)
+ n++;
+
+ LIST_FOREACH(conditions, c, i->conditions)
+ if (c->tristate < 0)
+ printf(" %s %s=%s%s%s was not met\n",
+ --n ? special_glyph(SPECIAL_GLYPH_TREE_BRANCH) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
+ c->name,
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->param);
+ }
+
+ if (!i->assert_result && i->assert_timestamp > 0) {
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
+ s2 = format_timestamp_style(since2, sizeof(since2), i->assert_timestamp, arg_timestamp_style);
+
+ printf(" Assert: start %sassertion failed%s at %s%s%s\n",
+ ansi_highlight_red(), ansi_normal(),
+ s2, s1 ? "; " : "", strempty(s1));
+ if (i->failed_assert_trigger)
+ printf(" none of the trigger assertions were met\n");
+ else if (i->failed_assert)
+ printf(" %s=%s%s was not met\n",
+ i->failed_assert,
+ i->failed_assert_negate ? "!" : "",
+ i->failed_assert_parameter);
+ }
+
+ if (i->sysfs_path)
+ printf(" Device: %s\n", i->sysfs_path);
+ if (i->where)
+ printf(" Where: %s\n", i->where);
+ if (i->what)
+ printf(" What: %s\n", i->what);
+
+ STRV_FOREACH(t, i->documentation) {
+ _cleanup_free_ char *formatted = NULL;
+ const char *q;
+
+ if (terminal_urlify(*t, NULL, &formatted) >= 0)
+ q = formatted;
+ else
+ q = *t;
+
+ printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q);
+ }
+
+ STRV_FOREACH_PAIR(t, t2, i->listen)
+ printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
+
+ if (i->accept) {
+ printf(" Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections);
+ if (i->n_refused)
+ printf(" Refused: %u", i->n_refused);
+ printf("\n");
+ }
+
+ LIST_FOREACH(exec, p, i->exec) {
+ _cleanup_free_ char *argv = NULL;
+ bool good;
+
+ /* Only show exited processes here */
+ if (p->code == 0)
+ continue;
+
+ /* Don't print ExecXYZEx= properties here since it will appear as a
+ * duplicate of the non-Ex= variant. */
+ if (endswith(p->name, "Ex"))
+ continue;
+
+ argv = strv_join(p->argv, " ");
+ printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
+
+ good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
+ if (!good) {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ } else
+ on = off = "";
+
+ printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
+
+ if (p->code == CLD_EXITED) {
+ const char *c;
+
+ printf("status=%i", p->status);
+
+ c = exit_status_to_string(p->status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
+ if (c)
+ printf("/%s", c);
+
+ } else
+ printf("signal=%s", signal_to_string(p->status));
+
+ printf(")%s\n", off);
+
+ if (i->main_pid == p->pid &&
+ i->start_timestamp == p->start_timestamp &&
+ i->exit_timestamp == p->start_timestamp)
+ /* Let's not show this twice */
+ i->main_pid = 0;
+
+ if (p->pid == i->control_pid)
+ i->control_pid = 0;
+ }
+
+ if (i->main_pid > 0 || i->control_pid > 0) {
+ if (i->main_pid > 0) {
+ printf(" Main PID: "PID_FMT, i->main_pid);
+
+ if (i->running) {
+
+ if (arg_transport == BUS_TRANSPORT_LOCAL) {
+ _cleanup_free_ char *comm = NULL;
+
+ (void) get_process_comm(i->main_pid, &comm);
+ if (comm)
+ printf(" (%s)", comm);
+ }
+
+ } else if (i->exit_code > 0) {
+ printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
+
+ if (i->exit_code == CLD_EXITED) {
+ const char *c;
+
+ printf("status=%i", i->exit_status);
+
+ c = exit_status_to_string(i->exit_status,
+ EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
+ if (c)
+ printf("/%s", c);
+
+ } else
+ printf("signal=%s", signal_to_string(i->exit_status));
+ printf(")");
+ }
+ }
+
+ if (i->control_pid > 0) {
+ _cleanup_free_ char *c = NULL;
+
+ if (i->main_pid > 0)
+ fputs("; Control PID: ", stdout);
+ else
+ fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
+
+ printf(PID_FMT, i->control_pid);
+
+ if (arg_transport == BUS_TRANSPORT_LOCAL) {
+ (void) get_process_comm(i->control_pid, &c);
+ if (c)
+ printf(" (%s)", c);
+ }
+ }
+
+ printf("\n");
+ }
+
+ if (i->status_text)
+ printf(" Status: \"%s\"\n", i->status_text);
+ if (i->status_errno > 0)
+ printf(" Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno));
+
+ if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
+ char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
+
+ printf(" IP: %s in, %s out\n",
+ format_bytes(buf_in, sizeof(buf_in), i->ip_ingress_bytes),
+ format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes));
+ }
+
+ if (i->io_read_bytes != UINT64_MAX && i->io_write_bytes != UINT64_MAX) {
+ char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
+
+ printf(" IO: %s read, %s written\n",
+ format_bytes(buf_in, sizeof(buf_in), i->io_read_bytes),
+ format_bytes(buf_out, sizeof(buf_out), i->io_write_bytes));
+ }
+
+ if (i->tasks_current != (uint64_t) -1) {
+ printf(" Tasks: %" PRIu64, i->tasks_current);
+
+ if (i->tasks_max != (uint64_t) -1)
+ printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
+ else
+ printf("\n");
+ }
+
+ if (i->memory_current != (uint64_t) -1) {
+ char buf[FORMAT_BYTES_MAX];
+
+ printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
+
+ if (i->memory_min > 0 || i->memory_low > 0 ||
+ i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
+ i->memory_swap_max != CGROUP_LIMIT_MAX ||
+ i->memory_limit != CGROUP_LIMIT_MAX) {
+ const char *prefix = "";
+
+ printf(" (");
+ if (i->memory_min > 0) {
+ printf("%smin: %s", prefix, format_bytes_cgroup_protection(buf, sizeof(buf), i->memory_min));
+ prefix = " ";
+ }
+ if (i->memory_low > 0) {
+ printf("%slow: %s", prefix, format_bytes_cgroup_protection(buf, sizeof(buf), i->memory_low));
+ prefix = " ";
+ }
+ if (i->memory_high != CGROUP_LIMIT_MAX) {
+ printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
+ prefix = " ";
+ }
+ if (i->memory_max != CGROUP_LIMIT_MAX) {
+ printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
+ prefix = " ";
+ }
+ if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
+ printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
+ prefix = " ";
+ }
+ if (i->memory_limit != CGROUP_LIMIT_MAX) {
+ printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
+ prefix = " ";
+ }
+ printf(")");
+ }
+ printf("\n");
+ }
+
+ if (i->cpu_usage_nsec != (uint64_t) -1) {
+ char buf[FORMAT_TIMESPAN_MAX];
+ printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
+ }
+
+ if (i->control_group) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ static const char prefix[] = " ";
+ unsigned c;
+
+ printf(" CGroup: %s\n", i->control_group);
+
+ c = columns();
+ if (c > sizeof(prefix) - 1)
+ c -= sizeof(prefix) - 1;
+ else
+ c = 0;
+
+ r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
+ if (r == -EBADR) {
+ unsigned k = 0;
+ pid_t extra[2];
+
+ /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
+
+ if (i->main_pid > 0)
+ extra[k++] = i->main_pid;
+
+ if (i->control_pid > 0)
+ extra[k++] = i->control_pid;
+
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
+ } else if (r < 0)
+ log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
+ i->id, bus_error_message(&error, r));
+ }
+
+ if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
+ show_journal_by_unit(
+ stdout,
+ i->id,
+ i->log_namespace,
+ arg_output,
+ 0,
+ i->inactive_exit_timestamp_monotonic,
+ arg_lines,
+ getuid(),
+ get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+ SD_JOURNAL_LOCAL_ONLY,
+ arg_scope == UNIT_FILE_SYSTEM,
+ ellipsized);
+
+ if (i->need_daemon_reload)
+ warn_unit_file_changed(i->id);
+}
+
+static void show_unit_help(UnitStatusInfo *i) {
+ char **p;
+
+ assert(i);
+
+ if (!i->documentation) {
+ log_info("Documentation for %s not known.", i->id);
+ return;
+ }
+
+ STRV_FOREACH(p, i->documentation)
+ if (startswith(*p, "man:"))
+ show_man_page(*p + 4, false);
+ else
+ log_info("Can't show: %s", *p);
+}
+
+static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ uint32_t u;
+ int r;
+
+ r = sd_bus_message_read(m, "u", &u);
+ if (r < 0)
+ return r;
+
+ i->main_pid = (pid_t) u;
+ i->running = u > 0;
+
+ return 0;
+}
+
+static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *message, **p = userdata;
+ int r;
+
+ r = sd_bus_message_read(m, "(ss)", NULL, &message);
+ if (r < 0)
+ return r;
+
+ if (!isempty(message))
+ *p = message;
+
+ return 0;
+}
+
+static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *type, *path;
+ char ***p = userdata;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
+
+ r = strv_extend(p, type);
+ if (r < 0)
+ return r;
+
+ r = strv_extend(p, path);
+ if (r < 0)
+ return r;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
+ _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
+
+ c = new(UnitCondition, 1);
+ if (!c)
+ return -ENOMEM;
+
+ *c = (UnitCondition) {
+ .name = strdup(cond),
+ .param = strdup(param),
+ .trigger = trigger,
+ .negate = negate,
+ .tristate = state,
+ };
+
+ if (!c->name || !c->param)
+ return -ENOMEM;
+
+ LIST_PREPEND(conditions, i->conditions, TAKE_PTR(c));
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
+ if (state < 0 && (!trigger || !i->failed_assert)) {
+ i->failed_assert = cond;
+ i->failed_assert_trigger = trigger;
+ i->failed_assert_negate = negate;
+ i->failed_assert_parameter = param;
+ }
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ _cleanup_free_ ExecStatusInfo *info = NULL;
+ ExecStatusInfo *last;
+ UnitStatusInfo *i = userdata;
+ bool is_ex_prop = endswith(member, "Ex");
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
+ if (r < 0)
+ return r;
+
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
+
+ LIST_FIND_TAIL(exec, i->exec, last);
+
+ while ((r = exec_status_info_deserialize(m, info, is_ex_prop)) > 0) {
+
+ info->name = strdup(member);
+ if (!info->name)
+ return -ENOMEM;
+
+ LIST_INSERT_AFTER(exec, i->exec, last, info);
+ last = info;
+
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+ char bus_type;
+ const char *contents;
+ int r;
+
+ assert(name);
+ assert(m);
+
+ /* This is a low-level property printer, see print_status_info() for the nicer output */
+
+ r = sd_bus_message_peek_type(m, &bus_type, &contents);
+ if (r < 0)
+ return r;
+
+ switch (bus_type) {
+
+ case SD_BUS_TYPE_INT32:
+ if (endswith(name, "ActionExitStatus")) {
+ int32_t i;
+
+ r = sd_bus_message_read_basic(m, bus_type, &i);
+ if (r < 0)
+ return r;
+
+ if (i >= 0 && i <= 255)
+ bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "[not set]");
+
+ return 1;
+ } else if (streq(name, "NUMAPolicy")) {
+ int32_t i;
+
+ r = sd_bus_message_read_basic(m, bus_type, &i);
+ if (r < 0)
+ return r;
+
+ bus_print_property_valuef(name, expected_value, value, "%s", strna(mpol_to_string(i)));
+
+ return 1;
+ }
+ break;
+
+ case SD_BUS_TYPE_STRUCT:
+
+ if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
+ uint32_t u;
+
+ r = sd_bus_message_read(m, "(uo)", &u, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (u > 0)
+ bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "");
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
+ const char *s;
+
+ r = sd_bus_message_read(m, "(so)", &s, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(s))
+ bus_print_property_value(name, expected_value, value, s);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
+ const char *a = NULL, *b = NULL;
+
+ r = sd_bus_message_read(m, "(ss)", &a, &b);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!isempty(a) || !isempty(b))
+ bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "");
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies")) {
+ _cleanup_strv_free_ char **l = NULL;
+ int allow_list;
+
+ r = sd_bus_message_enter_container(m, 'r', "bas");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read(m, "b", &allow_list);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_strv(m, &l);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || allow_list || !strv_isempty(l)) {
+ bool first = true;
+ char **i;
+
+ if (!value) {
+ fputs(name, stdout);
+ fputc('=', stdout);
+ }
+
+ if (!allow_list)
+ fputc('~', stdout);
+
+ STRV_FOREACH(i, l) {
+ if (first)
+ first = false;
+ else
+ fputc(' ', stdout);
+
+ fputs(*i, stdout);
+ }
+ fputc('\n', stdout);
+ }
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
+ int ignore;
+ const char *s;
+
+ r = sd_bus_message_read(m, "(bs)", &ignore, &s);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!isempty(s))
+ bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
+ else if (all)
+ bus_print_property_value(name, expected_value, value, "");
+
+ return 1;
+
+ } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
+ const int32_t *status, *signal;
+ size_t n_status, n_signal, i;
+
+ r = sd_bus_message_enter_container(m, 'r', "aiai");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'i', (const void **) &status, &n_status);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &n_signal);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ n_status /= sizeof(int32_t);
+ n_signal /= sizeof(int32_t);
+
+ if (all || n_status > 0 || n_signal > 0) {
+ bool first = true;
+
+ if (!value) {
+ fputs(name, stdout);
+ fputc('=', stdout);
+ }
+
+ for (i = 0; i < n_status; i++) {
+ if (first)
+ first = false;
+ else
+ fputc(' ', stdout);
+
+ printf("%"PRIi32, status[i]);
+ }
+
+ for (i = 0; i < n_signal; i++) {
+ const char *str;
+
+ str = signal_to_string((int) signal[i]);
+
+ if (first)
+ first = false;
+ else
+ fputc(' ', stdout);
+
+ if (str)
+ fputs(str, stdout);
+ else
+ printf("%"PRIi32, status[i]);
+ }
+
+ fputc('\n', stdout);
+ }
+ return 1;
+ }
+
+ break;
+
+ case SD_BUS_TYPE_ARRAY:
+
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
+ const char *path;
+ int ignore;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
+
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
+ const char *type, *path;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
+ const char *type, *path;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
+ const char *base;
+ uint64_t v, next_elapse;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
+ char timespan1[FORMAT_TIMESPAN_MAX] = "n/a", timespan2[FORMAT_TIMESPAN_MAX] = "n/a";
+
+ (void) format_timespan(timespan1, sizeof timespan1, v, 0);
+ (void) format_timespan(timespan2, sizeof timespan2, next_elapse, 0);
+
+ bus_print_property_valuef(name, expected_value, value,
+ "{ %s=%s ; next_elapse=%s }", base, timespan1, timespan2);
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
+ const char *base, *spec;
+ uint64_t next_elapse;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
+ char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a";
+
+ (void) format_timestamp_style(timestamp, sizeof(timestamp), next_elapse, arg_timestamp_style);
+ bus_print_property_valuef(name, expected_value, value,
+ "{ %s=%s ; next_elapse=%s }", base, spec, timestamp);
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
+ ExecStatusInfo info = {};
+ bool is_ex_prop = endswith(name, "Ex");
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = exec_status_info_deserialize(m, &info, is_ex_prop)) > 0) {
+ char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
+ _cleanup_strv_free_ char **optv = NULL;
+ _cleanup_free_ char *tt, *o = NULL;
+
+ tt = strv_join(info.argv, " ");
+
+ if (is_ex_prop) {
+ r = exec_command_flags_to_strv(info.flags, &optv);
+ if (r < 0)
+ return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
+
+ o = strv_join(optv, " ");
+
+ bus_print_property_valuef(name, expected_value, value,
+ "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
+ strna(info.path),
+ strna(tt),
+ strna(o),
+ strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
+ strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
+ info.pid,
+ sigchld_code_to_string(info.code),
+ info.status,
+ info.code == CLD_EXITED ? "" : "/",
+ strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
+ } else
+ bus_print_property_valuef(name, expected_value, value,
+ "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
+ strna(info.path),
+ strna(tt),
+ yes_no(info.ignore),
+ strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
+ strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
+ info.pid,
+ sigchld_code_to_string(info.code),
+ info.status,
+ info.code == CLD_EXITED ? "" : "/",
+ strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
+
+ free(info.path);
+ strv_free(info.argv);
+ zero(info);
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
+ const char *path, *rwm;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
+ const char *path;
+ uint64_t weight;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ (cgroup_io_limit_type_from_string(name) >= 0 ||
+ STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
+ const char *path;
+ uint64_t bandwidth;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ streq(name, "IODeviceLatencyTargetUSec")) {
+ char ts[FORMAT_TIMESPAN_MAX];
+ const char *path;
+ uint64_t target;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
+ bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
+ format_timespan(ts, sizeof(ts), target, 1));
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 1;
+
+ } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "StandardInputData", "RootHashSignature")) {
+ _cleanup_free_ char *h = NULL;
+ const void *p;
+ size_t sz;
+ ssize_t n;
+
+ r = sd_bus_message_read_array(m, 'y', &p, &sz);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ n = base64mem(p, sz, &h);
+ if (n < 0)
+ return log_oom();
+
+ bus_print_property_value(name, expected_value, value, h);
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
+ _cleanup_free_ char *addresses = NULL;
+
+ r = sd_bus_message_enter_container(m, 'a', "(iayu)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ _cleanup_free_ char *str = NULL;
+ uint32_t prefixlen;
+ int32_t family;
+ const void *ap;
+ size_t an;
+
+ r = sd_bus_message_enter_container(m, 'r', "iayu");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_read(m, "i", &family);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(m, 'y', &ap, &an);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read(m, "u", &prefixlen);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!IN_SET(family, AF_INET, AF_INET6))
+ continue;
+
+ if (an != FAMILY_ADDRESS_SIZE(family))
+ continue;
+
+ if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
+ continue;
+
+ if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0)
+ continue;
+
+ if (!strextend_with_separator(&addresses, " ", str, NULL))
+ return log_oom();
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(addresses))
+ bus_print_property_value(name, expected_value, value, strempty(addresses));
+
+ return 1;
+
+ } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
+ _cleanup_free_ char *paths = NULL;
+ const char *source, *dest;
+ int ignore_enoent;
+ uint64_t rbind;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
+ _cleanup_free_ char *str = NULL;
+
+ if (isempty(source))
+ continue;
+
+ if (asprintf(&str, "%s%s%s%s%s",
+ ignore_enoent ? "-" : "",
+ source,
+ isempty(dest) ? "" : ":",
+ strempty(dest),
+ rbind == MS_REC ? ":rbind" : "") < 0)
+ return log_oom();
+
+ if (!strextend_with_separator(&paths, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(paths))
+ bus_print_property_value(name, expected_value, value, strempty(paths));
+
+ return 1;
+
+ } else if (streq(name, "TemporaryFileSystem")) {
+ _cleanup_free_ char *paths = NULL;
+ const char *target, *option;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
+ _cleanup_free_ char *str = NULL;
+
+ if (isempty(target))
+ continue;
+
+ if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
+ return log_oom();
+
+ if (!strextend_with_separator(&paths, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(paths))
+ bus_print_property_value(name, expected_value, value, strempty(paths));
+
+ return 1;
+
+ } else if (streq(name, "LogExtraFields")) {
+ _cleanup_free_ char *fields = NULL;
+ const void *p;
+ size_t sz;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
+ _cleanup_free_ char *str = NULL;
+ const char *eq;
+
+ if (memchr(p, 0, sz))
+ continue;
+
+ eq = memchr(p, '=', sz);
+ if (!eq)
+ continue;
+
+ if (!journal_field_valid(p, eq - (const char*) p, false))
+ continue;
+
+ str = malloc(sz + 1);
+ if (!str)
+ return log_oom();
+
+ memcpy(str, p, sz);
+ str[sz] = '\0';
+
+ if (!utf8_is_valid(str))
+ continue;
+
+ if (!strextend_with_separator(&fields, " ", str, NULL))
+ return log_oom();
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(fields))
+ bus_print_property_value(name, expected_value, value, strempty(fields));
+
+ return 1;
+ } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) {
+ _cleanup_free_ char *affinity = NULL;
+ _cleanup_(cpu_set_reset) CPUSet set = {};
+ const void *a;
+ size_t n;
+
+ r = sd_bus_message_read_array(m, 'y', &a, &n);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = cpu_set_from_dbus(a, n, &set);
+ if (r < 0)
+ return log_error_errno(r, "Failed to deserialize %s: %m", name);
+
+ affinity = cpu_set_to_range_string(&set);
+ if (!affinity)
+ return log_oom();
+
+ bus_print_property_value(name, expected_value, value, affinity);
+
+ return 1;
+ } else if (streq(name, "MountImages")) {
+ _cleanup_free_ char *paths = NULL;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssba(ss))");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ _cleanup_free_ char *str = NULL;
+ const char *source, *destination, *partition, *mount_options;
+ int ignore_enoent;
+
+ r = sd_bus_message_enter_container(m, 'r', "ssba(ss)");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(m, "ssb", &source, &destination, &ignore_enoent);
+ if (r <= 0)
+ break;
+
+ str = strjoin(ignore_enoent ? "-" : "",
+ source,
+ ":",
+ destination);
+ if (!str)
+ return log_oom();
+
+ r = sd_bus_message_enter_container(m, 'a', "(ss)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0) {
+ _cleanup_free_ char *previous = NULL;
+
+ previous = TAKE_PTR(str);
+ str = strjoin(strempty(previous), previous ? ":" : "", partition, ":", mount_options);
+ if (!str)
+ return log_oom();
+ }
+ if (r < 0)
+ return r;
+
+ if (!strextend_with_separator(&paths, " ", str, NULL))
+ return log_oom();
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (all || !isempty(paths))
+ bus_print_property_value(name, expected_value, value, strempty(paths));
+
+ return 1;
+
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+typedef enum SystemctlShowMode{
+ SYSTEMCTL_SHOW_PROPERTIES,
+ SYSTEMCTL_SHOW_STATUS,
+ SYSTEMCTL_SHOW_HELP,
+ _SYSTEMCTL_SHOW_MODE_MAX,
+ _SYSTEMCTL_SHOW_MODE_INVALID = -1,
+} SystemctlShowMode;
+
+static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = {
+ [SYSTEMCTL_SHOW_PROPERTIES] = "show",
+ [SYSTEMCTL_SHOW_STATUS] = "status",
+ [SYSTEMCTL_SHOW_HELP] = "help",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
+
+static int show_one(
+ sd_bus *bus,
+ const char *path,
+ const char *unit,
+ SystemctlShowMode show_mode,
+ bool *new_line,
+ bool *ellipsized) {
+
+ static const struct bus_properties_map property_map[] = {
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "FreezerState", "s", NULL, offsetof(UnitStatusInfo, freezer_state) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ {}
+ }, status_map[] = {
+ { "Id", "s", NULL, offsetof(UnitStatusInfo, id) },
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "FreezerState", "s", NULL, offsetof(UnitStatusInfo, freezer_state) },
+ { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) },
+ { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
+ { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) },
+ { "Description", "s", NULL, offsetof(UnitStatusInfo, description) },
+ { "Following", "s", NULL, offsetof(UnitStatusInfo, following) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) },
+ { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) },
+ { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) },
+ { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) },
+ { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) },
+ { "Result", "s", NULL, offsetof(UnitStatusInfo, result) },
+ { "TriggeredBy", "as", NULL, offsetof(UnitStatusInfo, triggered_by) },
+ { "Triggers", "as", NULL, offsetof(UnitStatusInfo, triggers) },
+ { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) },
+ { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
+ { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) },
+ { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) },
+ { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) },
+ { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) },
+ { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) },
+ { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) },
+ { "MainPID", "u", map_main_pid, 0 },
+ { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) },
+ { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) },
+ { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) },
+ { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) },
+ { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) },
+ { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) },
+ { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) },
+ { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) },
+ { "LogNamespace", "s", NULL, offsetof(UnitStatusInfo, log_namespace) },
+ { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) },
+ { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) },
+ { "Conditions", "a(sbbsi)", map_conditions, 0 },
+ { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) },
+ { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) },
+ { "Asserts", "a(sbbsi)", map_asserts, 0 },
+ { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) },
+ { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) },
+ { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) },
+ { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) },
+ { "NRefused", "u", NULL, offsetof(UnitStatusInfo, n_refused) },
+ { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) },
+ { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) },
+ { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) },
+ { "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
+ { "What", "s", NULL, offsetof(UnitStatusInfo, what) },
+ { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
+ { "DefaultMemoryMin", "t", NULL, offsetof(UnitStatusInfo, default_memory_min) },
+ { "DefaultMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_memory_low) },
+ { "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) },
+ { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
+ { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },
+ { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) },
+ { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) },
+ { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) },
+ { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) },
+ { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) },
+ { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
+ { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
+ { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
+ { "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) },
+ { "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) },
+ { "ExecCondition", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStartPreEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecStart", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStartEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStartPostEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecReload", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecReloadEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStop", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopEx", "a(sasasttttuii)", map_exec, 0 },
+ { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopPostEx", "a(sasasttttuii)", map_exec, 0 },
+ {}
+ };
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_set_free_ Set *found_properties = NULL;
+ _cleanup_(unit_status_info_free) UnitStatusInfo info = {
+ .memory_current = (uint64_t) -1,
+ .memory_high = CGROUP_LIMIT_MAX,
+ .memory_max = CGROUP_LIMIT_MAX,
+ .memory_swap_max = CGROUP_LIMIT_MAX,
+ .memory_limit = (uint64_t) -1,
+ .cpu_usage_nsec = (uint64_t) -1,
+ .tasks_current = (uint64_t) -1,
+ .tasks_max = (uint64_t) -1,
+ .ip_ingress_bytes = (uint64_t) -1,
+ .ip_egress_bytes = (uint64_t) -1,
+ .io_read_bytes = UINT64_MAX,
+ .io_write_bytes = UINT64_MAX,
+ };
+ char **pp;
+ int r;
+
+ assert(path);
+ assert(new_line);
+
+ log_debug("Showing one %s", path);
+
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
+ &error,
+ &reply,
+ &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+
+ if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
+ log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG,
+ "Unit %s could not be found.", unit);
+
+ if (show_mode == SYSTEMCTL_SHOW_STATUS)
+ return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+ else if (show_mode == SYSTEMCTL_SHOW_HELP)
+ return -ENOENT;
+ }
+
+ if (*new_line)
+ printf("\n");
+
+ *new_line = true;
+
+ if (show_mode == SYSTEMCTL_SHOW_STATUS) {
+ print_status_info(bus, &info, ellipsized);
+
+ if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
+ return EXIT_PROGRAM_NOT_RUNNING;
+
+ return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
+
+ } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
+ show_unit_help(&info);
+ return 0;
+ }
+
+ r = sd_bus_message_rewind(reply, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+
+ r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ STRV_FOREACH(pp, arg_properties)
+ if (!set_contains(found_properties, *pp))
+ log_debug("Property %s does not exist.", *pp);
+
+ return 0;
+}
+
+static int get_unit_dbus_path_by_pid(
+ sd_bus *bus,
+ uint32_t pid,
+ char **unit) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ char *u;
+ int r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", pid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "o", &u);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ u = strdup(u);
+ if (!u)
+ return log_oom();
+
+ *unit = u;
+ return 0;
+}
+
+static int show_all(
+ sd_bus *bus,
+ bool *new_line,
+ bool *ellipsized) {
+
+ _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;
+
+ r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ c = (unsigned) r;
+
+ typesafe_qsort(unit_infos, c, unit_info_compare);
+
+ for (u = unit_infos; u < unit_infos + c; u++) {
+ _cleanup_free_ char *p = NULL;
+
+ p = unit_dbus_path_from_name(u->id);
+ if (!p)
+ return log_oom();
+
+ r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
+ if (r < 0)
+ return r;
+ else if (r > 0 && ret == 0)
+ ret = r;
+ }
+
+ return ret;
+}
+
+static int show_system_status(sd_bus *bus) {
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(machine_info_clear) struct machine_info mi = {};
+ _cleanup_free_ char *hn = NULL;
+ const char *on, *off;
+ int r;
+
+ hn = gethostname_malloc();
+ if (!hn)
+ return log_oom();
+
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ machine_info_property_map,
+ BUS_MAP_STRDUP,
+ &error,
+ NULL,
+ &mi);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
+
+ if (streq_ptr(mi.state, "degraded")) {
+ on = ansi_highlight_red();
+ off = ansi_normal();
+ } else if (streq_ptr(mi.state, "running")) {
+ on = ansi_highlight_green();
+ off = ansi_normal();
+ } else {
+ on = ansi_highlight_yellow();
+ off = ansi_normal();
+ }
+
+ printf("%s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
+
+ printf(" State: %s%s%s\n",
+ on, strna(mi.state), off);
+
+ printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
+ printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
+
+ printf(" Since: %s; %s\n",
+ format_timestamp_style(since2, sizeof(since2), mi.timestamp, arg_timestamp_style),
+ format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
+
+ printf(" CGroup: %s\n", mi.control_group ?: "/");
+ if (IN_SET(arg_transport,
+ BUS_TRANSPORT_LOCAL,
+ BUS_TRANSPORT_MACHINE)) {
+ static const char prefix[] = " ";
+ unsigned c;
+
+ c = columns();
+ if (c > sizeof(prefix) - 1)
+ c -= sizeof(prefix) - 1;
+ else
+ c = 0;
+
+ show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
+ }
+
+ return 0;
+}
+
+int show(int argc, char *argv[], void *userdata) {
+ bool new_line = false, ellipsized = false;
+ SystemctlShowMode show_mode;
+ int r, ret = 0;
+ sd_bus *bus;
+
+ assert(argv);
+
+ show_mode = systemctl_show_mode_from_string(argv[0]);
+ if (show_mode < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid argument.");
+
+ if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "'help' command expects one or more unit names.\n"
+ "(Alternatively, help for systemctl itself may be shown with --help)");
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_pager_flags);
+
+ /* If no argument is specified inspect the manager itself */
+ if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
+ return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
+
+ if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
+
+ show_system_status(bus);
+ new_line = true;
+
+ if (arg_all)
+ ret = show_all(bus, &new_line, &ellipsized);
+ } else {
+ _cleanup_free_ char **patterns = NULL;
+ char **name;
+
+ STRV_FOREACH(name, strv_skip(argv, 1)) {
+ _cleanup_free_ char *path = NULL, *unit = NULL;
+ uint32_t id;
+
+ if (safe_atou32(*name, &id) < 0) {
+ if (strv_push(&patterns, *name) < 0)
+ return log_oom();
+
+ continue;
+ } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
+ /* Interpret as job id */
+ if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
+ return log_oom();
+
+ } else {
+ /* Interpret as PID */
+ r = get_unit_dbus_path_by_pid(bus, id, &path);
+ if (r < 0) {
+ ret = r;
+ continue;
+ }
+
+ r = unit_name_from_dbus_path(path, &unit);
+ if (r < 0)
+ return log_oom();
+ }
+
+ r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
+ if (r < 0)
+ return r;
+ else if (r > 0 && ret == 0)
+ ret = r;
+ }
+
+ if (!strv_isempty(patterns)) {
+ _cleanup_strv_free_ char **names = NULL;
+
+ r = expand_unit_names(bus, patterns, NULL, &names, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ r = maybe_extend_with_unit_dependencies(bus, &names);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(name, names) {
+ _cleanup_free_ char *path;
+
+ path = unit_dbus_path_from_name(*name);
+ if (!path)
+ return log_oom();
+
+ r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
+ if (r < 0)
+ return r;
+ if (r > 0 && ret == 0)
+ ret = r;
+ }
+ }
+ }
+
+ if (ellipsized && !arg_quiet)
+ printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
+
+ return ret;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int show(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bootspec.h"
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "efivars.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "reboot-util.h"
+#include "systemctl-logind.h"
+#include "systemctl-start-special.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-trivial-method.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+static int load_kexec_kernel(void) {
+ _cleanup_(boot_config_free) BootConfig config = {};
+ _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL;
+ const BootEntry *e;
+ pid_t pid;
+ int r;
+
+ if (kexec_loaded()) {
+ log_debug("Kexec kernel already loaded.");
+ return 0;
+ }
+
+ if (access(KEXEC, X_OK) < 0)
+ return log_error_errno(errno, KEXEC" is not available: %m");
+
+ r = boot_entries_load_config_auto(NULL, NULL, &config);
+ if (r == -ENOKEY)
+ /* The call doesn't log about ENOKEY, let's do so here. */
+ return log_error_errno(r,
+ "No kexec kernel loaded and autodetection failed.\n%s",
+ is_efi_boot()
+ ? "Cannot automatically load kernel: ESP partition mount point not found."
+ : "Automatic loading works only on systems booted with EFI.");
+ if (r < 0)
+ return r;
+
+ e = boot_config_default_entry(&config);
+ if (!e)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "No boot loader entry suitable as default, refusing to guess.");
+
+ log_debug("Found default boot loader entry in file \"%s\"", e->path);
+
+ if (!e->kernel)
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Boot entry does not refer to Linux kernel, which is not supported currently.");
+ if (strv_length(e->initrd) > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Boot entry specifies multiple initrds, which is not supported currently.");
+
+ kernel = path_join(e->root, e->kernel);
+ if (!kernel)
+ return log_oom();
+
+ if (!strv_isempty(e->initrd)) {
+ initrd = path_join(e->root, e->initrd[0]);
+ if (!initrd)
+ return log_oom();
+ }
+
+ options = strv_join(e->options, " ");
+ if (!options)
+ return log_oom();
+
+ log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
+ "%s "KEXEC" --load \"%s\" --append \"%s\"%s%s%s",
+ arg_dry_run ? "Would run" : "Running",
+ kernel,
+ options,
+ initrd ? " --initrd \"" : NULL, strempty(initrd), initrd ? "\"" : "");
+ if (arg_dry_run)
+ return 0;
+
+ r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ const char* const args[] = {
+ KEXEC,
+ "--load", kernel,
+ "--append", options,
+ initrd ? "--initrd" : NULL, initrd,
+ NULL
+ };
+
+ /* Child */
+ execv(args[0], (char * const *) args);
+ _exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
+
+static int set_exit_code(uint8_t code) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "SetExitCode", &error, NULL, "y", code);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+int start_special(int argc, char *argv[], void *userdata) {
+ bool termination_action; /* An action that terminates the manager, can be performed also by
+ * signal. */
+ enum action a;
+ int r;
+
+ assert(argv);
+
+ a = verb_to_action(argv[0]);
+
+ r = logind_check_inhibitors(a);
+ if (r < 0)
+ return r;
+
+ if (arg_force >= 2) {
+ r = must_be_root();
+ if (r < 0)
+ return r;
+ }
+
+ r = prepare_firmware_setup();
+ if (r < 0)
+ return r;
+
+ r = prepare_boot_loader_menu();
+ if (r < 0)
+ return r;
+
+ r = prepare_boot_loader_entry();
+ if (r < 0)
+ return r;
+
+ if (a == ACTION_REBOOT) {
+ const char *arg = NULL;
+
+ if (argc > 1) {
+ if (arg_reboot_argument)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Both --reboot-argument= and positional argument passed to reboot command, refusing.");
+
+ log_notice("Positional argument to reboot command is deprecated, please use --reboot-argument= instead. Accepting anyway.");
+ arg = argv[1];
+ } else
+ arg = arg_reboot_argument;
+
+ if (arg) {
+ r = update_reboot_parameter_and_warn(arg, false);
+ if (r < 0)
+ return r;
+ }
+
+ } else if (a == ACTION_KEXEC) {
+ r = load_kexec_kernel();
+ if (r < 0 && arg_force >= 1)
+ log_notice("Failed to load kexec kernel, continuing without.");
+ else if (r < 0)
+ return r;
+
+ } else if (a == ACTION_EXIT && argc > 1) {
+ uint8_t code;
+
+ /* If the exit code is not given on the command line, don't reset it to zero: just keep it as
+ * it might have been set previously. */
+
+ r = safe_atou8(argv[1], &code);
+ if (r < 0)
+ return log_error_errno(r, "Invalid exit code.");
+
+ r = set_exit_code(code);
+ if (r < 0)
+ return r;
+ }
+
+ termination_action = IN_SET(a,
+ ACTION_HALT,
+ ACTION_POWEROFF,
+ ACTION_REBOOT);
+ if (termination_action && arg_force >= 2)
+ return halt_now(a);
+
+ if (arg_force >= 1 &&
+ (termination_action || IN_SET(a, ACTION_KEXEC, ACTION_EXIT)))
+ r = trivial_method(argc, argv, userdata);
+ else {
+ /* First try logind, to allow authentication with polkit */
+ if (IN_SET(a,
+ ACTION_POWEROFF,
+ ACTION_REBOOT,
+ ACTION_HALT,
+ ACTION_SUSPEND,
+ ACTION_HIBERNATE,
+ ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE)) {
+
+ r = logind_reboot(a);
+ if (r >= 0)
+ return r;
+ if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
+ /* Requested operation is not supported or already in progress */
+ return r;
+
+ /* On all other errors, try low-level operation. In order to minimize the difference
+ * between operation with and without logind, we explicitly enable non-blocking mode
+ * for this, as logind's shutdown operations are always non-blocking. */
+
+ arg_no_block = true;
+
+ } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
+ /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make
+ * them asynchronous, in order to not confuse the user needlessly with unexpected
+ * behaviour. */
+ arg_no_block = true;
+
+ r = start_unit(argc, argv, userdata);
+ }
+
+ if (termination_action && arg_force < 2 &&
+ IN_SET(r, -ENOENT, -ETIMEDOUT))
+ log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
+
+ return r;
+}
+
+int start_system_special(int argc, char *argv[], void *userdata) {
+ /* Like start_special above, but raises an error when running in user mode */
+
+ if (arg_scope != UNIT_FILE_SYSTEM)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Bad action for %s mode.",
+ arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
+
+ return start_special(argc, argv, userdata);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int start_special(int argc, char *argv[], void *userdata);
+int start_system_special(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-bus.h"
+
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "bus-util.h"
+#include "bus-wait-for-jobs.h"
+#include "bus-wait-for-units.h"
+#include "macro.h"
+#include "special.h"
+#include "string-util.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+
+static const struct {
+ const char *verb; /* systemctl verb */
+ const char *method; /* Name of the specific D-Bus method */
+ const char *job_type; /* Job type when passing to the generic EnqueueUnitJob() method */
+} unit_actions[] = {
+ { "start", "StartUnit", "start" },
+ { "stop", "StopUnit", "stop" },
+ { "condstop", "StopUnit", "stop" }, /* legacy alias */
+ { "reload", "ReloadUnit", "reload" },
+ { "restart", "RestartUnit", "restart" },
+ { "try-restart", "TryRestartUnit", "try-restart" },
+ { "condrestart", "TryRestartUnit", "try-restart" }, /* legacy alias */
+ { "reload-or-restart", "ReloadOrRestartUnit", "reload-or-restart" },
+ { "try-reload-or-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" },
+ { "reload-or-try-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
+ { "condreload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
+ { "force-reload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
+};
+
+static const char *verb_to_method(const char *verb) {
+ size_t i;
+
+ for (i = 0; i < ELEMENTSOF(unit_actions); i++)
+ if (streq_ptr(unit_actions[i].verb, verb))
+ return unit_actions[i].method;
+
+ return "StartUnit";
+}
+
+static const char *verb_to_job_type(const char *verb) {
+ size_t i;
+
+ for (i = 0; i < ELEMENTSOF(unit_actions); i++)
+ if (streq_ptr(unit_actions[i].verb, verb))
+ return unit_actions[i].job_type;
+
+ return "start";
+}
+
+static int start_unit_one(
+ sd_bus *bus,
+ const char *method, /* When using classic per-job bus methods */
+ const char *job_type, /* When using new-style EnqueueUnitJob() */
+ const char *name,
+ const char *mode,
+ sd_bus_error *error,
+ BusWaitForJobs *w,
+ BusWaitForUnits *wu) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *path;
+ bool done = false;
+ int r;
+
+ assert(method);
+ assert(name);
+ assert(mode);
+ assert(error);
+
+ log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
+ arg_dry_run ? "Would execute" : "Executing",
+ method, name, mode);
+
+ if (arg_dry_run)
+ return 0;
+
+ if (arg_show_transaction) {
+ _cleanup_(sd_bus_error_free) sd_bus_error enqueue_error = SD_BUS_ERROR_NULL;
+
+ /* Use the new, fancy EnqueueUnitJob() API if the user wants us to print the transaction */
+ r = bus_call_method(
+ bus,
+ bus_systemd_mgr,
+ "EnqueueUnitJob",
+ &enqueue_error,
+ &reply,
+ "sss",
+ name, job_type, mode);
+ if (r < 0) {
+ if (!sd_bus_error_has_name(&enqueue_error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
+ (void) sd_bus_error_move(error, &enqueue_error);
+ goto fail;
+ }
+
+ /* Hmm, the API is not yet available. Let's use the classic API instead (see below). */
+ log_notice("--show-transaction not supported by this service manager, proceeding without.");
+ } else {
+ const char *u, *jt;
+ uint32_t id;
+
+ r = sd_bus_message_read(reply, "uosos", &id, &path, &u, NULL, &jt);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ log_info("Enqueued anchor job %" PRIu32 " %s/%s.", id, u, jt);
+
+ r = sd_bus_message_enter_container(reply, 'a', "(uosos)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ for (;;) {
+ r = sd_bus_message_read(reply, "(uosos)", &id, NULL, &u, NULL, &jt);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ log_info("Enqueued auxiliary job %" PRIu32 " %s/%s.", id, u, jt);
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ done = true;
+ }
+ }
+
+ if (!done) {
+ r = bus_call_method(bus, bus_systemd_mgr, method, error, &reply, "ss", name, mode);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_message_read(reply, "o", &path);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+
+ if (need_daemon_reload(bus, name) > 0)
+ warn_unit_file_changed(name);
+
+ if (w) {
+ 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 for %s: %m", name);
+ }
+
+ if (wu) {
+ r = bus_wait_for_units_add_unit(wu, name, BUS_WAIT_FOR_INACTIVE|BUS_WAIT_NO_JOB, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch unit %s: %m", name);
+ }
+
+ return 0;
+
+fail:
+ /* There's always a fallback possible for legacy actions. */
+ if (arg_action != ACTION_SYSTEMCTL)
+ return r;
+
+ log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r));
+
+ if (!sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
+ BUS_ERROR_UNIT_MASKED,
+ BUS_ERROR_JOB_TYPE_NOT_APPLICABLE))
+ log_error("See %s logs and 'systemctl%s status%s %s' for details.",
+ arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ name[0] == '-' ? " --" : "",
+ name);
+
+ return r;
+}
+
+const struct action_metadata action_table[_ACTION_MAX] = {
+ [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
+ [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
+ [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
+ [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
+ [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
+ [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
+ [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
+ [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
+ [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
+ [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
+ [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
+ [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
+ [ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" },
+};
+
+enum action verb_to_action(const char *verb) {
+ enum action i;
+
+ for (i = 0; i < _ACTION_MAX; i++)
+ if (streq_ptr(action_table[i].verb, verb))
+ return i;
+
+ return _ACTION_INVALID;
+}
+
+static const char** make_extra_args(const char *extra_args[static 4]) {
+ size_t n = 0;
+
+ assert(extra_args);
+
+ if (arg_scope != UNIT_FILE_SYSTEM)
+ extra_args[n++] = "--user";
+
+ if (arg_transport == BUS_TRANSPORT_REMOTE) {
+ extra_args[n++] = "-H";
+ extra_args[n++] = arg_host;
+ } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
+ extra_args[n++] = "-M";
+ extra_args[n++] = arg_host;
+ } else
+ assert(arg_transport == BUS_TRANSPORT_LOCAL);
+
+ extra_args[n] = NULL;
+ return extra_args;
+}
+
+int start_unit(int argc, char *argv[], void *userdata) {
+ _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *wu = NULL;
+ _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
+ const char *method, *job_type, *mode, *one_name, *suffix = NULL;
+ _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */
+ _cleanup_strv_free_ char **names = NULL;
+ int r, ret = EXIT_SUCCESS;
+ sd_bus *bus;
+ char **name;
+
+ if (arg_wait && !STR_IN_SET(argv[0], "start", "restart"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--wait may only be used with the 'start' or 'restart' commands.");
+
+ /* We cannot do sender tracking on the private bus, so we need the full one for RefUnit to implement
+ * --wait */
+ r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ ask_password_agent_open_maybe();
+ polkit_agent_open_maybe();
+
+ if (arg_action == ACTION_SYSTEMCTL) {
+ enum action action;
+
+ action = verb_to_action(argv[0]);
+
+ if (action != _ACTION_INVALID) {
+ /* A command in style "systemctl reboot", "systemctl poweroff", … */
+ method = "StartUnit";
+ job_type = "start";
+ mode = action_table[action].mode;
+ one_name = action_table[action].target;
+ } else {
+ if (streq(argv[0], "isolate")) {
+ /* A "systemctl isolate <unit1> <unit2> …" command */
+ method = "StartUnit";
+ job_type = "start";
+ mode = "isolate";
+ suffix = ".target";
+ } else {
+ /* 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]);
+ mode = arg_job_mode;
+ }
+ one_name = NULL;
+ }
+ } else {
+ /* A SysV legacy command such as "halt", "reboot", "poweroff", … */
+ assert(arg_action >= 0 && arg_action < _ACTION_MAX);
+ assert(action_table[arg_action].target);
+ assert(action_table[arg_action].mode);
+
+ method = "StartUnit";
+ job_type = "start";
+ mode = action_table[arg_action].mode;
+ one_name = action_table[arg_action].target;
+ }
+
+ if (one_name) {
+ names = strv_new(one_name);
+ if (!names)
+ return log_oom();
+ } else {
+ bool expanded;
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
+ if (r < 0)
+ return log_error_errno(r, "Failed to expand names: %m");
+
+ if (!arg_all && expanded && streq(job_type, "start") && !arg_quiet) {
+ log_warning("Warning: %ssystemctl start called with a glob pattern.%s",
+ ansi_highlight_red(),
+ ansi_normal());
+ log_notice("Hint: unit globs expand to loaded units, so start will usually have no effect.\n"
+ " Passing --all will also load units which are pulled in by other units.\n"
+ " See systemctl(1) for more details.");
+ }
+ }
+
+ if (!arg_no_block) {
+ r = bus_wait_for_jobs_new(bus, &w);
+ if (r < 0)
+ return log_error_errno(r, "Could not watch jobs: %m");
+ }
+
+ if (arg_wait) {
+ r = bus_call_method_async(bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable subscription: %m");
+
+ r = bus_wait_for_units_new(bus, &wu);
+ if (r < 0)
+ 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;
+
+ 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];
+
+ r = bus_wait_for_jobs(w, arg_quiet, make_extra_args(extra_args));
+ if (r < 0)
+ return r;
+
+ /* When stopping units, warn if they can still be triggered by
+ * another active unit (socket, path, timer) */
+ if (!arg_quiet)
+ STRV_FOREACH(name, stopped_units)
+ (void) check_triggering_units(bus, *name);
+ }
+
+ if (arg_wait) {
+ r = bus_wait_for_units_run(wu);
+ if (r < 0)
+ return log_error_errno(r, "Failed to wait for units: %m");
+ if (r == BUS_WAIT_FAILURE && ret == EXIT_SUCCESS)
+ ret = EXIT_FAILURE;
+ }
+
+ return ret;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "systemctl.h"
+
+int start_unit(int argc, char *argv[], void *userdata);
+
+struct action_metadata {
+ const char *target;
+ const char *verb;
+ const char *mode;
+};
+
+extern const struct action_metadata action_table[_ACTION_MAX];
+
+enum action verb_to_action(const char *verb);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "proc-cmdline.h"
+#include "signal-util.h"
+#include "stat-util.h"
+#include "systemctl-switch-root.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+int switch_root(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *cmdline_init = NULL;
+ const char *root, *init;
+ sd_bus *bus;
+ int r;
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch root remotely.");
+
+ if (argc < 2 || argc > 3)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
+
+ root = argv[1];
+
+ if (argc >= 3)
+ init = argv[2];
+ else {
+ r = proc_cmdline_get_key("init", 0, &cmdline_init);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
+
+ init = cmdline_init;
+ }
+
+ init = empty_to_null(init);
+ if (init) {
+ const char *root_systemd_path = NULL, *root_init_path = NULL;
+
+ root_systemd_path = prefix_roota(root, "/" SYSTEMD_BINARY_PATH);
+ root_init_path = prefix_roota(root, init);
+
+ /* If the passed init is actually the same as the systemd binary, then let's suppress it. */
+ if (files_same(root_init_path, root_systemd_path, 0) > 0)
+ init = NULL;
+ }
+
+ /* Instruct PID1 to exclude us from its killing spree applied during the transition. Otherwise we
+ * would exit with a failure status even though the switch to the new root has succeed. */
+ assert(saved_argv);
+ assert(saved_argv[0]);
+ saved_argv[0][0] = '@';
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ /* If we are slow to exit after the root switch, the new systemd instance will send us a signal to
+ * terminate. Just ignore it and exit normally. This way the unit does not end up as failed. */
+ r = ignore_signals(SIGTERM, -1);
+ if (r < 0)
+ log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
+
+ log_debug("Switching root - root: %s; init: %s", root, strna(init));
+
+ r = bus_call_method(bus, bus_systemd_mgr, "SwitchRoot", &error, NULL, "ss", root, init);
+ if (r < 0) {
+ (void) default_signals(SIGTERM, -1);
+
+ return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int switch_root(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "env-util.h"
+#include "fd-util.h"
+#include "initreq.h"
+#include "install.h"
+#include "io-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "strv.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl.h"
+
+int talk_initctl(char rl) {
+#if HAVE_SYSV_COMPAT
+ struct init_request request;
+ _cleanup_close_ int fd = -1;
+ const char *p;
+ int r;
+
+ /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this
+ * system, and > 0 on success. */
+
+ if (rl == 0)
+ return 0;
+
+ FOREACH_STRING(p, "/run/initctl", "/dev/initctl") {
+ fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
+ if (fd >= 0 || errno != ENOENT)
+ break;
+ }
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return log_error_errno(errno, "Failed to open initctl fifo: %m");
+ }
+
+ request = (struct init_request) {
+ .magic = INIT_MAGIC,
+ .sleeptime = 0,
+ .cmd = INIT_CMD_RUNLVL,
+ .runlevel = rl,
+ };
+
+ r = loop_write(fd, &request, sizeof(request), false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write to %s: %m", p);
+
+ return 1;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+int parse_shutdown_time_spec(const char *t, usec_t *ret) {
+ assert(t);
+ assert(ret);
+
+ if (streq(t, "now"))
+ *ret = 0;
+ else if (!strchr(t, ':')) {
+ uint64_t u;
+
+ if (safe_atou64(t, &u) < 0)
+ return -EINVAL;
+
+ *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
+ } else {
+ char *e = NULL;
+ long hour, minute;
+ struct tm tm = {};
+ time_t s;
+ usec_t n;
+
+ errno = 0;
+ hour = strtol(t, &e, 10);
+ if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
+ return -EINVAL;
+
+ minute = strtol(e+1, &e, 10);
+ if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
+ return -EINVAL;
+
+ n = now(CLOCK_REALTIME);
+ s = (time_t) (n / USEC_PER_SEC);
+
+ assert_se(localtime_r(&s, &tm));
+
+ tm.tm_hour = (int) hour;
+ tm.tm_min = (int) minute;
+ tm.tm_sec = 0;
+
+ s = mktime(&tm);
+ assert(s >= 0);
+
+ *ret = (usec_t) s * USEC_PER_SEC;
+
+ while (*ret <= n)
+ *ret += USEC_PER_DAY;
+ }
+
+ return 0;
+}
+
+int enable_sysv_units(const char *verb, char **args) {
+ int r = 0;
+
+#if HAVE_SYSV_COMPAT
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
+ unsigned f = 0;
+
+ /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
+
+ if (arg_scope != UNIT_FILE_SYSTEM)
+ return 0;
+
+ if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
+ return 0;
+
+ if (!STR_IN_SET(verb,
+ "enable",
+ "disable",
+ "is-enabled"))
+ return 0;
+
+ r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
+ if (r < 0)
+ return r;
+
+ r = 0;
+ while (args[f]) {
+
+ const char *argv[] = {
+ ROOTLIBEXECDIR "/systemd-sysv-install",
+ NULL, /* --root= */
+ NULL, /* verb */
+ NULL, /* service */
+ NULL,
+ };
+
+ _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL;
+ bool found_native = false, found_sysv;
+ const char *name;
+ unsigned c = 1;
+ pid_t pid;
+ int j;
+
+ name = args[f++];
+
+ if (!endswith(name, ".service"))
+ continue;
+
+ if (path_is_absolute(name))
+ continue;
+
+ j = unit_file_exists(arg_scope, &paths, name);
+ if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
+ return log_error_errno(j, "Failed to look up unit file state: %m");
+ found_native = j != 0;
+
+ /* If we have both a native unit and a SysV script, enable/disable them both (below); for
+ * is-enabled, prefer the native unit */
+ if (found_native && streq(verb, "is-enabled"))
+ continue;
+
+ p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
+ if (!p)
+ return log_oom();
+
+ p[strlen(p) - STRLEN(".service")] = 0;
+ found_sysv = access(p, F_OK) >= 0;
+ if (!found_sysv)
+ continue;
+
+ if (!arg_quiet) {
+ if (found_native)
+ log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
+ else
+ log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
+ }
+
+ if (!isempty(arg_root)) {
+ q = strjoin("--root=", arg_root);
+ if (!q)
+ return log_oom();
+
+ argv[c++] = q;
+ }
+
+ /* Let's copy the verb, since it's still pointing directly into the original argv[] array we
+ * got passed, but safe_fork() is likely going to rewrite that for the new child */
+ v = strdup(verb);
+ if (!v)
+ return log_oom();
+
+ argv[c++] = v;
+ argv[c++] = basename(p);
+ argv[c] = NULL;
+
+ l = strv_join((char**)argv, " ");
+ if (!l)
+ return log_oom();
+
+ if (!arg_quiet)
+ log_info("Executing: %s", l);
+
+ j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ if (j < 0)
+ return j;
+ if (j == 0) {
+ /* Child */
+ execv(argv[0], (char**) argv);
+ log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
+ _exit(EXIT_FAILURE);
+ }
+
+ j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
+ if (j < 0)
+ return j;
+ if (streq(verb, "is-enabled")) {
+ if (j == EXIT_SUCCESS) {
+ if (!arg_quiet)
+ puts("enabled");
+ r = 1;
+ } else {
+ if (!arg_quiet)
+ puts("disabled");
+ }
+
+ } else if (j != EXIT_SUCCESS)
+ return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
+
+ if (found_native)
+ continue;
+
+ /* Remove this entry, so that we don't try enabling it as native unit */
+ assert(f > 0);
+ f--;
+ assert(args[f] == name);
+ strv_remove(args + f, name);
+ }
+
+#endif
+ return r;
+}
+
+int action_to_runlevel(void) {
+#if HAVE_SYSV_COMPAT
+ static const char table[_ACTION_MAX] = {
+ [ACTION_HALT] = '0',
+ [ACTION_POWEROFF] = '0',
+ [ACTION_REBOOT] = '6',
+ [ACTION_RUNLEVEL2] = '2',
+ [ACTION_RUNLEVEL3] = '3',
+ [ACTION_RUNLEVEL4] = '4',
+ [ACTION_RUNLEVEL5] = '5',
+ [ACTION_RESCUE] = '1'
+ };
+
+ assert(arg_action >= 0 && arg_action < _ACTION_MAX);
+ return table[arg_action];
+#else
+ return -EOPNOTSUPP;
+#endif
+}
#include "time-util.h"
-#if HAVE_SYSV_COMPAT
int talk_initctl(char runlevel);
-#endif
int parse_shutdown_time_spec(const char *t, usec_t *ret);
EXIT_PROGRAM_NOT_RUNNING = 3,
EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
};
+
+int enable_sysv_units(const char *verb, char **args);
+
+int action_to_runlevel(void) _pure_;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl-trivial-method.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+
+/* A generic implementation for cases we just need to invoke a simple method call on the Manager object. */
+
+int trivial_method(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *method;
+ sd_bus *bus;
+ int r;
+
+ if (arg_dry_run)
+ return 0;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ polkit_agent_open_maybe();
+
+ method =
+ streq(argv[0], "clear-jobs") ||
+ streq(argv[0], "cancel") ? "ClearJobs" :
+ streq(argv[0], "reset-failed") ? "ResetFailed" :
+ streq(argv[0], "halt") ? "Halt" :
+ streq(argv[0], "reboot") ? "Reboot" :
+ streq(argv[0], "kexec") ? "KExec" :
+ streq(argv[0], "exit") ? "Exit" :
+ /* poweroff */ "PowerOff";
+
+ r = bus_call_method(bus, bus_systemd_mgr, method, &error, NULL, NULL);
+ if (r < 0 && arg_action == ACTION_SYSTEMCTL)
+ return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
+
+ /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support
+ * fallbacks to the old ways of doing things, hence don't log any error in that case here. */
+
+ return r < 0 ? r : 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int trivial_method(int argc, char *argv[], void *userdata);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/reboot.h>
+#include <unistd.h>
+
+#include "sd-bus.h"
+#include "sd-daemon.h"
+
+#include "bus-common-errors.h"
+#include "bus-locator.h"
+#include "bus-map-properties.h"
+#include "bus-unit-util.h"
+#include "dropin.h"
+#include "env-util.h"
+#include "exit-status.h"
+#include "fs-util.h"
+#include "glob-util.h"
+#include "macro.h"
+#include "path-util.h"
+#include "reboot-util.h"
+#include "set.h"
+#include "spawn-ask-password-agent.h"
+#include "spawn-polkit-agent.h"
+#include "stat-util.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "verbs.h"
+
+static sd_bus *buses[_BUS_FOCUS_MAX] = {};
+
+int acquire_bus(BusFocus focus, sd_bus **ret) {
+ int r;
+
+ assert(focus < _BUS_FOCUS_MAX);
+ assert(ret);
+
+ /* We only go directly to the manager, if we are using a local transport */
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ focus = BUS_FULL;
+
+ if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
+ focus = BUS_FULL;
+
+ if (!buses[focus]) {
+ bool user;
+
+ user = arg_scope != UNIT_FILE_SYSTEM;
+
+ if (focus == BUS_MANAGER)
+ r = bus_connect_transport_systemd(arg_transport, arg_host, user, &buses[focus]);
+ else
+ r = bus_connect_transport(arg_transport, arg_host, user, &buses[focus]);
+ if (r < 0)
+ return bus_log_connect_error(r);
+
+ (void) sd_bus_set_allow_interactive_authorization(buses[focus], arg_ask_password);
+ }
+
+ *ret = buses[focus];
+ return 0;
+}
+
+void release_busses(void) {
+ BusFocus w;
+
+ for (w = 0; w < _BUS_FOCUS_MAX; w++)
+ buses[w] = sd_bus_flush_close_unref(buses[w]);
+}
+
+void ask_password_agent_open_maybe(void) {
+ /* Open the password agent as a child process if necessary */
+
+ if (arg_dry_run)
+ return;
+
+ if (arg_scope != UNIT_FILE_SYSTEM)
+ return;
+
+ ask_password_agent_open_if_enabled(arg_transport, arg_ask_password);
+}
+
+void polkit_agent_open_maybe(void) {
+ /* Open the polkit agent as a child process if necessary */
+
+ if (arg_scope != UNIT_FILE_SYSTEM)
+ return;
+
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+}
+
+int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
+ assert(error);
+
+ if (!sd_bus_error_is_set(error))
+ return r;
+
+ if (sd_bus_error_has_names(error, SD_BUS_ERROR_ACCESS_DENIED,
+ BUS_ERROR_ONLY_BY_DEPENDENCY,
+ BUS_ERROR_NO_ISOLATION,
+ BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
+ return EXIT_NOPERMISSION;
+
+ if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
+ return EXIT_NOTINSTALLED;
+
+ if (sd_bus_error_has_names(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
+ SD_BUS_ERROR_NOT_SUPPORTED))
+ return EXIT_NOTIMPLEMENTED;
+
+ if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
+ return EXIT_NOTCONFIGURED;
+
+ if (r != 0)
+ return r;
+
+ return EXIT_FAILURE;
+}
+
+int get_state_one_unit(sd_bus *bus, const char *unit, UnitActiveState *ret_active_state) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *buf = NULL, *dbus_path = NULL;
+ UnitActiveState state;
+ int r;
+
+ assert(unit);
+ assert(ret_active_state);
+
+ dbus_path = unit_dbus_path_from_name(unit);
+ if (!dbus_path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState",
+ &error,
+ &buf);
+ if (r < 0)
+ return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
+
+ state = unit_active_state_from_string(buf);
+ if (state < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit state '%s' for: %s", buf, unit);
+
+ *ret_active_state = state;
+ return 0;
+}
+
+int get_unit_list(
+ sd_bus *bus,
+ const char *machine,
+ char **patterns,
+ UnitInfo **unit_infos,
+ int c,
+ sd_bus_message **ret_reply) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ size_t size = c;
+ int r;
+ bool fallback = false;
+
+ assert(bus);
+ assert(unit_infos);
+ assert(ret_reply);
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitsByPatterns");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, arg_states);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, patterns);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, &reply);
+ if (r < 0 && (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD,
+ SD_BUS_ERROR_ACCESS_DENIED))) {
+ /* Fallback to legacy ListUnitsFiltered method */
+ fallback = true;
+ log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
+ m = sd_bus_message_unref(m);
+ sd_bus_error_free(&error);
+
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitsFiltered");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, arg_states);
+ 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 list units: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ UnitInfo u;
+
+ r = bus_parse_unit_info(reply, &u);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ u.machine = machine;
+
+ if (!output_show_unit(&u, fallback ? patterns : NULL))
+ continue;
+
+ if (!GREEDY_REALLOC(*unit_infos, size, c+1))
+ return log_oom();
+
+ (*unit_infos)[c++] = u;
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ *ret_reply = TAKE_PTR(reply);
+ return c;
+}
+
+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;
+
+ assert(bus);
+ assert(ret);
+
+ STRV_FOREACH(name, names) {
+ UnitNameMangle options = UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN);
+ char *t;
+
+ r = unit_name_mangle_with_suffix(*name, NULL, options, suffix ?: ".service", &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle name: %m");
+
+ if (string_is_glob(t))
+ r = strv_consume(&globs, t);
+ else
+ r = strv_consume(&mangled, t);
+ if (r < 0)
+ return log_oom();
+ }
+
+ /* Query the manager only if any of the names are a glob, since this is fairly expensive */
+ bool expanded = !strv_isempty(globs);
+ if (expanded) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_free_ UnitInfo *unit_infos = NULL;
+ size_t allocated, n;
+
+ r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
+ if (r < 0)
+ return r;
+
+ n = strv_length(mangled);
+ allocated = n + 1;
+
+ for (i = 0; i < r; i++) {
+ if (!GREEDY_REALLOC(mangled, allocated, n+2))
+ return log_oom();
+
+ mangled[n] = strdup(unit_infos[i].id);
+ if (!mangled[n])
+ return log_oom();
+
+ mangled[++n] = NULL;
+ }
+ }
+
+ if (ret_expanded)
+ *ret_expanded = expanded;
+
+ *ret = TAKE_PTR(mangled);
+ return 0;
+}
+
+int check_triggering_units(sd_bus *bus, const char *unit) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL;
+ _cleanup_strv_free_ char **triggered_by = NULL;
+ bool print_warning_label = true;
+ UnitActiveState active_state;
+ char **i;
+ int r;
+
+ r = unit_name_mangle(unit, 0, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+
+ r = unit_load_state(bus, n, &load_state);
+ if (r < 0)
+ return r;
+
+ if (streq(load_state, "masked"))
+ return 0;
+
+ dbus_path = unit_dbus_path_from_name(n);
+ if (!dbus_path)
+ return log_oom();
+
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "TriggeredBy",
+ &error,
+ &triggered_by);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
+
+ STRV_FOREACH(i, triggered_by) {
+ r = get_state_one_unit(bus, *i, &active_state);
+ if (r < 0)
+ return r;
+
+ if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
+ continue;
+
+ if (print_warning_label) {
+ log_warning("Warning: Stopping %s, but it can still be activated by:", n);
+ print_warning_label = false;
+ }
+
+ log_warning(" %s", *i);
+ }
+
+ return 0;
+}
+
+int need_daemon_reload(sd_bus *bus, const char *unit) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *path;
+ int b, r;
+
+ /* We ignore all errors here, since this is used to show a
+ * warning only */
+
+ /* We don't use unit_dbus_path_from_name() directly since we
+ * don't want to load the unit if it isn't loaded. */
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetUnit", NULL, &reply, "s", unit);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(reply, "o", &path);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_get_property_trivial(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Unit",
+ "NeedDaemonReload",
+ NULL,
+ 'b', &b);
+ if (r < 0)
+ return r;
+
+ return b;
+}
+
+void warn_unit_file_changed(const char *unit) {
+ assert(unit);
+
+ log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
+ ansi_highlight_red(),
+ ansi_normal(),
+ unit,
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
+}
+
+int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **ret_unit_path) {
+ char **p;
+
+ assert(lp);
+ assert(unit_name);
+
+ STRV_FOREACH(p, lp->search_path) {
+ _cleanup_free_ char *path = NULL, *lpath = NULL;
+ int r;
+
+ path = path_join(*p, unit_name);
+ if (!path)
+ return log_oom();
+
+ r = chase_symlinks(path, arg_root, 0, &lpath, NULL);
+ if (r == -ENOENT)
+ continue;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0)
+ return log_error_errno(r, "Failed to access path \"%s\": %m", path);
+
+ if (ret_unit_path)
+ *ret_unit_path = TAKE_PTR(lpath);
+
+ return 1;
+ }
+
+ if (ret_unit_path)
+ *ret_unit_path = NULL;
+
+ return 0;
+}
+
+int unit_find_paths(
+ sd_bus *bus,
+ const char *unit_name,
+ LookupPaths *lp,
+ bool force_client_side,
+ Hashmap **cached_name_map,
+ Hashmap **cached_id_map,
+ char **ret_fragment_path,
+ char ***ret_dropin_paths) {
+
+ _cleanup_strv_free_ char **dropins = NULL;
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ /**
+ * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is
+ * found, and sets:
+ * - the path to the unit in *ret_frament_path, if it exists on disk,
+ * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins
+ * were found.
+ *
+ * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for
+ * some reason (the latter only applies if we are going through the service manager).
+ */
+
+ assert(unit_name);
+ assert(ret_fragment_path);
+ assert(lp);
+
+ /* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
+ if (!force_client_side &&
+ !install_client_side() &&
+ !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *load_state = NULL, *dbus_path = NULL;
+
+ dbus_path = unit_dbus_path_from_name(unit_name);
+ if (!dbus_path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "LoadState",
+ &error,
+ &load_state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get LoadState: %s", bus_error_message(&error, r));
+
+ if (streq(load_state, "masked"))
+ return -ERFKILL;
+ if (streq(load_state, "not-found")) {
+ r = 0;
+ goto not_found;
+ }
+ if (!STR_IN_SET(load_state, "loaded", "bad-setting"))
+ return -EKEYREJECTED;
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "FragmentPath",
+ &error,
+ &path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
+
+ if (ret_dropin_paths) {
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "DropInPaths",
+ &error,
+ &dropins);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
+ }
+ } else {
+ const char *_path;
+ _cleanup_set_free_free_ Set *names = NULL;
+
+ if (!*cached_name_map) {
+ r = unit_file_build_name_map(lp, NULL, cached_id_map, cached_name_map, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ r = unit_file_find_fragment(*cached_id_map, *cached_name_map, unit_name, &_path, &names);
+ if (r < 0)
+ return r;
+
+ if (_path) {
+ path = strdup(_path);
+ if (!path)
+ return log_oom();
+ }
+
+ if (ret_dropin_paths) {
+ r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL,
+ ".d", ".conf",
+ NULL, names, &dropins);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ if (isempty(path)) {
+ *ret_fragment_path = NULL;
+ r = 0;
+ } else {
+ *ret_fragment_path = TAKE_PTR(path);
+ r = 1;
+ }
+
+ if (ret_dropin_paths) {
+ if (!strv_isempty(dropins)) {
+ *ret_dropin_paths = TAKE_PTR(dropins);
+ r = 1;
+ } else
+ *ret_dropin_paths = NULL;
+ }
+
+ not_found:
+ if (r == 0 && !arg_force)
+ log_error("No files found for %s.", unit_name);
+
+ return r;
+}
+
+static int unit_find_template_path(
+ const char *unit_name,
+ LookupPaths *lp,
+ char **ret_fragment_path,
+ char **ret_template) {
+
+ _cleanup_free_ char *t = NULL, *f = NULL;
+ int r;
+
+ /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
+
+ r = unit_file_find_path(lp, unit_name, &f);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ if (ret_fragment_path)
+ *ret_fragment_path = TAKE_PTR(f);
+ if (ret_template)
+ *ret_template = NULL;
+ return r; /* found a real unit */
+ }
+
+ r = unit_name_template(unit_name, &t);
+ if (r == -EINVAL) {
+ if (ret_fragment_path)
+ *ret_fragment_path = NULL;
+ if (ret_template)
+ *ret_template = NULL;
+
+ return 0; /* not a template, does not exist */
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine template name: %m");
+
+ r = unit_file_find_path(lp, t, ret_fragment_path);
+ if (r < 0)
+ return r;
+
+ if (ret_template)
+ *ret_template = r > 0 ? TAKE_PTR(t) : NULL;
+
+ return r;
+}
+
+int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) {
+ _cleanup_free_ char *load_state = NULL;
+ int r;
+
+ if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
+ _cleanup_free_ char *path = NULL;
+
+ /* A template cannot be loaded, but it can be still masked, so
+ * we need to use a different method. */
+
+ r = unit_file_find_path(lp, name, &path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return false;
+ return null_or_empty_path(path);
+ }
+
+ r = unit_load_state(bus, name, &load_state);
+ if (r < 0)
+ return r;
+
+ return streq(load_state, "masked");
+}
+
+int unit_exists(LookupPaths *lp, const char *unit) {
+ typedef struct UnitStateInfo {
+ const char *load_state;
+ const char *active_state;
+ } UnitStateInfo;
+
+ static const struct bus_properties_map property_map[] = {
+ { "LoadState", "s", NULL, offsetof(UnitStateInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStateInfo, active_state) },
+ {},
+ };
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_free_ char *path = NULL;
+ UnitStateInfo info = {};
+ sd_bus *bus;
+ int r;
+
+ if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
+ return unit_find_template_path(unit, lp, NULL, NULL);
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, 0, &error, &m, &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+
+ return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
+}
+
+
+int append_unit_dependencies(sd_bus *bus, char **names, char ***ret) {
+ _cleanup_strv_free_ char **with_deps = NULL;
+ char **name;
+
+ assert(bus);
+ assert(ret);
+
+ STRV_FOREACH(name, names) {
+ _cleanup_strv_free_ char **deps = NULL;
+
+ if (strv_extend(&with_deps, *name) < 0)
+ return log_oom();
+
+ (void) unit_get_dependencies(bus, *name, &deps);
+
+ if (strv_extend_strv(&with_deps, deps, true) < 0)
+ return log_oom();
+ }
+
+ *ret = TAKE_PTR(with_deps);
+
+ return 0;
+}
+
+int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) {
+ _cleanup_strv_free_ char **list_with_deps = NULL;
+ int r;
+
+ assert(bus);
+ assert(list);
+
+ if (!arg_with_dependencies)
+ return 0;
+
+ r = append_unit_dependencies(bus, *list, &list_with_deps);
+ if (r < 0)
+ return log_error_errno(r, "Failed to append unit dependencies: %m");
+
+ strv_free(*list);
+ *list = TAKE_PTR(list_with_deps);
+ return 0;
+}
+
+int unit_get_dependencies(sd_bus *bus, const char *name, char ***ret) {
+ _cleanup_strv_free_ char **deps = NULL;
+
+ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = {
+ [DEPENDENCY_FORWARD] = {
+ { "Requires", "as", NULL, 0 },
+ { "Requisite", "as", NULL, 0 },
+ { "Wants", "as", NULL, 0 },
+ { "ConsistsOf", "as", NULL, 0 },
+ { "BindsTo", "as", NULL, 0 },
+ {}
+ },
+ [DEPENDENCY_REVERSE] = {
+ { "RequiredBy", "as", NULL, 0 },
+ { "RequisiteOf", "as", NULL, 0 },
+ { "WantedBy", "as", NULL, 0 },
+ { "PartOf", "as", NULL, 0 },
+ { "BoundBy", "as", NULL, 0 },
+ {}
+ },
+ [DEPENDENCY_AFTER] = {
+ { "After", "as", NULL, 0 },
+ {}
+ },
+ [DEPENDENCY_BEFORE] = {
+ { "Before", "as", NULL, 0 },
+ {}
+ },
+ };
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *dbus_path = NULL;
+ int r;
+
+ assert(bus);
+ assert(name);
+ assert(ret);
+
+ dbus_path = unit_dbus_path_from_name(name);
+ if (!dbus_path)
+ return log_oom();
+
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ map[arg_dependency],
+ BUS_MAP_STRDUP,
+ &error,
+ NULL,
+ &deps);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
+
+ strv_uniq(deps); /* Sometimes a unit might have multiple deps on the other unit,
+ * but we still want to show it just once. */
+ *ret = TAKE_PTR(deps);
+
+ return 0;
+}
+
+const char* unit_type_suffix(const char *unit) {
+ const char *dot;
+
+ dot = strrchr(unit, '.');
+ if (!dot)
+ return "";
+
+ return dot + 1;
+}
+
+bool output_show_unit(const UnitInfo *u, char **patterns) {
+ assert(u);
+
+ if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
+ return false;
+
+ if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
+ return false;
+
+ if (arg_all)
+ return true;
+
+ /* Note that '--all' is not purely a state filter, but also a filter that hides units that "follow"
+ * other units (which is used for device units that appear under different names). */
+ if (!isempty(u->following))
+ return false;
+
+ if (!strv_isempty(arg_states))
+ return true;
+
+ /* By default show all units except the ones in inactive state and with no pending job */
+ if (u->job_id > 0)
+ return true;
+
+ if (streq(u->active_state, "inactive"))
+ return false;
+
+ return true;
+}
+
+bool install_client_side(void) {
+ /* Decides when to execute enable/disable/... operations client-side rather than server-side. */
+
+ if (running_in_chroot_or_offline())
+ return true;
+
+ if (sd_booted() <= 0)
+ return true;
+
+ if (!isempty(arg_root))
+ return true;
+
+ if (arg_scope == UNIT_FILE_GLOBAL)
+ return true;
+
+ /* Unsupported environment variable, mostly for debugging purposes */
+ if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
+ return true;
+
+ return false;
+}
+
+int output_table(Table *table) {
+ int r;
+
+ assert(table);
+
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
+ else
+ r = table_print(table, NULL);
+ if (r < 0)
+ return table_log_print_error(r);
+
+ return 0;
+}
+
+bool show_preset_for_state(UnitFileState state) {
+ /* Don't show preset state in those unit file states, it'll only confuse users. */
+ return !IN_SET(state,
+ UNIT_FILE_ALIAS,
+ UNIT_FILE_STATIC,
+ UNIT_FILE_GENERATED,
+ UNIT_FILE_TRANSIENT);
+}
+
+UnitFileFlags unit_file_flags_from_args(void) {
+ return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
+ (arg_force ? UNIT_FILE_FORCE : 0);
+}
+
+int mangle_names(const char *operation, char **original_names, char ***ret_mangled_names) {
+ _cleanup_strv_free_ char **l = NULL;
+ char **i, **name;
+ int r;
+
+ assert(ret_mangled_names);
+
+ l = i = new(char*, strv_length(original_names) + 1);
+ if (!l)
+ return log_oom();
+
+ STRV_FOREACH(name, original_names) {
+
+ /* When enabling units qualified path names are OK, too, hence allow them explicitly. */
+
+ if (is_path(*name)) {
+ *i = strdup(*name);
+ if (!*i)
+ return log_oom();
+ } else {
+ r = unit_name_mangle_with_suffix(*name, operation,
+ arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
+ ".service", i);
+ if (r < 0) {
+ *i = NULL;
+ return log_error_errno(r, "Failed to mangle unit name: %m");
+ }
+ }
+
+ i++;
+ }
+
+ *i = NULL;
+ *ret_mangled_names = TAKE_PTR(l);
+
+ return 0;
+}
+
+int halt_now(enum action a) {
+ /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need
+ * to be synced explicitly in advance. */
+ if (!arg_no_sync && !arg_dry_run)
+ (void) sync();
+
+ /* Make sure C-A-D is handled by the kernel from this point on... */
+ if (!arg_dry_run)
+ (void) reboot(RB_ENABLE_CAD);
+
+ switch (a) {
+
+ case ACTION_HALT:
+ if (!arg_quiet)
+ log_info("Halting.");
+ if (arg_dry_run)
+ return 0;
+ (void) reboot(RB_HALT_SYSTEM);
+ return -errno;
+
+ case ACTION_POWEROFF:
+ if (!arg_quiet)
+ log_info("Powering off.");
+ if (arg_dry_run)
+ return 0;
+ (void) reboot(RB_POWER_OFF);
+ return -errno;
+
+ case ACTION_KEXEC:
+ case ACTION_REBOOT:
+ return reboot_with_parameter(REBOOT_FALLBACK |
+ (arg_quiet ? 0 : REBOOT_LOG) |
+ (arg_dry_run ? REBOOT_DRY_RUN : 0));
+
+ default:
+ assert_not_reached("Unknown action.");
+ }
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+#include "bus-unit-util.h"
+#include "format-table.h"
+#include "systemctl.h"
+
+typedef enum BusFocus {
+ BUS_FULL, /* The full bus indicated via --system or --user */
+ BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */
+ _BUS_FOCUS_MAX
+} BusFocus;
+
+int acquire_bus(BusFocus focus, sd_bus **ret);
+void release_busses(void);
+
+void ask_password_agent_open_maybe(void);
+void polkit_agent_open_maybe(void);
+
+int translate_bus_error_to_exit_status(int r, const sd_bus_error *error);
+
+int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *ret_active_state);
+int get_unit_list(sd_bus *bus, const char *machine, char **patterns, UnitInfo **unit_infos, int c, sd_bus_message **ret_reply);
+int expand_unit_names(sd_bus *bus, char **names, const char* suffix, char ***ret, bool *ret_expanded);
+
+int check_triggering_units(sd_bus *bus, const char *unit);
+
+int need_daemon_reload(sd_bus *bus, const char *unit);
+
+void warn_unit_file_changed(const char *unit);
+
+int append_unit_dependencies(sd_bus *bus, char **names, char ***ret);
+int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list);
+
+int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **ret_unit_path);
+int unit_find_paths(sd_bus *bus, const char *unit_name, LookupPaths *lp, bool force_client_side, Hashmap **cached_id_map, Hashmap **cached_name_map, char **ret_fragment_path, char ***ret_dropin_paths);
+
+int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name);
+int unit_exists(LookupPaths *lp, const char *unit);
+
+int unit_get_dependencies(sd_bus *bus, const char *name, char ***ret);
+
+const char* unit_type_suffix(const char *unit);
+bool output_show_unit(const UnitInfo *u, char **patterns);
+
+bool install_client_side(void);
+
+int output_table(Table *table);
+
+bool show_preset_for_state(UnitFileState state);
+
+int mangle_names(const char *operation, char **original_names, char ***ret_mangled_names);
+
+UnitFileFlags unit_file_flags_from_args(void);
+
+int halt_now(enum action a);
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include <errno.h>
-#include <fcntl.h>
#include <getopt.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/prctl.h>
-#include <sys/reboot.h>
+#include <locale.h>
#include <unistd.h>
-#include "sd-bus.h"
#include "sd-daemon.h"
-#include "sd-event.h"
-#include "sd-login.h"
-
-#include "alloc-util.h"
-#include "bootspec.h"
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-locator.h"
-#include "bus-map-properties.h"
-#include "bus-message.h"
-#include "bus-print-properties.h"
-#include "bus-unit-procs.h"
-#include "bus-unit-util.h"
-#include "bus-wait-for-jobs.h"
-#include "bus-wait-for-units.h"
-#include "cgroup-show.h"
-#include "cgroup-util.h"
-#include "copy.h"
-#include "cpu-set-util.h"
-#include "dirent-util.h"
-#include "dropin.h"
-#include "efi-loader.h"
-#include "efivars.h"
-#include "env-util.h"
-#include "escape.h"
-#include "exec-util.h"
-#include "exit-status.h"
-#include "fd-util.h"
-#include "format-table.h"
-#include "format-util.h"
-#include "fs-util.h"
-#include "glob-util.h"
-#include "hexdecoct.h"
-#include "hostname-util.h"
-#include "in-addr-util.h"
-#include "initreq.h"
-#include "install.h"
-#include "io-util.h"
-#include "journal-util.h"
-#include "list.h"
-#include "locale-util.h"
-#include "log.h"
-#include "logs-show.h"
-#include "macro.h"
-#include "main-func.h"
-#include "memory-util.h"
-#include "mkdir.h"
-#include "numa-util.h"
-#include "pager.h"
-#include "parse-util.h"
-#include "path-lookup.h"
-#include "path-util.h"
-#include "pretty-print.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
-#include "reboot-util.h"
-#include "rlimit-util.h"
-#include "set.h"
-#include "sigbus.h"
-#include "signal-util.h"
-#include "socket-util.h"
-#include "sort-util.h"
-#include "spawn-ask-password-agent.h"
-#include "spawn-polkit-agent.h"
-#include "special.h"
-#include "stat-util.h"
-#include "string-table.h"
-#include "strv.h"
-#include "syslog-util.h"
-#include "sysv-compat.h"
-#include "terminal-util.h"
-#include "tmpfile-util.h"
-#include "unit-def.h"
-#include "unit-file.h"
-#include "unit-name.h"
-#include "user-util.h"
-#include "utf8.h"
-#include "utmp-wtmp.h"
-#include "verbs.h"
-#include "virt.h"
-
-static char **arg_types = NULL;
-static char **arg_states = NULL;
-static char **arg_properties = NULL;
-static bool arg_all = false;
-static enum dependency {
- DEPENDENCY_FORWARD,
- DEPENDENCY_REVERSE,
- DEPENDENCY_AFTER,
- DEPENDENCY_BEFORE,
- _DEPENDENCY_MAX
-} arg_dependency = DEPENDENCY_FORWARD;
-static const char *arg_job_mode = "replace";
-static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
-static bool arg_wait = false;
-static bool arg_no_block = false;
-static bool arg_no_legend = false;
-static PagerFlags arg_pager_flags = 0;
-static bool arg_no_wtmp = false;
-static bool arg_no_sync = false;
-static bool arg_no_wall = false;
-static bool arg_no_reload = false;
-static bool arg_value = false;
-static bool arg_show_types = false;
-static bool arg_ignore_inhibitors = false;
-static bool arg_dry_run = false;
-static bool arg_quiet = false;
-static bool arg_full = false;
-static bool arg_recursive = false;
-static bool arg_with_dependencies = false;
-static bool arg_show_transaction = false;
-static int arg_force = 0;
-static bool arg_ask_password = false;
-static bool arg_runtime = false;
-static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
-static char **arg_wall = NULL;
-static const char *arg_kill_who = NULL;
-static int arg_signal = SIGTERM;
-static char *arg_root = NULL;
-static usec_t arg_when = 0;
-static const char *arg_reboot_argument = NULL;
-static enum action {
- ACTION_SYSTEMCTL,
- ACTION_HALT,
- ACTION_POWEROFF,
- ACTION_REBOOT,
- ACTION_KEXEC,
- ACTION_EXIT,
- ACTION_SUSPEND,
- ACTION_HIBERNATE,
- ACTION_HYBRID_SLEEP,
- ACTION_SUSPEND_THEN_HIBERNATE,
- ACTION_RUNLEVEL2,
- ACTION_RUNLEVEL3,
- ACTION_RUNLEVEL4,
- ACTION_RUNLEVEL5,
- ACTION_RESCUE,
- ACTION_EMERGENCY,
- ACTION_DEFAULT,
- ACTION_RELOAD,
- ACTION_REEXEC,
- ACTION_RUNLEVEL,
- ACTION_CANCEL_SHUTDOWN,
- _ACTION_MAX,
- _ACTION_INVALID = -1
-} arg_action = ACTION_SYSTEMCTL;
-static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static const char *arg_host = NULL;
-static unsigned arg_lines = 10;
-static OutputMode arg_output = OUTPUT_SHORT;
-static bool arg_plain = false;
-static bool arg_firmware_setup = false;
-static usec_t arg_boot_loader_menu = USEC_INFINITY;
-static const char *arg_boot_loader_entry = NULL;
-static bool arg_now = false;
-static bool arg_jobs_before = false;
-static bool arg_jobs_after = false;
-static char **arg_clean_what = NULL;
-static TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
-
-/* This is a global cache that will be constructed on first use. */
-static Hashmap *cached_id_map = NULL;
-static Hashmap *cached_name_map = NULL;
-
-STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
-STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
-STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
-STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
-STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep);
-STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
-STATIC_DESTRUCTOR_REGISTER(cached_id_map, hashmap_freep);
-STATIC_DESTRUCTOR_REGISTER(cached_name_map, hashmap_freep);
-
-static int daemon_reload(int argc, char *argv[], void* userdata);
-static int trivial_method(int argc, char *argv[], void *userdata);
-static int halt_now(enum action a);
-static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
-
-static bool original_stdout_is_tty;
-
-typedef enum BusFocus {
- BUS_FULL, /* The full bus indicated via --system or --user */
- BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */
- _BUS_FOCUS_MAX
-} BusFocus;
-
-static sd_bus *buses[_BUS_FOCUS_MAX] = {};
-
-static UnitFileFlags args_to_flags(void) {
- return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
- (arg_force ? UNIT_FILE_FORCE : 0);
-}
-
-static int acquire_bus(BusFocus focus, sd_bus **ret) {
- int r;
-
- assert(focus < _BUS_FOCUS_MAX);
- assert(ret);
-
- /* We only go directly to the manager, if we are using a local transport */
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- focus = BUS_FULL;
-
- if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
- focus = BUS_FULL;
-
- if (!buses[focus]) {
- bool user;
-
- user = arg_scope != UNIT_FILE_SYSTEM;
-
- if (focus == BUS_MANAGER)
- r = bus_connect_transport_systemd(arg_transport, arg_host, user, &buses[focus]);
- else
- r = bus_connect_transport(arg_transport, arg_host, user, &buses[focus]);
- if (r < 0)
- return log_error_errno(r, "Failed to connect to bus: %m");
-
- (void) sd_bus_set_allow_interactive_authorization(buses[focus], arg_ask_password);
- }
-
- *ret = buses[focus];
- return 0;
-}
-
-static void release_busses(void) {
- BusFocus w;
-
- for (w = 0; w < _BUS_FOCUS_MAX; w++)
- buses[w] = sd_bus_flush_close_unref(buses[w]);
-}
-
-static void ask_password_agent_open_maybe(void) {
- /* Open the password agent as a child process if necessary */
-
- if (arg_dry_run)
- return;
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return;
-
- ask_password_agent_open_if_enabled(arg_transport, arg_ask_password);
-}
-
-static void polkit_agent_open_maybe(void) {
- /* Open the polkit agent as a child process if necessary */
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return;
-
- polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
-}
-
-static OutputFlags get_output_flags(void) {
- return
- arg_all * OUTPUT_SHOW_ALL |
- (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- colors_enabled() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF;
-}
-
-static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
- assert(error);
-
- if (!sd_bus_error_is_set(error))
- return r;
-
- if (sd_bus_error_has_names(error, SD_BUS_ERROR_ACCESS_DENIED,
- BUS_ERROR_ONLY_BY_DEPENDENCY,
- BUS_ERROR_NO_ISOLATION,
- BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
- return EXIT_NOPERMISSION;
-
- if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
- return EXIT_NOTINSTALLED;
-
- if (sd_bus_error_has_names(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
- SD_BUS_ERROR_NOT_SUPPORTED))
- return EXIT_NOTIMPLEMENTED;
-
- if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
- return EXIT_NOTCONFIGURED;
-
- if (r != 0)
- return r;
-
- return EXIT_FAILURE;
-}
-
-static bool install_client_side(void) {
- /* Decides when to execute enable/disable/... operations
- * client-side rather than server-side. */
-
- if (running_in_chroot_or_offline())
- return true;
-
- if (sd_booted() <= 0)
- return true;
-
- if (!isempty(arg_root))
- return true;
-
- if (arg_scope == UNIT_FILE_GLOBAL)
- return true;
-
- /* Unsupported environment variable, mostly for debugging purposes */
- if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
- return true;
-
- return false;
-}
-
-static int compare_unit_info(const UnitInfo *a, const UnitInfo *b) {
- int r;
-
- /* First, order by machine */
- r = strcasecmp_ptr(a->machine, b->machine);
- if (r != 0)
- return r;
-
- /* Second, order by unit type */
- r = strcasecmp_ptr(strrchr(a->id, '.'), strrchr(b->id, '.'));
- if (r != 0)
- return r;
-
- /* Third, order by name */
- return strcasecmp(a->id, b->id);
-}
-
-static const char* unit_type_suffix(const char *name) {
- const char *dot;
-
- dot = strrchr(name, '.');
- if (!dot)
- return "";
-
- return dot + 1;
-}
-
-static bool output_show_unit(const UnitInfo *u, char **patterns) {
- assert(u);
-
- if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
- return false;
-
- if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
- return false;
-
- if (arg_all)
- return true;
-
- /* Note that '--all' is not purely a state filter, but also a
- * filter that hides units that "follow" other units (which is
- * used for device units that appear under different names). */
- if (!isempty(u->following))
- return false;
-
- if (!strv_isempty(arg_states))
- return true;
-
- /* By default show all units except the ones in inactive
- * state and with no pending job */
- if (u->job_id > 0)
- return true;
-
- if (streq(u->active_state, "inactive"))
- return false;
-
- return true;
-}
-
-static int output_table(Table *table) {
- int r;
-
- assert(table);
-
- if (OUTPUT_MODE_IS_JSON(arg_output))
- r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
- else
- r = table_print(table, NULL);
- if (r < 0)
- return table_log_print_error(r);
-
- return 0;
-}
-
-static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
- _cleanup_(table_unrefp) Table *table = NULL;
- int r;
-
- table = table_new("", "unit", "load", "active", "sub", "job", "description");
- if (!table)
- return log_oom();
-
- table_set_header(table, !arg_no_legend);
- if (arg_plain) {
- /* Hide the 'glyph' column when --plain is requested */
- r = table_hide_column_from_display(table, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to hide column: %m");
- }
- if (arg_full)
- table_set_width(table, 0);
-
- (void) table_set_empty_string(table, "-");
-
- int job_count = 0;
- for (const UnitInfo *u = unit_infos; unit_infos && u < unit_infos + c; u++) {
- _cleanup_free_ char *j = NULL;
- const char *on_underline = "", *on_loaded = "", *on_active = "";
- const char *on_circle = "", *id;
- bool circle = false, underline = false;
-
- if (u + 1 < unit_infos + c &&
- !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
- on_underline = ansi_underline();
- underline = true;
- }
-
- if (STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked") && !arg_plain) {
- on_circle = underline ? ansi_highlight_yellow_underline() : ansi_highlight_yellow();
- circle = true;
- on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
- } else if (streq(u->active_state, "failed") && !arg_plain) {
- on_circle = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
- circle = true;
- on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
- } else {
- on_circle = on_underline;
- on_active = on_underline;
- on_loaded = on_underline;
- }
-
- if (u->machine) {
- j = strjoin(u->machine, ":", u->id);
- if (!j)
- return log_oom();
-
- id = j;
- } else
- id = u->id;
-
- r = table_add_many(table,
- TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
- TABLE_SET_BOTH_COLORS, on_circle,
- TABLE_STRING, id,
- TABLE_SET_BOTH_COLORS, on_active,
- TABLE_STRING, u->load_state,
- TABLE_SET_BOTH_COLORS, on_loaded,
- TABLE_STRING, u->active_state,
- TABLE_SET_BOTH_COLORS, on_active,
- TABLE_STRING, u->sub_state,
- TABLE_SET_BOTH_COLORS, on_active,
- TABLE_STRING, u->job_id ? u->job_type: "",
- TABLE_SET_BOTH_COLORS, u->job_id ? on_underline : "",
- TABLE_STRING, u->description,
- TABLE_SET_BOTH_COLORS, on_underline);
- if (r < 0)
- return table_log_add_error(r);
-
- if (u->job_id != 0)
- job_count++;
- }
-
- if (job_count == 0) {
- /* There's no data in the JOB column, so let's hide it */
- r = table_hide_column_from_display(table, 5);
- if (r < 0)
- return log_error_errno(r, "Failed to hide column: %m");
- }
-
- r = output_table(table);
- if (r < 0)
- return r;
-
- if (!arg_no_legend) {
- const char *on, *off;
- size_t records = table_get_rows(table) - 1;
-
- if (records > 0) {
- puts("\n"
- "LOAD = Reflects whether the unit definition was properly loaded.\n"
- "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
- "SUB = The low-level unit activation state, values depend on unit type.");
- puts(job_count ? "JOB = Pending job for the unit.\n" : "");
- on = ansi_highlight();
- off = ansi_normal();
- } else {
- on = ansi_highlight_red();
- off = ansi_normal();
- }
-
- if (arg_all || strv_contains(arg_states, "inactive"))
- printf("%s%zu loaded units listed.%s\n"
- "To show all installed unit files use 'systemctl list-unit-files'.\n",
- on, records, off);
- else if (!arg_states)
- printf("%s%zu loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
- "To show all installed unit files use 'systemctl list-unit-files'.\n",
- on, records, off);
- else
- printf("%zu loaded units listed.\n", records);
- }
-
- return 0;
-}
-
-static int get_unit_list(
- sd_bus *bus,
- const char *machine,
- char **patterns,
- UnitInfo **unit_infos,
- int c,
- sd_bus_message **_reply) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- size_t size = c;
- int r;
- UnitInfo u;
- bool fallback = false;
-
- assert(bus);
- assert(unit_infos);
- assert(_reply);
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitsByPatterns");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, arg_states);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, patterns);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0 && (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD,
- SD_BUS_ERROR_ACCESS_DENIED))) {
- /* Fallback to legacy ListUnitsFiltered method */
- fallback = true;
- log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
- m = sd_bus_message_unref(m);
- sd_bus_error_free(&error);
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitsFiltered");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, arg_states);
- 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 list units: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = bus_parse_unit_info(reply, &u)) > 0) {
- u.machine = machine;
-
- if (!output_show_unit(&u, fallback ? patterns : NULL))
- continue;
-
- if (!GREEDY_REALLOC(*unit_infos, size, c+1))
- return log_oom();
-
- (*unit_infos)[c++] = u;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- *_reply = TAKE_PTR(reply);
-
- return c;
-}
-
-static void message_set_freep(Set **set) {
- set_free_with_destructor(*set, sd_bus_message_unref);
-}
-
-static int get_unit_list_recursive(
- sd_bus *bus,
- char **patterns,
- UnitInfo **_unit_infos,
- Set **_replies,
- char ***_machines) {
-
- _cleanup_free_ UnitInfo *unit_infos = NULL;
- _cleanup_(message_set_freep) Set *replies;
- sd_bus_message *reply;
- int c, r;
-
- assert(bus);
- assert(_replies);
- assert(_unit_infos);
- assert(_machines);
-
- replies = set_new(NULL);
- if (!replies)
- return log_oom();
-
- c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
- if (c < 0)
- return c;
-
- r = set_put(replies, reply);
- if (r < 0) {
- sd_bus_message_unref(reply);
- return log_oom();
- }
-
- if (arg_recursive) {
- _cleanup_strv_free_ char **machines = NULL;
- char **i;
-
- r = sd_get_machine_names(&machines);
- if (r < 0)
- return log_error_errno(r, "Failed to get machine names: %m");
-
- STRV_FOREACH(i, machines) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
- int k;
-
- r = sd_bus_open_system_machine(&container, *i);
- if (r < 0) {
- log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
- continue;
- }
-
- k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
- if (k < 0)
- return k;
-
- c = k;
-
- r = set_put(replies, reply);
- if (r < 0) {
- sd_bus_message_unref(reply);
- return log_oom();
- }
- }
-
- *_machines = TAKE_PTR(machines);
- } else
- *_machines = NULL;
-
- *_unit_infos = TAKE_PTR(unit_infos);
- *_replies = TAKE_PTR(replies);
-
- return c;
-}
-
-static int expand_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;
-
- assert(bus);
- assert(ret);
-
- STRV_FOREACH(name, names) {
- char *t;
- UnitNameMangle options = UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN);
-
- r = unit_name_mangle_with_suffix(*name, NULL, options, suffix ?: ".service", &t);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle name: %m");
-
- if (string_is_glob(t))
- r = strv_consume(&globs, t);
- else
- r = strv_consume(&mangled, t);
- if (r < 0)
- return log_oom();
- }
-
- /* Query the manager only if any of the names are a glob, since
- * this is fairly expensive */
- bool expanded = !strv_isempty(globs);
- if (expanded) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ UnitInfo *unit_infos = NULL;
- size_t allocated, n;
-
- r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
- if (r < 0)
- return r;
-
- n = strv_length(mangled);
- allocated = n + 1;
-
- for (i = 0; i < r; i++) {
- if (!GREEDY_REALLOC(mangled, allocated, n+2))
- return log_oom();
-
- mangled[n] = strdup(unit_infos[i].id);
- if (!mangled[n])
- return log_oom();
-
- mangled[++n] = NULL;
- }
- }
-
- if (ret_expanded)
- *ret_expanded = expanded;
-
- *ret = TAKE_PTR(mangled);
- return 0;
-}
-
-static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***ret) {
- _cleanup_strv_free_ char **deps = NULL;
-
- static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = {
- [DEPENDENCY_FORWARD] = {
- { "Requires", "as", NULL, 0 },
- { "Requisite", "as", NULL, 0 },
- { "Wants", "as", NULL, 0 },
- { "ConsistsOf", "as", NULL, 0 },
- { "BindsTo", "as", NULL, 0 },
- {}
- },
- [DEPENDENCY_REVERSE] = {
- { "RequiredBy", "as", NULL, 0 },
- { "RequisiteOf", "as", NULL, 0 },
- { "WantedBy", "as", NULL, 0 },
- { "PartOf", "as", NULL, 0 },
- { "BoundBy", "as", NULL, 0 },
- {}
- },
- [DEPENDENCY_AFTER] = {
- { "After", "as", NULL, 0 },
- {}
- },
- [DEPENDENCY_BEFORE] = {
- { "Before", "as", NULL, 0 },
- {}
- },
- };
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *dbus_path = NULL;
- int r;
-
- assert(bus);
- assert(name);
- assert(ret);
-
- dbus_path = unit_dbus_path_from_name(name);
- if (!dbus_path)
- return log_oom();
-
- r = bus_map_all_properties(bus,
- "org.freedesktop.systemd1",
- dbus_path,
- map[arg_dependency],
- BUS_MAP_STRDUP,
- &error,
- NULL,
- &deps);
- if (r < 0)
- return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
-
- strv_uniq(deps); /* Sometimes a unit might have multiple deps on the other unit,
- * but we still want to show it just once. */
- *ret = TAKE_PTR(deps);
-
- return 0;
-}
-
-static int append_unit_dependencies(sd_bus *bus, char **names, char ***ret) {
- _cleanup_strv_free_ char **with_deps = NULL;
- char **name;
-
- assert(bus);
- assert(ret);
-
- STRV_FOREACH(name, names) {
- _cleanup_strv_free_ char **deps = NULL;
-
- if (strv_extend(&with_deps, *name) < 0)
- return log_oom();
-
- (void) list_dependencies_get_dependencies(bus, *name, &deps);
-
- if (strv_extend_strv(&with_deps, deps, true) < 0)
- return log_oom();
- }
-
- *ret = TAKE_PTR(with_deps);
-
- return 0;
-}
-
-static int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) {
- assert(bus);
- assert(list);
-
- if (arg_with_dependencies) {
- int r;
- _cleanup_strv_free_ char **list_with_deps = NULL;
-
- r = append_unit_dependencies(bus, *list, &list_with_deps);
- if (r < 0)
- return log_error_errno(r, "Failed to append unit dependencies: %m");
-
- strv_free(*list);
- *list = TAKE_PTR(list_with_deps);
- }
-
- return 0;
-}
-
-static int list_units(int argc, char *argv[], void *userdata) {
- _cleanup_free_ UnitInfo *unit_infos = NULL;
- _cleanup_(message_set_freep) Set *replies = NULL;
- _cleanup_strv_free_ char **machines = NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- if (arg_with_dependencies) {
- _cleanup_strv_free_ char **names = NULL;
-
- r = append_unit_dependencies(bus, strv_skip(argv, 1), &names);
- if (r < 0)
- return r;
-
- r = get_unit_list_recursive(bus, names, &unit_infos, &replies, &machines);
- if (r < 0)
- return r;
- } else {
- r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
- if (r < 0)
- return r;
- }
-
- typesafe_qsort(unit_infos, r, compare_unit_info);
- return output_units_list(unit_infos, r);
-}
-
-static int get_triggered_units(
- sd_bus *bus,
- const char* path,
- char*** ret) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
-
- assert(bus);
- assert(path);
- assert(ret);
-
- r = sd_bus_get_property_strv(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "Triggers",
- &error,
- ret);
- if (r < 0)
- return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-static int get_listening(
- sd_bus *bus,
- const char* unit_path,
- char*** listening) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *type, *path;
- int r, n = 0;
-
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.systemd1",
- unit_path,
- "org.freedesktop.systemd1.Socket",
- "Listen",
- &error,
- &reply,
- "a(ss)");
- if (r < 0)
- return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
-
- r = strv_extend(listening, type);
- if (r < 0)
- return log_oom();
-
- r = strv_extend(listening, path);
- if (r < 0)
- return log_oom();
-
- n++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return n;
-}
-
-struct socket_info {
- const char *machine;
- const char* id;
-
- char* type;
- char* path;
-
- /* Note: triggered is a list here, although it almost certainly
- * will always be one unit. Nevertheless, dbus API allows for multiple
- * values, so let's follow that. */
- char** triggered;
-
- /* The strv above is shared. free is set only in the first one. */
- bool own_triggered;
-};
-
-static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
- int r;
-
- assert(a);
- assert(b);
-
- r = strcasecmp_ptr(a->machine, b->machine);
- if (r != 0)
- return r;
-
- r = strcmp(a->path, b->path);
- if (r != 0)
- return r;
-
- return strcmp(a->type, b->type);
-}
-
-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;
-
- table = table_new("listen", "type", "unit", "activates");
- if (!table)
- return log_oom();
-
- if (!arg_show_types) {
- /* Hide the second (TYPE) column */
- r = table_set_display(table, (size_t) 0, (size_t) 2, (size_t) 3, (size_t) -1);
- if (r < 0)
- return log_error_errno(r, "Failed to set columns to display: %m");
- }
-
- table_set_header(table, !arg_no_legend);
- if (arg_full)
- table_set_width(table, 0);
-
- (void) table_set_empty_string(table, "-");
-
- if (cs) {
- for (s = socket_infos; s < socket_infos + cs; s++) {
- _cleanup_free_ char *j = NULL;
- const char *path;
-
- if (s->machine) {
- j = strjoin(s->machine, ":", s->path);
- if (!j)
- return log_oom();
- path = j;
- } else
- path = s->path;
-
- r = table_add_many(table,
- TABLE_STRING, path,
- TABLE_STRING, s->type,
- TABLE_STRING, s->id);
- if (r < 0)
- return table_log_add_error(r);
-
- if (strv_isempty(s->triggered))
- r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
- else if (strv_length(s->triggered) == 1)
- r = table_add_cell(table, NULL, TABLE_STRING, s->triggered[0]);
- else
- /* This should never happen, currently our socket units can only trigger a
- * single unit. But let's handle this anyway, who knows what the future
- * brings? */
- r = table_add_cell(table, NULL, TABLE_STRV, s->triggered);
- if (r < 0)
- return table_log_add_error(r);
-
- }
-
- on = ansi_highlight();
- off = ansi_normal();
- } else {
- on = ansi_highlight_red();
- off = ansi_normal();
- }
-
- r = output_table(table);
- if (r < 0)
- return r;
-
- if (!arg_no_legend) {
- printf("\n%s%u sockets listed.%s\n", on, cs, off);
- if (!arg_all)
- printf("Pass --all to see loaded but inactive sockets, too.\n");
- }
-
- return 0;
-}
-
-static int list_sockets(int argc, char *argv[], void *userdata) {
- _cleanup_(message_set_freep) Set *replies = NULL;
- _cleanup_strv_free_ char **machines = NULL;
- _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;
- sd_bus *bus;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- r = expand_names(bus, strv_skip(argv, 1), ".socket", &sockets_with_suffix, NULL);
- if (r < 0)
- return r;
-
- if (argc == 1 || sockets_with_suffix) {
- n = get_unit_list_recursive(bus, sockets_with_suffix, &unit_infos, &replies, &machines);
- if (n < 0)
- return n;
-
- for (u = unit_infos; u < unit_infos + n; u++) {
- _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
- int i, c;
-
- if (!endswith(u->id, ".socket"))
- continue;
-
- r = get_triggered_units(bus, u->unit_path, &triggered);
- if (r < 0)
- goto cleanup;
-
- c = get_listening(bus, u->unit_path, &listening);
- if (c < 0) {
- r = c;
- goto cleanup;
- }
-
- if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
- r = log_oom();
- goto cleanup;
- }
-
- for (i = 0; i < c; i++)
- socket_infos[cs + i] = (struct socket_info) {
- .machine = u->machine,
- .id = u->id,
- .type = listening[i*2],
- .path = listening[i*2 + 1],
- .triggered = triggered,
- .own_triggered = i==0,
- };
-
- /* from this point on we will cleanup those socket_infos */
- cs += c;
- free(listening);
- listening = triggered = NULL; /* avoid cleanup */
- }
-
- typesafe_qsort(socket_infos, cs, socket_info_compare);
- }
-
- output_sockets_list(socket_infos, cs);
-
- cleanup:
- assert(cs == 0 || socket_infos);
- for (s = socket_infos; s < socket_infos + cs; s++) {
- free(s->type);
- free(s->path);
- if (s->own_triggered)
- strv_free(s->triggered);
- }
-
- return r;
-}
-
-static int get_next_elapse(
- sd_bus *bus,
- const char *path,
- dual_timestamp *next) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- dual_timestamp t;
- int r;
-
- assert(bus);
- assert(path);
- assert(next);
-
- r = sd_bus_get_property_trivial(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Timer",
- "NextElapseUSecMonotonic",
- &error,
- 't',
- &t.monotonic);
- if (r < 0)
- return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
-
- r = sd_bus_get_property_trivial(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Timer",
- "NextElapseUSecRealtime",
- &error,
- 't',
- &t.realtime);
- if (r < 0)
- return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r));
-
- *next = t;
- return 0;
-}
-
-static int get_last_trigger(
- sd_bus *bus,
- const char *path,
- usec_t *last) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
-
- assert(bus);
- assert(path);
- assert(last);
-
- r = sd_bus_get_property_trivial(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Timer",
- "LastTriggerUSec",
- &error,
- 't',
- last);
- if (r < 0)
- return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-struct timer_info {
- const char* machine;
- const char* id;
- usec_t next_elapse;
- usec_t last_trigger;
- char** triggered;
-};
-
-static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
- int r;
-
- assert(a);
- assert(b);
-
- r = strcasecmp_ptr(a->machine, b->machine);
- if (r != 0)
- return r;
-
- r = CMP(a->next_elapse, b->next_elapse);
- if (r != 0)
- return r;
-
- return strcmp(a->id, b->id);
-}
-
-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;
-
- assert(timer_infos || n == 0);
-
- table = table_new("next", "left", "last", "passed", "unit", "activates");
- if (!table)
- return log_oom();
-
- table_set_header(table, !arg_no_legend);
- if (arg_full)
- table_set_width(table, 0);
-
- (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;
-
- 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);
- }
-
- on = ansi_highlight();
- off = ansi_normal();
- } else {
- on = ansi_highlight_red();
- off = ansi_normal();
- }
-
- r = output_table(table);
- if (r < 0)
- return r;
-
- if (!arg_no_legend) {
- printf("\n%s%u timers listed.%s\n", on, n, off);
- if (!arg_all)
- printf("Pass --all to see loaded but inactive timers, too.\n");
- }
-
- return 0;
-}
-
-static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
- usec_t next_elapse;
-
- assert(nw);
- assert(next);
-
- if (timestamp_is_set(next->monotonic)) {
- usec_t converted;
-
- if (next->monotonic > nw->monotonic)
- converted = nw->realtime + (next->monotonic - nw->monotonic);
- else
- converted = nw->realtime - (nw->monotonic - next->monotonic);
-
- if (timestamp_is_set(next->realtime))
- next_elapse = MIN(converted, next->realtime);
- else
- next_elapse = converted;
-
- } else
- next_elapse = next->realtime;
-
- return next_elapse;
-}
-
-static int list_timers(int argc, char *argv[], void *userdata) {
- _cleanup_(message_set_freep) Set *replies = NULL;
- _cleanup_strv_free_ char **machines = NULL;
- _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;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- r = expand_names(bus, strv_skip(argv, 1), ".timer", &timers_with_suffix, NULL);
- if (r < 0)
- return r;
-
- if (argc == 1 || timers_with_suffix) {
- n = get_unit_list_recursive(bus, timers_with_suffix, &unit_infos, &replies, &machines);
- if (n < 0)
- return n;
-
- dual_timestamp_get(&nw);
-
- for (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;
-
- if (!endswith(u->id, ".timer"))
- continue;
-
- r = get_triggered_units(bus, u->unit_path, &triggered);
- if (r < 0)
- goto cleanup;
-
- r = get_next_elapse(bus, u->unit_path, &next);
- if (r < 0)
- goto cleanup;
-
- get_last_trigger(bus, u->unit_path, &last);
-
- if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
- r = log_oom();
- goto cleanup;
- }
-
- m = calc_next_elapse(&nw, &next);
-
- timer_infos[c++] = (struct timer_info) {
- .machine = u->machine,
- .id = u->id,
- .next_elapse = m,
- .last_trigger = last,
- .triggered = TAKE_PTR(triggered),
- };
- }
-
- typesafe_qsort(timer_infos, c, timer_info_compare);
- }
-
- output_timers_list(timer_infos, c);
-
- cleanup:
- for (t = timer_infos; t < timer_infos + c; t++)
- strv_free(t->triggered);
-
- return r;
-}
-
-static int compare_unit_file_list(const UnitFileList *a, const UnitFileList *b) {
- const char *d1, *d2;
-
- d1 = strrchr(a->path, '.');
- d2 = strrchr(b->path, '.');
-
- if (d1 && d2) {
- int r;
-
- r = strcasecmp(d1, d2);
- if (r != 0)
- return r;
- }
-
- return strcasecmp(basename(a->path), basename(b->path));
-}
-
-static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) {
- assert(u);
-
- if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
- return false;
-
- if (!strv_isempty(arg_types)) {
- const char *dot;
-
- dot = strrchr(u->path, '.');
- if (!dot)
- return false;
-
- if (!strv_find(arg_types, dot+1))
- return false;
- }
-
- if (!strv_isempty(states) &&
- !strv_find(states, unit_file_state_to_string(u->state)))
- return false;
-
- return true;
-}
-
-static bool show_preset_for_state(UnitFileState state) {
- /* Don't show preset state in those unit file states, it'll only confuse users. */
- return !IN_SET(state,
- UNIT_FILE_ALIAS,
- UNIT_FILE_STATIC,
- UNIT_FILE_GENERATED,
- UNIT_FILE_TRANSIENT);
-}
-
-static int output_unit_file_list(const UnitFileList *units, unsigned c) {
- _cleanup_(table_unrefp) Table *table = NULL;
- _cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
- int r;
-
- table = table_new("unit file", "state", "vendor preset");
- if (!table)
- return log_oom();
-
- table_set_header(table, !arg_no_legend);
- if (arg_full)
- table_set_width(table, 0);
-
- (void) table_set_empty_string(table, "-");
-
- for (const UnitFileList *u = units; u < units + c; u++) {
- const char *on_underline = NULL, *on_unit_color = NULL, *id;
- bool underline;
-
- underline = u + 1 < units + c &&
- !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path));
-
- if (underline)
- on_underline = ansi_underline();
-
- if (IN_SET(u->state,
- UNIT_FILE_MASKED,
- UNIT_FILE_MASKED_RUNTIME,
- UNIT_FILE_DISABLED,
- UNIT_FILE_BAD))
- on_unit_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
- else if (IN_SET(u->state,
- UNIT_FILE_ENABLED,
- UNIT_FILE_ALIAS))
- on_unit_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
- else
- on_unit_color = on_underline;
-
- id = basename(u->path);
-
- r = table_add_many(table,
- TABLE_STRING, id,
- TABLE_SET_BOTH_COLORS, strempty(on_underline),
- TABLE_STRING, unit_file_state_to_string(u->state),
- TABLE_SET_BOTH_COLORS, strempty(on_unit_color));
- if (r < 0)
- return table_log_add_error(r);
-
- if (show_preset_for_state(u->state)) {
- const char *unit_preset_str, *on_preset_color;
-
- r = unit_file_query_preset(arg_scope, arg_root, id, &presets);
- if (r < 0) {
- unit_preset_str = "n/a";
- on_preset_color = underline ? on_underline : ansi_normal();
- } else if (r == 0) {
- unit_preset_str = "disabled";
- on_preset_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
- } else {
- unit_preset_str = "enabled";
- on_preset_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
- }
-
- r = table_add_many(table,
- TABLE_STRING, unit_preset_str,
- TABLE_SET_BOTH_COLORS, strempty(on_preset_color));
- } else
- r = table_add_many(table,
- TABLE_EMPTY,
- TABLE_SET_BOTH_COLORS, underline ? ansi_grey_underline() : ansi_grey());
- if (r < 0)
- return table_log_add_error(r);
- }
-
- r = output_table(table);
- if (r < 0)
- return r;
-
- if (!arg_no_legend)
- printf("\n%u unit files listed.\n", c);
-
- return 0;
-}
-
-static 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;
- char *path;
- int r;
- bool fallback = false;
-
- if (install_client_side()) {
- Hashmap *h;
- UnitFileList *u;
- unsigned n_units;
-
- h = hashmap_new(&string_hash_ops);
- if (!h)
- return log_oom();
-
- r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1));
- if (r < 0) {
- unit_file_list_free(h);
- return log_error_errno(r, "Failed to get unit file list: %m");
- }
-
- n_units = hashmap_size(h);
-
- units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */
- if (!units) {
- unit_file_list_free(h);
- return log_oom();
- }
-
- HASHMAP_FOREACH(u, h) {
- if (!output_show_unit_file(u, NULL, NULL))
- continue;
-
- units[c++] = *u;
- free(u);
- }
-
- assert(c <= n_units);
- hashmap_free(h);
-
- r = 0;
- } else {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitFilesByPatterns");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, arg_states);
- if (r < 0)
- return bus_log_create_error(r);
-
- if (arg_with_dependencies) {
- _cleanup_strv_free_ char **names_with_deps = NULL;
-
- r = append_unit_dependencies(bus, strv_skip(argv, 1), &names_with_deps);
- if (r < 0)
- return log_error_errno(r, "Failed to append unit dependencies: %m");
-
- r = sd_bus_message_append_strv(m, names_with_deps);
- if (r < 0)
- return bus_log_create_error(r);
- } else {
- r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
- /* Fallback to legacy ListUnitFiles method */
- fallback = true;
- log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
- m = sd_bus_message_unref(m);
- sd_bus_error_free(&error);
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "ListUnitFiles");
- 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 list unit files: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
-
- if (!GREEDY_REALLOC(units, size, c + 1))
- return log_oom();
-
- units[c] = (struct UnitFileList) {
- path,
- unit_file_state_from_string(state)
- };
-
- if (output_show_unit_file(&units[c],
- fallback ? arg_states : NULL,
- fallback ? strv_skip(argv, 1) : NULL))
- c++;
-
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- (void) pager_open(arg_pager_flags);
-
- typesafe_qsort(units, c, compare_unit_file_list);
- r = output_unit_file_list(units, c);
- if (r < 0)
- return r;
-
- if (install_client_side())
- for (unit = units; unit < units + c; unit++)
- free(unit->path);
-
- if (c == 0)
- return -ENOENT;
-
- return 0;
-}
-
-static int list_dependencies_print(const char *name, int level, unsigned branches, bool last) {
- _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--) {
- len += 2;
- if (len > max_len - 3 && !arg_full) {
- printf("%s...\n",max_len % 2 ? "" : " ");
- return 0;
- }
- printf("%s", special_glyph(branches & (1 << i) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
- }
- len += 2;
-
- if (len > max_len - 3 && !arg_full) {
- printf("%s...\n",max_len % 2 ? "" : " ");
- return 0;
- }
-
- printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
- }
-
- if (arg_full) {
- printf("%s\n", name);
- return 0;
- }
-
- n = ellipsize(name, max_len-len, 100);
- if (!n)
- return log_oom();
-
- printf("%s\n", n);
- return 0;
-}
-
-static int list_dependencies_compare(char * const *a, char * const *b) {
- if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
- return 1;
- if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
- return -1;
-
- return strcasecmp(*a, *b);
-}
-
-static int list_dependencies_one(
- sd_bus *bus,
- const char *name,
- int level,
- char ***units,
- unsigned branches) {
-
- _cleanup_strv_free_ char **deps = NULL;
- char **c;
- int r;
-
- assert(bus);
- assert(name);
- assert(units);
-
- r = strv_extend(units, name);
- if (r < 0)
- return log_oom();
-
- r = list_dependencies_get_dependencies(bus, name, &deps);
- if (r < 0)
- return r;
-
- typesafe_qsort(deps, strv_length(deps), list_dependencies_compare);
-
- STRV_FOREACH(c, deps) {
- if (strv_contains(*units, *c)) {
- if (!arg_plain) {
- printf(" ");
- r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
- if (r < 0)
- return r;
- }
- continue;
- }
-
- if (arg_plain)
- printf(" ");
- else {
- UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
- const char *on;
-
- (void) get_state_one_unit(bus, *c, &active_state);
-
- switch (active_state) {
- case UNIT_ACTIVE:
- case UNIT_RELOADING:
- case UNIT_ACTIVATING:
- on = ansi_highlight_green();
- break;
-
- case UNIT_INACTIVE:
- case UNIT_DEACTIVATING:
- on = ansi_normal();
- break;
-
- default:
- on = ansi_highlight_red();
- break;
- }
-
- printf("%s%s%s ", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), ansi_normal());
- }
-
- r = list_dependencies_print(*c, level, branches, c[1] == NULL);
- if (r < 0)
- return r;
-
- if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
- r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
- if (r < 0)
- return r;
- }
- }
-
- if (!arg_plain)
- strv_remove(*units, name);
-
- return 0;
-}
-
-static int list_dependencies(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **units = NULL, **done = NULL;
- char **u, **patterns;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- patterns = strv_skip(argv, 1);
- if (strv_isempty(patterns)) {
- units = strv_new(SPECIAL_DEFAULT_TARGET);
- if (!units)
- return log_oom();
- } else {
- r = expand_names(bus, patterns, NULL, &units, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
- }
-
- (void) pager_open(arg_pager_flags);
-
- STRV_FOREACH(u, units) {
- if (u != units)
- puts("");
-
- puts(*u);
- r = list_dependencies_one(bus, *u, 0, &done, 0);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-struct machine_info {
- bool is_host;
- char *name;
- char *state;
- char *control_group;
- uint32_t n_failed_units;
- uint32_t n_jobs;
- usec_t timestamp;
-};
-
-static const struct bus_properties_map machine_info_property_map[] = {
- { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
- { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
- { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
- { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
- { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
- {}
-};
-
-static void machine_info_clear(struct machine_info *info) {
- assert(info);
-
- free(info->name);
- free(info->state);
- free(info->control_group);
- zero(*info);
-}
-
-static void free_machines_list(struct machine_info *machine_infos, int n) {
- int i;
-
- if (!machine_infos)
- return;
-
- for (i = 0; i < n; i++)
- machine_info_clear(&machine_infos[i]);
-
- free(machine_infos);
-}
-
-static int compare_machine_info(const struct machine_info *a, const struct machine_info *b) {
- int r;
-
- r = CMP(b->is_host, a->is_host);
- if (r != 0)
- return r;
-
- return strcasecmp(a->name, b->name);
-}
-
-static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
- int r;
-
- assert(mi);
-
- if (!bus) {
- r = sd_bus_open_system_machine(&container, mi->name);
- if (r < 0)
- return r;
-
- bus = container;
- }
-
- r = bus_map_all_properties(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- machine_info_property_map,
- BUS_MAP_STRDUP,
- NULL,
- NULL,
- mi);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static bool output_show_machine(const char *name, char **patterns) {
- return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
-}
-
-static int get_machine_list(
- sd_bus *bus,
- struct machine_info **_machine_infos,
- char **patterns) {
-
- struct machine_info *machine_infos = NULL;
- _cleanup_strv_free_ char **m = NULL;
- _cleanup_free_ char *hn = NULL;
- size_t sz = 0;
- char **i;
- int c = 0, r;
-
- hn = gethostname_malloc();
- if (!hn)
- return log_oom();
-
- if (output_show_machine(hn, patterns)) {
- if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
- return log_oom();
-
- machine_infos[c].is_host = true;
- machine_infos[c].name = TAKE_PTR(hn);
-
- (void) get_machine_properties(bus, &machine_infos[c]);
- c++;
- }
-
- r = sd_get_machine_names(&m);
- if (r < 0)
- return log_error_errno(r, "Failed to get machine list: %m");
-
- STRV_FOREACH(i, m) {
- _cleanup_free_ char *class = NULL;
-
- if (!output_show_machine(*i, patterns))
- continue;
-
- sd_machine_get_class(*i, &class);
- if (!streq_ptr(class, "container"))
- continue;
-
- if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
- free_machines_list(machine_infos, c);
- return log_oom();
- }
-
- machine_infos[c].is_host = false;
- machine_infos[c].name = strdup(*i);
- if (!machine_infos[c].name) {
- free_machines_list(machine_infos, c);
- return log_oom();
- }
-
- (void) get_machine_properties(NULL, &machine_infos[c]);
- c++;
- }
-
- *_machine_infos = machine_infos;
- return c;
-}
-
-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;
-
- assert(machine_infos || n == 0);
-
- table = table_new("", "name", "state", "failed", "jobs");
- if (!table)
- return log_oom();
-
- table_set_header(table, !arg_no_legend);
- if (arg_plain) {
- /* Hide the 'glyph' column when --plain is requested */
- r = table_hide_column_from_display(table, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to hide column: %m");
- }
- if (arg_full)
- table_set_width(table, 0);
-
- (void) table_set_empty_string(table, "-");
-
- for (m = machine_infos; m < machine_infos + n; m++) {
- _cleanup_free_ char *mname = NULL;
- const char *on_state = "", *on_failed = "";
- bool circle = false;
-
- if (streq_ptr(m->state, "degraded")) {
- on_state = ansi_highlight_red();
- circle = true;
- } else if (!streq_ptr(m->state, "running")) {
- on_state = ansi_highlight_yellow();
- circle = true;
- }
-
- if (m->n_failed_units > 0)
- on_failed = ansi_highlight_red();
- else
- on_failed = "";
-
- if (!m->state)
- state_missing = true;
-
- if (m->is_host)
- mname = strjoin(strna(m->name), " (host)");
-
- r = table_add_many(table,
- TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
- TABLE_SET_COLOR, on_state,
- TABLE_STRING, m->is_host ? mname : strna(m->name),
- TABLE_STRING, strna(m->state),
- TABLE_SET_COLOR, on_state,
- TABLE_UINT32, m->n_failed_units,
- TABLE_SET_COLOR, on_failed,
- TABLE_UINT32, m->n_jobs);
- if (r < 0)
- return table_log_add_error(r);
- }
-
- r = output_table(table);
- if (r < 0)
- return r;
-
- if (!arg_no_legend) {
- printf("\n");
- if (state_missing && geteuid() != 0)
- printf("Notice: some information only available to privileged users was not shown.\n");
- printf("%u machines listed.\n", n);
- }
-
- return 0;
-}
-
-static int list_machines(int argc, char *argv[], void *userdata) {
- struct machine_info *machine_infos = NULL;
- sd_bus *bus;
- int r, rc;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1));
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- typesafe_qsort(machine_infos, r, compare_machine_info);
- rc = output_machines_list(machine_infos, r);
- free_machines_list(machine_infos, r);
-
- return rc;
-}
-
-static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
- char **ret = data;
-
- if (streq(key, "systemd.unit")) {
- if (proc_cmdline_value_missing(key, value))
- return 0;
- if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
- log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
- return 0;
- }
-
- return free_and_strdup_warn(ret, key);
-
- } else if (!value) {
- if (runlevel_to_target(key))
- return free_and_strdup_warn(ret, key);
- }
-
- return 0;
-}
-
-static void emit_cmdline_warning(void) {
- if (arg_quiet || arg_root)
- /* don't bother checking the commandline if we're operating on a container */
- return;
-
- _cleanup_free_ char *override = NULL;
- int r;
-
- r = proc_cmdline_parse(parse_proc_cmdline_item, &override, 0);
- if (r < 0)
- log_debug_errno(r, "Failed to parse kernel command line, ignoring: %m");
- if (override)
- log_notice("Note: found \"%s\" on the kernel commandline, which overrides the default unit.",
- override);
-}
-
-static int determine_default(char **ret_name) {
- int r;
-
- if (install_client_side()) {
- r = unit_file_get_default(arg_scope, arg_root, ret_name);
- if (r < 0)
- return log_error_errno(r, "Failed to get default target: %m");
- return 0;
-
- } else {
- sd_bus *bus;
- _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 *name;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "GetDefaultTarget", &error, &reply, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return free_and_strdup_warn(ret_name, name);
- }
-}
-
-static int get_default(int argc, char *argv[], void *userdata) {
- _cleanup_free_ char *name = NULL;
- int r;
-
- r = determine_default(&name);
- if (r < 0)
- return r;
-
- printf("%s\n", name);
-
- emit_cmdline_warning();
-
- return 0;
-}
-
-static int set_default(int argc, char *argv[], void *userdata) {
- _cleanup_free_ char *unit = NULL;
- UnitFileChange *changes = NULL;
- size_t n_changes = 0;
- int r;
-
- assert(argc >= 2);
- assert(argv);
-
- r = unit_name_mangle_with_suffix(argv[1], "set-default",
- arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
- ".target", &unit);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- if (install_client_side()) {
- r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
- unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
-
- if (r > 0)
- r = 0;
- } else {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- sd_bus *bus;
-
- polkit_agent_open_maybe();
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "SetDefaultTarget", &error, &reply, "sb", unit, 1);
- if (r < 0)
- return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
-
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
- if (r < 0)
- goto finish;
-
- /* Try to reload if enabled */
- if (!arg_no_reload)
- r = daemon_reload(argc, argv, userdata);
- else
- r = 0;
- }
-
- emit_cmdline_warning();
-
- if (!arg_quiet) {
- _cleanup_free_ char *final = NULL;
-
- r = determine_default(&final);
- if (r < 0)
- return r;
-
- if (!streq(final, unit))
- log_notice("Note: \"%s\" is the default unit (possibly a runtime override).", final);
- }
-
-finish:
- unit_file_changes_free(changes, n_changes);
-
- return r;
-}
-
-static int output_waiting_jobs(sd_bus *bus, Table *table, uint32_t id, const char *method, const char *prefix) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *name, *type;
- uint32_t other_id;
- int r;
-
- assert(bus);
-
- r = bus_call_method(bus, bus_systemd_mgr, method, &error, &reply, "u", id);
- if (r < 0)
- return log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id);
-
- r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0) {
- _cleanup_free_ char *row = NULL;
- int rc;
-
- if (asprintf(&row, "%s %u (%s/%s)", prefix, other_id, name, type) < 0)
- return log_oom();
-
- rc = table_add_many(table,
- TABLE_STRING, special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
- TABLE_STRING, row,
- TABLE_EMPTY,
- TABLE_EMPTY);
- if (rc < 0)
- return table_log_add_error(r);
- }
-
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-}
-
-struct job_info {
- uint32_t id;
- const char *name, *type, *state;
-};
-
-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;
-
- assert(n == 0 || jobs);
-
- if (n == 0) {
- if (!arg_no_legend) {
- on = ansi_highlight_green();
- off = ansi_normal();
-
- printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
- }
- return 0;
- }
-
- (void) pager_open(arg_pager_flags);
-
- table = table_new("job", "unit", "type", "state");
- if (!table)
- return log_oom();
-
- table_set_header(table, !arg_no_legend);
- if (arg_full)
- table_set_width(table, 0);
-
- (void) table_set_empty_string(table, "-");
-
- for (j = jobs; j < jobs + n; j++) {
- if (streq(j->state, "running"))
- on = ansi_highlight();
- else
- on = "";
-
- r = table_add_many(table,
- TABLE_UINT, j->id,
- TABLE_STRING, j->name,
- TABLE_SET_COLOR, on,
- TABLE_STRING, j->type,
- TABLE_STRING, j->state,
- TABLE_SET_COLOR, on);
- if (r < 0)
- return table_log_add_error(r);
-
- if (arg_jobs_after)
- output_waiting_jobs(bus, table, j->id, "GetJobAfter", "\twaiting for job");
- if (arg_jobs_before)
- output_waiting_jobs(bus, table, j->id, "GetJobBefore", "\tblocking job");
- }
-
- r = table_print(table, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to print the table: %m");
-
- if (!arg_no_legend) {
- on = ansi_highlight();
- off = ansi_normal();
-
- printf("\n%s%u jobs listed%s.\n", on, n, off);
- }
-
- return 0;
-}
-
-static bool output_show_job(struct job_info *job, char **patterns) {
- return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
-}
-
-static int list_jobs(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ struct job_info *jobs = NULL;
- const char *name, *type, *state;
- bool skipped = false;
- size_t size = 0;
- unsigned c = 0;
- sd_bus *bus;
- uint32_t id;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "ListJobs", &error, &reply, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, NULL, NULL)) > 0) {
- struct job_info job = { id, name, type, state };
-
- if (!output_show_job(&job, strv_skip(argv, 1))) {
- skipped = true;
- continue;
- }
-
- if (!GREEDY_REALLOC(jobs, size, c + 1))
- return log_oom();
-
- jobs[c++] = job;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- (void) pager_open(arg_pager_flags);
-
- return output_jobs_list(bus, jobs, c, skipped);
-}
-
-static int cancel_job(int argc, char *argv[], void *userdata) {
- sd_bus *bus;
- char **name;
- int r;
-
- if (argc <= 1)
- return trivial_method(argc, argv, userdata);
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- STRV_FOREACH(name, strv_skip(argv, 1)) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- uint32_t id;
- int q;
-
- q = safe_atou32(*name, &id);
- if (q < 0)
- return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
-
- q = bus_call_method(bus, bus_systemd_mgr, "CancelJob", &error, NULL, "u", id);
- if (q < 0) {
- log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
- }
-
- return r;
-}
-
-static int need_daemon_reload(sd_bus *bus, const char *unit) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *path;
- int b, r;
-
- /* We ignore all errors here, since this is used to show a
- * warning only */
-
- /* We don't use unit_dbus_path_from_name() directly since we
- * don't want to load the unit if it isn't loaded. */
-
- r = bus_call_method(bus, bus_systemd_mgr, "GetUnit", NULL, &reply, "s", unit);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "o", &path);
- if (r < 0)
- return r;
-
- r = sd_bus_get_property_trivial(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "NeedDaemonReload",
- NULL,
- 'b', &b);
- if (r < 0)
- return r;
-
- return b;
-}
-
-static void warn_unit_file_changed(const char *name) {
- assert(name);
-
- log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
- ansi_highlight_red(),
- ansi_normal(),
- name,
- arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
-}
-
-static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **ret_unit_path) {
- char **p;
-
- assert(lp);
- assert(unit_name);
-
- STRV_FOREACH(p, lp->search_path) {
- _cleanup_free_ char *path = NULL, *lpath = NULL;
- int r;
-
- path = path_join(*p, unit_name);
- if (!path)
- return log_oom();
-
- r = chase_symlinks(path, arg_root, 0, &lpath, NULL);
- if (r == -ENOENT)
- continue;
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0)
- return log_error_errno(r, "Failed to access path \"%s\": %m", path);
-
- if (ret_unit_path)
- *ret_unit_path = TAKE_PTR(lpath);
-
- return 1;
- }
-
- if (ret_unit_path)
- *ret_unit_path = NULL;
-
- return 0;
-}
-
-static int unit_find_template_path(
- const char *unit_name,
- LookupPaths *lp,
- char **ret_fragment_path,
- char **ret_template) {
-
- _cleanup_free_ char *t = NULL, *f = NULL;
- int r;
-
- /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
-
- r = unit_file_find_path(lp, unit_name, &f);
- if (r < 0)
- return r;
- if (r > 0) {
- if (ret_fragment_path)
- *ret_fragment_path = TAKE_PTR(f);
- if (ret_template)
- *ret_template = NULL;
- return r; /* found a real unit */
- }
-
- r = unit_name_template(unit_name, &t);
- if (r == -EINVAL) {
- if (ret_fragment_path)
- *ret_fragment_path = NULL;
- if (ret_template)
- *ret_template = NULL;
-
- return 0; /* not a template, does not exist */
- }
- if (r < 0)
- return log_error_errno(r, "Failed to determine template name: %m");
-
- r = unit_file_find_path(lp, t, ret_fragment_path);
- if (r < 0)
- return r;
-
- if (ret_template)
- *ret_template = r > 0 ? TAKE_PTR(t) : NULL;
-
- return r;
-}
-
-static int unit_find_paths(
- sd_bus *bus,
- const char *unit_name,
- LookupPaths *lp,
- bool force_client_side,
- char **ret_fragment_path,
- char ***ret_dropin_paths) {
-
- _cleanup_strv_free_ char **dropins = NULL;
- _cleanup_free_ char *path = NULL;
- int r;
-
- /**
- * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is
- * found, and sets:
- * - the path to the unit in *ret_frament_path, if it exists on disk,
- * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins
- * were found.
- *
- * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for
- * some reason (the latter only applies if we are going through the service manager).
- */
-
- assert(unit_name);
- assert(ret_fragment_path);
- assert(lp);
-
- /* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
- if (!force_client_side &&
- !install_client_side() &&
- !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *load_state = NULL, *dbus_path = NULL;
-
- dbus_path = unit_dbus_path_from_name(unit_name);
- if (!dbus_path)
- return log_oom();
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Unit",
- "LoadState",
- &error,
- &load_state);
- if (r < 0)
- return log_error_errno(r, "Failed to get LoadState: %s", bus_error_message(&error, r));
-
- if (streq(load_state, "masked"))
- return -ERFKILL;
- if (streq(load_state, "not-found")) {
- r = 0;
- goto not_found;
- }
- if (!STR_IN_SET(load_state, "loaded", "bad-setting"))
- return -EKEYREJECTED;
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Unit",
- "FragmentPath",
- &error,
- &path);
- if (r < 0)
- return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
-
- if (ret_dropin_paths) {
- r = sd_bus_get_property_strv(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Unit",
- "DropInPaths",
- &error,
- &dropins);
- if (r < 0)
- return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
- }
- } else {
- const char *_path;
- _cleanup_set_free_free_ Set *names = NULL;
-
- if (!cached_name_map) {
- r = unit_file_build_name_map(lp, NULL, &cached_id_map, &cached_name_map, NULL);
- if (r < 0)
- return r;
- }
-
- r = unit_file_find_fragment(cached_id_map, cached_name_map, unit_name, &_path, &names);
- if (r < 0)
- return r;
-
- if (_path) {
- path = strdup(_path);
- if (!path)
- return log_oom();
- }
-
- if (ret_dropin_paths) {
- r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL,
- ".d", ".conf",
- NULL, names, &dropins);
- if (r < 0)
- return r;
- }
- }
-
- if (isempty(path)) {
- *ret_fragment_path = NULL;
- r = 0;
- } else {
- *ret_fragment_path = TAKE_PTR(path);
- r = 1;
- }
-
- if (ret_dropin_paths) {
- if (!strv_isempty(dropins)) {
- *ret_dropin_paths = TAKE_PTR(dropins);
- r = 1;
- } else
- *ret_dropin_paths = NULL;
- }
-
- not_found:
- if (r == 0 && !arg_force)
- log_error("No files found for %s.", unit_name);
-
- return r;
-}
-
-static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *buf = NULL, *dbus_path = NULL;
- UnitActiveState state;
- int r;
-
- assert(name);
- assert(active_state);
-
- dbus_path = unit_dbus_path_from_name(name);
- if (!dbus_path)
- return log_oom();
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Unit",
- "ActiveState",
- &error,
- &buf);
- if (r < 0)
- return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
-
- state = unit_active_state_from_string(buf);
- if (state < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit state '%s' for: %s", buf, name);
-
- *active_state = state;
- return 0;
-}
-
-static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) {
- _cleanup_free_ char *load_state = NULL;
- int r;
-
- if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
- _cleanup_free_ char *path = NULL;
-
- /* A template cannot be loaded, but it can be still masked, so
- * we need to use a different method. */
-
- r = unit_file_find_path(lp, name, &path);
- if (r < 0)
- return r;
- if (r == 0)
- return false;
- return null_or_empty_path(path);
- }
-
- r = unit_load_state(bus, name, &load_state);
- if (r < 0)
- return r;
-
- return streq(load_state, "masked");
-}
-
-static int check_triggering_units(sd_bus *bus, const char *name) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL;
- _cleanup_strv_free_ char **triggered_by = NULL;
- bool print_warning_label = true;
- UnitActiveState active_state;
- char **i;
- int r;
-
- r = unit_name_mangle(name, 0, &n);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- r = unit_load_state(bus, name, &load_state);
- if (r < 0)
- return r;
-
- if (streq(load_state, "masked"))
- return 0;
-
- dbus_path = unit_dbus_path_from_name(n);
- if (!dbus_path)
- return log_oom();
-
- r = sd_bus_get_property_strv(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Unit",
- "TriggeredBy",
- &error,
- &triggered_by);
- if (r < 0)
- return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
-
- STRV_FOREACH(i, triggered_by) {
- r = get_state_one_unit(bus, *i, &active_state);
- if (r < 0)
- return r;
-
- if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
- continue;
-
- if (print_warning_label) {
- log_warning("Warning: Stopping %s, but it can still be activated by:", n);
- print_warning_label = false;
- }
-
- log_warning(" %s", *i);
- }
-
- return 0;
-}
-
-static const struct {
- const char *verb; /* systemctl verb */
- const char *method; /* Name of the specific D-Bus method */
- const char *job_type; /* Job type when passing to the generic EnqueueUnitJob() method */
-} unit_actions[] = {
- { "start", "StartUnit", "start" },
- { "stop", "StopUnit", "stop" },
- { "condstop", "StopUnit", "stop" }, /* legacy alias */
- { "reload", "ReloadUnit", "reload" },
- { "restart", "RestartUnit", "restart" },
- { "try-restart", "TryRestartUnit", "try-restart" },
- { "condrestart", "TryRestartUnit", "try-restart" }, /* legacy alias */
- { "reload-or-restart", "ReloadOrRestartUnit", "reload-or-restart" },
- { "try-reload-or-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" },
- { "reload-or-try-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
- { "condreload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
- { "force-reload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
-};
-
-static const char *verb_to_method(const char *verb) {
- size_t i;
-
- for (i = 0; i < ELEMENTSOF(unit_actions); i++)
- if (streq_ptr(unit_actions[i].verb, verb))
- return unit_actions[i].method;
-
- return "StartUnit";
-}
-
-static const char *verb_to_job_type(const char *verb) {
- size_t i;
-
- for (i = 0; i < ELEMENTSOF(unit_actions); i++)
- if (streq_ptr(unit_actions[i].verb, verb))
- return unit_actions[i].job_type;
-
- return "start";
-}
-
-static int start_unit_one(
- sd_bus *bus,
- const char *method, /* When using classic per-job bus methods */
- const char *job_type, /* When using new-style EnqueueUnitJob() */
- const char *name,
- const char *mode,
- sd_bus_error *error,
- BusWaitForJobs *w,
- BusWaitForUnits *wu) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *path;
- bool done = false;
- int r;
-
- assert(method);
- assert(name);
- assert(mode);
- assert(error);
-
- log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
- arg_dry_run ? "Would execute" : "Executing",
- method, name, mode);
-
- if (arg_dry_run)
- return 0;
-
- if (arg_show_transaction) {
- _cleanup_(sd_bus_error_free) sd_bus_error enqueue_error = SD_BUS_ERROR_NULL;
-
- /* Use the new, fancy EnqueueUnitJob() API if the user wants us to print the transaction */
- r = bus_call_method(
- bus,
- bus_systemd_mgr,
- "EnqueueUnitJob",
- &enqueue_error,
- &reply,
- "sss",
- name, job_type, mode);
- if (r < 0) {
- if (!sd_bus_error_has_name(&enqueue_error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
- (void) sd_bus_error_move(error, &enqueue_error);
- goto fail;
- }
-
- /* Hmm, the API is not yet available. Let's use the classic API instead (see below). */
- log_notice("--show-transaction not supported by this service manager, proceeding without.");
- } else {
- const char *u, *jt;
- uint32_t id;
-
- r = sd_bus_message_read(reply, "uosos", &id, &path, &u, NULL, &jt);
- if (r < 0)
- return bus_log_parse_error(r);
-
- log_info("Enqueued anchor job %" PRIu32 " %s/%s.", id, u, jt);
-
- r = sd_bus_message_enter_container(reply, 'a', "(uosos)");
- if (r < 0)
- return bus_log_parse_error(r);
- for (;;) {
- r = sd_bus_message_read(reply, "(uosos)", &id, NULL, &u, NULL, &jt);
- if (r < 0)
- return bus_log_parse_error(r);
- if (r == 0)
- break;
-
- log_info("Enqueued auxiliary job %" PRIu32 " %s/%s.", id, u, jt);
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- done = true;
- }
- }
-
- if (!done) {
- r = bus_call_method(bus, bus_systemd_mgr, method, error, &reply, "ss", name, mode);
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_read(reply, "o", &path);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- if (need_daemon_reload(bus, name) > 0)
- warn_unit_file_changed(name);
-
- if (w) {
- 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 for %s: %m", name);
- }
-
- if (wu) {
- r = bus_wait_for_units_add_unit(wu, name, BUS_WAIT_FOR_INACTIVE|BUS_WAIT_NO_JOB, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to watch unit %s: %m", name);
- }
-
- return 0;
-
-fail:
- /* There's always a fallback possible for legacy actions. */
- if (arg_action != ACTION_SYSTEMCTL)
- return r;
-
- log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r));
-
- if (!sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
- BUS_ERROR_UNIT_MASKED,
- BUS_ERROR_JOB_TYPE_NOT_APPLICABLE))
- log_error("See %s logs and 'systemctl%s status%s %s' for details.",
- arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
- arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
- name[0] == '-' ? " --" : "",
- name);
-
- return r;
-}
-
-static const struct {
- const char *target;
- const char *verb;
- const char *mode;
-} action_table[_ACTION_MAX] = {
- [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
- [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
- [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
- [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
- [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
- [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
- [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
- [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
- [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
- [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
- [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
- [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
- [ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" },
-};
-
-static enum action verb_to_action(const char *verb) {
- enum action i;
-
- for (i = 0; i < _ACTION_MAX; i++)
- if (streq_ptr(action_table[i].verb, verb))
- return i;
-
- return _ACTION_INVALID;
-}
-
-static const char** make_extra_args(const char *extra_args[static 4]) {
- size_t n = 0;
-
- assert(extra_args);
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- extra_args[n++] = "--user";
-
- if (arg_transport == BUS_TRANSPORT_REMOTE) {
- extra_args[n++] = "-H";
- extra_args[n++] = arg_host;
- } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
- extra_args[n++] = "-M";
- extra_args[n++] = arg_host;
- } else
- assert(arg_transport == BUS_TRANSPORT_LOCAL);
-
- extra_args[n] = NULL;
- return extra_args;
-}
-
-static int start_unit(int argc, char *argv[], void *userdata) {
- _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *wu = NULL;
- _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
- const char *method, *job_type, *mode, *one_name, *suffix = NULL;
- _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */
- _cleanup_strv_free_ char **names = NULL;
- int r, ret = EXIT_SUCCESS;
- sd_bus *bus;
- char **name;
-
- if (arg_wait && !STR_IN_SET(argv[0], "start", "restart"))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--wait may only be used with the 'start' or 'restart' commands.");
-
- /* we cannot do sender tracking on the private bus, so we need the full
- * one for RefUnit to implement --wait */
- r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- ask_password_agent_open_maybe();
- polkit_agent_open_maybe();
-
- if (arg_action == ACTION_SYSTEMCTL) {
- enum action action;
-
- action = verb_to_action(argv[0]);
-
- if (action != _ACTION_INVALID) {
- /* A command in style "systemctl reboot", "systemctl poweroff", … */
- method = "StartUnit";
- job_type = "start";
- mode = action_table[action].mode;
- one_name = action_table[action].target;
- } else {
- if (streq(argv[0], "isolate")) {
- /* A "systemctl isolate <unit1> <unit2> …" command */
- method = "StartUnit";
- job_type = "start";
- mode = "isolate";
- suffix = ".target";
- } else {
- /* 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]);
- mode = arg_job_mode;
- }
- one_name = NULL;
- }
- } else {
- /* A SysV legacy command such as "halt", "reboot", "poweroff", … */
- assert(arg_action >= 0 && arg_action < _ACTION_MAX);
- assert(action_table[arg_action].target);
- assert(action_table[arg_action].mode);
-
- method = "StartUnit";
- job_type = "start";
- mode = action_table[arg_action].mode;
- one_name = action_table[arg_action].target;
- }
-
- if (one_name) {
- names = strv_new(one_name);
- if (!names)
- return log_oom();
- } else {
- bool expanded;
-
- r = expand_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- if (!arg_all && expanded && streq(job_type, "start") && !arg_quiet) {
- log_warning("Warning: %ssystemctl start called with a glob pattern.%s",
- ansi_highlight_red(),
- ansi_normal());
- log_notice("Hint: unit globs expand to loaded units, so start will usually have no effect.\n"
- " Passing --all will also load units which are pulled in by other units.\n"
- " See systemctl(1) for more details.");
- }
- }
-
- if (!arg_no_block) {
- r = bus_wait_for_jobs_new(bus, &w);
- if (r < 0)
- return log_error_errno(r, "Could not watch jobs: %m");
- }
-
- if (arg_wait) {
- r = bus_call_method_async(bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to enable subscription: %m");
-
- r = bus_wait_for_units_new(bus, &wu);
- if (r < 0)
- 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;
-
- 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];
-
- r = bus_wait_for_jobs(w, arg_quiet, make_extra_args(extra_args));
- if (r < 0)
- return r;
-
- /* When stopping units, warn if they can still be triggered by
- * another active unit (socket, path, timer) */
- if (!arg_quiet)
- STRV_FOREACH(name, stopped_units)
- (void) check_triggering_units(bus, *name);
- }
-
- if (arg_wait) {
- r = bus_wait_for_units_run(wu);
- if (r < 0)
- return log_error_errno(r, "Failed to wait for units: %m");
- if (r == BUS_WAIT_FAILURE && ret == EXIT_SUCCESS)
- ret = EXIT_FAILURE;
- }
-
- return ret;
-}
-
-#if ENABLE_LOGIND
-static int logind_set_wall_message(void) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- _cleanup_free_ char *m = NULL;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- m = strv_join(arg_wall, " ");
- if (!m)
- return log_oom();
-
- log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
- if (arg_dry_run)
- return 0;
-
- r = bus_call_method(bus, bus_login_mgr, "SetWallMessage", &error, NULL, "sb", m, !arg_no_wall);
- if (r < 0)
- return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
- return 0;
-}
-#endif
-
-/* Ask systemd-logind, which might grant access to unprivileged users through polkit */
-static int logind_reboot(enum action a) {
-#if ENABLE_LOGIND
- static const struct {
- const char *method;
- const char *description;
- } actions[_ACTION_MAX] = {
- [ACTION_POWEROFF] = { "PowerOff", "power off system" },
- [ACTION_REBOOT] = { "Reboot", "reboot system" },
- [ACTION_HALT] = { "Halt", "halt system" },
- [ACTION_SUSPEND] = { "Suspend", "suspend system" },
- [ACTION_HIBERNATE] = { "Hibernate", "hibernate system" },
- [ACTION_HYBRID_SLEEP] = { "HybridSleep", "put system into hybrid sleep" },
- [ACTION_SUSPEND_THEN_HIBERNATE] = { "SuspendThenHibernate", "suspend system, hibernate later" },
- };
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- if (a < 0 || a >= _ACTION_MAX || !actions[a].method)
- return -EINVAL;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
- (void) logind_set_wall_message();
-
- log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", actions[a].method);
-
- if (arg_dry_run)
- return 0;
-
- 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));
-
- return 0;
-#else
- return -ENOSYS;
-#endif
-}
-
-static int logind_check_inhibitors(enum action a) {
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_strv_free_ char **sessions = NULL;
- const char *what, *who, *why, *mode;
- uint32_t uid, pid;
- sd_bus *bus;
- unsigned c = 0;
- char **s;
- int r;
-
- if (arg_ignore_inhibitors || arg_force > 0)
- return 0;
-
- if (arg_when > 0)
- return 0;
-
- if (geteuid() == 0)
- return 0;
-
- if (!on_tty())
- return 0;
-
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return 0;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_login_mgr, "ListInhibitors", NULL, &reply, NULL);
- if (r < 0)
- /* If logind is not around, then there are no inhibitors... */
- return 0;
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
- _cleanup_free_ char *comm = NULL, *user = NULL;
- _cleanup_strv_free_ char **sv = NULL;
-
- if (!streq(mode, "block"))
- continue;
-
- sv = strv_split(what, ":");
- if (!sv)
- return log_oom();
-
- if (!pid_is_valid((pid_t) pid))
- return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid PID "PID_FMT".", (pid_t) pid);
-
- if (!strv_contains(sv,
- IN_SET(a,
- ACTION_HALT,
- ACTION_POWEROFF,
- ACTION_REBOOT,
- ACTION_KEXEC) ? "shutdown" : "sleep"))
- continue;
-
- get_process_comm(pid, &comm);
- user = uid_to_name(uid);
-
- log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
- who, (pid_t) pid, strna(comm), strna(user), why);
-
- c++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- /* Check for current sessions */
- sd_get_sessions(&sessions);
- STRV_FOREACH(s, sessions) {
- _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
-
- if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
- continue;
-
- if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
- continue;
-
- if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
- continue;
-
- sd_session_get_tty(*s, &tty);
- sd_session_get_seat(*s, &seat);
- sd_session_get_service(*s, &service);
- user = uid_to_name(uid);
-
- log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
- c++;
- }
-
- if (c <= 0)
- return 0;
-
- log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
- action_table[a].verb);
-
- return -EPERM;
-#else
- return 0;
-#endif
-}
-
-static int prepare_firmware_setup(void) {
-
- if (!arg_firmware_setup)
- return 0;
-
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_login_mgr, "SetRebootToFirmwareSetup", &error, NULL, "b", true);
- if (r < 0)
- return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
-
- return 0;
-#else
- return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
- "Booting into firmware setup not supported.");
-#endif
-}
-
-static int prepare_boot_loader_menu(void) {
-
- if (arg_boot_loader_menu == USEC_INFINITY)
- return 0;
-
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderMenu", &error, NULL, "t", arg_boot_loader_menu);
- if (r < 0)
- return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
-
- return 0;
-#else
- return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
- "Booting into boot loader menu not supported.");
-#endif
-}
-
-static int prepare_boot_loader_entry(void) {
-
- if (!arg_boot_loader_entry)
- return 0;
-
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderEntry", &error, NULL, "s", arg_boot_loader_entry);
- if (r < 0)
- return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
-
- return 0;
-#else
- return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
- "Booting into boot loader entry not supported.");
-#endif
-}
-
-static int load_kexec_kernel(void) {
- _cleanup_(boot_config_free) BootConfig config = {};
- _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL;
- const BootEntry *e;
- pid_t pid;
- int r;
-
- if (kexec_loaded()) {
- log_debug("Kexec kernel already loaded.");
- return 0;
- }
-
- if (access(KEXEC, X_OK) < 0)
- return log_error_errno(errno, KEXEC" is not available: %m");
-
- r = boot_entries_load_config_auto(NULL, NULL, &config);
- if (r == -ENOKEY)
- /* The call doesn't log about ENOKEY, let's do so here. */
- return log_error_errno(r,
- "No kexec kernel loaded and autodetection failed.\n%s",
- is_efi_boot()
- ? "Cannot automatically load kernel: ESP partition mount point not found."
- : "Automatic loading works only on systems booted with EFI.");
- if (r < 0)
- return r;
-
- e = boot_config_default_entry(&config);
- if (!e)
- return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
- "No boot loader entry suitable as default, refusing to guess.");
-
- log_debug("Found default boot loader entry in file \"%s\"", e->path);
-
- if (!e->kernel)
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Boot entry does not refer to Linux kernel, which is not supported currently.");
- if (strv_length(e->initrd) > 1)
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Boot entry specifies multiple initrds, which is not supported currently.");
-
- kernel = path_join(e->root, e->kernel);
- if (!kernel)
- return log_oom();
-
- if (!strv_isempty(e->initrd)) {
- initrd = path_join(e->root, e->initrd[0]);
- if (!initrd)
- return log_oom();
- }
-
- options = strv_join(e->options, " ");
- if (!options)
- return log_oom();
-
- log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
- "%s "KEXEC" --load \"%s\" --append \"%s\"%s%s%s",
- arg_dry_run ? "Would run" : "Running",
- kernel,
- options,
- initrd ? " --initrd \"" : NULL, strempty(initrd), initrd ? "\"" : "");
- if (arg_dry_run)
- return 0;
-
- r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
- if (r < 0)
- return r;
- if (r == 0) {
- const char* const args[] = {
- KEXEC,
- "--load", kernel,
- "--append", options,
- initrd ? "--initrd" : NULL, initrd,
- NULL
- };
-
- /* Child */
- execv(args[0], (char * const *) args);
- _exit(EXIT_FAILURE);
- }
-
- return 0;
-}
-
-static int set_exit_code(uint8_t code) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "SetExitCode", &error, NULL, "y", code);
- if (r < 0)
- return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-static int start_special(int argc, char *argv[], void *userdata) {
- enum action a;
- int r;
- bool termination_action; /* an action that terminates the manager,
- * can be performed also by signal. */
-
- assert(argv);
-
- a = verb_to_action(argv[0]);
-
- r = logind_check_inhibitors(a);
- if (r < 0)
- return r;
-
- if (arg_force >= 2) {
- r = must_be_root();
- if (r < 0)
- return r;
- }
-
- r = prepare_firmware_setup();
- if (r < 0)
- return r;
-
- r = prepare_boot_loader_menu();
- if (r < 0)
- return r;
-
- r = prepare_boot_loader_entry();
- if (r < 0)
- return r;
-
- if (a == ACTION_REBOOT) {
- const char *arg = NULL;
-
- if (argc > 1) {
- if (arg_reboot_argument)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Both --reboot-argument= and positional argument passed to reboot command, refusing.");
-
- log_notice("Positional argument to reboot command is deprecated, please use --reboot-argument= instead. Accepting anyway.");
- arg = argv[1];
- } else
- arg = arg_reboot_argument;
-
- if (arg) {
- r = update_reboot_parameter_and_warn(arg, false);
- if (r < 0)
- return r;
- }
-
- } else if (a == ACTION_KEXEC) {
- r = load_kexec_kernel();
- if (r < 0 && arg_force >= 1)
- log_notice("Failed to load kexec kernel, continuing without.");
- else if (r < 0)
- return r;
-
- } else if (a == ACTION_EXIT && argc > 1) {
- uint8_t code;
-
- /* If the exit code is not given on the command line,
- * don't reset it to zero: just keep it as it might
- * have been set previously. */
-
- r = safe_atou8(argv[1], &code);
- if (r < 0)
- return log_error_errno(r, "Invalid exit code.");
-
- r = set_exit_code(code);
- if (r < 0)
- return r;
- }
-
- termination_action = IN_SET(a,
- ACTION_HALT,
- ACTION_POWEROFF,
- ACTION_REBOOT);
- if (termination_action && arg_force >= 2)
- return halt_now(a);
-
- if (arg_force >= 1 &&
- (termination_action || IN_SET(a, ACTION_KEXEC, ACTION_EXIT)))
- r = trivial_method(argc, argv, userdata);
- else {
- /* First try logind, to allow authentication with polkit */
- if (IN_SET(a,
- ACTION_POWEROFF,
- ACTION_REBOOT,
- ACTION_HALT,
- ACTION_SUSPEND,
- ACTION_HIBERNATE,
- ACTION_HYBRID_SLEEP,
- ACTION_SUSPEND_THEN_HIBERNATE)) {
-
- r = logind_reboot(a);
- if (r >= 0)
- return r;
- if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
- /* requested operation is not supported or already in progress */
- return r;
-
- /* On all other errors, try low-level operation. In order to minimize the difference between
- * operation with and without logind, we explicitly enable non-blocking mode for this, as
- * logind's shutdown operations are always non-blocking. */
-
- arg_no_block = true;
-
- } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
- /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
- * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
- arg_no_block = true;
-
- r = start_unit(argc, argv, userdata);
- }
-
- if (termination_action && arg_force < 2 &&
- IN_SET(r, -ENOENT, -ETIMEDOUT))
- log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
-
- return r;
-}
-
-static int start_system_special(int argc, char *argv[], void *userdata) {
- /* Like start_special above, but raises an error when running in user mode */
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Bad action for %s mode.",
- arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
-
- return start_special(argc, argv, userdata);
-}
-
-static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
- _cleanup_strv_free_ char **names = NULL;
- UnitActiveState active_state;
- sd_bus *bus;
- char **name;
- int r, i;
- bool found = false;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = expand_names(bus, args, NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- STRV_FOREACH(name, names) {
- r = get_state_one_unit(bus, *name, &active_state);
- if (r < 0)
- return r;
-
- if (!arg_quiet)
- puts(unit_active_state_to_string(active_state));
-
- for (i = 0; i < nb_states; ++i)
- if (good_states[i] == active_state)
- found = true;
- }
-
- /* use the given return code for the case that we won't find
- * any unit which matches the list */
- return found ? 0 : code;
-}
-
-static int check_unit_active(int argc, char *argv[], void *userdata) {
- static const UnitActiveState states[] = {
- UNIT_ACTIVE,
- UNIT_RELOADING,
- };
-
- /* According to LSB: 3, "program is not running" */
- return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
-}
-
-static int check_unit_failed(int argc, char *argv[], void *userdata) {
- static const UnitActiveState states[] = {
- UNIT_FAILED,
- };
-
- return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
-}
-
-static int kill_unit(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- char *kill_who = NULL, **name;
- sd_bus *bus;
- int r, q;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- if (!arg_kill_who)
- arg_kill_who = "all";
-
- /* --fail was specified */
- if (streq(arg_job_mode, "fail"))
- kill_who = strjoina(arg_kill_who, "-fail");
-
- r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- STRV_FOREACH(name, names) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- q = bus_call_method(
- bus,
- bus_systemd_mgr,
- "KillUnit",
- &error,
- NULL,
- "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
- if (q < 0) {
- log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
- }
-
- return r;
-}
-
-static int clean_or_freeze_unit(int argc, char *argv[], void *userdata) {
- _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *w = NULL;
- _cleanup_strv_free_ char **names = NULL;
- int r, ret = EXIT_SUCCESS;
- char **name;
- const char *method;
- sd_bus *bus;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- if (!arg_clean_what) {
- arg_clean_what = strv_new("cache", "runtime");
- if (!arg_clean_what)
- return log_oom();
- }
-
- r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- if (!arg_no_block) {
- r = bus_wait_for_units_new(bus, &w);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate unit waiter: %m");
- }
-
- if (streq(argv[0], "clean"))
- method = "CleanUnit";
- else if (streq(argv[0], "freeze"))
- method = "FreezeUnit";
- else if (streq(argv[0], "thaw"))
- method = "ThawUnit";
- else
- assert_not_reached("Unhandled method");
-
- STRV_FOREACH(name, names) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
- if (w) {
- /* If we shall wait for the cleaning to complete, let's add a ref on the unit first */
- r = bus_call_method(bus, bus_systemd_mgr, "RefUnit", &error, NULL, "s", *name);
- if (r < 0) {
- log_error_errno(r, "Failed to add reference to unit %s: %s", *name, bus_error_message(&error, r));
- if (ret == EXIT_SUCCESS)
- ret = r;
- continue;
- }
- }
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(m, "s", *name);
- if (r < 0)
- return bus_log_create_error(r);
-
- if (streq(method, "CleanUnit")) {
- r = sd_bus_message_append_strv(m, arg_clean_what);
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- r = sd_bus_call(bus, m, 0, &error, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to %s unit %s: %s", argv[0], *name, bus_error_message(&error, r));
- if (ret == EXIT_SUCCESS) {
- ret = r;
- continue;
- }
- }
-
- if (w) {
- r = bus_wait_for_units_add_unit(w, *name, BUS_WAIT_REFFED|BUS_WAIT_FOR_MAINTENANCE_END, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to watch unit %s: %m", *name);
- }
- }
-
- r = bus_wait_for_units_run(w);
- if (r < 0)
- return log_error_errno(r, "Failed to wait for units: %m");
- if (r == BUS_WAIT_FAILURE)
- ret = EXIT_FAILURE;
-
- return ret;
-}
-
-typedef struct ExecStatusInfo {
- char *name;
-
- char *path;
- char **argv;
-
- bool ignore;
-
- usec_t start_timestamp;
- usec_t exit_timestamp;
- pid_t pid;
- int code;
- int status;
-
- ExecCommandFlags flags;
-
- LIST_FIELDS(struct ExecStatusInfo, exec);
-} ExecStatusInfo;
-
-static void exec_status_info_free(ExecStatusInfo *i) {
- assert(i);
-
- free(i->name);
- free(i->path);
- strv_free(i->argv);
- free(i);
-}
-
-static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i, bool is_ex_prop) {
- _cleanup_strv_free_ char **ex_opts = NULL;
- uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
- const char *path;
- uint32_t pid;
- int32_t code, status;
- int ignore, r;
-
- assert(m);
- assert(i);
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, is_ex_prop ? "sasasttttuii" : "sasbttttuii");
- if (r < 0)
- return bus_log_parse_error(r);
- else if (r == 0)
- return 0;
-
- r = sd_bus_message_read(m, "s", &path);
- if (r < 0)
- return bus_log_parse_error(r);
-
- i->path = strdup(path);
- if (!i->path)
- return log_oom();
-
- r = sd_bus_message_read_strv(m, &i->argv);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = is_ex_prop ? sd_bus_message_read_strv(m, &ex_opts) : sd_bus_message_read(m, "b", &ignore);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(m,
- "ttttuii",
- &start_timestamp, &start_timestamp_monotonic,
- &exit_timestamp, &exit_timestamp_monotonic,
- &pid,
- &code, &status);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (is_ex_prop) {
- r = exec_command_flags_from_strv(ex_opts, &i->flags);
- if (r < 0)
- return log_error_errno(r, "Failed to convert strv to ExecCommandFlags: %m");
-
- i->ignore = FLAGS_SET(i->flags, EXEC_COMMAND_IGNORE_FAILURE);
- } else
- i->ignore = ignore;
-
- i->start_timestamp = (usec_t) start_timestamp;
- i->exit_timestamp = (usec_t) exit_timestamp;
- i->pid = (pid_t) pid;
- i->code = code;
- i->status = status;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-}
-
-typedef struct UnitCondition {
- char *name;
- char *param;
- bool trigger;
- bool negate;
- int tristate;
-
- LIST_FIELDS(struct UnitCondition, conditions);
-} UnitCondition;
-
-static void unit_condition_free(UnitCondition *c) {
- if (!c)
- return;
-
- free(c->name);
- free(c->param);
- free(c);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
-
-typedef struct UnitStatusInfo {
- const char *id;
- const char *load_state;
- const char *active_state;
- const char *freezer_state;
- const char *sub_state;
- const char *unit_file_state;
- const char *unit_file_preset;
-
- const char *description;
- const char *following;
-
- char **documentation;
-
- const char *fragment_path;
- const char *source_path;
- const char *control_group;
-
- char **dropin_paths;
-
- char **triggered_by;
- char **triggers;
-
- const char *load_error;
- const char *result;
-
- usec_t inactive_exit_timestamp;
- usec_t inactive_exit_timestamp_monotonic;
- usec_t active_enter_timestamp;
- usec_t active_exit_timestamp;
- usec_t inactive_enter_timestamp;
-
- bool need_daemon_reload;
- bool transient;
-
- /* Service */
- pid_t main_pid;
- pid_t control_pid;
- const char *status_text;
- const char *pid_file;
- bool running:1;
- int status_errno;
-
- usec_t start_timestamp;
- usec_t exit_timestamp;
-
- int exit_code, exit_status;
-
- const char *log_namespace;
-
- usec_t condition_timestamp;
- bool condition_result;
- LIST_HEAD(UnitCondition, conditions);
-
- usec_t assert_timestamp;
- bool assert_result;
- bool failed_assert_trigger;
- bool failed_assert_negate;
- const char *failed_assert;
- const char *failed_assert_parameter;
- usec_t next_elapse_real;
- usec_t next_elapse_monotonic;
-
- /* Socket */
- unsigned n_accepted;
- unsigned n_connections;
- unsigned n_refused;
- bool accept;
-
- /* Pairs of type, path */
- char **listen;
-
- /* Device */
- const char *sysfs_path;
-
- /* Mount, Automount */
- const char *where;
-
- /* Swap */
- const char *what;
-
- /* CGroup */
- uint64_t memory_current;
- uint64_t memory_min;
- uint64_t memory_low;
- uint64_t memory_high;
- uint64_t memory_max;
- uint64_t memory_swap_max;
- uint64_t memory_limit;
- uint64_t cpu_usage_nsec;
- uint64_t tasks_current;
- uint64_t tasks_max;
- uint64_t ip_ingress_bytes;
- uint64_t ip_egress_bytes;
- uint64_t io_read_bytes;
- uint64_t io_write_bytes;
-
- uint64_t default_memory_min;
- uint64_t default_memory_low;
-
- LIST_HEAD(ExecStatusInfo, exec);
-} UnitStatusInfo;
-
-static void unit_status_info_free(UnitStatusInfo *info) {
- ExecStatusInfo *p;
- UnitCondition *c;
-
- strv_free(info->documentation);
- strv_free(info->dropin_paths);
- strv_free(info->triggered_by);
- strv_free(info->triggers);
- strv_free(info->listen);
-
- while ((c = info->conditions)) {
- LIST_REMOVE(conditions, info->conditions, c);
- unit_condition_free(c);
- }
-
- while ((p = info->exec)) {
- LIST_REMOVE(exec, info->exec, p);
- exec_status_info_free(p);
- }
-}
-
-static void format_active_state(const char *active_state, const char **active_on, const char **active_off) {
- if (streq_ptr(active_state, "failed")) {
- *active_on = ansi_highlight_red();
- *active_off = ansi_normal();
- } else if (STRPTR_IN_SET(active_state, "active", "reloading")) {
- *active_on = ansi_highlight_green();
- *active_off = ansi_normal();
- } else
- *active_on = *active_off = "";
-}
-
-static void print_status_info(
- sd_bus *bus,
- UnitStatusInfo *i,
- bool *ellipsized) {
-
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
- const char *s1, *s2, *active_on, *active_off, *on, *off, *ss, *fs;
- _cleanup_free_ char *formatted_path = NULL;
- ExecStatusInfo *p;
- usec_t timestamp;
- const char *path;
- char **t, **t2;
- int r;
-
- assert(i);
-
- /* This shows pretty information about a unit. See
- * print_property() for a low-level property printer */
-
- 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));
-
- if (i->description && !streq_ptr(i->id, i->description))
- printf(" - %s", i->description);
-
- printf("\n");
-
- if (i->following)
- printf(" Follow: unit currently follows state of %s\n", i->following);
-
- if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) {
- on = ansi_highlight_red();
- off = ansi_normal();
- } else
- on = off = "";
-
- path = i->source_path ?: i->fragment_path;
- if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0)
- path = formatted_path;
-
- if (!isempty(i->load_error))
- printf(" Loaded: %s%s%s (Reason: %s)\n",
- on, strna(i->load_state), off, i->load_error);
- else if (path && !isempty(i->unit_file_state)) {
- bool show_preset = !isempty(i->unit_file_preset) &&
- show_preset_for_state(unit_file_state_from_string(i->unit_file_state));
-
- printf(" Loaded: %s%s%s (%s; %s%s%s)\n",
- on, strna(i->load_state), off,
- path,
- i->unit_file_state,
- show_preset ? "; vendor preset: " : "",
- show_preset ? i->unit_file_preset : "");
-
- } else if (path)
- printf(" Loaded: %s%s%s (%s)\n",
- on, strna(i->load_state), off, path);
- else
- printf(" Loaded: %s%s%s\n",
- on, strna(i->load_state), off);
-
- if (i->transient)
- printf(" Transient: yes\n");
-
- if (!strv_isempty(i->dropin_paths)) {
- _cleanup_free_ char *dir = NULL;
- bool last = false;
- char ** dropin;
-
- STRV_FOREACH(dropin, i->dropin_paths) {
- _cleanup_free_ char *dropin_formatted = NULL;
- const char *df;
-
- if (!dir || last) {
- printf(dir ? " " :
- " Drop-In: ");
-
- dir = mfree(dir);
-
- dir = dirname_malloc(*dropin);
- if (!dir) {
- log_oom();
- return;
- }
-
- printf("%s\n"
- " %s", dir,
- special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
- }
-
- last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
-
- if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0)
- df = dropin_formatted;
- else
- df = *dropin;
-
- printf("%s%s", df, last ? "\n" : ", ");
- }
- }
-
- ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
- if (ss)
- printf(" Active: %s%s (%s)%s",
- active_on, strna(i->active_state), ss, active_off);
- else
- printf(" Active: %s%s%s",
- active_on, strna(i->active_state), active_off);
-
- fs = !isempty(i->freezer_state) && !streq(i->freezer_state, "running") ? i->freezer_state : NULL;
- if (fs)
- printf(" %s(%s)%s", ansi_highlight_yellow(), fs, ansi_normal());
-
- if (!isempty(i->result) && !streq(i->result, "success"))
- printf(" (Result: %s)", i->result);
-
- timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
- STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
- STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
- i->active_exit_timestamp;
-
- s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
- s2 = format_timestamp_style(since2, sizeof(since2), timestamp, arg_timestamp_style);
-
- if (s1)
- printf(" since %s; %s\n", s2, s1);
- else if (s2)
- printf(" since %s\n", s2);
- else
- printf("\n");
-
- STRV_FOREACH(t, i->triggered_by) {
- UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
-
- (void) get_state_one_unit(bus, *t, &state);
- format_active_state(unit_active_state_to_string(state), &on, &off);
-
- printf("%s %s%s%s %s\n",
- t == i->triggered_by ? "TriggeredBy:" : " ",
- on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
- *t);
- }
-
- if (endswith(i->id, ".timer")) {
- char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
- tstamp2[FORMAT_TIMESTAMP_MAX];
- const char *next_rel_time, *next_time;
- dual_timestamp nw, next = {i->next_elapse_real,
- i->next_elapse_monotonic};
- usec_t next_elapse;
-
- printf(" Trigger: ");
-
- dual_timestamp_get(&nw);
- next_elapse = calc_next_elapse(&nw, &next);
- next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
- next_time = format_timestamp_style(tstamp2, sizeof tstamp2, next_elapse, arg_timestamp_style);
-
- if (next_time && next_rel_time)
- printf("%s; %s\n", next_time, next_rel_time);
- else
- printf("n/a\n");
- }
-
- STRV_FOREACH(t, i->triggers) {
- UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
-
- (void) get_state_one_unit(bus, *t, &state);
- format_active_state(unit_active_state_to_string(state), &on, &off);
-
- printf("%s %s%s%s %s\n",
- t == i->triggers ? " Triggers:" : " ",
- on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
- *t);
- }
-
- if (!i->condition_result && i->condition_timestamp > 0) {
- UnitCondition *c;
- int n = 0;
-
- s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
- s2 = format_timestamp_style(since2, sizeof(since2), i->condition_timestamp, arg_timestamp_style);
-
- printf(" Condition: start %scondition failed%s at %s%s%s\n",
- ansi_highlight_yellow(), ansi_normal(),
- s2, s1 ? "; " : "", strempty(s1));
-
- LIST_FOREACH(conditions, c, i->conditions)
- if (c->tristate < 0)
- n++;
-
- LIST_FOREACH(conditions, c, i->conditions)
- if (c->tristate < 0)
- printf(" %s %s=%s%s%s was not met\n",
- --n ? special_glyph(SPECIAL_GLYPH_TREE_BRANCH) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
- c->name,
- c->trigger ? "|" : "",
- c->negate ? "!" : "",
- c->param);
- }
-
- if (!i->assert_result && i->assert_timestamp > 0) {
- s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
- s2 = format_timestamp_style(since2, sizeof(since2), i->assert_timestamp, arg_timestamp_style);
-
- printf(" Assert: start %sassertion failed%s at %s%s%s\n",
- ansi_highlight_red(), ansi_normal(),
- s2, s1 ? "; " : "", strempty(s1));
- if (i->failed_assert_trigger)
- printf(" none of the trigger assertions were met\n");
- else if (i->failed_assert)
- printf(" %s=%s%s was not met\n",
- i->failed_assert,
- i->failed_assert_negate ? "!" : "",
- i->failed_assert_parameter);
- }
-
- if (i->sysfs_path)
- printf(" Device: %s\n", i->sysfs_path);
- if (i->where)
- printf(" Where: %s\n", i->where);
- if (i->what)
- printf(" What: %s\n", i->what);
-
- STRV_FOREACH(t, i->documentation) {
- _cleanup_free_ char *formatted = NULL;
- const char *q;
-
- if (terminal_urlify(*t, NULL, &formatted) >= 0)
- q = formatted;
- else
- q = *t;
-
- printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q);
- }
-
- STRV_FOREACH_PAIR(t, t2, i->listen)
- printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
-
- if (i->accept) {
- printf(" Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections);
- if (i->n_refused)
- printf(" Refused: %u", i->n_refused);
- printf("\n");
- }
-
- LIST_FOREACH(exec, p, i->exec) {
- _cleanup_free_ char *argv = NULL;
- bool good;
-
- /* Only show exited processes here */
- if (p->code == 0)
- continue;
-
- /* Don't print ExecXYZEx= properties here since it will appear as a
- * duplicate of the non-Ex= variant. */
- if (endswith(p->name, "Ex"))
- continue;
-
- argv = strv_join(p->argv, " ");
- printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
-
- good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
- if (!good) {
- on = ansi_highlight_red();
- off = ansi_normal();
- } else
- on = off = "";
-
- printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
-
- if (p->code == CLD_EXITED) {
- const char *c;
-
- printf("status=%i", p->status);
-
- c = exit_status_to_string(p->status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
- if (c)
- printf("/%s", c);
-
- } else
- printf("signal=%s", signal_to_string(p->status));
-
- printf(")%s\n", off);
-
- if (i->main_pid == p->pid &&
- i->start_timestamp == p->start_timestamp &&
- i->exit_timestamp == p->start_timestamp)
- /* Let's not show this twice */
- i->main_pid = 0;
-
- if (p->pid == i->control_pid)
- i->control_pid = 0;
- }
-
- if (i->main_pid > 0 || i->control_pid > 0) {
- if (i->main_pid > 0) {
- printf(" Main PID: "PID_FMT, i->main_pid);
-
- if (i->running) {
-
- if (arg_transport == BUS_TRANSPORT_LOCAL) {
- _cleanup_free_ char *comm = NULL;
-
- (void) get_process_comm(i->main_pid, &comm);
- if (comm)
- printf(" (%s)", comm);
- }
-
- } else if (i->exit_code > 0) {
- printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
-
- if (i->exit_code == CLD_EXITED) {
- const char *c;
-
- printf("status=%i", i->exit_status);
-
- c = exit_status_to_string(i->exit_status,
- EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
- if (c)
- printf("/%s", c);
-
- } else
- printf("signal=%s", signal_to_string(i->exit_status));
- printf(")");
- }
- }
-
- if (i->control_pid > 0) {
- _cleanup_free_ char *c = NULL;
-
- if (i->main_pid > 0)
- fputs("; Control PID: ", stdout);
- else
- fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
-
- printf(PID_FMT, i->control_pid);
-
- if (arg_transport == BUS_TRANSPORT_LOCAL) {
- (void) get_process_comm(i->control_pid, &c);
- if (c)
- printf(" (%s)", c);
- }
- }
-
- printf("\n");
- }
-
- if (i->status_text)
- printf(" Status: \"%s\"\n", i->status_text);
- if (i->status_errno > 0)
- printf(" Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno));
-
- if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
- char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
-
- printf(" IP: %s in, %s out\n",
- format_bytes(buf_in, sizeof(buf_in), i->ip_ingress_bytes),
- format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes));
- }
-
- if (i->io_read_bytes != UINT64_MAX && i->io_write_bytes != UINT64_MAX) {
- char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
-
- printf(" IO: %s read, %s written\n",
- format_bytes(buf_in, sizeof(buf_in), i->io_read_bytes),
- format_bytes(buf_out, sizeof(buf_out), i->io_write_bytes));
- }
-
- if (i->tasks_current != (uint64_t) -1) {
- printf(" Tasks: %" PRIu64, i->tasks_current);
-
- if (i->tasks_max != (uint64_t) -1)
- printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
- else
- printf("\n");
- }
-
- if (i->memory_current != (uint64_t) -1) {
- char buf[FORMAT_BYTES_MAX];
-
- printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
-
- if (i->memory_min > 0 || i->memory_low > 0 ||
- i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
- i->memory_swap_max != CGROUP_LIMIT_MAX ||
- i->memory_limit != CGROUP_LIMIT_MAX) {
- const char *prefix = "";
-
- printf(" (");
- if (i->memory_min > 0) {
- printf("%smin: %s", prefix, format_bytes_cgroup_protection(buf, sizeof(buf), i->memory_min));
- prefix = " ";
- }
- if (i->memory_low > 0) {
- printf("%slow: %s", prefix, format_bytes_cgroup_protection(buf, sizeof(buf), i->memory_low));
- prefix = " ";
- }
- if (i->memory_high != CGROUP_LIMIT_MAX) {
- printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
- prefix = " ";
- }
- if (i->memory_max != CGROUP_LIMIT_MAX) {
- printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
- prefix = " ";
- }
- if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
- printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
- prefix = " ";
- }
- if (i->memory_limit != CGROUP_LIMIT_MAX) {
- printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
- prefix = " ";
- }
- printf(")");
- }
- printf("\n");
- }
-
- if (i->cpu_usage_nsec != (uint64_t) -1) {
- char buf[FORMAT_TIMESPAN_MAX];
- printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
- }
-
- if (i->control_group) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- static const char prefix[] = " ";
- unsigned c;
-
- printf(" CGroup: %s\n", i->control_group);
-
- c = columns();
- if (c > sizeof(prefix) - 1)
- c -= sizeof(prefix) - 1;
- else
- c = 0;
-
- r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
- if (r == -EBADR) {
- unsigned k = 0;
- pid_t extra[2];
-
- /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
-
- if (i->main_pid > 0)
- extra[k++] = i->main_pid;
-
- if (i->control_pid > 0)
- extra[k++] = i->control_pid;
-
- show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
- } else if (r < 0)
- log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
- i->id, bus_error_message(&error, r));
- }
-
- if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
- show_journal_by_unit(
- stdout,
- i->id,
- i->log_namespace,
- arg_output,
- 0,
- i->inactive_exit_timestamp_monotonic,
- arg_lines,
- getuid(),
- get_output_flags() | OUTPUT_BEGIN_NEWLINE,
- SD_JOURNAL_LOCAL_ONLY,
- arg_scope == UNIT_FILE_SYSTEM,
- ellipsized);
-
- if (i->need_daemon_reload)
- warn_unit_file_changed(i->id);
-}
-
-static void show_unit_help(UnitStatusInfo *i) {
- char **p;
-
- assert(i);
-
- if (!i->documentation) {
- log_info("Documentation for %s not known.", i->id);
- return;
- }
-
- STRV_FOREACH(p, i->documentation)
- if (startswith(*p, "man:"))
- show_man_page(*p + 4, false);
- else
- log_info("Can't show: %s", *p);
-}
-
-static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- UnitStatusInfo *i = userdata;
- uint32_t u;
- int r;
-
- r = sd_bus_message_read(m, "u", &u);
- if (r < 0)
- return r;
-
- i->main_pid = (pid_t) u;
- i->running = u > 0;
-
- return 0;
-}
-
-static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- const char *message, **p = userdata;
- int r;
-
- r = sd_bus_message_read(m, "(ss)", NULL, &message);
- if (r < 0)
- return r;
-
- if (!isempty(message))
- *p = message;
-
- return 0;
-}
-
-static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- const char *type, *path;
- char ***p = userdata;
- int r;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
-
- r = strv_extend(p, type);
- if (r < 0)
- return r;
-
- r = strv_extend(p, path);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- UnitStatusInfo *i = userdata;
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
- int r;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
- _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
-
- c = new(UnitCondition, 1);
- if (!c)
- return -ENOMEM;
-
- *c = (UnitCondition) {
- .name = strdup(cond),
- .param = strdup(param),
- .trigger = trigger,
- .negate = negate,
- .tristate = state,
- };
-
- if (!c->name || !c->param)
- return -ENOMEM;
-
- LIST_PREPEND(conditions, i->conditions, TAKE_PTR(c));
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- UnitStatusInfo *i = userdata;
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
- int r;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
- if (state < 0 && (!trigger || !i->failed_assert)) {
- i->failed_assert = cond;
- i->failed_assert_trigger = trigger;
- i->failed_assert_negate = negate;
- i->failed_assert_parameter = param;
- }
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- _cleanup_free_ ExecStatusInfo *info = NULL;
- ExecStatusInfo *last;
- UnitStatusInfo *i = userdata;
- bool is_ex_prop = endswith(member, "Ex");
- int r;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
- if (r < 0)
- return r;
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return -ENOMEM;
-
- LIST_FIND_TAIL(exec, i->exec, last);
-
- while ((r = exec_status_info_deserialize(m, info, is_ex_prop)) > 0) {
-
- info->name = strdup(member);
- if (!info->name)
- return -ENOMEM;
-
- LIST_INSERT_AFTER(exec, i->exec, last, info);
- last = info;
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return -ENOMEM;
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
- char bus_type;
- const char *contents;
- int r;
-
- assert(name);
- assert(m);
-
- /* This is a low-level property printer, see
- * print_status_info() for the nicer output */
-
- r = sd_bus_message_peek_type(m, &bus_type, &contents);
- if (r < 0)
- return r;
-
- switch (bus_type) {
-
- case SD_BUS_TYPE_INT32:
- if (endswith(name, "ActionExitStatus")) {
- int32_t i;
-
- r = sd_bus_message_read_basic(m, bus_type, &i);
- if (r < 0)
- return r;
-
- if (i >= 0 && i <= 255)
- bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
- else if (all)
- bus_print_property_value(name, expected_value, value, "[not set]");
-
- return 1;
- } else if (streq(name, "NUMAPolicy")) {
- int32_t i;
-
- r = sd_bus_message_read_basic(m, bus_type, &i);
- if (r < 0)
- return r;
-
- bus_print_property_valuef(name, expected_value, value, "%s", strna(mpol_to_string(i)));
-
- return 1;
- }
- break;
-
- case SD_BUS_TYPE_STRUCT:
-
- if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
- uint32_t u;
-
- r = sd_bus_message_read(m, "(uo)", &u, NULL);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (u > 0)
- bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
- else if (all)
- bus_print_property_value(name, expected_value, value, "");
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
- const char *s;
-
- r = sd_bus_message_read(m, "(so)", &s, NULL);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(s))
- bus_print_property_value(name, expected_value, value, s);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
- const char *a = NULL, *b = NULL;
-
- r = sd_bus_message_read(m, "(ss)", &a, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(a) || !isempty(b))
- bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
- else if (all)
- bus_print_property_value(name, expected_value, value, "");
-
- return 1;
-
- } else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies")) {
- _cleanup_strv_free_ char **l = NULL;
- int allow_list;
-
- r = sd_bus_message_enter_container(m, 'r', "bas");
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(m, "b", &allow_list);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_strv(m, &l);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || allow_list || !strv_isempty(l)) {
- bool first = true;
- char **i;
-
- if (!value) {
- fputs(name, stdout);
- fputc('=', stdout);
- }
-
- if (!allow_list)
- fputc('~', stdout);
-
- STRV_FOREACH(i, l) {
- if (first)
- first = false;
- else
- fputc(' ', stdout);
-
- fputs(*i, stdout);
- }
- fputc('\n', stdout);
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
- int ignore;
- const char *s;
-
- r = sd_bus_message_read(m, "(bs)", &ignore, &s);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(s))
- bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
- else if (all)
- bus_print_property_value(name, expected_value, value, "");
-
- return 1;
-
- } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
- const int32_t *status, *signal;
- size_t n_status, n_signal, i;
-
- r = sd_bus_message_enter_container(m, 'r', "aiai");
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(m, 'i', (const void **) &status, &n_status);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &n_signal);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- n_status /= sizeof(int32_t);
- n_signal /= sizeof(int32_t);
-
- if (all || n_status > 0 || n_signal > 0) {
- bool first = true;
-
- if (!value) {
- fputs(name, stdout);
- fputc('=', stdout);
- }
-
- for (i = 0; i < n_status; i++) {
- if (first)
- first = false;
- else
- fputc(' ', stdout);
-
- printf("%"PRIi32, status[i]);
- }
-
- for (i = 0; i < n_signal; i++) {
- const char *str;
-
- str = signal_to_string((int) signal[i]);
-
- if (first)
- first = false;
- else
- fputc(' ', stdout);
-
- if (str)
- fputs(str, stdout);
- else
- printf("%"PRIi32, status[i]);
- }
-
- fputc('\n', stdout);
- }
- return 1;
- }
-
- break;
-
- case SD_BUS_TYPE_ARRAY:
-
- if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
- const char *path;
- int ignore;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
-
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
- const char *type, *path;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
- const char *type, *path;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
- const char *base;
- uint64_t v, next_elapse;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
- char timespan1[FORMAT_TIMESPAN_MAX] = "n/a", timespan2[FORMAT_TIMESPAN_MAX] = "n/a";
-
- (void) format_timespan(timespan1, sizeof timespan1, v, 0);
- (void) format_timespan(timespan2, sizeof timespan2, next_elapse, 0);
-
- bus_print_property_valuef(name, expected_value, value,
- "{ %s=%s ; next_elapse=%s }", base, timespan1, timespan2);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
- const char *base, *spec;
- uint64_t next_elapse;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
- char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a";
-
- (void) format_timestamp_style(timestamp, sizeof(timestamp), next_elapse, arg_timestamp_style);
- bus_print_property_valuef(name, expected_value, value,
- "{ %s=%s ; next_elapse=%s }", base, spec, timestamp);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
- ExecStatusInfo info = {};
- bool is_ex_prop = endswith(name, "Ex");
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = exec_status_info_deserialize(m, &info, is_ex_prop)) > 0) {
- char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
- _cleanup_strv_free_ char **optv = NULL;
- _cleanup_free_ char *tt, *o = NULL;
-
- tt = strv_join(info.argv, " ");
-
- if (is_ex_prop) {
- r = exec_command_flags_to_strv(info.flags, &optv);
- if (r < 0)
- return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
-
- o = strv_join(optv, " ");
-
- bus_print_property_valuef(name, expected_value, value,
- "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
- strna(info.path),
- strna(tt),
- strna(o),
- strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
- strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
- info.pid,
- sigchld_code_to_string(info.code),
- info.status,
- info.code == CLD_EXITED ? "" : "/",
- strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
- } else
- bus_print_property_valuef(name, expected_value, value,
- "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
- strna(info.path),
- strna(tt),
- yes_no(info.ignore),
- strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
- strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
- info.pid,
- sigchld_code_to_string(info.code),
- info.status,
- info.code == CLD_EXITED ? "" : "/",
- strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
-
- free(info.path);
- strv_free(info.argv);
- zero(info);
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
- const char *path, *rwm;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
- STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
- const char *path;
- uint64_t weight;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
- (cgroup_io_limit_type_from_string(name) >= 0 ||
- STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
- const char *path;
- uint64_t bandwidth;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
- streq(name, "IODeviceLatencyTargetUSec")) {
- char ts[FORMAT_TIMESPAN_MAX];
- const char *path;
- uint64_t target;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
- bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
- format_timespan(ts, sizeof(ts), target, 1));
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 1;
-
- } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "StandardInputData", "RootHashSignature")) {
- _cleanup_free_ char *h = NULL;
- const void *p;
- size_t sz;
- ssize_t n;
-
- r = sd_bus_message_read_array(m, 'y', &p, &sz);
- if (r < 0)
- return bus_log_parse_error(r);
-
- n = base64mem(p, sz, &h);
- if (n < 0)
- return log_oom();
-
- bus_print_property_value(name, expected_value, value, h);
-
- return 1;
-
- } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
- _cleanup_free_ char *addresses = NULL;
-
- r = sd_bus_message_enter_container(m, 'a', "(iayu)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- for (;;) {
- _cleanup_free_ char *str = NULL;
- uint32_t prefixlen;
- int32_t family;
- const void *ap;
- size_t an;
-
- r = sd_bus_message_enter_container(m, 'r', "iayu");
- if (r < 0)
- return bus_log_parse_error(r);
- if (r == 0)
- break;
-
- r = sd_bus_message_read(m, "i", &family);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(m, 'y', &ap, &an);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(m, "u", &prefixlen);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!IN_SET(family, AF_INET, AF_INET6))
- continue;
-
- if (an != FAMILY_ADDRESS_SIZE(family))
- continue;
-
- if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
- continue;
-
- if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0)
- continue;
-
- if (!strextend_with_separator(&addresses, " ", str, NULL))
- return log_oom();
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(addresses))
- bus_print_property_value(name, expected_value, value, strempty(addresses));
-
- return 1;
-
- } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
- _cleanup_free_ char *paths = NULL;
- const char *source, *dest;
- int ignore_enoent;
- uint64_t rbind;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
- _cleanup_free_ char *str = NULL;
-
- if (isempty(source))
- continue;
-
- if (asprintf(&str, "%s%s%s%s%s",
- ignore_enoent ? "-" : "",
- source,
- isempty(dest) ? "" : ":",
- strempty(dest),
- rbind == MS_REC ? ":rbind" : "") < 0)
- return log_oom();
-
- if (!strextend_with_separator(&paths, " ", str, NULL))
- return log_oom();
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(paths))
- bus_print_property_value(name, expected_value, value, strempty(paths));
-
- return 1;
-
- } else if (streq(name, "TemporaryFileSystem")) {
- _cleanup_free_ char *paths = NULL;
- const char *target, *option;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
- _cleanup_free_ char *str = NULL;
-
- if (isempty(target))
- continue;
-
- if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
- return log_oom();
-
- if (!strextend_with_separator(&paths, " ", str, NULL))
- return log_oom();
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(paths))
- bus_print_property_value(name, expected_value, value, strempty(paths));
-
- return 1;
-
- } else if (streq(name, "LogExtraFields")) {
- _cleanup_free_ char *fields = NULL;
- const void *p;
- size_t sz;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
- _cleanup_free_ char *str = NULL;
- const char *eq;
-
- if (memchr(p, 0, sz))
- continue;
-
- eq = memchr(p, '=', sz);
- if (!eq)
- continue;
-
- if (!journal_field_valid(p, eq - (const char*) p, false))
- continue;
-
- str = malloc(sz + 1);
- if (!str)
- return log_oom();
-
- memcpy(str, p, sz);
- str[sz] = '\0';
-
- if (!utf8_is_valid(str))
- continue;
-
- if (!strextend_with_separator(&fields, " ", str, NULL))
- return log_oom();
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(fields))
- bus_print_property_value(name, expected_value, value, strempty(fields));
-
- return 1;
- } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) {
- _cleanup_free_ char *affinity = NULL;
- _cleanup_(cpu_set_reset) CPUSet set = {};
- const void *a;
- size_t n;
-
- r = sd_bus_message_read_array(m, 'y', &a, &n);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = cpu_set_from_dbus(a, n, &set);
- if (r < 0)
- return log_error_errno(r, "Failed to deserialize %s: %m", name);
-
- affinity = cpu_set_to_range_string(&set);
- if (!affinity)
- return log_oom();
-
- bus_print_property_value(name, expected_value, value, affinity);
-
- return 1;
- } else if (streq(name, "MountImages")) {
- _cleanup_free_ char *paths = NULL;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssba(ss))");
- if (r < 0)
- return bus_log_parse_error(r);
-
- for (;;) {
- _cleanup_free_ char *str = NULL;
- const char *source, *destination, *partition, *mount_options;
- int ignore_enoent;
-
- r = sd_bus_message_enter_container(m, 'r', "ssba(ss)");
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(m, "ssb", &source, &destination, &ignore_enoent);
- if (r <= 0)
- break;
-
- str = strjoin(ignore_enoent ? "-" : "",
- source,
- ":",
- destination);
- if (!str)
- return log_oom();
-
- r = sd_bus_message_enter_container(m, 'a', "(ss)");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0) {
- _cleanup_free_ char *previous = NULL;
-
- previous = TAKE_PTR(str);
- str = strjoin(strempty(previous), previous ? ":" : "", partition, ":", mount_options);
- if (!str)
- return log_oom();
- }
- if (r < 0)
- return r;
-
- if (!strextend_with_separator(&paths, " ", str, NULL))
- return log_oom();
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (all || !isempty(paths))
- bus_print_property_value(name, expected_value, value, strempty(paths));
-
- return 1;
-
- }
-
- break;
- }
-
- return 0;
-}
-
-typedef enum SystemctlShowMode{
- SYSTEMCTL_SHOW_PROPERTIES,
- SYSTEMCTL_SHOW_STATUS,
- SYSTEMCTL_SHOW_HELP,
- _SYSTEMCTL_SHOW_MODE_MAX,
- _SYSTEMCTL_SHOW_MODE_INVALID = -1,
-} SystemctlShowMode;
-
-static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = {
- [SYSTEMCTL_SHOW_PROPERTIES] = "show",
- [SYSTEMCTL_SHOW_STATUS] = "status",
- [SYSTEMCTL_SHOW_HELP] = "help",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
-
-static int show_one(
- sd_bus *bus,
- const char *path,
- const char *unit,
- SystemctlShowMode show_mode,
- bool *new_line,
- bool *ellipsized) {
-
- static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
- { "FreezerState", "s", NULL, offsetof(UnitStatusInfo, freezer_state) },
- { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
- {}
- }, status_map[] = {
- { "Id", "s", NULL, offsetof(UnitStatusInfo, id) },
- { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
- { "FreezerState", "s", NULL, offsetof(UnitStatusInfo, freezer_state) },
- { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) },
- { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
- { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) },
- { "Description", "s", NULL, offsetof(UnitStatusInfo, description) },
- { "Following", "s", NULL, offsetof(UnitStatusInfo, following) },
- { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
- { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) },
- { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) },
- { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) },
- { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) },
- { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) },
- { "Result", "s", NULL, offsetof(UnitStatusInfo, result) },
- { "TriggeredBy", "as", NULL, offsetof(UnitStatusInfo, triggered_by) },
- { "Triggers", "as", NULL, offsetof(UnitStatusInfo, triggers) },
- { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) },
- { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
- { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) },
- { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) },
- { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) },
- { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) },
- { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) },
- { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) },
- { "MainPID", "u", map_main_pid, 0 },
- { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) },
- { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) },
- { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) },
- { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) },
- { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) },
- { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) },
- { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) },
- { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) },
- { "LogNamespace", "s", NULL, offsetof(UnitStatusInfo, log_namespace) },
- { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) },
- { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) },
- { "Conditions", "a(sbbsi)", map_conditions, 0 },
- { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) },
- { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) },
- { "Asserts", "a(sbbsi)", map_asserts, 0 },
- { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) },
- { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) },
- { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) },
- { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) },
- { "NRefused", "u", NULL, offsetof(UnitStatusInfo, n_refused) },
- { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) },
- { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) },
- { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) },
- { "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
- { "What", "s", NULL, offsetof(UnitStatusInfo, what) },
- { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
- { "DefaultMemoryMin", "t", NULL, offsetof(UnitStatusInfo, default_memory_min) },
- { "DefaultMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_memory_low) },
- { "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) },
- { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
- { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },
- { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) },
- { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) },
- { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) },
- { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) },
- { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) },
- { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
- { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
- { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
- { "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) },
- { "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) },
- { "ExecCondition", "a(sasbttttuii)", map_exec, 0 },
- { "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStartPreEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecStart", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStartEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStartPostEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecReload", "a(sasbttttuii)", map_exec, 0 },
- { "ExecReloadEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStop", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStopEx", "a(sasasttttuii)", map_exec, 0 },
- { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 },
- { "ExecStopPostEx", "a(sasasttttuii)", map_exec, 0 },
- {}
- };
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_set_free_ Set *found_properties = NULL;
- _cleanup_(unit_status_info_free) UnitStatusInfo info = {
- .memory_current = (uint64_t) -1,
- .memory_high = CGROUP_LIMIT_MAX,
- .memory_max = CGROUP_LIMIT_MAX,
- .memory_swap_max = CGROUP_LIMIT_MAX,
- .memory_limit = (uint64_t) -1,
- .cpu_usage_nsec = (uint64_t) -1,
- .tasks_current = (uint64_t) -1,
- .tasks_max = (uint64_t) -1,
- .ip_ingress_bytes = (uint64_t) -1,
- .ip_egress_bytes = (uint64_t) -1,
- .io_read_bytes = UINT64_MAX,
- .io_write_bytes = UINT64_MAX,
- };
- char **pp;
- int r;
-
- assert(path);
- assert(new_line);
-
- log_debug("Showing one %s", path);
-
- r = bus_map_all_properties(
- bus,
- "org.freedesktop.systemd1",
- path,
- show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
- BUS_MAP_BOOLEAN_AS_BOOL,
- &error,
- &reply,
- &info);
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
- log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG,
- "Unit %s could not be found.", unit);
-
- if (show_mode == SYSTEMCTL_SHOW_STATUS)
- return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
- else if (show_mode == SYSTEMCTL_SHOW_HELP)
- return -ENOENT;
- }
-
- if (*new_line)
- printf("\n");
-
- *new_line = true;
-
- if (show_mode == SYSTEMCTL_SHOW_STATUS) {
- print_status_info(bus, &info, ellipsized);
-
- if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
- return EXIT_PROGRAM_NOT_RUNNING;
-
- return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
-
- } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
- show_unit_help(&info);
- return 0;
- }
-
- r = sd_bus_message_rewind(reply, true);
- if (r < 0)
- return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
-
- r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
- if (r < 0)
- return bus_log_parse_error(r);
-
- STRV_FOREACH(pp, arg_properties)
- if (!set_contains(found_properties, *pp))
- log_debug("Property %s does not exist.", *pp);
-
- return 0;
-}
-
-static int get_unit_dbus_path_by_pid(
- sd_bus *bus,
- uint32_t pid,
- char **unit) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- char *u;
- int r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", pid);
- if (r < 0)
- return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "o", &u);
- if (r < 0)
- return bus_log_parse_error(r);
-
- u = strdup(u);
- if (!u)
- return log_oom();
-
- *unit = u;
- return 0;
-}
-
-static int show_all(
- sd_bus *bus,
- bool *new_line,
- bool *ellipsized) {
-
- _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;
-
- r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- c = (unsigned) r;
-
- typesafe_qsort(unit_infos, c, compare_unit_info);
-
- for (u = unit_infos; u < unit_infos + c; u++) {
- _cleanup_free_ char *p = NULL;
-
- p = unit_dbus_path_from_name(u->id);
- if (!p)
- return log_oom();
-
- r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
- if (r < 0)
- return r;
- else if (r > 0 && ret == 0)
- ret = r;
- }
-
- return ret;
-}
-
-static int show_system_status(sd_bus *bus) {
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(machine_info_clear) struct machine_info mi = {};
- _cleanup_free_ char *hn = NULL;
- const char *on, *off;
- int r;
-
- hn = gethostname_malloc();
- if (!hn)
- return log_oom();
-
- r = bus_map_all_properties(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- machine_info_property_map,
- BUS_MAP_STRDUP,
- &error,
- NULL,
- &mi);
- if (r < 0)
- return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
-
- if (streq_ptr(mi.state, "degraded")) {
- on = ansi_highlight_red();
- off = ansi_normal();
- } else if (streq_ptr(mi.state, "running")) {
- on = ansi_highlight_green();
- off = ansi_normal();
- } else {
- on = ansi_highlight_yellow();
- off = ansi_normal();
- }
-
- printf("%s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
-
- printf(" State: %s%s%s\n",
- on, strna(mi.state), off);
-
- printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
- printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
-
- printf(" Since: %s; %s\n",
- format_timestamp_style(since2, sizeof(since2), mi.timestamp, arg_timestamp_style),
- format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
-
- printf(" CGroup: %s\n", mi.control_group ?: "/");
- if (IN_SET(arg_transport,
- BUS_TRANSPORT_LOCAL,
- BUS_TRANSPORT_MACHINE)) {
- static const char prefix[] = " ";
- unsigned c;
-
- c = columns();
- if (c > sizeof(prefix) - 1)
- c -= sizeof(prefix) - 1;
- else
- c = 0;
-
- show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
- }
-
- return 0;
-}
-
-static int show(int argc, char *argv[], void *userdata) {
- bool new_line = false, ellipsized = false;
- SystemctlShowMode show_mode;
- int r, ret = 0;
- sd_bus *bus;
-
- assert(argv);
-
- show_mode = systemctl_show_mode_from_string(argv[0]);
- if (show_mode < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid argument.");
-
- if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "'help' command expects one or more unit names.\n"
- "(Alternatively, help for systemctl itself may be shown with --help)");
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- /* If no argument is specified inspect the manager itself */
- if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
- return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
-
- if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
-
- show_system_status(bus);
- new_line = true;
-
- if (arg_all)
- ret = show_all(bus, &new_line, &ellipsized);
- } else {
- _cleanup_free_ char **patterns = NULL;
- char **name;
-
- STRV_FOREACH(name, strv_skip(argv, 1)) {
- _cleanup_free_ char *path = NULL, *unit = NULL;
- uint32_t id;
-
- if (safe_atou32(*name, &id) < 0) {
- if (strv_push(&patterns, *name) < 0)
- return log_oom();
-
- continue;
- } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
- /* Interpret as job id */
- if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
- return log_oom();
-
- } else {
- /* Interpret as PID */
- r = get_unit_dbus_path_by_pid(bus, id, &path);
- if (r < 0) {
- ret = r;
- continue;
- }
-
- r = unit_name_from_dbus_path(path, &unit);
- if (r < 0)
- return log_oom();
- }
-
- r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
- if (r < 0)
- return r;
- else if (r > 0 && ret == 0)
- ret = r;
- }
-
- if (!strv_isempty(patterns)) {
- _cleanup_strv_free_ char **names = NULL;
-
- r = expand_names(bus, patterns, NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- r = maybe_extend_with_unit_dependencies(bus, &names);
- if (r < 0)
- return r;
-
- STRV_FOREACH(name, names) {
- _cleanup_free_ char *path;
-
- path = unit_dbus_path_from_name(*name);
- if (!path)
- return log_oom();
-
- r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
- if (r < 0)
- return r;
- if (r > 0 && ret == 0)
- ret = r;
- }
- }
- }
-
- if (ellipsized && !arg_quiet)
- printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
-
- return ret;
-}
-
-static int cat(int argc, char *argv[], void *userdata) {
- _cleanup_(lookup_paths_free) LookupPaths lp = {};
- _cleanup_strv_free_ char **names = NULL;
- char **name;
- sd_bus *bus;
- bool first = true;
- int r, rc = 0;
-
- /* Include all units by default — i.e. continue as if the --all
- * option was used */
- if (strv_isempty(arg_states))
- arg_all = true;
-
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot remotely cat units.");
-
- r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
- if (r < 0)
- return log_error_errno(r, "Failed to determine unit paths: %m");
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- r = maybe_extend_with_unit_dependencies(bus, &names);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- STRV_FOREACH(name, names) {
- _cleanup_free_ char *fragment_path = NULL;
- _cleanup_strv_free_ char **dropin_paths = NULL;
-
- r = unit_find_paths(bus, *name, &lp, false, &fragment_path, &dropin_paths);
- if (r == -ERFKILL) {
- printf("%s# Unit %s is masked%s.\n",
- ansi_highlight_magenta(),
- *name,
- ansi_normal());
- continue;
- }
- if (r == -EKEYREJECTED) {
- printf("%s# Unit %s could not be loaded.%s\n",
- ansi_highlight_magenta(),
- *name,
- ansi_normal());
- continue;
- }
- if (r < 0)
- return r;
- if (r == 0) {
- /* Skip units which have no on-disk counterpart, but
- * propagate the error to the user */
- rc = -ENOENT;
- continue;
- }
-
- if (first)
- first = false;
- else
- puts("");
-
- if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
- fprintf(stderr,
- "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
- "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
- "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
- "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
- ansi_highlight_red(),
- *name,
- ansi_highlight_red(),
- ansi_highlight_red(),
- ansi_highlight_red(),
- arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
- ansi_normal());
-
- r = cat_files(fragment_path, dropin_paths, 0);
- if (r < 0)
- return r;
- }
-
- return rc;
-}
-
-static int set_property(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *n = NULL;
- UnitType t;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetUnitProperties");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- t = unit_name_to_type(n);
- if (t < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit type: %s", n);
-
- r = sd_bus_message_append(m, "sb", n, arg_runtime);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = bus_append_unit_property_assignment_many(m, t, strv_skip(argv, 2));
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_call(bus, m, 0, &error, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
-
- return 0;
-}
-
-static int daemon_reload(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- const char *method;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- switch (arg_action) {
-
- case ACTION_RELOAD:
- method = "Reload";
- break;
-
- case ACTION_REEXEC:
- method = "Reexecute";
- break;
-
- case ACTION_SYSTEMCTL:
- method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
- /* "daemon-reload" */ "Reload";
- break;
-
- default:
- assert_not_reached("Unexpected action");
- }
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
- if (r < 0)
- return bus_log_create_error(r);
-
- /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
- * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
- * their timeout, and for everything else there's the same time budget in place. */
-
- r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
-
- /* On reexecution, we expect a disconnect, not a reply */
- if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
- r = 0;
-
- if (r < 0 && arg_action == ACTION_SYSTEMCTL)
- return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
-
- /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
- * old ways of doing things, hence don't log any error in that case here. */
-
- return r < 0 ? r : 0;
-}
-
-static int trivial_method(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *method;
- sd_bus *bus;
- int r;
-
- if (arg_dry_run)
- return 0;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- method =
- streq(argv[0], "clear-jobs") ||
- streq(argv[0], "cancel") ? "ClearJobs" :
- streq(argv[0], "reset-failed") ? "ResetFailed" :
- streq(argv[0], "halt") ? "Halt" :
- streq(argv[0], "reboot") ? "Reboot" :
- streq(argv[0], "kexec") ? "KExec" :
- streq(argv[0], "exit") ? "Exit" :
- /* poweroff */ "PowerOff";
-
- r = bus_call_method(bus, bus_systemd_mgr, method, &error, NULL, NULL);
- if (r < 0 && arg_action == ACTION_SYSTEMCTL)
- return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
-
- /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
- * old ways of doing things, hence don't log any error in that case here. */
-
- return r < 0 ? r : 0;
-}
-
-static int reset_failed(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- sd_bus *bus;
- char **name;
- int r, q;
-
- if (argc <= 1)
- return trivial_method(argc, argv, userdata);
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- STRV_FOREACH(name, names) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- q = bus_call_method(bus, bus_systemd_mgr, "ResetFailedUnit", &error, NULL, "s", *name);
- if (q < 0) {
- log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
- }
-
- return r;
-}
-
-static int print_variable(const char *s) {
- const char *sep;
- _cleanup_free_ char *esc = NULL;
-
- sep = strchr(s, '=');
- if (!sep)
- return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "Invalid environment block");
-
- esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
- if (!esc)
- return log_oom();
-
- printf("%.*s=%s\n", (int)(sep-s), s, esc);
- return 0;
-}
-
-static int show_environment(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *text;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- (void) pager_open(arg_pager_flags);
-
- r = bus_get_property(bus, bus_systemd_mgr, "Environment", &error, &reply, "as");
- if (r < 0)
- return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
- r = print_variable(text);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-}
-
-static int switch_root(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *cmdline_init = NULL;
- const char *root, *init;
- sd_bus *bus;
- int r;
-
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch root remotely.");
-
- if (argc < 2 || argc > 3)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
-
- root = argv[1];
-
- if (argc >= 3)
- init = argv[2];
- else {
- r = proc_cmdline_get_key("init", 0, &cmdline_init);
- if (r < 0)
- log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
-
- init = cmdline_init;
- }
-
- init = empty_to_null(init);
- if (init) {
- const char *root_systemd_path = NULL, *root_init_path = NULL;
-
- root_systemd_path = prefix_roota(root, "/" SYSTEMD_BINARY_PATH);
- root_init_path = prefix_roota(root, init);
-
- /* If the passed init is actually the same as the
- * systemd binary, then let's suppress it. */
- if (files_same(root_init_path, root_systemd_path, 0) > 0)
- init = NULL;
- }
-
- /* Instruct PID1 to exclude us from its killing spree applied during the transition. Otherwise we
- * would exit with a failure status even though the switch to the new root has succeed. */
- assert(saved_argv);
- assert(saved_argv[0]);
- saved_argv[0][0] = '@';
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- /* If we are slow to exit after the root switch, the new systemd instance
- * will send us a signal to terminate. Just ignore it and exit normally.
- * This way the unit does not end up as failed.
- */
- r = ignore_signals(SIGTERM, -1);
- if (r < 0)
- log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
-
- log_debug("Switching root - root: %s; init: %s", root, strna(init));
-
- r = bus_call_method(bus, bus_systemd_mgr, "SwitchRoot", &error, NULL, "ss", root, init);
- if (r < 0) {
- (void) default_signals(SIGTERM, -1);
-
- return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
- }
-
- return 0;
-}
-
-static void give_log_control1_hint(const char *name) {
- _cleanup_free_ char *link = NULL;
-
- if (arg_quiet)
- return;
-
- (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link);
-
- log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n"
- " See the %s for details.", link ?: "org.freedesktop.LogControl1(5) man page");
-}
-
-static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) {
- assert(bus);
- assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target"));
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- bool level = endswith(verb, "log-level");
- int 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 = bus_set_property(bus, bloc,
- level ? "LogLevel" : "LogTarget",
- &error, "s", value);
- if (r >= 0)
- return 0;
-
- log_error_errno(r, "Failed to set log %s of %s to %s: %s",
- level ? "level" : "target",
- bloc->destination, value, bus_error_message(&error, r));
- } else {
- _cleanup_free_ char *t = NULL;
-
- r = bus_get_property_string(bus, bloc,
- level ? "LogLevel" : "LogTarget",
- &error, &t);
- if (r >= 0) {
- puts(t);
- return 0;
- }
-
- log_error_errno(r, "Failed to get log %s of %s: %s",
- level ? "level" : "target",
- bloc->destination, bus_error_message(&error, r));
- }
-
- if (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD,
- SD_BUS_ERROR_UNKNOWN_OBJECT,
- SD_BUS_ERROR_UNKNOWN_INTERFACE,
- SD_BUS_ERROR_UNKNOWN_PROPERTY))
- give_log_control1_hint(bloc->destination);
- return r;
-}
-
-static int log_setting(int argc, char *argv[], void *userdata) {
- sd_bus *bus;
- int r;
-
- assert(argc >= 1 && argc <= 2);
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]);
-}
-
-static int service_name_to_dbus(sd_bus *bus, const char *name, char **ret_dbus_name) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *bus_name = NULL;
- int r;
-
- /* First, look for the BusName= property */
- _cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name);
- if (!dbus_path)
- return log_oom();
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- dbus_path,
- "org.freedesktop.systemd1.Service",
- "BusName",
- &error,
- &bus_name);
- if (r < 0)
- return log_error_errno(r, "Failed to obtain BusName= property of %s: %s",
- name, bus_error_message(&error, r));
-
- if (isempty(bus_name)) {
- log_error("Unit %s doesn't declare BusName=.", name);
- give_log_control1_hint(name);
- return -ENOLINK;
- }
-
- *ret_dbus_name = TAKE_PTR(bus_name);
- return 0;
-}
-
-static int service_log_setting(int argc, char *argv[], void *userdata) {
- sd_bus *bus;
- _cleanup_free_ char *unit = NULL, *dbus_name = NULL;
- int r;
-
- assert(argc >= 2 && argc <= 3);
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = unit_name_mangle_with_suffix(argv[1], argv[0],
- arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
- ".service", &unit);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- r = service_name_to_dbus(bus, unit, &dbus_name);
- if (r < 0)
- return r;
-
- const BusLocator bloc = {
- .destination = dbus_name,
- .path = "/org/freedesktop/LogControl1",
- .interface = "org.freedesktop.LogControl1",
- };
-
- return log_setting_internal(bus, &bloc, argv[0], argv[2]);
-}
-
-static int service_watchdogs(int argc, char *argv[], void *userdata) {
- sd_bus *bus;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int b, r;
-
- assert(argv);
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- if (argc == 1) {
- /* get ServiceWatchdogs */
- r = bus_get_property_trivial(bus, bus_systemd_mgr, "ServiceWatchdogs", &error, 'b', &b);
- if (r < 0)
- return log_error_errno(r, "Failed to get service-watchdog state: %s", bus_error_message(&error, r));
-
- printf("%s\n", yes_no(!!b));
-
- } else {
- /* set ServiceWatchdogs */
- assert(argc == 2);
-
- b = parse_boolean(argv[1]);
- if (b < 0)
- return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
-
- r = bus_set_property(bus, bus_systemd_mgr, "ServiceWatchdogs", &error, "b", b);
- if (r < 0)
- return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
- }
-
- return 0;
-}
-
-static int set_environment(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- const char *method;
- sd_bus *bus;
- int r;
-
- assert(argc > 1);
- assert(argv);
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- method = streq(argv[0], "set-environment")
- ? "SetEnvironment"
- : "UnsetEnvironment";
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_call(bus, m, 0, &error, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-static int import_environment(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetEnvironment");
- if (r < 0)
- return bus_log_create_error(r);
-
- if (argc < 2)
- r = sd_bus_message_append_strv(m, environ);
- else {
- char **a, **b;
-
- r = sd_bus_message_open_container(m, 'a', "s");
- if (r < 0)
- return bus_log_create_error(r);
-
- STRV_FOREACH(a, strv_skip(argv, 1)) {
-
- if (!env_name_is_valid(*a))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid environment variable name: %s", *a);
-
- STRV_FOREACH(b, environ) {
- const char *eq;
-
- eq = startswith(*b, *a);
- if (eq && *eq == '=') {
-
- r = sd_bus_message_append(m, "s", *b);
- if (r < 0)
- return bus_log_create_error(r);
-
- break;
- }
- }
- }
-
- r = sd_bus_message_close_container(m);
- }
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_call(bus, m, 0, &error, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-static int enable_sysv_units(const char *verb, char **args) {
- int r = 0;
-
-#if HAVE_SYSV_COMPAT
- _cleanup_(lookup_paths_free) LookupPaths paths = {};
- unsigned f = 0;
-
- /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return 0;
-
- if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
- return 0;
-
- if (!STR_IN_SET(verb,
- "enable",
- "disable",
- "is-enabled"))
- return 0;
-
- r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
- if (r < 0)
- return r;
-
- r = 0;
- while (args[f]) {
-
- const char *argv[] = {
- ROOTLIBEXECDIR "/systemd-sysv-install",
- NULL, /* --root= */
- NULL, /* verb */
- NULL, /* service */
- NULL,
- };
-
- _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL;
- bool found_native = false, found_sysv;
- const char *name;
- unsigned c = 1;
- pid_t pid;
- int j;
-
- name = args[f++];
-
- if (!endswith(name, ".service"))
- continue;
-
- if (path_is_absolute(name))
- continue;
-
- j = unit_file_exists(arg_scope, &paths, name);
- if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
- return log_error_errno(j, "Failed to look up unit file state: %m");
- found_native = j != 0;
-
- /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
- * prefer the native unit */
- if (found_native && streq(verb, "is-enabled"))
- continue;
-
- p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
- if (!p)
- return log_oom();
-
- p[strlen(p) - STRLEN(".service")] = 0;
- found_sysv = access(p, F_OK) >= 0;
- if (!found_sysv)
- continue;
-
- if (!arg_quiet) {
- if (found_native)
- log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
- else
- log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
- }
-
- if (!isempty(arg_root)) {
- q = strjoin("--root=", arg_root);
- if (!q)
- return log_oom();
-
- argv[c++] = q;
- }
-
- /* Let's copy the verb, since it's still pointing directly into the original argv[] array we
- * got passed, but safe_fork() is likely going to rewrite that for the new child */
- v = strdup(verb);
- if (!v)
- return log_oom();
-
- argv[c++] = v;
- argv[c++] = basename(p);
- argv[c] = NULL;
-
- l = strv_join((char**)argv, " ");
- if (!l)
- return log_oom();
-
- if (!arg_quiet)
- log_info("Executing: %s", l);
-
- j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
- if (j < 0)
- return j;
- if (j == 0) {
- /* Child */
- execv(argv[0], (char**) argv);
- log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
- _exit(EXIT_FAILURE);
- }
-
- j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
- if (j < 0)
- return j;
- if (streq(verb, "is-enabled")) {
- if (j == EXIT_SUCCESS) {
- if (!arg_quiet)
- puts("enabled");
- r = 1;
- } else {
- if (!arg_quiet)
- puts("disabled");
- }
-
- } else if (j != EXIT_SUCCESS)
- return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
-
- if (found_native)
- continue;
-
- /* Remove this entry, so that we don't try enabling it as native unit */
- assert(f > 0);
- f--;
- assert(args[f] == name);
- strv_remove(args + f, name);
- }
-
-#endif
- return r;
-}
-
-static int mangle_names(const char *operation, char **original_names, char ***mangled_names) {
- char **i, **l, **name;
- int r;
-
- l = i = new(char*, strv_length(original_names) + 1);
- if (!l)
- return log_oom();
-
- STRV_FOREACH(name, original_names) {
-
- /* When enabling units qualified path names are OK,
- * too, hence allow them explicitly. */
-
- if (is_path(*name)) {
- *i = strdup(*name);
- if (!*i) {
- strv_free(l);
- return log_oom();
- }
- } else {
- r = unit_name_mangle_with_suffix(*name, operation,
- arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
- ".service", i);
- if (r < 0) {
- *i = NULL;
- strv_free(l);
- return log_error_errno(r, "Failed to mangle unit name: %m");
- }
- }
-
- i++;
- }
-
- *i = NULL;
- *mangled_names = l;
-
- return 0;
-}
-
-static int normalize_filenames(char **names) {
- char **u;
- int r;
-
- STRV_FOREACH(u, names)
- if (!path_is_absolute(*u)) {
- char* normalized_path;
-
- if (!isempty(arg_root))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Non-absolute paths are not allowed when --root is used: %s",
- *u);
-
- if (!strchr(*u,'/'))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Link argument does contain at least one directory separator: %s",
- *u);
-
- r = path_make_absolute_cwd(*u, &normalized_path);
- if (r < 0)
- return r;
-
- free_and_replace(*u, normalized_path);
- }
-
- return 0;
-}
-
-static int normalize_names(char **names, bool warn_if_path) {
- char **u;
- bool was_path = false;
-
- STRV_FOREACH(u, names) {
- int r;
-
- if (!is_path(*u))
- continue;
-
- r = free_and_strdup(u, basename(*u));
- if (r < 0)
- return log_error_errno(r, "Failed to normalize unit file path: %m");
-
- was_path = true;
- }
-
- if (warn_if_path && was_path)
- log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
-
- return 0;
-}
-
-static int unit_exists(LookupPaths *lp, const char *unit) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_free_ char *path = NULL;
- static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)},
- {},
- };
- UnitStatusInfo info = {};
- sd_bus *bus;
- int r;
-
- if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
- return unit_find_template_path(unit, lp, NULL, NULL);
-
- path = unit_dbus_path_from_name(unit);
- if (!path)
- return log_oom();
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, 0, &error, &m, &info);
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
-}
-
-static int enable_unit(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- const char *verb = argv[0];
- UnitFileChange *changes = NULL;
- size_t n_changes = 0;
- int carries_install_info = -1;
- bool ignore_carries_install_info = arg_quiet;
- int r;
-
- if (!argv[1])
- return 0;
-
- r = mangle_names("to enable", strv_skip(argv, 1), &names);
- if (r < 0)
- return r;
-
- r = enable_sysv_units(verb, names);
- if (r < 0)
- return r;
-
- /* If the operation was fully executed by the SysV compat, let's finish early */
- if (strv_isempty(names)) {
- if (arg_no_reload || install_client_side())
- return 0;
- return daemon_reload(argc, argv, userdata);
- }
-
- if (streq(verb, "disable")) {
- r = normalize_names(names, true);
- if (r < 0)
- return r;
- }
-
- if (streq(verb, "link")) {
- r = normalize_filenames(names);
- if (r < 0)
- return r;
- }
-
- if (install_client_side()) {
- UnitFileFlags flags;
-
- flags = args_to_flags();
- if (streq(verb, "enable")) {
- r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(verb, "disable"))
- r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
- else if (streq(verb, "reenable")) {
- r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(verb, "link"))
- r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
- else if (streq(verb, "preset")) {
- r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
- } else if (streq(verb, "mask"))
- r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
- else if (streq(verb, "unmask"))
- r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
- else if (streq(verb, "revert"))
- r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
- else
- assert_not_reached("Unknown verb");
-
- unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
- if (r < 0)
- goto finish;
- r = 0;
- } else {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- bool expect_carries_install_info = false;
- bool send_runtime = true, send_force = true, send_preset_mode = false;
- const char *method;
- sd_bus *bus;
-
- if (STR_IN_SET(verb, "mask", "unmask")) {
- char **name;
- _cleanup_(lookup_paths_free) LookupPaths lp = {};
-
- r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
- if (r < 0)
- return r;
-
- STRV_FOREACH(name, names) {
- r = unit_exists(&lp, *name);
- if (r < 0)
- return r;
- if (r == 0)
- log_notice("Unit %s does not exist, proceeding anyway.", *name);
- }
- }
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- if (streq(verb, "enable")) {
- method = "EnableUnitFiles";
- expect_carries_install_info = true;
- } else if (streq(verb, "disable")) {
- method = "DisableUnitFiles";
- send_force = false;
- } else if (streq(verb, "reenable")) {
- method = "ReenableUnitFiles";
- expect_carries_install_info = true;
- } else if (streq(verb, "link"))
- method = "LinkUnitFiles";
- else if (streq(verb, "preset")) {
-
- if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
- method = "PresetUnitFilesWithMode";
- send_preset_mode = true;
- } else
- method = "PresetUnitFiles";
-
- expect_carries_install_info = true;
- ignore_carries_install_info = true;
- } else if (streq(verb, "mask"))
- method = "MaskUnitFiles";
- else if (streq(verb, "unmask")) {
- method = "UnmaskUnitFiles";
- send_force = false;
- } else if (streq(verb, "revert")) {
- method = "RevertUnitFiles";
- send_runtime = send_force = false;
- } else
- assert_not_reached("Unknown verb");
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, names);
- if (r < 0)
- return bus_log_create_error(r);
-
- if (send_preset_mode) {
- r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- if (send_runtime) {
- r = sd_bus_message_append(m, "b", arg_runtime);
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- if (send_force) {
- r = sd_bus_message_append(m, "b", arg_force);
- 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 %s unit: %s", verb, bus_error_message(&error, r));
-
- if (expect_carries_install_info) {
- r = sd_bus_message_read(reply, "b", &carries_install_info);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
- if (r < 0)
- goto finish;
-
- /* Try to reload if enabled */
- if (!arg_no_reload)
- r = daemon_reload(argc, argv, userdata);
- else
- r = 0;
- }
-
- if (carries_install_info == 0 && !ignore_carries_install_info)
- log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n"
- "Alias= settings in the [Install] section, and DefaultInstance= for template\n"
- "units). This means they are not meant to be enabled using systemctl.\n"
- " \n" /* trick: the space is needed so that the line does not get stripped from output */
- "Possible reasons for having this kind of units are:\n"
- "%1$s A unit may be statically enabled by being symlinked from another unit's\n"
- " .wants/ or .requires/ directory.\n"
- "%1$s A unit's purpose may be to act as a helper for some other unit which has\n"
- " a requirement dependency on it.\n"
- "%1$s A unit may be started when needed via activation (socket, path, timer,\n"
- " D-Bus, udev, scripted systemctl call, ...).\n"
- "%1$s In case of template units, the unit is meant to be enabled with some\n"
- " instance name specified.",
- special_glyph(SPECIAL_GLYPH_BULLET));
-
- if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
- sd_bus *bus;
- size_t len, i;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- goto finish;
-
- len = strv_length(names);
- {
- char *new_args[len + 2];
-
- new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
- for (i = 0; i < len; i++)
- new_args[i + 1] = basename(names[i]);
- new_args[i + 1] = NULL;
-
- r = start_unit(len + 1, new_args, userdata);
- }
- }
-
-finish:
- unit_file_changes_free(changes, n_changes);
-
- return r;
-}
-
-static int add_dependency(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- _cleanup_free_ char *target = NULL;
- const char *verb = argv[0];
- UnitFileChange *changes = NULL;
- size_t n_changes = 0;
- UnitDependency dep;
- int r;
-
- if (!argv[1])
- return 0;
-
- r = unit_name_mangle_with_suffix(argv[1], "as target",
- arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
- ".target", &target);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle unit name: %m");
-
- r = mangle_names("as dependency", strv_skip(argv, 2), &names);
- if (r < 0)
- return r;
-
- if (streq(verb, "add-wants"))
- dep = UNIT_WANTS;
- else if (streq(verb, "add-requires"))
- dep = UNIT_REQUIRES;
- else
- assert_not_reached("Unknown verb");
-
- if (install_client_side()) {
- r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes);
- unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
-
- if (r > 0)
- r = 0;
- } else {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "AddDependencyUnitFiles");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_strv(m, names);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
- 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 add dependency: %s", bus_error_message(&error, r));
-
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
- if (r < 0)
- goto finish;
-
- if (arg_no_reload) {
- r = 0;
- goto finish;
- }
-
- r = daemon_reload(argc, argv, userdata);
- }
-
-finish:
- unit_file_changes_free(changes, n_changes);
-
- return r;
-}
-
-static int preset_all(int argc, char *argv[], void *userdata) {
- UnitFileChange *changes = NULL;
- size_t n_changes = 0;
- int r;
-
- if (install_client_side()) {
- r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes);
- unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
-
- if (r > 0)
- r = 0;
- } else {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- sd_bus *bus;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- polkit_agent_open_maybe();
-
- r = bus_call_method(
- bus,
- bus_systemd_mgr,
- "PresetAllUnitFiles",
- &error,
- &reply,
- "sbb",
- unit_file_preset_mode_to_string(arg_preset_mode),
- arg_runtime,
- arg_force);
- if (r < 0)
- return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
-
- r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
- if (r < 0)
- goto finish;
-
- if (arg_no_reload) {
- r = 0;
- goto finish;
- }
-
- r = daemon_reload(argc, argv, userdata);
- }
-
-finish:
- unit_file_changes_free(changes, n_changes);
-
- return r;
-}
-
-static int show_installation_targets_client_side(const char *name) {
- UnitFileChange *changes = NULL;
- size_t n_changes = 0, i;
- UnitFileFlags flags;
- char **p;
- int r;
-
- p = STRV_MAKE(name);
- flags = UNIT_FILE_DRY_RUN |
- (arg_runtime ? UNIT_FILE_RUNTIME : 0);
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
- if (r < 0)
- return log_error_errno(r, "Failed to get file links for %s: %m", name);
-
- for (i = 0; i < n_changes; i++)
- if (changes[i].type == UNIT_FILE_UNLINK)
- printf(" %s\n", changes[i].path);
-
- return 0;
-}
-
-static int show_installation_targets(sd_bus *bus, const char *name) {
- _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 *link;
- int r;
-
- r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileLinks", &error, &reply, "sb", name, arg_runtime);
- if (r < 0)
- return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
- printf(" %s\n", link);
-
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-}
-
-static int unit_is_enabled(int argc, char *argv[], void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- bool enabled;
- char **name;
- int r;
-
- r = mangle_names("to check", strv_skip(argv, 1), &names);
- if (r < 0)
- return r;
-
- r = enable_sysv_units(argv[0], names);
- if (r < 0)
- return r;
-
- enabled = r > 0;
-
- if (install_client_side()) {
- STRV_FOREACH(name, names) {
- UnitFileState state;
-
- r = unit_file_get_state(arg_scope, arg_root, *name, &state);
- if (r < 0)
- return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
-
- if (IN_SET(state,
- UNIT_FILE_ENABLED,
- UNIT_FILE_ENABLED_RUNTIME,
- UNIT_FILE_STATIC,
- UNIT_FILE_ALIAS,
- UNIT_FILE_INDIRECT,
- UNIT_FILE_GENERATED))
- enabled = true;
-
- if (!arg_quiet) {
- puts(unit_file_state_to_string(state));
- if (arg_full) {
- r = show_installation_targets_client_side(*name);
- if (r < 0)
- return r;
- }
- }
- }
-
- r = 0;
- } else {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- STRV_FOREACH(name, names) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *s;
-
- r = bus_call_method(bus, bus_systemd_mgr, "GetUnitFileState", &error, &reply, "s", *name);
- if (r < 0)
- return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "s", &s);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
- enabled = true;
- if (!arg_quiet) {
- puts(s);
- if (arg_full) {
- r = show_installation_targets(bus, *name);
- if (r < 0)
- return r;
- }
- }
- }
- }
-
- return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int match_startup_finished(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- char **state = userdata;
- int r;
-
- assert(state);
-
- r = bus_get_property_string(sd_bus_message_get_bus(m), bus_systemd_mgr, "SystemState", NULL, state);
-
- sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), r);
- return 0;
-}
-
-static int is_system_running(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_startup_finished = NULL;
- _cleanup_(sd_event_unrefp) sd_event* event = NULL;
- _cleanup_free_ char *state = NULL;
- sd_bus *bus;
- int r;
-
- if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
- if (!arg_quiet)
- puts("offline");
- return EXIT_FAILURE;
- }
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- if (arg_wait) {
- r = sd_event_default(&event);
- if (r >= 0)
- r = sd_bus_attach_event(bus, event, 0);
- if (r >= 0)
- r = bus_match_signal_async(
- bus,
- &slot_startup_finished,
- bus_systemd_mgr,
- "StartupFinished",
- match_startup_finished, NULL, &state);
- if (r < 0) {
- log_warning_errno(r, "Failed to request match for StartupFinished: %m");
- arg_wait = false;
- }
- }
-
- r = bus_get_property_string(bus, bus_systemd_mgr, "SystemState", &error, &state);
- if (r < 0) {
- log_warning_errno(r, "Failed to query system state: %s", bus_error_message(&error, r));
-
- if (!arg_quiet)
- puts("unknown");
- return EXIT_FAILURE;
- }
-
- if (arg_wait && STR_IN_SET(state, "initializing", "starting")) {
- r = sd_event_loop(event);
- if (r < 0) {
- log_warning_errno(r, "Failed to get property from event loop: %m");
- if (!arg_quiet)
- puts("unknown");
- return EXIT_FAILURE;
- }
- }
-
- if (!arg_quiet)
- puts(state);
-
- return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(new_path);
- assert(original_path);
- assert(ret_tmp_fn);
-
- r = tempfn_random(new_path, NULL, &t);
- if (r < 0)
- return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
-
- r = mkdir_parents_label(new_path, 0755);
- if (r < 0)
- return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
-
- r = mac_selinux_create_file_prepare(original_path, S_IFREG);
- if (r < 0)
- return r;
-
- r = copy_file(original_path, t, 0, 0644, 0, 0, COPY_REFLINK);
- if (r == -ENOENT) {
-
- r = touch(t);
-
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
-
- } else {
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
- }
-
- *ret_tmp_fn = TAKE_PTR(t);
-
- return 0;
-}
-
-static int get_file_to_edit(
- const LookupPaths *paths,
- const char *name,
- char **ret_path) {
-
- _cleanup_free_ char *path = NULL, *run = NULL;
-
- assert(name);
- assert(ret_path);
-
- path = path_join(paths->persistent_config, name);
- if (!path)
- return log_oom();
-
- if (arg_runtime) {
- run = path_join(paths->runtime_config, name);
- if (!run)
- return log_oom();
- }
-
- if (arg_runtime) {
- if (access(path, F_OK) >= 0)
- return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
- "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.",
- run, path);
-
- *ret_path = TAKE_PTR(run);
- } else
- *ret_path = TAKE_PTR(path);
-
- return 0;
-}
-
-static int unit_file_create_new(
- const LookupPaths *paths,
- const char *unit_name,
- const char *suffix,
- char **ret_new_path,
- char **ret_tmp_path) {
-
- _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
- const char *ending;
- int r;
-
- assert(unit_name);
- assert(ret_new_path);
- assert(ret_tmp_path);
-
- ending = strjoina(unit_name, suffix);
- r = get_file_to_edit(paths, ending, &new_path);
- if (r < 0)
- return r;
-
- r = create_edit_temp_file(new_path, new_path, &tmp_path);
- if (r < 0)
- return r;
-
- *ret_new_path = TAKE_PTR(new_path);
- *ret_tmp_path = TAKE_PTR(tmp_path);
-
- return 0;
-}
-
-static int unit_file_create_copy(
- const LookupPaths *paths,
- const char *unit_name,
- const char *fragment_path,
- char **ret_new_path,
- char **ret_tmp_path) {
-
- _cleanup_free_ char *new_path = NULL, *tmp_path = NULL;
- int r;
-
- assert(fragment_path);
- assert(unit_name);
- assert(ret_new_path);
- assert(ret_tmp_path);
-
- r = get_file_to_edit(paths, unit_name, &new_path);
- if (r < 0)
- return r;
-
- if (!path_equal(fragment_path, new_path) && access(new_path, F_OK) >= 0) {
- char response;
-
- r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", new_path, fragment_path);
- if (r < 0)
- return r;
- if (response != 'y')
- return log_warning_errno(SYNTHETIC_ERRNO(EKEYREJECTED), "%s skipped.", unit_name);
- }
-
- r = create_edit_temp_file(new_path, fragment_path, &tmp_path);
- if (r < 0)
- return r;
-
- *ret_new_path = TAKE_PTR(new_path);
- *ret_tmp_path = TAKE_PTR(tmp_path);
-
- return 0;
-}
-
-static int run_editor(char **paths) {
- int r;
-
- assert(paths);
-
- r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
- if (r < 0)
- return r;
- if (r == 0) {
- char **editor_args = NULL, **tmp_path, **original_path;
- size_t n_editor_args = 0, i = 1, argc;
- const char **args, *editor, *p;
-
- argc = strv_length(paths)/2 + 1;
-
- /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
- * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
- * we try to execute well known editors
- */
- editor = getenv("SYSTEMD_EDITOR");
- if (!editor)
- editor = getenv("EDITOR");
- if (!editor)
- editor = getenv("VISUAL");
-
- if (!isempty(editor)) {
- editor_args = strv_split(editor, WHITESPACE);
- if (!editor_args) {
- (void) log_oom();
- _exit(EXIT_FAILURE);
- }
- n_editor_args = strv_length(editor_args);
- argc += n_editor_args - 1;
- }
-
- args = newa(const char*, argc + 1);
-
- if (n_editor_args > 0) {
- args[0] = editor_args[0];
- for (; i < n_editor_args; i++)
- args[i] = editor_args[i];
- }
-
- STRV_FOREACH_PAIR(original_path, tmp_path, paths)
- args[i++] = *tmp_path;
- args[i] = NULL;
-
- if (n_editor_args > 0)
- execvp(args[0], (char* const*) args);
-
- FOREACH_STRING(p, "editor", "nano", "vim", "vi") {
- args[0] = p;
- execvp(p, (char* const*) args);
- /* We do not fail if the editor doesn't exist
- * because we want to try each one of them before
- * failing.
- */
- if (errno != ENOENT) {
- log_error_errno(errno, "Failed to execute %s: %m", editor);
- _exit(EXIT_FAILURE);
- }
- }
-
- log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
- _exit(EXIT_FAILURE);
- }
-
- return 0;
-}
-
-static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
- _cleanup_(lookup_paths_free) LookupPaths lp = {};
- char **name;
- int r;
-
- assert(names);
- assert(paths);
-
- r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
- if (r < 0)
- return r;
-
- STRV_FOREACH(name, names) {
- _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL;
- const char *unit_name;
-
- r = unit_find_paths(bus, *name, &lp, false, &path, NULL);
- if (r == -EKEYREJECTED) {
- /* If loading of the unit failed server side complete, then the server won't tell us the unit
- * file path. In that case, find the file client side. */
- log_debug_errno(r, "Unit '%s' was not loaded correctly, retrying client-side.", *name);
- r = unit_find_paths(bus, *name, &lp, true, &path, NULL);
- }
- if (r == -ERFKILL)
- return log_error_errno(r, "Unit '%s' masked, cannot edit.", *name);
- if (r < 0)
- return r;
-
- if (r == 0) {
- assert(!path);
-
- if (!arg_force) {
- log_info("Run 'systemctl edit%s --force --full %s' to create a new unit.",
- arg_scope == UNIT_FILE_GLOBAL ? " --global" :
- arg_scope == UNIT_FILE_USER ? " --user" : "",
- *name);
- return -ENOENT;
- }
-
- /* Create a new unit from scratch */
- unit_name = *name;
- r = unit_file_create_new(&lp, unit_name,
- arg_full ? NULL : ".d/override.conf",
- &new_path, &tmp_path);
- } else {
- assert(path);
-
- unit_name = basename(path);
- /* We follow unit aliases, but we need to propagate the instance */
- if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) &&
- unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
- _cleanup_free_ char *instance = NULL;
-
- r = unit_name_to_instance(*name, &instance);
- if (r < 0)
- return r;
-
- r = unit_name_replace_instance(unit_name, instance, &tmp_name);
- if (r < 0)
- return r;
-
- unit_name = tmp_name;
- }
-
- if (arg_full)
- r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path);
- else
- r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path);
- }
- if (r < 0)
- return r;
-
- r = strv_push_pair(paths, new_path, tmp_path);
- if (r < 0)
- return log_oom();
-
- new_path = tmp_path = NULL;
- }
-
- return 0;
-}
-
-static int edit(int argc, char *argv[], void *userdata) {
- _cleanup_(lookup_paths_free) LookupPaths lp = {};
- _cleanup_strv_free_ char **names = NULL;
- _cleanup_strv_free_ char **paths = NULL;
- char **original, **tmp;
- sd_bus *bus;
- int r;
-
- if (!on_tty())
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units if not on a tty.");
-
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units remotely.");
-
- r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
- if (r < 0)
- return log_error_errno(r, "Failed to determine unit paths: %m");
-
- r = mac_selinux_init();
- if (r < 0)
- return r;
-
- r = acquire_bus(BUS_MANAGER, &bus);
- if (r < 0)
- return r;
-
- r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to expand names: %m");
-
- STRV_FOREACH(tmp, names) {
- r = unit_is_masked(bus, &lp, *tmp);
- if (r < 0)
- return r;
- if (r > 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit %s: unit is masked.", *tmp);
- }
-
- r = find_paths_to_edit(bus, names, &paths);
- if (r < 0)
- return r;
-
- if (strv_isempty(paths))
- return -ENOENT;
-
- r = run_editor(paths);
- if (r < 0)
- goto end;
-
- STRV_FOREACH_PAIR(original, tmp, paths) {
- /* If the temporary file is empty we ignore it.
- * This allows the user to cancel the modification.
- */
- if (null_or_empty_path(*tmp)) {
- log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
- continue;
- }
-
- r = rename(*tmp, *original);
- if (r < 0) {
- r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
- goto end;
- }
- }
-
- r = 0;
-
- if (!arg_no_reload && !install_client_side())
- r = daemon_reload(argc, argv, userdata);
-
-end:
- STRV_FOREACH_PAIR(original, tmp, paths) {
- (void) unlink(*tmp);
-
- /* Removing empty dropin dirs */
- if (!arg_full) {
- _cleanup_free_ char *dir;
-
- dir = dirname_malloc(*original);
- if (!dir)
- return log_oom();
+#include "bus-util.h"
+#include "install.h"
+#include "main-func.h"
+#include "output-mode.h"
+#include "pager.h"
+#include "path-util.h"
+#include "pretty-print.h"
+#include "rlimit-util.h"
+#include "sigbus.h"
+#include "signal-util.h"
+#include "string-table.h"
+#include "systemctl-add-dependency.h"
+#include "systemctl-cancel-job.h"
+#include "systemctl-clean-or-freeze.h"
+#include "systemctl-compat-halt.h"
+#include "systemctl-compat-runlevel.h"
+#include "systemctl-compat-shutdown.h"
+#include "systemctl-compat-telinit.h"
+#include "systemctl-daemon-reload.h"
+#include "systemctl-edit.h"
+#include "systemctl-enable.h"
+#include "systemctl-is-active.h"
+#include "systemctl-is-enabled.h"
+#include "systemctl-is-system-running.h"
+#include "systemctl-kill.h"
+#include "systemctl-list-dependencies.h"
+#include "systemctl-list-jobs.h"
+#include "systemctl-list-machines.h"
+#include "systemctl-list-unit-files.h"
+#include "systemctl-list-units.h"
+#include "systemctl-log-setting.h"
+#include "systemctl-logind.h"
+#include "systemctl-preset-all.h"
+#include "systemctl-reset-failed.h"
+#include "systemctl-service-watchdogs.h"
+#include "systemctl-set-default.h"
+#include "systemctl-set-environment.h"
+#include "systemctl-set-property.h"
+#include "systemctl-show.h"
+#include "systemctl-start-special.h"
+#include "systemctl-start-unit.h"
+#include "systemctl-switch-root.h"
+#include "systemctl-sysv-compat.h"
+#include "systemctl-trivial-method.h"
+#include "systemctl-util.h"
+#include "systemctl.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "verbs.h"
+#include "virt.h"
- /* no need to check if the dir is empty, rmdir
- * does nothing if it is not the case.
- */
- (void) rmdir(dir);
- }
- }
+char **arg_types = NULL;
+char **arg_states = NULL;
+char **arg_properties = NULL;
+bool arg_all = false;
+enum dependency arg_dependency = DEPENDENCY_FORWARD;
+const char *arg_job_mode = "replace";
+UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
+bool arg_wait = false;
+bool arg_no_block = false;
+bool arg_no_legend = false;
+PagerFlags arg_pager_flags = 0;
+bool arg_no_wtmp = false;
+bool arg_no_sync = false;
+bool arg_no_wall = false;
+bool arg_no_reload = false;
+bool arg_value = false;
+bool arg_show_types = false;
+bool arg_ignore_inhibitors = false;
+bool arg_dry_run = false;
+bool arg_quiet = false;
+bool arg_full = false;
+bool arg_recursive = false;
+bool arg_with_dependencies = false;
+bool arg_show_transaction = false;
+int arg_force = 0;
+bool arg_ask_password = false;
+bool arg_runtime = false;
+UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
+char **arg_wall = NULL;
+const char *arg_kill_who = NULL;
+int arg_signal = SIGTERM;
+char *arg_root = NULL;
+usec_t arg_when = 0;
+const char *arg_reboot_argument = NULL;
+enum action arg_action = ACTION_SYSTEMCTL;
+BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
+const char *arg_host = NULL;
+unsigned arg_lines = 10;
+OutputMode arg_output = OUTPUT_SHORT;
+bool arg_plain = false;
+bool arg_firmware_setup = false;
+usec_t arg_boot_loader_menu = USEC_INFINITY;
+const char *arg_boot_loader_entry = NULL;
+bool arg_now = false;
+bool arg_jobs_before = false;
+bool arg_jobs_after = false;
+char **arg_clean_what = NULL;
+TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
- return r;
-}
+STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
static int systemctl_help(void) {
_cleanup_free_ char *link = NULL;
return 0;
}
-static int halt_help(void) {
- _cleanup_free_ char *link = NULL;
- int r;
-
- r = terminal_urlify_man("halt", "8", &link);
- if (r < 0)
- return log_oom();
-
- printf("%s [OPTIONS...]%s\n"
- "\n%s%s the system.%s\n"
- "\nOptions:\n"
- " --help Show this help\n"
- " --halt Halt the machine\n"
- " -p --poweroff Switch off the machine\n"
- " --reboot Reboot the machine\n"
- " -f --force Force immediate halt/power-off/reboot\n"
- " -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
- );
-
- return 0;
-}
-
-static int shutdown_help(void) {
- _cleanup_free_ char *link = NULL;
- int r;
-
- r = terminal_urlify_man("shutdown", "8", &link);
- if (r < 0)
- return log_oom();
-
- printf("%s [OPTIONS...] [TIME] [WALL...]\n"
- "\n%sShut down the system.%s\n"
- "\nOptions:\n"
- " --help Show this help\n"
- " -H --halt Halt the machine\n"
- " -P --poweroff Power-off the machine\n"
- " -r --reboot Reboot the machine\n"
- " -h Equivalent to --poweroff, overridden by --halt\n"
- " -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
- );
-
- return 0;
-}
-
-static int telinit_help(void) {
- _cleanup_free_ char *link = NULL;
- int r;
-
- r = terminal_urlify_man("telinit", "8", &link);
- if (r < 0)
- return log_oom();
-
- printf("%s [OPTIONS...] COMMAND\n\n"
- "%sSend control commands to the init daemon.%s\n"
- "\nCommands:\n"
- " 0 Power-off the machine\n"
- " 6 Reboot the machine\n"
- " 2, 3, 4, 5 Start runlevelX.target unit\n"
- " 1, s, S Enter rescue mode\n"
- " q, Q Reload init daemon configuration\n"
- " u, U Reexecute init daemon\n"
- "\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
- );
-
- return 0;
-}
-
-static int runlevel_help(void) {
- _cleanup_free_ char *link = NULL;
- int r;
-
- r = terminal_urlify_man("runlevel", "8", &link);
- if (r < 0)
- return log_oom();
-
- printf("%s [OPTIONS...]\n"
- "\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
- );
-
- return 0;
-}
-
static void help_types(void) {
if (!arg_no_legend)
puts("Available unit types:");
if (!arg_no_legend)
puts("\nAvailable swap unit substates:");
- DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
-
- if (!arg_no_legend)
- puts("\nAvailable target unit substates:");
- DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
-
- if (!arg_no_legend)
- puts("\nAvailable timer unit substates:");
- DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
-}
-
-static int help_boot_loader_entry(void) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_strv_free_ char **l = NULL;
- sd_bus *bus;
- char **i;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- r = bus_get_property_strv(bus, bus_login_mgr, "BootLoaderEntries", &error, &l);
- if (r < 0)
- return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
-
- if (strv_isempty(l))
- return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No boot loader entries discovered.");
+ DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
- STRV_FOREACH(i, l)
- puts(*i);
+ if (!arg_no_legend)
+ puts("\nAvailable target unit substates:");
+ DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
- return 0;
+ if (!arg_no_legend)
+ puts("\nAvailable timer unit substates:");
+ DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
}
static int systemctl_parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
+ /* We default to allowing interactive authorization only in systemctl (not in the legacy commands) */
arg_ask_password = true;
while ((c = getopt_long(argc, argv, "ht:p:P:alqfs:H:M:n:o:iTr.::", options, NULL)) >= 0)
continue;
}
- /* It's much nicer to use --state= for
- * load states, but let's support this
- * in --types= too for compatibility
- * with old versions */
+ /* It's much nicer to use --state= for load states, but let's support this in
+ * --types= too for compatibility with old versions */
if (unit_load_state_from_string(type) >= 0) {
if (strv_consume(&arg_states, TAKE_PTR(type)) < 0)
return log_oom();
case ARG_BOOT_LOADER_MENU:
- r = parse_sec(optarg, &arg_boot_loader_menu);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
-
- break;
-
- case ARG_BOOT_LOADER_ENTRY:
-
- if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
- r = help_boot_loader_entry();
- if (r < 0)
- return r;
-
- return 0;
- }
-
- arg_boot_loader_entry = empty_to_null(optarg);
- break;
-
- case ARG_STATE: {
- const char *p;
-
- if (isempty(optarg))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--state= requires arguments.");
-
- for (p = optarg;;) {
- _cleanup_free_ char *s = NULL;
-
- r = extract_first_word(&p, &s, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to parse state: %s", optarg);
- if (r == 0)
- break;
-
- if (streq(s, "help")) {
- help_states();
- return 0;
- }
-
- if (strv_consume(&arg_states, TAKE_PTR(s)) < 0)
- return log_oom();
- }
- break;
- }
-
- case 'r':
- if (geteuid() != 0)
- return log_error_errno(SYNTHETIC_ERRNO(EPERM),
- "--recursive requires root privileges.");
-
- arg_recursive = true;
- break;
-
- case ARG_PRESET_MODE:
- if (streq(optarg, "help")) {
- DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
- return 0;
- }
-
- arg_preset_mode = unit_file_preset_mode_from_string(optarg);
- if (arg_preset_mode < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Failed to parse preset mode: %s.", optarg);
-
- break;
-
- case ARG_NOW:
- arg_now = true;
- break;
-
- case ARG_MESSAGE:
- if (strv_extend(&arg_wall, optarg) < 0)
- return log_oom();
- break;
-
- case 'T':
- arg_show_transaction = true;
- break;
-
- case ARG_WITH_DEPENDENCIES:
- arg_with_dependencies = true;
- break;
-
- case ARG_WHAT: {
- const char *p;
-
- if (isempty(optarg))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments.");
-
- for (p = optarg;;) {
- _cleanup_free_ char *k = NULL;
-
- r = extract_first_word(&p, &k, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to parse directory type: %s", optarg);
- if (r == 0)
- break;
-
- if (streq(k, "help")) {
- puts("runtime\n"
- "state\n"
- "cache\n"
- "logs\n"
- "configuration");
- return 0;
- }
-
- r = strv_consume(&arg_clean_what, TAKE_PTR(k));
- if (r < 0)
- return log_oom();
- }
-
- break;
- }
-
- case ARG_REBOOT_ARG:
- arg_reboot_argument = optarg;
- break;
-
- case ARG_TIMESTAMP_STYLE:
- if (streq(optarg, "help")) {
- DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX);
- return 0;
- }
-
- arg_timestamp_style = timestamp_style_from_string(optarg);
- if (arg_timestamp_style < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid value: %s.", optarg);
-
- break;
-
- case '.':
- /* Output an error mimicking getopt, and print a hint afterwards */
- log_error("%s: invalid option -- '.'", program_invocation_name);
- log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
- " %s [OPTIONS...] COMMAND -- -.%s ...",
- program_invocation_name, optarg ?: "mount");
- _fallthrough_;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Cannot access user instance remotely.");
-
- if (arg_wait && arg_no_block)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--wait may not be combined with --no-block.");
-
- return 1;
-}
-
-static int halt_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_HELP = 0x100,
- ARG_HALT,
- ARG_REBOOT,
- ARG_NO_WALL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "halt", no_argument, NULL, ARG_HALT },
- { "poweroff", no_argument, NULL, 'p' },
- { "reboot", no_argument, NULL, ARG_REBOOT },
- { "force", no_argument, NULL, 'f' },
- { "wtmp-only", no_argument, NULL, 'w' },
- { "no-wtmp", no_argument, NULL, 'd' },
- { "no-sync", no_argument, NULL, 'n' },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- {}
- };
-
- int c, r, runlevel;
-
- assert(argc >= 0);
- assert(argv);
-
- if (utmp_get_runlevel(&runlevel, NULL) >= 0)
- if (IN_SET(runlevel, '0', '6'))
- arg_force = 2;
-
- while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
- switch (c) {
-
- case ARG_HELP:
- return halt_help();
-
- case ARG_HALT:
- arg_action = ACTION_HALT;
- break;
-
- case 'p':
- if (arg_action != ACTION_REBOOT)
- arg_action = ACTION_POWEROFF;
- break;
-
- case ARG_REBOOT:
- arg_action = ACTION_REBOOT;
- break;
-
- case 'f':
- arg_force = 2;
- break;
-
- case 'w':
- arg_dry_run = true;
- break;
-
- case 'd':
- arg_no_wtmp = true;
- break;
-
- case 'n':
- arg_no_sync = true;
- break;
-
- case ARG_NO_WALL:
- arg_no_wall = true;
- break;
-
- case 'i':
- case 'h':
- /* Compatibility nops */
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
- r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL, false);
- if (r < 0)
- return r;
- } else if (optind < argc)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Too many arguments.");
-
- return 1;
-}
-
-static int shutdown_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_HELP = 0x100,
- ARG_NO_WALL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "halt", no_argument, NULL, 'H' },
- { "poweroff", no_argument, NULL, 'P' },
- { "reboot", no_argument, NULL, 'r' },
- { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- {}
- };
-
- char **wall = NULL;
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0)
- switch (c) {
-
- case ARG_HELP:
- return shutdown_help();
-
- case 'H':
- arg_action = ACTION_HALT;
- break;
-
- case 'P':
- arg_action = ACTION_POWEROFF;
- break;
-
- case 'r':
- if (kexec_loaded())
- arg_action = ACTION_KEXEC;
- else
- arg_action = ACTION_REBOOT;
- break;
-
- case 'K':
- arg_action = ACTION_KEXEC;
- break;
-
- case 'h':
- if (arg_action != ACTION_HALT)
- arg_action = ACTION_POWEROFF;
- break;
-
- case 'k':
- arg_dry_run = true;
- break;
+ r = parse_sec(optarg, &arg_boot_loader_menu);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
- case ARG_NO_WALL:
- arg_no_wall = true;
break;
- case 'a':
- case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
- case 'f':
- case 'F':
- /* Compatibility nops */
- break;
+ case ARG_BOOT_LOADER_ENTRY:
- case 'c':
- arg_action = ACTION_CANCEL_SHUTDOWN;
- break;
+ if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
+ r = help_boot_loader_entry();
+ if (r < 0)
+ return r;
- case '?':
- return -EINVAL;
+ return 0;
+ }
- default:
- assert_not_reached("Unhandled option");
- }
+ arg_boot_loader_entry = empty_to_null(optarg);
+ break;
- if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
- r = parse_shutdown_time_spec(argv[optind], &arg_when);
- if (r < 0) {
- log_error("Failed to parse time specification: %s", argv[optind]);
- return r;
- }
- } else
- arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
-
- if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
- /* No time argument for shutdown cancel */
- wall = argv + optind;
- else if (argc > optind + 1)
- /* We skip the time argument */
- wall = argv + optind + 1;
-
- if (wall) {
- arg_wall = strv_copy(wall);
- if (!arg_wall)
- return log_oom();
- }
+ case ARG_STATE: {
+ const char *p;
- optind = argc;
+ if (isempty(optarg))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--state= requires arguments.");
- return 1;
-}
+ for (p = optarg;;) {
+ _cleanup_free_ char *s = NULL;
-static int telinit_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_HELP = 0x100,
- ARG_NO_WALL
- };
+ r = extract_first_word(&p, &s, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse state: %s", optarg);
+ if (r == 0)
+ break;
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- {}
- };
+ if (streq(s, "help")) {
+ help_states();
+ return 0;
+ }
- static const struct {
- char from;
- enum action to;
- } table[] = {
- { '0', ACTION_POWEROFF },
- { '6', ACTION_REBOOT },
- { '1', ACTION_RESCUE },
- { '2', ACTION_RUNLEVEL2 },
- { '3', ACTION_RUNLEVEL3 },
- { '4', ACTION_RUNLEVEL4 },
- { '5', ACTION_RUNLEVEL5 },
- { 's', ACTION_RESCUE },
- { 'S', ACTION_RESCUE },
- { 'q', ACTION_RELOAD },
- { 'Q', ACTION_RELOAD },
- { 'u', ACTION_REEXEC },
- { 'U', ACTION_REEXEC }
- };
+ if (strv_consume(&arg_states, TAKE_PTR(s)) < 0)
+ return log_oom();
+ }
+ break;
+ }
- unsigned i;
- int c;
+ case 'r':
+ if (geteuid() != 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+ "--recursive requires root privileges.");
- assert(argc >= 0);
- assert(argv);
+ arg_recursive = true;
+ break;
- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
- switch (c) {
+ case ARG_PRESET_MODE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
+ return 0;
+ }
- case ARG_HELP:
- return telinit_help();
+ arg_preset_mode = unit_file_preset_mode_from_string(optarg);
+ if (arg_preset_mode < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse preset mode: %s.", optarg);
- case ARG_NO_WALL:
- arg_no_wall = true;
break;
- case '?':
- return -EINVAL;
+ case ARG_NOW:
+ arg_now = true;
+ break;
- default:
- assert_not_reached("Unhandled option");
- }
+ case ARG_MESSAGE:
+ if (strv_extend(&arg_wall, optarg) < 0)
+ return log_oom();
+ break;
- if (optind >= argc)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: required argument missing.",
- program_invocation_short_name);
+ case 'T':
+ arg_show_transaction = true;
+ break;
- if (optind + 1 < argc)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Too many arguments.");
+ case ARG_WITH_DEPENDENCIES:
+ arg_with_dependencies = true;
+ break;
- if (strlen(argv[optind]) != 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Expected single character argument.");
+ case ARG_WHAT: {
+ const char *p;
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (table[i].from == argv[optind][0])
- break;
+ if (isempty(optarg))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments.");
- if (i >= ELEMENTSOF(table))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown command '%s'.", argv[optind]);
+ for (p = optarg;;) {
+ _cleanup_free_ char *k = NULL;
- arg_action = table[i].to;
+ r = extract_first_word(&p, &k, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse directory type: %s", optarg);
+ if (r == 0)
+ break;
- optind++;
+ if (streq(k, "help")) {
+ puts("runtime\n"
+ "state\n"
+ "cache\n"
+ "logs\n"
+ "configuration");
+ return 0;
+ }
- return 1;
-}
+ r = strv_consume(&arg_clean_what, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
-static int runlevel_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_HELP = 0x100,
- };
+ break;
+ }
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- {}
- };
+ case ARG_REBOOT_ARG:
+ arg_reboot_argument = optarg;
+ break;
- int c;
+ case ARG_TIMESTAMP_STYLE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX);
+ return 0;
+ }
- assert(argc >= 0);
- assert(argv);
+ arg_timestamp_style = timestamp_style_from_string(optarg);
+ if (arg_timestamp_style < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid value: %s.", optarg);
- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
- switch (c) {
+ break;
- case ARG_HELP:
- return runlevel_help();
+ case '.':
+ /* Output an error mimicking getopt, and print a hint afterwards */
+ log_error("%s: invalid option -- '.'", program_invocation_name);
+ log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
+ " %s [OPTIONS...] COMMAND -- -.%s ...",
+ program_invocation_name, optarg ?: "mount");
+ _fallthrough_;
case '?':
return -EINVAL;
assert_not_reached("Unhandled option");
}
- if (optind < argc)
+ if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Cannot access user instance remotely.");
+
+ if (arg_wait && arg_no_block)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Too many arguments.");
+ "--wait may not be combined with --no-block.");
return 1;
}
} 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.
+ /* 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,
return systemctl_parse_argv(argc, argv);
}
-#if HAVE_SYSV_COMPAT
-_pure_ static int action_to_runlevel(void) {
- static const char table[_ACTION_MAX] = {
- [ACTION_HALT] = '0',
- [ACTION_POWEROFF] = '0',
- [ACTION_REBOOT] = '6',
- [ACTION_RUNLEVEL2] = '2',
- [ACTION_RUNLEVEL3] = '3',
- [ACTION_RUNLEVEL4] = '4',
- [ACTION_RUNLEVEL5] = '5',
- [ACTION_RESCUE] = '1'
- };
-
- assert(arg_action >= 0 && arg_action < _ACTION_MAX);
- return table[arg_action];
-}
-#endif
-
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 },
return dispatch_verb(argc, argv, verbs, NULL);
}
-static int reload_with_fallback(void) {
- /* First, try systemd via D-Bus. */
- if (daemon_reload(0, NULL, NULL) >= 0)
- return 0;
-
- /* Nothing else worked, so let's try signals */
- assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
-
- if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
- return log_error_errno(errno, "kill() failed: %m");
-
- return 0;
-}
-
-static int start_with_fallback(void) {
- /* First, try systemd via D-Bus. */
- if (start_unit(0, NULL, NULL) == 0)
- return 0;
-
-#if HAVE_SYSV_COMPAT
- /* Nothing else worked, so let's try /dev/initctl */
- if (talk_initctl(action_to_runlevel()) > 0)
- return 0;
-#endif
-
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to talk to init daemon.");
-}
-
-static int halt_now(enum action a) {
- /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
- * synced explicitly in advance. */
- if (!arg_no_sync && !arg_dry_run)
- (void) sync();
-
- /* Make sure C-A-D is handled by the kernel from this point on... */
- if (!arg_dry_run)
- (void) reboot(RB_ENABLE_CAD);
-
- switch (a) {
-
- case ACTION_HALT:
- if (!arg_quiet)
- log_info("Halting.");
- if (arg_dry_run)
- return 0;
- (void) reboot(RB_HALT_SYSTEM);
- return -errno;
-
- case ACTION_POWEROFF:
- if (!arg_quiet)
- log_info("Powering off.");
- if (arg_dry_run)
- return 0;
- (void) reboot(RB_POWER_OFF);
- return -errno;
-
- case ACTION_KEXEC:
- case ACTION_REBOOT:
- return reboot_with_parameter(REBOOT_FALLBACK |
- (arg_quiet ? 0 : REBOOT_LOG) |
- (arg_dry_run ? REBOOT_DRY_RUN : 0));
-
- default:
- assert_not_reached("Unknown action.");
- }
-}
-
-static int logind_schedule_shutdown(void) {
-
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char date[FORMAT_TIMESTAMP_MAX];
- const char *action;
- const char *log_action;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- switch (arg_action) {
- case ACTION_HALT:
- action = "halt";
- log_action = "Shutdown";
- break;
- case ACTION_POWEROFF:
- action = "poweroff";
- log_action = "Shutdown";
- break;
- case ACTION_KEXEC:
- action = "kexec";
- log_action = "Reboot via kexec";
- break;
- case ACTION_EXIT:
- action = "exit";
- log_action = "Shutdown";
- break;
- case ACTION_REBOOT:
- default:
- action = "reboot";
- log_action = "Reboot";
- break;
- }
-
- if (arg_dry_run)
- action = strjoina("dry-", action);
-
- (void) logind_set_wall_message();
-
- r = bus_call_method(bus, bus_login_mgr, "ScheduleShutdown", &error, NULL, "st", action, arg_when);
- if (r < 0)
- return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
-
- if (!arg_quiet)
- log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp_style(date, sizeof(date), arg_when, arg_timestamp_style));
- return 0;
-#else
- return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
- "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
-#endif
-}
-
-static int halt_main(void) {
- int r;
-
- r = logind_check_inhibitors(arg_action);
- if (r < 0)
- return r;
-
- /* Delayed shutdown requested, and was successful */
- if (arg_when > 0 && logind_schedule_shutdown() == 0)
- return 0;
- /* no delay, or logind failed or is not at all available */
-
- if (geteuid() != 0) {
- if (arg_dry_run || arg_force > 0) {
- (void) must_be_root();
- return -EPERM;
- }
-
- /* Try logind if we are a normal user and no special
- * mode applies. Maybe polkit allows us to shutdown
- * the machine. */
- if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
- r = logind_reboot(arg_action);
- if (r >= 0)
- return r;
- if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
- /* requested operation is not
- * supported on the local system or
- * already in progress */
- return r;
- /* on all other errors, try low-level operation */
- }
- }
-
- /* In order to minimize the difference between operation with and
- * without logind, we explicitly enable non-blocking mode for this,
- * as logind's shutdown operations are always non-blocking. */
- arg_no_block = true;
-
- if (!arg_dry_run && !arg_force)
- return start_with_fallback();
-
- assert(geteuid() == 0);
-
- if (!arg_no_wtmp) {
- if (sd_booted() > 0)
- log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
- else {
- r = utmp_put_shutdown();
- if (r < 0)
- log_warning_errno(r, "Failed to write utmp record: %m");
- }
- }
-
- if (arg_dry_run)
- return 0;
-
- r = halt_now(arg_action);
- return log_error_errno(r, "Failed to reboot: %m");
-}
-
-static int runlevel_main(void) {
- int r, runlevel, previous;
-
- r = utmp_get_runlevel(&runlevel, &previous);
- if (r < 0) {
- puts("unknown");
- return r;
- }
-
- printf("%c %c\n",
- previous <= 0 ? 'N' : previous,
- runlevel <= 0 ? 'N' : runlevel);
-
- return 0;
-}
-
-static int logind_cancel_shutdown(void) {
-#if ENABLE_LOGIND
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus *bus;
- int r;
-
- r = acquire_bus(BUS_FULL, &bus);
- if (r < 0)
- return r;
-
- (void) logind_set_wall_message();
-
- r = bus_call_method(bus, bus_login_mgr, "CancelScheduledShutdown", &error, NULL, NULL);
- if (r < 0)
- return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
-
- return 0;
-#else
- return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
- "Not compiled with logind support, cannot cancel scheduled shutdowns.");
-#endif
-}
-
static int run(int argc, char *argv[]) {
int r;
sigbus_install();
- /* Explicitly not on_tty() to avoid setting cached value.
- * This becomes relevant for piping output which might be
- * ellipsized. */
- original_stdout_is_tty = isatty(STDOUT_FILENO);
-
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
goto finish;
}
- /* systemctl_main() will print an error message for the bus
- * connection, but only if it needs to */
+ /* systemctl_main() will print an error message for the bus connection, but only if it needs to */
switch (arg_action) {
r = systemctl_main(argc, argv);
break;
- /* Legacy command aliases set arg_action. They provide some fallbacks,
- * e.g. to tell sysvinit to reboot after you have installed systemd
- * binaries. */
+ /* Legacy command aliases set arg_action. They provide some fallbacks, e.g. to tell sysvinit to
+ * reboot after you have installed systemd binaries. */
case ACTION_HALT:
case ACTION_POWEROFF:
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:
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "bus-util.h"
+#include "install.h"
+#include "output-mode.h"
+#include "pager.h"
+
+enum action {
+ ACTION_SYSTEMCTL,
+ ACTION_HALT,
+ ACTION_POWEROFF,
+ ACTION_REBOOT,
+ ACTION_KEXEC,
+ ACTION_EXIT,
+ ACTION_SUSPEND,
+ ACTION_HIBERNATE,
+ ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE,
+ ACTION_RUNLEVEL2,
+ ACTION_RUNLEVEL3,
+ ACTION_RUNLEVEL4,
+ ACTION_RUNLEVEL5,
+ ACTION_RESCUE,
+ ACTION_EMERGENCY,
+ ACTION_DEFAULT,
+ ACTION_RELOAD,
+ ACTION_REEXEC,
+ ACTION_RUNLEVEL,
+ ACTION_CANCEL_SHUTDOWN,
+ _ACTION_MAX,
+ _ACTION_INVALID = -1
+};
+
+enum dependency {
+ DEPENDENCY_FORWARD,
+ DEPENDENCY_REVERSE,
+ DEPENDENCY_AFTER,
+ DEPENDENCY_BEFORE,
+ _DEPENDENCY_MAX
+};
+
+extern char **arg_types;
+extern char **arg_states;
+extern char **arg_properties;
+extern bool arg_all;
+extern enum dependency arg_dependency;
+extern const char *arg_job_mode;
+extern UnitFileScope arg_scope;
+extern bool arg_wait;
+extern bool arg_no_block;
+extern bool arg_no_legend;
+extern PagerFlags arg_pager_flags;
+extern bool arg_no_wtmp;
+extern bool arg_no_sync;
+extern bool arg_no_wall;
+extern bool arg_no_reload;
+extern bool arg_value;
+extern bool arg_show_types;
+extern bool arg_ignore_inhibitors;
+extern bool arg_dry_run;
+extern bool arg_quiet;
+extern bool arg_full;
+extern bool arg_recursive;
+extern bool arg_with_dependencies;
+extern bool arg_show_transaction;
+extern int arg_force;
+extern bool arg_ask_password;
+extern bool arg_runtime;
+extern UnitFilePresetMode arg_preset_mode;
+extern char **arg_wall;
+extern const char *arg_kill_who;
+extern int arg_signal;
+extern char *arg_root;
+extern usec_t arg_when;
+extern const char *arg_reboot_argument;
+extern enum action arg_action;
+extern BusTransport arg_transport;
+extern const char *arg_host;
+extern unsigned arg_lines;
+extern OutputMode arg_output;
+extern bool arg_plain;
+extern bool arg_firmware_setup;
+extern usec_t arg_boot_loader_menu;
+extern const char *arg_boot_loader_entry;
+extern bool arg_now;
+extern bool arg_jobs_before;
+extern bool arg_jobs_after;
+extern char **arg_clean_what;
+extern TimestampStyle arg_timestamp_style;
+++ /dev/null
-/* SPDX-License-Identifier: LGPL-2.1+ */
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "fd-util.h"
-#include "initreq.h"
-#include "io-util.h"
-#include "parse-util.h"
-#include "strv.h"
-#include "sysv-compat.h"
-
-#if HAVE_SYSV_COMPAT
-int talk_initctl(char rl) {
- struct init_request request;
- _cleanup_close_ int fd = -1;
- const char *p;
- int r;
-
- /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this
- * system, and > 0 on success. */
-
- if (rl == 0)
- return 0;
-
- FOREACH_STRING(p, "/run/initctl", "/dev/initctl") {
- fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
- if (fd >= 0 || errno != ENOENT)
- break;
- }
- if (fd < 0) {
- if (errno == ENOENT)
- return 0;
-
- return log_error_errno(errno, "Failed to open initctl fifo: %m");
- }
-
- request = (struct init_request) {
- .magic = INIT_MAGIC,
- .sleeptime = 0,
- .cmd = INIT_CMD_RUNLVL,
- .runlevel = rl,
- };
-
- r = loop_write(fd, &request, sizeof(request), false);
- if (r < 0)
- return log_error_errno(r, "Failed to write to %s: %m", p);
-
- return 1;
-}
-#endif
-
-int parse_shutdown_time_spec(const char *t, usec_t *ret) {
- assert(t);
- assert(ret);
-
- if (streq(t, "now"))
- *ret = 0;
- else if (!strchr(t, ':')) {
- uint64_t u;
-
- if (safe_atou64(t, &u) < 0)
- return -EINVAL;
-
- *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
- } else {
- char *e = NULL;
- long hour, minute;
- struct tm tm = {};
- time_t s;
- usec_t n;
-
- errno = 0;
- hour = strtol(t, &e, 10);
- if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
- return -EINVAL;
-
- minute = strtol(e+1, &e, 10);
- if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
- return -EINVAL;
-
- n = now(CLOCK_REALTIME);
- s = (time_t) (n / USEC_PER_SEC);
-
- assert_se(localtime_r(&s, &tm));
-
- tm.tm_hour = (int) hour;
- tm.tm_min = (int) minute;
- tm.tm_sec = 0;
-
- s = mktime(&tm);
- assert(s >= 0);
-
- *ret = (usec_t) s * USEC_PER_SEC;
-
- while (*ret <= n)
- *ret += USEC_PER_DAY;
- }
-
- return 0;
-}
int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
int sd_event_source_get_floating(sd_event_source *s);
int sd_event_source_set_floating(sd_event_source *s, int b);
+int sd_event_source_get_exit_on_failure(sd_event_source *s);
+int sd_event_source_set_exit_on_failure(sd_event_source *s, int b);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
#define SD_MESSAGE_OVERMOUNTING SD_ID128_MAKE(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7)
#define SD_MESSAGE_OVERMOUNTING_STR SD_ID128_MAKE_STR(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7)
+#define SD_MESSAGE_UNIT_OOMD_KILL SD_ID128_MAKE(d9,89,61,1b,15,e4,4c,9d,bf,31,e3,c8,12,56,e4,ed)
+#define SD_MESSAGE_UNIT_OOMD_KILL_STR SD_ID128_MAKE_STR(d9,89,61,1b,15,e4,4c,9d,bf,31,e3,c8,12,56,e4,ed)
+
#define SD_MESSAGE_UNIT_OUT_OF_MEMORY SD_ID128_MAKE(fe,6f,aa,94,e7,77,46,63,a0,da,52,71,78,91,d8,ef)
#define SD_MESSAGE_UNIT_OUT_OF_MEMORY_STR SD_ID128_MAKE_STR(fe,6f,aa,94,e7,77,46,63,a0,da,52,71,78,91,d8,ef)
int sd_netlink_message_close_container(sd_netlink_message *m);
int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
+int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data);
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data);
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret);
#include "strv.h"
#include "tmpfile-util-label.h"
#include "uid-range.h"
+#include "user-record.h"
#include "user-util.h"
#include "utf8.h"
#include "util.h"
static UidRange *uid_range = NULL;
static unsigned n_uid_range = 0;
+static UGIDAllocationRange login_defs = {};
+static bool login_defs_need_warning = false;
+
STATIC_DESTRUCTOR_REGISTER(groups, ordered_hashmap_freep);
STATIC_DESTRUCTOR_REGISTER(users, ordered_hashmap_freep);
STATIC_DESTRUCTOR_REGISTER(members, ordered_hashmap_freep);
return IN_SET(code, 0, ENOENT, ESRCH, EBADF, EPERM);
}
+static void maybe_emit_login_defs_warning(void) {
+ if (!login_defs_need_warning)
+ return;
+
+ if (login_defs.system_alloc_uid_min != SYSTEM_ALLOC_UID_MIN ||
+ login_defs.system_uid_max != SYSTEM_UID_MAX)
+ log_warning("login.defs specifies UID allocation range "UID_FMT"–"UID_FMT
+ " that is different than the built-in defaults ("UID_FMT"–"UID_FMT")",
+ login_defs.system_alloc_uid_min, login_defs.system_uid_max,
+ SYSTEM_ALLOC_UID_MIN, SYSTEM_UID_MAX);
+ if (login_defs.system_alloc_gid_min != SYSTEM_ALLOC_GID_MIN ||
+ login_defs.system_gid_max != SYSTEM_GID_MAX)
+ log_warning("login.defs specifies GID allocation range "GID_FMT"–"GID_FMT
+ " that is different than the built-in defaults ("GID_FMT"–"GID_FMT")",
+ login_defs.system_alloc_gid_min, login_defs.system_gid_max,
+ SYSTEM_ALLOC_GID_MIN, SYSTEM_GID_MAX);
+
+ login_defs_need_warning = false;
+}
+
static int load_user_database(void) {
_cleanup_fclose_ FILE *f = NULL;
const char *passwd_path;
ORDERED_HASHMAP_FOREACH(i, todo_gids) {
struct sgrp n = {
.sg_namp = i->name,
- .sg_passwd = (char*) "!!",
+ .sg_passwd = (char*) "!*",
};
r = putsgent_with_members(&n, gshadow);
/* And if that didn't work either, let's try to find a free one */
if (!i->uid_set) {
+ maybe_emit_login_defs_warning();
+
for (;;) {
r = uid_range_next_lower(uid_range, n_uid_range, &search_uid);
if (r < 0)
/* And if that didn't work either, let's try to find a free one */
if (!i->gid_set) {
+ maybe_emit_login_defs_warning();
+
for (;;) {
/* We look for new GIDs in the UID pool! */
r = uid_range_next_lower(uid_range, n_uid_range, &search_uid);
break;
case ARG_IMAGE:
+#ifdef STANDALONE
+ 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);
if (r < 0)
return r;
break;
+#endif
case ARG_REPLACE:
if (!path_is_absolute(optarg) ||
}
static int run(int argc, char *argv[]) {
+#ifndef STANDALONE
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
+#endif
_cleanup_close_ int lock = -1;
Item *i;
int r;
if (r < 0)
return r;
+#ifndef STANDALONE
if (arg_image) {
assert(!arg_root);
if (!arg_root)
return log_oom();
}
+#else
+ assert(!arg_image);
+#endif
/* If command line arguments are specified along with --replace, read all
* configuration files and insert the positional arguments at the specified
return log_error_errno(errno, "Failed to set SYSTEMD_NSS_BYPASS_SYNTHETIC environment variable: %m");
if (!uid_range) {
- /* Default to default range of 1..SYSTEM_UID_MAX */
- r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX);
+ /* Default to default range of SYSTEMD_UID_MIN..SYSTEM_UID_MAX. */
+ r = read_login_defs(&login_defs, NULL, arg_root);
if (r < 0)
- return log_oom();
+ return log_error_errno(r, "Failed to read %s%s: %m",
+ strempty(arg_root), "/etc/login.defs");
+
+ login_defs_need_warning = true;
+
+ /* We pick a range that very conservative: we look at compiled-in maximum and the value in
+ * /etc/login.defs. That way the uids/gids which we allocate will be interpreted correctly,
+ * even if /etc/login.defs is removed later. (The bottom bound doesn't matter much, since
+ * it's only used during allocation, so we use the configured value directly). */
+ uid_t begin = login_defs.system_alloc_uid_min,
+ end = MIN3((uid_t) SYSTEM_UID_MAX, login_defs.system_uid_max, login_defs.system_gid_max);
+ if (begin < end) {
+ r = uid_range_add(&uid_range, &n_uid_range, begin, end - begin + 1);
+ if (r < 0)
+ return log_oom();
+ }
}
r = add_implicit();
[['src/test/test-parse-util.c'],
[],
- []],
+ [libseccomp]],
[['src/test/test-sysctl-util.c'],
[],
[]],
+ [['src/test/test-user-record.c'],
+ [],
+ []],
+
[['src/test/test-user-util.c'],
[],
[]],
[['src/test/test-local-addresses.c'],
[],
[]],
+
+ [['src/test/test-psi-util.c'],
+ [],
+ []],
]
############################################################
#include "strv.h"
#include "tests.h"
#include "tomoyo-util.h"
+#include "user-record.h"
#include "user-util.h"
#include "virt.h"
assert_se(dns_name_is_valid_or_address("::1") > 0);
}
+static void test_dns_name_dot_suffixed(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(dns_name_dot_suffixed("") == 0);
+ assert_se(dns_name_dot_suffixed(".") > 0);
+ assert_se(dns_name_dot_suffixed("foo") == 0);
+ assert_se(dns_name_dot_suffixed("foo.") > 0);
+ assert_se(dns_name_dot_suffixed("foo\\..") > 0);
+ assert_se(dns_name_dot_suffixed("foo\\.") == 0);
+ assert_se(dns_name_dot_suffixed("foo.bar.") > 0);
+ assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\..") > 0);
+ assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\.\\.") == 0);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_dns_name_common_suffix();
test_dns_name_apply_idna();
test_dns_name_is_valid_or_address();
+ test_dns_name_dot_suffixed();
return 0;
}
#include "util.h"
static void test_strv_env_delete(void) {
+ log_info("/* %s */", __func__);
+
_cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
}
static void test_strv_env_get(void) {
- char **l;
+ log_info("/* %s */", __func__);
- l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
+ char **l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2"));
assert_se(streq(strv_env_get(l, "THREE"), "3"));
}
static void test_strv_env_unset(void) {
+ log_info("/* %s */", __func__);
+
_cleanup_strv_free_ char **l = NULL;
l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES");
}
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");
}
static void test_strv_env_merge(void) {
+ log_info("/* %s */", __func__);
+
_cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL;
a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF");
}
static void test_env_strv_get_n(void) {
+ log_info("/* %s */", __func__);
+
const char *_env[] = {
"FOO=NO NO NO",
"FOO=BAR BAR",
}
static void test_replace_env(bool braceless) {
+ log_info("/* %s(braceless=%s) */", __func__, yes_no(braceless));
+
const char *env[] = {
"FOO=BAR BAR",
"BAR=waldo",
}
static void test_replace_env2(bool extended) {
+ log_info("/* %s(extended=%s) */", __func__, yes_no(extended));
+
const char *env[] = {
"FOO=foo",
"BAR=bar",
}
static void test_replace_env_argv(void) {
+ log_info("/* %s */", __func__);
+
const char *env[] = {
"FOO=BAR BAR",
"BAR=waldo",
}
static void test_env_clean(void) {
- _cleanup_strv_free_ char **e;
-
- e = strv_new("FOOBAR=WALDO",
- "FOOBAR=WALDO",
- "FOOBAR",
- "F",
- "X=",
- "F=F",
- "=",
- "=F",
- "",
- "0000=000",
- "äöüß=abcd",
- "abcd=äöüß",
- "xyz\n=xyz",
- "xyz=xyz\n",
- "another=one",
- "another=final one");
+ log_info("/* %s */", __func__);
+
+ _cleanup_strv_free_ char **e = strv_new("FOOBAR=WALDO",
+ "FOOBAR=WALDO",
+ "FOOBAR",
+ "F",
+ "X=",
+ "F=F",
+ "=",
+ "=F",
+ "",
+ "0000=000",
+ "äöüß=abcd",
+ "abcd=äöüß",
+ "xyz\n=xyz",
+ "xyz=xyz\n",
+ "another=one",
+ "another=final one",
+ "CRLF=\r\n",
+ "BASH_FUNC_foo%%=() { echo foo\n}");
assert_se(e);
assert_se(!strv_env_is_valid(e));
assert_se(strv_env_clean(e) == e);
assert_se(streq(e[0], "FOOBAR=WALDO"));
assert_se(streq(e[1], "X="));
assert_se(streq(e[2], "F=F"));
- assert_se(streq(e[3], "abcd=äöüß"));
- assert_se(streq(e[4], "xyz=xyz\n"));
- assert_se(streq(e[5], "another=final one"));
- assert_se(e[6] == NULL);
+ assert_se(streq(e[3], "0000=000"));
+ assert_se(streq(e[4], "abcd=äöüß"));
+ assert_se(streq(e[5], "xyz=xyz\n"));
+ assert_se(streq(e[6], "another=final one"));
+ assert_se(streq(e[7], "BASH_FUNC_foo%%=() { echo foo\n}"));
+ assert_se(e[8] == NULL);
}
static void test_env_name_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(env_name_is_valid("test"));
assert_se(!env_name_is_valid(NULL));
assert_se(!env_name_is_valid("xxx\a"));
assert_se(!env_name_is_valid("xxx\007b"));
assert_se(!env_name_is_valid("\007\009"));
- assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
+ assert_se( env_name_is_valid("5_starting_with_a_number_is_unexpected_but_valid"));
assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
+ assert_se( env_name_is_valid("BASH_FUNC_foo%%"));
+ assert_se(!env_name_is_valid("with spaces%%"));
+ assert_se(!env_name_is_valid("with\nnewline%%"));
}
static void test_env_value_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(env_value_is_valid(""));
assert_se(env_value_is_valid("głąb kapuściany"));
assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
assert_se(env_value_is_valid("tab\tcharacter"));
assert_se(env_value_is_valid("new\nline"));
+ assert_se(!env_value_is_valid("Show this?\rNope. Show that!"));
+ assert_se(!env_value_is_valid("new DOS\r\nline"));
}
static void test_env_assignment_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(env_assignment_is_valid("a="));
assert_se(env_assignment_is_valid("b=głąb kapuściany"));
assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
assert_se(!env_assignment_is_valid("a b="));
assert_se(!env_assignment_is_valid("a ="));
assert_se(!env_assignment_is_valid(" b="));
- /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
- assert_se(!env_assignment_is_valid("a.b="));
- assert_se(!env_assignment_is_valid("a-b="));
+ /* Names with dots and dashes makes those variables inaccessible as bash variables (as the syntax
+ * simply does not allow such variable names, see http://tldp.org/LDP/abs/html/gotchas.html). They
+ * are still valid variables according to POSIX though. */
+ assert_se( env_assignment_is_valid("a.b="));
+ assert_se( env_assignment_is_valid("a-b="));
+ /* Those are not ASCII, so not valid according to POSIX (though zsh does allow unicode variable
+ * names…). */
assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
return code == CLD_DUMPED ? CLD_KILLED : code;
}
-_unused_ static bool is_run_on_travis_ci(void) {
- /* https://docs.travis-ci.com/user/environment-variables#default-environment-variables */
- return streq_ptr(getenv("TRAVIS"), "true");
-}
-
static void wait_for_service_finish(Manager *m, Unit *unit) {
Service *service = NULL;
usec_t ts;
test_setup_logging(LOG_DEBUG);
#if HAS_FEATURE_ADDRESS_SANITIZER
- if (is_run_on_travis_ci()) {
+ if (strstr_ptr(ci_environment(), "travis")) {
log_notice("Running on TravisCI under ASan, skipping, see https://github.com/systemd/systemd/issues/10696");
return EXIT_TEST_SKIP;
}
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
+#include "rlimit-util.h"
#include "serialize.h"
#include "string-util.h"
#include "tests.h"
log_info("nr-open: %i", read_nr_open());
}
+static size_t validate_fds(
+ bool opened,
+ const int *fds,
+ size_t n_fds) {
+
+ size_t c = 0;
+
+ /* Validates that fds in the specified array are one of the following three:
+ *
+ * 1. < 0 (test is skipped) or
+ * 2. opened (if 'opened' param is true) or
+ * 3. closed (if 'opened' param is false)
+ */
+
+ for (size_t i = 0; i < n_fds; i++) {
+ if (fds[i] < 0)
+ continue;
+
+ if (opened)
+ assert_se(fcntl(fds[i], F_GETFD) >= 0);
+ else
+ assert_se(fcntl(fds[i], F_GETFD) < 0 && errno == EBADF);
+
+ c++;
+ }
+
+ return c; /* Return number of fds >= 0 in the array */
+}
+
+static void test_close_all_fds(void) {
+ _cleanup_free_ int *fds = NULL, *keep = NULL;
+ struct rlimit rl;
+ size_t n_fds, n_keep;
+
+ log_info("/* %s */", __func__);
+
+ rlimit_nofile_bump(-1);
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+ assert_se(rl.rlim_cur > 10);
+
+ /* Try to use 5000 fds, but when we can't bump the rlimit to make that happen use the whole limit minus 10 */
+ n_fds = MIN((rl.rlim_cur & ~1U) - 10U, 5000U);
+ assert_se((n_fds & 1U) == 0U); /* make sure even number of fds */
+
+ /* Allocate the determined number of fds, always two at a time */
+ assert_se(fds = new(int, n_fds));
+ for (size_t i = 0; i < n_fds; i += 2)
+ assert_se(pipe2(fds + i, O_CLOEXEC) >= 0);
+
+ /* Validate this worked */
+ assert_se(validate_fds(true, fds, n_fds) == n_fds);
+
+ /* Randomized number of fds to keep, but at most every second */
+ n_keep = (random_u64() % (n_fds / 2));
+
+ /* Now randomly select a number of fds from the array above to keep */
+ assert_se(keep = new(int, n_keep));
+ for (size_t k = 0; k < n_keep; k++) {
+ for (;;) {
+ size_t p;
+
+ p = random_u64() % n_fds;
+ if (fds[p] >= 0) {
+ keep[k] = TAKE_FD(fds[p]);
+ break;
+ }
+ }
+ }
+
+ /* Check that all fds from both arrays are still open, and test how many in each are >= 0 */
+ assert_se(validate_fds(true, fds, n_fds) == n_fds - n_keep);
+ assert_se(validate_fds(true, keep, n_keep) == n_keep);
+
+ /* Close logging fd first, so that we don't confuse it by closing its fd */
+ log_close();
+ log_set_open_when_needed(true);
+
+ /* Close all but the ones to keep */
+ assert_se(close_all_fds(keep, n_keep) >= 0);
+
+ assert_se(validate_fds(false, fds, n_fds) == n_fds - n_keep);
+ assert_se(validate_fds(true, keep, n_keep) == n_keep);
+
+ /* Close everything else too! */
+ assert_se(close_all_fds(NULL, 0) >= 0);
+
+ assert_se(validate_fds(false, fds, n_fds) == n_fds - n_keep);
+ assert_se(validate_fds(false, keep, n_keep) == n_keep);
+
+ log_set_open_when_needed(false);
+ log_open();
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_rearrange_stdio();
test_fd_duplicate_data_fd();
test_read_nr_open();
+ test_close_all_fds();
return 0;
}
_cleanup_(table_unrefp) Table *table = NULL;
_cleanup_free_ char *formatted = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(table = table_new("name", "type", "ro", "usage", "created", "modified"));
assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(3), 100) >= 0);
assert_se(table_add_many(table,
_cleanup_(table_unrefp) Table *table = NULL;
_cleanup_free_ char *formatted = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(table = table_new("foo", "bar"));
assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100) >= 0);
_cleanup_(table_unrefp) Table *table = NULL;
_cleanup_free_ char *formatted = NULL;
+ log_info("/* %s */", __func__);
+
assert_se(table = table_new("foo", "bar"));
assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100) >= 0);
formatted = mfree(formatted);
}
-int main(int argc, char *argv[]) {
+static void test_strv_wrapped(void) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ _cleanup_free_ char *formatted = NULL;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(table = table_new("foo", "bar"));
+
+ assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100) >= 0);
+
+ assert_se(table_add_many(table,
+ TABLE_STRV_WRAPPED, STRV_MAKE("three", "different", "lines"),
+ TABLE_STRV_WRAPPED, STRV_MAKE("two", "lines")) >= 0);
+
+ table_set_cell_height_max(table, 1);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different lines two lines\n"));
+ formatted = mfree(formatted);
+
+ table_set_cell_height_max(table, 2);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different lines two lines\n"));
+ formatted = mfree(formatted);
+
+ table_set_cell_height_max(table, 3);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different lines two lines\n"));
+ formatted = mfree(formatted);
+
+ table_set_cell_height_max(table, (size_t) -1);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different lines two lines\n"));
+ formatted = mfree(formatted);
+
+ assert_se(table_add_many(table,
+ TABLE_STRING, "short",
+ TABLE_STRV_WRAPPED, STRV_MAKE("a", "pair")) >= 0);
+
+ assert_se(table_add_many(table,
+ TABLE_STRV_WRAPPED, STRV_MAKE("short2"),
+ TABLE_STRV_WRAPPED, STRV_MAKE("a", "eight", "line", "ćęłł",
+ "___5___", "___6___", "___7___", "___8___")) >= 0);
+
+ table_set_cell_height_max(table, 1);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different… two lines\n"
+ "short a pair\n"
+ "short2 a eight line ćęłł…\n"));
+ formatted = mfree(formatted);
+
+ table_set_cell_height_max(table, 2);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different two lines\n"
+ "lines \n"
+ "short a pair\n"
+ "short2 a eight line ćęłł\n"
+ " ___5___ ___6___…\n"));
+ formatted = mfree(formatted);
+
+ table_set_cell_height_max(table, 3);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different two lines\n"
+ "lines \n"
+ "short a pair\n"
+ "short2 a eight line ćęłł\n"
+ " ___5___ ___6___\n"
+ " ___7___ ___8___\n"));
+ formatted = mfree(formatted);
+ table_set_cell_height_max(table, (size_t) -1);
+ assert_se(table_format(table, &formatted) >= 0);
+ fputs(formatted, stdout);
+ assert_se(streq(formatted,
+ "FOO BAR\n"
+ "three different two lines\n"
+ "lines \n"
+ "short a pair\n"
+ "short2 a eight line ćęłł\n"
+ " ___5___ ___6___\n"
+ " ___7___ ___8___\n"));
+ formatted = mfree(formatted);
+}
+
+int main(int argc, char *argv[]) {
_cleanup_(table_unrefp) Table *t = NULL;
_cleanup_free_ char *formatted = NULL;
test_issue_9549();
test_multiline();
test_strv();
+ test_strv_wrapped();
return 0;
}
*/
static void do_fstab_filter_options(const char *opts,
- const char *remove,
- int r_expected,
- const char *name_expected,
- const char *value_expected,
- const char *filtered_expected) {
-
+ const char *remove,
+ int r_expected,
+ const char *name_expected,
+ const char *value_expected,
+ const char *filtered_expected) {
int r;
const char *name;
_cleanup_free_ char *value = NULL, *filtered = NULL;
/* also test the malloc-less mode */
r = fstab_filter_options(opts, remove, &name, NULL, NULL);
- log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"",
+ log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"\n-",
opts, r, name,
r_expected, name_expected);
assert_se(r == r_expected);
do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other");
do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other");
+ do_fstab_filter_options("opt=0\\,1,other", "opt\0x-opt\0", 1, "opt", "0,1", "other");
+ do_fstab_filter_options("opt=0,other,x-opt\\,foobar", "x-opt\0opt\0", 1, "opt", "0", "other,x-opt\\,foobar");
+ do_fstab_filter_options("opt,other,x-opt\\,part", "opt\0x-opt\0", 1, "opt", NULL, "other,x-opt\\,part");
+ do_fstab_filter_options("opt,other,part\\,x-opt", "x-opt\0opt\0", 1, "opt", NULL, "other,part\\,x-opt");
+ do_fstab_filter_options("opt,other\\,\\,\\,opt,x-part", "opt\0x-opt\0", 1, "opt", NULL, "other\\,\\,\\,opt,x-part");
+
do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "clean-ipc.h"
-#include "user-util.h"
+#include "errno-util.h"
+#include "main-func.h"
#include "tests.h"
-#include "util.h"
+#include "user-util.h"
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
uid_t uid;
int r;
const char* name = argv[1] ?: NOBODY_USER_NAME;
r = get_user_creds(&name, &uid, NULL, NULL, NULL, 0);
if (r == -ESRCH)
return log_tests_skipped("Failed to resolve user");
- if (r < 0) {
- log_error_errno(r, "Failed to resolve \"%s\": %m", name);
- return EXIT_FAILURE;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to resolve \"%s\": %m", name);
r = clean_ipc_by_uid(uid);
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ if (ERRNO_IS_PRIVILEGE(r))
+ return log_tests_skipped("No privileges");
+
+ return r;
}
+
+DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
log_info("/* %s, device %s */", __func__, syspath);
device = udev_device_new_from_syspath(udev, syspath);
- if (device == NULL)
+ if (!device)
return;
log_info("looking at parents");
log_info("looking up device: '%s:%s'", subsys, dev);
device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
- if (device == NULL)
+ if (!device)
log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
else
print_device(device);
for (i = 0; i < fdcount; i++) {
if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
device = udev_monitor_receive_device(udev_monitor);
- if (device == NULL) {
+ if (!device) {
printf("no device from socket\n");
continue;
}
_cleanup_strv_free_ char **passenv = NULL;
r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "A B",
- &passenv, NULL);
+ "PassEnvironment", 0, "A B",
+ &passenv, NULL);
assert_se(r >= 0);
assert_se(strv_length(passenv) == 2);
assert_se(streq(passenv[0], "A"));
assert_se(streq(passenv[1], "B"));
r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "",
- &passenv, NULL);
+ "PassEnvironment", 0, "",
+ &passenv, NULL);
assert_se(r >= 0);
assert_se(strv_isempty(passenv));
r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
- "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
- &passenv, NULL);
+ "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 'special_name$$' \\",
+ &passenv, NULL);
assert_se(r >= 0);
- assert_se(strv_length(passenv) == 1);
+ assert_se(strv_length(passenv) == 2);
assert_se(streq(passenv[0], "normal_name"));
-
+ assert_se(streq(passenv[1], "special_name$$"));
}
static void test_unit_dump_config_items(void) {
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <sched.h>
#include <sys/mount.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
+ /* let's move into our own mount namespace with all propagation from the host turned off, so that
+ * /proc/self/mountinfo is static and constant for the whole time our test runs. */
+ if (unshare(CLONE_NEWNS) < 0) {
+ if (!ERRNO_IS_PRIVILEGE(errno))
+ return log_error_errno(errno, "Failed to detach mount namespace: %m");
+
+ log_notice("Lacking privilege to create separate mount namespace, proceeding in originating mount namespace.");
+ } else
+ assert_se(mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) >= 0);
+
test_mount_propagation_flags("shared", 0, MS_SHARED);
test_mount_propagation_flags("slave", 0, MS_SLAVE);
test_mount_propagation_flags("private", 0, MS_PRIVATE);
c = strjoina(a, "/tmp");
assert_se(stat(c, &x) >= 0);
assert_se(S_ISDIR(x.st_mode));
- assert_se((x.st_mode & 01777) == 01777);
+ assert_se(FLAGS_SET(x.st_mode, 01777));
assert_se(rmdir(c) >= 0);
assert_se(rmdir(a) >= 0);
}
d = strjoina(b, "/tmp");
assert_se(stat(d, &y) >= 0);
assert_se(S_ISDIR(y.st_mode));
- assert_se((y.st_mode & 01777) == 01777);
+ assert_se(FLAGS_SET(y.st_mode, 01777));
assert_se(rmdir(d) >= 0);
assert_se(rmdir(b) >= 0);
}
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
+#include <linux/loadavg.h>
#include <locale.h>
#include <math.h>
#include <sys/socket.h>
assert_se(parse_mtu(AF_UNSPEC, "", &mtu) == -EINVAL);
}
+static void test_parse_loadavg_fixed_point(void) {
+ loadavg_t fp;
+
+ assert_se(parse_loadavg_fixed_point("1.23", &fp) == 0);
+ assert_se(LOAD_INT(fp) == 1);
+ assert_se(LOAD_FRAC(fp) == 23);
+
+ assert_se(parse_loadavg_fixed_point("1.80", &fp) == 0);
+ assert_se(LOAD_INT(fp) == 1);
+ assert_se(LOAD_FRAC(fp) == 80);
+
+ assert_se(parse_loadavg_fixed_point("0.07", &fp) == 0);
+ assert_se(LOAD_INT(fp) == 0);
+ assert_se(LOAD_FRAC(fp) == 7);
+
+ assert_se(parse_loadavg_fixed_point("0.00", &fp) == 0);
+ assert_se(LOAD_INT(fp) == 0);
+ assert_se(LOAD_FRAC(fp) == 0);
+
+ assert_se(parse_loadavg_fixed_point("4096.57", &fp) == 0);
+ assert_se(LOAD_INT(fp) == 4096);
+ assert_se(LOAD_FRAC(fp) == 57);
+
+ /* Caps out at 2 digit fracs */
+ assert_se(parse_loadavg_fixed_point("1.100", &fp) == -ERANGE);
+
+ assert_se(parse_loadavg_fixed_point("4096.4096", &fp) == -ERANGE);
+ assert_se(parse_loadavg_fixed_point("-4000.5", &fp) == -ERANGE);
+ assert_se(parse_loadavg_fixed_point("18446744073709551615.5", &fp) == -ERANGE);
+ assert_se(parse_loadavg_fixed_point("foobar", &fp) == -EINVAL);
+ assert_se(parse_loadavg_fixed_point("3333", &fp) == -EINVAL);
+ assert_se(parse_loadavg_fixed_point("1.2.3", &fp) == -EINVAL);
+ assert_se(parse_loadavg_fixed_point(".", &fp) == -EINVAL);
+ assert_se(parse_loadavg_fixed_point("", &fp) == -EINVAL);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
test_parse_errno();
test_parse_syscall_and_errno();
test_parse_mtu();
+ test_parse_loadavg_fixed_point();
return 0;
}
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdbool.h>
-#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
return SERVICE(service_unit);
}
-static void check_states(Manager *m, Path *path, Service *service, PathState path_state, ServiceState service_state) {
+static int _check_states(unsigned line,
+ Manager *m, Path *path, Service *service, PathState path_state, ServiceState service_state) {
assert_se(m);
assert_se(service);
usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC;
- while (path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS ||
- path->state != path_state || service->state != service_state) {
+ while (path->state != path_state || service->state != service_state ||
+ path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS) {
assert_se(sd_event_run(m->event, 100 * USEC_PER_MSEC) >= 0);
- printf("%s: state = %s; result = %s \n",
- UNIT(path)->id,
- path_state_to_string(path->state),
- path_result_to_string(path->result));
- printf("%s: state = %s; result = %s \n",
- UNIT(service)->id,
- service_state_to_string(service->state),
- service_result_to_string(service->result));
-
- if (now(CLOCK_MONOTONIC) >= end) {
+ usec_t n = now(CLOCK_MONOTONIC);
+ log_info("line %u: %s: state = %s; result = %s (left: %" PRIi64 ")",
+ line,
+ UNIT(path)->id,
+ path_state_to_string(path->state),
+ path_result_to_string(path->result),
+ end - n);
+ log_info("line %u: %s: state = %s; result = %s",
+ line,
+ UNIT(service)->id,
+ service_state_to_string(service->state),
+ service_result_to_string(service->result));
+
+ if (service->state == SERVICE_FAILED &&
+ service->main_exec_status.status == EXIT_CGROUP &&
+ !ci_environment())
+ /* On a general purpose system we may fail to start the service for reasons which are
+ * not under our control: permission limits, resource exhaustion, etc. Let's skip the
+ * test in those cases. On developer machines we require proper setup. */
+ return log_notice_errno(SYNTHETIC_ERRNO(ECANCELED),
+ "Failed to start service %s, aborting test: %s/%s",
+ UNIT(service)->id,
+ service_state_to_string(service->state),
+ service_result_to_string(service->result));
+
+ if (n >= end) {
log_error("Test timeout when testing %s", UNIT(path)->id);
exit(EXIT_FAILURE);
}
}
+
+ return 0;
}
+#define check_states(...) _check_states(__LINE__, __VA_ARGS__)
static void test_path_exists(Manager *m) {
const char *test_path = "/tmp/test-path_exists";
service = service_for_path(m, path, NULL);
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(touch(test_path) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
/* Service restarts if file still exists */
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(unit_stop(unit) >= 0);
}
service = service_for_path(m, path, NULL);
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(touch(test_path) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
/* Service restarts if file still exists */
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(unit_stop(unit) >= 0);
}
service = service_for_path(m, path, NULL);
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(touch(test_path) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
/* Service does not restart if file still exists */
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
f = fopen(test_path, "w");
assert_se(f);
fclose(f);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
assert_se(unit_stop(unit) >= 0);
service = service_for_path(m, path, NULL);
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(touch(test_path) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
/* Service does not restart if file still exists */
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
f = fopen(test_path, "w");
assert_se(f);
fputs("test", f);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
assert_se(unit_stop(unit) >= 0);
service = service_for_path(m, path, "path-mycustomunit.service");
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(touch(test_path) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(unit_stop(unit) >= 0);
}
assert_se(access(test_path, F_OK) < 0);
assert_se(unit_start(unit) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
/* MakeDirectory default to no */
assert_se(access(test_path, F_OK) < 0);
assert_se(mkdir_p(test_path, 0755) >= 0);
assert_se(touch(strjoina(test_path, "test_file")) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
/* Service restarts if directory is still not empty */
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING);
+ if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
+ return;
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
assert_se(unit_stop(UNIT(service)) >= 0);
- check_states(m, path, service, PATH_WAITING, SERVICE_DEAD);
+ if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
+ return;
assert_se(unit_stop(unit) >= 0);
}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <linux/loadavg.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "psi-util.h"
+#include "tests.h"
+
+static void test_read_mem_pressure(void) {
+ _cleanup_(unlink_tempfilep) char path[] = "/tmp/pressurereadtestXXXXXX";
+ ResourcePressure rp;
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ assert_se(mkstemp(path));
+
+ assert_se(read_resource_pressure("/verylikelynonexistentpath", PRESSURE_TYPE_SOME, &rp) < 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0);
+
+ assert_se(write_string_file(path, "herpdederp\n", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0);
+
+ /* Pressure file with some invalid values*/
+ assert_se(write_string_file(path, "some avg10=0.22=55 avg60=0.17=8 avg300=1.11=00 total=58761459\n"
+ "full avg10=0.23=55 avg60=0.16=8 avg300=1.08=00 total=58464525", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0);
+
+ /* Same pressure valid values as below but with duplicate avg60 field */
+ assert_se(write_string_file(path, "some avg10=0.22 avg60=0.17 avg60=0.18 avg300=1.11 total=58761459\n"
+ "full avg10=0.23 avg60=0.16 avg300=1.08 total=58464525", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0);
+
+ assert_se(write_string_file(path, "some avg10=0.22 avg60=0.17 avg300=1.11 total=58761459\n"
+ "full avg10=0.23 avg60=0.16 avg300=1.08 total=58464525", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) == 0);
+ assert_se(LOAD_INT(rp.avg10) == 0);
+ assert_se(LOAD_FRAC(rp.avg10) == 22);
+ assert_se(LOAD_INT(rp.avg60) == 0);
+ assert_se(LOAD_FRAC(rp.avg60) == 17);
+ assert_se(LOAD_INT(rp.avg300) == 1);
+ assert_se(LOAD_FRAC(rp.avg300) == 11);
+ assert_se(rp.total == 58761459);
+ assert(read_resource_pressure(path, PRESSURE_TYPE_FULL, &rp) == 0);
+ assert_se(LOAD_INT(rp.avg10) == 0);
+ assert_se(LOAD_FRAC(rp.avg10) == 23);
+ assert_se(LOAD_INT(rp.avg60) == 0);
+ assert_se(LOAD_FRAC(rp.avg60) == 16);
+ assert_se(LOAD_INT(rp.avg300) == 1);
+ assert_se(LOAD_FRAC(rp.avg300) == 8);
+ assert_se(rp.total == 58464525);
+
+ /* Pressure file with extra unsupported fields */
+ assert_se(write_string_file(path, "some avg5=0.55 avg10=0.22 avg60=0.17 avg300=1.11 total=58761459\n"
+ "full avg10=0.23 avg60=0.16 avg300=1.08 avg600=2.00 total=58464525", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) == 0);
+ assert_se(LOAD_INT(rp.avg10) == 0);
+ assert_se(LOAD_FRAC(rp.avg10) == 22);
+ assert_se(LOAD_INT(rp.avg60) == 0);
+ assert_se(LOAD_FRAC(rp.avg60) == 17);
+ assert_se(LOAD_INT(rp.avg300) == 1);
+ assert_se(LOAD_FRAC(rp.avg300) == 11);
+ assert_se(rp.total == 58761459);
+ assert(read_resource_pressure(path, PRESSURE_TYPE_FULL, &rp) == 0);
+ assert_se(LOAD_INT(rp.avg10) == 0);
+ assert_se(LOAD_FRAC(rp.avg10) == 23);
+ assert_se(LOAD_INT(rp.avg60) == 0);
+ assert_se(LOAD_FRAC(rp.avg60) == 16);
+ assert_se(LOAD_INT(rp.avg300) == 1);
+ assert_se(LOAD_FRAC(rp.avg300) == 8);
+ assert_se(rp.total == 58464525);
+}
+
+int main(void) {
+ test_setup_logging(LOG_DEBUG);
+ test_read_mem_pressure();
+ return 0;
+}
}
static void test_strv_join(void) {
- _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
-
log_info("/* %s */", __func__);
- p = strv_join((char **)input_table_multiple, ", ");
+ _cleanup_free_ char *p = strv_join((char **)input_table_multiple, ", ");
assert_se(p);
assert_se(streq(p, "one, two, three"));
- q = strv_join((char **)input_table_multiple, ";");
+ _cleanup_free_ char *q = strv_join((char **)input_table_multiple, ";");
assert_se(q);
assert_se(streq(q, "one;two;three"));
- r = strv_join((char **)input_table_multiple, NULL);
+ _cleanup_free_ char *r = strv_join((char **)input_table_multiple, NULL);
assert_se(r);
assert_se(streq(r, "one two three"));
- s = strv_join((char **)input_table_one, ", ");
+ _cleanup_free_ char *s = strv_join(STRV_MAKE("1", "2", "3,3"), ",");
assert_se(s);
- assert_se(streq(s, "one"));
+ assert_se(streq(s, "1,2,3,3"));
- t = strv_join((char **)input_table_none, ", ");
+ _cleanup_free_ char *t = strv_join((char **)input_table_one, ", ");
assert_se(t);
- assert_se(streq(t, ""));
+ assert_se(streq(t, "one"));
+
+ _cleanup_free_ char *u = strv_join((char **)input_table_none, ", ");
+ assert_se(u);
+ assert_se(streq(u, ""));
- v = strv_join((char **)input_table_two_empties, ", ");
+ _cleanup_free_ char *v = strv_join((char **)input_table_two_empties, ", ");
assert_se(v);
assert_se(streq(v, ", "));
- w = strv_join((char **)input_table_one_empty, ", ");
+ _cleanup_free_ char *w = strv_join((char **)input_table_one_empty, ", ");
assert_se(w);
assert_se(streq(w, ""));
}
-static void test_strv_join_prefix(void) {
- _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
-
+static void test_strv_join_full(void) {
log_info("/* %s */", __func__);
- p = strv_join_prefix((char **)input_table_multiple, ", ", "foo");
+ _cleanup_free_ char *p = strv_join_full((char **)input_table_multiple, ", ", "foo", false);
assert_se(p);
assert_se(streq(p, "fooone, footwo, foothree"));
- q = strv_join_prefix((char **)input_table_multiple, ";", "foo");
+ _cleanup_free_ char *q = strv_join_full((char **)input_table_multiple, ";", "foo", false);
assert_se(q);
assert_se(streq(q, "fooone;footwo;foothree"));
- r = strv_join_prefix((char **)input_table_multiple, NULL, "foo");
+ _cleanup_free_ char *r = strv_join_full(STRV_MAKE("a", "a;b", "a:c"), ";", NULL, true);
assert_se(r);
- assert_se(streq(r, "fooone footwo foothree"));
+ assert_se(streq(r, "a;a\\;b;a:c"));
- s = strv_join_prefix((char **)input_table_one, ", ", "foo");
+ _cleanup_free_ char *s = strv_join_full(STRV_MAKE("a", "a;b", "a;;c", ";", ";x"), ";", NULL, true);
assert_se(s);
- assert_se(streq(s, "fooone"));
+ assert_se(streq(s, "a;a\\;b;a\\;\\;c;\\;;\\;x"));
- t = strv_join_prefix((char **)input_table_none, ", ", "foo");
+ _cleanup_free_ char *t = strv_join_full(STRV_MAKE("a", "a;b", "a:c", ";"), ";", "=", true);
assert_se(t);
- assert_se(streq(t, ""));
+ assert_se(streq(t, "=a;=a\\;b;=a:c;=\\;"));
+ t = mfree(t);
+
+ _cleanup_free_ char *u = strv_join_full((char **)input_table_multiple, NULL, "foo", false);
+ assert_se(u);
+ assert_se(streq(u, "fooone footwo foothree"));
- v = strv_join_prefix((char **)input_table_two_empties, ", ", "foo");
+ _cleanup_free_ char *v = strv_join_full((char **)input_table_one, ", ", "foo", false);
assert_se(v);
- assert_se(streq(v, "foo, foo"));
+ assert_se(streq(v, "fooone"));
- w = strv_join_prefix((char **)input_table_one_empty, ", ", "foo");
+ _cleanup_free_ char *w = strv_join_full((char **)input_table_none, ", ", "foo", false);
assert_se(w);
- assert_se(streq(w, "foo"));
+ assert_se(streq(w, ""));
+
+ _cleanup_free_ char *x = strv_join_full((char **)input_table_two_empties, ", ", "foo", false);
+ assert_se(x);
+ assert_se(streq(x, "foo, foo"));
+
+ _cleanup_free_ char *y = strv_join_full((char **)input_table_one_empty, ", ", "foo", false);
+ assert_se(y);
+ assert_se(streq(y, "foo"));
}
static void test_strv_unquote(const char *quoted, char **list) {
test_strv_find_prefix();
test_strv_find_startswith();
test_strv_join();
- test_strv_join_prefix();
+ test_strv_join_full();
test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
test_strv_unquote("", STRV_MAKE_EMPTY);
#include "architecture.h"
#include "automount.h"
#include "cgroup.h"
+#include "cgroup-util.h"
#include "compress.h"
#include "condition.h"
#include "device-private.h"
test_table(locale_variable, VARIABLE_LC);
test_table(log_target, LOG_TARGET);
test_table(mac_address_policy, MAC_ADDRESS_POLICY);
+ test_table(managed_oom_mode, MANAGED_OOM_MODE);
test_table(manager_state, MANAGER_STATE);
test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "format-util.h"
+#include "fs-util.h"
+#include "tmpfile-util.h"
+#include "tests.h"
+#include "user-record.h"
+
+static void test_read_login_defs(const char *path) {
+ log_info("/* %s(\"%s\") */", __func__, path ?: "<custom>");
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-user-record.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+ if (!path) {
+ assert_se(fmkostemp_safe(name, "r+", &f) == 0);
+ fprintf(f,
+ "SYS_UID_MIN "UID_FMT"\n"
+ "SYS_UID_MAX "UID_FMT"\n"
+ "SYS_GID_MIN "GID_FMT"\n"
+ "SYS_GID_MAX "GID_FMT"\n",
+ SYSTEM_ALLOC_UID_MIN + 5,
+ SYSTEM_UID_MAX + 5,
+ SYSTEM_ALLOC_GID_MIN + 5,
+ SYSTEM_GID_MAX + 5);
+ assert_se(fflush_and_check(f) >= 0);
+ }
+
+ UGIDAllocationRange defs;
+ assert_se(read_login_defs(&defs, path ?: name, NULL) >= 0);
+
+ log_info("system_alloc_uid_min="UID_FMT, defs.system_alloc_uid_min);
+ log_info("system_uid_max="UID_FMT, defs.system_uid_max);
+ log_info("system_alloc_gid_min="GID_FMT, defs.system_alloc_gid_min);
+ log_info("system_gid_max="GID_FMT, defs.system_gid_max);
+
+ if (!path) {
+ uid_t offset = ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES ? 5 : 0;
+ assert_se(defs.system_alloc_uid_min == SYSTEM_ALLOC_UID_MIN + offset);
+ assert_se(defs.system_uid_max == SYSTEM_UID_MAX + offset);
+ assert_se(defs.system_alloc_gid_min == SYSTEM_ALLOC_GID_MIN + offset);
+ assert_se(defs.system_gid_max == SYSTEM_GID_MAX + offset);
+ } else if (streq(path, "/dev/null")) {
+ assert_se(defs.system_alloc_uid_min == SYSTEM_ALLOC_UID_MIN);
+ assert_se(defs.system_uid_max == SYSTEM_UID_MAX);
+ assert_se(defs.system_alloc_gid_min == SYSTEM_ALLOC_GID_MIN);
+ assert_se(defs.system_gid_max == SYSTEM_GID_MAX);
+ }
+}
+
+static void test_acquire_ugid_allocation_range(void) {
+ log_info("/* %s */", __func__);
+
+ const UGIDAllocationRange *defs;
+ assert_se(defs = acquire_ugid_allocation_range());
+
+ log_info("system_alloc_uid_min="UID_FMT, defs->system_alloc_uid_min);
+ log_info("system_uid_max="UID_FMT, defs->system_uid_max);
+ log_info("system_alloc_gid_min="GID_FMT, defs->system_alloc_gid_min);
+ log_info("system_gid_max="GID_FMT, defs->system_gid_max);
+}
+
+static void test_uid_is_system(void) {
+ log_info("/* %s */", __func__);
+
+ uid_t uid = 0;
+ log_info("uid_is_system("UID_FMT") = %s", uid, yes_no(uid_is_system(uid)));
+
+ uid = 999;
+ log_info("uid_is_system("UID_FMT") = %s", uid, yes_no(uid_is_system(uid)));
+
+ uid = getuid();
+ log_info("uid_is_system("UID_FMT") = %s", uid, yes_no(uid_is_system(uid)));
+}
+
+static void test_gid_is_system(void) {
+ log_info("/* %s */", __func__);
+
+ gid_t gid = 0;
+ log_info("gid_is_system("GID_FMT") = %s", gid, yes_no(gid_is_system(gid)));
+
+ gid = 999;
+ log_info("gid_is_system("GID_FMT") = %s", gid, yes_no(gid_is_system(gid)));
+
+ gid = getgid();
+ log_info("gid_is_system("GID_FMT") = %s", gid, yes_no(gid_is_system(gid)));
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_read_login_defs("/dev/null");
+ test_read_login_defs("/etc/login.defs");
+ test_read_login_defs(NULL);
+ test_acquire_ugid_allocation_range();
+ test_uid_is_system();
+ test_gid_is_system();
+
+ return 0;
+}
int a, b, c, *i;
size_t k = 0;
+ log_info("/* %s */", __func__);
+
FOREACH_POINTER(i, &a, &b, &c) {
switch (k) {
assert(k == 11);
}
+static void test_ptr_to_int(void) {
+ log_info("/* %s */", __func__);
+
+ /* Primary reason to have this test is to validate that pointers are large enough to hold entire int range */
+ assert_se(PTR_TO_INT(INT_TO_PTR(0)) == 0);
+ assert_se(PTR_TO_INT(INT_TO_PTR(1)) == 1);
+ assert_se(PTR_TO_INT(INT_TO_PTR(-1)) == -1);
+ assert_se(PTR_TO_INT(INT_TO_PTR(INT_MAX)) == INT_MAX);
+ assert_se(PTR_TO_INT(INT_TO_PTR(INT_MIN)) == INT_MIN);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_system_tasks_max();
test_system_tasks_max_scale();
test_foreach_pointer();
+ test_ptr_to_int();
return 0;
}
if (r < 0)
log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
#else
- log_warning_errno(SYNTHETIC_ERRNO(ENOSYS), "ACLs are not supported. Ignoring");
+ log_warning("ACLs are not supported. Ignoring.");
#endif
return 0;
if (fstat(fd, &stbuf) < 0)
return log_error_errno(errno, "stat(%s) failed: %m", path);
- if (!S_ISREG(stbuf.st_mode)) {
- log_error("%s exists and is not a regular file.", path);
- return -EEXIST;
- }
+ if (!S_ISREG(stbuf.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "%s exists and is not a regular file.",
+ path);
st = &stbuf;
} else {
fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode);
if (fd < 0) {
- if (errno == ENOENT) {
- log_error("Cannot create file %s on a read-only file system.", path);
- return -EROFS;
- }
+ if (errno == ENOENT)
+ return log_error_errno(SYNTHETIC_ERRNO(EROFS),
+ "Cannot create file %s on a read-only file system.",
+ path);
return log_error_errno(errno, "Failed to re-open file %s: %m", path);
}
if (fstat(fd, &stbuf) < 0)
return log_error_errno(errno, "stat(%s) failed: %m", path);
- if (!S_ISREG(stbuf.st_mode)) {
- log_error("%s exists and is not a regular file.", path);
- return -EEXIST;
- }
+ if (!S_ISREG(stbuf.st_mode))
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "%s exists and is not a regular file.",
+ path);
if (stbuf.st_size > 0) {
if (ftruncate(fd, 0) < 0) {
break;
case ARG_IMAGE:
+#ifdef STANDALONE
+ 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);
if (r < 0)
return r;
-
- /* Imply -E here since it makes little sense to create files persistently in the /run mointpoint of a disk image */
+#endif
+ /* Imply -E here since it makes little sense to create files persistently in the /run mountpoint of a disk image */
_fallthrough_;
case 'E':
ItemArray, item_array_free);
static int run(int argc, char *argv[]) {
+#ifndef STANDALONE
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
+#endif
_cleanup_strv_free_ char **config_dirs = NULL;
bool invalid_config = false;
ItemArray *a;
if (r < 0)
return r;
+#ifndef STANDALONE
if (arg_image) {
assert(!arg_root);
if (!arg_root)
return log_oom();
}
+#else
+ assert(!arg_image);
+#endif
items = ordered_hashmap_new(&item_array_hash_ops);
globs = ordered_hashmap_new(&item_array_hash_ops);
#include "conf-files.h"
#include "conf-parser.h"
#include "def.h"
+#include "device-private.h"
#include "device-util.h"
#include "ethtool-util.h"
#include "fd-util.h"
}
int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
+ unsigned name_assign_type = NET_NAME_UNKNOWN;
struct ether_addr permanent_mac = {};
unsigned short iftype = 0;
link_config *link;
if (r < 0)
log_device_debug_errno(device, r, "Failed to get permanent MAC address, ignoring: %m");
+ (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
+
LIST_FOREACH(links, link, ctx->links) {
if (net_match_config(link->match_mac, link->match_permanent_mac, link->match_path, link->match_driver,
link->match_type, link->match_name, link->match_property, NULL, NULL, NULL,
device, NULL, &permanent_mac, NULL, iftype, NULL, NULL, 0, NULL, NULL)) {
- if (link->match_name && !strv_contains(link->match_name, "*")) {
- unsigned name_assign_type = NET_NAME_UNKNOWN;
- (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
+ if (link->match_name && !strv_contains(link->match_name, "*") && name_assign_type == NET_NAME_ENUM)
+ log_device_warning(device, "Config file %s is applied to device based on potentially unpredictable interface name.",
+ link->filename);
+ else
+ log_device_debug(device, "Config file %s is applied", link->filename);
- if (name_assign_type == NET_NAME_ENUM) {
- log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name",
- link->filename);
- *ret = link;
+ *ret = link;
+ return 0;
+ }
+ }
- return 0;
- } else if (name_assign_type == NET_NAME_RENAMED) {
- log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring",
- link->filename);
+ return -ENOENT;
+}
- continue;
- }
- }
+static int link_config_apply_ethtool_settings(int *ethtool_fd, const link_config *config, sd_device *device) {
+ const char *name;
+ int r;
- log_device_debug(device, "Config file %s is applied", link->filename);
+ assert(ethtool_fd);
+ assert(config);
+ assert(device);
- *ret = link;
- return 0;
+ r = sd_device_get_sysname(device, &name);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get sysname: %m");
+
+ r = ethtool_set_glinksettings(ethtool_fd, name,
+ config->autonegotiation, config->advertise,
+ config->speed, config->duplex, config->port);
+ if (r < 0) {
+ if (config->port != _NET_DEV_PORT_INVALID)
+ log_device_warning_errno(device, r, "Could not set port '%s', ignoring: %m", port_to_string(config->port));
+
+ if (!eqzero(config->advertise))
+ log_device_warning_errno(device, r, "Could not set advertise mode, ignoring: %m"); /* TODO: include modes in the log message. */
+
+ if (config->speed) {
+ unsigned speed = DIV_ROUND_UP(config->speed, 1000000);
+ if (r == -EOPNOTSUPP) {
+ r = ethtool_set_speed(ethtool_fd, name, speed, config->duplex);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set speed to %uMbps, ignoring: %m", speed);
+ }
}
+
+ if (config->duplex != _DUP_INVALID)
+ log_device_warning_errno(device, r, "Could not set duplex to %s, ignoring: %m", duplex_to_string(config->duplex));
}
- *ret = NULL;
- return -ENOENT;
+ r = ethtool_set_wol(ethtool_fd, name, config->wol);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set WakeOnLan to %s, ignoring: %m", wol_to_string(config->wol));
+
+ r = ethtool_set_features(ethtool_fd, name, config->features);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set offload features, ignoring: %m");
+
+ if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
+ r = ethtool_set_channels(ethtool_fd, name, &config->channels);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set channels, ignoring: %m");
+ }
+
+ if (config->ring.rx_pending_set || config->ring.rx_mini_pending_set || config->ring.rx_jumbo_pending_set || config->ring.tx_pending_set) {
+ r = ethtool_set_nic_buffer_size(ethtool_fd, name, &config->ring);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set ring buffer, ignoring: %m");
+ }
+
+ if (config->rx_flow_control >= 0 || config->tx_flow_control >= 0 || config->autoneg_flow_control >= 0) {
+ r = ethtool_set_flow_control(ethtool_fd, name, config->rx_flow_control, config->tx_flow_control, config->autoneg_flow_control);
+ if (r < 0)
+ log_device_warning_errno(device, r, "Could not set flow control, ignoring: %m");
+ }
+
+ return 0;
}
static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) {
return 1;
}
-int link_config_apply(link_config_ctx *ctx, link_config *config,
- sd_device *device, const char **name) {
- _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL;
- struct ether_addr generated_mac;
- struct ether_addr *mac = NULL;
- const char *new_name = NULL;
- const char *old_name;
- unsigned speed, name_type = NET_NAME_UNKNOWN;
- NamePolicy policy;
- int r, ifindex;
+static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config *config, sd_device *device) {
+ struct ether_addr generated_mac, *mac = NULL;
+ int ifindex, r;
- assert(ctx);
+ assert(rtnl);
assert(config);
assert(device);
- assert(name);
- r = sd_device_get_sysname(device, &old_name);
+ r = sd_device_get_ifindex(device, &ifindex);
if (r < 0)
- return r;
+ return log_device_error_errno(device, r, "Could not find ifindex: %m");
- r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name,
- config->autonegotiation, config->advertise,
- config->speed, config->duplex, config->port);
- if (r < 0) {
-
- if (config->port != _NET_DEV_PORT_INVALID)
- log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name);
-
- if (!eqzero(config->advertise))
- log_warning_errno(r, "Could not set advertise mode: %m"); /* TODO: include modes in the log message. */
-
- if (config->speed) {
- speed = DIV_ROUND_UP(config->speed, 1000000);
- if (r == -EOPNOTSUPP) {
- r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex);
- if (r < 0)
- log_warning_errno(r, "Could not set speed of %s to %u Mbps: %m", old_name, speed);
- }
- }
-
- if (config->duplex != _DUP_INVALID)
- log_warning_errno(r, "Could not set duplex of %s to %s: %m", old_name, duplex_to_string(config->duplex));
- }
-
- r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
- if (r < 0)
- log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
- old_name, wol_to_string(config->wol));
+ if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) {
+ if (get_mac(device, config->mac_address_policy, &generated_mac) > 0)
+ mac = &generated_mac;
+ } else
+ mac = config->mac;
- r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features);
+ r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->mtu);
if (r < 0)
- log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
-
- if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
- r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
- if (r < 0)
- log_warning_errno(r, "Could not set channels of %s: %m", old_name);
- }
+ log_device_warning_errno(device, r, "Could not set Alias=, MACAddress= or MTU=, ignoring: %m");
- if (config->ring.rx_pending_set || config->ring.rx_mini_pending_set || config->ring.rx_jumbo_pending_set || config->ring.tx_pending_set) {
- r = ethtool_set_nic_buffer_size(&ctx->ethtool_fd, old_name, &config->ring);
- if (r < 0)
- log_warning_errno(r, "Could not set ring buffer of %s: %m", old_name);
- }
+ return 0;
+}
- if (config->rx_flow_control >= 0 || config->tx_flow_control >= 0 || config->autoneg_flow_control >= 0) {
- r = ethtool_set_flow_control(&ctx->ethtool_fd, old_name, config->rx_flow_control, config->tx_flow_control, config->autoneg_flow_control);
- if (r < 0)
- log_warning_errno(r, "Could not set flow control of %s: %m", old_name);
- }
+static int link_config_generate_new_name(const link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) {
+ unsigned name_type = NET_NAME_UNKNOWN;
+ const char *new_name = NULL;
+ NamePolicy policy;
+ int r;
- r = sd_device_get_ifindex(device, &ifindex);
- if (r < 0)
- return log_device_warning_errno(device, r, "Could not find ifindex: %m");
+ assert(ctx);
+ assert(config);
+ assert(device);
+ assert(ret_name);
(void) link_unsigned_attribute(device, "name_assign_type", &name_type);
break;
}
- if (new_name)
+ if (new_name) {
log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name);
- else if (config->name) {
- new_name = config->name;
- log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name);
- } else
- log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
- no_rename:
+ *ret_name = new_name;
+ return 0;
+ }
- if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) {
- if (get_mac(device, config->mac_address_policy, &generated_mac) > 0)
- mac = &generated_mac;
- } else
- mac = config->mac;
+ if (config->name) {
+ log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", config->name);
+ *ret_name = config->name;
+ return 0;
+ }
+
+ log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
+no_rename:
+ r = sd_device_get_sysname(device, ret_name);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get sysname: %m");
+
+ return 0;
+}
+
+static int link_config_apply_alternative_names(sd_netlink **rtnl, const link_config *config, sd_device *device, const char *new_name) {
+ _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL;
+ const char *current_name;
+ int ifindex, r;
+
+ assert(rtnl);
+ assert(config);
+ assert(device);
+
+ r = sd_device_get_sysname(device, ¤t_name);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get sysname: %m");
- r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
+ r = sd_device_get_ifindex(device, &ifindex);
if (r < 0)
- return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
+ return log_device_error_errno(device, r, "Could not find ifindex: %m");
if (config->alternative_names) {
altnames = strv_copy(config->alternative_names);
if (new_name)
strv_remove(altnames, new_name);
- strv_remove(altnames, old_name);
+ strv_remove(altnames, current_name);
- r = rtnl_get_link_alternative_names(&ctx->rtnl, ifindex, ¤t_altnames);
+ r = rtnl_get_link_alternative_names(rtnl, ifindex, ¤t_altnames);
if (r < 0)
- log_debug_errno(r, "Failed to get alternative names on %s, ignoring: %m", old_name);
+ log_device_debug_errno(device, r, "Failed to get alternative names, ignoring: %m");
char **p;
STRV_FOREACH(p, current_altnames)
strv_uniq(altnames);
strv_sort(altnames);
- r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, altnames);
- if (r == -EOPNOTSUPP)
- log_debug_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s, ignoring: %m", old_name);
- else if (r < 0)
- return log_warning_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s: %m", old_name);
+ r = rtnl_set_link_alternative_names(rtnl, ifindex, altnames);
+ if (r < 0)
+ log_device_full_errno(device, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
+ "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
+
+ return 0;
+}
+
+int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) {
+ const char *new_name;
+ DeviceAction a;
+ int r;
+
+ assert(ctx);
+ assert(config);
+ assert(device);
+ assert(ret_name);
+
+ r = device_get_action(device, &a);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get ACTION= property: %m");
+
+ if (!IN_SET(a, DEVICE_ACTION_ADD, DEVICE_ACTION_BIND, DEVICE_ACTION_MOVE)) {
+ log_device_debug(device, "Skipping to apply .link settings on '%s' uevent.", device_action_to_string(a));
- *name = new_name;
+ r = sd_device_get_sysname(device, ret_name);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get sysname: %m");
+
+ return 0;
+ }
+
+ r = link_config_apply_ethtool_settings(&ctx->ethtool_fd, config, device);
+ if (r < 0)
+ return r;
+
+ r = link_config_apply_rtnl_settings(&ctx->rtnl, config, device);
+ if (r < 0)
+ return r;
+
+ if (a == DEVICE_ACTION_MOVE) {
+ log_device_debug(device, "Skipping to apply Name= and NamePolicy= on '%s' uevent.", device_action_to_string(a));
+
+ r = sd_device_get_sysname(device, &new_name);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get sysname: %m");
+ } else {
+ r = link_config_generate_new_name(ctx, config, device, &new_name);
+ if (r < 0)
+ return r;
+ }
+
+ r = link_config_apply_alternative_names(&ctx->rtnl, config, device, new_name);
+ if (r < 0)
+ return r;
+ *ret_name = new_name;
return 0;
}
int link_config_load(link_config_ctx *ctx);
bool link_config_should_reload(link_config_ctx *ctx);
-int link_config_get(link_config_ctx *ctx, sd_device *device, struct link_config **ret);
-int link_config_apply(link_config_ctx *ctx, struct link_config *config, sd_device *device, const char **name);
+int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret);
+int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name);
int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret);
const char *name_policy_to_string(NamePolicy p) _const_;
retval = -1;
break;
}
- if (vendor == NULL) {
+ if (!vendor) {
if (!vendor_in)
break;
} else if (vendor_in &&
static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) {
struct input_absinfo absinfo;
const char *next;
- int r;
- r = ioctl(fd, EVIOCGABS(evcode), &absinfo);
- if (r < 0)
+ if (ioctl(fd, EVIOCGABS(evcode), &absinfo) < 0)
return log_device_error_errno(dev, errno, "Failed to call EVIOCGABS");
next = parse_token(value, &absinfo.minimum);
next = parse_token(next, &absinfo.fuzz);
next = parse_token(next, &absinfo.flat);
if (!next)
- return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse EV_ABS override '%s'", value);
+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse EV_ABS override '%s'", value);
log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32,
evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat);
- r = ioctl(fd, EVIOCSABS(evcode), &absinfo);
- if (r < 0)
+ if (ioctl(fd, EVIOCSABS(evcode), &absinfo) < 0)
return log_device_error_errno(dev, errno, "Failed to call EVIOCSABS");
return 0;
return streq(a, "1");
}
+static bool is_pci_bridge(sd_device *dev) {
+ const char *v, *p;
+
+ if (sd_device_get_sysattr_value(dev, "modalias", &v) < 0)
+ return false;
+
+ if (!startswith(v, "pci:"))
+ return false;
+
+ p = strrchr(v, 's');
+ if (!p)
+ return false;
+ if (p[1] != 'c')
+ return false;
+
+ /* PCI device subclass 04 corresponds to PCI bridge */
+ return strneq(p + 2, "04", 2);
+}
+
static int dev_pci_slot(sd_device *dev, struct netnames *names) {
unsigned long dev_port = 0;
- unsigned domain, bus, slot, func, hotplug_slot = 0;
+ unsigned domain, bus, slot, func;
+ int hotplug_slot = -1;
size_t l;
char *s;
const char *sysname, *attr, *port_name = NULL, *syspath;
continue;
FOREACH_DIRENT_ALL(dent, dir, break) {
- unsigned i;
+ int i;
char str[PATH_MAX];
_cleanup_free_ char *address = NULL;
if (dot_or_dot_dot(dent->d_name))
continue;
- r = safe_atou_full(dent->d_name, 10, &i);
+ r = safe_atoi(dent->d_name, &i);
if (r < 0 || i <= 0)
continue;
read_one_line_file(str, &address) >= 0 &&
startswith(sysname, address)) {
hotplug_slot = i;
+
+ /* We found the match between PCI device and slot. However, we won't use the
+ * slot index if the device is a PCI bridge, because it can have other child
+ * devices that will try to claim the same index and that would create name
+ * collision. */
+ if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev))
+ hotplug_slot = 0;
+
break;
}
}
- if (hotplug_slot > 0)
+ if (hotplug_slot >= 0)
break;
if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
break;
int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd) {
_cleanup_close_ int sock = -1;
struct udev_ctrl *uctrl;
- int r;
assert(ret);
.bound = fd >= 0,
};
- /*
- * FIXME: remove it as soon as we can depend on this:
- * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=90c6bd34f884cd9cee21f1d152baf6c18bcac949
- */
- r = setsockopt_int(uctrl->sock, SOL_SOCKET, SO_PASSCRED, true);
- if (r < 0)
- log_warning_errno(r, "Failed to set SO_PASSCRED: %m");
-
uctrl->saddr.un = (struct sockaddr_un) {
.sun_family = AF_UNIX,
.sun_path = "/run/udev/control",
return 0;
}
-static int udev_ctrl_wait_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- return sd_event_exit(sd_event_source_get_event(s), 0);
-}
-
int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
_cleanup_(sd_event_source_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL;
int r;
return r;
}
- r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, udev_ctrl_wait_io_handler, NULL);
+ r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, NULL, INT_TO_PTR(0));
if (r < 0)
return r;
(void) udev_node_remove(dev);
}
-static int udev_event_on_move(UdevEvent *event) {
- sd_device *dev = event->dev;
+static int udev_event_on_move(sd_device *dev) {
int r;
- if (sd_device_get_devnum(dev, NULL) < 0) {
- r = device_copy_properties(dev, event->dev_db_clone);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m");
- }
-
/* Drop previously added property */
r = device_add_property(dev, "ID_RENAMING", NULL);
if (r < 0)
(void) udev_watch_end(event->dev_db_clone);
if (action == DEVICE_ACTION_MOVE) {
- r = udev_event_on_move(event);
+ r = udev_event_on_move(event->dev);
if (r < 0)
return r;
}
mode_t mode, uid_t uid, gid_t gid,
OrderedHashmap *seclabel_list) {
const char *devnode, *subsystem, *id_filename = NULL;
+ bool apply_mode, apply_uid, apply_gid;
+ _cleanup_close_ int node_fd = -1;
struct stat stats;
dev_t devnum;
- bool apply_mode, apply_uid, apply_gid;
int r;
assert(dev);
else
mode |= S_IFCHR;
- if (lstat(devnode, &stats) < 0) {
- if (errno == ENOENT)
- return 0; /* this is necessarily racey, so ignore missing the device */
- return log_device_debug_errno(dev, errno, "cannot stat() node %s: %m", devnode);
+ node_fd = open(devnode, O_PATH|O_NOFOLLOW|O_CLOEXEC);
+ if (node_fd < 0) {
+ if (errno == ENOENT) {
+ log_device_debug_errno(dev, errno, "Device node %s is missing, skipping handling.", devnode);
+ return 0; /* This is necessarily racey, so ignore missing the device */
+ }
+
+ return log_device_debug_errno(dev, errno, "Cannot open node %s: %m", devnode);
}
- if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum)
- return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
- "Found node '%s' with non-matching devnum %s, skip handling",
- devnode, id_filename);
+ if (fstat(node_fd, &stats) < 0)
+ return log_device_debug_errno(dev, errno, "cannot stat() node %s: %m", devnode);
+
+ if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) {
+ log_device_debug(dev, "Found node '%s' with non-matching devnum %s, skipping handling.",
+ devnode, id_filename);
+ return 0; /* We might process a device that already got replaced by the time we have a look
+ * at it, handle this gracefully and step away. */
+ }
apply_mode = mode != MODE_INVALID && (stats.st_mode & 0777) != (mode & 0777);
apply_uid = uid_is_valid(uid) && stats.st_uid != uid;
gid_is_valid(gid) ? gid : stats.st_gid,
mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777);
- r = chmod_and_chown(devnode, mode, uid, gid);
+ r = fchmod_and_chown(node_fd, mode, uid, gid);
if (r < 0)
log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r,
"Failed to set owner/mode of %s to uid=" UID_FMT
if (streq(name, "selinux")) {
selinux = true;
- q = mac_selinux_apply(devnode, label);
+ q = mac_selinux_apply_fd(node_fd, devnode, label);
if (q < 0)
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SELinux label '%s': %m", label);
} else if (streq(name, "smack")) {
smack = true;
- q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label);
+ q = mac_smack_apply_fd(node_fd, SMACK_ATTR_ACCESS, label);
if (q < 0)
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SMACK label '%s': %m", label);
/* set the defaults */
if (!selinux)
- (void) mac_selinux_fix(devnode, LABEL_IGNORE_ENOENT);
+ (void) mac_selinux_fix_fd(node_fd, devnode, LABEL_IGNORE_ENOENT);
if (!smack)
- (void) mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL);
+ (void) mac_smack_apply_fd(node_fd, SMACK_ATTR_ACCESS, NULL);
}
/* always update timestamp when we re-use the node, like on media change events */
- (void) utimensat(AT_FDCWD, devnode, NULL, 0);
+ r = futimens_opath(node_fd, NULL);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to adjust timestamp of node %s: %m", devnode);
return r;
}
if (len > 0 && !isspace(value[len - 1]))
remove_trailing_whitespace = true;
- subst_type = rule_get_substitution_type((const char*) data);
+ subst_type = rule_get_substitution_type(data);
}
token = new(UdevRuleToken, 1);
assert(dev);
assert(event);
- name = (const char*) token->data;
+ name = token->data;
switch (token->attr_subst_type) {
case SUBST_TYPE_FORMAT:
case TK_M_NAME:
return token_match_string(token, event->name);
case TK_M_ENV:
- if (sd_device_get_property_value(dev, (const char*) token->data, &val) < 0)
+ if (sd_device_get_property_value(dev, token->data, &val) < 0)
val = hashmap_get(properties_list, token->data);
return token_match_string(token, val);
case TK_M_SYSCTL: {
_cleanup_free_ char *value = NULL;
- (void) udev_event_apply_format(event, (const char*) token->data, buf, sizeof(buf), false);
+ (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false);
r = sysctl_read(sysctl_normalize(buf), &value);
if (r < 0 && r != -ENOENT)
return log_rule_error_errno(dev, rules, r, "Failed to read sysctl '%s': %m", buf);
_cleanup_free_ char *name = NULL, *label = NULL;
char label_str[UTIL_LINE_SIZE] = {};
- name = strdup((const char*) token->data);
+ name = strdup(token->data);
if (!name)
return log_oom();
break;
}
case TK_A_ENV: {
- const char *name = (const char*) token->data;
+ const char *name = token->data;
char value_new[UTIL_NAME_SIZE], *p = value_new;
size_t l = sizeof(value_new);
break;
}
case TK_A_ATTR: {
- const char *key_name = (const char*) token->data;
+ const char *key_name = token->data;
char value[UTIL_NAME_SIZE];
if (util_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 &&
case TK_A_SYSCTL: {
char value[UTIL_NAME_SIZE];
- (void) udev_event_apply_format(event, (const char*) token->data, buf, sizeof(buf), false);
+ (void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false);
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false);
sysctl_normalize(buf);
log_rule_debug(dev, rules, "SYSCTL '%s' writing '%s'", buf, value);
r = write_string_file(filename, action, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) {
- bool ignore = IN_SET(r, -ENOENT, -EACCES, -ENODEV, -EROFS);
+ bool ignore = IN_SET(r, -ENOENT, -ENODEV);
log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r,
"Failed to write '%s' to '%s'%s: %m",
action, filename, ignore ? ", ignoring" : "");
- if (r == -EROFS)
- return 0; /* Read only filesystem. Return earlier. */
+ if (IN_SET(r, -EACCES, -EROFS))
+ /* Inovoked by unpriviledged user, or read only filesystem. Return earlier. */
+ return r;
if (ret == 0 && !ignore)
ret = r;
continue;
#include <errno.h>
#include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
#include "device-private.h"
#include "path-util.h"
#include "udevadm-util.h"
#include "unit-name.h"
+static int find_device_from_path(const char *path, sd_device **ret) {
+ if (path_startswith(path, "/sys/"))
+ return sd_device_new_from_syspath(ret, path);
+
+ if (path_startswith(path, "/dev/")) {
+ struct stat st;
+
+ if (stat(path, &st) < 0)
+ return -errno;
+
+ return device_new_from_stat_rdev(ret, &st);
+ }
+
+ return -EINVAL;
+}
+
+static int find_device_from_unit(const char *unit_name, sd_device **ret) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_free_ char *unit_path = NULL, *syspath = NULL;
+ int r;
+
+ if (!unit_name_is_valid(unit_name, UNIT_NAME_PLAIN))
+ return -EINVAL;
+
+ if (unit_name_to_type(unit_name) != UNIT_DEVICE)
+ return -EINVAL;
+
+ r = bus_connect_system_systemd(&bus);
+ if (r < 0) {
+ _cleanup_free_ char *path = NULL;
+
+ log_debug_errno(r, "Failed to open connection to systemd, using unit name as syspath: %m");
+
+ r = unit_name_to_path(unit_name, &path);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", unit_name);
+
+ return find_device_from_path(path, ret);
+ }
+
+ unit_path = unit_dbus_path_from_name(unit_name);
+ if (!unit_path)
+ return -ENOMEM;
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.systemd1.Device",
+ "SysFSPath",
+ &error,
+ &syspath);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get SysFSPath= dbus property for %s: %s",
+ unit_name, bus_error_message(&error, r));
+
+ return sd_device_new_from_syspath(ret, syspath);
+}
+
int find_device(const char *id, const char *prefix, sd_device **ret) {
_cleanup_free_ char *path = NULL;
int r;
} else {
/* In cases where the argument is generic (no prefix specified),
* check if the argument looks like a device unit name. */
- if (unit_name_is_valid(id, UNIT_NAME_PLAIN) &&
- unit_name_to_type(id) == UNIT_DEVICE) {
- r = unit_name_to_path(id, &path);
- if (r < 0)
- return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", id);
- id = path;
- }
+ r = find_device_from_unit(id, ret);
+ if (r >= 0)
+ return r;
}
- if (path_startswith(id, "/sys/"))
- return sd_device_new_from_syspath(ret, id);
-
- if (path_startswith(id, "/dev/")) {
- struct stat st;
-
- if (stat(id, &st) < 0)
- return -errno;
-
- return device_new_from_stat_rdev(ret, &st);
- }
-
- return -EINVAL;
+ return find_device_from_path(id, ret);
}
return -ENOMEM;
r = worker_lock_block_device(dev, &fd_lock);
+ if (r == -EAGAIN) {
+ /* So this is a block device and the device is locked currently via the BSD advisory locks —
+ * someone else is exclusively using it. This means we don't run our udev rules now, to not
+ * interfere. However we want to know when the device is unlocked again, and retrigger the
+ * device again then, so that the rules are run eventually. For that we use IN_CLOSE_WRITE
+ * inotify watches (which isn't exactly the same as waiting for the BSD locks to release, but
+ * not totally off, as long as unlock+close() is done together, as it usually is).
+ *
+ * (The user-facing side of this: https://systemd.io/BLOCK_DEVICE_LOCKING)
+ *
+ * There's a bit of a chicken and egg problem here for this however: inotify watching is
+ * supposed to be enabled via an option set via udev rules (OPTIONS+="watch"). If we skip the
+ * udev rules here however (as we just said we do), we would thus never see that specific
+ * udev rule, and thus never turn on inotify watching. But in order to catch up eventually
+ * and run them we we need the inotify watching: hence a classic chicken and egg problem.
+ *
+ * Our way out here: if we see the block device locked, unconditionally watch the device via
+ * inotify, regardless of any explicit request via OPTIONS+="watch". Thus, a device that is
+ * currently locked via the BSD file locks will be treated as if we ran a single udev rule
+ * only for it: the one that turns on inotify watching for it. If we eventually see the
+ * inotify IN_CLOSE_WRITE event, and then run the rules after all and we then realize that
+ * this wasn't actually requested (i.e. no OPTIONS+="watch" set) we'll simply turn off the
+ * watching again (see below). Effectively this means: inotify watching is now enabled either
+ * a) when the udev rules say so, or b) while the device is locked.
+ *
+ * Worst case scenario hence: in the (unlikely) case someone locked the device and we clash
+ * with that we might do inotify watching for a brief moment for a device where we actually
+ * weren't supposed to. But that shouldn't be too bad, in particular as BSD locks being taken
+ * on a block device is kinda an indication that the inotify logic is desired too, to some
+ * degree — they go hand-in-hand after all. */
+
+ log_device_debug(dev, "Block device is currently locked, installing watch to wait until the lock is released.");
+ (void) udev_watch_begin(dev);
+
+ /* Now the watch is installed, let's lock the device again, maybe in the meantime things changed */
+ r = worker_lock_block_device(dev, &fd_lock);
+ }
if (r < 0)
return r;
/* in case rtnl was initialized */
manager->rtnl = sd_netlink_ref(udev_event->rtnl);
- /* apply/restore inotify watch */
+ /* apply/restore/end inotify watch */
if (udev_event->inotify_watch) {
(void) udev_watch_begin(dev);
r = device_update_db(dev);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
- }
+ } else
+ (void) udev_watch_end(dev);
log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) processed",
seqnum, device_action_to_string(action));
r = write_string_file_atomic_label_ts(path, message, ts);
if (r == -EROFS)
- return log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
- if (r < 0)
+ log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
+ else if (r < 0)
return log_error_errno(r, "Failed to write \"%s\": %m", path);
return 0;
}
free(s->type);
free(s->exec_string);
+ free(s->working_directory);
strv_free(s->only_show_in);
strv_free(s->not_show_in);
const ConfigTableItem items[] = {
{ "Desktop Entry", "Name", xdg_config_parse_string, 0, &service->description},
{ "Desktop Entry", "Exec", xdg_config_parse_string, 0, &service->exec_string},
+ { "Desktop Entry", "Path", xdg_config_parse_string, 0, &service->working_directory},
{ "Desktop Entry", "TryExec", xdg_config_parse_string, 0, &service->try_exec},
{ "Desktop Entry", "Type", xdg_config_parse_string, 0, &service->type},
{ "Desktop Entry", "OnlyShowIn", xdg_config_parse_strv, 0, &service->only_show_in},
{ "Desktop Entry", "GenericName", NULL, 0, NULL},
{ "Desktop Entry", "Icon", NULL, 0, NULL},
{ "Desktop Entry", "Keywords", NULL, 0, NULL},
+ { "Desktop Entry", "MimeType", NULL, 0, NULL},
{ "Desktop Entry", "NoDisplay", NULL, 0, NULL},
{ "Desktop Entry", "StartupNotify", NULL, 0, NULL},
+ { "Desktop Entry", "StartupWMClass", NULL, 0, NULL},
{ "Desktop Entry", "Terminal", NULL, 0, NULL},
+ { "Desktop Entry", "URL", NULL, 0, NULL},
{ "Desktop Entry", "Version", NULL, 0, NULL},
{}
};
r = find_executable(test_binary, &gnome_autostart_condition_path);
if (r < 0) {
- log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r,
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"%s not found: %m", test_binary);
fprintf(f, "# ExecCondition using %s skipped due to missing binary.\n", test_binary);
return r;
/* Nothing to do for hidden services. */
if (service->hidden) {
- log_info("Not generating service for XDG autostart %s, it is hidden.", service->name);
+ log_debug("Not generating service for XDG autostart %s, it is hidden.", service->name);
return 0;
}
if (service->systemd_skip) {
- log_info("Not generating service for XDG autostart %s, should be skipped by generator.", service->name);
+ log_debug("Not generating service for XDG autostart %s, should be skipped by generator.", service->name);
return 0;
}
/* Nothing to do if type is not Application. */
if (!streq_ptr(service->type, "Application")) {
- log_info("Not generating service for XDG autostart %s, only Type=Application is supported.", service->name);
+ log_debug("Not generating service for XDG autostart %s, only Type=Application is supported.", service->name);
return 0;
}
if (service->try_exec) {
r = find_executable(service->try_exec, NULL);
if (r < 0) {
- log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r,
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Not generating service for XDG autostart %s, could not find TryExec= binary %s: %m",
service->name, service->try_exec);
return 0;
if (service->gnome_autostart_phase) {
/* There is no explicit value for the "Application" phase. */
- log_info("Not generating service for XDG autostart %s, startup phases are not supported.",
- service->name);
+ log_debug("Not generating service for XDG autostart %s, startup phases are not supported.",
+ service->name);
return 0;
}
fprintf(f,
"\n[Service]\n"
- "Type=simple\n"
+ "Type=exec\n"
"ExecStart=:%s\n"
"Restart=no\n"
"TimeoutSec=5s\n"
"Slice=app.slice\n",
exec_start);
+ if (service->working_directory) {
+ _cleanup_free_ char *e_working_directory = NULL;
+
+ e_working_directory = cescape(service->working_directory);
+ if (!e_working_directory)
+ return log_oom();
+
+ fprintf(f, "WorkingDirectory=-%s\n", e_working_directory);
+ }
+
/* Generate an ExecCondition to check $XDG_CURRENT_DESKTOP */
if (!strv_isempty(service->only_show_in) || !strv_isempty(service->not_show_in)) {
_cleanup_free_ char *only_show_in = NULL, *not_show_in = NULL, *e_only_show_in = NULL, *e_not_show_in = NULL;
char *type; /* Purely as an assertion check */
char *exec_string;
+ char *working_directory;
char **only_show_in;
char **not_show_in;
# See systemd-coredump(8) and core(5).
kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %h
+# Allow that 16 coredumps are dispatched in parallel by the kernel. We want to
+# be able to collect process metadata from /proc/%P/ while processing
+# coredumps, and thus need to make sure the crashed processes are not reaped
+# until we finished collecting what we need. The kernel default for this sysctl
+# is "0" which means the kernel doesn't wait for userspace processes to finish
+# processing before reaping the crashed processes — by setting this higher the
+# kernel will delay reaping until we are done, but only for the specified
+# number of crashes in parallel. The value of 16 is chosen to match
+# systemd-coredump.socket's MaxConnections= value.
+kernel.core_pipe_limit=16
+
# Also dump processes executing a set-user-ID/set-group-ID program that is
# owned by a user/group other than the real user/group ID of the process, or
# a program that has file capabilities. ("2" is called "suidsafe" in core(5)).
in_files = ['basic.conf']
-enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
-
foreach file : in_files
gen = configure_file(
input : file + '.in',
m4_ifdef(`ENABLE_NETWORKD',
u systemd-network - "systemd Network Management"
)m4_dnl
+m4_ifdef(`ENABLE_OOMD',
+u systemd-oom - "systemd Userspace OOM Killer"
+)m4_dnl
m4_ifdef(`ENABLE_RESOLVE',
u systemd-resolve - "systemd Resolver"
)m4_dnl
For PRs that fix a currently deny-listed test, the PR should include removal
of the deny-list file.
+
+In case a test fails, the full set of artifacts, including the journal of the
+failed run, can be downloaded from the artifacts.tar.gz archive which will be
+reachable in the same URL parent directory as the logs.gz that gets linked on
+the Github CI status.
+
+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.
+++ /dev/null
-../TEST-01-BASIC/Makefile
\ No newline at end of file
+++ /dev/null
-u1:x:300:u2
-u2:x:SYSTEM_UID_MAX:
+++ /dev/null
-u1:x:300:300::/:NOLOGIN
-u2:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN
+++ /dev/null
-aaa:x:SYSTEM_UID_MAX:987::/:NOLOGIN
+++ /dev/null
-g1:x:111:
-u1:x:SYSTEM_UID_MAX:
+++ /dev/null
-u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN
+++ /dev/null
-username:x:SYSTEM_UID_MAX:300::/:NOLOGIN
+++ /dev/null
-user1:x:300:300::/:NOLOGIN
-user2:x:SYSTEM_UID_MAX:300::/:NOLOGIN
+++ /dev/null
-#!/usr/bin/env bash
-set -e
-TEST_DESCRIPTION="Sysuser-related tests"
-IMAGE_NAME="sysusers"
-. $TEST_BASE_DIR/test-functions
-
-test_setup() {
- mkdir -p $TESTDIR/etc/sysusers.d $TESTDIR/usr/lib/sysusers.d $TESTDIR/tmp
-}
-
-prepare_testdir() {
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
- for i in $1.initial-{passwd,group,shadow}; do
- test -f $i && cp $i $TESTDIR/etc/${i#*.initial-}
- done
- return 0
-}
-
-preprocess() {
- in="$1"
-
- # see meson.build how to extract this. gcc -E was used before to
- # get this value from config.h, however the autopkgtest fails with
- # it
- [[ -e /etc/login.defs ]] && login_defs_file="/etc/login.defs" || login_defs_file="/usr/etc/login.defs"
- SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' $login_defs_file)
- SYSTEM_GID_MAX=$(awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' $login_defs_file)
-
- # we can't rely on config.h to get the nologin path, as autopkgtest
- # uses pre-compiled binaries, so extract it from the systemd-sysusers
- # binary which we are about to execute
- NOLOGIN=$(strings $(type -p systemd-sysusers) | grep nologin)
-
- sed -e "s/SYSTEM_UID_MAX/${SYSTEM_UID_MAX}/g" \
- -e "s/SYSTEM_GID_MAX/${SYSTEM_GID_MAX}/g" \
- -e "s#NOLOGIN#${NOLOGIN}#g" "$in"
-}
-
-compare() {
- if ! diff -u $TESTDIR/etc/passwd <(preprocess ${1%.*}.expected-passwd); then
- echo "**** Unexpected output for $f"
- exit 1
- fi
-
- if ! diff -u $TESTDIR/etc/group <(preprocess ${1%.*}.expected-group); then
- echo "**** Unexpected output for $f $2"
- exit 1
- fi
-}
-
-test_run() {
- # ensure our build of systemd-sysusers is run
- PATH=${BUILD_DIR}:$PATH
-
- rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
-
- # happy tests
- for f in test-*.input; do
- echo "*** Running $f"
- prepare_testdir ${f%.input}
- cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
- systemd-sysusers --root=$TESTDIR
-
- compare $f ""
- done
-
- for f in test-*.input; do
- echo "*** Running $f on stdin"
- prepare_testdir ${f%.input}
- touch $TESTDIR/etc/sysusers.d/test.conf
- cat $f | systemd-sysusers --root=$TESTDIR -
-
- compare $f "on stdin"
- done
-
- for f in test-*.input; do
- echo "*** Running $f on stdin with --replace"
- prepare_testdir ${f%.input}
- touch $TESTDIR/etc/sysusers.d/test.conf
- # this overrides test.conf which is masked on disk
- cat $f | systemd-sysusers --root=$TESTDIR --replace=/etc/sysusers.d/test.conf -
- # this should be ignored
- cat test-1.input | systemd-sysusers --root=$TESTDIR --replace=/usr/lib/sysusers.d/test.conf -
-
- compare $f "on stdin with --replace"
- done
-
- # test --inline
- echo "*** Testing --inline"
- prepare_testdir
- # copy a random file to make sure it is ignored
- cp $f $TESTDIR/etc/sysusers.d/confuse.conf
- systemd-sysusers --root=$TESTDIR --inline \
- "u u1 222 - - /bin/zsh" \
- "g g1 111"
-
- compare inline "(--inline)"
-
- # test --replace
- echo "*** Testing --inline with --replace"
- prepare_testdir
- # copy a random file to make sure it is ignored
- cp $f $TESTDIR/etc/sysusers.d/confuse.conf
- systemd-sysusers --root=$TESTDIR \
- --inline \
- --replace=/etc/sysusers.d/confuse.conf \
- "u u1 222 - - /bin/zsh" \
- "g g1 111"
-
- compare inline "(--inline --replace=…)"
-
- rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
-
- # tests for error conditions
- for f in unhappy-*.input; do
- echo "*** Running test $f"
- prepare_testdir ${f%.input}
- cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
- systemd-sysusers --root=$TESTDIR 2>&1 | tail -n1 > $TESTDIR/tmp/err
- if ! diff -u $TESTDIR/tmp/err ${f%.*}.expected-err; then
- echo "**** Unexpected error output for $f"
- cat $TESTDIR/tmp/err
- exit 1
- fi
- done
-}
-
-do_test "$@"
#!/usr/bin/env bash
set -e
TEST_DESCRIPTION="UDEV ID_RENAMING property"
+IMAGE_NAME="udev-id-renaming"
TEST_NO_NSPAWN=1
. $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
+ (
+ LOG_LEVEL=5
+ setup_basic_environment
+ mask_supporting_services
+
+ instmods dummy
+ generate_module_dependencies
+ )
+}
+
do_test "$@" 29
)
oldinitdir=$initdir
export initdir=$TESTDIR/minimal
- mkdir -p $initdir
+ mkdir -p $initdir/usr/lib $initdir/etc
setup_basic_dirs
install_basic_tools
cp $os_release $initdir/usr/lib/os-release
Subject: Utworzono nową sesję @SESSION_ID@ dla użytkownika @USER_ID@
Defined-By: systemd
Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika
@USER_ID@.
Subject: Zakończono sesję @SESSION_ID@
Defined-By: systemd
Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Sesja o identyfikatorze @SESSION_ID@ została zakończona.
Subject: Dostępne jest nowe stanowisko @SEAT_ID@
Defined-By: systemd
Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne.
Subject: Usunięto stanowisko @SEAT_ID@
Defined-By: systemd
Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
-Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation: sd-login(3)
Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne.
RouteMetric=
[DHCPv6PrefixDelegation]
SubnetId=
+Announce=
Assign=
Token=
[Route]
Bond=
IPv6ProxyNDP=
DNS=
+DNSDefaultRoute=
ActiveSlave=
LLMNR=
DNSSEC=
NTP=
DHCP=
Domains=
+IPv6SendRA=
IPv6PrefixDelegation=
VLAN=
DHCPServer=
VRF=
IgnoreCarrierLoss=
KeepConfiguration=
+DHCPv6PrefixDelegation=
[IPv6Prefix]
Prefix=
OnLink=
Family=
SuppressPrefixLength=
User=
+[IPv6SendRA]
+RouterPreference=
+DNSLifetimeSec=
+DNS=
+RouterLifetimeSec=
+Domains=
+EmitDNS=
+EmitDomains=
+Managed=
+OtherInformation=
[IPv6PrefixDelegation]
RouterPreference=
DNSLifetimeSec=
DNS=
-DNSDefaultRoute=
RouterLifetimeSec=
Domains=
EmitDNS=
exit 1
fi
-D=$(mktemp --directory)
+D=$(mktemp --tmpdir --directory "hwdb-test.XXXXXXXXXX")
trap "rm -rf '$D'" EXIT INT QUIT PIPE
mkdir -p "$D/etc/udev"
ln -s "$ROOTDIR/hwdb.d" "$D/etc/udev/hwdb.d"
############################################################
+test_sysusers_dir = join_paths(meson.current_source_dir(), 'test-sysusers')
+
+test_sysusers_sh = configure_file(
+ input : 'test-sysusers.sh.in',
+ output : 'test-sysusers.sh',
+ configuration : substs)
+if install_tests and conf.get('ENABLE_SYSUSERS') == 1
+ install_data(test_sysusers_sh,
+ install_dir : testsdir)
+ install_subdir('test-sysusers',
+ install_dir : testdata_dir)
+endif
+
+############################################################
+
rule_syntax_check_py = find_program('rule-syntax-check.py')
if want_tests != 'false'
test('rule-syntax-check',
echo "*** Running $f"
(
- out=$(mktemp --directory)
+ out=$(mktemp --tmpdir --directory "test-network-generator-conversion.XXXXXXXXXX")
trap "rm -rf '$out'" EXIT INT QUIT PIPE
$generator --root "$out" -- $(cat $f)
--- /dev/null
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+
+[Address]
+Address=100.64.0.1/32
+Peer=100.64.0.2/32
Address=10.3.3.99/16
Address=10.3.3.100/16
Address=10.3.3.101/16
-Address=10.3.3.101/16
Address=10.3.3.102/16
Address=10.3.3.103/16
Address=10.3.3.104/16
[Route]
Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
-Scope=link
[Route]
Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
-Scope=link
[Route]
-Destination=::/0
Gateway=2001:1234:5:8fff:ff:ff:ff:ff
[Route]
--- /dev/null
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:1234:5:8f63::1/128
+Address=149.10.124.58/28
+
+[Route]
+Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
+
+[Route]
+Destination=149.10.124.66
+Gateway=2001:1234:5:8fff:ff:ff:ff:ff
[Network]
Address=192.168.100.100/24
+IPv6AcceptRA=no
[SR-IOV]
VirtualFunction=0
IPv6AcceptRA=no
[Route]
-Gateway=_dhcp
+Gateway=_dhcp4
Destination=10.0.0.0/8
DHCP=ipv6
[Route]
-Gateway=_dhcp
+Gateway=_ipv6ra
Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
Name=veth-peer
[Network]
-IPv6PrefixDelegation=yes
+IPv6SendRA=yes
-[IPv6PrefixDelegation]
+[IPv6SendRA]
DNS=_link_local 2002:da8:1:0::1
DNSLifetimeSec=1min
[Network]
DHCP=no
-IPv6PrefixDelegation=yes
+IPv6SendRA=yes
[IPv6Prefix]
Prefix=2001:db8:0:1::/64
return f
+def expectedFailureIfRTA_VIAIsNotSupported():
+ def f(func):
+ call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
+ call('ip link set up dev dummy98', stderr=subprocess.DEVNULL)
+ call('ip route add 2001:1234:5:8fff:ff:ff:ff:fe/128 dev dummy98', stderr=subprocess.DEVNULL)
+ rc = call('ip route add 10.10.10.10 via inet6 2001:1234:5:8fff:ff:ff:ff:fe dev dummy98', stderr=subprocess.DEVNULL)
+ call('ip link del dummy98', stderr=subprocess.DEVNULL)
+ if rc == 0:
+ return func
+ else:
+ return unittest.expectedFailure(func)
+
+ return f
+
def expectedFailureIfAlternativeNameIsNotAvailable():
def f(func):
call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
rc = 0
while rc == 0:
rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ rc = 0
+ while rc == 0:
+ rc = call('ip -6 rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def remove_routes(routes):
for route_type, addr in routes:
links = [
'6rdtun99',
'bareudp99',
+ 'bond98',
'bond99',
'bridge99',
'dropin-test',
'25-sit-tunnel.netdev',
'25-tap.netdev',
'25-tun.netdev',
+ '25-tunnel-any-any.network',
'25-tunnel-local-any.network',
'25-tunnel-remote-any.network',
'25-tunnel.network',
'25-address-dad-veth-peer.network',
'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-bind-carrier.network',
'25-prefix-route-without-vrf.network',
'25-route-ipv6-src.network',
'25-route-static.network',
+ '25-route-via-ipv6.network',
'25-route-vrf.network',
'25-gateway-static.network',
'25-gateway-next-static.network',
print(output)
self.assertNotRegex(output, '192.168.100.10/24')
+ def test_address_peer_ipv4(self):
+ # test for issue #17304
+ copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev')
+
+ for trial in range(2):
+ if trial == 0:
+ start_networkd()
+ else:
+ restart_networkd()
+
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('ip -4 address show dev dummy98')
+ self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output)
+
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_prefix_route(self):
copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
- print('### ip -6 route show dev dummy98 default')
- output = check_output('ip -6 route show dev dummy98 default')
+ print('### ip -6 route show default')
+ output = check_output('ip -6 route show default')
print(output)
- self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
+ self.assertRegex(output, 'default')
+ self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff')
print('### ip -4 route show dev dummy98')
output = check_output('ip -4 route show dev dummy98')
self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
+ @expectedFailureIfRTA_VIAIsNotSupported()
+ def test_route_via_ipv6(self):
+ copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
+ print(output)
+
+ print('### ip -6 route show dev dummy98')
+ output = check_output('ip -6 route show dev dummy98')
+ print(output)
+ self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
+ self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
+
+ print('### ip -4 route show dev dummy98')
+ output = check_output('ip -4 route show dev dummy98')
+ print(output)
+ self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
+ self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
+
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_route_vrf(self):
copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
output = check_output('ip -4 route show dev dummy98')
print(output)
self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
- output = check_output('ip -6 route show dev dummy98')
+ output = check_output('ip -6 route show default')
print(output)
- self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
+ self.assertRegex(output, 'default')
+ self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
check_output('ip link del dummy98')
output = check_output('ip -4 route show dev dummy98')
print(output)
self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
- output = check_output('ip -6 route show dev dummy98')
+ output = check_output('ip -6 route show default')
print(output)
- self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
+ self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
def test_bind_carrier(self):
check_output('ip link add dummy98 type dummy')
output = check_output('ip route list dev veth99 10.0.0.0/8')
print(output)
- self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
+ self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto dhcp')
def test_dhcp_client_gateway_ipv6(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test for Path units
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
Description=Service Test Path Unit
[Service]
-ExecStart=/bin/true
-Type=simple
+ExecStart=sleep infinity
+Type=exec
RemainAfterExit=true
+++ /dev/null
-[Unit]
-Description=Service Test for Path units
-
-[Service]
-ExecStart=/bin/true
-Type=oneshot
--- /dev/null
+#!/usr/bin/env bash
+set -e
+
+SYSUSERS="${1:-systemd-sysusers}"
+
+[ -e "$(dirname $0)/../systemd-runtest.env" ] && . "$(dirname $0)/../systemd-runtest.env"
+SYSTEMD_TEST_DATA=${SYSTEMD_TEST_DATA:-@SYSTEMD_TEST_DATA@}
+SOURCE=$SYSTEMD_TEST_DATA/test-sysusers
+
+TESTDIR=$(mktemp --tmpdir --directory "test-sysusers.XXXXXXXXXX")
+trap "rm -rf '$TESTDIR'" EXIT INT QUIT PIPE
+
+prepare_testdir() {
+ mkdir -p $TESTDIR/etc/sysusers.d/
+ mkdir -p $TESTDIR/usr/lib/sysusers.d/
+ rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ for i in $1.initial-{passwd,group,shadow}; do
+ test -f $i && cp $i $TESTDIR/etc/${i#*.initial-}
+ done
+ return 0
+}
+
+[ @SYSTEM_UID_MAX@ -lt @SYSTEM_GID_MAX@ ] && system_guid_max=@SYSTEM_UID_MAX@ || system_guid_max=@SYSTEM_GID_MAX@
+
+preprocess() {
+ m=${2:-$system_guid_max}
+
+ sed -e "s/SYSTEM_UGID_MAX/$m/g;
+ s#NOLOGIN#@NOLOGIN@#g" "$1"
+}
+
+compare() {
+ if ! diff -u $TESTDIR/etc/passwd <(preprocess $1.expected-passwd $3); then
+ echo "**** Unexpected output for $f $2"
+ exit 1
+ fi
+
+ if ! diff -u $TESTDIR/etc/group <(preprocess $1.expected-group $3); then
+ echo "**** Unexpected output for $f $2"
+ exit 1
+ fi
+}
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
+# happy tests
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR
+
+ compare ${f%.*} ""
+done
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f on stdin"
+ prepare_testdir ${f%.input}
+ touch $TESTDIR/etc/sysusers.d/test.conf
+ cat $f | $SYSUSERS --root=$TESTDIR -
+
+ compare ${f%.*} "on stdin"
+done
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f on stdin with --replace"
+ prepare_testdir ${f%.input}
+ touch $TESTDIR/etc/sysusers.d/test.conf
+ # this overrides test.conf which is masked on disk
+ cat $f | $SYSUSERS --root=$TESTDIR --replace=/etc/sysusers.d/test.conf -
+ # this should be ignored
+ cat $SOURCE/test-1.input | $SYSUSERS --root=$TESTDIR --replace=/usr/lib/sysusers.d/test.conf -
+
+ compare ${f%.*} "on stdin with --replace"
+done
+
+# test --inline
+echo "*** Testing --inline"
+prepare_testdir $SOURCE/inline
+# copy a random file to make sure it is ignored
+cp $f $TESTDIR/etc/sysusers.d/confuse.conf
+$SYSUSERS --root=$TESTDIR --inline \
+ "u u1 222 - - /bin/zsh" \
+ "g g1 111"
+
+compare $SOURCE/inline "(--inline)"
+
+# test --replace
+echo "*** Testing --inline with --replace"
+prepare_testdir $SOURCE/inline
+# copy a random file to make sure it is ignored
+cp $f $TESTDIR/etc/sysusers.d/confuse.conf
+$SYSUSERS --root=$TESTDIR \
+ --inline \
+ --replace=/etc/sysusers.d/confuse.conf \
+ "u u1 222 - - /bin/zsh" \
+ "g g1 111"
+
+compare $SOURCE/inline "(--inline --replace=…)"
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
+cat >$TESTDIR/etc/login.defs <<EOF
+SYS_UID_MIN abcd
+SYS_UID_MAX abcd
+SYS_GID_MIN abcd
+SYS_GID_MAX abcd
+SYS_UID_MIN 401
+SYS_UID_MAX 555
+SYS_GID_MIN 405
+SYS_GID_MAX 666
+SYS_UID_MIN abcd
+SYS_UID_MAX abcd
+SYS_GID_MIN abcd
+SYS_GID_MAX abcd
+SYS_UID_MIN999
+SYS_UID_MAX999
+SYS_GID_MIN999
+SYS_GID_MAX999
+EOF
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f (with login.defs)"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR
+
+ [ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
+ compare ${f%.*} "(with login.defs)" $bound
+done
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
+mv $TESTDIR/etc/login.defs $TESTDIR/etc/login.defs.moved
+ln -s ../../../../../etc/login.defs.moved $TESTDIR/etc/login.defs
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f (with login.defs symlinked)"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR
+
+ [ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
+ compare ${f%.*} "(with login.defs symlinked)" $bound
+done
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
+# tests for error conditions
+for f in $(ls -1 $SOURCE/unhappy-*.input | sort -V); do
+ echo "*** Running test $f"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR 2>&1 | tail -n1 > $TESTDIR/err
+ if ! diff -u $TESTDIR/err ${f%.*}.expected-err; then
+ echo "**** Unexpected error output for $f"
+ cat $TESTDIR/err
+ exit 1
+ fi
+done
--- /dev/null
+u1:x:300:u2
+u2:x:SYSTEM_UGID_MAX:
--- /dev/null
+u1:x:300:300::/:NOLOGIN
+u2:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX::/:NOLOGIN
hoge:x:300:
baz:x:302:
-yyy:x:SYSTEM_GID_MAX:
+yyy:x:SYSTEM_UGID_MAX:
foo:x:301:
ccc:x:305:
aaa:x:303:302::/:NOLOGIN
bbb:x:304:302::/:NOLOGIN
ccc:x:305:305::/:NOLOGIN
-zzz:x:306:SYSTEM_GID_MAX::/:NOLOGIN
+zzz:x:306:SYSTEM_UGID_MAX::/:NOLOGIN
--- /dev/null
+aaa:x:SYSTEM_UGID_MAX:987::/:NOLOGIN
-u1:x:SYSTEM_UID_MAX:
+u1:x:SYSTEM_UGID_MAX:
u2:x:777:
u3:x:778:
u4:x:779:
-u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX:some gecos:/random/dir:NOLOGIN
+u1:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX:some gecos:/random/dir:NOLOGIN
u2:x:777:777:some gecos:/random/dir:/bin/zsh
u3:x:778:778::/random/dir2:/bin/bash
u4:x:779:779::/:/bin/csh
-# Test generation of ID dynamically based on SYSTEM_UID_MAX and
+# Test generation of ID dynamically based on SYSTEM_UGID_MAX and
# replacement of all fields up to the login shell.
#
#Type Name ID GECOS homedir shell
--- /dev/null
+g1:x:111:
+u1:x:SYSTEM_UGID_MAX:
--- /dev/null
+u1:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX::/:NOLOGIN
--- /dev/null
+username:x:SYSTEM_UGID_MAX:300::/:NOLOGIN
--- /dev/null
+user1:x:300:300::/:NOLOGIN
+user2:x:SYSTEM_UGID_MAX:300::/:NOLOGIN
Description=ForeverPrintHola service
[Service]
-Type=simple
+Type=exec
ExecStart=sh -x -c 'while :; do printf "Hola\n" || touch /i-lose-my-logs; sleep 1; done'
StartLimitBurst=3
[Service]
-Type=simple
+Type=exec
ExecStart=false
Restart=always
[Service]
ExecStartPre=rm -f /failed /testok
-Type=simple
+Type=exec
TimeoutStartSec=infinity
ExecStartPre=/usr/lib/systemd/tests/testdata/units/%N.sh
ExecStart=true
rm -f /run/udev/rules.d/50-testsuite.rules
udevadm control --reload --timeout=600
+# test for issue #16967
+
+ip link add hoge type dummy
+udevadm info --wait-for-initialization=10s /sys/devices/virtual/net/hoge
+sleep 1
+if ! systemctl status sys-devices-virtual-net-hoge.device; then exit 1; fi
+if ! systemctl status sys-subsystem-net-devices-hoge.device; then exit 1; fi
+
+ip link set hoge name foobar
+udevadm info --wait-for-initialization=10s /sys/devices/virtual/net/foobar
+sleep 1
+if systemctl status sys-devices-virtual-net-hoge.device; then exit 1; fi
+if systemctl status sys-subsystem-net-devices-hoge.device; then exit 1; fi
+if ! systemctl status sys-devices-virtual-net-foobar.device; then exit 1; fi
+if ! systemctl status sys-subsystem-net-devices-foobar.device; then exit 1; fi
+
echo OK > /testok
exit 0
umount ${image_dir}/mount
umount ${image_dir}/mount2
-systemd-run -t --property RootImage=${image}.raw /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p RootImage=${image}.raw cat /usr/lib/os-release | grep -q -F "MARKER=1"
mv ${image}.verity ${image}.fooverity
mv ${image}.roothash ${image}.foohash
-systemd-run -t --property RootImage=${image}.raw --property RootHash=${image}.foohash --property RootVerity=${image}.fooverity /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property RootImage=${image}.raw --property RootHash=${roothash} --property RootVerity=${image}.fooverity /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p RootImage=${image}.raw -p RootHash=${image}.foohash -p RootVerity=${image}.fooverity cat /usr/lib/os-release | grep -q -F "MARKER=1"
+# Let's use the long option name just here as a test
+systemd-run -t --property RootImage=${image}.raw --property RootHash=${roothash} --property RootVerity=${image}.fooverity cat /usr/lib/os-release | grep -q -F "MARKER=1"
mv ${image}.fooverity ${image}.verity
mv ${image}.foohash ${image}.roothash
if [ "${machine}" = "x86_64" ]; then
root_guid=4f68bce3-e8cd-4db1-96e7-fbcaf984b709
verity_guid=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5
+ architecture="x86-64"
elif [ "${machine}" = "i386" ] || [ "${machine}" = "i686" ] || [ "${machine}" = "x86" ]; then
root_guid=44479540-f297-41b2-9af7-d131d5f0458a
verity_guid=d13c5d3b-b5d1-422a-b29f-9454fdc89d76
+ architecture="x86"
elif [ "${machine}" = "aarch64" ] || [ "${machine}" = "aarch64_be" ] || [ "${machine}" = "armv8b" ] || [ "${machine}" = "armv8l" ]; then
root_guid=b921b045-1df0-41c3-af44-4c6f280d3fae
verity_guid=df3300ce-d69f-4c92-978c-9bfb0f38d820
+ architecture="arm64"
elif [ "${machine}" = "arm" ]; then
root_guid=69dad710-2ce4-4e3c-b16c-21a1d49abed3
verity_guid=7386cdf2-203c-47a9-a498-f2ecce45a2d6
+ architecture="arm"
elif [ "${machine}" = "ia64" ]; then
root_guid=993d8d3d-f80e-4225-855a-9daf8ed7ea97
verity_guid=86ed10d5-b607-45bb-8957-d350f23d0571
+ architecture="ia64"
+elif [ "${machine}" = "ppc64le" ]; then
+ # There's no support of PPC in the discoverable partitions specification yet, so skip the rest for now
+ echo OK >/testok
+ exit 0
else
echo "Unexpected uname -m: ${machine} in testsuite-50.sh, please fix me"
exit 1
else
root_size="${root_size}KiB"
fi
-verity_size="${verity_size}KiB"
+verity_size="$((${verity_size} * 2))KiB"
uuid="$(head -c 32 ${image}.roothash | cut -c -8)-$(head -c 32 ${image}.roothash | cut -c 9-12)-$(head -c 32 ${image}.roothash | cut -c 13-16)-$(head -c 32 ${image}.roothash | cut -c 17-20)-$(head -c 32 ${image}.roothash | cut -c 21-)"
echo -e "label: gpt\nsize=${root_size}, type=${root_guid}, uuid=${uuid}" | sfdisk ${image}.gpt
uuid="$(tail -c 32 ${image}.roothash | cut -c -8)-$(tail -c 32 ${image}.roothash | cut -c 9-12)-$(tail -c 32 ${image}.roothash | cut -c 13-16)-$(tail -c 32 ${image}.roothash | cut -c 17-20)-$(tail -c 32 ${image}.roothash | cut -c 21-)"
ROOT_UUID=$(systemd-id128 -u show $(head -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-)
VERITY_UUID=$(systemd-id128 -u show $(tail -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-)
-systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'$ROOT_UUID'","fstype":"squashfs","architecture":"x86-64","verity":"yes","node":'
-systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'$VERITY_UUID'","fstype":"DM_verity_hash","architecture":"x86-64","verity":null,"node":'
+systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'$ROOT_UUID'","fstype":"squashfs","architecture":"'$architecture'","verity":"yes","node":'
+systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'$VERITY_UUID'","fstype":"DM_verity_hash","architecture":"'$architecture'","verity":null,"node":'
systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F "MARKER=1"
systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f $os_release
cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1"
umount ${image_dir}/mount
-systemd-run -t --property RootImage=${image}.gpt --property RootHash=${roothash} /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
+# add explicit -p MountAPIVFS=yes once to test the parser
+systemd-run -t -p RootImage=${image}.gpt -p RootHash=${roothash} -p MountAPIVFS=yes cat /usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property RootImage=${image}.raw --property RootImageOptions="root:nosuid,dev home:ro,dev ro,noatime" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t --property RootImage=${image}.gpt --property RootImageOptions="root:ro,noatime root:ro,dev" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "noatime"
+systemd-run -t -p RootImage=${image}.raw -p RootImageOptions="root:nosuid,dev home:ro,dev ro,noatime" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -t -p RootImage=${image}.gpt -p RootImageOptions="root:ro,noatime root:ro,dev" mount | grep -F "squashfs" | grep -q -F "noatime"
mkdir -p mkdir -p ${image_dir}/result
-cat > /run/systemd/system/testservice-50a.service <<EOF
+cat >/run/systemd/system/testservice-50a.service <<EOF
[Service]
Type=oneshot
-ExecStart=bash -c "mount > /run/result/a"
+ExecStart=bash -c "mount >/run/result/a"
BindPaths=${image_dir}/result:/run/result
TemporaryFileSystem=/run
-MountAPIVFS=yes
RootImage=${image}.raw
RootImageOptions=root:ro,noatime home:ro,dev relatime,dev
RootImageOptions=nosuid,dev
grep -F "squashfs" ${image_dir}/result/a | grep -q -F "noatime"
grep -F "squashfs" ${image_dir}/result/a | grep -q -F -v "nosuid"
-cat > /run/systemd/system/testservice-50b.service <<EOF
+cat >/run/systemd/system/testservice-50b.service <<EOF
[Service]
Type=oneshot
-ExecStart=bash -c "mount > /run/result/b"
+ExecStart=bash -c "mount >/run/result/b"
BindPaths=${image_dir}/result:/run/result
TemporaryFileSystem=/run
-MountAPIVFS=yes
RootImage=${image}.gpt
RootImageOptions=root:ro,noatime,nosuid home:ro,dev nosuid,dev
RootImageOptions=home:ro,dev nosuid,dev,%%foo
+# this is the default, but let's specify once to test the parser
+MountAPIVFS=yes
EOF
systemctl start testservice-50b.service
grep -F "squashfs" ${image_dir}/result/b | grep -q -F "noatime"
-# Check that specifier escape is applied %%foo -> %foo
+# Check that specifier escape is applied %%foo → %foo
busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/testservice_2d50b_2eservice org.freedesktop.systemd1.Service RootImageOptions | grep -F "nosuid,dev,%foo"
# Now do some checks with MountImages, both by itself, with options and in combination with RootImage, and as single FS or GPT image
-systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2:nosuid,dev" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t --property MountImages="${image}.gpt:/run/img1:root:nosuid ${image}.raw:/run/img2:home:suid" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t --property MountImages="${image}.raw:/run/img2\:3" /usr/bin/cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property MountImages="${image}.raw:/run/img2\:3:nosuid" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.gpt --property RootHash=${roothash} --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2:nosuid,dev" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -t -p MountImages="${image}.gpt:/run/img1:root:nosuid ${image}.raw:/run/img2:home:suid" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -t -p MountImages="${image}.raw:/run/img2\:3" cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p MountImages="${image}.raw:/run/img2\:3:nosuid" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.raw -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.raw -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.gpt -p RootHash=${roothash} -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
cat >/run/systemd/system/testservice-50c.service <<EOF
[Service]
MountAPIVFS=yes
RootImage=${image}.raw
MountImages=${image}.gpt:/run/img1:root:noatime:home:relatime
MountImages=${image}.raw:/run/img2\:3:nosuid
-ExecStart=bash -c "cat /run/img1/usr/lib/os-release > /run/result/c"
-ExecStart=bash -c "cat /run/img2:3/usr/lib/os-release >> /run/result/c"
-ExecStart=bash -c "mount >> /run/result/c"
+ExecStart=bash -c "cat /run/img1/usr/lib/os-release >/run/result/c"
+ExecStart=bash -c "cat /run/img2:3/usr/lib/os-release >>/run/result/c"
+ExecStart=bash -c "mount >>/run/result/c"
BindPaths=${image_dir}/result:/run/result
Type=oneshot
EOF
grep -F "squashfs" ${image_dir}/result/c | grep -q -F "noatime"
grep -F "squashfs" ${image_dir}/result/c | grep -q -F -v "nosuid"
-echo OK > /testok
+echo OK >/testok
exit 0
# control writes into pstore.
#
# The crash_kexec_post_notifiers parameter enables the kernel to write
-# dmesg (including stack trace) into pstore upon a panic, and
-# printk.always_kmsg_dump parameter enables the kernel to write dmesg
+# dmesg (including stack trace) into pstore upon a panic even if kdump
+# is loaded, only needed if you want to use pstore with kdump. Without
+# this parameter, kdump could block writing to pstore for stability
+# reason. Note this increases the risk of kdump failure even if pstore
+# is not available.
+#
+# The printk.always_kmsg_dump parameter enables the kernel to write dmesg
# upon a normal shutdown (shutdown, reboot, halt).
#
# To configure the kernel parameters, uncomment the appropriate
d /var/lib/systemd/pstore 0755 root root 14d
#w- /sys/module/printk/parameters/always_kmsg_dump - - - - Y
-w- /sys/module/kernel/parameters/crash_kexec_post_notifiers - - - - Y
+#w- /sys/module/kernel/parameters/crash_kexec_post_notifiers - - - - Y
'8086:02a4',
# USB controller
'8086:02ed',
+ # Volteer xHCI controller
+ '8086:a0ed',
# Graphics
'8086:9b41',
# DSP
import chromiumos.gen_autosuspend_rules
-print('# pci:v<00VENDOR>d<00DEVICE> (8 uppercase hexadecimal digits twice)')
+print('# pci:v<00VENDOR>d<00DEVICE>:* (8 uppercase hexadecimal digits twice)')
for entry in chromiumos.gen_autosuspend_rules.PCI_IDS:
vendor, device = entry.split(':')
vendor = int(vendor, 16)
device = int(device, 16)
- print('pci:v{:08X}d{:08X}*'.format(vendor, device))
+ print('pci:v{:08X}d{:08X}:*'.format(vendor, device))
-print('# usb:v<VEND>p<PROD> (4 uppercase hexadecimal digits twice)')
+print('# usb:v<VEND>p<PROD>:* (4 uppercase hexadecimal digits twice)')
for entry in chromiumos.gen_autosuspend_rules.USB_IDS:
vendor, product = entry.split(':')
vendor = int(vendor, 16)
product = int(product, 16)
- print('usb:v{:04X}p{:04X}*'.format(vendor, product))
+ print('usb:v{:04X}p{:04X}:*'.format(vendor, product))
print(' ID_AUTOSUSPEND=1')
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=First Boot Complete
+Documentation=man:systemd.special(7)
+RefuseManualStart=yes
+ConditionFirstBoot=yes
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Initrd Encrypted Volumes
+Documentation=man:systemd.special(7)
+OnFailure=emergency.target
+OnFailureJobMode=replace-irreversibly
+AssertPathExists=/etc/initrd-release
+DefaultDependencies=no
+Conflicts=shutdown.target
['emergency.target', ''],
['exit.target', ''],
['final.target', ''],
+ ['first-boot-complete.target', ''],
['getty.target', '',
'multi-user.target.wants/'],
['getty-pre.target', ''],
['hybrid-sleep.target', 'ENABLE_HIBERNATE'],
['suspend-then-hibernate.target', 'ENABLE_HIBERNATE'],
['initrd-cleanup.service', 'ENABLE_INITRD'],
+ ['initrd-cryptsetup.target', 'HAVE_LIBCRYPTSETUP ENABLE_INITRD',
+ 'sysinit.target.wants/'],
['initrd-fs.target', 'ENABLE_INITRD'],
['initrd-parse-etc.service', 'ENABLE_INITRD'],
['initrd-root-device.target', 'ENABLE_INITRD'],
['systemd-firstboot.service', 'ENABLE_FIRSTBOOT',
'sysinit.target.wants/'],
['systemd-halt.service', ''],
+ ['systemd-homed-activate.service', 'ENABLE_HOMED'],
['systemd-initctl.socket', 'HAVE_SYSV_COMPAT',
'sockets.target.wants/'],
['systemd-journal-catalog-update.service', '',
['systemd-networkd.service', 'ENABLE_NETWORKD'],
['systemd-networkd-wait-online.service', 'ENABLE_NETWORKD'],
['systemd-nspawn@.service', ''],
+ ['systemd-oomd.service', 'ENABLE_OOMD'],
['systemd-portabled.service', 'ENABLE_PORTABLED',
'dbus-org.freedesktop.portable1.service'],
['systemd-userdbd.service', 'ENABLE_USERDB'],
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
-ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,38400,9600 %I $TERM
+ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,57600,38400,9600 %I $TERM
Type=idle
Restart=always
UtmpIdentifier=%I
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-remount-fs.service
-Before=systemd-sysusers.service sysinit.target shutdown.target
+Before=systemd-sysusers.service sysinit.target first-boot-complete.target shutdown.target
+Wants=first-boot-complete.target
ConditionPathIsReadWrite=/etc
ConditionFirstBoot=yes
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Home Area Activation
+Documentation=man:systemd-homed.service(8)
+After=home.mount systemd-homed.service
+Before=systemd-user-sessions.service
+
+[Service]
+ExecStop=homectl deactivate-all
+RemainAfterExit=true
+Type=oneshot
+
+[Install]
+WantedBy=systemd-homed.service
+Also=systemd-homed.service
[Unit]
Description=Home Area Manager
Documentation=man:systemd-homed.service(8)
+Documentation=man:org.freedesktop.home1(5)
+
After=home.mount
[Service]
[Install]
WantedBy=multi-user.target
Alias=dbus-org.freedesktop.home1.service
-Also=systemd-userdbd.service
+Also=systemd-homed-activate.service systemd-userdbd.service
[Unit]
Description=Hostname Service
-Documentation=man:systemd-hostnamed.service(8) man:hostname(5) man:machine-info(5)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/hostnamed
+Documentation=man:systemd-hostnamed.service(8)
+Documentation=man:hostname(5)
+Documentation=man:machine-info(5)
+Documentation=man:org.freedesktop.resolve1(5)
[Service]
BusName=org.freedesktop.hostname1
[Unit]
Description=Virtual Machine and Container Download Service
Documentation=man:systemd-importd.service(8)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/importd
+Documentation=man:org.freedesktop.import1(5)
[Service]
ExecStart=@rootlibexecdir@/systemd-importd
[Unit]
Description=Locale Service
-Documentation=man:systemd-localed.service(8) man:locale.conf(5) man:vconsole.conf(5)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/localed
+Documentation=man:systemd-localed.service(8)
+Documentation=man:locale.conf(5)
+Documentation=man:vconsole.conf(5)
+Documentation=man:org.freedesktop.locale1(5)
[Service]
BusName=org.freedesktop.locale1
[Unit]
Description=User Login Management
-Documentation=man:systemd-logind.service(8) man:logind.conf(5)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation=man:sd-login(3)
+Documentation=man:systemd-logind.service(8)
+Documentation=man:logind.conf(5)
+Documentation=man:org.freedesktop.login1(5)
+
Wants=user.slice modprobe@drm.service
After=nss-user-lookup.target user.slice modprobe@drm.service
Documentation=man:systemd-machine-id-commit.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
-Before=sysinit.target shutdown.target
-After=local-fs.target
+Before=shutdown.target
+After=local-fs.target first-boot-complete.target
ConditionPathIsReadWrite=/etc
ConditionPathIsMountPoint=/etc/machine-id
[Unit]
Description=Virtual Machine and Container Registration Service
Documentation=man:systemd-machined.service(8)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined
+Documentation=man:org.freedesktop.machine1(5)
+
Wants=machine.slice
After=machine.slice
RequiresMountsFor=/var/lib/machines
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Userspace Out-Of-Memory (OOM) Killer
+Documentation=man:systemd-oomd.service(8)
+DefaultDependencies=no
+Before=multi-user.target shutdown.target
+Conflicts=shutdown.target
+
+[Service]
+AmbientCapabilities=CAP_KILL CAP_DAC_OVERRIDE
+BusName=org.freedesktop.oom1
+CapabilityBoundingSet=CAP_KILL CAP_DAC_OVERRIDE
+ExecStart=@rootlibexecdir@/systemd-oomd
+IPAddressDeny=any
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+# Reserve some minimum amount of memory so that systemd-oomd can continue to
+# run in resource starved scenarios.
+MemoryMin=64M
+MemoryLow=64M
+NoNewPrivileges=yes
+OOMScoreAdjust=-900
+PrivateDevices=yes
+PrivateTmp=yes
+ProtectClock=yes
+ProtectHome=yes
+ProtectHostname=yes
+ProtectKernelLogs=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+ProtectSystem=strict
+Restart=on-failure
+RestrictAddressFamilies=AF_UNIX
+RestrictNamespaces=yes
+RestrictRealtime=yes
+RestrictSUIDSGID=yes
+SystemCallArchitectures=native
+SystemCallErrorNumber=EPERM
+SystemCallFilter=@system-service
+Type=notify
+User=systemd-oom
+@SERVICE_WATCHDOG@
+
+[Install]
+WantedBy=multi-user.target
+Alias=dbus-org.freedesktop.oom1.service
RequiresMountsFor=@RANDOM_SEED@
Conflicts=shutdown.target
After=systemd-remount-fs.service
-Before=shutdown.target
+Before=first-boot-complete.target shutdown.target
+Wants=first-boot-complete.target
ConditionVirtualization=!container
[Service]
[Unit]
Description=Network Name Resolution
Documentation=man:systemd-resolved.service(8)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
+Documentation=man:org.freedesktop.resolve1(5)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
+
DefaultDependencies=no
After=systemd-sysusers.service systemd-networkd.service
Before=network.target nss-lookup.target shutdown.target
[Unit]
Description=Time & Date Service
-Documentation=man:systemd-timedated.service(8) man:localtime(5)
-Documentation=https://www.freedesktop.org/wiki/Software/systemd/timedated
+Documentation=man:systemd-timedated.service(8)
+Documentation=man:localtime(5)
+Documentation=man:org.freedesktop.timedate1(5)
[Service]
BusName=org.freedesktop.timedate1