mirror of
https://github.com/systemd/systemd
synced 2026-03-10 07:04:46 +01:00
Compare commits
61 Commits
6d0e8271b4
...
ed6a2eaa31
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed6a2eaa31 | ||
|
|
4e40c2a515 | ||
|
|
e271497d97 | ||
|
|
a5ceab95ab | ||
|
|
d1e0b59843 | ||
|
|
211c3c9d41 | ||
|
|
dae5af119b | ||
|
|
389cd296ec | ||
|
|
5561623ef4 | ||
|
|
b166461f82 | ||
|
|
9676845efa | ||
|
|
ba08fa3230 | ||
|
|
702db03034 | ||
|
|
ba5bd88db3 | ||
|
|
3cfd35eef9 | ||
|
|
fe48347ce6 | ||
|
|
eeead6e177 | ||
|
|
1f9ba6ba73 | ||
|
|
86ac1083c9 | ||
|
|
959f6923e5 | ||
|
|
9257690859 | ||
|
|
122bde2c45 | ||
|
|
3482e4dd70 | ||
|
|
e2fb041564 | ||
|
|
097243cc30 | ||
|
|
03023fd12c | ||
|
|
41e675996d | ||
|
|
09388a6b9e | ||
|
|
42ed373294 | ||
|
|
05d1cfee90 | ||
|
|
926ae62a27 | ||
|
|
daeb7dd390 | ||
|
|
89769fb4ad | ||
|
|
3ac675dff3 | ||
|
|
36f82366d0 | ||
|
|
763f615c3a | ||
|
|
e0fb180483 | ||
|
|
e2c1f3ca2a | ||
|
|
051d228b1c | ||
|
|
77b3ddf2aa | ||
|
|
e1ecec0274 | ||
|
|
618952f07e | ||
|
|
06dca3f629 | ||
|
|
c33b112cac | ||
|
|
5ac9a481cd | ||
|
|
3be36e6d64 | ||
|
|
2291cf0626 | ||
|
|
a48145203c | ||
|
|
345208a49b | ||
|
|
f8a4c3d375 | ||
|
|
4ed1e2ea17 | ||
|
|
a4381cae8b | ||
|
|
babfd9cbaa | ||
|
|
1b1799e9ba | ||
|
|
b0ca2ef264 | ||
|
|
1bb9306f1e | ||
|
|
e93511b10e | ||
|
|
f4f1956d42 | ||
|
|
4153a2a6f4 | ||
|
|
41615d59fa | ||
|
|
0132a02bd6 |
4
.github/workflows/linter.yml
vendored
4
.github/workflows/linter.yml
vendored
@ -50,10 +50,6 @@ jobs:
|
|||||||
[Build]
|
[Build]
|
||||||
ToolsTreeDistribution=fedora
|
ToolsTreeDistribution=fedora
|
||||||
ToolsTreeRelease=rawhide
|
ToolsTreeRelease=rawhide
|
||||||
ToolsTreePackages=
|
|
||||||
libgcrypt-devel
|
|
||||||
libgpg-error-devel
|
|
||||||
musl-gcc
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
mkosi -f box -- true
|
mkosi -f box -- true
|
||||||
|
|||||||
8
NEWS
8
NEWS
@ -44,6 +44,14 @@ CHANGES WITH 260 in spe:
|
|||||||
SYSTEMD_COLORS=256, and SYSTEMD_COLORS=24bit respectively when output
|
SYSTEMD_COLORS=256, and SYSTEMD_COLORS=24bit respectively when output
|
||||||
is to a non-dumb TTY, and like SYSTEMD_COLORS=no otherwise.
|
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:
|
CHANGES WITH 259:
|
||||||
|
|
||||||
Announcements of Future Feature Removals and Incompatible Changes:
|
Announcements of Future Feature Removals and Incompatible Changes:
|
||||||
|
|||||||
3
TODO
3
TODO
@ -121,6 +121,9 @@ Deprecations and removals:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* networkd: maintain a file in /run/ that can be symlinked into /run/issue.d/
|
||||||
|
that always shows the current primary IP address
|
||||||
|
|
||||||
* report:
|
* report:
|
||||||
- should the list of metrics use JSON-SEQ? or maybe be wrapped in a json
|
- 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)
|
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"
|
- 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
|
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,
|
about at `LOG_ERR` level. Failures that are noteworthy, but we proceed anyway,
|
||||||
should be loged at `LOG_WARN` level. Important informational messages should
|
should be logged at `LOG_WARN` level. Important informational messages should
|
||||||
use `LOG_NOTICE` and regular informational messages should use
|
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_INFO`. Note that the latter is the default maximum log level, i.e. only
|
||||||
`LOG_DEBUG` messages are hidden by default.
|
`LOG_DEBUG` messages are hidden by default.
|
||||||
|
|||||||
@ -30,15 +30,12 @@
|
|||||||
#
|
#
|
||||||
# If the property is missing, user-space can assume:
|
# If the property is missing, user-space can assume:
|
||||||
# ID_INPUT_JOYSTICK_INTEGRATION=external
|
# 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.
|
||||||
|
|
||||||
joystick:bluetooth:*
|
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
|
||||||
ID_INPUT_JOYSTICK_INTEGRATION=external
|
# this will make this usb joystick to behave as internal.
|
||||||
|
#joystick:usb:vffffp0000*
|
||||||
###########################################################
|
# ID_INPUT_JOYSTICK_INTEGRATION=internal
|
||||||
# GPD
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
# GPD Win, Classic and XBox 360 compat modes
|
|
||||||
joystick:usb:v11c5p5507*
|
|
||||||
joystick:usb:v045ep028e*
|
|
||||||
ID_INPUT_JOYSTICK_INTEGRATION=internal
|
|
||||||
|
|||||||
@ -28,44 +28,18 @@
|
|||||||
# Permitted keys:
|
# Permitted keys:
|
||||||
# Specify whether a touchpad is a built-in one or external:
|
# Specify whether a touchpad is a built-in one or external:
|
||||||
# ID_INPUT_TOUCHPAD_INTEGRATION=internal|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.
|
||||||
|
|
||||||
touchpad:i8042:*
|
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
|
||||||
touchpad:rmi:*
|
# this will make this bluetooth touchpad to behave as internal.
|
||||||
touchpad:usb:*
|
#touchpad:bluetooth:vffffp0000:*
|
||||||
ID_INPUT_TOUCHPAD_INTEGRATION=internal
|
# 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)
|
# Lenovo IdeaPad Duet3 10IGL5 (82AT)
|
||||||
###########################################################
|
###########################################################
|
||||||
touchpad:bluetooth:v17efp60fa:*
|
touchpad:bluetooth:v17efp60fa:*
|
||||||
ID_INPUT_TOUCHPAD_INTEGRATION=internal
|
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')
|
print(f'{fname}: {len(groups)} match groups, {n_matches} matches, {n_props} properties')
|
||||||
|
|
||||||
if n_matches == 0 or n_props == 0:
|
if n_matches == 0 or n_props == 0:
|
||||||
error(f'{fname}: no matches or props')
|
print(f'{fname}: no matches or props')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = sys.argv[1:] or sorted([
|
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
|
<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
|
to the firmware boot option item description (as configured with
|
||||||
<option>--efi-boot-option-description=</option> above). This is useful when installing multiple
|
<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 discernable
|
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernible
|
||||||
and give a hint which disk is booted into. Note that this uses hardware model information, and hence
|
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>
|
might not be too useful in case multiple disks of an identical model are used.</para>
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,18 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
</variablelist>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
@ -79,10 +91,11 @@
|
|||||||
<programlisting># /etc/systemd/dns-delegate.d/foobar.dns-delegate
|
<programlisting># /etc/systemd/dns-delegate.d/foobar.dns-delegate
|
||||||
[Delegate]
|
[Delegate]
|
||||||
DNS=203.0.113.47
|
DNS=203.0.113.47
|
||||||
Domains=foobar.com</programlisting>
|
Domains=foobar.com
|
||||||
|
FirewallMark=42</programlisting>
|
||||||
|
|
||||||
<para>This ensures lookups of <literal>foobar.com</literal> and any domains below it are directed to
|
<para>This ensures lookups of <literal>foobar.com</literal> and any domains below it are directed to
|
||||||
DNS server 203.0.113.47.</para>
|
DNS server 203.0.113.47 and any packets related to this lookup have a firewall mark set to 42.</para>
|
||||||
</example>
|
</example>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@ -6444,6 +6444,117 @@ ServerAddress=192.168.0.1/24</programlisting>
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</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>
|
<refsect1>
|
||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
<example>
|
<example>
|
||||||
@ -6771,6 +6882,29 @@ Xfrm=xfrm0</programlisting>
|
|||||||
This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
|
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.
|
If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
|
||||||
</para>
|
</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>
|
</example>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Packages=
|
|||||||
github-cli
|
github-cli
|
||||||
lcov
|
lcov
|
||||||
libucontext
|
libucontext
|
||||||
|
musl
|
||||||
mypy
|
mypy
|
||||||
pkgconf
|
pkgconf
|
||||||
ruff
|
ruff
|
||||||
|
|||||||
@ -5,7 +5,12 @@ Distribution=fedora
|
|||||||
|
|
||||||
[Content]
|
[Content]
|
||||||
Packages=
|
Packages=
|
||||||
lcov
|
|
||||||
gh
|
gh
|
||||||
|
lcov
|
||||||
|
libgcrypt-devel
|
||||||
|
libgpg-error-devel
|
||||||
|
musl-libc
|
||||||
|
musl-clang
|
||||||
|
musl-gcc
|
||||||
ruff
|
ruff
|
||||||
shellcheck
|
shellcheck
|
||||||
|
|||||||
@ -5,11 +5,19 @@ SUBSYSTEM!="input", GOTO="persistent_input_end"
|
|||||||
SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
|
SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
|
||||||
# Bluetooth devices don't always have the bluetooth subsystem
|
# Bluetooth devices don't always have the bluetooth subsystem
|
||||||
ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
|
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=="rmi4", ENV{ID_BUS}="rmi"
|
||||||
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
|
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
|
||||||
|
|
||||||
SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"
|
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
|
# determine class name for persistent symlinks
|
||||||
ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
|
ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
|
||||||
ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"
|
ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"
|
||||||
|
|||||||
25
rules.d/65-integration.rules
Normal file
25
rules.d/65-integration.rules
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# 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,6 +23,7 @@ rules = [
|
|||||||
'60-persistent-v4l.rules',
|
'60-persistent-v4l.rules',
|
||||||
'60-sensor.rules',
|
'60-sensor.rules',
|
||||||
'60-serial.rules',
|
'60-serial.rules',
|
||||||
|
'65-integration.rules',
|
||||||
'70-camera.rules',
|
'70-camera.rules',
|
||||||
'70-joystick.rules',
|
'70-joystick.rules',
|
||||||
'70-mouse.rules',
|
'70-mouse.rules',
|
||||||
|
|||||||
@ -348,8 +348,8 @@ static int clamp_brightness(
|
|||||||
assert(brightness);
|
assert(brightness);
|
||||||
|
|
||||||
/* Some systems turn the backlight all the way off at the lowest levels. This clamps the saved
|
/* Some systems turn the backlight all the way off at the lowest levels. This clamps the saved
|
||||||
* brightness to at least 1 or 5% of max_brightness in case of 'backlight' subsystem. This
|
* brightness to at least 1 or 1% of max_brightness (whichever is bigger) in case of 'backlight' subsystem.
|
||||||
* avoids preserving an unreadably dim screen, which would otherwise force the user to disable
|
* This avoids preserving an unreadably dim screen, which would otherwise force the user to disable
|
||||||
* state restoration. */
|
* state restoration. */
|
||||||
|
|
||||||
min_brightness = (unsigned) ((double) max_brightness * percent / 100);
|
min_brightness = (unsigned) ((double) max_brightness * percent / 100);
|
||||||
@ -385,7 +385,7 @@ static int shall_clamp(sd_device *device, unsigned *ret) {
|
|||||||
return r;
|
return r;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
property = "ID_BACKLIGHT_CLAMP";
|
property = "ID_BACKLIGHT_CLAMP";
|
||||||
default_percent = 5;
|
default_percent = 1;
|
||||||
} else {
|
} else {
|
||||||
property = "ID_LEDS_CLAMP";
|
property = "ID_LEDS_CLAMP";
|
||||||
default_percent = 0;
|
default_percent = 0;
|
||||||
|
|||||||
@ -32,8 +32,6 @@
|
|||||||
* message.
|
* message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct iovec;
|
|
||||||
|
|
||||||
typedef struct LogContext {
|
typedef struct LogContext {
|
||||||
unsigned n_ref;
|
unsigned n_ref;
|
||||||
/* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory
|
/* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "capability-util.h"
|
||||||
#include "dlfcn-util.h"
|
#include "dlfcn-util.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
@ -215,53 +216,6 @@ int namespace_open(
|
|||||||
return pidref_namespace_open(&pidref, ret_pidns_fd, ret_mntns_fd, ret_netns_fd, ret_userns_fd, ret_root_fd);
|
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) {
|
static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -283,20 +237,43 @@ static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
|
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||||
int r;
|
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() now, to avoid us inadvertently loading shared library from another namespace */
|
||||||
block_dlopen();
|
block_dlopen();
|
||||||
|
|
||||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
if (userns_fd >= 0) {
|
||||||
return -errno;
|
/* 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) {
|
if (pidns_fd >= 0) {
|
||||||
r = namespace_enter_one_idempotent(pidns_fd, NAMESPACE_PID);
|
r = namespace_enter_one_idempotent(pidns_fd, NAMESPACE_PID);
|
||||||
@ -316,6 +293,10 @@ int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int net
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userns_fd >= 0 && have_cap_sys_admin)
|
||||||
|
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
if (root_fd >= 0) {
|
if (root_fd >= 0) {
|
||||||
if (fchdir(root_fd) < 0)
|
if (fchdir(root_fd) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
@ -324,7 +305,15 @@ int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int net
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
return maybe_setgroups(/* size = */ 0, NULL);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_is_namespace(int fd, NamespaceType type) {
|
int fd_is_namespace(int fd, NamespaceType type) {
|
||||||
|
|||||||
@ -47,7 +47,6 @@ int namespace_open(
|
|||||||
int *ret_root_fd);
|
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(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 fd_is_namespace(int fd, NamespaceType type);
|
||||||
int is_our_namespace(int fd, NamespaceType type);
|
int is_our_namespace(int fd, NamespaceType type);
|
||||||
|
|||||||
@ -1128,10 +1128,6 @@ bool is_main_thread(void) {
|
|||||||
return cached;
|
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) {
|
unsigned long personality_from_string(const char *s) {
|
||||||
Architecture architecture;
|
Architecture architecture;
|
||||||
|
|
||||||
@ -1778,7 +1774,6 @@ int namespace_fork_full(
|
|||||||
int netns_fd,
|
int netns_fd,
|
||||||
int userns_fd,
|
int userns_fd,
|
||||||
int root_fd,
|
int root_fd,
|
||||||
bool delegated,
|
|
||||||
PidRef *ret) {
|
PidRef *ret) {
|
||||||
|
|
||||||
_cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
|
||||||
@ -1824,10 +1819,7 @@ int namespace_fork_full(
|
|||||||
|
|
||||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||||
|
|
||||||
if (delegated)
|
r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
|
||||||
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) {
|
if (r < 0) {
|
||||||
log_full_errno(prio, r, "Failed to join namespace: %m");
|
log_full_errno(prio, r, "Failed to join namespace: %m");
|
||||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||||
@ -1887,6 +1879,10 @@ int namespace_fork_full(
|
|||||||
return 1;
|
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) {
|
int set_oom_score_adjust(int value) {
|
||||||
char t[DECIMAL_STR_MAX(int)];
|
char t[DECIMAL_STR_MAX(int)];
|
||||||
|
|
||||||
|
|||||||
@ -87,8 +87,6 @@ int pidref_from_same_root_fs(PidRef *a, PidRef *b);
|
|||||||
|
|
||||||
bool is_main_thread(void);
|
bool is_main_thread(void);
|
||||||
|
|
||||||
bool oom_score_adjust_is_valid(int oa);
|
|
||||||
|
|
||||||
#ifndef PERSONALITY_INVALID
|
#ifndef PERSONALITY_INVALID
|
||||||
/* personality(2) documents that 0xFFFFFFFFUL is used for querying the
|
/* personality(2) documents that 0xFFFFFFFFUL is used for querying the
|
||||||
* current personality, hence let's use that here as error
|
* current personality, hence let's use that here as error
|
||||||
@ -201,7 +199,6 @@ int namespace_fork_full(
|
|||||||
int netns_fd,
|
int netns_fd,
|
||||||
int userns_fd,
|
int userns_fd,
|
||||||
int root_fd,
|
int root_fd,
|
||||||
bool delegated,
|
|
||||||
PidRef *ret);
|
PidRef *ret);
|
||||||
|
|
||||||
static inline int namespace_fork(
|
static inline int namespace_fork(
|
||||||
@ -216,10 +213,11 @@ static inline int namespace_fork(
|
|||||||
PidRef *ret) {
|
PidRef *ret) {
|
||||||
|
|
||||||
return namespace_fork_full(outer_name, inner_name, NULL, 0, flags,
|
return namespace_fork_full(outer_name, inner_name, NULL, 0, flags,
|
||||||
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd, false,
|
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd,
|
||||||
ret);
|
ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oom_score_adjust_is_valid(int oa);
|
||||||
int set_oom_score_adjust(int value);
|
int set_oom_score_adjust(int value);
|
||||||
int get_oom_score_adjust(int *ret);
|
int get_oom_score_adjust(int *ret);
|
||||||
|
|
||||||
@ -235,9 +233,6 @@ int get_oom_score_adjust(int *ret);
|
|||||||
|
|
||||||
assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
|
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);
|
int setpriority_closest(int priority);
|
||||||
|
|
||||||
_noreturn_ void freeze(void);
|
_noreturn_ void freeze(void);
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#include "namespace-util.h"
|
#include "namespace-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
@ -1666,7 +1667,7 @@ int openpt_allocate_in_namespace(
|
|||||||
|
|
||||||
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
|
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_debug_errno(r, "Failed to open namespaces of PID "PID_FMT": %m", pidref->pid);
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair) < 0)
|
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|||||||
@ -437,7 +437,7 @@ void cleanup_tmpfile_data_done(struct cleanup_tmpfile_data *d) {
|
|||||||
assert(d);
|
assert(d);
|
||||||
|
|
||||||
if (!d->dir_fd ||
|
if (!d->dir_fd ||
|
||||||
*d->dir_fd < 0 ||
|
(*d->dir_fd < 0 && *d->dir_fd != AT_FDCWD) ||
|
||||||
!d->filename ||
|
!d->filename ||
|
||||||
!*d->filename)
|
!*d->filename)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -920,19 +920,28 @@ int maybe_setgroups(size_t size, const gid_t *list) {
|
|||||||
|
|
||||||
/* Check if setgroups is allowed before we try to drop all the auxiliary groups */
|
/* Check if setgroups is allowed before we try to drop all the auxiliary groups */
|
||||||
if (size == 0) { /* Dropping all aux 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;
|
_cleanup_free_ char *setgroups_content = NULL;
|
||||||
bool can_setgroups;
|
|
||||||
|
|
||||||
r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
|
r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
|
||||||
if (r == -ENOENT)
|
if (r < 0 && 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;
|
return r;
|
||||||
else
|
if (r > 0 && streq(setgroups_content, "deny")) {
|
||||||
can_setgroups = streq(setgroups_content, "allow");
|
|
||||||
|
|
||||||
if (!can_setgroups) {
|
|
||||||
log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
|
log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -175,26 +175,22 @@ int install_random_seed(const char *esp) {
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(fd, "Failed to open random seed file for writing: %m");
|
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 */
|
if (!warned) /* only warn once per seed file */
|
||||||
(void) random_seed_verify_permissions(fd, S_IFREG);
|
(void) random_seed_verify_permissions(fd, S_IFREG);
|
||||||
|
|
||||||
r = loop_write(fd, buffer, sizeof(buffer));
|
r = loop_write(fd, buffer, sizeof(buffer));
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to write random seed file: %m");
|
return log_error_errno(r, "Failed to write random seed file: %m");
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0) {
|
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0)
|
||||||
r = log_error_errno(errno, "Failed to sync random seed file: %m");
|
return 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) {
|
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");
|
return log_error_errno(errno, "Failed to move random seed file into place: %m");
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = mfree(tmp);
|
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
|
||||||
|
|
||||||
if (syncfs(fd) < 0)
|
if (syncfs(fd) < 0)
|
||||||
return log_error_errno(errno, "Failed to sync ESP file system: %m");
|
return log_error_errno(errno, "Failed to sync ESP file system: %m");
|
||||||
@ -202,12 +198,6 @@ 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));
|
log_info("Random seed file %s/loader/random-seed successfully %s (%zu bytes).", esp, refreshed ? "refreshed" : "written", sizeof(buffer));
|
||||||
|
|
||||||
return set_system_token();
|
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) {
|
int verb_random_seed(int argc, char *argv[], void *userdata) {
|
||||||
|
|||||||
@ -642,14 +642,12 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
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,
|
r = acquire_esp(/* unprivileged_mode= */ false,
|
||||||
/* graceful= */ false,
|
/* graceful= */ false,
|
||||||
/* ret_part= */ NULL,
|
/* ret_part= */ NULL,
|
||||||
|
|||||||
@ -1255,7 +1255,6 @@ int unit_refresh_credentials(Unit *u) {
|
|||||||
(int[]) { tunnel_fds[1] }, 1,
|
(int[]) { tunnel_fds[1] }, 1,
|
||||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
|
||||||
pidns_fd, mntns_fd, /* netns_fd = */ -EBADF, userns_fd, root_fd,
|
pidns_fd, mntns_fd, /* netns_fd = */ -EBADF, userns_fd, root_fd,
|
||||||
/* delegated = */ MANAGER_IS_USER(u->manager),
|
|
||||||
&child);
|
&child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_full_errno(ERRNO_IS_NEG_PRIVILEGE(r) ? LOG_WARNING : LOG_ERR, r,
|
return log_full_errno(ERRNO_IS_NEG_PRIVILEGE(r) ? LOG_WARNING : LOG_ERR, r,
|
||||||
|
|||||||
@ -171,7 +171,11 @@ int manager_serialize(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = varlink_server_serialize(m->varlink_server, f, fds);
|
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);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -282,7 +286,6 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
||||||
bool deserialize_varlink_sockets = false;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
@ -490,23 +493,28 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|||||||
r = strv_extend(&m->subscribed_as_strv, val);
|
r = strv_extend(&m->subscribed_as_strv, val);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
|
} else if ((val = startswith(l, "varlink-server-metrics-"))) {
|
||||||
if (!m->varlink_server) {
|
if (m->objective == MANAGER_RELOAD)
|
||||||
r = manager_setup_varlink_server(m);
|
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
|
||||||
if (r < 0) {
|
continue;
|
||||||
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
deserialize_varlink_sockets = true;
|
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);
|
||||||
|
|
||||||
/* To avoid unnecessary deserialization (i.e. during reload vs. reexec) we only deserialize
|
} else if ((val = startswith(l, "varlink-server-"))) {
|
||||||
* the FDs if we had to create a new m->varlink_server. The deserialize_varlink_sockets flag
|
if (m->objective == MANAGER_RELOAD)
|
||||||
* is initialized outside of the loop, is flipped after the VarlinkServer is setup, and
|
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
|
||||||
* remains set until all serialized contents are handled. */
|
continue;
|
||||||
if (deserialize_varlink_sockets)
|
|
||||||
|
r = manager_setup_varlink_server(m);
|
||||||
|
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);
|
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
|
||||||
|
|
||||||
} else if ((val = startswith(l, "dump-ratelimit=")))
|
} else if ((val = startswith(l, "dump-ratelimit=")))
|
||||||
deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val);
|
deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val);
|
||||||
else if ((val = startswith(l, "reload-reexec-ratelimit=")))
|
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(
|
r = sd_json_variant_append_arraybo(
|
||||||
&v,
|
&v,
|
||||||
SD_JSON_BUILD_PAIR_INTEGER("family", i->family),
|
SD_JSON_BUILD_PAIR_INTEGER("family", i->family),
|
||||||
JSON_BUILD_PAIR_IN_ADDR("address", &i->address, i->family),
|
JSON_BUILD_PAIR_IN_ADDR("address", i->family, &i->address),
|
||||||
SD_JSON_BUILD_PAIR_UNSIGNED("prefixLength", i->prefixlen));
|
SD_JSON_BUILD_PAIR_UNSIGNED("prefixLength", i->prefixlen));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -299,6 +299,7 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void
|
|||||||
SD_JSON_BUILD_OBJECT(
|
SD_JSON_BUILD_OBJECT(
|
||||||
SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->restrict_network_interfaces_is_allow_list),
|
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_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),
|
JSON_BUILD_PAIR_CALLBACK_NON_NULL("NFTSet", nft_set_build_json, &c->nft_set_context),
|
||||||
|
|
||||||
/* BPF programs */
|
/* BPF programs */
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "sd-json.h"
|
||||||
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "metrics.h"
|
#include "metrics.h"
|
||||||
@ -175,10 +178,10 @@ const MetricFamily metric_family_table[] = {
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
int vl_method_describe(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) {
|
||||||
return metrics_method_describe(metric_family_table, link, parameters, flags, userdata);
|
return metrics_method_describe(metric_family_table, link, parameters, flags, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
int vl_method_list_metrics(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);
|
return metrics_method_list(metric_family_table, link, parameters, flags, userdata);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sd-varlink.h"
|
#include "core-forward.h"
|
||||||
#include "sd-json.h"
|
|
||||||
|
|
||||||
#define METRIC_IO_SYSTEMD_MANAGER_PREFIX "io.systemd.Manager."
|
#define METRIC_IO_SYSTEMD_MANAGER_PREFIX "io.systemd.Manager."
|
||||||
|
|
||||||
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
int vl_method_list_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);
|
int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "varlink.h"
|
#include "varlink.h"
|
||||||
#include "varlink-dynamic-user.h"
|
#include "varlink-dynamic-user.h"
|
||||||
@ -375,6 +374,8 @@ int manager_setup_varlink_server(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to allocate Varlink server: %m");
|
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(
|
r = sd_varlink_server_add_interface_many(
|
||||||
s,
|
s,
|
||||||
&vl_interface_io_systemd_Manager,
|
&vl_interface_io_systemd_Manager,
|
||||||
@ -425,26 +426,64 @@ int manager_setup_varlink_server(Manager *m) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_setup_varlink_metrics_server(Manager *m) {
|
int manager_setup_varlink_metrics_server(Manager *m) {
|
||||||
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
|
||||||
if (MANAGER_IS_SYSTEM(m))
|
if (MANAGER_IS_SYSTEM(m))
|
||||||
flags |= SD_VARLINK_SERVER_ACCOUNT_UID;
|
flags |= SD_VARLINK_SERVER_ACCOUNT_UID;
|
||||||
|
|
||||||
r = metrics_setup_varlink_server(
|
return metrics_setup_varlink_server(&m->metrics_varlink_server, flags,
|
||||||
&m->metrics_varlink_server, flags, m->event, vl_method_list, vl_method_describe, m);
|
m->event, EVENT_PRIORITY_IPC,
|
||||||
if (r < 0)
|
vl_method_list_metrics, vl_method_describe_metrics,
|
||||||
return r;
|
m);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_varlink_init_system(Manager *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);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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) {
|
||||||
int r;
|
int r;
|
||||||
_cleanup_free_ char *metrics_address = NULL;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
@ -453,38 +492,21 @@ static int manager_varlink_init_system(Manager *m) {
|
|||||||
return log_error_errno(r, "Failed to set up varlink server: %m");
|
return log_error_errno(r, "Failed to set up varlink server: %m");
|
||||||
bool fresh = r > 0;
|
bool fresh = r > 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 metrics_fresh = r > 0;
|
|
||||||
|
|
||||||
r = runtime_directory_generic(m->runtime_scope, "systemd/report/io.systemd.Manager", &metrics_address);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!MANAGER_IS_TEST_RUN(m)) {
|
if (!MANAGER_IS_TEST_RUN(m)) {
|
||||||
FOREACH_STRING(address,
|
r = varlink_server_listen_many_idempotent(
|
||||||
"/run/systemd/userdb/io.systemd.DynamicUser",
|
m->varlink_server, fresh,
|
||||||
VARLINK_PATH_MANAGED_OOM_SYSTEM,
|
/* prefix = */ NULL,
|
||||||
"/run/systemd/io.systemd.Manager",
|
"/run/systemd/io.systemd.Manager",
|
||||||
metrics_address) {
|
"/run/systemd/userdb/io.systemd.DynamicUser",
|
||||||
|
VARLINK_PATH_MANAGED_OOM_SYSTEM);
|
||||||
sd_varlink_server *server = streq(address, metrics_address) ? m->metrics_varlink_server : m->varlink_server;
|
if (r < 0)
|
||||||
fresh = streq(address, metrics_address) ? metrics_fresh : fresh;
|
return r;
|
||||||
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_varlink_init_user(Manager *m) {
|
static int manager_varlink_init_user_api(Manager *m) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
@ -497,30 +519,46 @@ static int manager_varlink_init_user(Manager *m) {
|
|||||||
return log_error_errno(r, "Failed to set up varlink server: %m");
|
return log_error_errno(r, "Failed to set up varlink server: %m");
|
||||||
bool fresh = r > 0;
|
bool fresh = r > 0;
|
||||||
|
|
||||||
FOREACH_STRING(a,
|
r = varlink_server_listen_many_idempotent(
|
||||||
"systemd/io.systemd.Manager") {
|
m->varlink_server, fresh,
|
||||||
_cleanup_free_ char *address = NULL;
|
m->prefix[EXEC_DIRECTORY_RUNTIME],
|
||||||
address = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], a);
|
"systemd/io.systemd.Manager");
|
||||||
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
|
return r;
|
||||||
|
|
||||||
return manager_varlink_managed_oom_connect(m);
|
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;
|
||||||
|
|
||||||
|
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 manager_varlink_init(Manager *m) {
|
||||||
return MANAGER_IS_SYSTEM(m) ? manager_varlink_init_system(m) : manager_varlink_init_user(m);
|
int r;
|
||||||
|
|
||||||
|
if (MANAGER_IS_SYSTEM(m))
|
||||||
|
r = manager_varlink_init_system_api(m);
|
||||||
|
else
|
||||||
|
r = manager_varlink_init_user_api(m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return manager_varlink_init_metrics(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void manager_varlink_done(Manager *m) {
|
void manager_varlink_done(Manager *m) {
|
||||||
@ -534,6 +572,7 @@ void manager_varlink_done(Manager *m) {
|
|||||||
|
|
||||||
m->varlink_server = sd_varlink_server_unref(m->varlink_server);
|
m->varlink_server = sd_varlink_server_unref(m->varlink_server);
|
||||||
m->managed_oom_varlink = sd_varlink_close_unref(m->managed_oom_varlink);
|
m->managed_oom_varlink = sd_varlink_close_unref(m->managed_oom_varlink);
|
||||||
|
|
||||||
m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server);
|
m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "core-forward.h"
|
#include "core-forward.h"
|
||||||
|
|
||||||
int manager_setup_varlink_server(Manager *m);
|
int manager_setup_varlink_server(Manager *m);
|
||||||
|
int manager_setup_varlink_metrics_server(Manager *m);
|
||||||
|
|
||||||
int manager_varlink_init(Manager *m);
|
int manager_varlink_init(Manager *m);
|
||||||
void manager_varlink_done(Manager *m);
|
void manager_varlink_done(Manager *m);
|
||||||
|
|||||||
@ -1793,14 +1793,12 @@ static int vl_method_list_transfers(sd_varlink *link, sd_json_variant *parameter
|
|||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
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");
|
r = varlink_set_sentinel(link, "io.systemd.Import.NoTransfers");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -317,8 +317,6 @@ int dhcp_server_static_leases_append_json(sd_dhcp_server *server, sd_json_varian
|
|||||||
|
|
||||||
int dhcp_server_save_leases(sd_dhcp_server *server) {
|
int dhcp_server_save_leases(sd_dhcp_server *server) {
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
_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;
|
sd_id128_t boot_id;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -355,25 +353,27 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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);
|
r = fopen_temporary_at(server->lease_dir_fd, server->lease_file, &f, &temp_path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
CLEANUP_TMPFILE_AT(server->lease_dir_fd, temp_path);
|
||||||
|
|
||||||
(void) fchmod(fileno(f), 0644);
|
(void) fchmod(fileno(f), 0644);
|
||||||
|
|
||||||
r = sd_json_variant_dump(v, SD_JSON_FORMAT_NEWLINE | SD_JSON_FORMAT_FLUSH, f, /* prefix= */ NULL);
|
r = sd_json_variant_dump(v, SD_JSON_FORMAT_NEWLINE | SD_JSON_FORMAT_FLUSH, f, /* prefix= */ NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto failure;
|
return r;
|
||||||
|
|
||||||
r = conservative_renameat(server->lease_dir_fd, temp_path, server->lease_dir_fd, server->lease_file);
|
r = conservative_renameat(server->lease_dir_fd, temp_path, server->lease_dir_fd, server->lease_file);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto failure;
|
return r;
|
||||||
|
|
||||||
|
temp_path = mfree(temp_path); /* disarm CLEANUP_TMPFILE_AT() */
|
||||||
return 0;
|
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) {
|
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 "sd-json.h"
|
||||||
|
|
||||||
#include "sd-forward.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "sd-forward.h"
|
||||||
#include "string-util.h" /* IWYU pragma: keep */
|
#include "string-util.h" /* IWYU pragma: keep */
|
||||||
|
|
||||||
#define JSON_VARIANT_REPLACE(v, q) \
|
#define JSON_VARIANT_REPLACE(v, q) \
|
||||||
@ -175,9 +175,9 @@ enum {
|
|||||||
_JSON_BUILD_PAIR_VARIANT_NON_EMPTY,
|
_JSON_BUILD_PAIR_VARIANT_NON_EMPTY,
|
||||||
/* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */
|
/* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */
|
||||||
_JSON_BUILD_PAIR_BYTE_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_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_ETHER_ADDR_NON_NULL,
|
||||||
_JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
|
_JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
|
||||||
_JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL,
|
_JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL,
|
||||||
@ -190,12 +190,6 @@ enum {
|
|||||||
_JSON_BUILD_PAIR_TRISTATE_NON_NULL,
|
_JSON_BUILD_PAIR_TRISTATE_NON_NULL,
|
||||||
_JSON_BUILD_PAIR_PIDREF_NON_NULL,
|
_JSON_BUILD_PAIR_PIDREF_NON_NULL,
|
||||||
_JSON_BUILD_PAIR_DEVNUM,
|
_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,
|
_SD_JSON_BUILD_REALLYMAX,
|
||||||
};
|
};
|
||||||
@ -206,7 +200,7 @@ enum {
|
|||||||
#define JSON_BUILD_CONST_STRING(s) _SD_JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s)
|
#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_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_IN6_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr))
|
||||||
#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_IN_ADDR(f, v) 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_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_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 }
|
#define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s }
|
||||||
@ -229,9 +223,15 @@ 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_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_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_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_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_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_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_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_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_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_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_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_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 }
|
#define JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL(name, t) _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, (const char*) { name }, (dual_timestamp*) { t }
|
||||||
@ -243,18 +243,12 @@ 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_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_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_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_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_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_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_IN6_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(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_IN_ADDR(name, f, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(f, v))
|
||||||
#define JSON_BUILD_PAIR_ETHER_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v))
|
#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_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))
|
#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;
|
r = 0;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
for (size_t i = 0; i < n_stack; i++)
|
FOREACH_ARRAY(i, stack, n_stack)
|
||||||
json_stack_release(stack + i);
|
json_stack_release(i);
|
||||||
|
|
||||||
free(stack);
|
free(stack);
|
||||||
|
|
||||||
@ -4666,63 +4666,9 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: {
|
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL:
|
||||||
const struct in_addr *a;
|
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL:
|
||||||
const char *n;
|
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: {
|
||||||
|
|
||||||
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 union in_addr_union *a;
|
||||||
const char *n;
|
const char *n;
|
||||||
int f;
|
int f;
|
||||||
@ -4733,10 +4679,16 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n = va_arg(ap, const char *);
|
n = va_arg(ap, const char *);
|
||||||
a = va_arg(ap, const union in_addr_union *);
|
|
||||||
f = va_arg(ap, int);
|
f = va_arg(ap, int);
|
||||||
|
a = va_arg(ap, const union in_addr_union *);
|
||||||
|
|
||||||
|
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);
|
r = sd_json_variant_new_string(&add, n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
@ -4744,9 +4696,36 @@ _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));
|
r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
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 = 2; /* we generated two items */
|
n_subtract = command == _JSON_BUILD_PAIR_IN_ADDR_NON_NULL ? 2 : 4;
|
||||||
|
|
||||||
current->expect = EXPECT_OBJECT_KEY;
|
current->expect = EXPECT_OBJECT_KEY;
|
||||||
break;
|
break;
|
||||||
@ -4896,207 +4875,6 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
|
|||||||
break;
|
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: {
|
case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: {
|
||||||
sd_json_build_callback_t cb;
|
sd_json_build_callback_t cb;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
@ -5227,8 +5005,8 @@ done:
|
|||||||
r = 0;
|
r = 0;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
for (size_t i = 0; i < n_stack; i++)
|
FOREACH_ARRAY(i, stack, n_stack)
|
||||||
json_stack_release(stack + i);
|
json_stack_release(i);
|
||||||
|
|
||||||
free(stack);
|
free(stack);
|
||||||
|
|
||||||
|
|||||||
@ -247,28 +247,20 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
|
|||||||
/* stdio_fds= */ NULL,
|
/* stdio_fds= */ NULL,
|
||||||
/* except_fds= */ (int[]) { pair[1] },
|
/* except_fds= */ (int[]) { pair[1] },
|
||||||
/* n_except_fds= */ 1,
|
/* n_except_fds= */ 1,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
&pidref);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
char spid[DECIMAL_STR_MAX(pid_t)+1];
|
char spid[DECIMAL_STR_MAX(pid_t)+1];
|
||||||
const char *setenv_list[] = {
|
const char *setenv_list[] = {
|
||||||
"LISTEN_FDS", "1",
|
|
||||||
"LISTEN_PID", spid,
|
"LISTEN_PID", spid,
|
||||||
|
"LISTEN_FDS", "1",
|
||||||
"LISTEN_FDNAMES", "varlink",
|
"LISTEN_FDNAMES", "varlink",
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
};
|
};
|
||||||
/* Child */
|
/* 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);
|
xsprintf(spid, PID_FMT, pidref.pid);
|
||||||
|
|
||||||
uint64_t pidfdid;
|
uint64_t pidfdid;
|
||||||
@ -364,7 +356,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
|||||||
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
|
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
|
||||||
/* except_fds= */ NULL,
|
/* except_fds= */ NULL,
|
||||||
/* n_except_fds= */ 0,
|
/* n_except_fds= */ 0,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||||
&pidref);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
@ -448,7 +440,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
|||||||
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
|
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
|
||||||
/* except_fds= */ NULL,
|
/* except_fds= */ NULL,
|
||||||
/* n_except_fds= */ 0,
|
/* n_except_fds= */ 0,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||||
&pidref);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
@ -1389,15 +1381,14 @@ static int varlink_format_queue(sd_varlink *v) {
|
|||||||
* would not corrupt our fd message boundaries */
|
* would not corrupt our fd message boundaries */
|
||||||
|
|
||||||
while (v->output_queue) {
|
while (v->output_queue) {
|
||||||
_cleanup_free_ int *array = NULL;
|
|
||||||
|
|
||||||
assert(v->n_output_queue > 0);
|
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 */
|
if (v->n_output_fds > 0) /* unwritten fds? if we'd add more we'd corrupt the fd message boundaries, hence wait */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
VarlinkJsonQueueItem *q = v->output_queue;
|
||||||
|
_cleanup_free_ int *array = NULL;
|
||||||
|
|
||||||
if (q->n_fds > 0) {
|
if (q->n_fds > 0) {
|
||||||
array = newdup(int, q->fds, q->n_fds);
|
array = newdup(int, q->fds, q->n_fds);
|
||||||
if (!array)
|
if (!array)
|
||||||
@ -1409,8 +1400,7 @@ static int varlink_format_queue(sd_varlink *v) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Take possession of the queue element's fds */
|
/* Take possession of the queue element's fds */
|
||||||
free(v->output_fds);
|
free_and_replace(v->output_fds, array);
|
||||||
v->output_fds = TAKE_PTR(array);
|
|
||||||
v->n_output_fds = q->n_fds;
|
v->n_output_fds = q->n_fds;
|
||||||
q->n_fds = 0;
|
q->n_fds = 0;
|
||||||
|
|
||||||
@ -1593,7 +1583,7 @@ static int varlink_dispatch_method(sd_varlink *v) {
|
|||||||
r = callback(v, parameters, flags, v->userdata);
|
r = callback(v, parameters, flags, v->userdata);
|
||||||
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
|
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
|
||||||
if (r < 0) {
|
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
|
/* We got an error back from the callback. Propagate it to the client
|
||||||
* if the method call remains unanswered. */
|
* if the method call remains unanswered. */
|
||||||
@ -1622,6 +1612,16 @@ static int varlink_dispatch_method(sd_varlink *v) {
|
|||||||
varlink_log_errno(v, r, "Failed to process sentinel for method '%s': %m", method);
|
varlink_log_errno(v, r, "Failed to process sentinel for method '%s': %m", method);
|
||||||
} else {
|
} else {
|
||||||
assert(!v->previous);
|
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;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1857,19 +1857,10 @@ _public_ int sd_varlink_wait(sd_varlink *v, uint64_t timeout) {
|
|||||||
r = sd_varlink_get_timeout(v, &t);
|
r = sd_varlink_get_timeout(v, &t);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (t != USEC_INFINITY) {
|
if (t != USEC_INFINITY)
|
||||||
usec_t n;
|
t = usec_sub_unsigned(t, now(CLOCK_MONOTONIC));
|
||||||
|
|
||||||
n = now(CLOCK_MONOTONIC);
|
t = MIN(t, timeout);
|
||||||
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);
|
events = sd_varlink_get_events(v);
|
||||||
if (events < 0)
|
if (events < 0)
|
||||||
@ -2019,7 +2010,7 @@ _public_ int sd_varlink_flush(sd_varlink *v) {
|
|||||||
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
|
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (v->output_buffer_size == 0)
|
if (v->output_buffer_size == 0 && !v->output_queue)
|
||||||
break;
|
break;
|
||||||
if (v->write_disconnected)
|
if (v->write_disconnected)
|
||||||
return -ECONNRESET;
|
return -ECONNRESET;
|
||||||
@ -2681,8 +2672,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
|
* rollback the fds. Note that this is implicitly called whenever an error reply is sent, see
|
||||||
* below. */
|
* below. */
|
||||||
|
|
||||||
close_many(v->output_fds, v->n_output_fds);
|
close_many(v->pushed_fds, v->n_pushed_fds);
|
||||||
v->n_output_fds = 0;
|
v->n_pushed_fds = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2706,7 +2697,7 @@ _public_ int sd_varlink_error(sd_varlink *v, const char *error_id, sd_json_varia
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* If we have a previous reply still ready make sure we queue it before the error. We only
|
/* 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 uncondtionally
|
* ever set "previous" if we're in a streaming method so we pass more=true unconditionally
|
||||||
* here as we know we're still going to queue an error afterwards. */
|
* here as we know we're still going to queue an error afterwards. */
|
||||||
r = varlink_enqueue_item(v, v->previous);
|
r = varlink_enqueue_item(v, v->previous);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -3556,8 +3547,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)));
|
c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
|
||||||
if (c >= server->connections_per_uid_max) {
|
if (c >= server->connections_per_uid_max) {
|
||||||
varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.",
|
varlink_server_log(server, "Per-UID connection limit of %u for '" UID_FMT "' reached, refusing.",
|
||||||
server->connections_per_uid_max);
|
server->connections_per_uid_max, ucred->uid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3610,7 +3601,7 @@ _public_ int sd_varlink_server_add_connection_pair(
|
|||||||
assert_return(input_fd >= 0, -EBADF);
|
assert_return(input_fd >= 0, -EBADF);
|
||||||
assert_return(output_fd >= 0, -EBADF);
|
assert_return(output_fd >= 0, -EBADF);
|
||||||
|
|
||||||
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
|
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_MYSELF_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
|
||||||
|
|
||||||
if (override_ucred)
|
if (override_ucred)
|
||||||
ucred = *override_ucred;
|
ucred = *override_ucred;
|
||||||
@ -3752,11 +3743,7 @@ static int varlink_server_create_listen_fd_socket(sd_varlink_server *s, int fd,
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (s->event) {
|
if (s->event) {
|
||||||
r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss);
|
r = varlink_server_add_socket_event_source(s, ss);
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_event_source_set_priority(ss->event_source, s->event_priority);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -4080,13 +4067,14 @@ _public_ int sd_varlink_server_set_exit_on_idle(sd_varlink_server *s, int b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority) {
|
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss) {
|
||||||
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
|
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(s->event);
|
assert(s->event);
|
||||||
assert(ss);
|
assert(ss);
|
||||||
|
assert(ss->server == s);
|
||||||
assert(ss->fd >= 0);
|
assert(ss->fd >= 0);
|
||||||
assert(!ss->event_source);
|
assert(!ss->event_source);
|
||||||
|
|
||||||
@ -4094,7 +4082,7 @@ int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSo
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_event_source_set_priority(es, priority);
|
r = sd_event_source_set_priority(es, s->event_priority);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -4116,13 +4104,14 @@ _public_ int sd_varlink_server_attach_event(sd_varlink_server *s, sd_event *e, i
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->event_priority = priority;
|
||||||
|
|
||||||
LIST_FOREACH(sockets, ss, s->sockets) {
|
LIST_FOREACH(sockets, ss, s->sockets) {
|
||||||
r = varlink_server_add_socket_event_source(s, ss, priority);
|
r = varlink_server_add_socket_event_source(s, ss);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->event_priority = priority;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -4293,20 +4282,16 @@ _public_ int sd_varlink_server_add_interface_many_internal(sd_varlink_server *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_public_ unsigned sd_varlink_server_connections_max(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 a server is specified, return the setting for that server, otherwise the default value */
|
||||||
if (s)
|
if (s)
|
||||||
return s->connections_max;
|
return s->connections_max;
|
||||||
|
|
||||||
dts = getdtablesize();
|
int dts = getdtablesize();
|
||||||
assert_se(dts > 0);
|
assert_se(dts > 0);
|
||||||
|
|
||||||
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
|
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
|
||||||
if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3)
|
return MIN(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) {
|
_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);
|
VarlinkServerSocket* varlink_server_socket_free(VarlinkServerSocket *ss);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket *, varlink_server_socket_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket *, varlink_server_socket_free);
|
||||||
|
|
||||||
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority);
|
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss);
|
||||||
|
|||||||
@ -376,7 +376,10 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
if (m->uid != 0 && m->class != MACHINE_HOST) {
|
if (m->uid != 0 && m->class != MACHINE_HOST) {
|
||||||
r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
|
r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_debug_errno(
|
||||||
|
r,
|
||||||
|
"Failed to check if machine '%s' is running in the root user namespace: %m",
|
||||||
|
m->name);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return sd_bus_error_set(
|
return sd_bus_error_set(
|
||||||
error,
|
error,
|
||||||
|
|||||||
@ -273,6 +273,7 @@ static int vl_method_mute(
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
_cleanup_free_ Context *nc = new(Context, 1);
|
_cleanup_free_ Context *nc = new(Context, 1);
|
||||||
if (!nc)
|
if (!nc)
|
||||||
@ -294,9 +295,6 @@ static int vl_method_mute(
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
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);
|
r = sd_varlink_server_bind_disconnect(sd_varlink_get_server(link), vl_on_disconnect);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -89,6 +89,8 @@ systemd_networkd_extract_sources = files(
|
|||||||
'networkd-util.c',
|
'networkd-util.c',
|
||||||
'networkd-wifi.c',
|
'networkd-wifi.c',
|
||||||
'networkd-wiphy.c',
|
'networkd-wiphy.c',
|
||||||
|
'networkd-wwan.c',
|
||||||
|
'networkd-wwan-bus.c',
|
||||||
'tc/cake.c',
|
'tc/cake.c',
|
||||||
'tc/codel.c',
|
'tc/codel.c',
|
||||||
'tc/drr.c',
|
'tc/drr.c',
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#include "networkd-route.h"
|
#include "networkd-route.h"
|
||||||
#include "networkd-setlink.h"
|
#include "networkd-setlink.h"
|
||||||
#include "networkd-state-file.h"
|
#include "networkd-state-file.h"
|
||||||
|
#include "networkd-wwan.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
@ -1770,6 +1771,9 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity) {
|
|||||||
if (!link->dhcp_client)
|
if (!link->dhcp_client)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (link_dhcp_enabled_by_bearer(link, AF_INET) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!link_has_carrier(link))
|
if (!link_has_carrier(link))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "networkd-queue.h"
|
#include "networkd-queue.h"
|
||||||
#include "networkd-route.h"
|
#include "networkd-route.h"
|
||||||
#include "networkd-state-file.h"
|
#include "networkd-state-file.h"
|
||||||
|
#include "networkd-wwan.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -494,6 +495,9 @@ int dhcp6_start(Link *link) {
|
|||||||
if (!link_dhcp6_enabled(link))
|
if (!link_dhcp6_enabled(link))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (link_dhcp_enabled_by_bearer(link, AF_INET6) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!link_has_carrier(link))
|
if (!link_has_carrier(link))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
#include "networkd-route.h"
|
#include "networkd-route.h"
|
||||||
#include "networkd-route-util.h"
|
#include "networkd-route-util.h"
|
||||||
#include "networkd-routing-policy-rule.h"
|
#include "networkd-routing-policy-rule.h"
|
||||||
|
#include "networkd-wwan.h"
|
||||||
#include "ordered-set.h"
|
#include "ordered-set.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -541,6 +542,15 @@ static int dns_append_json(Link *link, sd_json_variant **v) {
|
|||||||
return r;
|
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)) {
|
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
|
||||||
const struct in_addr *dns;
|
const struct in_addr *dns;
|
||||||
union in_addr_union s;
|
union in_addr_union s;
|
||||||
@ -613,7 +623,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne
|
|||||||
FOREACH_ARRAY(addr, res->addrs, res->n_addrs) {
|
FOREACH_ARRAY(addr, res->addrs, res->n_addrs) {
|
||||||
r = sd_json_variant_append_arrayb(
|
r = sd_json_variant_append_arrayb(
|
||||||
&addrs_array,
|
&addrs_array,
|
||||||
JSON_BUILD_IN_ADDR(addr, res->family));
|
JSON_BUILD_IN_ADDR(res->family, addr));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -634,7 +644,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_STRING_NON_EMPTY("DoHPath", res->dohpath),
|
||||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports),
|
JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports),
|
||||||
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
||||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, res->family)));
|
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", res->family, p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dnr_append_json(Link *link, sd_json_variant **v) {
|
static int dnr_append_json(Link *link, sd_json_variant **v) {
|
||||||
@ -723,7 +733,7 @@ static int server_append_json_one_addr(int family, const union in_addr_union *a,
|
|||||||
return sd_json_variant_append_arraybo(
|
return sd_json_variant_append_arraybo(
|
||||||
array,
|
array,
|
||||||
SD_JSON_BUILD_PAIR_INTEGER("Family", family),
|
SD_JSON_BUILD_PAIR_INTEGER("Family", family),
|
||||||
JSON_BUILD_PAIR_IN_ADDR("Address", a, family),
|
JSON_BUILD_PAIR_IN_ADDR("Address", family, a),
|
||||||
SD_JSON_BUILD_PAIR_STRING("AddressString", address_str),
|
SD_JSON_BUILD_PAIR_STRING("AddressString", address_str),
|
||||||
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
|
||||||
JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p));
|
JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p));
|
||||||
|
|||||||
@ -63,6 +63,7 @@
|
|||||||
#include "networkd-state-file.h"
|
#include "networkd-state-file.h"
|
||||||
#include "networkd-sysctl.h"
|
#include "networkd-sysctl.h"
|
||||||
#include "networkd-wifi.h"
|
#include "networkd-wifi.h"
|
||||||
|
#include "networkd-wwan-bus.h"
|
||||||
#include "ordered-set.h"
|
#include "ordered-set.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
@ -529,6 +530,9 @@ void link_check_ready(Link *link) {
|
|||||||
if (!link->sr_iov_configured)
|
if (!link->sr_iov_configured)
|
||||||
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
|
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. */
|
/* IPv6LL is assigned after the link gains its carrier. */
|
||||||
if (!link->network->configure_without_carrier &&
|
if (!link->network->configure_without_carrier &&
|
||||||
link_ipv6ll_enabled(link) &&
|
link_ipv6ll_enabled(link) &&
|
||||||
@ -538,7 +542,7 @@ void link_check_ready(Link *link) {
|
|||||||
/* All static addresses must be ready. */
|
/* All static addresses must be ready. */
|
||||||
bool has_static_address = false;
|
bool has_static_address = false;
|
||||||
SET_FOREACH(a, link->addresses) {
|
SET_FOREACH(a, link->addresses) {
|
||||||
if (a->source != NETWORK_CONFIG_SOURCE_STATIC)
|
if (!IN_SET(a->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_MODEM_MANAGER))
|
||||||
continue;
|
continue;
|
||||||
if (!address_is_ready(a))
|
if (!address_is_ready(a))
|
||||||
return (void) log_link_debug(link, "%s(): static address %s is not ready.", __func__,
|
return (void) log_link_debug(link, "%s(): static address %s is not ready.", __func__,
|
||||||
@ -1293,6 +1297,10 @@ static int link_configure(Link *link) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = link_modem_reconfigure(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (!link_has_carrier(link))
|
if (!link_has_carrier(link))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@ -108,6 +108,7 @@ typedef struct Link {
|
|||||||
unsigned set_link_messages;
|
unsigned set_link_messages;
|
||||||
unsigned set_flags_messages;
|
unsigned set_flags_messages;
|
||||||
unsigned create_stacked_netdev_messages;
|
unsigned create_stacked_netdev_messages;
|
||||||
|
unsigned bearer_messages;
|
||||||
|
|
||||||
Set *addresses;
|
Set *addresses;
|
||||||
Set *neighbors;
|
Set *neighbors;
|
||||||
@ -141,6 +142,7 @@ typedef struct Link {
|
|||||||
bool master_set:1;
|
bool master_set:1;
|
||||||
bool stacked_netdevs_created:1;
|
bool stacked_netdevs_created:1;
|
||||||
bool bridge_vlan_set:1;
|
bool bridge_vlan_set:1;
|
||||||
|
bool bearer_configured:1;
|
||||||
|
|
||||||
sd_dhcp_server *dhcp_server;
|
sd_dhcp_server *dhcp_server;
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "networkd-link.h"
|
#include "networkd-link.h"
|
||||||
#include "networkd-manager.h"
|
#include "networkd-manager.h"
|
||||||
#include "networkd-manager-varlink.h"
|
#include "networkd-manager-varlink.h"
|
||||||
|
#include "networkd-setlink.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "varlink-io.systemd.Network.h"
|
#include "varlink-io.systemd.Network.h"
|
||||||
#include "varlink-io.systemd.service.h"
|
#include "varlink-io.systemd.service.h"
|
||||||
@ -92,26 +93,30 @@ 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)));
|
SD_JSON_BUILD_PAIR_CONDITION(nsid != UINT32_MAX, "NamespaceNSID", SD_JSON_BUILD_UNSIGNED(nsid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct InterfaceInfo {
|
static int dispatch_interface(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, bool polkit, Link **ret) {
|
||||||
int ifindex;
|
struct {
|
||||||
const char *ifname;
|
int ifindex;
|
||||||
} InterfaceInfo;
|
const char *ifname;
|
||||||
|
} info = {};
|
||||||
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, 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;
|
Link *link = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
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,
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
assert(vlink);
|
assert(vlink);
|
||||||
assert(manager);
|
assert(manager);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
r = sd_varlink_dispatch(vlink, parameters, dispatch_table, &info);
|
r = sd_varlink_dispatch(vlink, parameters, polkit ? dispatch_polkit_table : dispatch_table, &info);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -158,7 +163,7 @@ static int vl_method_get_lldp_neighbors(sd_varlink *vlink, sd_json_variant *para
|
|||||||
assert(vlink);
|
assert(vlink);
|
||||||
assert(manager);
|
assert(manager);
|
||||||
|
|
||||||
r = dispatch_interface(vlink, parameters, manager, &link);
|
r = dispatch_interface(vlink, parameters, manager, /* polkit= */ false, &link);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -279,6 +284,46 @@ static int vl_method_set_persistent_storage(sd_varlink *vlink, sd_json_variant *
|
|||||||
return sd_varlink_reply(vlink, NULL);
|
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) {
|
int manager_varlink_init(Manager *m, int fd) {
|
||||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
||||||
_unused_ _cleanup_close_ int fd_close = fd; /* take possession */
|
_unused_ _cleanup_close_ int fd_close = fd; /* take possession */
|
||||||
@ -313,6 +358,8 @@ int manager_varlink_init(Manager *m, int fd) {
|
|||||||
"io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id,
|
"io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id,
|
||||||
"io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors,
|
"io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors,
|
||||||
"io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage,
|
"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.Ping", varlink_method_ping,
|
||||||
"io.systemd.service.SetLogLevel", varlink_method_set_log_level,
|
"io.systemd.service.SetLogLevel", varlink_method_set_log_level,
|
||||||
"io.systemd.service.GetEnvironment", varlink_method_get_environment);
|
"io.systemd.service.GetEnvironment", varlink_method_get_environment);
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
#include "networkd-state-file.h"
|
#include "networkd-state-file.h"
|
||||||
#include "networkd-wifi.h"
|
#include "networkd-wifi.h"
|
||||||
#include "networkd-wiphy.h"
|
#include "networkd-wiphy.h"
|
||||||
|
#include "networkd-wwan-bus.h"
|
||||||
#include "ordered-set.h"
|
#include "ordered-set.h"
|
||||||
#include "qdisc.h"
|
#include "qdisc.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
@ -96,6 +97,8 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r
|
|||||||
if (m->product_uuid_requested)
|
if (m->product_uuid_requested)
|
||||||
(void) manager_request_product_uuid(m);
|
(void) manager_request_product_uuid(m);
|
||||||
|
|
||||||
|
(void) manager_notify_mm_bus_connected(m);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +148,8 @@ static int manager_connect_bus(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
|
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
|
||||||
|
|
||||||
|
(void) manager_match_mm_signals(m);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,6 +738,9 @@ Manager* manager_free(Manager *m) {
|
|||||||
|
|
||||||
set_free(m->rules);
|
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->rtnl);
|
||||||
sd_netlink_unref(m->genl);
|
sd_netlink_unref(m->genl);
|
||||||
sd_netlink_unref(m->nfnl);
|
sd_netlink_unref(m->nfnl);
|
||||||
|
|||||||
@ -99,6 +99,10 @@ typedef struct Manager {
|
|||||||
Hashmap *wiphy_by_index;
|
Hashmap *wiphy_by_index;
|
||||||
Hashmap *wiphy_by_name;
|
Hashmap *wiphy_by_name;
|
||||||
|
|
||||||
|
/* ModemManager support */
|
||||||
|
sd_bus_slot *slot_mm;
|
||||||
|
Hashmap *modems_by_path;
|
||||||
|
|
||||||
/* For link speed meter */
|
/* For link speed meter */
|
||||||
bool use_speed_meter;
|
bool use_speed_meter;
|
||||||
sd_event_source *speed_meter_event_source;
|
sd_event_source *speed_meter_event_source;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ _Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
|
|||||||
#include "networkd-radv.h"
|
#include "networkd-radv.h"
|
||||||
#include "networkd-route.h"
|
#include "networkd-route.h"
|
||||||
#include "networkd-routing-policy-rule.h"
|
#include "networkd-routing-policy-rule.h"
|
||||||
|
#include "networkd-wwan.h"
|
||||||
#include "qdisc.h"
|
#include "qdisc.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "tclass.h"
|
#include "tclass.h"
|
||||||
@ -492,6 +493,9 @@ CAN.ClassicDataLengthCode, config_parse_can_control_mode,
|
|||||||
CAN.Termination, config_parse_can_termination, 0, 0
|
CAN.Termination, config_parse_can_termination, 0, 0
|
||||||
IPoIB.Mode, config_parse_ipoib_mode, 0, offsetof(Network, ipoib_mode)
|
IPoIB.Mode, config_parse_ipoib_mode, 0, offsetof(Network, ipoib_mode)
|
||||||
IPoIB.IgnoreUserspaceMulticastGroups, config_parse_tristate, 0, offsetof(Network, ipoib_umcast)
|
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.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
|
||||||
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
|
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
|
||||||
BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0
|
BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0
|
||||||
|
|||||||
@ -512,6 +512,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
|
|
||||||
.ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
|
.ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
|
||||||
.ipoib_umcast = -1,
|
.ipoib_umcast = -1,
|
||||||
|
|
||||||
|
.mm_use_gateway = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = config_parse_many_full(
|
r = config_parse_many_full(
|
||||||
@ -551,6 +553,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
"LLDP\0"
|
"LLDP\0"
|
||||||
"TrafficControlQueueingDiscipline\0"
|
"TrafficControlQueueingDiscipline\0"
|
||||||
"CAN\0"
|
"CAN\0"
|
||||||
|
"ModemManager\0"
|
||||||
"QDisc\0"
|
"QDisc\0"
|
||||||
"BFIFO\0"
|
"BFIFO\0"
|
||||||
"CAKE\0"
|
"CAKE\0"
|
||||||
@ -847,6 +850,9 @@ static Network *network_free(Network *network) {
|
|||||||
hashmap_free(network->qdiscs_by_section);
|
hashmap_free(network->qdiscs_by_section);
|
||||||
hashmap_free(network->tclasses_by_section);
|
hashmap_free(network->tclasses_by_section);
|
||||||
|
|
||||||
|
/* ModemManager */
|
||||||
|
strv_free(network->mm_simple_connect_props);
|
||||||
|
|
||||||
return mfree(network);
|
return mfree(network);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -414,6 +414,12 @@ typedef struct Network {
|
|||||||
|
|
||||||
/* NTP */
|
/* NTP */
|
||||||
char **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;
|
} Network;
|
||||||
|
|
||||||
DECLARE_TRIVIAL_REF_UNREF_FUNC(Network, network);
|
DECLARE_TRIVIAL_REF_UNREF_FUNC(Network, network);
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "sd-netlink.h"
|
#include "sd-netlink.h"
|
||||||
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
#include "device-private.h"
|
#include "device-private.h"
|
||||||
#include "missing-network.h"
|
#include "missing-network.h"
|
||||||
#include "netif-util.h"
|
#include "netif-util.h"
|
||||||
@ -1341,6 +1343,103 @@ int link_up_or_down_now(Link *link, bool up) {
|
|||||||
return 0;
|
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) {
|
int link_down_slave_links(Link *link) {
|
||||||
Link *slave;
|
Link *slave;
|
||||||
int r;
|
int r;
|
||||||
|
|||||||
@ -22,6 +22,7 @@ int link_request_to_activate(Link *link);
|
|||||||
int link_request_to_bring_up_or_down(Link *link, bool up);
|
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(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) {
|
static inline int link_up_now(Link *link) {
|
||||||
return link_up_or_down_now(link, true);
|
return link_up_or_down_now(link, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "networkd-network.h"
|
#include "networkd-network.h"
|
||||||
#include "networkd-ntp.h"
|
#include "networkd-ntp.h"
|
||||||
#include "networkd-state-file.h"
|
#include "networkd-state-file.h"
|
||||||
|
#include "networkd-wwan.h"
|
||||||
#include "ordered-set.h"
|
#include "ordered-set.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -109,6 +110,14 @@ static int link_put_dns(Link *link, OrderedSet **s) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)) {
|
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
|
||||||
const struct in_addr *addresses;
|
const struct in_addr *addresses;
|
||||||
|
|
||||||
@ -801,6 +810,11 @@ static int link_save(Link *link) {
|
|||||||
space = false;
|
space = false;
|
||||||
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
|
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
|
/* 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
|
* know how to handle such a server so for now Do53 service is required, and
|
||||||
* assumed. */
|
* assumed. */
|
||||||
|
|||||||
@ -17,14 +17,15 @@
|
|||||||
|
|
||||||
/* This is used in log messages, and never used in parsing settings. So, upper cases are OK. */
|
/* This is used in log messages, and never used in parsing settings. So, upper cases are OK. */
|
||||||
static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX] = {
|
static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX] = {
|
||||||
[NETWORK_CONFIG_SOURCE_FOREIGN] = "foreign",
|
[NETWORK_CONFIG_SOURCE_FOREIGN] = "foreign",
|
||||||
[NETWORK_CONFIG_SOURCE_STATIC] = "static",
|
[NETWORK_CONFIG_SOURCE_STATIC] = "static",
|
||||||
[NETWORK_CONFIG_SOURCE_IPV4LL] = "IPv4LL",
|
[NETWORK_CONFIG_SOURCE_IPV4LL] = "IPv4LL",
|
||||||
[NETWORK_CONFIG_SOURCE_DHCP4] = "DHCPv4",
|
[NETWORK_CONFIG_SOURCE_DHCP4] = "DHCPv4",
|
||||||
[NETWORK_CONFIG_SOURCE_DHCP6] = "DHCPv6",
|
[NETWORK_CONFIG_SOURCE_DHCP6] = "DHCPv6",
|
||||||
[NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
|
[NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
|
||||||
[NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
|
[NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
|
||||||
[NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
|
[NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
|
||||||
|
[NETWORK_CONFIG_SOURCE_MODEM_MANAGER] = "ModemManager",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(network_config_source, NetworkConfigSource);
|
DEFINE_STRING_TABLE_LOOKUP(network_config_source, NetworkConfigSource);
|
||||||
|
|||||||
@ -14,6 +14,7 @@ typedef enum NetworkConfigSource {
|
|||||||
NETWORK_CONFIG_SOURCE_DHCP_PD,
|
NETWORK_CONFIG_SOURCE_DHCP_PD,
|
||||||
NETWORK_CONFIG_SOURCE_NDISC,
|
NETWORK_CONFIG_SOURCE_NDISC,
|
||||||
NETWORK_CONFIG_SOURCE_RUNTIME, /* through D-Bus method */
|
NETWORK_CONFIG_SOURCE_RUNTIME, /* through D-Bus method */
|
||||||
|
NETWORK_CONFIG_SOURCE_MODEM_MANAGER,
|
||||||
_NETWORK_CONFIG_SOURCE_MAX,
|
_NETWORK_CONFIG_SOURCE_MAX,
|
||||||
_NETWORK_CONFIG_SOURCE_INVALID = -EINVAL,
|
_NETWORK_CONFIG_SOURCE_INVALID = -EINVAL,
|
||||||
} NetworkConfigSource;
|
} NetworkConfigSource;
|
||||||
|
|||||||
1341
src/network/networkd-wwan-bus.c
Normal file
1341
src/network/networkd-wwan-bus.c
Normal file
File diff suppressed because it is too large
Load Diff
88
src/network/networkd-wwan-bus.h
Normal file
88
src/network/networkd-wwan-bus.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* 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);
|
||||||
641
src/network/networkd-wwan.c
Normal file
641
src/network/networkd-wwan.c
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
/* 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;
|
||||||
|
}
|
||||||
80
src/network/networkd-wwan.h
Normal file
80
src/network/networkd-wwan.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/* 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,4 +194,15 @@
|
|||||||
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
|
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
|
||||||
</action>
|
</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>
|
</policyconfig>
|
||||||
|
|||||||
@ -541,9 +541,8 @@ 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);
|
log_error_errno(r, "Failed to select any cgroups under %s based on pressure, ignoring: %m", t->path);
|
||||||
else {
|
else {
|
||||||
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one.
|
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one.
|
||||||
* If r == 0 then it means there were not eligible candidates, the candidate cgroup
|
* If r == 0 then the cgroup is already queued for kill by an earlier iteration.
|
||||||
* disappeared, or the candidate cgroup has no processes by the time we tried to kill
|
* In either case, go through the event loop again and select a new candidate if
|
||||||
* it. In either case, go through the event loop again and select a new candidate if
|
|
||||||
* pressure is still high. */
|
* pressure is still high. */
|
||||||
m->mem_pressure_post_action_delay_start = usec_now;
|
m->mem_pressure_post_action_delay_start = usec_now;
|
||||||
if (selected && r > 0) {
|
if (selected && r > 0) {
|
||||||
|
|||||||
@ -494,12 +494,20 @@ int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) {
|
|||||||
r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks);
|
r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom_debug();
|
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);
|
r = oomd_prekill_hook(m, ks);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "oomd prekill hook failed for %s, ignoring: %m", ctx->path);
|
log_warning_errno(r, "oomd prekill hook failed for %s, ignoring: %m", ctx->path);
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*dump_candidate_func)(const OomdCGroupContext *ctx, FILE *f, const char *prefix);
|
typedef void (*dump_candidate_func)(const OomdCGroupContext *ctx, FILE *f, const char *prefix);
|
||||||
|
|||||||
@ -5404,6 +5404,7 @@ static int vl_method_read_event_log(sd_varlink *link, sd_json_variant *parameter
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
|
|||||||
@ -10324,14 +10324,12 @@ static int vl_method_list_candidate_devices(
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
|
||||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
|
||||||
|
|
||||||
BlockDevice *l = NULL;
|
BlockDevice *l = NULL;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
CLEANUP_ARRAY(l, n, block_device_array_free);
|
CLEANUP_ARRAY(l, n, block_device_array_free);
|
||||||
|
|||||||
@ -21,3 +21,4 @@ struct ConfigPerfItem;
|
|||||||
Delegate.DNS, config_parse_delegate_dns_servers, 0, 0
|
Delegate.DNS, config_parse_delegate_dns_servers, 0, 0
|
||||||
Delegate.Domains, config_parse_delegate_domains, 0, 0
|
Delegate.Domains, config_parse_delegate_domains, 0, 0
|
||||||
Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route)
|
Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route)
|
||||||
|
Delegate.FirewallMark, config_parse_unsigned, 0, offsetof(DnsDelegate, fwmark)
|
||||||
|
|||||||
@ -23,6 +23,8 @@ typedef struct DnsDelegate {
|
|||||||
|
|
||||||
int default_route;
|
int default_route;
|
||||||
|
|
||||||
|
uint32_t fwmark;
|
||||||
|
|
||||||
DnsScope *scope;
|
DnsScope *scope;
|
||||||
|
|
||||||
LIST_FIELDS(DnsDelegate, delegates);
|
LIST_FIELDS(DnsDelegate, delegates);
|
||||||
|
|||||||
@ -475,6 +475,12 @@ static int dns_scope_socket(
|
|||||||
return r;
|
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 &&
|
bool addr_is_nonlocal = s->link &&
|
||||||
!manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
|
!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;
|
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(
|
return sd_json_buildo(
|
||||||
ret,
|
ret,
|
||||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("addressString", dns_server_string(server)),
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("addressString", dns_server_string(server)),
|
||||||
JSON_BUILD_PAIR_IN_ADDR("address", &server->address, server->family),
|
JSON_BUILD_PAIR_IN_ADDR("address", server->family, &server->address),
|
||||||
SD_JSON_BUILD_PAIR_INTEGER("family", server->family),
|
SD_JSON_BUILD_PAIR_INTEGER("family", server->family),
|
||||||
SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)),
|
SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)),
|
SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)),
|
||||||
|
|||||||
@ -1214,10 +1214,7 @@ static int vl_method_browse_services(sd_varlink* link, sd_json_variant* paramete
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
assert(link);
|
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)));
|
m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link)));
|
||||||
|
|
||||||
@ -1239,9 +1236,7 @@ static int vl_method_subscribe_query_results(sd_varlink *link, sd_json_variant *
|
|||||||
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* if the client didn't set the more flag, it is using us incorrectly */
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
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");
|
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-query-results");
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
@ -1382,9 +1377,7 @@ static int vl_method_subscribe_dns_configuration(sd_varlink *link, sd_json_varia
|
|||||||
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* if the client didn't set the more flag, it is using us incorrectly */
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
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");
|
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-dns-configuration");
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#if HAVE_APPARMOR
|
|
||||||
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
@ -67,4 +65,3 @@ bool mac_apparmor_use(void) {
|
|||||||
|
|
||||||
return (cached_use = true);
|
return (cached_use = true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|||||||
@ -831,10 +831,6 @@ int ask_password_agent(
|
|||||||
|
|
||||||
_cleanup_close_ int socket_fd = -EBADF, signal_fd = -EBADF, inotify_fd = -EBADF, dfd = -EBADF;
|
_cleanup_close_ int socket_fd = -EBADF, signal_fd = -EBADF, inotify_fd = -EBADF, dfd = -EBADF;
|
||||||
_cleanup_(unlink_and_freep) char *socket_name = NULL;
|
_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;
|
int r;
|
||||||
|
|
||||||
assert(req);
|
assert(req);
|
||||||
@ -850,64 +846,59 @@ int ask_password_agent(
|
|||||||
if (req->flag_file)
|
if (req->flag_file)
|
||||||
return -EOPNOTSUPP;
|
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(sigemptyset(&mask) >= 0);
|
||||||
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
|
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
|
||||||
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
|
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
|
||||||
|
|
||||||
_cleanup_free_ char *askpwdir = NULL;
|
saved_ssp = &oldmask;
|
||||||
r = get_ask_password_directory_for_flags(flags, &askpwdir);
|
|
||||||
|
_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);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
if (r == 0) {
|
|
||||||
r = -ENXIO;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
dfd = open_mkdir(askpwdir, O_RDONLY|O_CLOEXEC, 0755);
|
CLEANUP_TMPFILE_AT(dfd, fname);
|
||||||
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);
|
signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
|
||||||
if (signal_fd < 0) {
|
if (signal_fd < 0)
|
||||||
r = -errno;
|
return -errno;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket_fd = create_socket(askpwdir, &socket_name);
|
socket_fd = create_socket(askpwdir, &socket_name);
|
||||||
if (socket_fd < 0) {
|
if (socket_fd < 0)
|
||||||
r = socket_fd;
|
return socket_fd;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"[Ask]\n"
|
"[Ask]\n"
|
||||||
@ -933,21 +924,19 @@ int ask_password_agent(
|
|||||||
if (req->id)
|
if (req->id)
|
||||||
fprintf(f, "Id=%s\n", req->id);
|
fprintf(f, "Id=%s\n", req->id);
|
||||||
|
|
||||||
if (fchmod(fileno(f), 0644) < 0) {
|
if (fchmod(fileno(f), 0644) < 0)
|
||||||
r = -errno;
|
return -errno;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = fflush_and_check(f);
|
r = fflush_and_check(f);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
|
|
||||||
if (renameat(dfd, temp, dfd, final) < 0) {
|
/* Paranoia: never clobber an ongoing request */
|
||||||
r = -errno;
|
r = rename_noreplace(dfd, fname, dfd, final);
|
||||||
goto finish;
|
if (r < 0)
|
||||||
}
|
return r;
|
||||||
|
|
||||||
temp = mfree(temp);
|
free_and_replace(fname, final);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
POLL_SOCKET,
|
POLL_SOCKET,
|
||||||
@ -969,20 +958,17 @@ int ask_password_agent(
|
|||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
};
|
};
|
||||||
if (req->hup_fd >= 0)
|
if (req->hup_fd >= 0)
|
||||||
pollfd[hup_fd_idx = n_pollfd ++] = (struct pollfd) {
|
pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) {
|
||||||
.fd = req->hup_fd,
|
.fd = req->hup_fd,
|
||||||
.events = POLLHUP,
|
.events = POLLHUP,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(n_pollfd <= _POLL_MAX);
|
assert(n_pollfd <= _POLL_MAX);
|
||||||
|
|
||||||
|
_cleanup_strv_free_erase_ char **l = NULL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
|
||||||
char passphrase[LINE_MAX+1];
|
|
||||||
struct iovec iovec;
|
|
||||||
struct ucred *ucred;
|
|
||||||
usec_t timeout;
|
usec_t timeout;
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
if (req->until > 0)
|
if (req->until > 0)
|
||||||
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
|
||||||
@ -993,45 +979,34 @@ int ask_password_agent(
|
|||||||
if (r == -EINTR)
|
if (r == -EINTR)
|
||||||
continue;
|
continue;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0)
|
||||||
r = -ETIME;
|
return -ETIME;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pollfd[POLL_SIGNAL].revents & POLLIN) {
|
if (pollfd[POLL_SIGNAL].revents & POLLIN)
|
||||||
r = -EINTR;
|
return -EINTR;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) {
|
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
|
||||||
r = -ECONNRESET;
|
return -ECONNRESET;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
|
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
|
||||||
(void) flush_fd(inotify_fd);
|
(void) flush_fd(inotify_fd);
|
||||||
|
|
||||||
if (req->keyring) {
|
if (req->keyring) {
|
||||||
r = ask_password_keyring(req, flags, ret);
|
r = ask_password_keyring(req, flags, ret);
|
||||||
if (r >= 0) {
|
if (r != -ENOKEY)
|
||||||
r = 0;
|
return r;
|
||||||
goto finish;
|
|
||||||
} else if (r != -ENOKEY)
|
|
||||||
goto finish;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pollfd[POLL_SOCKET].revents == 0)
|
if (pollfd[POLL_SOCKET].revents == 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (pollfd[POLL_SOCKET].revents != POLLIN)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
if (pollfd[POLL_SOCKET].revents != POLLIN) {
|
char passphrase[LINE_MAX+1];
|
||||||
r = -EIO;
|
struct iovec iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
|
||||||
goto finish;
|
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
|
||||||
}
|
|
||||||
|
|
||||||
iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
|
|
||||||
|
|
||||||
struct msghdr msghdr = {
|
struct msghdr msghdr = {
|
||||||
.msg_iov = &iovec,
|
.msg_iov = &iovec,
|
||||||
.msg_iovlen = 1,
|
.msg_iovlen = 1,
|
||||||
@ -1039,7 +1014,7 @@ int ask_password_agent(
|
|||||||
.msg_controllen = sizeof(control),
|
.msg_controllen = sizeof(control),
|
||||||
};
|
};
|
||||||
|
|
||||||
n = recvmsg_safe(socket_fd, &msghdr, 0);
|
ssize_t n = recvmsg_safe(socket_fd, &msghdr, 0);
|
||||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||||
continue;
|
continue;
|
||||||
if (n == -ECHRNG) {
|
if (n == -ECHRNG) {
|
||||||
@ -1050,30 +1025,30 @@ int ask_password_agent(
|
|||||||
log_debug_errno(n, "Got message with truncated payload data, ignoring.");
|
log_debug_errno(n, "Got message with truncated payload data, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (n < 0) {
|
if (n < 0)
|
||||||
r = (int) n;
|
return n;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLEANUP_ERASE(passphrase);
|
CLEANUP_ERASE(passphrase);
|
||||||
|
|
||||||
cmsg_close_all(&msghdr);
|
cmsg_close_all(&msghdr);
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
log_debug("Message too short");
|
log_debug("Got empty reply from ask-password agent, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
struct ucred *ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
if (!ucred) {
|
if (!ucred) {
|
||||||
log_debug("Received message without credentials. Ignoring.");
|
log_debug("Received message without credentials, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ucred->uid != getuid() && ucred->uid != 0) {
|
||||||
|
log_debug("Got password response from bad user, ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ucred->uid != getuid() && ucred->uid != 0) {
|
if (passphrase[0] == '-')
|
||||||
log_debug("Got response from bad user. Ignoring.");
|
return -ECANCELED;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passphrase[0] == '+') {
|
if (passphrase[0] == '+') {
|
||||||
/* An empty message refers to the empty password */
|
/* An empty message refers to the empty password */
|
||||||
@ -1081,45 +1056,23 @@ int ask_password_agent(
|
|||||||
l = strv_new("");
|
l = strv_new("");
|
||||||
else
|
else
|
||||||
l = strv_parse_nulstr(passphrase+1, n-1);
|
l = strv_parse_nulstr(passphrase+1, n-1);
|
||||||
if (!l) {
|
if (!l)
|
||||||
r = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strv_isempty(l)) {
|
if (!strv_isempty(l))
|
||||||
l = strv_free(l);
|
break;
|
||||||
log_debug("Invalid packet");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
l = strv_free(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passphrase[0] == '-') {
|
log_debug("Got invalid response from ask-password agent, ignoring.");
|
||||||
r = -ECANCELED;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("Invalid packet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->keyring)
|
if (req->keyring)
|
||||||
(void) add_to_keyring_and_log(req->keyring, flags, l);
|
(void) add_to_keyring_and_log(req->keyring, flags, l);
|
||||||
|
|
||||||
*ret = TAKE_PTR(l);
|
*ret = TAKE_PTR(l);
|
||||||
r = 0;
|
return 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) {
|
static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) {
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
shared_sources = files(
|
shared_sources = files(
|
||||||
'acl-util.c',
|
'acl-util.c',
|
||||||
'acpi-fpdt.c',
|
'acpi-fpdt.c',
|
||||||
'apparmor-util.c',
|
|
||||||
'ask-password-agent.c',
|
'ask-password-agent.c',
|
||||||
'ask-password-api.c',
|
'ask-password-api.c',
|
||||||
'async.c',
|
'async.c',
|
||||||
@ -279,6 +278,10 @@ if conf.get('HAVE_LIBIDN2') == 1
|
|||||||
shared_sources += files('idn-util.c')
|
shared_sources += files('idn-util.c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if conf.get('HAVE_APPARMOR') == 1
|
||||||
|
shared_sources += files('apparmor-util.c')
|
||||||
|
endif
|
||||||
|
|
||||||
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
|
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
|
||||||
ip_protocol_list_txt = custom_target(
|
ip_protocol_list_txt = custom_target(
|
||||||
input : [generate_ip_protocol_list, ipproto_sources],
|
input : [generate_ip_protocol_list, ipproto_sources],
|
||||||
|
|||||||
@ -11,6 +11,7 @@ int metrics_setup_varlink_server(
|
|||||||
sd_varlink_server **server, /* in and out param */
|
sd_varlink_server **server, /* in and out param */
|
||||||
sd_varlink_server_flags_t flags,
|
sd_varlink_server_flags_t flags,
|
||||||
sd_event *event,
|
sd_event *event,
|
||||||
|
int64_t priority,
|
||||||
sd_varlink_method_t vl_method_list_cb,
|
sd_varlink_method_t vl_method_list_cb,
|
||||||
sd_varlink_method_t vl_method_describe_cb,
|
sd_varlink_method_t vl_method_describe_cb,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
@ -20,6 +21,8 @@ int metrics_setup_varlink_server(
|
|||||||
|
|
||||||
assert(server);
|
assert(server);
|
||||||
assert(event);
|
assert(event);
|
||||||
|
assert(vl_method_list_cb);
|
||||||
|
assert(vl_method_describe_cb);
|
||||||
|
|
||||||
if (*server)
|
if (*server)
|
||||||
return 0;
|
return 0;
|
||||||
@ -34,24 +37,21 @@ int metrics_setup_varlink_server(
|
|||||||
|
|
||||||
r = sd_varlink_server_bind_method_many(
|
r = sd_varlink_server_bind_method_many(
|
||||||
s,
|
s,
|
||||||
"io.systemd.Metrics.List",
|
"io.systemd.Metrics.List", vl_method_list_cb,
|
||||||
vl_method_list_cb,
|
"io.systemd.Metrics.Describe", vl_method_describe_cb);
|
||||||
"io.systemd.Metrics.Describe",
|
|
||||||
vl_method_describe_cb);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to register varlink metrics methods: %m");
|
return log_debug_errno(r, "Failed to register varlink metrics methods: %m");
|
||||||
|
|
||||||
r = sd_varlink_server_set_description(s, "systemd varlink metrics server");
|
r = sd_varlink_server_set_description(s, "varlink-metrics");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to set varlink metrics server description: %m");
|
return log_debug_errno(r, "Failed to set varlink metrics server description: %m");
|
||||||
|
|
||||||
r = sd_varlink_server_attach_event(s, event, SD_EVENT_PRIORITY_NORMAL);
|
r = sd_varlink_server_attach_event(s, event, priority);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to attach varlink metrics server to event loop: %m");
|
return log_debug_errno(r, "Failed to attach varlink metrics server to event loop: %m");
|
||||||
|
|
||||||
*server = TAKE_PTR(s);
|
*server = TAKE_PTR(s);
|
||||||
|
return 1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const metric_family_type_table[_METRIC_FAMILY_TYPE_MAX] = {
|
static const char * const metric_family_type_table[_METRIC_FAMILY_TYPE_MAX] = {
|
||||||
@ -84,14 +84,12 @@ int metrics_method_describe(
|
|||||||
assert(metric_family_table);
|
assert(metric_family_table);
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
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");
|
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -123,14 +121,12 @@ int metrics_method_list(
|
|||||||
assert(metric_family_table);
|
assert(metric_family_table);
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
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");
|
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -31,6 +31,7 @@ int metrics_setup_varlink_server(
|
|||||||
sd_varlink_server **server, /* in and out param */
|
sd_varlink_server **server, /* in and out param */
|
||||||
sd_varlink_server_flags_t flags,
|
sd_varlink_server_flags_t flags,
|
||||||
sd_event *event,
|
sd_event *event,
|
||||||
|
int64_t priority,
|
||||||
sd_varlink_method_t vl_method_list_cb,
|
sd_varlink_method_t vl_method_list_cb,
|
||||||
sd_varlink_method_t vl_method_describe_cb,
|
sd_varlink_method_t vl_method_describe_cb,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
|
|||||||
@ -240,6 +240,8 @@ static int archive_unpack_regular(
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(fd, "Failed to create regular file '%s': %m", path);
|
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) {
|
if ((fflags & CHATTR_EARLY_FL) != 0) {
|
||||||
r = chattr_full(fd,
|
r = chattr_full(fd,
|
||||||
/* path= */ NULL,
|
/* path= */ NULL,
|
||||||
@ -250,45 +252,29 @@ static int archive_unpack_regular(
|
|||||||
CHATTR_FALLBACK_BITWISE);
|
CHATTR_FALLBACK_BITWISE);
|
||||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||||
log_warning_errno(r, "Failed to apply chattr of '%s', ignoring: %m", path);
|
log_warning_errno(r, "Failed to apply chattr of '%s', ignoring: %m", path);
|
||||||
else if (r < 0) {
|
else if (r < 0)
|
||||||
log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
|
return log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sym_archive_read_data_into_fd(a, fd);
|
r = sym_archive_read_data_into_fd(a, fd);
|
||||||
if (r != ARCHIVE_OK) {
|
if (r != ARCHIVE_OK)
|
||||||
r = log_error_errno(
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||||
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
"Failed to unpack regular file '%s': %s", path, sym_archive_error_string(a));
|
||||||
"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
|
/* 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. */
|
* hole. We need to manually truncate. */
|
||||||
off_t l = lseek(fd, 0, SEEK_CUR);
|
off_t l = lseek(fd, 0, SEEK_CUR);
|
||||||
if (l < 0) {
|
if (l < 0)
|
||||||
r = log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
|
return log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
|
||||||
goto fail;
|
if (ftruncate(fd, l) < 0)
|
||||||
}
|
return log_error_errno(errno, "Failed to truncate regular file '%s' to %" PRIu64 ": %m", path, (uint64_t) l);
|
||||||
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);
|
r = link_tmpfile_at(fd, parent_fd, tmp, filename, LINK_TMPFILE_REPLACE);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to install regular file '%s': %m", path);
|
return 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);
|
return TAKE_FD(fd);
|
||||||
|
|
||||||
fail:
|
|
||||||
if (tmp)
|
|
||||||
(void) unlinkat(parent_fd, tmp, /* flags= */ 0);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int archive_unpack_directory(
|
static int archive_unpack_directory(
|
||||||
|
|||||||
@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
#include "varlink-io.systemd.MuteConsole.h"
|
#include "varlink-io.systemd.MuteConsole.h"
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_METHOD(
|
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||||
Mute,
|
Mute,
|
||||||
|
SD_VARLINK_REQUIRES_MORE,
|
||||||
SD_VARLINK_FIELD_COMMENT("Whether to mute the kernel's output to the console (defaults to true)."),
|
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_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)."),
|
SD_VARLINK_FIELD_COMMENT("Whether to mute PID1's output to the console (defaults to true)."),
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "bus-polkit.h"
|
||||||
#include "varlink-io.systemd.Network.h"
|
#include "varlink-io.systemd.Network.h"
|
||||||
|
|
||||||
/* Helper macro to define address fields with both binary and string representation */
|
/* Helper macro to define address fields with both binary and string representation */
|
||||||
#define SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
|
#define VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
|
||||||
SD_VARLINK_FIELD_COMMENT(comment), \
|
SD_VARLINK_FIELD_COMMENT(comment), \
|
||||||
SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \
|
SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \
|
||||||
SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \
|
SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \
|
||||||
SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags))
|
SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags))
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||||
LinkState,
|
LinkState,
|
||||||
@ -42,10 +43,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
RoutingPolicyRule,
|
RoutingPolicyRule,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Length of source prefix in bits"),
|
||||||
SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Length of destination prefix in bits"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
|
SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
|
||||||
@ -97,14 +98,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
Route,
|
Route,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
|
SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
|
||||||
SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
|
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),
|
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_FIELD_COMMENT("Source prefix length"),
|
||||||
SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Type of Service (TOS) field"),
|
||||||
SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"),
|
SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"),
|
||||||
@ -139,7 +140,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this route"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this route"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Configuration state of this route"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Interface index for serialization"),
|
SD_VARLINK_FIELD_COMMENT("Interface index for serialization"),
|
||||||
@ -162,7 +163,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
|
SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
|
||||||
@ -177,7 +178,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Configuration source for this next hop"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Configuration state of this next hop"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
|
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
@ -208,7 +209,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
DNS,
|
DNS,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("DNS server port number"),
|
SD_VARLINK_FIELD_COMMENT("DNS server port number"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"),
|
SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"),
|
||||||
@ -217,29 +218,29 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
NTP,
|
NTP,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
|
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),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("NTP server"),
|
SD_VARLINK_FIELD_COMMENT("NTP server"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
SIP,
|
SIP,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
|
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),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("SIP server domain name"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
Domain,
|
Domain,
|
||||||
@ -247,7 +248,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
DNSSECNegativeTrustAnchor,
|
DNSSECNegativeTrustAnchor,
|
||||||
@ -279,7 +280,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"),
|
SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"),
|
||||||
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
|
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
NDisc,
|
NDisc,
|
||||||
@ -290,14 +291,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
Address,
|
Address,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
|
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),
|
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_FIELD_COMMENT("Network prefix length"),
|
||||||
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this address"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this address"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
|
||||||
SD_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(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),
|
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_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
|
SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
|
||||||
@ -323,7 +324,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
Neighbor,
|
Neighbor,
|
||||||
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
|
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_FIELD_COMMENT("Link layer (MAC) address of the neighbor"),
|
||||||
SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY),
|
SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY),
|
||||||
SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"),
|
SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"),
|
||||||
@ -386,7 +387,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
DHCPServerLease,
|
DHCPServerLease,
|
||||||
SD_VARLINK_FIELD_COMMENT("DHCP client identifier"),
|
SD_VARLINK_FIELD_COMMENT("DHCP client identifier"),
|
||||||
SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Hostname provided by the DHCP client"),
|
||||||
SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"),
|
SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"),
|
||||||
@ -447,7 +448,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Broadcast address for Ethernet interfaces"),
|
||||||
SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE),
|
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_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"),
|
||||||
SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),
|
SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),
|
||||||
@ -593,6 +594,22 @@ static SD_VARLINK_DEFINE_METHOD(
|
|||||||
SD_VARLINK_FIELD_COMMENT("Whether persistent storage is ready and writable"),
|
SD_VARLINK_FIELD_COMMENT("Whether persistent storage is ready and writable"),
|
||||||
SD_VARLINK_DEFINE_INPUT(Ready, SD_VARLINK_BOOL, 0));
|
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);
|
static SD_VARLINK_DEFINE_ERROR(StorageReadOnly);
|
||||||
|
|
||||||
SD_VARLINK_DEFINE_INTERFACE(
|
SD_VARLINK_DEFINE_INTERFACE(
|
||||||
@ -603,6 +620,10 @@ SD_VARLINK_DEFINE_INTERFACE(
|
|||||||
&vl_method_GetNamespaceId,
|
&vl_method_GetNamespaceId,
|
||||||
&vl_method_GetLLDPNeighbors,
|
&vl_method_GetLLDPNeighbors,
|
||||||
&vl_method_SetPersistentStorage,
|
&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_Address,
|
||||||
&vl_type_DHCPLease,
|
&vl_type_DHCPLease,
|
||||||
&vl_type_DHCPServer,
|
&vl_type_DHCPServer,
|
||||||
|
|||||||
@ -59,8 +59,9 @@ 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_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));
|
SD_VARLINK_DEFINE_OUTPUT(progress, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_METHOD(
|
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||||
ListCandidateDevices,
|
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_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_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."),
|
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(
|
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||||
BrowseServices,
|
BrowseServices,
|
||||||
SD_VARLINK_SUPPORTS_MORE,
|
SD_VARLINK_REQUIRES_MORE,
|
||||||
SD_VARLINK_FIELD_COMMENT("The domain to browse for services. If null, the default browsing domain local is used."),
|
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_DEFINE_INPUT(domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."),
|
SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."),
|
||||||
|
|||||||
@ -179,6 +179,8 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_DEFINE_FIELD_BY_TYPE(SocketBindDeny, CGroupSocketBind, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
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_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_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_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),
|
SD_VARLINK_DEFINE_FIELD_BY_TYPE(NFTSet, CGroupNFTSet, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||||
|
|
||||||
|
|||||||
@ -1,78 +1,73 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include "sd-event.h"
|
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "extract-word.h"
|
||||||
|
#include "fd-util.h"
|
||||||
#include "fdset.h"
|
#include "fdset.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "parse-util.h"
|
#include "serialize.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "varlink-internal.h"
|
#include "varlink-internal.h"
|
||||||
#include "varlink-serialize.h"
|
#include "varlink-serialize.h"
|
||||||
|
|
||||||
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds) {
|
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) {
|
||||||
assert(f);
|
assert(f);
|
||||||
assert(fds);
|
assert(fds);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LIST_FOREACH(sockets, ss, s->sockets) {
|
const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server";
|
||||||
int copy;
|
|
||||||
|
|
||||||
|
LIST_FOREACH(sockets, ss, s->sockets) {
|
||||||
assert(ss->address);
|
assert(ss->address);
|
||||||
assert(ss->fd >= 0);
|
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 */
|
/* If we fail to serialize the fd, it will be considered an error during deserialization */
|
||||||
copy = fdset_put_dup(fds, ss->fd);
|
int copy = fdset_put_dup(fds, ss->fd);
|
||||||
if (copy < 0)
|
if (copy < 0)
|
||||||
return copy;
|
return copy;
|
||||||
|
|
||||||
fprintf(f, " varlink-server-socket-fd=%i", copy);
|
fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy);
|
||||||
|
|
||||||
fputc('\n', f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) {
|
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_free_ char *address = NULL;
|
||||||
const char *v = ASSERT_PTR(value);
|
_cleanup_close_ int fd = -EBADF;
|
||||||
int r, fd = -EBADF;
|
const char *v;
|
||||||
char *buf;
|
int r;
|
||||||
size_t n;
|
|
||||||
|
/* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
|
assert(value);
|
||||||
assert(fds);
|
assert(fds);
|
||||||
|
|
||||||
n = strcspn(v, " ");
|
v = startswith(value, "socket-address=");
|
||||||
address = strndup(v, n);
|
|
||||||
if (!address)
|
|
||||||
return log_oom_debug();
|
|
||||||
|
|
||||||
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)
|
if (!v)
|
||||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"Failed to deserialize VarlinkServerSocket fd: %s", value);
|
"Invalid varlink server serialization entry: %s", value);
|
||||||
|
|
||||||
n = strcspn(v, " ");
|
r = extract_first_word(&v, &address, " ", /* flags = */ 0);
|
||||||
buf = strndupa_safe(v, n);
|
if (r <= 0)
|
||||||
|
return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA),
|
||||||
fd = parse_fd(buf);
|
"Failed to extract socket address from varlink serialization: %s", value);
|
||||||
if (fd < 0)
|
if (v)
|
||||||
return varlink_server_log_errno(s, fd, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf);
|
v = startswith(v, "varlink-server-socket-fd=");
|
||||||
if (!fdset_contains(fds, fd))
|
if (!v)
|
||||||
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
|
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
|
||||||
"VarlinkServerSocket varlink-server-socket-fd= has unknown fd: %d", fd);
|
"Got varlink serialization without socket fd, refusing.");
|
||||||
|
|
||||||
|
fd = deserialize_fd(fds, v);
|
||||||
|
if (fd < 0)
|
||||||
|
return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m");
|
||||||
|
|
||||||
|
/* NB: varlink_server_socket_free() does not close the fd! */
|
||||||
|
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
|
||||||
ss = new(VarlinkServerSocket, 1);
|
ss = new(VarlinkServerSocket, 1);
|
||||||
if (!ss)
|
if (!ss)
|
||||||
return log_oom_debug();
|
return log_oom_debug();
|
||||||
@ -80,14 +75,16 @@ int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSe
|
|||||||
*ss = (VarlinkServerSocket) {
|
*ss = (VarlinkServerSocket) {
|
||||||
.server = s,
|
.server = s,
|
||||||
.address = TAKE_PTR(address),
|
.address = TAKE_PTR(address),
|
||||||
.fd = fdset_remove(fds, fd),
|
.fd = fd,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = varlink_server_add_socket_event_source(s, ss, SD_EVENT_PRIORITY_NORMAL);
|
r = varlink_server_add_socket_event_source(s, ss);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m");
|
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));
|
LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
|
||||||
|
TAKE_FD(fd); /* ownership is now transferred to varlink server */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "shared-forward.h"
|
#include "shared-forward.h"
|
||||||
|
|
||||||
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds);
|
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds);
|
||||||
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, 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);
|
bool varlink_server_contains_socket(sd_varlink_server *s, const char *address);
|
||||||
|
|||||||
@ -2749,6 +2749,7 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||||
|
|
||||||
const char *class = NULL;
|
const char *class = NULL;
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &class);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &class);
|
||||||
|
|||||||
@ -149,6 +149,7 @@ simple_tests += files(
|
|||||||
'test-mkdir.c',
|
'test-mkdir.c',
|
||||||
'test-modhex.c',
|
'test-modhex.c',
|
||||||
'test-mountpoint-util.c',
|
'test-mountpoint-util.c',
|
||||||
|
'test-namespace-util.c',
|
||||||
'test-net-naming-scheme.c',
|
'test-net-naming-scheme.c',
|
||||||
'test-notify-recv.c',
|
'test-notify-recv.c',
|
||||||
'test-nsresource.c',
|
'test-nsresource.c',
|
||||||
|
|||||||
48
src/test/test-namespace-util.c
Normal file
48
src/test/test-namespace-util.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* 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(manager_new(&m) == 0);
|
||||||
|
|
||||||
assert_se(!m->have_fallbacks);
|
assert_se(!m->fallback_set);
|
||||||
assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0);
|
assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0);
|
||||||
assert_se(m->have_fallbacks);
|
assert_se(m->fallback_set);
|
||||||
assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0);
|
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);
|
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;
|
first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers;
|
||||||
|
|
||||||
if (type == SERVER_FALLBACK)
|
if (type == SERVER_FALLBACK)
|
||||||
m->have_fallbacks = true;
|
m->fallback_set = true;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_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) {
|
int manager_parse_fallback_string(Manager *m, const char *string) {
|
||||||
if (m->have_fallbacks)
|
if (m->fallback_set)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return manager_parse_server_string(m, SERVER_FALLBACK, string);
|
return manager_parse_server_string(m, SERVER_FALLBACK, string);
|
||||||
@ -84,15 +84,21 @@ int config_parse_servers(
|
|||||||
assert(lvalue);
|
assert(lvalue);
|
||||||
assert(rvalue);
|
assert(rvalue);
|
||||||
|
|
||||||
if (isempty(rvalue))
|
if (isempty(rvalue)) {
|
||||||
manager_flush_server_names(m, ltype);
|
manager_flush_server_names(m, ltype);
|
||||||
else {
|
|
||||||
r = manager_parse_server_string(m, ltype, rvalue);
|
/* FallbackNTP= with an empty string disables the built-in fallback servers. */
|
||||||
if (r < 0) {
|
if (ltype == SERVER_FALLBACK)
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
m->fallback_set = true;
|
||||||
"Failed to parse NTP server string '%s', ignoring: %m", rvalue);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
|
|||||||
@ -33,7 +33,7 @@ typedef struct Manager {
|
|||||||
|
|
||||||
RateLimit ratelimit;
|
RateLimit ratelimit;
|
||||||
bool exhausted_servers;
|
bool exhausted_servers;
|
||||||
bool have_fallbacks;
|
bool fallback_set; /* Indicate if FallbackNTP= is explicitly configured. */
|
||||||
|
|
||||||
/* network */
|
/* network */
|
||||||
sd_event_source *network_event_source;
|
sd_event_source *network_event_source;
|
||||||
|
|||||||
@ -1452,6 +1452,7 @@ testcase_delegate() {
|
|||||||
[Delegate]
|
[Delegate]
|
||||||
DNS=192.168.77.78
|
DNS=192.168.77.78
|
||||||
Domains=exercise.test
|
Domains=exercise.test
|
||||||
|
FirewallMark=42
|
||||||
EOF
|
EOF
|
||||||
systemctl reload systemd-resolved
|
systemctl reload systemd-resolved
|
||||||
resolvectl status
|
resolvectl status
|
||||||
|
|||||||
@ -573,3 +573,4 @@ 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="reboot"]
|
||||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]
|
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"]
|
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