mirror of
https://github.com/systemd/systemd
synced 2026-03-10 07:04:46 +01:00
Compare commits
No commits in common. "ed6a2eaa31872c69e56035927a358bbcbad114a0" and "6d0e8271b4ab332d356d7f59394035da2d8845a8" have entirely different histories.
ed6a2eaa31
...
6d0e8271b4
4
.github/workflows/linter.yml
vendored
4
.github/workflows/linter.yml
vendored
@ -50,6 +50,10 @@ jobs:
|
||||
[Build]
|
||||
ToolsTreeDistribution=fedora
|
||||
ToolsTreeRelease=rawhide
|
||||
ToolsTreePackages=
|
||||
libgcrypt-devel
|
||||
libgpg-error-devel
|
||||
musl-gcc
|
||||
EOF
|
||||
|
||||
mkosi -f box -- true
|
||||
|
||||
8
NEWS
8
NEWS
@ -44,14 +44,6 @@ CHANGES WITH 260 in spe:
|
||||
SYSTEMD_COLORS=256, and SYSTEMD_COLORS=24bit respectively when output
|
||||
is to a non-dumb TTY, and like SYSTEMD_COLORS=no otherwise.
|
||||
|
||||
* Minimum backlight brightness clamp for restoring it at boot has been
|
||||
lowered from 5% to 1%. This is a safe change allowing more chance to
|
||||
user environments to set lower values that won't be set higher at boot
|
||||
while still giving the chance to recover from blackouts because
|
||||
excessive lower bright values by just rebooting. Notice that if your
|
||||
environment allow you to set excessive low brightness values this has
|
||||
nothing to do with systemd's brightness clamp.
|
||||
|
||||
CHANGES WITH 259:
|
||||
|
||||
Announcements of Future Feature Removals and Incompatible Changes:
|
||||
|
||||
3
TODO
3
TODO
@ -121,9 +121,6 @@ Deprecations and removals:
|
||||
|
||||
Features:
|
||||
|
||||
* networkd: maintain a file in /run/ that can be symlinked into /run/issue.d/
|
||||
that always shows the current primary IP address
|
||||
|
||||
* report:
|
||||
- should the list of metrics use JSON-SEQ? or maybe be wrapped in a json
|
||||
array (the latter might be necessary, once we sign the combination)
|
||||
|
||||
@ -705,7 +705,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
- Think about the log level you choose: for functions that are of the "logging"
|
||||
kind (see above), please ensure that failures we propagate should be logged
|
||||
about at `LOG_ERR` level. Failures that are noteworthy, but we proceed anyway,
|
||||
should be logged at `LOG_WARN` level. Important informational messages should
|
||||
should be loged at `LOG_WARN` level. Important informational messages should
|
||||
use `LOG_NOTICE` and regular informational messages should use
|
||||
`LOG_INFO`. Note that the latter is the default maximum log level, i.e. only
|
||||
`LOG_DEBUG` messages are hidden by default.
|
||||
|
||||
@ -30,12 +30,15 @@
|
||||
#
|
||||
# If the property is missing, user-space can assume:
|
||||
# ID_INPUT_JOYSTICK_INTEGRATION=external
|
||||
#
|
||||
# By default i8042, i2c, and rmi devices are assumed to be internal,
|
||||
# bluetooth devices are assumed to be external, usb devices are assumed
|
||||
# to be internal when connected to a PCB port and external otherwise.
|
||||
|
||||
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
|
||||
# this will make this usb joystick to behave as internal.
|
||||
#joystick:usb:vffffp0000*
|
||||
# ID_INPUT_JOYSTICK_INTEGRATION=internal
|
||||
joystick:bluetooth:*
|
||||
ID_INPUT_JOYSTICK_INTEGRATION=external
|
||||
|
||||
###########################################################
|
||||
# GPD
|
||||
###########################################################
|
||||
|
||||
# GPD Win, Classic and XBox 360 compat modes
|
||||
joystick:usb:v11c5p5507*
|
||||
joystick:usb:v045ep028e*
|
||||
ID_INPUT_JOYSTICK_INTEGRATION=internal
|
||||
|
||||
@ -28,18 +28,44 @@
|
||||
# Permitted keys:
|
||||
# Specify whether a touchpad is a built-in one or external:
|
||||
# ID_INPUT_TOUCHPAD_INTEGRATION=internal|external
|
||||
#
|
||||
# By default i8042, i2c, and rmi devices are assumed to be internal,
|
||||
# bluetooth devices are assumed to be external, usb devices are assumed
|
||||
# to be internal when connected to a PCB port and external otherwise.
|
||||
|
||||
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
|
||||
# this will make this bluetooth touchpad to behave as internal.
|
||||
#touchpad:bluetooth:vffffp0000:*
|
||||
# ID_INPUT_TOUCHPAD_INTEGRATION=internal
|
||||
touchpad:i8042:*
|
||||
touchpad:rmi:*
|
||||
touchpad:usb:*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=internal
|
||||
|
||||
touchpad:bluetooth:*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=external
|
||||
|
||||
###########################################################
|
||||
# Apple
|
||||
###########################################################
|
||||
# Magic Trackpad (1 and 2)
|
||||
touchpad:usb:v05acp030e:*
|
||||
touchpad:usb:v05acp0265:*
|
||||
touchpad:usb:v05acp0324:*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=external
|
||||
|
||||
###########################################################
|
||||
# HP Elite x2 1013 G3
|
||||
###########################################################
|
||||
touchpad:usb:v044ep1221:*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=external
|
||||
|
||||
###########################################################
|
||||
# Lenovo IdeaPad Duet3 10IGL5 (82AT)
|
||||
###########################################################
|
||||
touchpad:bluetooth:v17efp60fa:*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=internal
|
||||
|
||||
###########################################################
|
||||
# Logitech
|
||||
###########################################################
|
||||
touchpad:usb:v046d*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=external
|
||||
|
||||
###########################################################
|
||||
# Wacom
|
||||
###########################################################
|
||||
touchpad:usb:v056a*
|
||||
ID_INPUT_TOUCHPAD_INTEGRATION=external
|
||||
|
||||
@ -350,7 +350,7 @@ def print_summary(fname, groups):
|
||||
print(f'{fname}: {len(groups)} match groups, {n_matches} matches, {n_props} properties')
|
||||
|
||||
if n_matches == 0 or n_props == 0:
|
||||
print(f'{fname}: no matches or props')
|
||||
error(f'{fname}: no matches or props')
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = sys.argv[1:] or sorted([
|
||||
|
||||
@ -529,7 +529,7 @@
|
||||
<listitem><para>Takes a boolean, defaults to false. Controls whether to append disk model information
|
||||
to the firmware boot option item description (as configured with
|
||||
<option>--efi-boot-option-description=</option> above). This is useful when installing multiple
|
||||
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernible
|
||||
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernable
|
||||
and give a hint which disk is booted into. Note that this uses hardware model information, and hence
|
||||
might not be too useful in case multiple disks of an identical model are used.</para>
|
||||
|
||||
|
||||
@ -69,18 +69,6 @@
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>FirewallMark=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a 32 bit unsigned integer value. Controls the firewall mark of packets generated by the
|
||||
socket used to make DNS requests for this DNS delegate. This can be used in the firewall logic to
|
||||
filter packets from this socket.
|
||||
This sets the <constant>SO_MARK</constant> socket option. See <citerefentry
|
||||
project='die-net'><refentrytitle>iptables</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
|
||||
details.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v260"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
@ -91,11 +79,10 @@
|
||||
<programlisting># /etc/systemd/dns-delegate.d/foobar.dns-delegate
|
||||
[Delegate]
|
||||
DNS=203.0.113.47
|
||||
Domains=foobar.com
|
||||
FirewallMark=42</programlisting>
|
||||
Domains=foobar.com</programlisting>
|
||||
|
||||
<para>This ensures lookups of <literal>foobar.com</literal> and any domains below it are directed to
|
||||
DNS server 203.0.113.47 and any packets related to this lookup have a firewall mark set to 42.</para>
|
||||
DNS server 203.0.113.47.</para>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -6444,117 +6444,6 @@ ServerAddress=192.168.0.1/24</programlisting>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>[ModemManager] Section Options</title>
|
||||
|
||||
<para>This section configures the default setting of the ModemManager integration. See
|
||||
<ulink url="https://modemmanager.org/docs/modemmanager/" /> for more information about ModemManager.</para>
|
||||
|
||||
<para>Regardless of the [ModemManager] section settings consider using the following for LTE modems (take into account
|
||||
that LTE modems do not typically support LLDP because LLDP is a Layer 2 protocol for Ethernet networks and an LTE
|
||||
modem connects to a cellular network, not a local Ethernet LAN):
|
||||
<programlisting>[Network]
|
||||
LLDP=no
|
||||
LinkLocalAddressing=no
|
||||
IPv6AcceptRA=no
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>The following options are available in the [ModemManager] section:</para>
|
||||
<variablelist class='network-directives'>
|
||||
<varlistentry>
|
||||
<term><varname>SimpleConnectProperties=</varname></term>
|
||||
<listitem>
|
||||
<para>Specifies the white-space separated list of simple connect properties used to connect a modem. See
|
||||
<ulink url="https://www.freedesktop.org/software/ModemManager/man/latest/mmcli.1.html" /> for more
|
||||
information about simple connect. If no properties provided then the connection is not initiated.</para>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>apn</option>=<replaceable>NAME</replaceable></term>
|
||||
<listitem><para>An Access Point Name (APN) is the name of a gateway between a mobile network
|
||||
(GSM, GPRS, 3G, 4G and 5G) and another computer network. Required in 3GPP.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>allowed-auth</option>=<replaceable>METHOD</replaceable></term>
|
||||
<listitem><para>Authentication method to use. Takes one of "none", "pap", "chap", "mschap", "mschapv2" or "eap".
|
||||
Optional in 3GPP.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>user</option>=<replaceable>NAME</replaceable></term>
|
||||
<listitem><para>User name (if any) required by the network. Optional in 3GPP.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>password</option>=<replaceable>PASSWORD</replaceable></term>
|
||||
<listitem><para>Password (if any) required by the network. Optional in 3GPP.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ip-type</option>=<replaceable>TYPE</replaceable></term>
|
||||
<listitem><para>Addressing type. Takes one of "none", "ipv4", "ipv6", "ipv4v6" or "any".
|
||||
Optional in 3GPP and CDMA.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>allow-roaming</option>=<replaceable>BOOL</replaceable></term>
|
||||
<listitem><para>A boolean. When true, connection is allowed during roaming. When false,
|
||||
connection is not allowed during roaming. Optional in 3GPP.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>pin</option>=<replaceable>PIN</replaceable></term>
|
||||
<listitem><para>SIM-PIN unlock code.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>operator-id</option>=<replaceable>ID</replaceable></term>
|
||||
<listitem><para>ETSI MCC-MNC of a network to force registration.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RouteMetric=</varname></term>
|
||||
<listitem>
|
||||
<para>Set the routing metric for routes specified by the mobile network (including the prefix route
|
||||
added for the specified prefix). Takes an unsigned integer in the range 0…4294967295.
|
||||
When unset or set to 0, the kernel's default value will be used.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>UseGateway=</varname></term>
|
||||
<listitem>
|
||||
<para>When true (the default), the router address will be configured as the default gateway.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
<example>
|
||||
@ -6882,29 +6771,6 @@ Xfrm=xfrm0</programlisting>
|
||||
This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
|
||||
If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
|
||||
</para>
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Connecting to a cellular network with ModemManager</title>
|
||||
<programlisting># /etc/systemd/network/27-wwan0.network
|
||||
[Match]
|
||||
Name=wwan0
|
||||
|
||||
[Network]
|
||||
LLDP=no
|
||||
LinkLocalAddressing=no
|
||||
IPv6AcceptRA=no
|
||||
|
||||
[ModemManager]
|
||||
SimpleConnectProperties=apn=internet pin=1111
|
||||
RouteMetric=30
|
||||
UseGateway=yes</programlisting>
|
||||
|
||||
<para>This connects a cellular modem to a broadband network matched with the network interface <literal>wwan0</literal>,
|
||||
with APN name <literal>internet</literal>, SIM card pin unlock code <literal>1111</literal> and sets up a default
|
||||
gateway with route metric of 30.
|
||||
</para>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ Packages=
|
||||
github-cli
|
||||
lcov
|
||||
libucontext
|
||||
musl
|
||||
mypy
|
||||
pkgconf
|
||||
ruff
|
||||
|
||||
@ -5,12 +5,7 @@ Distribution=fedora
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
gh
|
||||
lcov
|
||||
libgcrypt-devel
|
||||
libgpg-error-devel
|
||||
musl-libc
|
||||
musl-clang
|
||||
musl-gcc
|
||||
gh
|
||||
ruff
|
||||
shellcheck
|
||||
|
||||
@ -5,19 +5,11 @@ SUBSYSTEM!="input", GOTO="persistent_input_end"
|
||||
SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
|
||||
# Bluetooth devices don't always have the bluetooth subsystem
|
||||
ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
|
||||
SUBSYSTEMS=="acpi", ENV{ID_BUS}="acpi"
|
||||
# platform must be before serio as serio can be child
|
||||
SUBSYSTEMS=="platform", ENV{ID_BUS}="platform"
|
||||
SUBSYSTEMS=="i2c", ENV{ID_BUS}="i2c"
|
||||
SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi"
|
||||
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
|
||||
|
||||
SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"
|
||||
|
||||
# subsystems before (usb, platform, i2c) can be under pci so only set them if we still have no ID_BUS.
|
||||
# we could set this the first but will break the ENV{ID_BUS}=="" condition for usb.
|
||||
SUBSYSTEMS=="pci", ENV{ID_BUS}=="", ENV{ID_BUS}="pci"
|
||||
|
||||
# determine class name for persistent symlinks
|
||||
ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
|
||||
ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
# do not edit this file, it will be overwritten on update
|
||||
|
||||
# ID_INTEGRATION variable tells us if a device is internal (inherent part of the system) or external otherwise.
|
||||
# This must be loaded after 60-persistent-*.rules to have ID_BUS.
|
||||
|
||||
ACTION=="remove", GOTO="integration_end"
|
||||
ENV{ID_BUS}=="", GOTO="integration_end"
|
||||
|
||||
# ACPI, platform, PS/2, I2C, RMI and PCI devices: Internal by default.
|
||||
ENV{ID_BUS}=="acpi|platform|i8042|i2c|rmi|pci", ENV{ID_INTEGRATION}="internal"
|
||||
|
||||
# Bluetooth devices: External by default.
|
||||
ENV{ID_BUS}=="bluetooth", ENV{ID_INTEGRATION}="external"
|
||||
|
||||
# USB devices: Internal if it's connected to a fixed port, external to a removable or unknown.
|
||||
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="fixed", ENV{ID_INTEGRATION}="internal"
|
||||
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="removable|unknown", ENV{ID_INTEGRATION}="external"
|
||||
|
||||
# libinput compatibility variables, must be loaded before 70-(joystick|touchpad).rules to allow hwdb quirks to override.
|
||||
ENV{ID_INPUT}=="", GOTO="integration_libinput_end"
|
||||
ENV{ID_INPUT_JOYSTICK}=="1", ENV{ID_INPUT_JOYSTICK_INTEGRATION}="$env{ID_INTEGRATION}"
|
||||
ENV{ID_INPUT_TOUCHPAD}=="1", ENV{ID_INPUT_TOUCHPAD_INTEGRATION}="$env{ID_INTEGRATION}"
|
||||
LABEL="integration_libinput_end"
|
||||
|
||||
LABEL="integration_end"
|
||||
@ -23,7 +23,6 @@ rules = [
|
||||
'60-persistent-v4l.rules',
|
||||
'60-sensor.rules',
|
||||
'60-serial.rules',
|
||||
'65-integration.rules',
|
||||
'70-camera.rules',
|
||||
'70-joystick.rules',
|
||||
'70-mouse.rules',
|
||||
|
||||
@ -348,8 +348,8 @@ static int clamp_brightness(
|
||||
assert(brightness);
|
||||
|
||||
/* Some systems turn the backlight all the way off at the lowest levels. This clamps the saved
|
||||
* brightness to at least 1 or 1% of max_brightness (whichever is bigger) in case of 'backlight' subsystem.
|
||||
* This avoids preserving an unreadably dim screen, which would otherwise force the user to disable
|
||||
* brightness to at least 1 or 5% of max_brightness in case of 'backlight' subsystem. This
|
||||
* avoids preserving an unreadably dim screen, which would otherwise force the user to disable
|
||||
* state restoration. */
|
||||
|
||||
min_brightness = (unsigned) ((double) max_brightness * percent / 100);
|
||||
@ -385,7 +385,7 @@ static int shall_clamp(sd_device *device, unsigned *ret) {
|
||||
return r;
|
||||
if (r > 0) {
|
||||
property = "ID_BACKLIGHT_CLAMP";
|
||||
default_percent = 1;
|
||||
default_percent = 5;
|
||||
} else {
|
||||
property = "ID_LEDS_CLAMP";
|
||||
default_percent = 0;
|
||||
|
||||
@ -32,6 +32,8 @@
|
||||
* message.
|
||||
*/
|
||||
|
||||
struct iovec;
|
||||
|
||||
typedef struct LogContext {
|
||||
unsigned n_ref;
|
||||
/* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include <sys/mount.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
@ -216,6 +215,53 @@ int namespace_open(
|
||||
return pidref_namespace_open(&pidref, ret_pidns_fd, ret_mntns_fd, ret_netns_fd, ret_userns_fd, ret_root_fd);
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
int r;
|
||||
|
||||
/* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */
|
||||
block_dlopen();
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
/* Can't setns to your own userns, since then you could escalate from non-root to root in
|
||||
* your own namespace, so check if namespaces are equal before attempting to enter. */
|
||||
|
||||
r = is_our_namespace(userns_fd, NAMESPACE_USER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
userns_fd = -EBADF;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0)
|
||||
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
||||
return -errno;
|
||||
|
||||
if (mntns_fd >= 0)
|
||||
if (setns(mntns_fd, CLONE_NEWNS) < 0)
|
||||
return -errno;
|
||||
|
||||
if (netns_fd >= 0)
|
||||
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (userns_fd >= 0)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (root_fd >= 0) {
|
||||
if (fchdir(root_fd) < 0)
|
||||
return -errno;
|
||||
|
||||
if (chroot(".") < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (userns_fd >= 0)
|
||||
return reset_uid_gid();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
|
||||
int r;
|
||||
|
||||
@ -237,43 +283,20 @@ static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
|
||||
int r;
|
||||
|
||||
/* Similar to namespace_enter(), but operates on a set of namespaces that are potentially owned
|
||||
* by the userns ("delegated"), in which case we'll need to gain CAP_SYS_ADMIN by joining
|
||||
* the userns first, and the rest later. */
|
||||
|
||||
assert(userns_fd >= 0);
|
||||
|
||||
/* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */
|
||||
block_dlopen();
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
/* Can't setns to your own userns, since then you could escalate from non-root to root in
|
||||
* your own namespace, so check if namespaces are equal before attempting to enter. */
|
||||
|
||||
r = is_our_namespace(userns_fd, NAMESPACE_USER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
userns_fd = -EBADF;
|
||||
}
|
||||
|
||||
r = have_effective_cap(CAP_SYS_ADMIN);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
bool have_cap_sys_admin = r > 0;
|
||||
|
||||
if (!have_cap_sys_admin) {
|
||||
/* If we don't have CAP_SYS_ADMIN in our own user namespace, our best bet is to enter the
|
||||
* user namespace first (if we got one) to get CAP_SYS_ADMIN within the child user namespace,
|
||||
* and then hope the other namespaces are owned by the child user namespace. If they aren't,
|
||||
* we'll just get an EPERM later on when trying to setns() to them. */
|
||||
|
||||
if (userns_fd < 0)
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(EPERM),
|
||||
"Need CAP_SYS_ADMIN or a child user namespace to enter namespaces.");
|
||||
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0) {
|
||||
r = namespace_enter_one_idempotent(pidns_fd, NAMESPACE_PID);
|
||||
@ -293,10 +316,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
return r;
|
||||
}
|
||||
|
||||
if (userns_fd >= 0 && have_cap_sys_admin)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (root_fd >= 0) {
|
||||
if (fchdir(root_fd) < 0)
|
||||
return -errno;
|
||||
@ -305,15 +324,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
/* Try to become root in the user namespace but don't error out if we can't, since it's not
|
||||
* uncommon to have user namespaces without a root user in them. */
|
||||
r = reset_uid_gid();
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Unable to drop auxiliary groups or reset UID/GID, ignoring: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return maybe_setgroups(/* size = */ 0, NULL);
|
||||
}
|
||||
|
||||
int fd_is_namespace(int fd, NamespaceType type) {
|
||||
|
||||
@ -47,6 +47,7 @@ int namespace_open(
|
||||
int *ret_root_fd);
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
|
||||
|
||||
int fd_is_namespace(int fd, NamespaceType type);
|
||||
int is_our_namespace(int fd, NamespaceType type);
|
||||
|
||||
@ -1128,6 +1128,10 @@ bool is_main_thread(void) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa) {
|
||||
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
|
||||
}
|
||||
|
||||
unsigned long personality_from_string(const char *s) {
|
||||
Architecture architecture;
|
||||
|
||||
@ -1774,6 +1778,7 @@ int namespace_fork_full(
|
||||
int netns_fd,
|
||||
int userns_fd,
|
||||
int root_fd,
|
||||
bool delegated,
|
||||
PidRef *ret) {
|
||||
|
||||
_cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
|
||||
@ -1819,6 +1824,9 @@ int namespace_fork_full(
|
||||
|
||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||
|
||||
if (delegated)
|
||||
r = namespace_enter_delegated(userns_fd, pidns_fd, mntns_fd, netns_fd, root_fd);
|
||||
else
|
||||
r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
|
||||
if (r < 0) {
|
||||
log_full_errno(prio, r, "Failed to join namespace: %m");
|
||||
@ -1879,10 +1887,6 @@ int namespace_fork_full(
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa) {
|
||||
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
|
||||
}
|
||||
|
||||
int set_oom_score_adjust(int value) {
|
||||
char t[DECIMAL_STR_MAX(int)];
|
||||
|
||||
|
||||
@ -87,6 +87,8 @@ int pidref_from_same_root_fs(PidRef *a, PidRef *b);
|
||||
|
||||
bool is_main_thread(void);
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa);
|
||||
|
||||
#ifndef PERSONALITY_INVALID
|
||||
/* personality(2) documents that 0xFFFFFFFFUL is used for querying the
|
||||
* current personality, hence let's use that here as error
|
||||
@ -199,6 +201,7 @@ int namespace_fork_full(
|
||||
int netns_fd,
|
||||
int userns_fd,
|
||||
int root_fd,
|
||||
bool delegated,
|
||||
PidRef *ret);
|
||||
|
||||
static inline int namespace_fork(
|
||||
@ -213,11 +216,10 @@ static inline int namespace_fork(
|
||||
PidRef *ret) {
|
||||
|
||||
return namespace_fork_full(outer_name, inner_name, NULL, 0, flags,
|
||||
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd,
|
||||
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd, false,
|
||||
ret);
|
||||
}
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa);
|
||||
int set_oom_score_adjust(int value);
|
||||
int get_oom_score_adjust(int *ret);
|
||||
|
||||
@ -233,6 +235,9 @@ int get_oom_score_adjust(int *ret);
|
||||
|
||||
assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
|
||||
|
||||
/* Like TAKE_PTR() but for pid_t, resetting them to 0 */
|
||||
#define TAKE_PID(pid) TAKE_GENERIC(pid, pid_t, 0)
|
||||
|
||||
int setpriority_closest(int priority);
|
||||
|
||||
_noreturn_ void freeze(void);
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
@ -1667,7 +1666,7 @@ int openpt_allocate_in_namespace(
|
||||
|
||||
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to open namespaces of PID "PID_FMT": %m", pidref->pid);
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
@ -437,7 +437,7 @@ void cleanup_tmpfile_data_done(struct cleanup_tmpfile_data *d) {
|
||||
assert(d);
|
||||
|
||||
if (!d->dir_fd ||
|
||||
(*d->dir_fd < 0 && *d->dir_fd != AT_FDCWD) ||
|
||||
*d->dir_fd < 0 ||
|
||||
!d->filename ||
|
||||
!*d->filename)
|
||||
return;
|
||||
|
||||
@ -920,28 +920,19 @@ int maybe_setgroups(size_t size, const gid_t *list) {
|
||||
|
||||
/* Check if setgroups is allowed before we try to drop all the auxiliary groups */
|
||||
if (size == 0) { /* Dropping all aux groups? */
|
||||
|
||||
/* The kernel refuses setgroups() if there are no GID mappings in the current
|
||||
* user namespace, so check that beforehand and don't try to setgroups() if
|
||||
* there are no GID mappings. */
|
||||
_cleanup_fclose_ FILE *f = fopen("/proc/self/gid_map", "re");
|
||||
if (!f && errno != ENOENT)
|
||||
return -errno;
|
||||
if (f) {
|
||||
r = safe_fgetc(f, /* ret= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
log_debug("Skipping setgroups(), /proc/self/gid_map is empty");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_cleanup_free_ char *setgroups_content = NULL;
|
||||
bool can_setgroups;
|
||||
|
||||
r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
if (r == -ENOENT)
|
||||
/* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
|
||||
can_setgroups = true;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
if (r > 0 && streq(setgroups_content, "deny")) {
|
||||
else
|
||||
can_setgroups = streq(setgroups_content, "allow");
|
||||
|
||||
if (!can_setgroups) {
|
||||
log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -175,22 +175,26 @@ int install_random_seed(const char *esp) {
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to open random seed file for writing: %m");
|
||||
|
||||
CLEANUP_TMPFILE_AT(loader_dir_fd, tmp);
|
||||
|
||||
if (!warned) /* only warn once per seed file */
|
||||
(void) random_seed_verify_permissions(fd, S_IFREG);
|
||||
|
||||
r = loop_write(fd, buffer, sizeof(buffer));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write random seed file: %m");
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to write random seed file: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0)
|
||||
return log_error_errno(errno, "Failed to sync random seed file: %m");
|
||||
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0) {
|
||||
r = log_error_errno(errno, "Failed to sync random seed file: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (renameat(loader_dir_fd, tmp, loader_dir_fd, "random-seed") < 0)
|
||||
return log_error_errno(errno, "Failed to move random seed file into place: %m");
|
||||
if (renameat(loader_dir_fd, tmp, loader_dir_fd, "random-seed") < 0) {
|
||||
r = log_error_errno(errno, "Failed to move random seed file into place: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
tmp = mfree(tmp);
|
||||
|
||||
if (syncfs(fd) < 0)
|
||||
return log_error_errno(errno, "Failed to sync ESP file system: %m");
|
||||
@ -198,6 +202,12 @@ int install_random_seed(const char *esp) {
|
||||
log_info("Random seed file %s/loader/random-seed successfully %s (%zu bytes).", esp, refreshed ? "refreshed" : "written", sizeof(buffer));
|
||||
|
||||
return set_system_token();
|
||||
|
||||
fail:
|
||||
assert(tmp);
|
||||
(void) unlinkat(loader_dir_fd, tmp, 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int verb_random_seed(int argc, char *argv[], void *userdata) {
|
||||
|
||||
@ -642,12 +642,14 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = acquire_esp(/* unprivileged_mode= */ false,
|
||||
/* graceful= */ false,
|
||||
/* ret_part= */ NULL,
|
||||
|
||||
@ -1255,6 +1255,7 @@ int unit_refresh_credentials(Unit *u) {
|
||||
(int[]) { tunnel_fds[1] }, 1,
|
||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
|
||||
pidns_fd, mntns_fd, /* netns_fd = */ -EBADF, userns_fd, root_fd,
|
||||
/* delegated = */ MANAGER_IS_USER(u->manager),
|
||||
&child);
|
||||
if (r < 0)
|
||||
return log_full_errno(ERRNO_IS_NEG_PRIVILEGE(r) ? LOG_WARNING : LOG_ERR, r,
|
||||
|
||||
@ -171,11 +171,7 @@ int manager_serialize(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = varlink_server_serialize(m->varlink_server, /* name = */ NULL, f, fds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = varlink_server_serialize(m->metrics_varlink_server, "metrics", f, fds);
|
||||
r = varlink_server_serialize(m->varlink_server, f, fds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -286,6 +282,7 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
|
||||
}
|
||||
|
||||
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
||||
bool deserialize_varlink_sockets = false;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -493,28 +490,23 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
||||
r = strv_extend(&m->subscribed_as_strv, val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "varlink-server-metrics-"))) {
|
||||
if (m->objective == MANAGER_RELOAD)
|
||||
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
|
||||
continue;
|
||||
|
||||
r = manager_setup_varlink_metrics_server(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to setup metrics varlink server, ignoring: %m");
|
||||
else
|
||||
(void) varlink_server_deserialize_one(m->metrics_varlink_server, val, fds);
|
||||
|
||||
} else if ((val = startswith(l, "varlink-server-"))) {
|
||||
if (m->objective == MANAGER_RELOAD)
|
||||
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
|
||||
continue;
|
||||
|
||||
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
|
||||
if (!m->varlink_server) {
|
||||
r = manager_setup_varlink_server(m);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
|
||||
else
|
||||
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
|
||||
continue;
|
||||
}
|
||||
|
||||
deserialize_varlink_sockets = true;
|
||||
}
|
||||
|
||||
/* To avoid unnecessary deserialization (i.e. during reload vs. reexec) we only deserialize
|
||||
* the FDs if we had to create a new m->varlink_server. The deserialize_varlink_sockets flag
|
||||
* is initialized outside of the loop, is flipped after the VarlinkServer is setup, and
|
||||
* remains set until all serialized contents are handled. */
|
||||
if (deserialize_varlink_sockets)
|
||||
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
|
||||
} else if ((val = startswith(l, "dump-ratelimit=")))
|
||||
deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val);
|
||||
else if ((val = startswith(l, "reload-reexec-ratelimit=")))
|
||||
|
||||
@ -112,7 +112,7 @@ static int ip_address_access_build_json(sd_json_variant **ret, const char *name,
|
||||
r = sd_json_variant_append_arraybo(
|
||||
&v,
|
||||
SD_JSON_BUILD_PAIR_INTEGER("family", i->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR("address", i->family, &i->address),
|
||||
JSON_BUILD_PAIR_IN_ADDR("address", &i->address, i->family),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("prefixLength", i->prefixlen));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -299,7 +299,6 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void
|
||||
SD_JSON_BUILD_OBJECT(
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->restrict_network_interfaces_is_allow_list),
|
||||
JSON_BUILD_PAIR_STRING_SET("interfaces", c->restrict_network_interfaces))),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("BindNetworkInterface", c->bind_network_interface),
|
||||
JSON_BUILD_PAIR_CALLBACK_NON_NULL("NFTSet", nft_set_build_json, &c->nft_set_context),
|
||||
|
||||
/* BPF programs */
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-json.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "manager.h"
|
||||
#include "metrics.h"
|
||||
@ -178,10 +175,10 @@ const MetricFamily metric_family_table[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return metrics_method_describe(metric_family_table, link, parameters, flags, userdata);
|
||||
}
|
||||
|
||||
int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return metrics_method_list(metric_family_table, link, parameters, flags, userdata);
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "core-forward.h"
|
||||
#include "sd-varlink.h"
|
||||
#include "sd-json.h"
|
||||
|
||||
#define METRIC_IO_SYSTEMD_MANAGER_PREFIX "io.systemd.Manager."
|
||||
|
||||
int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||
int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||
int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unit.h"
|
||||
#include "varlink.h"
|
||||
#include "varlink-dynamic-user.h"
|
||||
@ -374,8 +375,6 @@ int manager_setup_varlink_server(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to allocate Varlink server: %m");
|
||||
|
||||
(void) sd_varlink_server_set_description(s, "varlink-api");
|
||||
|
||||
r = sd_varlink_server_add_interface_many(
|
||||
s,
|
||||
&vl_interface_io_systemd_Manager,
|
||||
@ -426,64 +425,26 @@ int manager_setup_varlink_server(Manager *m) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_setup_varlink_metrics_server(Manager *m) {
|
||||
static int manager_setup_varlink_metrics_server(Manager *m) {
|
||||
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
|
||||
if (MANAGER_IS_SYSTEM(m))
|
||||
flags |= SD_VARLINK_SERVER_ACCOUNT_UID;
|
||||
|
||||
return metrics_setup_varlink_server(&m->metrics_varlink_server, flags,
|
||||
m->event, EVENT_PRIORITY_IPC,
|
||||
vl_method_list_metrics, vl_method_describe_metrics,
|
||||
m);
|
||||
}
|
||||
|
||||
static int varlink_server_listen_many_idempotent_sentinel(
|
||||
sd_varlink_server *s,
|
||||
bool known_fresh,
|
||||
const char *prefix,
|
||||
...) {
|
||||
|
||||
va_list ap;
|
||||
int r = 0;
|
||||
|
||||
assert(s);
|
||||
|
||||
va_start(ap, prefix);
|
||||
for (const char *address; (address = va_arg(ap, const char*)); ) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (prefix) {
|
||||
p = path_join(prefix, address);
|
||||
if (!p) {
|
||||
r = log_oom();
|
||||
break;
|
||||
}
|
||||
|
||||
address = p;
|
||||
}
|
||||
|
||||
/* We might have got sockets through deserialization. Do not bind to them twice. */
|
||||
if (!known_fresh && varlink_server_contains_socket(s, address))
|
||||
continue;
|
||||
|
||||
r = sd_varlink_server_listen_address(s, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
r = metrics_setup_varlink_server(
|
||||
&m->metrics_varlink_server, flags, m->event, vl_method_list, vl_method_describe, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define varlink_server_listen_many_idempotent(s, known_fresh, prefix, ...) \
|
||||
varlink_server_listen_many_idempotent_sentinel((s), (known_fresh), (prefix), __VA_ARGS__, NULL)
|
||||
|
||||
static int manager_varlink_init_system_api(Manager *m) {
|
||||
static int manager_varlink_init_system(Manager *m) {
|
||||
int r;
|
||||
_cleanup_free_ char *metrics_address = NULL;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -492,73 +453,74 @@ static int manager_varlink_init_system_api(Manager *m) {
|
||||
return log_error_errno(r, "Failed to set up varlink server: %m");
|
||||
bool fresh = r > 0;
|
||||
|
||||
if (!MANAGER_IS_TEST_RUN(m)) {
|
||||
r = varlink_server_listen_many_idempotent(
|
||||
m->varlink_server, fresh,
|
||||
/* prefix = */ NULL,
|
||||
"/run/systemd/io.systemd.Manager",
|
||||
"/run/systemd/userdb/io.systemd.DynamicUser",
|
||||
VARLINK_PATH_MANAGED_OOM_SYSTEM);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_varlink_init_user_api(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (MANAGER_IS_TEST_RUN(m))
|
||||
return 0;
|
||||
|
||||
r = manager_setup_varlink_server(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up varlink server: %m");
|
||||
bool fresh = r > 0;
|
||||
|
||||
r = varlink_server_listen_many_idempotent(
|
||||
m->varlink_server, fresh,
|
||||
m->prefix[EXEC_DIRECTORY_RUNTIME],
|
||||
"systemd/io.systemd.Manager");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_varlink_managed_oom_connect(m);
|
||||
}
|
||||
|
||||
static int manager_varlink_init_metrics(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (MANAGER_IS_TEST_RUN(m))
|
||||
return 0;
|
||||
|
||||
r = manager_setup_varlink_metrics_server(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
|
||||
bool fresh = r > 0;
|
||||
bool metrics_fresh = r > 0;
|
||||
|
||||
return varlink_server_listen_many_idempotent(
|
||||
m->metrics_varlink_server, fresh,
|
||||
m->prefix[EXEC_DIRECTORY_RUNTIME],
|
||||
"systemd/report/io.systemd.Manager");
|
||||
}
|
||||
|
||||
int manager_varlink_init(Manager *m) {
|
||||
int r;
|
||||
|
||||
if (MANAGER_IS_SYSTEM(m))
|
||||
r = manager_varlink_init_system_api(m);
|
||||
else
|
||||
r = manager_varlink_init_user_api(m);
|
||||
r = runtime_directory_generic(m->runtime_scope, "systemd/report/io.systemd.Manager", &metrics_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_varlink_init_metrics(m);
|
||||
if (!MANAGER_IS_TEST_RUN(m)) {
|
||||
FOREACH_STRING(address,
|
||||
"/run/systemd/userdb/io.systemd.DynamicUser",
|
||||
VARLINK_PATH_MANAGED_OOM_SYSTEM,
|
||||
"/run/systemd/io.systemd.Manager",
|
||||
metrics_address) {
|
||||
|
||||
sd_varlink_server *server = streq(address, metrics_address) ? m->metrics_varlink_server : m->varlink_server;
|
||||
fresh = streq(address, metrics_address) ? metrics_fresh : fresh;
|
||||
/* We might have got sockets through deserialization. Do not bind to them twice. */
|
||||
if (!fresh && varlink_server_contains_socket(server, address))
|
||||
continue;
|
||||
|
||||
r = sd_varlink_server_listen_address(server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int manager_varlink_init_user(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (MANAGER_IS_TEST_RUN(m))
|
||||
return 0;
|
||||
|
||||
r = manager_setup_varlink_server(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up varlink server: %m");
|
||||
bool fresh = r > 0;
|
||||
|
||||
FOREACH_STRING(a,
|
||||
"systemd/io.systemd.Manager") {
|
||||
_cleanup_free_ char *address = NULL;
|
||||
address = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], a);
|
||||
if (!address)
|
||||
return -ENOMEM;
|
||||
/* We might have got sockets through deserialization. Do not bind to them twice. */
|
||||
if (!fresh && varlink_server_contains_socket(m->varlink_server, address))
|
||||
continue;
|
||||
|
||||
r = sd_varlink_server_listen_address(m->varlink_server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
|
||||
}
|
||||
|
||||
r = manager_setup_varlink_metrics_server(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
|
||||
|
||||
return manager_varlink_managed_oom_connect(m);
|
||||
}
|
||||
|
||||
int manager_varlink_init(Manager *m) {
|
||||
return MANAGER_IS_SYSTEM(m) ? manager_varlink_init_system(m) : manager_varlink_init_user(m);
|
||||
}
|
||||
|
||||
void manager_varlink_done(Manager *m) {
|
||||
@ -572,7 +534,6 @@ void manager_varlink_done(Manager *m) {
|
||||
|
||||
m->varlink_server = sd_varlink_server_unref(m->varlink_server);
|
||||
m->managed_oom_varlink = sd_varlink_close_unref(m->managed_oom_varlink);
|
||||
|
||||
m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server);
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
#include "core-forward.h"
|
||||
|
||||
int manager_setup_varlink_server(Manager *m);
|
||||
int manager_setup_varlink_metrics_server(Manager *m);
|
||||
|
||||
int manager_varlink_init(Manager *m);
|
||||
void manager_varlink_done(Manager *m);
|
||||
|
||||
@ -1793,12 +1793,14 @@ static int vl_method_list_transfers(sd_varlink *link, sd_json_variant *parameter
|
||||
|
||||
assert(link);
|
||||
assert(parameters);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = varlink_set_sentinel(link, "io.systemd.Import.NoTransfers");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -317,6 +317,8 @@ int dhcp_server_static_leases_append_json(sd_dhcp_server *server, sd_json_varian
|
||||
|
||||
int dhcp_server_save_leases(sd_dhcp_server *server) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
sd_id128_t boot_id;
|
||||
int r;
|
||||
|
||||
@ -353,27 +355,25 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
r = fopen_temporary_at(server->lease_dir_fd, server->lease_file, &f, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
CLEANUP_TMPFILE_AT(server->lease_dir_fd, temp_path);
|
||||
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
r = sd_json_variant_dump(v, SD_JSON_FORMAT_NEWLINE | SD_JSON_FORMAT_FLUSH, f, /* prefix= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto failure;
|
||||
|
||||
r = conservative_renameat(server->lease_dir_fd, temp_path, server->lease_dir_fd, server->lease_file);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto failure;
|
||||
|
||||
temp_path = mfree(temp_path); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
(void) unlinkat(server->lease_dir_fd, temp_path, /* flags= */ 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int json_dispatch_chaddr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "sd-forward.h"
|
||||
#include "log.h"
|
||||
#include "string-util.h" /* IWYU pragma: keep */
|
||||
|
||||
#define JSON_VARIANT_REPLACE(v, q) \
|
||||
@ -175,9 +175,9 @@ enum {
|
||||
_JSON_BUILD_PAIR_VARIANT_NON_EMPTY,
|
||||
/* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */
|
||||
_JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY,
|
||||
_JSON_BUILD_PAIR_IN4_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN6_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL,
|
||||
_JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL,
|
||||
@ -190,6 +190,12 @@ enum {
|
||||
_JSON_BUILD_PAIR_TRISTATE_NON_NULL,
|
||||
_JSON_BUILD_PAIR_PIDREF_NON_NULL,
|
||||
_JSON_BUILD_PAIR_DEVNUM,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING,
|
||||
_JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING,
|
||||
_JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL,
|
||||
|
||||
_SD_JSON_BUILD_REALLYMAX,
|
||||
};
|
||||
@ -200,7 +206,7 @@ enum {
|
||||
#define JSON_BUILD_CONST_STRING(s) _SD_JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s)
|
||||
#define JSON_BUILD_IN4_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr))
|
||||
#define JSON_BUILD_IN6_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr))
|
||||
#define JSON_BUILD_IN_ADDR(f, v) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
|
||||
#define JSON_BUILD_IN_ADDR(v, f) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
|
||||
#define JSON_BUILD_ETHER_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr))
|
||||
#define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v }
|
||||
#define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s }
|
||||
@ -223,15 +229,9 @@ enum {
|
||||
#define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (sd_json_variant*) { v }
|
||||
#define JSON_BUILD_PAIR_VARIANT_NON_EMPTY(name, v) _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, (const char*) { name }, (sd_json_variant*) { v }
|
||||
#define JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, v, f) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (const union in_addr_union*) { v }, (int) { f }
|
||||
#define JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, (const char*) { name }, (const struct ether_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v }
|
||||
#define JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL(name, t) _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, (const char*) { name }, (dual_timestamp*) { t }
|
||||
@ -243,12 +243,18 @@ enum {
|
||||
#define JSON_BUILD_PAIR_OCTESCAPE_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_HEX_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n }
|
||||
#define JSON_BUILD_PAIR_TRISTATE_NON_NULL(name, i) _JSON_BUILD_PAIR_TRISTATE_NON_NULL, (const char*) { name }, (int) { i }
|
||||
#define JSON_BUILD_PAIR_PIDREF_NON_NULL(name, p) _JSON_BUILD_PAIR_PIDREF_NON_NULL, (const char*) { name }, (const PidRef*) { p }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, (const char*) { name }, (const struct in6_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, (const char*) { name }, (const struct in_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
|
||||
|
||||
#define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov))
|
||||
#define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov))
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_IN_ADDR(name, f, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(f, v))
|
||||
#define JSON_BUILD_PAIR_IN_ADDR(name, v, f) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f))
|
||||
#define JSON_BUILD_PAIR_ETHER_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_HW_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_STRING_SET(name, s) SD_JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s))
|
||||
|
||||
@ -3370,8 +3370,8 @@ done:
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
FOREACH_ARRAY(i, stack, n_stack)
|
||||
json_stack_release(i);
|
||||
for (size_t i = 0; i < n_stack; i++)
|
||||
json_stack_release(stack + i);
|
||||
|
||||
free(stack);
|
||||
|
||||
@ -4666,9 +4666,63 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL:
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL:
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: {
|
||||
case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: {
|
||||
const struct in_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in_addr *);
|
||||
|
||||
if (a && in4_addr_is_set(a) && current->n_suppress == 0) {
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two items */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL: {
|
||||
const struct in6_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in6_addr *);
|
||||
|
||||
if (a && in6_addr_is_set(a) && current->n_suppress == 0) {
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two items */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: {
|
||||
const union in_addr_union *a;
|
||||
const char *n;
|
||||
int f;
|
||||
@ -4679,16 +4733,10 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
f = va_arg(ap, int);
|
||||
a = va_arg(ap, const union in_addr_union *);
|
||||
f = va_arg(ap, int);
|
||||
|
||||
if (current->n_suppress == 0 &&
|
||||
((a && in_addr_is_set(f, a)) ||
|
||||
command == _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING)) {
|
||||
|
||||
if (!a)
|
||||
a = &IN_ADDR_NULL;
|
||||
|
||||
if (a && in_addr_is_set(f, a) && current->n_suppress == 0) {
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@ -4696,36 +4744,9 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (IN_SET(command, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL)) {
|
||||
_cleanup_free_ char *string_key_name = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
|
||||
|
||||
string_key_name = strjoin(n, "String");
|
||||
if (!string_key_name) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_string(&string_key, string_key_name);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_value, IN_ADDR_TO_STRING(f, a));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_key);
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_value);
|
||||
}
|
||||
}
|
||||
|
||||
n_subtract = command == _JSON_BUILD_PAIR_IN_ADDR_NON_NULL ? 2 : 4;
|
||||
n_subtract = 2; /* we generated two items */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
@ -4875,6 +4896,207 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL:
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: {
|
||||
const union in_addr_union *a;
|
||||
const char *n;
|
||||
int f;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
f = va_arg(ap, int);
|
||||
a = va_arg(ap, const union in_addr_union *);
|
||||
|
||||
if (current->n_suppress == 0) {
|
||||
bool have_address = a && in_addr_is_set(f, a);
|
||||
|
||||
if (have_address || command != _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL) {
|
||||
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
|
||||
|
||||
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
|
||||
* For NON_NULL variant, we only get here when have_address is true. */
|
||||
if (a) {
|
||||
r = in_addr_to_string(f, a, &addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
string_key_name = strjoin(n, "String");
|
||||
if (!string_key_name) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_key, string_key_name);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_value, addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_key);
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_value);
|
||||
}
|
||||
}
|
||||
|
||||
n_subtract = 4; /* we generated two pairs (binary and string) */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL:
|
||||
case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING: {
|
||||
const struct in6_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in6_addr *);
|
||||
|
||||
if (current->n_suppress == 0) {
|
||||
bool have_address = a && in6_addr_is_set(a);
|
||||
|
||||
if (have_address || command != _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL) {
|
||||
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
|
||||
|
||||
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
|
||||
* For NON_NULL variant, we only get here when have_address is true. */
|
||||
if (a) {
|
||||
r = in6_addr_to_string(a, &addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
string_key_name = strjoin(n, "String");
|
||||
if (!string_key_name) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_key, string_key_name);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_value, addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_key);
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_value);
|
||||
}
|
||||
}
|
||||
|
||||
n_subtract = 4; /* we generated two pairs (binary and string) */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL:
|
||||
case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING: {
|
||||
const struct in_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in_addr *);
|
||||
|
||||
if (current->n_suppress == 0) {
|
||||
bool have_address = a && !in4_addr_is_null(a);
|
||||
|
||||
if (have_address || command != _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL) {
|
||||
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
|
||||
|
||||
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
|
||||
* For NON_NULL variant, we only get here when have_address is true. */
|
||||
if (a) {
|
||||
union in_addr_union addr_union = { .in = *a };
|
||||
r = in_addr_to_string(AF_INET, &addr_union, &addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
string_key_name = strjoin(n, "String");
|
||||
if (!string_key_name) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_key, string_key_name);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_json_variant_new_string(&string_value, addr_str);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_key);
|
||||
current->elements[current->n_elements++] = TAKE_PTR(string_value);
|
||||
}
|
||||
}
|
||||
|
||||
n_subtract = 4; /* we generated two pairs (binary and string) */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: {
|
||||
sd_json_build_callback_t cb;
|
||||
void *userdata;
|
||||
@ -5005,8 +5227,8 @@ done:
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
FOREACH_ARRAY(i, stack, n_stack)
|
||||
json_stack_release(i);
|
||||
for (size_t i = 0; i < n_stack; i++)
|
||||
json_stack_release(stack + i);
|
||||
|
||||
free(stack);
|
||||
|
||||
|
||||
@ -247,20 +247,28 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
|
||||
/* stdio_fds= */ NULL,
|
||||
/* except_fds= */ (int[]) { pair[1] },
|
||||
/* n_except_fds= */ 1,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||
&pidref);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||
if (r == 0) {
|
||||
char spid[DECIMAL_STR_MAX(pid_t)+1];
|
||||
const char *setenv_list[] = {
|
||||
"LISTEN_PID", spid,
|
||||
"LISTEN_FDS", "1",
|
||||
"LISTEN_PID", spid,
|
||||
"LISTEN_FDNAMES", "varlink",
|
||||
NULL, NULL,
|
||||
};
|
||||
/* Child */
|
||||
|
||||
pair[0] = -EBADF;
|
||||
|
||||
r = move_fd(pair[1], 3, /* cloexec= */ false);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to move file descriptor to 3: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
xsprintf(spid, PID_FMT, pidref.pid);
|
||||
|
||||
uint64_t pidfdid;
|
||||
@ -356,7 +364,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
||||
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
|
||||
/* except_fds= */ NULL,
|
||||
/* n_except_fds= */ 0,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||
&pidref);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||
@ -440,7 +448,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
||||
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
|
||||
/* except_fds= */ NULL,
|
||||
/* n_except_fds= */ 0,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||
&pidref);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||
@ -1381,14 +1389,15 @@ static int varlink_format_queue(sd_varlink *v) {
|
||||
* would not corrupt our fd message boundaries */
|
||||
|
||||
while (v->output_queue) {
|
||||
_cleanup_free_ int *array = NULL;
|
||||
|
||||
assert(v->n_output_queue > 0);
|
||||
|
||||
VarlinkJsonQueueItem *q = v->output_queue;
|
||||
|
||||
if (v->n_output_fds > 0) /* unwritten fds? if we'd add more we'd corrupt the fd message boundaries, hence wait */
|
||||
return 0;
|
||||
|
||||
VarlinkJsonQueueItem *q = v->output_queue;
|
||||
_cleanup_free_ int *array = NULL;
|
||||
|
||||
if (q->n_fds > 0) {
|
||||
array = newdup(int, q->fds, q->n_fds);
|
||||
if (!array)
|
||||
@ -1400,7 +1409,8 @@ static int varlink_format_queue(sd_varlink *v) {
|
||||
return r;
|
||||
|
||||
/* Take possession of the queue element's fds */
|
||||
free_and_replace(v->output_fds, array);
|
||||
free(v->output_fds);
|
||||
v->output_fds = TAKE_PTR(array);
|
||||
v->n_output_fds = q->n_fds;
|
||||
q->n_fds = 0;
|
||||
|
||||
@ -1583,7 +1593,7 @@ static int varlink_dispatch_method(sd_varlink *v) {
|
||||
r = callback(v, parameters, flags, v->userdata);
|
||||
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
|
||||
if (r < 0) {
|
||||
varlink_log_errno(v, r, "Callback for '%s' returned error: %m", method);
|
||||
varlink_log_errno(v, r, "Callback for %s returned error: %m", method);
|
||||
|
||||
/* We got an error back from the callback. Propagate it to the client
|
||||
* if the method call remains unanswered. */
|
||||
@ -1612,16 +1622,6 @@ static int varlink_dispatch_method(sd_varlink *v) {
|
||||
varlink_log_errno(v, r, "Failed to process sentinel for method '%s': %m", method);
|
||||
} else {
|
||||
assert(!v->previous);
|
||||
|
||||
/* We're at the bare minimum referenced by sd_varlink_server and
|
||||
* sd_varlink_process() */
|
||||
if (v->n_ref <= 2) {
|
||||
r = varlink_log_errno(v, SYNTHETIC_ERRNO(EPROTO),
|
||||
"Callback for method '%s' returned without enqueuing a reply or stashing connection, failing.",
|
||||
method);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
}
|
||||
|
||||
@ -1857,10 +1857,19 @@ _public_ int sd_varlink_wait(sd_varlink *v, uint64_t timeout) {
|
||||
r = sd_varlink_get_timeout(v, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (t != USEC_INFINITY)
|
||||
t = usec_sub_unsigned(t, now(CLOCK_MONOTONIC));
|
||||
if (t != USEC_INFINITY) {
|
||||
usec_t n;
|
||||
|
||||
t = MIN(t, timeout);
|
||||
n = now(CLOCK_MONOTONIC);
|
||||
if (t < n)
|
||||
t = 0;
|
||||
else
|
||||
t = usec_sub_unsigned(t, n);
|
||||
}
|
||||
|
||||
if (timeout != USEC_INFINITY &&
|
||||
(t == USEC_INFINITY || timeout < t))
|
||||
t = timeout;
|
||||
|
||||
events = sd_varlink_get_events(v);
|
||||
if (events < 0)
|
||||
@ -2010,7 +2019,7 @@ _public_ int sd_varlink_flush(sd_varlink *v) {
|
||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
|
||||
|
||||
for (;;) {
|
||||
if (v->output_buffer_size == 0 && !v->output_queue)
|
||||
if (v->output_buffer_size == 0)
|
||||
break;
|
||||
if (v->write_disconnected)
|
||||
return -ECONNRESET;
|
||||
@ -2672,8 +2681,8 @@ _public_ int sd_varlink_reset_fds(sd_varlink *v) {
|
||||
* rollback the fds. Note that this is implicitly called whenever an error reply is sent, see
|
||||
* below. */
|
||||
|
||||
close_many(v->pushed_fds, v->n_pushed_fds);
|
||||
v->n_pushed_fds = 0;
|
||||
close_many(v->output_fds, v->n_output_fds);
|
||||
v->n_output_fds = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2697,7 +2706,7 @@ _public_ int sd_varlink_error(sd_varlink *v, const char *error_id, sd_json_varia
|
||||
return r;
|
||||
|
||||
/* If we have a previous reply still ready make sure we queue it before the error. We only
|
||||
* ever set "previous" if we're in a streaming method so we pass more=true unconditionally
|
||||
* ever set "previous" if we're in a streaming method so we pass more=true uncondtionally
|
||||
* here as we know we're still going to queue an error afterwards. */
|
||||
r = varlink_enqueue_item(v, v->previous);
|
||||
if (r < 0)
|
||||
@ -3547,8 +3556,8 @@ static int validate_connection(sd_varlink_server *server, const struct ucred *uc
|
||||
|
||||
c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
|
||||
if (c >= server->connections_per_uid_max) {
|
||||
varlink_server_log(server, "Per-UID connection limit of %u for '" UID_FMT "' reached, refusing.",
|
||||
server->connections_per_uid_max, ucred->uid);
|
||||
varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.",
|
||||
server->connections_per_uid_max);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -3601,7 +3610,7 @@ _public_ int sd_varlink_server_add_connection_pair(
|
||||
assert_return(input_fd >= 0, -EBADF);
|
||||
assert_return(output_fd >= 0, -EBADF);
|
||||
|
||||
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_MYSELF_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
|
||||
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
|
||||
|
||||
if (override_ucred)
|
||||
ucred = *override_ucred;
|
||||
@ -3743,7 +3752,11 @@ static int varlink_server_create_listen_fd_socket(sd_varlink_server *s, int fd,
|
||||
};
|
||||
|
||||
if (s->event) {
|
||||
r = varlink_server_add_socket_event_source(s, ss);
|
||||
r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_priority(ss->event_source, s->event_priority);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -4067,14 +4080,13 @@ _public_ int sd_varlink_server_set_exit_on_idle(sd_varlink_server *s, int b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss) {
|
||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority) {
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(s->event);
|
||||
assert(ss);
|
||||
assert(ss->server == s);
|
||||
assert(ss->fd >= 0);
|
||||
assert(!ss->event_source);
|
||||
|
||||
@ -4082,7 +4094,7 @@ int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSo
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_priority(es, s->event_priority);
|
||||
r = sd_event_source_set_priority(es, priority);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -4104,14 +4116,13 @@ _public_ int sd_varlink_server_attach_event(sd_varlink_server *s, sd_event *e, i
|
||||
return r;
|
||||
}
|
||||
|
||||
s->event_priority = priority;
|
||||
|
||||
LIST_FOREACH(sockets, ss, s->sockets) {
|
||||
r = varlink_server_add_socket_event_source(s, ss);
|
||||
r = varlink_server_add_socket_event_source(s, ss, priority);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->event_priority = priority;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -4282,16 +4293,20 @@ _public_ int sd_varlink_server_add_interface_many_internal(sd_varlink_server *s,
|
||||
}
|
||||
|
||||
_public_ unsigned sd_varlink_server_connections_max(sd_varlink_server *s) {
|
||||
int dts;
|
||||
|
||||
/* If a server is specified, return the setting for that server, otherwise the default value */
|
||||
if (s)
|
||||
return s->connections_max;
|
||||
|
||||
int dts = getdtablesize();
|
||||
dts = getdtablesize();
|
||||
assert_se(dts > 0);
|
||||
|
||||
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
|
||||
return MIN(VARLINK_DEFAULT_CONNECTIONS_MAX, (unsigned) dts / 4 * 3);
|
||||
if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3)
|
||||
return dts / 4 * 3;
|
||||
|
||||
return VARLINK_DEFAULT_CONNECTIONS_MAX;
|
||||
}
|
||||
|
||||
_public_ unsigned sd_varlink_server_connections_per_uid_max(sd_varlink_server *s) {
|
||||
|
||||
@ -262,4 +262,4 @@ static inline const char* varlink_server_description(sd_varlink_server *s) {
|
||||
VarlinkServerSocket* varlink_server_socket_free(VarlinkServerSocket *ss);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket *, varlink_server_socket_free);
|
||||
|
||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss);
|
||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority);
|
||||
|
||||
@ -376,10 +376,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
if (m->uid != 0 && m->class != MACHINE_HOST) {
|
||||
r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
|
||||
if (r < 0)
|
||||
return log_debug_errno(
|
||||
r,
|
||||
"Failed to check if machine '%s' is running in the root user namespace: %m",
|
||||
m->name);
|
||||
return r;
|
||||
if (r != 0)
|
||||
return sd_bus_error_set(
|
||||
error,
|
||||
|
||||
@ -273,7 +273,6 @@ static int vl_method_mute(
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
_cleanup_free_ Context *nc = new(Context, 1);
|
||||
if (!nc)
|
||||
@ -295,6 +294,9 @@ static int vl_method_mute(
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = sd_varlink_server_bind_disconnect(sd_varlink_get_server(link), vl_on_disconnect);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -89,8 +89,6 @@ systemd_networkd_extract_sources = files(
|
||||
'networkd-util.c',
|
||||
'networkd-wifi.c',
|
||||
'networkd-wiphy.c',
|
||||
'networkd-wwan.c',
|
||||
'networkd-wwan-bus.c',
|
||||
'tc/cake.c',
|
||||
'tc/codel.c',
|
||||
'tc/drr.c',
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "parse-util.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
@ -1771,9 +1770,6 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity) {
|
||||
if (!link->dhcp_client)
|
||||
return 0;
|
||||
|
||||
if (link_dhcp_enabled_by_bearer(link, AF_INET) == 0)
|
||||
return 0;
|
||||
|
||||
if (!link_has_carrier(link))
|
||||
return 0;
|
||||
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
#include "networkd-queue.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "set.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@ -495,9 +494,6 @@ int dhcp6_start(Link *link) {
|
||||
if (!link_dhcp6_enabled(link))
|
||||
return 0;
|
||||
|
||||
if (link_dhcp_enabled_by_bearer(link, AF_INET6) == 0)
|
||||
return 0;
|
||||
|
||||
if (!link_has_carrier(link))
|
||||
return 0;
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-route-util.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "ordered-set.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
@ -542,15 +541,6 @@ static int dns_append_json(Link *link, sd_json_variant **v) {
|
||||
return r;
|
||||
}
|
||||
|
||||
Bearer *b;
|
||||
|
||||
if (link_get_bearer(link, &b) >= 0)
|
||||
FOREACH_ARRAY(dns, b->dns, b->n_dns) {
|
||||
r = dns_append_json_one(link, *dns, NETWORK_CONFIG_SOURCE_MODEM_MANAGER, NULL, &array);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
|
||||
const struct in_addr *dns;
|
||||
union in_addr_union s;
|
||||
@ -623,7 +613,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne
|
||||
FOREACH_ARRAY(addr, res->addrs, res->n_addrs) {
|
||||
r = sd_json_variant_append_arrayb(
|
||||
&addrs_array,
|
||||
JSON_BUILD_IN_ADDR(res->family, addr));
|
||||
JSON_BUILD_IN_ADDR(addr, res->family));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -644,7 +634,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("DoHPath", res->dohpath),
|
||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports),
|
||||
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", res->family, p)));
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, res->family)));
|
||||
}
|
||||
|
||||
static int dnr_append_json(Link *link, sd_json_variant **v) {
|
||||
@ -733,7 +723,7 @@ static int server_append_json_one_addr(int family, const union in_addr_union *a,
|
||||
return sd_json_variant_append_arraybo(
|
||||
array,
|
||||
SD_JSON_BUILD_PAIR_INTEGER("Family", family),
|
||||
JSON_BUILD_PAIR_IN_ADDR("Address", family, a),
|
||||
JSON_BUILD_PAIR_IN_ADDR("Address", a, family),
|
||||
SD_JSON_BUILD_PAIR_STRING("AddressString", address_str),
|
||||
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
||||
JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p));
|
||||
|
||||
@ -63,7 +63,6 @@
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-sysctl.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "networkd-wwan-bus.h"
|
||||
#include "ordered-set.h"
|
||||
#include "parse-util.h"
|
||||
#include "set.h"
|
||||
@ -530,9 +529,6 @@ void link_check_ready(Link *link) {
|
||||
if (!link->sr_iov_configured)
|
||||
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
|
||||
|
||||
if (!link->bearer_configured)
|
||||
return (void) log_link_debug(link, "%s(): Bearer has not been applied.", __func__);
|
||||
|
||||
/* IPv6LL is assigned after the link gains its carrier. */
|
||||
if (!link->network->configure_without_carrier &&
|
||||
link_ipv6ll_enabled(link) &&
|
||||
@ -542,7 +538,7 @@ void link_check_ready(Link *link) {
|
||||
/* All static addresses must be ready. */
|
||||
bool has_static_address = false;
|
||||
SET_FOREACH(a, link->addresses) {
|
||||
if (!IN_SET(a->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_MODEM_MANAGER))
|
||||
if (a->source != NETWORK_CONFIG_SOURCE_STATIC)
|
||||
continue;
|
||||
if (!address_is_ready(a))
|
||||
return (void) log_link_debug(link, "%s(): static address %s is not ready.", __func__,
|
||||
@ -1297,10 +1293,6 @@ static int link_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_modem_reconfigure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!link_has_carrier(link))
|
||||
return 0;
|
||||
|
||||
|
||||
@ -108,7 +108,6 @@ typedef struct Link {
|
||||
unsigned set_link_messages;
|
||||
unsigned set_flags_messages;
|
||||
unsigned create_stacked_netdev_messages;
|
||||
unsigned bearer_messages;
|
||||
|
||||
Set *addresses;
|
||||
Set *neighbors;
|
||||
@ -142,7 +141,6 @@ typedef struct Link {
|
||||
bool master_set:1;
|
||||
bool stacked_netdevs_created:1;
|
||||
bool bridge_vlan_set:1;
|
||||
bool bearer_configured:1;
|
||||
|
||||
sd_dhcp_server *dhcp_server;
|
||||
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-manager-varlink.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "stat-util.h"
|
||||
#include "varlink-io.systemd.Network.h"
|
||||
#include "varlink-io.systemd.service.h"
|
||||
@ -93,30 +92,26 @@ static int vl_method_get_namespace_id(sd_varlink *link, sd_json_variant *paramet
|
||||
SD_JSON_BUILD_PAIR_CONDITION(nsid != UINT32_MAX, "NamespaceNSID", SD_JSON_BUILD_UNSIGNED(nsid)));
|
||||
}
|
||||
|
||||
static int dispatch_interface(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, bool polkit, Link **ret) {
|
||||
struct {
|
||||
typedef struct InterfaceInfo {
|
||||
int ifindex;
|
||||
const char *ifname;
|
||||
} info = {};
|
||||
Link *link = NULL;
|
||||
int r;
|
||||
} InterfaceInfo;
|
||||
|
||||
static int dispatch_interface(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, Link **ret) {
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, voffsetof(info, ifindex), SD_JSON_RELAX },
|
||||
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(info, ifname), 0 },
|
||||
{}
|
||||
}, dispatch_polkit_table[] = {
|
||||
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, voffsetof(info, ifindex), SD_JSON_RELAX },
|
||||
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(info, ifname), 0 },
|
||||
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(InterfaceInfo, ifindex), SD_JSON_RELAX },
|
||||
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(InterfaceInfo, ifname), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
InterfaceInfo info = {};
|
||||
Link *link = NULL;
|
||||
int r;
|
||||
|
||||
assert(vlink);
|
||||
assert(manager);
|
||||
assert(ret);
|
||||
|
||||
r = sd_varlink_dispatch(vlink, parameters, polkit ? dispatch_polkit_table : dispatch_table, &info);
|
||||
r = sd_varlink_dispatch(vlink, parameters, dispatch_table, &info);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@ -163,7 +158,7 @@ static int vl_method_get_lldp_neighbors(sd_varlink *vlink, sd_json_variant *para
|
||||
assert(vlink);
|
||||
assert(manager);
|
||||
|
||||
r = dispatch_interface(vlink, parameters, manager, /* polkit= */ false, &link);
|
||||
r = dispatch_interface(vlink, parameters, manager, &link);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@ -284,46 +279,6 @@ static int vl_method_set_persistent_storage(sd_varlink *vlink, sd_json_variant *
|
||||
return sd_varlink_reply(vlink, NULL);
|
||||
}
|
||||
|
||||
static int vl_method_link_up_or_down(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, bool up) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(vlink);
|
||||
assert(manager);
|
||||
|
||||
r = dispatch_interface(vlink, parameters, manager, /* polkit= */ true, &link);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
/* Require a specific link to be specified. */
|
||||
if (!link)
|
||||
return sd_varlink_error_invalid_parameter(vlink, JSON_VARIANT_STRING_CONST("InterfaceIndex"));
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
vlink,
|
||||
manager->bus,
|
||||
"org.freedesktop.network1.manage-links",
|
||||
/* details= */ NULL,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (!up)
|
||||
/* Stop all network engines while interface is still up to allow proper cleanup,
|
||||
* e.g. sending IPv6 shutdown RA messages before the interface is brought down. */
|
||||
(void) link_stop_engines(link, /* may_keep_dynamic = */ false);
|
||||
|
||||
return link_up_or_down_now_by_varlink(link, up, vlink);
|
||||
}
|
||||
|
||||
static int vl_method_link_up(sd_varlink *vlink, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return vl_method_link_up_or_down(vlink, parameters, userdata, /* up= */ true);
|
||||
}
|
||||
|
||||
static int vl_method_link_down(sd_varlink *vlink, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return vl_method_link_up_or_down(vlink, parameters, userdata, /* up= */ false);
|
||||
}
|
||||
|
||||
int manager_varlink_init(Manager *m, int fd) {
|
||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
||||
_unused_ _cleanup_close_ int fd_close = fd; /* take possession */
|
||||
@ -358,8 +313,6 @@ int manager_varlink_init(Manager *m, int fd) {
|
||||
"io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id,
|
||||
"io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors,
|
||||
"io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage,
|
||||
"io.systemd.Network.LinkUp", vl_method_link_up,
|
||||
"io.systemd.Network.LinkDown", vl_method_link_down,
|
||||
"io.systemd.service.Ping", varlink_method_ping,
|
||||
"io.systemd.service.SetLogLevel", varlink_method_set_log_level,
|
||||
"io.systemd.service.GetEnvironment", varlink_method_get_environment);
|
||||
|
||||
@ -46,7 +46,6 @@
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "networkd-wiphy.h"
|
||||
#include "networkd-wwan-bus.h"
|
||||
#include "ordered-set.h"
|
||||
#include "qdisc.h"
|
||||
#include "set.h"
|
||||
@ -97,8 +96,6 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r
|
||||
if (m->product_uuid_requested)
|
||||
(void) manager_request_product_uuid(m);
|
||||
|
||||
(void) manager_notify_mm_bus_connected(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,8 +145,6 @@ static int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
|
||||
|
||||
(void) manager_match_mm_signals(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -738,9 +733,6 @@ Manager* manager_free(Manager *m) {
|
||||
|
||||
set_free(m->rules);
|
||||
|
||||
sd_bus_slot_unref(m->slot_mm);
|
||||
hashmap_free(m->modems_by_path);
|
||||
|
||||
sd_netlink_unref(m->rtnl);
|
||||
sd_netlink_unref(m->genl);
|
||||
sd_netlink_unref(m->nfnl);
|
||||
|
||||
@ -99,10 +99,6 @@ typedef struct Manager {
|
||||
Hashmap *wiphy_by_index;
|
||||
Hashmap *wiphy_by_name;
|
||||
|
||||
/* ModemManager support */
|
||||
sd_bus_slot *slot_mm;
|
||||
Hashmap *modems_by_path;
|
||||
|
||||
/* For link speed meter */
|
||||
bool use_speed_meter;
|
||||
sd_event_source *speed_meter_event_source;
|
||||
|
||||
@ -40,7 +40,6 @@ _Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
|
||||
#include "networkd-radv.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "qdisc.h"
|
||||
#include "socket-util.h"
|
||||
#include "tclass.h"
|
||||
@ -493,9 +492,6 @@ CAN.ClassicDataLengthCode, config_parse_can_control_mode,
|
||||
CAN.Termination, config_parse_can_termination, 0, 0
|
||||
IPoIB.Mode, config_parse_ipoib_mode, 0, offsetof(Network, ipoib_mode)
|
||||
IPoIB.IgnoreUserspaceMulticastGroups, config_parse_tristate, 0, offsetof(Network, ipoib_umcast)
|
||||
ModemManager.SimpleConnectProperties, config_parse_strv, 0, offsetof(Network, mm_simple_connect_props)
|
||||
ModemManager.RouteMetric, config_parse_mm_route_metric, 0, 0
|
||||
ModemManager.UseGateway, config_parse_tristate, 0, offsetof(Network, mm_use_gateway)
|
||||
QDisc.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
|
||||
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
|
||||
BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0
|
||||
|
||||
@ -512,8 +512,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
|
||||
.ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
|
||||
.ipoib_umcast = -1,
|
||||
|
||||
.mm_use_gateway = -1,
|
||||
};
|
||||
|
||||
r = config_parse_many_full(
|
||||
@ -553,7 +551,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
"LLDP\0"
|
||||
"TrafficControlQueueingDiscipline\0"
|
||||
"CAN\0"
|
||||
"ModemManager\0"
|
||||
"QDisc\0"
|
||||
"BFIFO\0"
|
||||
"CAKE\0"
|
||||
@ -850,9 +847,6 @@ static Network *network_free(Network *network) {
|
||||
hashmap_free(network->qdiscs_by_section);
|
||||
hashmap_free(network->tclasses_by_section);
|
||||
|
||||
/* ModemManager */
|
||||
strv_free(network->mm_simple_connect_props);
|
||||
|
||||
return mfree(network);
|
||||
}
|
||||
|
||||
|
||||
@ -414,12 +414,6 @@ typedef struct Network {
|
||||
|
||||
/* NTP */
|
||||
char **ntp;
|
||||
|
||||
/* ModemManager support */
|
||||
char **mm_simple_connect_props;
|
||||
int mm_use_gateway;
|
||||
uint32_t mm_route_metric;
|
||||
bool mm_route_metric_set;
|
||||
} Network;
|
||||
|
||||
DECLARE_TRIVIAL_REF_UNREF_FUNC(Network, network);
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "device-private.h"
|
||||
#include "missing-network.h"
|
||||
#include "netif-util.h"
|
||||
@ -1343,103 +1341,6 @@ int link_up_or_down_now(Link *link, bool up) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct SetLinkVarlinkContext {
|
||||
Link *link;
|
||||
sd_varlink *vlink;
|
||||
bool up;
|
||||
} SetLinkVarlinkContext;
|
||||
|
||||
static SetLinkVarlinkContext* set_link_varlink_context_free(SetLinkVarlinkContext *ctx) {
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
if (ctx->vlink)
|
||||
sd_varlink_unref(ctx->vlink);
|
||||
if (ctx->link)
|
||||
link_unref(ctx->link);
|
||||
return mfree(ctx);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(SetLinkVarlinkContext*, set_link_varlink_context_free);
|
||||
|
||||
static void set_link_varlink_context_destroy(SetLinkVarlinkContext *ctx) {
|
||||
set_link_varlink_context_free(ctx);
|
||||
}
|
||||
|
||||
static int link_up_or_down_now_varlink_handler(sd_netlink *rtnl, sd_netlink_message *m, SetLinkVarlinkContext *ctx) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(ctx);
|
||||
|
||||
Link *link = ASSERT_PTR(ctx->link);
|
||||
sd_varlink *vlink = ASSERT_PTR(ctx->vlink);
|
||||
bool up = ctx->up;
|
||||
|
||||
assert(link->set_flags_messages > 0);
|
||||
|
||||
link->set_flags_messages--;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0) {
|
||||
(void) sd_varlink_error_errno(vlink, r);
|
||||
log_link_message_warning_errno(link, m, r, "Could not bring %s interface", up_or_down(up));
|
||||
} else
|
||||
(void) sd_varlink_reply(vlink, NULL);
|
||||
|
||||
if (link->state == LINK_STATE_LINGER)
|
||||
return 0;
|
||||
|
||||
r = link_call_getlink(link, get_link_update_flag_handler);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
link->set_flags_messages++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_up_or_down_now_by_varlink(Link *link, bool up, sd_varlink *vlink) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
|
||||
log_link_debug(link, "Bringing link %s (varlink)", up_or_down(up));
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
||||
|
||||
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set link flags: %m");
|
||||
|
||||
_cleanup_(set_link_varlink_context_freep) SetLinkVarlinkContext *ctx = new(SetLinkVarlinkContext, 1);
|
||||
if (!ctx)
|
||||
return log_oom();
|
||||
|
||||
*ctx = (SetLinkVarlinkContext) {
|
||||
.link = link_ref(link),
|
||||
.vlink = sd_varlink_ref(vlink),
|
||||
.up = up,
|
||||
};
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req,
|
||||
link_up_or_down_now_varlink_handler,
|
||||
set_link_varlink_context_destroy,
|
||||
ctx);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
|
||||
|
||||
TAKE_PTR(ctx);
|
||||
link->set_flags_messages++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_down_slave_links(Link *link) {
|
||||
Link *slave;
|
||||
int r;
|
||||
|
||||
@ -22,7 +22,6 @@ int link_request_to_activate(Link *link);
|
||||
int link_request_to_bring_up_or_down(Link *link, bool up);
|
||||
|
||||
int link_up_or_down_now(Link *link, bool up);
|
||||
int link_up_or_down_now_by_varlink(Link *link, bool up, sd_varlink *vlink);
|
||||
static inline int link_up_now(Link *link) {
|
||||
return link_up_or_down_now(link, true);
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-ntp.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "ordered-set.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
@ -110,14 +109,6 @@ static int link_put_dns(Link *link, OrderedSet **s) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
Bearer *b;
|
||||
|
||||
if (link_get_bearer(link, &b) >= 0) {
|
||||
r = ordered_set_put_dns_servers(s, link->ifindex, b->dns, b->n_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
@ -810,11 +801,6 @@ static int link_save(Link *link) {
|
||||
space = false;
|
||||
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
|
||||
|
||||
Bearer *b;
|
||||
|
||||
if (link_get_bearer(link, &b) >= 0)
|
||||
link_save_dns(link, f, b->dns, b->n_dns, &space);
|
||||
|
||||
/* DNR resolvers are not required to provide Do53 service, however resolved doesn't
|
||||
* know how to handle such a server so for now Do53 service is required, and
|
||||
* assumed. */
|
||||
|
||||
@ -25,7 +25,6 @@ static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX
|
||||
[NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
|
||||
[NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
|
||||
[NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
|
||||
[NETWORK_CONFIG_SOURCE_MODEM_MANAGER] = "ModemManager",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(network_config_source, NetworkConfigSource);
|
||||
|
||||
@ -14,7 +14,6 @@ typedef enum NetworkConfigSource {
|
||||
NETWORK_CONFIG_SOURCE_DHCP_PD,
|
||||
NETWORK_CONFIG_SOURCE_NDISC,
|
||||
NETWORK_CONFIG_SOURCE_RUNTIME, /* through D-Bus method */
|
||||
NETWORK_CONFIG_SOURCE_MODEM_MANAGER,
|
||||
_NETWORK_CONFIG_SOURCE_MAX,
|
||||
_NETWORK_CONFIG_SOURCE_INVALID = -EINVAL,
|
||||
} NetworkConfigSource;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Link Link;
|
||||
|
||||
/* From ModemManager-enums.h */
|
||||
typedef enum {
|
||||
MM_BEARER_IP_FAMILY_NONE = 0,
|
||||
MM_BEARER_IP_FAMILY_IPV4 = 1 << 0,
|
||||
MM_BEARER_IP_FAMILY_IPV6 = 1 << 1,
|
||||
MM_BEARER_IP_FAMILY_IPV4V6 = 1 << 2,
|
||||
MM_BEARER_IP_FAMILY_ANY = 0xFFFFFFFF,
|
||||
} MMBearerIpFamily;
|
||||
|
||||
typedef enum {
|
||||
MM_BEARER_TYPE_UNKNOWN = 0,
|
||||
MM_BEARER_TYPE_DEFAULT = 1,
|
||||
MM_BEARER_TYPE_DEFAULT_ATTACH = 2,
|
||||
MM_BEARER_TYPE_DEDICATED = 3,
|
||||
} MMBearerType;
|
||||
|
||||
typedef enum {
|
||||
MM_MODEM_STATE_FAILED = -1,
|
||||
MM_MODEM_STATE_UNKNOWN = 0,
|
||||
MM_MODEM_STATE_INITIALIZING = 1,
|
||||
MM_MODEM_STATE_LOCKED = 2,
|
||||
MM_MODEM_STATE_DISABLED = 3,
|
||||
MM_MODEM_STATE_DISABLING = 4,
|
||||
MM_MODEM_STATE_ENABLING = 5,
|
||||
MM_MODEM_STATE_ENABLED = 6,
|
||||
MM_MODEM_STATE_SEARCHING = 7,
|
||||
MM_MODEM_STATE_REGISTERED = 8,
|
||||
MM_MODEM_STATE_DISCONNECTING = 9,
|
||||
MM_MODEM_STATE_CONNECTING = 10,
|
||||
MM_MODEM_STATE_CONNECTED = 11,
|
||||
} MMModemState;
|
||||
|
||||
typedef enum { /*< underscore_name=mm_modem_state_failed_reason >*/
|
||||
MM_MODEM_STATE_FAILED_REASON_NONE = 0,
|
||||
MM_MODEM_STATE_FAILED_REASON_UNKNOWN = 1,
|
||||
MM_MODEM_STATE_FAILED_REASON_SIM_MISSING = 2,
|
||||
MM_MODEM_STATE_FAILED_REASON_SIM_ERROR = 3,
|
||||
MM_MODEM_STATE_FAILED_REASON_UNKNOWN_CAPABILITIES = 4,
|
||||
MM_MODEM_STATE_FAILED_REASON_ESIM_WITHOUT_PROFILES = 5,
|
||||
__MM_MODEM_STATE_FAILED_REASON_MAX = 6,
|
||||
} MMModemStateFailedReason;
|
||||
|
||||
typedef enum {
|
||||
MM_BEARER_IP_METHOD_UNKNOWN = 0,
|
||||
MM_BEARER_IP_METHOD_PPP = 1,
|
||||
MM_BEARER_IP_METHOD_STATIC = 2,
|
||||
MM_BEARER_IP_METHOD_DHCP = 3,
|
||||
} MMBearerIpMethod;
|
||||
|
||||
typedef enum { /*< underscore_name=mm_modem_port_type >*/
|
||||
MM_MODEM_PORT_TYPE_UNKNOWN = 1,
|
||||
MM_MODEM_PORT_TYPE_NET = 2,
|
||||
MM_MODEM_PORT_TYPE_AT = 3,
|
||||
MM_MODEM_PORT_TYPE_QCDM = 4,
|
||||
MM_MODEM_PORT_TYPE_GPS = 5,
|
||||
MM_MODEM_PORT_TYPE_QMI = 6,
|
||||
MM_MODEM_PORT_TYPE_MBIM = 7,
|
||||
MM_MODEM_PORT_TYPE_AUDIO = 8,
|
||||
MM_MODEM_PORT_TYPE_IGNORED = 9,
|
||||
MM_MODEM_PORT_TYPE_XMMRPC = 10,
|
||||
} MMModemPortType;
|
||||
|
||||
typedef enum { /*< underscore_name=mm_bearer_allowed_auth >*/
|
||||
MM_BEARER_ALLOWED_AUTH_UNKNOWN = 0,
|
||||
/* bits 0..4 order match Ericsson device bitmap */
|
||||
MM_BEARER_ALLOWED_AUTH_NONE = 1 << 0,
|
||||
MM_BEARER_ALLOWED_AUTH_PAP = 1 << 1,
|
||||
MM_BEARER_ALLOWED_AUTH_CHAP = 1 << 2,
|
||||
MM_BEARER_ALLOWED_AUTH_MSCHAP = 1 << 3,
|
||||
MM_BEARER_ALLOWED_AUTH_MSCHAPV2 = 1 << 4,
|
||||
MM_BEARER_ALLOWED_AUTH_EAP = 1 << 5,
|
||||
} MMBearerAllowedAuth;
|
||||
|
||||
typedef enum {
|
||||
MODEM_RECONNECT_DONE, /* No reconnect is required, e.g. connected. */
|
||||
MODEM_RECONNECT_SCHEDULED, /* Reconnect is in progress. */
|
||||
MODEM_RECONNECT_WAITING, /* Waiting for modem to recover. */
|
||||
} ModemReconnectState;
|
||||
|
||||
int manager_notify_mm_bus_connected(Manager *manager);
|
||||
int manager_match_mm_signals(Manager *manager);
|
||||
int link_modem_reconfigure(Link *link);
|
||||
@ -1,641 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-dhcp4.h"
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-wwan.h"
|
||||
#include "parse-util.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
#include "sd-dhcp6-client.h"
|
||||
#include "sd-ndisc.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
|
||||
Bearer* bearer_free(Bearer *b) {
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
||||
if (b->modem) {
|
||||
if (b->path)
|
||||
hashmap_remove_value(b->modem->bearers_by_path, b->path, b);
|
||||
if (b->name)
|
||||
hashmap_remove_value(b->modem->bearers_by_name, b->name, b);
|
||||
}
|
||||
|
||||
sd_bus_slot_unref(b->slot_getall);
|
||||
|
||||
free(b->path);
|
||||
free(b->name);
|
||||
free(b->apn);
|
||||
|
||||
in_addr_full_array_free(b->dns, b->n_dns);
|
||||
|
||||
return mfree(b);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
bearer_hash_ops,
|
||||
char,
|
||||
string_hash_func,
|
||||
string_compare_func,
|
||||
Bearer,
|
||||
bearer_free);
|
||||
|
||||
int bearer_new(Modem *modem, const char *path, Bearer **ret) {
|
||||
_cleanup_(bearer_freep) Bearer *b = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(modem);
|
||||
assert(path);
|
||||
|
||||
if (hashmap_contains(modem->bearers_by_path, path))
|
||||
return -EEXIST;
|
||||
|
||||
p = strdup(path);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
b = new(Bearer, 1);
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
*b = (Bearer) {
|
||||
.modem = modem,
|
||||
.path = TAKE_PTR(p),
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&modem->bearers_by_path, &bearer_hash_ops, b->path, b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = b;
|
||||
TAKE_PTR(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bearer_set_name(Bearer *b, const char *name) {
|
||||
Bearer *old;
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
assert(b->modem);
|
||||
assert(name);
|
||||
|
||||
if (streq_ptr(b->name, name))
|
||||
return 0;
|
||||
|
||||
if (b->name)
|
||||
hashmap_remove_value(b->modem->bearers_by_name, b->name, b);
|
||||
|
||||
if (isempty(name)) {
|
||||
b->name = mfree(b->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = free_and_strdup(&b->name, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* FIXME: it is possible during reconnect that an interface is already
|
||||
* registered in the hash map: if simple connect options
|
||||
* are changed, e.g. externally modified .network file and then
|
||||
* reloaded with 'networkctl reload'. This may create a new bearer
|
||||
* attached to the same interface name, e.g. "wwan0". The order in which
|
||||
* we parse the bearer properties is undetermined and it can be that we
|
||||
* need to raplce the old one with the new one now, so only one bearer
|
||||
* with the given interface name exists.
|
||||
*/
|
||||
old = hashmap_get(b->modem->bearers_by_name, name);
|
||||
if (old) {
|
||||
hashmap_remove_value(old->modem->bearers_by_name, name, old);
|
||||
old->name = mfree(old->name);
|
||||
}
|
||||
|
||||
return hashmap_ensure_put(&b->modem->bearers_by_name, &bearer_hash_ops, b->name, b);
|
||||
}
|
||||
|
||||
int bearer_get_by_path(Manager *manager, const char *path, Modem **ret_modem, Bearer **ret_bearer) {
|
||||
Modem *modem;
|
||||
Bearer *b;
|
||||
|
||||
assert(manager);
|
||||
assert(path);
|
||||
|
||||
HASHMAP_FOREACH(modem, manager->modems_by_path) {
|
||||
b = hashmap_get(modem->bearers_by_path, path);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (ret_bearer)
|
||||
*ret_bearer = b;
|
||||
if (ret_modem)
|
||||
*ret_modem = modem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
Modem* modem_free(Modem *modem) {
|
||||
if (!modem)
|
||||
return NULL;
|
||||
|
||||
if (modem->bearers_by_name)
|
||||
hashmap_free(modem->bearers_by_name);
|
||||
|
||||
if (modem->bearers_by_path)
|
||||
hashmap_free(modem->bearers_by_path);
|
||||
|
||||
if (modem->manager)
|
||||
hashmap_remove_value(modem->manager->modems_by_path, modem->path, modem);
|
||||
|
||||
sd_bus_slot_unref(modem->slot_propertieschanged);
|
||||
sd_bus_slot_unref(modem->slot_statechanged);
|
||||
sd_bus_slot_unref(modem->slot_connect);
|
||||
|
||||
free(modem->path);
|
||||
free(modem->manufacturer);
|
||||
free(modem->model);
|
||||
free(modem->port_name);
|
||||
|
||||
return mfree(modem);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
modems_hash_ops,
|
||||
char,
|
||||
string_hash_func,
|
||||
string_compare_func,
|
||||
Modem,
|
||||
modem_free);
|
||||
|
||||
int modem_new(Manager *m, const char *path, Modem **ret) {
|
||||
_cleanup_(modem_freep) Modem *modem = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(path);
|
||||
|
||||
if (hashmap_contains(m->modems_by_path, path))
|
||||
return -EEXIST;
|
||||
|
||||
p = strdup(path);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
modem = new(Modem, 1);
|
||||
if (!modem)
|
||||
return -ENOMEM;
|
||||
|
||||
*modem = (Modem) {
|
||||
.manager = m,
|
||||
.path = TAKE_PTR(p),
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&m->modems_by_path, &modems_hash_ops, modem->path, modem);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = modem;
|
||||
|
||||
TAKE_PTR(modem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int modem_get_by_path(Manager *m, const char *path, Modem **ret) {
|
||||
Modem *modem;
|
||||
|
||||
assert(m);
|
||||
assert(path);
|
||||
|
||||
modem = hashmap_get(m->modems_by_path, path);
|
||||
if (!modem)
|
||||
return -ENOENT;
|
||||
|
||||
if (ret)
|
||||
*ret = modem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_get_modem(Link *link, Modem **ret) {
|
||||
Modem *modem;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->ifname);
|
||||
|
||||
HASHMAP_FOREACH(modem, link->manager->modems_by_path)
|
||||
if (modem->port_name && streq(modem->port_name, link->ifname)) {
|
||||
*ret = modem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int link_get_bearer(Link *link, Bearer **ret) {
|
||||
Modem *modem;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->ifname);
|
||||
|
||||
HASHMAP_FOREACH(modem, link->manager->modems_by_path) {
|
||||
Bearer *b;
|
||||
|
||||
b = hashmap_get(modem->bearers_by_name, link->ifname);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (ret)
|
||||
*ret = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int link_dhcp_enabled_by_bearer(Link *link, int family) {
|
||||
Bearer *b;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
r = link_get_bearer(link, &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!b->connected)
|
||||
return false;
|
||||
|
||||
if (!FLAGS_SET(b->ip_type, family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6))
|
||||
return false;
|
||||
|
||||
return (family == AF_INET ? b->ip4_method : b->ip6_method) == MM_BEARER_IP_METHOD_DHCP;
|
||||
}
|
||||
|
||||
static int bearer_address_handler(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
Address *address) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = address_configure_handler_internal(m, link, address);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (link->bearer_messages == 0) {
|
||||
link->bearer_configured = true;
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_request_bearer_address(
|
||||
Link *link,
|
||||
int family,
|
||||
const union in_addr_union *addr,
|
||||
unsigned prefixlen) {
|
||||
|
||||
_cleanup_(address_unrefp) Address *address = NULL;
|
||||
Address *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(addr);
|
||||
|
||||
if (!in_addr_is_set(family, addr))
|
||||
return 0;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
address->source = NETWORK_CONFIG_SOURCE_MODEM_MANAGER;
|
||||
address->family = family;
|
||||
address->in_addr = *addr;
|
||||
address->prefixlen = prefixlen;
|
||||
|
||||
if (address_get(link, address, &existing) < 0) /* The address is new. */
|
||||
link->bearer_configured = false;
|
||||
else
|
||||
address_unmark(existing);
|
||||
|
||||
r = link_request_address(link, address, &link->bearer_messages,
|
||||
bearer_address_handler, /* ret = */ NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request address provided by bearer: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bearer_route_handler(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
Route *route) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = route_configure_handler_internal(m, req, route);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (link->bearer_messages == 0) {
|
||||
link->bearer_configured = true;
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_request_bearer_route(
|
||||
Link *link,
|
||||
int family,
|
||||
const union in_addr_union *gw,
|
||||
const union in_addr_union *prefsrc) {
|
||||
|
||||
_cleanup_(route_unrefp) Route *route = NULL;
|
||||
Route *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(gw);
|
||||
assert(prefsrc);
|
||||
|
||||
if (!in_addr_is_set(family, gw))
|
||||
return 0;
|
||||
|
||||
if (link->network->mm_use_gateway == 0)
|
||||
return 0;
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
route->source = NETWORK_CONFIG_SOURCE_MODEM_MANAGER;
|
||||
route->family = family;
|
||||
route->nexthop.family = family;
|
||||
route->nexthop.gw = *gw;
|
||||
if (link->network->mm_route_metric_set) {
|
||||
route->priority = link->network->mm_route_metric;
|
||||
route->priority_set = true;
|
||||
}
|
||||
|
||||
if (prefsrc)
|
||||
route->prefsrc = *prefsrc;
|
||||
|
||||
if (route_get(link->manager, route, &existing) < 0) /* This is a new route. */
|
||||
link->bearer_configured = false;
|
||||
else
|
||||
route_unmark(existing);
|
||||
|
||||
r = link_request_route(link, route, &link->bearer_messages, bearer_route_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request gateway provided by bearer: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_apply_bearer_impl(Link *link, Bearer *b) {
|
||||
Address *address;
|
||||
Route *route;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return 0;
|
||||
|
||||
/* First, mark bearer configs. */
|
||||
SET_FOREACH(address, link->addresses) {
|
||||
if (address->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
|
||||
continue;
|
||||
|
||||
address_mark(address);
|
||||
}
|
||||
|
||||
SET_FOREACH(route, link->manager->routes) {
|
||||
if (route->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
|
||||
continue;
|
||||
|
||||
route_mark(route);
|
||||
}
|
||||
|
||||
if (b && FLAGS_SET(b->ip_type, ADDRESS_FAMILY_IPV4)) {
|
||||
if (b->connected && b->ip4_method == MM_BEARER_IP_METHOD_STATIC) {
|
||||
r = link_request_bearer_address(link, AF_INET, &b->ip4_address, b->ip4_prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_request_bearer_route(link, AF_INET, &b->ip4_gateway, &b->ip4_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (b->connected && b->ip4_method == MM_BEARER_IP_METHOD_DHCP) {
|
||||
if (!link_dhcp4_enabled(link))
|
||||
log_link_notice(link, "The WWAN connection requested DHCPv4 client, but it is disabled.");
|
||||
|
||||
r = dhcp4_start(link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m");
|
||||
} else {
|
||||
r = sd_dhcp_client_stop(link->dhcp_client);
|
||||
if (r < 0)
|
||||
ret = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
|
||||
}
|
||||
}
|
||||
|
||||
if (b && FLAGS_SET(b->ip_type, ADDRESS_FAMILY_IPV6)) {
|
||||
if (b->connected && b->ip6_method == MM_BEARER_IP_METHOD_STATIC) {
|
||||
r = link_request_bearer_address(link, AF_INET6, &b->ip6_address, b->ip6_prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_request_bearer_route(link, AF_INET6, &b->ip6_gateway, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (b->connected && b->ip6_method == MM_BEARER_IP_METHOD_DHCP) {
|
||||
if (!link_ndisc_enabled(link) && !link_dhcp6_enabled(link))
|
||||
log_link_notice(link,
|
||||
"The WWAN connection requested IPv6 dynamic address configuration,"
|
||||
"but both IPv6 Router Discovery and DHCPv6 client are disabled.");
|
||||
|
||||
r = ndisc_start(link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
|
||||
|
||||
r = dhcp6_start(link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m");
|
||||
} else {
|
||||
r = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
ret = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
|
||||
|
||||
r = sd_ndisc_stop(link->ndisc);
|
||||
if (r < 0)
|
||||
ret = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, remove all marked configs. */
|
||||
SET_FOREACH(address, link->addresses) {
|
||||
if (address->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
|
||||
continue;
|
||||
|
||||
if (!address_is_marked(address))
|
||||
continue;
|
||||
|
||||
r = address_remove(address, link);
|
||||
if (r < 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
SET_FOREACH(route, link->manager->routes) {
|
||||
if (route->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
|
||||
continue;
|
||||
|
||||
if (!route_is_marked(route))
|
||||
continue;
|
||||
|
||||
r = route_remove(route, link->manager);
|
||||
if (ret)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (link->bearer_messages == 0)
|
||||
link->bearer_configured = true;
|
||||
|
||||
if (!link->bearer_configured)
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
|
||||
link_check_ready(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_apply_bearer(Link *link) {
|
||||
Bearer *b = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
(void) link_get_bearer(link, &b);
|
||||
|
||||
r = link_apply_bearer_impl(link, b);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int bearer_update_link(Bearer *b) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
assert(b->modem);
|
||||
assert(b->modem->manager);
|
||||
|
||||
if (!b->name)
|
||||
return 0;
|
||||
|
||||
if (link_get_by_name(b->modem->manager, b->name, &link) < 0)
|
||||
return 0;
|
||||
|
||||
r = link_apply_bearer_impl(link, b);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
||||
/*
|
||||
* Need to bring up the interface after the modem has connected.
|
||||
* This is because ModemManger does the following while connecting:
|
||||
* <msg> [1755871777.322239] [modem2] state changed (registered -> connecting)
|
||||
* <dbg> [1755871777.325012] [modem2/bearer5] launching connection with QMI port (cdc-wdm0) and data port (wwan0) (multiplex none)
|
||||
* <dbg> [1755871777.327665] [cdc-wdm0/qmi] bringing down data interface 'wwan0'
|
||||
* <dbg> [1755871777.330108] [modem2/wwan0/net] interface index: 9
|
||||
* <dbg> [1755871777.335265] [cdc-wdm0/qmi] deleting all links in data interface 'wwan0'
|
||||
*/
|
||||
|
||||
r = link_request_to_bring_up_or_down(link, b->connected);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bearer_drop(Bearer *b) {
|
||||
assert(b);
|
||||
|
||||
b->connected = false;
|
||||
b->apn = mfree(b->apn);
|
||||
|
||||
(void) bearer_update_link(b);
|
||||
|
||||
bearer_free(b);
|
||||
}
|
||||
|
||||
int config_parse_mm_route_metric(
|
||||
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;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->mm_route_metric_set = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = safe_atou32(rvalue, &network->mm_route_metric);
|
||||
if (r < 0)
|
||||
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||
|
||||
network->mm_route_metric_set = true;
|
||||
return 0;
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser-forward.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "network-util.h"
|
||||
#include "networkd-wwan-bus.h"
|
||||
|
||||
typedef struct Modem Modem;
|
||||
|
||||
typedef struct Bearer {
|
||||
Modem *modem;
|
||||
|
||||
sd_bus_slot *slot_getall; /* for GetAll method */
|
||||
|
||||
char *path; /* DBus path e.g /org/freedesktop/ModemManager/Bearer/0 */
|
||||
char *name; /* Interface property, e.g. wwan0 */
|
||||
char *apn; /* "apn" field in Properties */
|
||||
AddressFamily ip_type; /* "ip-type" field in Properties */
|
||||
|
||||
/* Ip4Config or IP6Config property */
|
||||
MMBearerIpMethod ip4_method;
|
||||
MMBearerIpMethod ip6_method;
|
||||
unsigned ip4_prefixlen;
|
||||
unsigned ip6_prefixlen;
|
||||
union in_addr_union ip4_address;
|
||||
union in_addr_union ip6_address;
|
||||
union in_addr_union ip4_gateway;
|
||||
union in_addr_union ip6_gateway;
|
||||
struct in_addr_full **dns;
|
||||
size_t n_dns;
|
||||
uint32_t ip4_mtu;
|
||||
uint32_t ip6_mtu;
|
||||
|
||||
bool connected; /* Connected property */
|
||||
} Bearer;
|
||||
|
||||
typedef struct Modem {
|
||||
Manager *manager;
|
||||
|
||||
sd_bus_slot *slot_propertieschanged;
|
||||
sd_bus_slot *slot_statechanged;
|
||||
sd_bus_slot *slot_connect;
|
||||
|
||||
char *path; /* DBus path e.g /org/freedesktop/ModemManager/Modem/0 */
|
||||
char *manufacturer; /* The "Manufacturer" property */
|
||||
char *model; /* The "Model" property */
|
||||
char *port_name; /* MM_MODEM_PORT_TYPE_NET of Ports property */
|
||||
|
||||
Hashmap *bearers_by_path;
|
||||
Hashmap *bearers_by_name;
|
||||
|
||||
MMModemState state;
|
||||
MMModemStateFailedReason state_fail_reason;
|
||||
ModemReconnectState reconnect_state;
|
||||
} Modem;
|
||||
|
||||
int bearer_new(Modem *modem, const char *path, Bearer **ret);
|
||||
Bearer* bearer_free(Bearer *b);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Bearer*, bearer_free);
|
||||
|
||||
int bearer_set_name(Bearer *b, const char *name);
|
||||
|
||||
int bearer_get_by_path(Manager *manager, const char *path, Modem **ret_modem, Bearer **ret_bearer);
|
||||
int link_get_bearer(Link *link, Bearer **ret);
|
||||
|
||||
int link_dhcp_enabled_by_bearer(Link *link, int family);
|
||||
|
||||
int link_apply_bearer(Link *link);
|
||||
int bearer_update_link(Bearer *b);
|
||||
void bearer_drop(Bearer *b);
|
||||
|
||||
int modem_new(Manager *m, const char *path, Modem **ret);
|
||||
Modem* modem_free(Modem *modem);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Modem*, modem_free);
|
||||
|
||||
int modem_get_by_path(Manager *m, const char *path, Modem **ret);
|
||||
int link_get_modem(Link *link, Modem **ret);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mm_route_metric);
|
||||
@ -194,15 +194,4 @@
|
||||
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.network1.manage-links">
|
||||
<description gettext-domain="systemd">Manage network links</description>
|
||||
<message gettext-domain="systemd">Authentication is required to manage network links.</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
||||
@ -541,8 +541,9 @@ static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t
|
||||
log_error_errno(r, "Failed to select any cgroups under %s based on pressure, ignoring: %m", t->path);
|
||||
else {
|
||||
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one.
|
||||
* If r == 0 then the cgroup is already queued for kill by an earlier iteration.
|
||||
* In either case, go through the event loop again and select a new candidate if
|
||||
* If r == 0 then it means there were not eligible candidates, the candidate cgroup
|
||||
* disappeared, or the candidate cgroup has no processes by the time we tried to kill
|
||||
* it. In either case, go through the event loop again and select a new candidate if
|
||||
* pressure is still high. */
|
||||
m->mem_pressure_post_action_delay_start = usec_now;
|
||||
if (selected && r > 0) {
|
||||
|
||||
@ -494,20 +494,12 @@ int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) {
|
||||
r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
if (r == 0) {
|
||||
/* The cgroup is already queued. Drop only this temporary object, because running the normal
|
||||
* cleanup path would remove by cgroup path key and could interfere with the existing queued
|
||||
* kill state. */
|
||||
oomd_cgroup_context_unref(ks->ctx);
|
||||
ks = mfree(ks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = oomd_prekill_hook(m, ks);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "oomd prekill hook failed for %s, ignoring: %m", ctx->path);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef void (*dump_candidate_func)(const OomdCGroupContext *ctx, FILE *f, const char *prefix);
|
||||
|
||||
@ -5404,7 +5404,6 @@ static int vl_method_read_event_log(sd_varlink *link, sd_json_variant *parameter
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||
if (r != 0)
|
||||
|
||||
@ -10324,12 +10324,14 @@ static int vl_method_list_candidate_devices(
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
BlockDevice *l = NULL;
|
||||
size_t n = 0;
|
||||
CLEANUP_ARRAY(l, n, block_device_array_free);
|
||||
|
||||
@ -21,4 +21,3 @@ struct ConfigPerfItem;
|
||||
Delegate.DNS, config_parse_delegate_dns_servers, 0, 0
|
||||
Delegate.Domains, config_parse_delegate_domains, 0, 0
|
||||
Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route)
|
||||
Delegate.FirewallMark, config_parse_unsigned, 0, offsetof(DnsDelegate, fwmark)
|
||||
|
||||
@ -23,8 +23,6 @@ typedef struct DnsDelegate {
|
||||
|
||||
int default_route;
|
||||
|
||||
uint32_t fwmark;
|
||||
|
||||
DnsScope *scope;
|
||||
|
||||
LIST_FIELDS(DnsDelegate, delegates);
|
||||
|
||||
@ -475,12 +475,6 @@ static int dns_scope_socket(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (s->delegate && s->delegate->fwmark > 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_MARK, s->delegate->fwmark);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to set firewall mark on DNS socket: %m)");
|
||||
}
|
||||
|
||||
bool addr_is_nonlocal = s->link &&
|
||||
!manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
|
||||
in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0;
|
||||
|
||||
@ -1374,7 +1374,7 @@ int dns_server_dump_configuration_to_json(DnsServer *server, sd_json_variant **r
|
||||
return sd_json_buildo(
|
||||
ret,
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("addressString", dns_server_string(server)),
|
||||
JSON_BUILD_PAIR_IN_ADDR("address", server->family, &server->address),
|
||||
JSON_BUILD_PAIR_IN_ADDR("address", &server->address, server->family),
|
||||
SD_JSON_BUILD_PAIR_INTEGER("family", server->family),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)),
|
||||
|
||||
@ -1214,7 +1214,10 @@ static int vl_method_browse_services(sd_varlink* link, sd_json_variant* paramete
|
||||
int r = 0;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
/* if the client didn't set the more flag, it is using us incorrectly */
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link)));
|
||||
|
||||
@ -1236,7 +1239,9 @@ static int vl_method_subscribe_query_results(sd_varlink *link, sd_json_variant *
|
||||
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
||||
int r;
|
||||
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
/* if the client didn't set the more flag, it is using us incorrectly */
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-query-results");
|
||||
if (r <= 0)
|
||||
@ -1377,7 +1382,9 @@ static int vl_method_subscribe_dns_configuration(sd_varlink *link, sd_json_varia
|
||||
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
||||
int r;
|
||||
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
/* if the client didn't set the more flag, it is using us incorrectly */
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-dns-configuration");
|
||||
if (r <= 0)
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_APPARMOR
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
@ -65,3 +67,4 @@ bool mac_apparmor_use(void) {
|
||||
|
||||
return (cached_use = true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -831,6 +831,10 @@ int ask_password_agent(
|
||||
|
||||
_cleanup_close_ int socket_fd = -EBADF, signal_fd = -EBADF, inotify_fd = -EBADF, dfd = -EBADF;
|
||||
_cleanup_(unlink_and_freep) char *socket_name = NULL;
|
||||
_cleanup_free_ char *temp = NULL, *final = NULL;
|
||||
_cleanup_strv_free_erase_ char **l = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
sigset_t mask, oldmask;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
@ -846,59 +850,64 @@ int ask_password_agent(
|
||||
if (req->flag_file)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
_cleanup_free_ char *askpwdir = NULL;
|
||||
r = get_ask_password_directory_for_flags(flags, &askpwdir);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -ENXIO;
|
||||
|
||||
dfd = open_mkdir(askpwdir, O_CLOEXEC, 0755);
|
||||
if (dfd < 0)
|
||||
return log_debug_errno(dfd, "Failed to open directory '%s': %m", askpwdir);
|
||||
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req->keyring) {
|
||||
r = ask_password_keyring(req, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
return r;
|
||||
|
||||
inotify_fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
|
||||
if (inotify_fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = inotify_add_watch_fd(inotify_fd, dfd, IN_ONLYDIR|IN_ATTRIB /* for mtime */);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
sigset_t mask, oldmask;
|
||||
_unused_ _cleanup_(block_signals_reset) sigset_t *saved_ssp = NULL;
|
||||
|
||||
assert_se(sigemptyset(&mask) >= 0);
|
||||
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
|
||||
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
|
||||
|
||||
saved_ssp = &oldmask;
|
||||
|
||||
_cleanup_free_ char *fname = NULL, *final = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
if (asprintf(&final, "ask.%" PRIu64, random_u64()) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = fopen_temporary_at(dfd, final, &f, &fname);
|
||||
_cleanup_free_ char *askpwdir = NULL;
|
||||
r = get_ask_password_directory_for_flags(flags, &askpwdir);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finish;
|
||||
if (r == 0) {
|
||||
r = -ENXIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
CLEANUP_TMPFILE_AT(dfd, fname);
|
||||
dfd = open_mkdir(askpwdir, O_RDONLY|O_CLOEXEC, 0755);
|
||||
if (dfd < 0) {
|
||||
r = log_debug_errno(dfd, "Failed to open directory '%s': %m", askpwdir);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req->keyring) {
|
||||
r = ask_password_keyring(req, flags, ret);
|
||||
if (r >= 0) {
|
||||
r = 0;
|
||||
goto finish;
|
||||
} else if (r != -ENOKEY)
|
||||
goto finish;
|
||||
|
||||
inotify_fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
|
||||
if (inotify_fd < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = inotify_add_watch_fd(inotify_fd, dfd, IN_ONLYDIR|IN_ATTRIB /* for mtime */);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (asprintf(&final, "ask.%" PRIu64, random_u64()) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = fopen_temporary_at(dfd, final, &f, &temp);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
|
||||
if (signal_fd < 0)
|
||||
return -errno;
|
||||
if (signal_fd < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
socket_fd = create_socket(askpwdir, &socket_name);
|
||||
if (socket_fd < 0)
|
||||
return socket_fd;
|
||||
if (socket_fd < 0) {
|
||||
r = socket_fd;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"[Ask]\n"
|
||||
@ -924,19 +933,21 @@ int ask_password_agent(
|
||||
if (req->id)
|
||||
fprintf(f, "Id=%s\n", req->id);
|
||||
|
||||
if (fchmod(fileno(f), 0644) < 0)
|
||||
return -errno;
|
||||
if (fchmod(fileno(f), 0644) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finish;
|
||||
|
||||
/* Paranoia: never clobber an ongoing request */
|
||||
r = rename_noreplace(dfd, fname, dfd, final);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (renameat(dfd, temp, dfd, final) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
free_and_replace(fname, final);
|
||||
temp = mfree(temp);
|
||||
|
||||
enum {
|
||||
POLL_SOCKET,
|
||||
@ -965,10 +976,13 @@ int ask_password_agent(
|
||||
|
||||
assert(n_pollfd <= _POLL_MAX);
|
||||
|
||||
_cleanup_strv_free_erase_ char **l = NULL;
|
||||
|
||||
for (;;) {
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
char passphrase[LINE_MAX+1];
|
||||
struct iovec iovec;
|
||||
struct ucred *ucred;
|
||||
usec_t timeout;
|
||||
ssize_t n;
|
||||
|
||||
if (req->until > 0)
|
||||
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
||||
@ -979,34 +993,45 @@ int ask_password_agent(
|
||||
if (r == -EINTR)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -ETIME;
|
||||
goto finish;
|
||||
if (r == 0) {
|
||||
r = -ETIME;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pollfd[POLL_SIGNAL].revents & POLLIN)
|
||||
return -EINTR;
|
||||
if (pollfd[POLL_SIGNAL].revents & POLLIN) {
|
||||
r = -EINTR;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
|
||||
return -ECONNRESET;
|
||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) {
|
||||
r = -ECONNRESET;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
|
||||
(void) flush_fd(inotify_fd);
|
||||
|
||||
if (req->keyring) {
|
||||
r = ask_password_keyring(req, flags, ret);
|
||||
if (r != -ENOKEY)
|
||||
return r;
|
||||
if (r >= 0) {
|
||||
r = 0;
|
||||
goto finish;
|
||||
} else if (r != -ENOKEY)
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (pollfd[POLL_SOCKET].revents == 0)
|
||||
continue;
|
||||
if (pollfd[POLL_SOCKET].revents != POLLIN)
|
||||
return -EIO;
|
||||
|
||||
char passphrase[LINE_MAX+1];
|
||||
struct iovec iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||
if (pollfd[POLL_SOCKET].revents != POLLIN) {
|
||||
r = -EIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
|
||||
|
||||
struct msghdr msghdr = {
|
||||
.msg_iov = &iovec,
|
||||
.msg_iovlen = 1,
|
||||
@ -1014,7 +1039,7 @@ int ask_password_agent(
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
|
||||
ssize_t n = recvmsg_safe(socket_fd, &msghdr, 0);
|
||||
n = recvmsg_safe(socket_fd, &msghdr, 0);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
continue;
|
||||
if (n == -ECHRNG) {
|
||||
@ -1025,30 +1050,30 @@ int ask_password_agent(
|
||||
log_debug_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
continue;
|
||||
}
|
||||
if (n < 0)
|
||||
return n;
|
||||
if (n < 0) {
|
||||
r = (int) n;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
CLEANUP_ERASE(passphrase);
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
if (n == 0) {
|
||||
log_debug("Got empty reply from ask-password agent, ignoring.");
|
||||
log_debug("Message too short");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct ucred *ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||
if (!ucred) {
|
||||
log_debug("Received message without credentials, ignoring.");
|
||||
continue;
|
||||
}
|
||||
if (ucred->uid != getuid() && ucred->uid != 0) {
|
||||
log_debug("Got password response from bad user, ignoring.");
|
||||
log_debug("Received message without credentials. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passphrase[0] == '-')
|
||||
return -ECANCELED;
|
||||
if (ucred->uid != getuid() && ucred->uid != 0) {
|
||||
log_debug("Got response from bad user. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passphrase[0] == '+') {
|
||||
/* An empty message refers to the empty password */
|
||||
@ -1056,23 +1081,45 @@ int ask_password_agent(
|
||||
l = strv_new("");
|
||||
else
|
||||
l = strv_parse_nulstr(passphrase+1, n-1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strv_isempty(l))
|
||||
break;
|
||||
|
||||
l = strv_free(l);
|
||||
if (!l) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
log_debug("Got invalid response from ask-password agent, ignoring.");
|
||||
if (strv_isempty(l)) {
|
||||
l = strv_free(l);
|
||||
log_debug("Invalid packet");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (passphrase[0] == '-') {
|
||||
r = -ECANCELED;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
log_debug("Invalid packet");
|
||||
}
|
||||
|
||||
if (req->keyring)
|
||||
(void) add_to_keyring_and_log(req->keyring, flags, l);
|
||||
|
||||
*ret = TAKE_PTR(l);
|
||||
return 0;
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
if (temp) {
|
||||
assert(dfd >= 0);
|
||||
(void) unlinkat(dfd, temp, 0);
|
||||
} else if (final) {
|
||||
assert(dfd >= 0);
|
||||
(void) unlinkat(dfd, final, 0);
|
||||
}
|
||||
|
||||
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
shared_sources = files(
|
||||
'acl-util.c',
|
||||
'acpi-fpdt.c',
|
||||
'apparmor-util.c',
|
||||
'ask-password-agent.c',
|
||||
'ask-password-api.c',
|
||||
'async.c',
|
||||
@ -278,10 +279,6 @@ if conf.get('HAVE_LIBIDN2') == 1
|
||||
shared_sources += files('idn-util.c')
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_APPARMOR') == 1
|
||||
shared_sources += files('apparmor-util.c')
|
||||
endif
|
||||
|
||||
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
|
||||
ip_protocol_list_txt = custom_target(
|
||||
input : [generate_ip_protocol_list, ipproto_sources],
|
||||
|
||||
@ -11,7 +11,6 @@ int metrics_setup_varlink_server(
|
||||
sd_varlink_server **server, /* in and out param */
|
||||
sd_varlink_server_flags_t flags,
|
||||
sd_event *event,
|
||||
int64_t priority,
|
||||
sd_varlink_method_t vl_method_list_cb,
|
||||
sd_varlink_method_t vl_method_describe_cb,
|
||||
void *userdata) {
|
||||
@ -21,8 +20,6 @@ int metrics_setup_varlink_server(
|
||||
|
||||
assert(server);
|
||||
assert(event);
|
||||
assert(vl_method_list_cb);
|
||||
assert(vl_method_describe_cb);
|
||||
|
||||
if (*server)
|
||||
return 0;
|
||||
@ -37,21 +34,24 @@ int metrics_setup_varlink_server(
|
||||
|
||||
r = sd_varlink_server_bind_method_many(
|
||||
s,
|
||||
"io.systemd.Metrics.List", vl_method_list_cb,
|
||||
"io.systemd.Metrics.Describe", vl_method_describe_cb);
|
||||
"io.systemd.Metrics.List",
|
||||
vl_method_list_cb,
|
||||
"io.systemd.Metrics.Describe",
|
||||
vl_method_describe_cb);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to register varlink metrics methods: %m");
|
||||
|
||||
r = sd_varlink_server_set_description(s, "varlink-metrics");
|
||||
r = sd_varlink_server_set_description(s, "systemd varlink metrics server");
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to set varlink metrics server description: %m");
|
||||
|
||||
r = sd_varlink_server_attach_event(s, event, priority);
|
||||
r = sd_varlink_server_attach_event(s, event, SD_EVENT_PRIORITY_NORMAL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to attach varlink metrics server to event loop: %m");
|
||||
|
||||
*server = TAKE_PTR(s);
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const metric_family_type_table[_METRIC_FAMILY_TYPE_MAX] = {
|
||||
@ -84,12 +84,14 @@ int metrics_method_describe(
|
||||
assert(metric_family_table);
|
||||
assert(link);
|
||||
assert(parameters);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -121,12 +123,14 @@ int metrics_method_list(
|
||||
assert(metric_family_table);
|
||||
assert(link);
|
||||
assert(parameters);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -31,7 +31,6 @@ int metrics_setup_varlink_server(
|
||||
sd_varlink_server **server, /* in and out param */
|
||||
sd_varlink_server_flags_t flags,
|
||||
sd_event *event,
|
||||
int64_t priority,
|
||||
sd_varlink_method_t vl_method_list_cb,
|
||||
sd_varlink_method_t vl_method_describe_cb,
|
||||
void *userdata);
|
||||
|
||||
@ -240,8 +240,6 @@ static int archive_unpack_regular(
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to create regular file '%s': %m", path);
|
||||
|
||||
CLEANUP_TMPFILE_AT(parent_fd, tmp);
|
||||
|
||||
if ((fflags & CHATTR_EARLY_FL) != 0) {
|
||||
r = chattr_full(fd,
|
||||
/* path= */ NULL,
|
||||
@ -252,29 +250,45 @@ static int archive_unpack_regular(
|
||||
CHATTR_FALLBACK_BITWISE);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
log_warning_errno(r, "Failed to apply chattr of '%s', ignoring: %m", path);
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
|
||||
else if (r < 0) {
|
||||
log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
r = sym_archive_read_data_into_fd(a, fd);
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
if (r != ARCHIVE_OK) {
|
||||
r = log_error_errno(
|
||||
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to unpack regular file '%s': %s", path, sym_archive_error_string(a));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* If this is a sparse file, then libarchive's archive_read_data_into_fd() won't insert the final
|
||||
* hole. We need to manually truncate. */
|
||||
off_t l = lseek(fd, 0, SEEK_CUR);
|
||||
if (l < 0)
|
||||
return log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
|
||||
if (ftruncate(fd, l) < 0)
|
||||
return log_error_errno(errno, "Failed to truncate regular file '%s' to %" PRIu64 ": %m", path, (uint64_t) l);
|
||||
if (l < 0) {
|
||||
r = log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
|
||||
goto fail;
|
||||
}
|
||||
if (ftruncate(fd, l) < 0) {
|
||||
r = log_error_errno(errno, "Failed to truncate regular file '%s' to %" PRIu64 ": %m", path, (uint64_t) l);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = link_tmpfile_at(fd, parent_fd, tmp, filename, LINK_TMPFILE_REPLACE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install regular file '%s': %m", path);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to install regular file '%s': %m", path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
return TAKE_FD(fd);
|
||||
|
||||
fail:
|
||||
if (tmp)
|
||||
(void) unlinkat(parent_fd, tmp, /* flags= */ 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int archive_unpack_directory(
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
|
||||
#include "varlink-io.systemd.MuteConsole.h"
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
Mute,
|
||||
SD_VARLINK_REQUIRES_MORE,
|
||||
SD_VARLINK_FIELD_COMMENT("Whether to mute the kernel's output to the console (defaults to true)."),
|
||||
SD_VARLINK_DEFINE_INPUT(kernel, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Whether to mute PID1's output to the console (defaults to true)."),
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "bus-polkit.h"
|
||||
#include "varlink-io.systemd.Network.h"
|
||||
|
||||
/* Helper macro to define address fields with both binary and string representation */
|
||||
#define VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
|
||||
#define SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
|
||||
SD_VARLINK_FIELD_COMMENT(comment), \
|
||||
SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \
|
||||
SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \
|
||||
@ -43,10 +42,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
RoutingPolicyRule,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"),
|
||||
SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Length of destination prefix in bits"),
|
||||
SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
|
||||
@ -98,14 +97,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
Route,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
|
||||
SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Source prefix length"),
|
||||
SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field"),
|
||||
SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"),
|
||||
@ -140,7 +139,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this route"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration state of this route"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Interface index for serialization"),
|
||||
@ -163,7 +162,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
|
||||
@ -178,7 +177,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this next hop"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration state of this next hop"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
|
||||
|
||||
@ -209,7 +208,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
DNS,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
|
||||
SD_VARLINK_FIELD_COMMENT("DNS server port number"),
|
||||
SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"),
|
||||
@ -218,29 +217,29 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
NTP,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("NTP server"),
|
||||
SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SIP,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("SIP server domain name"),
|
||||
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
Domain,
|
||||
@ -248,7 +247,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
DNSSECNegativeTrustAnchor,
|
||||
@ -280,7 +279,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"),
|
||||
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
NDisc,
|
||||
@ -291,14 +290,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
Address,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Network prefix length"),
|
||||
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this address"),
|
||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
|
||||
@ -324,7 +323,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
Neighbor,
|
||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Link layer (MAC) address of the neighbor"),
|
||||
SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY),
|
||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"),
|
||||
@ -387,7 +386,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
DHCPServerLease,
|
||||
SD_VARLINK_FIELD_COMMENT("DHCP client identifier"),
|
||||
SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Hostname provided by the DHCP client"),
|
||||
SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"),
|
||||
@ -448,7 +447,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Broadcast address for Ethernet interfaces"),
|
||||
SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"),
|
||||
SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),
|
||||
@ -594,22 +593,6 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
SD_VARLINK_FIELD_COMMENT("Whether persistent storage is ready and writable"),
|
||||
SD_VARLINK_DEFINE_INPUT(Ready, SD_VARLINK_BOOL, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
LinkUp,
|
||||
SD_VARLINK_FIELD_COMMENT("Index of the interface. If specified together with InterfaceName, both must reference the same link."),
|
||||
SD_VARLINK_DEFINE_INPUT(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Name of the interface. If specified together with InterfaceIndex, both must reference the same link."),
|
||||
SD_VARLINK_DEFINE_INPUT(InterfaceName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_POLKIT_INPUT);
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
LinkDown,
|
||||
SD_VARLINK_FIELD_COMMENT("Index of the interface. If specified together with InterfaceName, both must reference the same link."),
|
||||
SD_VARLINK_DEFINE_INPUT(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Name of the interface. If specified together with InterfaceIndex, both must reference the same link."),
|
||||
SD_VARLINK_DEFINE_INPUT(InterfaceName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
VARLINK_DEFINE_POLKIT_INPUT);
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(StorageReadOnly);
|
||||
|
||||
SD_VARLINK_DEFINE_INTERFACE(
|
||||
@ -620,10 +603,6 @@ SD_VARLINK_DEFINE_INTERFACE(
|
||||
&vl_method_GetNamespaceId,
|
||||
&vl_method_GetLLDPNeighbors,
|
||||
&vl_method_SetPersistentStorage,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Bring the specified link up."),
|
||||
&vl_method_LinkUp,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Bring the specified link down."),
|
||||
&vl_method_LinkDown,
|
||||
&vl_type_Address,
|
||||
&vl_type_DHCPLease,
|
||||
&vl_type_DHCPServer,
|
||||
|
||||
@ -59,9 +59,8 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a progress percentrage (specific to the work done for the specified phase+object is sent in progress updates."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(progress, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
ListCandidateDevices,
|
||||
SD_VARLINK_REQUIRES_MORE,
|
||||
SD_VARLINK_FIELD_COMMENT("Control whether to include the root disk of the currently booted OS in the list. Defaults to false, i.e. the root disk is included."),
|
||||
SD_VARLINK_DEFINE_INPUT(ignoreRoot, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Control whether to include block devices with zero size in the list, i.e. typically block devices without any inserted medium. Defaults to false, i.e. empty block devices are included."),
|
||||
|
||||
@ -300,7 +300,7 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
BrowseServices,
|
||||
SD_VARLINK_REQUIRES_MORE,
|
||||
SD_VARLINK_SUPPORTS_MORE,
|
||||
SD_VARLINK_FIELD_COMMENT("The domain to browse for services. If null, the default browsing domain local is used."),
|
||||
SD_VARLINK_DEFINE_INPUT(domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."),
|
||||
|
||||
@ -179,8 +179,6 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(SocketBindDeny, CGroupSocketBind, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#RestrictNetworkInterfaces="),
|
||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(RestrictNetworkInterfaces, CGroupRestrictNetworkInterfaces, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#BindNetworkInterface="),
|
||||
SD_VARLINK_DEFINE_FIELD(BindNetworkInterface, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#NFTSet=family:table:set"),
|
||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(NFTSet, CGroupNFTSet, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
|
||||
|
||||
@ -1,73 +1,78 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fdset.h"
|
||||
#include "log.h"
|
||||
#include "serialize.h"
|
||||
#include "parse-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "varlink-internal.h"
|
||||
#include "varlink-serialize.h"
|
||||
|
||||
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) {
|
||||
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds) {
|
||||
assert(f);
|
||||
assert(fds);
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server";
|
||||
|
||||
LIST_FOREACH(sockets, ss, s->sockets) {
|
||||
int copy;
|
||||
|
||||
assert(ss->address);
|
||||
assert(ss->fd >= 0);
|
||||
|
||||
fprintf(f, "varlink-server-socket-address=%s", ss->address);
|
||||
|
||||
/* If we fail to serialize the fd, it will be considered an error during deserialization */
|
||||
int copy = fdset_put_dup(fds, ss->fd);
|
||||
copy = fdset_put_dup(fds, ss->fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy);
|
||||
fprintf(f, " varlink-server-socket-fd=%i", copy);
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) {
|
||||
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
|
||||
_cleanup_free_ char *address = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
const char *v;
|
||||
int r;
|
||||
|
||||
/* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */
|
||||
const char *v = ASSERT_PTR(value);
|
||||
int r, fd = -EBADF;
|
||||
char *buf;
|
||||
size_t n;
|
||||
|
||||
assert(s);
|
||||
assert(value);
|
||||
assert(fds);
|
||||
|
||||
v = startswith(value, "socket-address=");
|
||||
if (!v)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid varlink server serialization entry: %s", value);
|
||||
n = strcspn(v, " ");
|
||||
address = strndup(v, n);
|
||||
if (!address)
|
||||
return log_oom_debug();
|
||||
|
||||
r = extract_first_word(&v, &address, " ", /* flags = */ 0);
|
||||
if (r <= 0)
|
||||
return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA),
|
||||
"Failed to extract socket address from varlink serialization: %s", value);
|
||||
if (v)
|
||||
v = startswith(v, "varlink-server-socket-fd=");
|
||||
if (v[n] != ' ')
|
||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to deserialize sd_varlink_server_socket: %s", value);
|
||||
v = startswith(v + n + 1, "varlink-server-socket-fd=");
|
||||
if (!v)
|
||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
|
||||
"Got varlink serialization without socket fd, refusing.");
|
||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to deserialize VarlinkServerSocket fd: %s", value);
|
||||
|
||||
fd = deserialize_fd(fds, v);
|
||||
n = strcspn(v, " ");
|
||||
buf = strndupa_safe(v, n);
|
||||
|
||||
fd = parse_fd(buf);
|
||||
if (fd < 0)
|
||||
return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m");
|
||||
return varlink_server_log_errno(s, fd, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf);
|
||||
if (!fdset_contains(fds, fd))
|
||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
|
||||
"VarlinkServerSocket varlink-server-socket-fd= has unknown fd: %d", fd);
|
||||
|
||||
/* NB: varlink_server_socket_free() does not close the fd! */
|
||||
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
|
||||
ss = new(VarlinkServerSocket, 1);
|
||||
if (!ss)
|
||||
return log_oom_debug();
|
||||
@ -75,16 +80,14 @@ int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSe
|
||||
*ss = (VarlinkServerSocket) {
|
||||
.server = s,
|
||||
.address = TAKE_PTR(address),
|
||||
.fd = fd,
|
||||
.fd = fdset_remove(fds, fd),
|
||||
};
|
||||
|
||||
r = varlink_server_add_socket_event_source(s, ss);
|
||||
r = varlink_server_add_socket_event_source(s, ss, SD_EVENT_PRIORITY_NORMAL);
|
||||
if (r < 0)
|
||||
return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m");
|
||||
|
||||
LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
|
||||
TAKE_FD(fd); /* ownership is now transferred to varlink server */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include "shared-forward.h"
|
||||
|
||||
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds);
|
||||
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds);
|
||||
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds);
|
||||
|
||||
bool varlink_server_contains_socket(sd_varlink_server *s, const char *address);
|
||||
|
||||
@ -2749,7 +2749,6 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
const char *class = NULL;
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &class);
|
||||
|
||||
@ -149,7 +149,6 @@ simple_tests += files(
|
||||
'test-mkdir.c',
|
||||
'test-modhex.c',
|
||||
'test-mountpoint-util.c',
|
||||
'test-namespace-util.c',
|
||||
'test-net-naming-scheme.c',
|
||||
'test-notify-recv.c',
|
||||
'test-nsresource.c',
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(namespace_enter) {
|
||||
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
r = pidref_safe_fork(
|
||||
"test-ns-enter-1",
|
||||
FORK_NEW_USERNS|FORK_NEW_MOUNTNS|FORK_LOG|FORK_FREEZE|FORK_DEATHSIG_SIGKILL,
|
||||
&pidref);
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(r))
|
||||
return (void) log_tests_skipped_errno(r, "Unable to unshare user namespace");
|
||||
|
||||
ASSERT_OK(r);
|
||||
|
||||
_cleanup_close_ int mntns_fd = -EBADF, userns_fd = -EBADF, root_fd = -EBADF;
|
||||
ASSERT_OK(pidref_namespace_open(&pidref, NULL, &mntns_fd, NULL, &userns_fd, &root_fd));
|
||||
|
||||
r = ASSERT_OK(pidref_safe_fork(
|
||||
"test-ns-enter-2",
|
||||
FORK_LOG|FORK_WAIT|FORK_DEATHSIG_SIGKILL,
|
||||
NULL));
|
||||
if (r == 0) {
|
||||
ASSERT_OK(namespace_enter(-EBADF, mntns_fd, -EBADF, userns_fd, root_fd));
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Make sure we can enter the namespaces as well if we don't have CAP_SYS_ADMIN. */
|
||||
r = ASSERT_OK(pidref_safe_fork(
|
||||
"test-ns-enter-3",
|
||||
FORK_LOG|FORK_WAIT|FORK_DEATHSIG_SIGKILL,
|
||||
NULL));
|
||||
if (r == 0) {
|
||||
ASSERT_OK(drop_capability(CAP_SYS_ADMIN));
|
||||
ASSERT_OK(namespace_enter(-EBADF, mntns_fd, -EBADF, userns_fd, root_fd));
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
@ -15,9 +15,9 @@ TEST(manager_parse_string) {
|
||||
|
||||
assert_se(manager_new(&m) == 0);
|
||||
|
||||
assert_se(!m->fallback_set);
|
||||
assert_se(!m->have_fallbacks);
|
||||
assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0);
|
||||
assert_se(m->fallback_set);
|
||||
assert_se(m->have_fallbacks);
|
||||
assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0);
|
||||
|
||||
assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);
|
||||
|
||||
@ -20,7 +20,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
|
||||
first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers;
|
||||
|
||||
if (type == SERVER_FALLBACK)
|
||||
m->fallback_set = true;
|
||||
m->have_fallbacks = true;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
@ -59,7 +59,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
|
||||
}
|
||||
|
||||
int manager_parse_fallback_string(Manager *m, const char *string) {
|
||||
if (m->fallback_set)
|
||||
if (m->have_fallbacks)
|
||||
return 0;
|
||||
|
||||
return manager_parse_server_string(m, SERVER_FALLBACK, string);
|
||||
@ -84,22 +84,16 @@ int config_parse_servers(
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
if (isempty(rvalue))
|
||||
manager_flush_server_names(m, ltype);
|
||||
|
||||
/* FallbackNTP= with an empty string disables the built-in fallback servers. */
|
||||
if (ltype == SERVER_FALLBACK)
|
||||
m->fallback_set = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
else {
|
||||
r = manager_parse_server_string(m, ltype, rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse NTP server string '%s', ignoring: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ typedef struct Manager {
|
||||
|
||||
RateLimit ratelimit;
|
||||
bool exhausted_servers;
|
||||
bool fallback_set; /* Indicate if FallbackNTP= is explicitly configured. */
|
||||
bool have_fallbacks;
|
||||
|
||||
/* network */
|
||||
sd_event_source *network_event_source;
|
||||
|
||||
@ -1452,7 +1452,6 @@ testcase_delegate() {
|
||||
[Delegate]
|
||||
DNS=192.168.77.78
|
||||
Domains=exercise.test
|
||||
FirewallMark=42
|
||||
EOF
|
||||
systemctl reload systemd-resolved
|
||||
resolvectl status
|
||||
|
||||
@ -573,4 +573,3 @@ loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="rebo
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]
|
||||
varlinkctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--system"]
|
||||
systemd.network.xml ./refsect1[title="[ModemManager] Section Options"]/variablelist/varlistentry[term="SimpleConnectProperties="]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user