1
0
mirror of https://github.com/systemd/systemd synced 2026-03-10 07:04:46 +01:00

Compare commits

..

No commits in common. "ed6a2eaa31872c69e56035927a358bbcbad114a0" and "6d0e8271b4ab332d356d7f59394035da2d8845a8" have entirely different histories.

93 changed files with 918 additions and 3270 deletions

View File

@ -50,6 +50,10 @@ jobs:
[Build]
ToolsTreeDistribution=fedora
ToolsTreeRelease=rawhide
ToolsTreePackages=
libgcrypt-devel
libgpg-error-devel
musl-gcc
EOF
mkosi -f box -- true

8
NEWS
View File

@ -44,14 +44,6 @@ CHANGES WITH 260 in spe:
SYSTEMD_COLORS=256, and SYSTEMD_COLORS=24bit respectively when output
is to a non-dumb TTY, and like SYSTEMD_COLORS=no otherwise.
* Minimum backlight brightness clamp for restoring it at boot has been
lowered from 5% to 1%. This is a safe change allowing more chance to
user environments to set lower values that won't be set higher at boot
while still giving the chance to recover from blackouts because
excessive lower bright values by just rebooting. Notice that if your
environment allow you to set excessive low brightness values this has
nothing to do with systemd's brightness clamp.
CHANGES WITH 259:
Announcements of Future Feature Removals and Incompatible Changes:

3
TODO
View File

@ -121,9 +121,6 @@ Deprecations and removals:
Features:
* networkd: maintain a file in /run/ that can be symlinked into /run/issue.d/
that always shows the current primary IP address
* report:
- should the list of metrics use JSON-SEQ? or maybe be wrapped in a json
array (the latter might be necessary, once we sign the combination)

View File

@ -705,7 +705,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
- Think about the log level you choose: for functions that are of the "logging"
kind (see above), please ensure that failures we propagate should be logged
about at `LOG_ERR` level. Failures that are noteworthy, but we proceed anyway,
should be logged at `LOG_WARN` level. Important informational messages should
should be loged at `LOG_WARN` level. Important informational messages should
use `LOG_NOTICE` and regular informational messages should use
`LOG_INFO`. Note that the latter is the default maximum log level, i.e. only
`LOG_DEBUG` messages are hidden by default.

View File

@ -30,12 +30,15 @@
#
# If the property is missing, user-space can assume:
# ID_INPUT_JOYSTICK_INTEGRATION=external
#
# By default i8042, i2c, and rmi devices are assumed to be internal,
# bluetooth devices are assumed to be external, usb devices are assumed
# to be internal when connected to a PCB port and external otherwise.
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
# this will make this usb joystick to behave as internal.
#joystick:usb:vffffp0000*
# ID_INPUT_JOYSTICK_INTEGRATION=internal
joystick:bluetooth:*
ID_INPUT_JOYSTICK_INTEGRATION=external
###########################################################
# GPD
###########################################################
# GPD Win, Classic and XBox 360 compat modes
joystick:usb:v11c5p5507*
joystick:usb:v045ep028e*
ID_INPUT_JOYSTICK_INTEGRATION=internal

View File

@ -28,18 +28,44 @@
# Permitted keys:
# Specify whether a touchpad is a built-in one or external:
# ID_INPUT_TOUCHPAD_INTEGRATION=internal|external
#
# By default i8042, i2c, and rmi devices are assumed to be internal,
# bluetooth devices are assumed to be external, usb devices are assumed
# to be internal when connected to a PCB port and external otherwise.
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
# this will make this bluetooth touchpad to behave as internal.
#touchpad:bluetooth:vffffp0000:*
# ID_INPUT_TOUCHPAD_INTEGRATION=internal
touchpad:i8042:*
touchpad:rmi:*
touchpad:usb:*
ID_INPUT_TOUCHPAD_INTEGRATION=internal
touchpad:bluetooth:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Apple
###########################################################
# Magic Trackpad (1 and 2)
touchpad:usb:v05acp030e:*
touchpad:usb:v05acp0265:*
touchpad:usb:v05acp0324:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# HP Elite x2 1013 G3
###########################################################
touchpad:usb:v044ep1221:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Lenovo IdeaPad Duet3 10IGL5 (82AT)
###########################################################
touchpad:bluetooth:v17efp60fa:*
ID_INPUT_TOUCHPAD_INTEGRATION=internal
###########################################################
# Logitech
###########################################################
touchpad:usb:v046d*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Wacom
###########################################################
touchpad:usb:v056a*
ID_INPUT_TOUCHPAD_INTEGRATION=external

View File

@ -350,7 +350,7 @@ def print_summary(fname, groups):
print(f'{fname}: {len(groups)} match groups, {n_matches} matches, {n_props} properties')
if n_matches == 0 or n_props == 0:
print(f'{fname}: no matches or props')
error(f'{fname}: no matches or props')
if __name__ == '__main__':
args = sys.argv[1:] or sorted([

View File

@ -529,7 +529,7 @@
<listitem><para>Takes a boolean, defaults to false. Controls whether to append disk model information
to the firmware boot option item description (as configured with
<option>--efi-boot-option-description=</option> above). This is useful when installing multiple
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernible
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernable
and give a hint which disk is booted into. Note that this uses hardware model information, and hence
might not be too useful in case multiple disks of an identical model are used.</para>

View File

@ -69,18 +69,6 @@
<xi:include href="version-info.xml" xpointer="v258"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FirewallMark=</varname></term>
<listitem>
<para>Takes a 32 bit unsigned integer value. Controls the firewall mark of packets generated by the
socket used to make DNS requests for this DNS delegate. This can be used in the firewall logic to
filter packets from this socket.
This sets the <constant>SO_MARK</constant> socket option. See <citerefentry
project='die-net'><refentrytitle>iptables</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details.</para>
<xi:include href="version-info.xml" xpointer="v260"/>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -91,11 +79,10 @@
<programlisting># /etc/systemd/dns-delegate.d/foobar.dns-delegate
[Delegate]
DNS=203.0.113.47
Domains=foobar.com
FirewallMark=42</programlisting>
Domains=foobar.com</programlisting>
<para>This ensures lookups of <literal>foobar.com</literal> and any domains below it are directed to
DNS server 203.0.113.47 and any packets related to this lookup have a firewall mark set to 42.</para>
DNS server 203.0.113.47.</para>
</example>
</refsect1>

View File

@ -6444,117 +6444,6 @@ ServerAddress=192.168.0.1/24</programlisting>
</variablelist>
</refsect1>
<refsect1>
<title>[ModemManager] Section Options</title>
<para>This section configures the default setting of the ModemManager integration. See
<ulink url="https://modemmanager.org/docs/modemmanager/" /> for more information about ModemManager.</para>
<para>Regardless of the [ModemManager] section settings consider using the following for LTE modems (take into account
that LTE modems do not typically support LLDP because LLDP is a Layer 2 protocol for Ethernet networks and an LTE
modem connects to a cellular network, not a local Ethernet LAN):
<programlisting>[Network]
LLDP=no
LinkLocalAddressing=no
IPv6AcceptRA=no
</programlisting>
</para>
<para>The following options are available in the [ModemManager] section:</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>SimpleConnectProperties=</varname></term>
<listitem>
<para>Specifies the white-space separated list of simple connect properties used to connect a modem. See
<ulink url="https://www.freedesktop.org/software/ModemManager/man/latest/mmcli.1.html" /> for more
information about simple connect. If no properties provided then the connection is not initiated.</para>
<varlistentry>
<term><option>apn</option>=<replaceable>NAME</replaceable></term>
<listitem><para>An Access Point Name (APN) is the name of a gateway between a mobile network
(GSM, GPRS, 3G, 4G and 5G) and another computer network. Required in 3GPP.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>allowed-auth</option>=<replaceable>METHOD</replaceable></term>
<listitem><para>Authentication method to use. Takes one of "none", "pap", "chap", "mschap", "mschapv2" or "eap".
Optional in 3GPP.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>user</option>=<replaceable>NAME</replaceable></term>
<listitem><para>User name (if any) required by the network. Optional in 3GPP.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>password</option>=<replaceable>PASSWORD</replaceable></term>
<listitem><para>Password (if any) required by the network. Optional in 3GPP.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>ip-type</option>=<replaceable>TYPE</replaceable></term>
<listitem><para>Addressing type. Takes one of "none", "ipv4", "ipv6", "ipv4v6" or "any".
Optional in 3GPP and CDMA.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>allow-roaming</option>=<replaceable>BOOL</replaceable></term>
<listitem><para>A boolean. When true, connection is allowed during roaming. When false,
connection is not allowed during roaming. Optional in 3GPP.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>pin</option>=<replaceable>PIN</replaceable></term>
<listitem><para>SIM-PIN unlock code.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>operator-id</option>=<replaceable>ID</replaceable></term>
<listitem><para>ETSI MCC-MNC of a network to force registration.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<para>Set the routing metric for routes specified by the mobile network (including the prefix route
added for the specified prefix). Takes an unsigned integer in the range 0…4294967295.
When unset or set to 0, the kernel's default value will be used.</para>
<xi:include href="version-info.xml" xpointer="v260"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseGateway=</varname></term>
<listitem>
<para>When true (the default), the router address will be configured as the default gateway.</para>
<xi:include href="version-info.xml" xpointer="v260"/>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<example>
@ -6882,29 +6771,6 @@ Xfrm=xfrm0</programlisting>
This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
</para>
</example>
<example>
<title>Connecting to a cellular network with ModemManager</title>
<programlisting># /etc/systemd/network/27-wwan0.network
[Match]
Name=wwan0
[Network]
LLDP=no
LinkLocalAddressing=no
IPv6AcceptRA=no
[ModemManager]
SimpleConnectProperties=apn=internet pin=1111
RouteMetric=30
UseGateway=yes</programlisting>
<para>This connects a cellular modem to a broadband network matched with the network interface <literal>wwan0</literal>,
with APN name <literal>internet</literal>, SIM card pin unlock code <literal>1111</literal> and sets up a default
gateway with route metric of 30.
</para>
</example>
</refsect1>

View File

@ -11,7 +11,6 @@ Packages=
github-cli
lcov
libucontext
musl
mypy
pkgconf
ruff

View File

@ -5,12 +5,7 @@ Distribution=fedora
[Content]
Packages=
gh
lcov
libgcrypt-devel
libgpg-error-devel
musl-libc
musl-clang
musl-gcc
gh
ruff
shellcheck

View File

@ -5,19 +5,11 @@ SUBSYSTEM!="input", GOTO="persistent_input_end"
SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
# Bluetooth devices don't always have the bluetooth subsystem
ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
SUBSYSTEMS=="acpi", ENV{ID_BUS}="acpi"
# platform must be before serio as serio can be child
SUBSYSTEMS=="platform", ENV{ID_BUS}="platform"
SUBSYSTEMS=="i2c", ENV{ID_BUS}="i2c"
SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi"
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"
# subsystems before (usb, platform, i2c) can be under pci so only set them if we still have no ID_BUS.
# we could set this the first but will break the ENV{ID_BUS}=="" condition for usb.
SUBSYSTEMS=="pci", ENV{ID_BUS}=="", ENV{ID_BUS}="pci"
# determine class name for persistent symlinks
ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"

View File

@ -1,25 +0,0 @@
# do not edit this file, it will be overwritten on update
# ID_INTEGRATION variable tells us if a device is internal (inherent part of the system) or external otherwise.
# This must be loaded after 60-persistent-*.rules to have ID_BUS.
ACTION=="remove", GOTO="integration_end"
ENV{ID_BUS}=="", GOTO="integration_end"
# ACPI, platform, PS/2, I2C, RMI and PCI devices: Internal by default.
ENV{ID_BUS}=="acpi|platform|i8042|i2c|rmi|pci", ENV{ID_INTEGRATION}="internal"
# Bluetooth devices: External by default.
ENV{ID_BUS}=="bluetooth", ENV{ID_INTEGRATION}="external"
# USB devices: Internal if it's connected to a fixed port, external to a removable or unknown.
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="fixed", ENV{ID_INTEGRATION}="internal"
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="removable|unknown", ENV{ID_INTEGRATION}="external"
# libinput compatibility variables, must be loaded before 70-(joystick|touchpad).rules to allow hwdb quirks to override.
ENV{ID_INPUT}=="", GOTO="integration_libinput_end"
ENV{ID_INPUT_JOYSTICK}=="1", ENV{ID_INPUT_JOYSTICK_INTEGRATION}="$env{ID_INTEGRATION}"
ENV{ID_INPUT_TOUCHPAD}=="1", ENV{ID_INPUT_TOUCHPAD_INTEGRATION}="$env{ID_INTEGRATION}"
LABEL="integration_libinput_end"
LABEL="integration_end"

View File

@ -23,7 +23,6 @@ rules = [
'60-persistent-v4l.rules',
'60-sensor.rules',
'60-serial.rules',
'65-integration.rules',
'70-camera.rules',
'70-joystick.rules',
'70-mouse.rules',

View File

@ -348,8 +348,8 @@ static int clamp_brightness(
assert(brightness);
/* Some systems turn the backlight all the way off at the lowest levels. This clamps the saved
* brightness to at least 1 or 1% of max_brightness (whichever is bigger) in case of 'backlight' subsystem.
* This avoids preserving an unreadably dim screen, which would otherwise force the user to disable
* brightness to at least 1 or 5% of max_brightness in case of 'backlight' subsystem. This
* avoids preserving an unreadably dim screen, which would otherwise force the user to disable
* state restoration. */
min_brightness = (unsigned) ((double) max_brightness * percent / 100);
@ -385,7 +385,7 @@ static int shall_clamp(sd_device *device, unsigned *ret) {
return r;
if (r > 0) {
property = "ID_BACKLIGHT_CLAMP";
default_percent = 1;
default_percent = 5;
} else {
property = "ID_LEDS_CLAMP";
default_percent = 0;

View File

@ -32,6 +32,8 @@
* message.
*/
struct iovec;
typedef struct LogContext {
unsigned n_ref;
/* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory

View File

@ -8,7 +8,6 @@
#include <sys/mount.h>
#include <unistd.h>
#include "capability-util.h"
#include "dlfcn-util.h"
#include "errno-util.h"
#include "fd-util.h"
@ -216,6 +215,53 @@ int namespace_open(
return pidref_namespace_open(&pidref, ret_pidns_fd, ret_mntns_fd, ret_netns_fd, ret_userns_fd, ret_root_fd);
}
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
int r;
/* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */
block_dlopen();
if (userns_fd >= 0) {
/* Can't setns to your own userns, since then you could escalate from non-root to root in
* your own namespace, so check if namespaces are equal before attempting to enter. */
r = is_our_namespace(userns_fd, NAMESPACE_USER);
if (r < 0)
return r;
if (r > 0)
userns_fd = -EBADF;
}
if (pidns_fd >= 0)
if (setns(pidns_fd, CLONE_NEWPID) < 0)
return -errno;
if (mntns_fd >= 0)
if (setns(mntns_fd, CLONE_NEWNS) < 0)
return -errno;
if (netns_fd >= 0)
if (setns(netns_fd, CLONE_NEWNET) < 0)
return -errno;
if (userns_fd >= 0)
if (setns(userns_fd, CLONE_NEWUSER) < 0)
return -errno;
if (root_fd >= 0) {
if (fchdir(root_fd) < 0)
return -errno;
if (chroot(".") < 0)
return -errno;
}
if (userns_fd >= 0)
return reset_uid_gid();
return 0;
}
static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
int r;
@ -237,43 +283,20 @@ static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
return 1;
}
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
int r;
/* Similar to namespace_enter(), but operates on a set of namespaces that are potentially owned
* by the userns ("delegated"), in which case we'll need to gain CAP_SYS_ADMIN by joining
* the userns first, and the rest later. */
assert(userns_fd >= 0);
/* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */
block_dlopen();
if (userns_fd >= 0) {
/* Can't setns to your own userns, since then you could escalate from non-root to root in
* your own namespace, so check if namespaces are equal before attempting to enter. */
r = is_our_namespace(userns_fd, NAMESPACE_USER);
if (r < 0)
return r;
if (r > 0)
userns_fd = -EBADF;
}
r = have_effective_cap(CAP_SYS_ADMIN);
if (r < 0)
return r;
bool have_cap_sys_admin = r > 0;
if (!have_cap_sys_admin) {
/* If we don't have CAP_SYS_ADMIN in our own user namespace, our best bet is to enter the
* user namespace first (if we got one) to get CAP_SYS_ADMIN within the child user namespace,
* and then hope the other namespaces are owned by the child user namespace. If they aren't,
* we'll just get an EPERM later on when trying to setns() to them. */
if (userns_fd < 0)
return log_debug_errno(
SYNTHETIC_ERRNO(EPERM),
"Need CAP_SYS_ADMIN or a child user namespace to enter namespaces.");
if (setns(userns_fd, CLONE_NEWUSER) < 0)
return -errno;
}
if (pidns_fd >= 0) {
r = namespace_enter_one_idempotent(pidns_fd, NAMESPACE_PID);
@ -293,10 +316,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
return r;
}
if (userns_fd >= 0 && have_cap_sys_admin)
if (setns(userns_fd, CLONE_NEWUSER) < 0)
return -errno;
if (root_fd >= 0) {
if (fchdir(root_fd) < 0)
return -errno;
@ -305,15 +324,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
return -errno;
}
if (userns_fd >= 0) {
/* Try to become root in the user namespace but don't error out if we can't, since it's not
* uncommon to have user namespaces without a root user in them. */
r = reset_uid_gid();
if (r < 0)
log_debug_errno(r, "Unable to drop auxiliary groups or reset UID/GID, ignoring: %m");
}
return 0;
return maybe_setgroups(/* size = */ 0, NULL);
}
int fd_is_namespace(int fd, NamespaceType type) {

View File

@ -47,6 +47,7 @@ int namespace_open(
int *ret_root_fd);
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
int namespace_enter_delegated(int userns_fd, int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
int fd_is_namespace(int fd, NamespaceType type);
int is_our_namespace(int fd, NamespaceType type);

View File

@ -1128,6 +1128,10 @@ bool is_main_thread(void) {
return cached;
}
bool oom_score_adjust_is_valid(int oa) {
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
}
unsigned long personality_from_string(const char *s) {
Architecture architecture;
@ -1774,6 +1778,7 @@ int namespace_fork_full(
int netns_fd,
int userns_fd,
int root_fd,
bool delegated,
PidRef *ret) {
_cleanup_(pidref_done_sigkill_wait) PidRef pidref_outer = PIDREF_NULL;
@ -1819,6 +1824,9 @@ int namespace_fork_full(
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
if (delegated)
r = namespace_enter_delegated(userns_fd, pidns_fd, mntns_fd, netns_fd, root_fd);
else
r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
if (r < 0) {
log_full_errno(prio, r, "Failed to join namespace: %m");
@ -1879,10 +1887,6 @@ int namespace_fork_full(
return 1;
}
bool oom_score_adjust_is_valid(int oa) {
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
}
int set_oom_score_adjust(int value) {
char t[DECIMAL_STR_MAX(int)];

View File

@ -87,6 +87,8 @@ int pidref_from_same_root_fs(PidRef *a, PidRef *b);
bool is_main_thread(void);
bool oom_score_adjust_is_valid(int oa);
#ifndef PERSONALITY_INVALID
/* personality(2) documents that 0xFFFFFFFFUL is used for querying the
* current personality, hence let's use that here as error
@ -199,6 +201,7 @@ int namespace_fork_full(
int netns_fd,
int userns_fd,
int root_fd,
bool delegated,
PidRef *ret);
static inline int namespace_fork(
@ -213,11 +216,10 @@ static inline int namespace_fork(
PidRef *ret) {
return namespace_fork_full(outer_name, inner_name, NULL, 0, flags,
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd,
pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd, false,
ret);
}
bool oom_score_adjust_is_valid(int oa);
int set_oom_score_adjust(int value);
int get_oom_score_adjust(int *ret);
@ -233,6 +235,9 @@ int get_oom_score_adjust(int *ret);
assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
/* Like TAKE_PTR() but for pid_t, resetting them to 0 */
#define TAKE_PID(pid) TAKE_GENERIC(pid, pid_t, 0)
int setpriority_closest(int priority);
_noreturn_ void freeze(void);

View File

@ -31,7 +31,6 @@
#include "namespace-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "signal-util.h"
@ -1667,7 +1666,7 @@ int openpt_allocate_in_namespace(
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
if (r < 0)
return log_debug_errno(r, "Failed to open namespaces of PID "PID_FMT": %m", pidref->pid);
return r;
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair) < 0)
return -errno;

View File

@ -437,7 +437,7 @@ void cleanup_tmpfile_data_done(struct cleanup_tmpfile_data *d) {
assert(d);
if (!d->dir_fd ||
(*d->dir_fd < 0 && *d->dir_fd != AT_FDCWD) ||
*d->dir_fd < 0 ||
!d->filename ||
!*d->filename)
return;

View File

@ -920,28 +920,19 @@ int maybe_setgroups(size_t size, const gid_t *list) {
/* Check if setgroups is allowed before we try to drop all the auxiliary groups */
if (size == 0) { /* Dropping all aux groups? */
/* The kernel refuses setgroups() if there are no GID mappings in the current
* user namespace, so check that beforehand and don't try to setgroups() if
* there are no GID mappings. */
_cleanup_fclose_ FILE *f = fopen("/proc/self/gid_map", "re");
if (!f && errno != ENOENT)
return -errno;
if (f) {
r = safe_fgetc(f, /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
log_debug("Skipping setgroups(), /proc/self/gid_map is empty");
return 0;
}
}
_cleanup_free_ char *setgroups_content = NULL;
bool can_setgroups;
r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
if (r < 0 && r != -ENOENT)
if (r == -ENOENT)
/* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
can_setgroups = true;
else if (r < 0)
return r;
if (r > 0 && streq(setgroups_content, "deny")) {
else
can_setgroups = streq(setgroups_content, "allow");
if (!can_setgroups) {
log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
return 0;
}

View File

@ -175,22 +175,26 @@ int install_random_seed(const char *esp) {
if (fd < 0)
return log_error_errno(fd, "Failed to open random seed file for writing: %m");
CLEANUP_TMPFILE_AT(loader_dir_fd, tmp);
if (!warned) /* only warn once per seed file */
(void) random_seed_verify_permissions(fd, S_IFREG);
r = loop_write(fd, buffer, sizeof(buffer));
if (r < 0)
return log_error_errno(r, "Failed to write random seed file: %m");
if (r < 0) {
log_error_errno(r, "Failed to write random seed file: %m");
goto fail;
}
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0)
return log_error_errno(errno, "Failed to sync random seed file: %m");
if (fsync(fd) < 0 || fsync(loader_dir_fd) < 0) {
r = log_error_errno(errno, "Failed to sync random seed file: %m");
goto fail;
}
if (renameat(loader_dir_fd, tmp, loader_dir_fd, "random-seed") < 0)
return log_error_errno(errno, "Failed to move random seed file into place: %m");
if (renameat(loader_dir_fd, tmp, loader_dir_fd, "random-seed") < 0) {
r = log_error_errno(errno, "Failed to move random seed file into place: %m");
goto fail;
}
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
tmp = mfree(tmp);
if (syncfs(fd) < 0)
return log_error_errno(errno, "Failed to sync ESP file system: %m");
@ -198,6 +202,12 @@ int install_random_seed(const char *esp) {
log_info("Random seed file %s/loader/random-seed successfully %s (%zu bytes).", esp, refreshed ? "refreshed" : "written", sizeof(buffer));
return set_system_token();
fail:
assert(tmp);
(void) unlinkat(loader_dir_fd, tmp, 0);
return r;
}
int verb_random_seed(int argc, char *argv[], void *userdata) {

View File

@ -642,12 +642,14 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s
int r;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = acquire_esp(/* unprivileged_mode= */ false,
/* graceful= */ false,
/* ret_part= */ NULL,

View File

@ -1255,6 +1255,7 @@ int unit_refresh_credentials(Unit *u) {
(int[]) { tunnel_fds[1] }, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
pidns_fd, mntns_fd, /* netns_fd = */ -EBADF, userns_fd, root_fd,
/* delegated = */ MANAGER_IS_USER(u->manager),
&child);
if (r < 0)
return log_full_errno(ERRNO_IS_NEG_PRIVILEGE(r) ? LOG_WARNING : LOG_ERR, r,

View File

@ -171,11 +171,7 @@ int manager_serialize(
if (r < 0)
return r;
r = varlink_server_serialize(m->varlink_server, /* name = */ NULL, f, fds);
if (r < 0)
return r;
r = varlink_server_serialize(m->metrics_varlink_server, "metrics", f, fds);
r = varlink_server_serialize(m->varlink_server, f, fds);
if (r < 0)
return r;
@ -286,6 +282,7 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
bool deserialize_varlink_sockets = false;
int r;
assert(m);
@ -493,28 +490,23 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
r = strv_extend(&m->subscribed_as_strv, val);
if (r < 0)
return r;
} else if ((val = startswith(l, "varlink-server-metrics-"))) {
if (m->objective == MANAGER_RELOAD)
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
continue;
r = manager_setup_varlink_metrics_server(m);
if (r < 0)
log_warning_errno(r, "Failed to setup metrics varlink server, ignoring: %m");
else
(void) varlink_server_deserialize_one(m->metrics_varlink_server, val, fds);
} else if ((val = startswith(l, "varlink-server-"))) {
if (m->objective == MANAGER_RELOAD)
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
continue;
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
if (!m->varlink_server) {
r = manager_setup_varlink_server(m);
if (r < 0)
if (r < 0) {
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
else
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
continue;
}
deserialize_varlink_sockets = true;
}
/* To avoid unnecessary deserialization (i.e. during reload vs. reexec) we only deserialize
* the FDs if we had to create a new m->varlink_server. The deserialize_varlink_sockets flag
* is initialized outside of the loop, is flipped after the VarlinkServer is setup, and
* remains set until all serialized contents are handled. */
if (deserialize_varlink_sockets)
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
} else if ((val = startswith(l, "dump-ratelimit=")))
deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val);
else if ((val = startswith(l, "reload-reexec-ratelimit=")))

View File

@ -112,7 +112,7 @@ static int ip_address_access_build_json(sd_json_variant **ret, const char *name,
r = sd_json_variant_append_arraybo(
&v,
SD_JSON_BUILD_PAIR_INTEGER("family", i->family),
JSON_BUILD_PAIR_IN_ADDR("address", i->family, &i->address),
JSON_BUILD_PAIR_IN_ADDR("address", &i->address, i->family),
SD_JSON_BUILD_PAIR_UNSIGNED("prefixLength", i->prefixlen));
if (r < 0)
return r;
@ -299,7 +299,6 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void
SD_JSON_BUILD_OBJECT(
SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->restrict_network_interfaces_is_allow_list),
JSON_BUILD_PAIR_STRING_SET("interfaces", c->restrict_network_interfaces))),
JSON_BUILD_PAIR_STRING_NON_EMPTY("BindNetworkInterface", c->bind_network_interface),
JSON_BUILD_PAIR_CALLBACK_NON_NULL("NFTSet", nft_set_build_json, &c->nft_set_context),
/* BPF programs */

View File

@ -1,8 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-json.h"
#include "sd-varlink.h"
#include "hashmap.h"
#include "manager.h"
#include "metrics.h"
@ -178,10 +175,10 @@ const MetricFamily metric_family_table[] = {
{}
};
int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return metrics_method_describe(metric_family_table, link, parameters, flags, userdata);
}
int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return metrics_method_list(metric_family_table, link, parameters, flags, userdata);
}

View File

@ -1,9 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "core-forward.h"
#include "sd-varlink.h"
#include "sd-json.h"
#define METRIC_IO_SYSTEMD_MANAGER_PREFIX "io.systemd.Manager."
int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);

View File

@ -9,6 +9,7 @@
#include "path-util.h"
#include "pidref.h"
#include "string-util.h"
#include "strv.h"
#include "unit.h"
#include "varlink.h"
#include "varlink-dynamic-user.h"
@ -374,8 +375,6 @@ int manager_setup_varlink_server(Manager *m) {
if (r < 0)
return log_debug_errno(r, "Failed to allocate Varlink server: %m");
(void) sd_varlink_server_set_description(s, "varlink-api");
r = sd_varlink_server_add_interface_many(
s,
&vl_interface_io_systemd_Manager,
@ -426,64 +425,26 @@ int manager_setup_varlink_server(Manager *m) {
return 1;
}
int manager_setup_varlink_metrics_server(Manager *m) {
static int manager_setup_varlink_metrics_server(Manager *m) {
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
int r;
assert(m);
sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA;
if (MANAGER_IS_SYSTEM(m))
flags |= SD_VARLINK_SERVER_ACCOUNT_UID;
return metrics_setup_varlink_server(&m->metrics_varlink_server, flags,
m->event, EVENT_PRIORITY_IPC,
vl_method_list_metrics, vl_method_describe_metrics,
m);
}
static int varlink_server_listen_many_idempotent_sentinel(
sd_varlink_server *s,
bool known_fresh,
const char *prefix,
...) {
va_list ap;
int r = 0;
assert(s);
va_start(ap, prefix);
for (const char *address; (address = va_arg(ap, const char*)); ) {
_cleanup_free_ char *p = NULL;
if (prefix) {
p = path_join(prefix, address);
if (!p) {
r = log_oom();
break;
}
address = p;
}
/* We might have got sockets through deserialization. Do not bind to them twice. */
if (!known_fresh && varlink_server_contains_socket(s, address))
continue;
r = sd_varlink_server_listen_address(s, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
if (r < 0) {
log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
break;
}
}
va_end(ap);
r = metrics_setup_varlink_server(
&m->metrics_varlink_server, flags, m->event, vl_method_list, vl_method_describe, m);
if (r < 0)
return r;
return 0;
}
#define varlink_server_listen_many_idempotent(s, known_fresh, prefix, ...) \
varlink_server_listen_many_idempotent_sentinel((s), (known_fresh), (prefix), __VA_ARGS__, NULL)
static int manager_varlink_init_system_api(Manager *m) {
static int manager_varlink_init_system(Manager *m) {
int r;
_cleanup_free_ char *metrics_address = NULL;
assert(m);
@ -492,73 +453,74 @@ static int manager_varlink_init_system_api(Manager *m) {
return log_error_errno(r, "Failed to set up varlink server: %m");
bool fresh = r > 0;
if (!MANAGER_IS_TEST_RUN(m)) {
r = varlink_server_listen_many_idempotent(
m->varlink_server, fresh,
/* prefix = */ NULL,
"/run/systemd/io.systemd.Manager",
"/run/systemd/userdb/io.systemd.DynamicUser",
VARLINK_PATH_MANAGED_OOM_SYSTEM);
if (r < 0)
return r;
}
return 0;
}
static int manager_varlink_init_user_api(Manager *m) {
int r;
assert(m);
if (MANAGER_IS_TEST_RUN(m))
return 0;
r = manager_setup_varlink_server(m);
if (r < 0)
return log_error_errno(r, "Failed to set up varlink server: %m");
bool fresh = r > 0;
r = varlink_server_listen_many_idempotent(
m->varlink_server, fresh,
m->prefix[EXEC_DIRECTORY_RUNTIME],
"systemd/io.systemd.Manager");
if (r < 0)
return r;
return manager_varlink_managed_oom_connect(m);
}
static int manager_varlink_init_metrics(Manager *m) {
int r;
assert(m);
if (MANAGER_IS_TEST_RUN(m))
return 0;
r = manager_setup_varlink_metrics_server(m);
if (r < 0)
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
bool fresh = r > 0;
bool metrics_fresh = r > 0;
return varlink_server_listen_many_idempotent(
m->metrics_varlink_server, fresh,
m->prefix[EXEC_DIRECTORY_RUNTIME],
"systemd/report/io.systemd.Manager");
}
int manager_varlink_init(Manager *m) {
int r;
if (MANAGER_IS_SYSTEM(m))
r = manager_varlink_init_system_api(m);
else
r = manager_varlink_init_user_api(m);
r = runtime_directory_generic(m->runtime_scope, "systemd/report/io.systemd.Manager", &metrics_address);
if (r < 0)
return r;
return manager_varlink_init_metrics(m);
if (!MANAGER_IS_TEST_RUN(m)) {
FOREACH_STRING(address,
"/run/systemd/userdb/io.systemd.DynamicUser",
VARLINK_PATH_MANAGED_OOM_SYSTEM,
"/run/systemd/io.systemd.Manager",
metrics_address) {
sd_varlink_server *server = streq(address, metrics_address) ? m->metrics_varlink_server : m->varlink_server;
fresh = streq(address, metrics_address) ? metrics_fresh : fresh;
/* We might have got sockets through deserialization. Do not bind to them twice. */
if (!fresh && varlink_server_contains_socket(server, address))
continue;
r = sd_varlink_server_listen_address(server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
}
}
return 1;
}
static int manager_varlink_init_user(Manager *m) {
int r;
assert(m);
if (MANAGER_IS_TEST_RUN(m))
return 0;
r = manager_setup_varlink_server(m);
if (r < 0)
return log_error_errno(r, "Failed to set up varlink server: %m");
bool fresh = r > 0;
FOREACH_STRING(a,
"systemd/io.systemd.Manager") {
_cleanup_free_ char *address = NULL;
address = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], a);
if (!address)
return -ENOMEM;
/* We might have got sockets through deserialization. Do not bind to them twice. */
if (!fresh && varlink_server_contains_socket(m->varlink_server, address))
continue;
r = sd_varlink_server_listen_address(m->varlink_server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
}
r = manager_setup_varlink_metrics_server(m);
if (r < 0)
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
return manager_varlink_managed_oom_connect(m);
}
int manager_varlink_init(Manager *m) {
return MANAGER_IS_SYSTEM(m) ? manager_varlink_init_system(m) : manager_varlink_init_user(m);
}
void manager_varlink_done(Manager *m) {
@ -572,7 +534,6 @@ void manager_varlink_done(Manager *m) {
m->varlink_server = sd_varlink_server_unref(m->varlink_server);
m->managed_oom_varlink = sd_varlink_close_unref(m->managed_oom_varlink);
m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server);
}

View File

@ -4,7 +4,6 @@
#include "core-forward.h"
int manager_setup_varlink_server(Manager *m);
int manager_setup_varlink_metrics_server(Manager *m);
int manager_varlink_init(Manager *m);
void manager_varlink_done(Manager *m);

View File

@ -1793,12 +1793,14 @@ static int vl_method_list_transfers(sd_varlink *link, sd_json_variant *parameter
assert(link);
assert(parameters);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = varlink_set_sentinel(link, "io.systemd.Import.NoTransfers");
if (r < 0)
return r;

View File

@ -317,6 +317,8 @@ int dhcp_server_static_leases_append_json(sd_dhcp_server *server, sd_json_varian
int dhcp_server_save_leases(sd_dhcp_server *server) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
sd_id128_t boot_id;
int r;
@ -353,27 +355,25 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
if (r < 0)
return r;
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
r = fopen_temporary_at(server->lease_dir_fd, server->lease_file, &f, &temp_path);
if (r < 0)
return r;
CLEANUP_TMPFILE_AT(server->lease_dir_fd, temp_path);
(void) fchmod(fileno(f), 0644);
r = sd_json_variant_dump(v, SD_JSON_FORMAT_NEWLINE | SD_JSON_FORMAT_FLUSH, f, /* prefix= */ NULL);
if (r < 0)
return r;
goto failure;
r = conservative_renameat(server->lease_dir_fd, temp_path, server->lease_dir_fd, server->lease_file);
if (r < 0)
return r;
goto failure;
temp_path = mfree(temp_path); /* disarm CLEANUP_TMPFILE_AT() */
return 0;
failure:
(void) unlinkat(server->lease_dir_fd, temp_path, /* flags= */ 0);
return r;
}
static int json_dispatch_chaddr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {

View File

@ -5,8 +5,8 @@
#include "sd-json.h"
#include "log.h"
#include "sd-forward.h"
#include "log.h"
#include "string-util.h" /* IWYU pragma: keep */
#define JSON_VARIANT_REPLACE(v, q) \
@ -175,9 +175,9 @@ enum {
_JSON_BUILD_PAIR_VARIANT_NON_EMPTY,
/* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */
_JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY,
_JSON_BUILD_PAIR_IN4_ADDR_NON_NULL,
_JSON_BUILD_PAIR_IN6_ADDR_NON_NULL,
_JSON_BUILD_PAIR_IN_ADDR_NON_NULL,
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING,
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL,
_JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL,
_JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
_JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL,
@ -190,6 +190,12 @@ enum {
_JSON_BUILD_PAIR_TRISTATE_NON_NULL,
_JSON_BUILD_PAIR_PIDREF_NON_NULL,
_JSON_BUILD_PAIR_DEVNUM,
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING,
_JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING,
_JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING,
_JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL,
_JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL,
_JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL,
_SD_JSON_BUILD_REALLYMAX,
};
@ -200,7 +206,7 @@ enum {
#define JSON_BUILD_CONST_STRING(s) _SD_JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s)
#define JSON_BUILD_IN4_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr))
#define JSON_BUILD_IN6_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr))
#define JSON_BUILD_IN_ADDR(f, v) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
#define JSON_BUILD_IN_ADDR(v, f) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
#define JSON_BUILD_ETHER_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr))
#define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v }
#define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s }
@ -223,15 +229,9 @@ enum {
#define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (sd_json_variant*) { v }
#define JSON_BUILD_PAIR_VARIANT_NON_EMPTY(name, v) _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, (const char*) { name }, (sd_json_variant*) { v }
#define JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n }
#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) }
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) }
#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, v, f) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (const union in_addr_union*) { v }, (int) { f }
#define JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, (const char*) { name }, (const struct ether_addr*) { v }
#define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v }
#define JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL(name, t) _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, (const char*) { name }, (dual_timestamp*) { t }
@ -243,12 +243,18 @@ enum {
#define JSON_BUILD_PAIR_OCTESCAPE_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_HEX_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n }
#define JSON_BUILD_PAIR_TRISTATE_NON_NULL(name, i) _JSON_BUILD_PAIR_TRISTATE_NON_NULL, (const char*) { name }, (int) { i }
#define JSON_BUILD_PAIR_PIDREF_NON_NULL(name, p) _JSON_BUILD_PAIR_PIDREF_NON_NULL, (const char*) { name }, (const PidRef*) { p }
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, (const char*) { name }, (const struct in6_addr*) { v }
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, (const char*) { name }, (const struct in_addr*) { v }
#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v }
#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
#define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov))
#define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov))
#define JSON_BUILD_PAIR_IN4_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v))
#define JSON_BUILD_PAIR_IN6_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v))
#define JSON_BUILD_PAIR_IN_ADDR(name, f, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(f, v))
#define JSON_BUILD_PAIR_IN_ADDR(name, v, f) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f))
#define JSON_BUILD_PAIR_ETHER_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v))
#define JSON_BUILD_PAIR_HW_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v))
#define JSON_BUILD_PAIR_STRING_SET(name, s) SD_JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s))

View File

@ -3370,8 +3370,8 @@ done:
r = 0;
finish:
FOREACH_ARRAY(i, stack, n_stack)
json_stack_release(i);
for (size_t i = 0; i < n_stack; i++)
json_stack_release(stack + i);
free(stack);
@ -4666,9 +4666,63 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
break;
}
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL:
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL:
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: {
case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: {
const struct in_addr *a;
const char *n;
if (current->expect != EXPECT_OBJECT_KEY) {
r = -EINVAL;
goto finish;
}
n = va_arg(ap, const char *);
a = va_arg(ap, const struct in_addr *);
if (a && in4_addr_is_set(a) && current->n_suppress == 0) {
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
if (r < 0)
goto finish;
}
n_subtract = 2; /* we generated two items */
current->expect = EXPECT_OBJECT_KEY;
break;
}
case _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL: {
const struct in6_addr *a;
const char *n;
if (current->expect != EXPECT_OBJECT_KEY) {
r = -EINVAL;
goto finish;
}
n = va_arg(ap, const char *);
a = va_arg(ap, const struct in6_addr *);
if (a && in6_addr_is_set(a) && current->n_suppress == 0) {
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
if (r < 0)
goto finish;
}
n_subtract = 2; /* we generated two items */
current->expect = EXPECT_OBJECT_KEY;
break;
}
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: {
const union in_addr_union *a;
const char *n;
int f;
@ -4679,16 +4733,10 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
}
n = va_arg(ap, const char *);
f = va_arg(ap, int);
a = va_arg(ap, const union in_addr_union *);
f = va_arg(ap, int);
if (current->n_suppress == 0 &&
((a && in_addr_is_set(f, a)) ||
command == _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING)) {
if (!a)
a = &IN_ADDR_NULL;
if (a && in_addr_is_set(f, a) && current->n_suppress == 0) {
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
@ -4696,36 +4744,9 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f));
if (r < 0)
goto finish;
if (IN_SET(command, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL)) {
_cleanup_free_ char *string_key_name = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
string_key_name = strjoin(n, "String");
if (!string_key_name) {
r = -ENOMEM;
goto finish;
}
r = sd_json_variant_new_string(&string_key, string_key_name);
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_value, IN_ADDR_TO_STRING(f, a));
if (r < 0)
goto finish;
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
r = -ENOMEM;
goto finish;
}
current->elements[current->n_elements++] = TAKE_PTR(string_key);
current->elements[current->n_elements++] = TAKE_PTR(string_value);
}
}
n_subtract = command == _JSON_BUILD_PAIR_IN_ADDR_NON_NULL ? 2 : 4;
n_subtract = 2; /* we generated two items */
current->expect = EXPECT_OBJECT_KEY;
break;
@ -4875,6 +4896,207 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) {
break;
}
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL:
case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: {
const union in_addr_union *a;
const char *n;
int f;
if (current->expect != EXPECT_OBJECT_KEY) {
r = -EINVAL;
goto finish;
}
n = va_arg(ap, const char *);
f = va_arg(ap, int);
a = va_arg(ap, const union in_addr_union *);
if (current->n_suppress == 0) {
bool have_address = a && in_addr_is_set(f, a);
if (have_address || command != _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL) {
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
* For NON_NULL variant, we only get here when have_address is true. */
if (a) {
r = in_addr_to_string(f, a, &addr_str);
if (r < 0)
goto finish;
}
string_key_name = strjoin(n, "String");
if (!string_key_name) {
r = -ENOMEM;
goto finish;
}
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f));
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_key, string_key_name);
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_value, addr_str);
if (r < 0)
goto finish;
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
r = -ENOMEM;
goto finish;
}
current->elements[current->n_elements++] = TAKE_PTR(string_key);
current->elements[current->n_elements++] = TAKE_PTR(string_value);
}
}
n_subtract = 4; /* we generated two pairs (binary and string) */
current->expect = EXPECT_OBJECT_KEY;
break;
}
case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL:
case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING: {
const struct in6_addr *a;
const char *n;
if (current->expect != EXPECT_OBJECT_KEY) {
r = -EINVAL;
goto finish;
}
n = va_arg(ap, const char *);
a = va_arg(ap, const struct in6_addr *);
if (current->n_suppress == 0) {
bool have_address = a && in6_addr_is_set(a);
if (have_address || command != _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL) {
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
* For NON_NULL variant, we only get here when have_address is true. */
if (a) {
r = in6_addr_to_string(a, &addr_str);
if (r < 0)
goto finish;
}
string_key_name = strjoin(n, "String");
if (!string_key_name) {
r = -ENOMEM;
goto finish;
}
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_key, string_key_name);
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_value, addr_str);
if (r < 0)
goto finish;
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
r = -ENOMEM;
goto finish;
}
current->elements[current->n_elements++] = TAKE_PTR(string_key);
current->elements[current->n_elements++] = TAKE_PTR(string_value);
}
}
n_subtract = 4; /* we generated two pairs (binary and string) */
current->expect = EXPECT_OBJECT_KEY;
break;
}
case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL:
case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING: {
const struct in_addr *a;
const char *n;
if (current->expect != EXPECT_OBJECT_KEY) {
r = -EINVAL;
goto finish;
}
n = va_arg(ap, const char *);
a = va_arg(ap, const struct in_addr *);
if (current->n_suppress == 0) {
bool have_address = a && !in4_addr_is_null(a);
if (have_address || command != _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL) {
_cleanup_free_ char *addr_str = NULL, *string_key_name = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL;
/* For non-NON_NULL variant, always convert address to string (even if all zeros).
* For NON_NULL variant, we only get here when have_address is true. */
if (a) {
union in_addr_union addr_union = { .in = *a };
r = in_addr_to_string(AF_INET, &addr_union, &addr_str);
if (r < 0)
goto finish;
}
string_key_name = strjoin(n, "String");
if (!string_key_name) {
r = -ENOMEM;
goto finish;
}
r = sd_json_variant_new_string(&add, n);
if (r < 0)
goto finish;
r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_key, string_key_name);
if (r < 0)
goto finish;
r = sd_json_variant_new_string(&string_value, addr_str);
if (r < 0)
goto finish;
if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) {
r = -ENOMEM;
goto finish;
}
current->elements[current->n_elements++] = TAKE_PTR(string_key);
current->elements[current->n_elements++] = TAKE_PTR(string_value);
}
}
n_subtract = 4; /* we generated two pairs (binary and string) */
current->expect = EXPECT_OBJECT_KEY;
break;
}
case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: {
sd_json_build_callback_t cb;
void *userdata;
@ -5005,8 +5227,8 @@ done:
r = 0;
finish:
FOREACH_ARRAY(i, stack, n_stack)
json_stack_release(i);
for (size_t i = 0; i < n_stack; i++)
json_stack_release(stack + i);
free(stack);

View File

@ -247,20 +247,28 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
/* stdio_fds= */ NULL,
/* except_fds= */ (int[]) { pair[1] },
/* n_except_fds= */ 1,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
if (r == 0) {
char spid[DECIMAL_STR_MAX(pid_t)+1];
const char *setenv_list[] = {
"LISTEN_PID", spid,
"LISTEN_FDS", "1",
"LISTEN_PID", spid,
"LISTEN_FDNAMES", "varlink",
NULL, NULL,
};
/* Child */
pair[0] = -EBADF;
r = move_fd(pair[1], 3, /* cloexec= */ false);
if (r < 0) {
log_debug_errno(r, "Failed to move file descriptor to 3: %m");
_exit(EXIT_FAILURE);
}
xsprintf(spid, PID_FMT, pidref.pid);
uint64_t pidfdid;
@ -356,7 +364,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
/* except_fds= */ NULL,
/* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
@ -440,7 +448,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
/* except_fds= */ NULL,
/* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
@ -1381,14 +1389,15 @@ static int varlink_format_queue(sd_varlink *v) {
* would not corrupt our fd message boundaries */
while (v->output_queue) {
_cleanup_free_ int *array = NULL;
assert(v->n_output_queue > 0);
VarlinkJsonQueueItem *q = v->output_queue;
if (v->n_output_fds > 0) /* unwritten fds? if we'd add more we'd corrupt the fd message boundaries, hence wait */
return 0;
VarlinkJsonQueueItem *q = v->output_queue;
_cleanup_free_ int *array = NULL;
if (q->n_fds > 0) {
array = newdup(int, q->fds, q->n_fds);
if (!array)
@ -1400,7 +1409,8 @@ static int varlink_format_queue(sd_varlink *v) {
return r;
/* Take possession of the queue element's fds */
free_and_replace(v->output_fds, array);
free(v->output_fds);
v->output_fds = TAKE_PTR(array);
v->n_output_fds = q->n_fds;
q->n_fds = 0;
@ -1583,7 +1593,7 @@ static int varlink_dispatch_method(sd_varlink *v) {
r = callback(v, parameters, flags, v->userdata);
if (VARLINK_STATE_WANTS_REPLY(v->state)) {
if (r < 0) {
varlink_log_errno(v, r, "Callback for '%s' returned error: %m", method);
varlink_log_errno(v, r, "Callback for %s returned error: %m", method);
/* We got an error back from the callback. Propagate it to the client
* if the method call remains unanswered. */
@ -1612,16 +1622,6 @@ static int varlink_dispatch_method(sd_varlink *v) {
varlink_log_errno(v, r, "Failed to process sentinel for method '%s': %m", method);
} else {
assert(!v->previous);
/* We're at the bare minimum referenced by sd_varlink_server and
* sd_varlink_process() */
if (v->n_ref <= 2) {
r = varlink_log_errno(v, SYNTHETIC_ERRNO(EPROTO),
"Callback for method '%s' returned without enqueuing a reply or stashing connection, failing.",
method);
goto fail;
}
r = 0;
}
@ -1857,10 +1857,19 @@ _public_ int sd_varlink_wait(sd_varlink *v, uint64_t timeout) {
r = sd_varlink_get_timeout(v, &t);
if (r < 0)
return r;
if (t != USEC_INFINITY)
t = usec_sub_unsigned(t, now(CLOCK_MONOTONIC));
if (t != USEC_INFINITY) {
usec_t n;
t = MIN(t, timeout);
n = now(CLOCK_MONOTONIC);
if (t < n)
t = 0;
else
t = usec_sub_unsigned(t, n);
}
if (timeout != USEC_INFINITY &&
(t == USEC_INFINITY || timeout < t))
t = timeout;
events = sd_varlink_get_events(v);
if (events < 0)
@ -2010,7 +2019,7 @@ _public_ int sd_varlink_flush(sd_varlink *v) {
return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected.");
for (;;) {
if (v->output_buffer_size == 0 && !v->output_queue)
if (v->output_buffer_size == 0)
break;
if (v->write_disconnected)
return -ECONNRESET;
@ -2672,8 +2681,8 @@ _public_ int sd_varlink_reset_fds(sd_varlink *v) {
* rollback the fds. Note that this is implicitly called whenever an error reply is sent, see
* below. */
close_many(v->pushed_fds, v->n_pushed_fds);
v->n_pushed_fds = 0;
close_many(v->output_fds, v->n_output_fds);
v->n_output_fds = 0;
return 0;
}
@ -2697,7 +2706,7 @@ _public_ int sd_varlink_error(sd_varlink *v, const char *error_id, sd_json_varia
return r;
/* If we have a previous reply still ready make sure we queue it before the error. We only
* ever set "previous" if we're in a streaming method so we pass more=true unconditionally
* ever set "previous" if we're in a streaming method so we pass more=true uncondtionally
* here as we know we're still going to queue an error afterwards. */
r = varlink_enqueue_item(v, v->previous);
if (r < 0)
@ -3547,8 +3556,8 @@ static int validate_connection(sd_varlink_server *server, const struct ucred *uc
c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
if (c >= server->connections_per_uid_max) {
varlink_server_log(server, "Per-UID connection limit of %u for '" UID_FMT "' reached, refusing.",
server->connections_per_uid_max, ucred->uid);
varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.",
server->connections_per_uid_max);
return 0;
}
}
@ -3601,7 +3610,7 @@ _public_ int sd_varlink_server_add_connection_pair(
assert_return(input_fd >= 0, -EBADF);
assert_return(output_fd >= 0, -EBADF);
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_MYSELF_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) {
if (override_ucred)
ucred = *override_ucred;
@ -3743,7 +3752,11 @@ static int varlink_server_create_listen_fd_socket(sd_varlink_server *s, int fd,
};
if (s->event) {
r = varlink_server_add_socket_event_source(s, ss);
r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss);
if (r < 0)
return r;
r = sd_event_source_set_priority(ss->event_source, s->event_priority);
if (r < 0)
return r;
}
@ -4067,14 +4080,13 @@ _public_ int sd_varlink_server_set_exit_on_idle(sd_varlink_server *s, int b) {
return 0;
}
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss) {
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority) {
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
int r;
assert(s);
assert(s->event);
assert(ss);
assert(ss->server == s);
assert(ss->fd >= 0);
assert(!ss->event_source);
@ -4082,7 +4094,7 @@ int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSo
if (r < 0)
return r;
r = sd_event_source_set_priority(es, s->event_priority);
r = sd_event_source_set_priority(es, priority);
if (r < 0)
return r;
@ -4104,14 +4116,13 @@ _public_ int sd_varlink_server_attach_event(sd_varlink_server *s, sd_event *e, i
return r;
}
s->event_priority = priority;
LIST_FOREACH(sockets, ss, s->sockets) {
r = varlink_server_add_socket_event_source(s, ss);
r = varlink_server_add_socket_event_source(s, ss, priority);
if (r < 0)
goto fail;
}
s->event_priority = priority;
return 0;
fail:
@ -4282,16 +4293,20 @@ _public_ int sd_varlink_server_add_interface_many_internal(sd_varlink_server *s,
}
_public_ unsigned sd_varlink_server_connections_max(sd_varlink_server *s) {
int dts;
/* If a server is specified, return the setting for that server, otherwise the default value */
if (s)
return s->connections_max;
int dts = getdtablesize();
dts = getdtablesize();
assert_se(dts > 0);
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
return MIN(VARLINK_DEFAULT_CONNECTIONS_MAX, (unsigned) dts / 4 * 3);
if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3)
return dts / 4 * 3;
return VARLINK_DEFAULT_CONNECTIONS_MAX;
}
_public_ unsigned sd_varlink_server_connections_per_uid_max(sd_varlink_server *s) {

View File

@ -262,4 +262,4 @@ static inline const char* varlink_server_description(sd_varlink_server *s) {
VarlinkServerSocket* varlink_server_socket_free(VarlinkServerSocket *ss);
DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket *, varlink_server_socket_free);
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss);
int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority);

View File

@ -376,10 +376,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
if (m->uid != 0 && m->class != MACHINE_HOST) {
r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
if (r < 0)
return log_debug_errno(
r,
"Failed to check if machine '%s' is running in the root user namespace: %m",
m->name);
return r;
if (r != 0)
return sd_bus_error_set(
error,

View File

@ -273,7 +273,6 @@ static int vl_method_mute(
int r;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
_cleanup_free_ Context *nc = new(Context, 1);
if (!nc)
@ -295,6 +294,9 @@ static int vl_method_mute(
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = sd_varlink_server_bind_disconnect(sd_varlink_get_server(link), vl_on_disconnect);
if (r < 0)
return r;

View File

@ -89,8 +89,6 @@ systemd_networkd_extract_sources = files(
'networkd-util.c',
'networkd-wifi.c',
'networkd-wiphy.c',
'networkd-wwan.c',
'networkd-wwan-bus.c',
'tc/cake.c',
'tc/codel.c',
'tc/drr.c',

View File

@ -29,7 +29,6 @@
#include "networkd-route.h"
#include "networkd-setlink.h"
#include "networkd-state-file.h"
#include "networkd-wwan.h"
#include "parse-util.h"
#include "set.h"
#include "socket-util.h"
@ -1771,9 +1770,6 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity) {
if (!link->dhcp_client)
return 0;
if (link_dhcp_enabled_by_bearer(link, AF_INET) == 0)
return 0;
if (!link_has_carrier(link))
return 0;

View File

@ -24,7 +24,6 @@
#include "networkd-queue.h"
#include "networkd-route.h"
#include "networkd-state-file.h"
#include "networkd-wwan.h"
#include "set.h"
#include "string-table.h"
#include "string-util.h"
@ -495,9 +494,6 @@ int dhcp6_start(Link *link) {
if (!link_dhcp6_enabled(link))
return 0;
if (link_dhcp_enabled_by_bearer(link, AF_INET6) == 0)
return 0;
if (!link_has_carrier(link))
return 0;

View File

@ -26,7 +26,6 @@
#include "networkd-route.h"
#include "networkd-route-util.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-wwan.h"
#include "ordered-set.h"
#include "set.h"
#include "string-util.h"
@ -542,15 +541,6 @@ static int dns_append_json(Link *link, sd_json_variant **v) {
return r;
}
Bearer *b;
if (link_get_bearer(link, &b) >= 0)
FOREACH_ARRAY(dns, b->dns, b->n_dns) {
r = dns_append_json_one(link, *dns, NETWORK_CONFIG_SOURCE_MODEM_MANAGER, NULL, &array);
if (r < 0)
return r;
}
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
const struct in_addr *dns;
union in_addr_union s;
@ -623,7 +613,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne
FOREACH_ARRAY(addr, res->addrs, res->n_addrs) {
r = sd_json_variant_append_arrayb(
&addrs_array,
JSON_BUILD_IN_ADDR(res->family, addr));
JSON_BUILD_IN_ADDR(addr, res->family));
if (r < 0)
return r;
}
@ -644,7 +634,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne
JSON_BUILD_PAIR_STRING_NON_EMPTY("DoHPath", res->dohpath),
JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports),
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", res->family, p)));
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, res->family)));
}
static int dnr_append_json(Link *link, sd_json_variant **v) {
@ -733,7 +723,7 @@ static int server_append_json_one_addr(int family, const union in_addr_union *a,
return sd_json_variant_append_arraybo(
array,
SD_JSON_BUILD_PAIR_INTEGER("Family", family),
JSON_BUILD_PAIR_IN_ADDR("Address", family, a),
JSON_BUILD_PAIR_IN_ADDR("Address", a, family),
SD_JSON_BUILD_PAIR_STRING("AddressString", address_str),
SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)),
JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p));

View File

@ -63,7 +63,6 @@
#include "networkd-state-file.h"
#include "networkd-sysctl.h"
#include "networkd-wifi.h"
#include "networkd-wwan-bus.h"
#include "ordered-set.h"
#include "parse-util.h"
#include "set.h"
@ -530,9 +529,6 @@ void link_check_ready(Link *link) {
if (!link->sr_iov_configured)
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
if (!link->bearer_configured)
return (void) log_link_debug(link, "%s(): Bearer has not been applied.", __func__);
/* IPv6LL is assigned after the link gains its carrier. */
if (!link->network->configure_without_carrier &&
link_ipv6ll_enabled(link) &&
@ -542,7 +538,7 @@ void link_check_ready(Link *link) {
/* All static addresses must be ready. */
bool has_static_address = false;
SET_FOREACH(a, link->addresses) {
if (!IN_SET(a->source, NETWORK_CONFIG_SOURCE_STATIC, NETWORK_CONFIG_SOURCE_MODEM_MANAGER))
if (a->source != NETWORK_CONFIG_SOURCE_STATIC)
continue;
if (!address_is_ready(a))
return (void) log_link_debug(link, "%s(): static address %s is not ready.", __func__,
@ -1297,10 +1293,6 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
r = link_modem_reconfigure(link);
if (r < 0)
return r;
if (!link_has_carrier(link))
return 0;

View File

@ -108,7 +108,6 @@ typedef struct Link {
unsigned set_link_messages;
unsigned set_flags_messages;
unsigned create_stacked_netdev_messages;
unsigned bearer_messages;
Set *addresses;
Set *neighbors;
@ -142,7 +141,6 @@ typedef struct Link {
bool master_set:1;
bool stacked_netdevs_created:1;
bool bridge_vlan_set:1;
bool bearer_configured:1;
sd_dhcp_server *dhcp_server;

View File

@ -16,7 +16,6 @@
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-manager-varlink.h"
#include "networkd-setlink.h"
#include "stat-util.h"
#include "varlink-io.systemd.Network.h"
#include "varlink-io.systemd.service.h"
@ -93,30 +92,26 @@ static int vl_method_get_namespace_id(sd_varlink *link, sd_json_variant *paramet
SD_JSON_BUILD_PAIR_CONDITION(nsid != UINT32_MAX, "NamespaceNSID", SD_JSON_BUILD_UNSIGNED(nsid)));
}
static int dispatch_interface(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, bool polkit, Link **ret) {
struct {
typedef struct InterfaceInfo {
int ifindex;
const char *ifname;
} info = {};
Link *link = NULL;
int r;
} InterfaceInfo;
static int dispatch_interface(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, Link **ret) {
static const sd_json_dispatch_field dispatch_table[] = {
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, voffsetof(info, ifindex), SD_JSON_RELAX },
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(info, ifname), 0 },
{}
}, dispatch_polkit_table[] = {
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, voffsetof(info, ifindex), SD_JSON_RELAX },
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(info, ifname), 0 },
VARLINK_DISPATCH_POLKIT_FIELD,
{ "InterfaceIndex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(InterfaceInfo, ifindex), SD_JSON_RELAX },
{ "InterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(InterfaceInfo, ifname), 0 },
{}
};
InterfaceInfo info = {};
Link *link = NULL;
int r;
assert(vlink);
assert(manager);
assert(ret);
r = sd_varlink_dispatch(vlink, parameters, polkit ? dispatch_polkit_table : dispatch_table, &info);
r = sd_varlink_dispatch(vlink, parameters, dispatch_table, &info);
if (r != 0)
return r;
@ -163,7 +158,7 @@ static int vl_method_get_lldp_neighbors(sd_varlink *vlink, sd_json_variant *para
assert(vlink);
assert(manager);
r = dispatch_interface(vlink, parameters, manager, /* polkit= */ false, &link);
r = dispatch_interface(vlink, parameters, manager, &link);
if (r != 0)
return r;
@ -284,46 +279,6 @@ static int vl_method_set_persistent_storage(sd_varlink *vlink, sd_json_variant *
return sd_varlink_reply(vlink, NULL);
}
static int vl_method_link_up_or_down(sd_varlink *vlink, sd_json_variant *parameters, Manager *manager, bool up) {
Link *link;
int r;
assert(vlink);
assert(manager);
r = dispatch_interface(vlink, parameters, manager, /* polkit= */ true, &link);
if (r != 0)
return r;
/* Require a specific link to be specified. */
if (!link)
return sd_varlink_error_invalid_parameter(vlink, JSON_VARIANT_STRING_CONST("InterfaceIndex"));
r = varlink_verify_polkit_async(
vlink,
manager->bus,
"org.freedesktop.network1.manage-links",
/* details= */ NULL,
&manager->polkit_registry);
if (r <= 0)
return r;
if (!up)
/* Stop all network engines while interface is still up to allow proper cleanup,
* e.g. sending IPv6 shutdown RA messages before the interface is brought down. */
(void) link_stop_engines(link, /* may_keep_dynamic = */ false);
return link_up_or_down_now_by_varlink(link, up, vlink);
}
static int vl_method_link_up(sd_varlink *vlink, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return vl_method_link_up_or_down(vlink, parameters, userdata, /* up= */ true);
}
static int vl_method_link_down(sd_varlink *vlink, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return vl_method_link_up_or_down(vlink, parameters, userdata, /* up= */ false);
}
int manager_varlink_init(Manager *m, int fd) {
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
_unused_ _cleanup_close_ int fd_close = fd; /* take possession */
@ -358,8 +313,6 @@ int manager_varlink_init(Manager *m, int fd) {
"io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id,
"io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors,
"io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage,
"io.systemd.Network.LinkUp", vl_method_link_up,
"io.systemd.Network.LinkDown", vl_method_link_down,
"io.systemd.service.Ping", varlink_method_ping,
"io.systemd.service.SetLogLevel", varlink_method_set_log_level,
"io.systemd.service.GetEnvironment", varlink_method_get_environment);

View File

@ -46,7 +46,6 @@
#include "networkd-state-file.h"
#include "networkd-wifi.h"
#include "networkd-wiphy.h"
#include "networkd-wwan-bus.h"
#include "ordered-set.h"
#include "qdisc.h"
#include "set.h"
@ -97,8 +96,6 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r
if (m->product_uuid_requested)
(void) manager_request_product_uuid(m);
(void) manager_notify_mm_bus_connected(m);
return 0;
}
@ -148,8 +145,6 @@ static int manager_connect_bus(Manager *m) {
if (r < 0)
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
(void) manager_match_mm_signals(m);
return 0;
}
@ -738,9 +733,6 @@ Manager* manager_free(Manager *m) {
set_free(m->rules);
sd_bus_slot_unref(m->slot_mm);
hashmap_free(m->modems_by_path);
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
sd_netlink_unref(m->nfnl);

View File

@ -99,10 +99,6 @@ typedef struct Manager {
Hashmap *wiphy_by_index;
Hashmap *wiphy_by_name;
/* ModemManager support */
sd_bus_slot *slot_mm;
Hashmap *modems_by_path;
/* For link speed meter */
bool use_speed_meter;
sd_event_source *speed_meter_event_source;

View File

@ -40,7 +40,6 @@ _Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
#include "networkd-radv.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-wwan.h"
#include "qdisc.h"
#include "socket-util.h"
#include "tclass.h"
@ -493,9 +492,6 @@ CAN.ClassicDataLengthCode, config_parse_can_control_mode,
CAN.Termination, config_parse_can_termination, 0, 0
IPoIB.Mode, config_parse_ipoib_mode, 0, offsetof(Network, ipoib_mode)
IPoIB.IgnoreUserspaceMulticastGroups, config_parse_tristate, 0, offsetof(Network, ipoib_umcast)
ModemManager.SimpleConnectProperties, config_parse_strv, 0, offsetof(Network, mm_simple_connect_props)
ModemManager.RouteMetric, config_parse_mm_route_metric, 0, 0
ModemManager.UseGateway, config_parse_tristate, 0, offsetof(Network, mm_use_gateway)
QDisc.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0

View File

@ -512,8 +512,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
.ipoib_umcast = -1,
.mm_use_gateway = -1,
};
r = config_parse_many_full(
@ -553,7 +551,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"LLDP\0"
"TrafficControlQueueingDiscipline\0"
"CAN\0"
"ModemManager\0"
"QDisc\0"
"BFIFO\0"
"CAKE\0"
@ -850,9 +847,6 @@ static Network *network_free(Network *network) {
hashmap_free(network->qdiscs_by_section);
hashmap_free(network->tclasses_by_section);
/* ModemManager */
strv_free(network->mm_simple_connect_props);
return mfree(network);
}

View File

@ -414,12 +414,6 @@ typedef struct Network {
/* NTP */
char **ntp;
/* ModemManager support */
char **mm_simple_connect_props;
int mm_use_gateway;
uint32_t mm_route_metric;
bool mm_route_metric_set;
} Network;
DECLARE_TRIVIAL_REF_UNREF_FUNC(Network, network);

View File

@ -5,9 +5,7 @@
#include <netinet/in.h>
#include "sd-netlink.h"
#include "sd-varlink.h"
#include "alloc-util.h"
#include "device-private.h"
#include "missing-network.h"
#include "netif-util.h"
@ -1343,103 +1341,6 @@ int link_up_or_down_now(Link *link, bool up) {
return 0;
}
typedef struct SetLinkVarlinkContext {
Link *link;
sd_varlink *vlink;
bool up;
} SetLinkVarlinkContext;
static SetLinkVarlinkContext* set_link_varlink_context_free(SetLinkVarlinkContext *ctx) {
if (!ctx)
return NULL;
if (ctx->vlink)
sd_varlink_unref(ctx->vlink);
if (ctx->link)
link_unref(ctx->link);
return mfree(ctx);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(SetLinkVarlinkContext*, set_link_varlink_context_free);
static void set_link_varlink_context_destroy(SetLinkVarlinkContext *ctx) {
set_link_varlink_context_free(ctx);
}
static int link_up_or_down_now_varlink_handler(sd_netlink *rtnl, sd_netlink_message *m, SetLinkVarlinkContext *ctx) {
int r;
assert(m);
assert(ctx);
Link *link = ASSERT_PTR(ctx->link);
sd_varlink *vlink = ASSERT_PTR(ctx->vlink);
bool up = ctx->up;
assert(link->set_flags_messages > 0);
link->set_flags_messages--;
r = sd_netlink_message_get_errno(m);
if (r < 0) {
(void) sd_varlink_error_errno(vlink, r);
log_link_message_warning_errno(link, m, r, "Could not bring %s interface", up_or_down(up));
} else
(void) sd_varlink_reply(vlink, NULL);
if (link->state == LINK_STATE_LINGER)
return 0;
r = link_call_getlink(link, get_link_update_flag_handler);
if (r < 0) {
link_enter_failed(link);
return 0;
}
link->set_flags_messages++;
return 0;
}
int link_up_or_down_now_by_varlink(Link *link, bool up, sd_varlink *vlink) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
log_link_debug(link, "Bringing link %s (varlink)", up_or_down(up));
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set link flags: %m");
_cleanup_(set_link_varlink_context_freep) SetLinkVarlinkContext *ctx = new(SetLinkVarlinkContext, 1);
if (!ctx)
return log_oom();
*ctx = (SetLinkVarlinkContext) {
.link = link_ref(link),
.vlink = sd_varlink_ref(vlink),
.up = up,
};
r = netlink_call_async(link->manager->rtnl, NULL, req,
link_up_or_down_now_varlink_handler,
set_link_varlink_context_destroy,
ctx);
if (r < 0)
return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
TAKE_PTR(ctx);
link->set_flags_messages++;
return 0;
}
int link_down_slave_links(Link *link) {
Link *slave;
int r;

View File

@ -22,7 +22,6 @@ int link_request_to_activate(Link *link);
int link_request_to_bring_up_or_down(Link *link, bool up);
int link_up_or_down_now(Link *link, bool up);
int link_up_or_down_now_by_varlink(Link *link, bool up, sd_varlink *vlink);
static inline int link_up_now(Link *link) {
return link_up_or_down_now(link, true);
}

View File

@ -23,7 +23,6 @@
#include "networkd-network.h"
#include "networkd-ntp.h"
#include "networkd-state-file.h"
#include "networkd-wwan.h"
#include "ordered-set.h"
#include "set.h"
#include "string-util.h"
@ -110,14 +109,6 @@ static int link_put_dns(Link *link, OrderedSet **s) {
if (r < 0)
return r;
Bearer *b;
if (link_get_bearer(link, &b) >= 0) {
r = ordered_set_put_dns_servers(s, link->ifindex, b->dns, b->n_dns);
if (r < 0)
return r;
}
if (link->dhcp_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
const struct in_addr *addresses;
@ -810,11 +801,6 @@ static int link_save(Link *link) {
space = false;
link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
Bearer *b;
if (link_get_bearer(link, &b) >= 0)
link_save_dns(link, f, b->dns, b->n_dns, &space);
/* DNR resolvers are not required to provide Do53 service, however resolved doesn't
* know how to handle such a server so for now Do53 service is required, and
* assumed. */

View File

@ -25,7 +25,6 @@ static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX
[NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
[NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
[NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
[NETWORK_CONFIG_SOURCE_MODEM_MANAGER] = "ModemManager",
};
DEFINE_STRING_TABLE_LOOKUP(network_config_source, NetworkConfigSource);

View File

@ -14,7 +14,6 @@ typedef enum NetworkConfigSource {
NETWORK_CONFIG_SOURCE_DHCP_PD,
NETWORK_CONFIG_SOURCE_NDISC,
NETWORK_CONFIG_SOURCE_RUNTIME, /* through D-Bus method */
NETWORK_CONFIG_SOURCE_MODEM_MANAGER,
_NETWORK_CONFIG_SOURCE_MAX,
_NETWORK_CONFIG_SOURCE_INVALID = -EINVAL,
} NetworkConfigSource;

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
typedef struct Manager Manager;
typedef struct Link Link;
/* From ModemManager-enums.h */
typedef enum {
MM_BEARER_IP_FAMILY_NONE = 0,
MM_BEARER_IP_FAMILY_IPV4 = 1 << 0,
MM_BEARER_IP_FAMILY_IPV6 = 1 << 1,
MM_BEARER_IP_FAMILY_IPV4V6 = 1 << 2,
MM_BEARER_IP_FAMILY_ANY = 0xFFFFFFFF,
} MMBearerIpFamily;
typedef enum {
MM_BEARER_TYPE_UNKNOWN = 0,
MM_BEARER_TYPE_DEFAULT = 1,
MM_BEARER_TYPE_DEFAULT_ATTACH = 2,
MM_BEARER_TYPE_DEDICATED = 3,
} MMBearerType;
typedef enum {
MM_MODEM_STATE_FAILED = -1,
MM_MODEM_STATE_UNKNOWN = 0,
MM_MODEM_STATE_INITIALIZING = 1,
MM_MODEM_STATE_LOCKED = 2,
MM_MODEM_STATE_DISABLED = 3,
MM_MODEM_STATE_DISABLING = 4,
MM_MODEM_STATE_ENABLING = 5,
MM_MODEM_STATE_ENABLED = 6,
MM_MODEM_STATE_SEARCHING = 7,
MM_MODEM_STATE_REGISTERED = 8,
MM_MODEM_STATE_DISCONNECTING = 9,
MM_MODEM_STATE_CONNECTING = 10,
MM_MODEM_STATE_CONNECTED = 11,
} MMModemState;
typedef enum { /*< underscore_name=mm_modem_state_failed_reason >*/
MM_MODEM_STATE_FAILED_REASON_NONE = 0,
MM_MODEM_STATE_FAILED_REASON_UNKNOWN = 1,
MM_MODEM_STATE_FAILED_REASON_SIM_MISSING = 2,
MM_MODEM_STATE_FAILED_REASON_SIM_ERROR = 3,
MM_MODEM_STATE_FAILED_REASON_UNKNOWN_CAPABILITIES = 4,
MM_MODEM_STATE_FAILED_REASON_ESIM_WITHOUT_PROFILES = 5,
__MM_MODEM_STATE_FAILED_REASON_MAX = 6,
} MMModemStateFailedReason;
typedef enum {
MM_BEARER_IP_METHOD_UNKNOWN = 0,
MM_BEARER_IP_METHOD_PPP = 1,
MM_BEARER_IP_METHOD_STATIC = 2,
MM_BEARER_IP_METHOD_DHCP = 3,
} MMBearerIpMethod;
typedef enum { /*< underscore_name=mm_modem_port_type >*/
MM_MODEM_PORT_TYPE_UNKNOWN = 1,
MM_MODEM_PORT_TYPE_NET = 2,
MM_MODEM_PORT_TYPE_AT = 3,
MM_MODEM_PORT_TYPE_QCDM = 4,
MM_MODEM_PORT_TYPE_GPS = 5,
MM_MODEM_PORT_TYPE_QMI = 6,
MM_MODEM_PORT_TYPE_MBIM = 7,
MM_MODEM_PORT_TYPE_AUDIO = 8,
MM_MODEM_PORT_TYPE_IGNORED = 9,
MM_MODEM_PORT_TYPE_XMMRPC = 10,
} MMModemPortType;
typedef enum { /*< underscore_name=mm_bearer_allowed_auth >*/
MM_BEARER_ALLOWED_AUTH_UNKNOWN = 0,
/* bits 0..4 order match Ericsson device bitmap */
MM_BEARER_ALLOWED_AUTH_NONE = 1 << 0,
MM_BEARER_ALLOWED_AUTH_PAP = 1 << 1,
MM_BEARER_ALLOWED_AUTH_CHAP = 1 << 2,
MM_BEARER_ALLOWED_AUTH_MSCHAP = 1 << 3,
MM_BEARER_ALLOWED_AUTH_MSCHAPV2 = 1 << 4,
MM_BEARER_ALLOWED_AUTH_EAP = 1 << 5,
} MMBearerAllowedAuth;
typedef enum {
MODEM_RECONNECT_DONE, /* No reconnect is required, e.g. connected. */
MODEM_RECONNECT_SCHEDULED, /* Reconnect is in progress. */
MODEM_RECONNECT_WAITING, /* Waiting for modem to recover. */
} ModemReconnectState;
int manager_notify_mm_bus_connected(Manager *manager);
int manager_match_mm_signals(Manager *manager);
int link_modem_reconfigure(Link *link);

View File

@ -1,641 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "bus-util.h"
#include "hashmap.h"
#include "networkd-address.h"
#include "networkd-dhcp4.h"
#include "networkd-dhcp6.h"
#include "networkd-link.h"
#include "networkd-setlink.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "networkd-route.h"
#include "networkd-wwan.h"
#include "parse-util.h"
#include "sd-dhcp-client.h"
#include "sd-dhcp6-client.h"
#include "sd-ndisc.h"
#include "set.h"
#include "string-util.h"
Bearer* bearer_free(Bearer *b) {
if (!b)
return NULL;
if (b->modem) {
if (b->path)
hashmap_remove_value(b->modem->bearers_by_path, b->path, b);
if (b->name)
hashmap_remove_value(b->modem->bearers_by_name, b->name, b);
}
sd_bus_slot_unref(b->slot_getall);
free(b->path);
free(b->name);
free(b->apn);
in_addr_full_array_free(b->dns, b->n_dns);
return mfree(b);
}
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
bearer_hash_ops,
char,
string_hash_func,
string_compare_func,
Bearer,
bearer_free);
int bearer_new(Modem *modem, const char *path, Bearer **ret) {
_cleanup_(bearer_freep) Bearer *b = NULL;
_cleanup_free_ char *p = NULL;
int r;
assert(modem);
assert(path);
if (hashmap_contains(modem->bearers_by_path, path))
return -EEXIST;
p = strdup(path);
if (!p)
return -ENOMEM;
b = new(Bearer, 1);
if (!b)
return -ENOMEM;
*b = (Bearer) {
.modem = modem,
.path = TAKE_PTR(p),
};
r = hashmap_ensure_put(&modem->bearers_by_path, &bearer_hash_ops, b->path, b);
if (r < 0)
return r;
if (ret)
*ret = b;
TAKE_PTR(b);
return 0;
}
int bearer_set_name(Bearer *b, const char *name) {
Bearer *old;
int r;
assert(b);
assert(b->modem);
assert(name);
if (streq_ptr(b->name, name))
return 0;
if (b->name)
hashmap_remove_value(b->modem->bearers_by_name, b->name, b);
if (isempty(name)) {
b->name = mfree(b->name);
return 0;
}
r = free_and_strdup(&b->name, name);
if (r < 0)
return r;
/*
* FIXME: it is possible during reconnect that an interface is already
* registered in the hash map: if simple connect options
* are changed, e.g. externally modified .network file and then
* reloaded with 'networkctl reload'. This may create a new bearer
* attached to the same interface name, e.g. "wwan0". The order in which
* we parse the bearer properties is undetermined and it can be that we
* need to raplce the old one with the new one now, so only one bearer
* with the given interface name exists.
*/
old = hashmap_get(b->modem->bearers_by_name, name);
if (old) {
hashmap_remove_value(old->modem->bearers_by_name, name, old);
old->name = mfree(old->name);
}
return hashmap_ensure_put(&b->modem->bearers_by_name, &bearer_hash_ops, b->name, b);
}
int bearer_get_by_path(Manager *manager, const char *path, Modem **ret_modem, Bearer **ret_bearer) {
Modem *modem;
Bearer *b;
assert(manager);
assert(path);
HASHMAP_FOREACH(modem, manager->modems_by_path) {
b = hashmap_get(modem->bearers_by_path, path);
if (!b)
continue;
if (ret_bearer)
*ret_bearer = b;
if (ret_modem)
*ret_modem = modem;
return 0;
}
return -ENOENT;
}
Modem* modem_free(Modem *modem) {
if (!modem)
return NULL;
if (modem->bearers_by_name)
hashmap_free(modem->bearers_by_name);
if (modem->bearers_by_path)
hashmap_free(modem->bearers_by_path);
if (modem->manager)
hashmap_remove_value(modem->manager->modems_by_path, modem->path, modem);
sd_bus_slot_unref(modem->slot_propertieschanged);
sd_bus_slot_unref(modem->slot_statechanged);
sd_bus_slot_unref(modem->slot_connect);
free(modem->path);
free(modem->manufacturer);
free(modem->model);
free(modem->port_name);
return mfree(modem);
}
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
modems_hash_ops,
char,
string_hash_func,
string_compare_func,
Modem,
modem_free);
int modem_new(Manager *m, const char *path, Modem **ret) {
_cleanup_(modem_freep) Modem *modem = NULL;
_cleanup_free_ char *p = NULL;
int r;
assert(m);
assert(path);
if (hashmap_contains(m->modems_by_path, path))
return -EEXIST;
p = strdup(path);
if (!p)
return -ENOMEM;
modem = new(Modem, 1);
if (!modem)
return -ENOMEM;
*modem = (Modem) {
.manager = m,
.path = TAKE_PTR(p),
};
r = hashmap_ensure_put(&m->modems_by_path, &modems_hash_ops, modem->path, modem);
if (r < 0)
return r;
if (ret)
*ret = modem;
TAKE_PTR(modem);
return 0;
}
int modem_get_by_path(Manager *m, const char *path, Modem **ret) {
Modem *modem;
assert(m);
assert(path);
modem = hashmap_get(m->modems_by_path, path);
if (!modem)
return -ENOENT;
if (ret)
*ret = modem;
return 0;
}
int link_get_modem(Link *link, Modem **ret) {
Modem *modem;
assert(link);
assert(link->manager);
assert(link->ifname);
HASHMAP_FOREACH(modem, link->manager->modems_by_path)
if (modem->port_name && streq(modem->port_name, link->ifname)) {
*ret = modem;
return 0;
}
return -ENOENT;
}
int link_get_bearer(Link *link, Bearer **ret) {
Modem *modem;
assert(link);
assert(link->manager);
assert(link->ifname);
HASHMAP_FOREACH(modem, link->manager->modems_by_path) {
Bearer *b;
b = hashmap_get(modem->bearers_by_name, link->ifname);
if (!b)
continue;
if (ret)
*ret = b;
return 0;
}
return -ENOENT;
}
int link_dhcp_enabled_by_bearer(Link *link, int family) {
Bearer *b;
int r;
assert(link);
assert(IN_SET(family, AF_INET, AF_INET6));
r = link_get_bearer(link, &b);
if (r < 0)
return r;
if (!b->connected)
return false;
if (!FLAGS_SET(b->ip_type, family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6))
return false;
return (family == AF_INET ? b->ip4_method : b->ip6_method) == MM_BEARER_IP_METHOD_DHCP;
}
static int bearer_address_handler(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
Address *address) {
int r;
assert(link);
r = address_configure_handler_internal(m, link, address);
if (r <= 0)
return r;
if (link->bearer_messages == 0) {
link->bearer_configured = true;
link_check_ready(link);
}
return 0;
}
static int link_request_bearer_address(
Link *link,
int family,
const union in_addr_union *addr,
unsigned prefixlen) {
_cleanup_(address_unrefp) Address *address = NULL;
Address *existing;
int r;
assert(link);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(addr);
if (!in_addr_is_set(family, addr))
return 0;
r = address_new(&address);
if (r < 0)
return log_oom();
address->source = NETWORK_CONFIG_SOURCE_MODEM_MANAGER;
address->family = family;
address->in_addr = *addr;
address->prefixlen = prefixlen;
if (address_get(link, address, &existing) < 0) /* The address is new. */
link->bearer_configured = false;
else
address_unmark(existing);
r = link_request_address(link, address, &link->bearer_messages,
bearer_address_handler, /* ret = */ NULL);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request address provided by bearer: %m");
return 0;
}
static int bearer_route_handler(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
Route *route) {
int r;
assert(link);
r = route_configure_handler_internal(m, req, route);
if (r <= 0)
return r;
if (link->bearer_messages == 0) {
link->bearer_configured = true;
link_check_ready(link);
}
return 0;
}
static int link_request_bearer_route(
Link *link,
int family,
const union in_addr_union *gw,
const union in_addr_union *prefsrc) {
_cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
assert(link);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(gw);
assert(prefsrc);
if (!in_addr_is_set(family, gw))
return 0;
if (link->network->mm_use_gateway == 0)
return 0;
r = route_new(&route);
if (r < 0)
return log_oom();
route->source = NETWORK_CONFIG_SOURCE_MODEM_MANAGER;
route->family = family;
route->nexthop.family = family;
route->nexthop.gw = *gw;
if (link->network->mm_route_metric_set) {
route->priority = link->network->mm_route_metric;
route->priority_set = true;
}
if (prefsrc)
route->prefsrc = *prefsrc;
if (route_get(link->manager, route, &existing) < 0) /* This is a new route. */
link->bearer_configured = false;
else
route_unmark(existing);
r = link_request_route(link, route, &link->bearer_messages, bearer_route_handler);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request gateway provided by bearer: %m");
return 0;
}
static int link_apply_bearer_impl(Link *link, Bearer *b) {
Address *address;
Route *route;
int r, ret = 0;
assert(link);
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
/* First, mark bearer configs. */
SET_FOREACH(address, link->addresses) {
if (address->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
continue;
address_mark(address);
}
SET_FOREACH(route, link->manager->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
continue;
route_mark(route);
}
if (b && FLAGS_SET(b->ip_type, ADDRESS_FAMILY_IPV4)) {
if (b->connected && b->ip4_method == MM_BEARER_IP_METHOD_STATIC) {
r = link_request_bearer_address(link, AF_INET, &b->ip4_address, b->ip4_prefixlen);
if (r < 0)
return r;
r = link_request_bearer_route(link, AF_INET, &b->ip4_gateway, &b->ip4_address);
if (r < 0)
return r;
}
if (b->connected && b->ip4_method == MM_BEARER_IP_METHOD_DHCP) {
if (!link_dhcp4_enabled(link))
log_link_notice(link, "The WWAN connection requested DHCPv4 client, but it is disabled.");
r = dhcp4_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m");
} else {
r = sd_dhcp_client_stop(link->dhcp_client);
if (r < 0)
ret = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
}
}
if (b && FLAGS_SET(b->ip_type, ADDRESS_FAMILY_IPV6)) {
if (b->connected && b->ip6_method == MM_BEARER_IP_METHOD_STATIC) {
r = link_request_bearer_address(link, AF_INET6, &b->ip6_address, b->ip6_prefixlen);
if (r < 0)
return r;
r = link_request_bearer_route(link, AF_INET6, &b->ip6_gateway, NULL);
if (r < 0)
return r;
}
if (b->connected && b->ip6_method == MM_BEARER_IP_METHOD_DHCP) {
if (!link_ndisc_enabled(link) && !link_dhcp6_enabled(link))
log_link_notice(link,
"The WWAN connection requested IPv6 dynamic address configuration,"
"but both IPv6 Router Discovery and DHCPv6 client are disabled.");
r = ndisc_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
r = dhcp6_start(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m");
} else {
r = sd_dhcp6_client_stop(link->dhcp6_client);
if (r < 0)
ret = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
r = sd_ndisc_stop(link->ndisc);
if (r < 0)
ret = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
}
}
/* Finally, remove all marked configs. */
SET_FOREACH(address, link->addresses) {
if (address->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
continue;
if (!address_is_marked(address))
continue;
r = address_remove(address, link);
if (r < 0)
ret = r;
}
SET_FOREACH(route, link->manager->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_MODEM_MANAGER)
continue;
if (!route_is_marked(route))
continue;
r = route_remove(route, link->manager);
if (ret)
ret = r;
}
if (ret < 0)
return ret;
if (link->bearer_messages == 0)
link->bearer_configured = true;
if (!link->bearer_configured)
link_set_state(link, LINK_STATE_CONFIGURING);
link_check_ready(link);
return 0;
}
int link_apply_bearer(Link *link) {
Bearer *b = NULL;
int r;
assert(link);
(void) link_get_bearer(link, &b);
r = link_apply_bearer_impl(link, b);
if (r < 0)
link_enter_failed(link);
return r;
}
int bearer_update_link(Bearer *b) {
Link *link;
int r;
assert(b);
assert(b->modem);
assert(b->modem->manager);
if (!b->name)
return 0;
if (link_get_by_name(b->modem->manager, b->name, &link) < 0)
return 0;
r = link_apply_bearer_impl(link, b);
if (r < 0)
link_enter_failed(link);
/*
* Need to bring up the interface after the modem has connected.
* This is because ModemManger does the following while connecting:
* <msg> [1755871777.322239] [modem2] state changed (registered -> connecting)
* <dbg> [1755871777.325012] [modem2/bearer5] launching connection with QMI port (cdc-wdm0) and data port (wwan0) (multiplex none)
* <dbg> [1755871777.327665] [cdc-wdm0/qmi] bringing down data interface 'wwan0'
* <dbg> [1755871777.330108] [modem2/wwan0/net] interface index: 9
* <dbg> [1755871777.335265] [cdc-wdm0/qmi] deleting all links in data interface 'wwan0'
*/
r = link_request_to_bring_up_or_down(link, b->connected);
if (r < 0)
link_enter_failed(link);
return 0;
}
void bearer_drop(Bearer *b) {
assert(b);
b->connected = false;
b->apn = mfree(b->apn);
(void) bearer_update_link(b);
bearer_free(b);
}
int config_parse_mm_route_metric(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
network->mm_route_metric_set = false;
return 0;
}
r = safe_atou32(rvalue, &network->mm_route_metric);
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
network->mm_route_metric_set = true;
return 0;
}

View File

@ -1,80 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser-forward.h"
#include "in-addr-util.h"
#include "network-util.h"
#include "networkd-wwan-bus.h"
typedef struct Modem Modem;
typedef struct Bearer {
Modem *modem;
sd_bus_slot *slot_getall; /* for GetAll method */
char *path; /* DBus path e.g /org/freedesktop/ModemManager/Bearer/0 */
char *name; /* Interface property, e.g. wwan0 */
char *apn; /* "apn" field in Properties */
AddressFamily ip_type; /* "ip-type" field in Properties */
/* Ip4Config or IP6Config property */
MMBearerIpMethod ip4_method;
MMBearerIpMethod ip6_method;
unsigned ip4_prefixlen;
unsigned ip6_prefixlen;
union in_addr_union ip4_address;
union in_addr_union ip6_address;
union in_addr_union ip4_gateway;
union in_addr_union ip6_gateway;
struct in_addr_full **dns;
size_t n_dns;
uint32_t ip4_mtu;
uint32_t ip6_mtu;
bool connected; /* Connected property */
} Bearer;
typedef struct Modem {
Manager *manager;
sd_bus_slot *slot_propertieschanged;
sd_bus_slot *slot_statechanged;
sd_bus_slot *slot_connect;
char *path; /* DBus path e.g /org/freedesktop/ModemManager/Modem/0 */
char *manufacturer; /* The "Manufacturer" property */
char *model; /* The "Model" property */
char *port_name; /* MM_MODEM_PORT_TYPE_NET of Ports property */
Hashmap *bearers_by_path;
Hashmap *bearers_by_name;
MMModemState state;
MMModemStateFailedReason state_fail_reason;
ModemReconnectState reconnect_state;
} Modem;
int bearer_new(Modem *modem, const char *path, Bearer **ret);
Bearer* bearer_free(Bearer *b);
DEFINE_TRIVIAL_CLEANUP_FUNC(Bearer*, bearer_free);
int bearer_set_name(Bearer *b, const char *name);
int bearer_get_by_path(Manager *manager, const char *path, Modem **ret_modem, Bearer **ret_bearer);
int link_get_bearer(Link *link, Bearer **ret);
int link_dhcp_enabled_by_bearer(Link *link, int family);
int link_apply_bearer(Link *link);
int bearer_update_link(Bearer *b);
void bearer_drop(Bearer *b);
int modem_new(Manager *m, const char *path, Modem **ret);
Modem* modem_free(Modem *modem);
DEFINE_TRIVIAL_CLEANUP_FUNC(Modem*, modem_free);
int modem_get_by_path(Manager *m, const char *path, Modem **ret);
int link_get_modem(Link *link, Modem **ret);
CONFIG_PARSER_PROTOTYPE(config_parse_mm_route_metric);

View File

@ -194,15 +194,4 @@
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
</action>
<action id="org.freedesktop.network1.manage-links">
<description gettext-domain="systemd">Manage network links</description>
<message gettext-domain="systemd">Authentication is required to manage network links.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
</action>
</policyconfig>

View File

@ -541,8 +541,9 @@ static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t
log_error_errno(r, "Failed to select any cgroups under %s based on pressure, ignoring: %m", t->path);
else {
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one.
* If r == 0 then the cgroup is already queued for kill by an earlier iteration.
* In either case, go through the event loop again and select a new candidate if
* If r == 0 then it means there were not eligible candidates, the candidate cgroup
* disappeared, or the candidate cgroup has no processes by the time we tried to kill
* it. In either case, go through the event loop again and select a new candidate if
* pressure is still high. */
m->mem_pressure_post_action_delay_start = usec_now;
if (selected && r > 0) {

View File

@ -494,20 +494,12 @@ int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) {
r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks);
if (r < 0)
return log_oom_debug();
if (r == 0) {
/* The cgroup is already queued. Drop only this temporary object, because running the normal
* cleanup path would remove by cgroup path key and could interfere with the existing queued
* kill state. */
oomd_cgroup_context_unref(ks->ctx);
ks = mfree(ks);
return 0;
}
r = oomd_prekill_hook(m, ks);
if (r < 0)
log_warning_errno(r, "oomd prekill hook failed for %s, ignoring: %m", ctx->path);
return 1;
return 0;
}
typedef void (*dump_candidate_func)(const OomdCGroupContext *ctx, FILE *f, const char *prefix);

View File

@ -5404,7 +5404,6 @@ static int vl_method_read_event_log(sd_varlink *link, sd_json_variant *parameter
int r;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
if (r != 0)

View File

@ -10324,12 +10324,14 @@ static int vl_method_list_candidate_devices(
int r;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
BlockDevice *l = NULL;
size_t n = 0;
CLEANUP_ARRAY(l, n, block_device_array_free);

View File

@ -21,4 +21,3 @@ struct ConfigPerfItem;
Delegate.DNS, config_parse_delegate_dns_servers, 0, 0
Delegate.Domains, config_parse_delegate_domains, 0, 0
Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route)
Delegate.FirewallMark, config_parse_unsigned, 0, offsetof(DnsDelegate, fwmark)

View File

@ -23,8 +23,6 @@ typedef struct DnsDelegate {
int default_route;
uint32_t fwmark;
DnsScope *scope;
LIST_FIELDS(DnsDelegate, delegates);

View File

@ -475,12 +475,6 @@ static int dns_scope_socket(
return r;
}
if (s->delegate && s->delegate->fwmark > 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_MARK, s->delegate->fwmark);
if (r < 0)
return log_debug_errno(r, "Failed to set firewall mark on DNS socket: %m)");
}
bool addr_is_nonlocal = s->link &&
!manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0;

View File

@ -1374,7 +1374,7 @@ int dns_server_dump_configuration_to_json(DnsServer *server, sd_json_variant **r
return sd_json_buildo(
ret,
JSON_BUILD_PAIR_STRING_NON_EMPTY("addressString", dns_server_string(server)),
JSON_BUILD_PAIR_IN_ADDR("address", server->family, &server->address),
JSON_BUILD_PAIR_IN_ADDR("address", &server->address, server->family),
SD_JSON_BUILD_PAIR_INTEGER("family", server->family),
SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)),
SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)),

View File

@ -1214,7 +1214,10 @@ static int vl_method_browse_services(sd_varlink* link, sd_json_variant* paramete
int r = 0;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
/* if the client didn't set the more flag, it is using us incorrectly */
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link)));
@ -1236,7 +1239,9 @@ static int vl_method_subscribe_query_results(sd_varlink *link, sd_json_variant *
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
int r;
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
/* if the client didn't set the more flag, it is using us incorrectly */
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-query-results");
if (r <= 0)
@ -1377,7 +1382,9 @@ static int vl_method_subscribe_dns_configuration(sd_varlink *link, sd_json_varia
Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link)));
int r;
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
/* if the client didn't set the more flag, it is using us incorrectly */
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-dns-configuration");
if (r <= 0)

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#if HAVE_APPARMOR
#include <syslog.h>
#include "alloc-util.h"
@ -65,3 +67,4 @@ bool mac_apparmor_use(void) {
return (cached_use = true);
}
#endif

View File

@ -831,6 +831,10 @@ int ask_password_agent(
_cleanup_close_ int socket_fd = -EBADF, signal_fd = -EBADF, inotify_fd = -EBADF, dfd = -EBADF;
_cleanup_(unlink_and_freep) char *socket_name = NULL;
_cleanup_free_ char *temp = NULL, *final = NULL;
_cleanup_strv_free_erase_ char **l = NULL;
_cleanup_fclose_ FILE *f = NULL;
sigset_t mask, oldmask;
int r;
assert(req);
@ -846,59 +850,64 @@ int ask_password_agent(
if (req->flag_file)
return -EOPNOTSUPP;
_cleanup_free_ char *askpwdir = NULL;
r = get_ask_password_directory_for_flags(flags, &askpwdir);
if (r < 0)
return r;
if (r == 0)
return -ENXIO;
dfd = open_mkdir(askpwdir, O_CLOEXEC, 0755);
if (dfd < 0)
return log_debug_errno(dfd, "Failed to open directory '%s': %m", askpwdir);
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req->keyring) {
r = ask_password_keyring(req, flags, ret);
if (r != -ENOKEY)
return r;
inotify_fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
if (inotify_fd < 0)
return -errno;
r = inotify_add_watch_fd(inotify_fd, dfd, IN_ONLYDIR|IN_ATTRIB /* for mtime */);
if (r < 0)
return r;
}
sigset_t mask, oldmask;
_unused_ _cleanup_(block_signals_reset) sigset_t *saved_ssp = NULL;
assert_se(sigemptyset(&mask) >= 0);
assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
saved_ssp = &oldmask;
_cleanup_free_ char *fname = NULL, *final = NULL;
_cleanup_fclose_ FILE *f = NULL;
if (asprintf(&final, "ask.%" PRIu64, random_u64()) < 0)
return -ENOMEM;
r = fopen_temporary_at(dfd, final, &f, &fname);
_cleanup_free_ char *askpwdir = NULL;
r = get_ask_password_directory_for_flags(flags, &askpwdir);
if (r < 0)
return r;
goto finish;
if (r == 0) {
r = -ENXIO;
goto finish;
}
CLEANUP_TMPFILE_AT(dfd, fname);
dfd = open_mkdir(askpwdir, O_RDONLY|O_CLOEXEC, 0755);
if (dfd < 0) {
r = log_debug_errno(dfd, "Failed to open directory '%s': %m", askpwdir);
goto finish;
}
if (FLAGS_SET(flags, ASK_PASSWORD_ACCEPT_CACHED) && req->keyring) {
r = ask_password_keyring(req, flags, ret);
if (r >= 0) {
r = 0;
goto finish;
} else if (r != -ENOKEY)
goto finish;
inotify_fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
if (inotify_fd < 0) {
r = -errno;
goto finish;
}
r = inotify_add_watch_fd(inotify_fd, dfd, IN_ONLYDIR|IN_ATTRIB /* for mtime */);
if (r < 0)
goto finish;
}
if (asprintf(&final, "ask.%" PRIu64, random_u64()) < 0) {
r = -ENOMEM;
goto finish;
}
r = fopen_temporary_at(dfd, final, &f, &temp);
if (r < 0)
goto finish;
signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
if (signal_fd < 0)
return -errno;
if (signal_fd < 0) {
r = -errno;
goto finish;
}
socket_fd = create_socket(askpwdir, &socket_name);
if (socket_fd < 0)
return socket_fd;
if (socket_fd < 0) {
r = socket_fd;
goto finish;
}
fprintf(f,
"[Ask]\n"
@ -924,19 +933,21 @@ int ask_password_agent(
if (req->id)
fprintf(f, "Id=%s\n", req->id);
if (fchmod(fileno(f), 0644) < 0)
return -errno;
if (fchmod(fileno(f), 0644) < 0) {
r = -errno;
goto finish;
}
r = fflush_and_check(f);
if (r < 0)
return r;
goto finish;
/* Paranoia: never clobber an ongoing request */
r = rename_noreplace(dfd, fname, dfd, final);
if (r < 0)
return r;
if (renameat(dfd, temp, dfd, final) < 0) {
r = -errno;
goto finish;
}
free_and_replace(fname, final);
temp = mfree(temp);
enum {
POLL_SOCKET,
@ -965,10 +976,13 @@ int ask_password_agent(
assert(n_pollfd <= _POLL_MAX);
_cleanup_strv_free_erase_ char **l = NULL;
for (;;) {
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
char passphrase[LINE_MAX+1];
struct iovec iovec;
struct ucred *ucred;
usec_t timeout;
ssize_t n;
if (req->until > 0)
timeout = usec_sub_unsigned(req->until, now(CLOCK_MONOTONIC));
@ -979,34 +993,45 @@ int ask_password_agent(
if (r == -EINTR)
continue;
if (r < 0)
return r;
if (r == 0)
return -ETIME;
goto finish;
if (r == 0) {
r = -ETIME;
goto finish;
}
if (pollfd[POLL_SIGNAL].revents & POLLIN)
return -EINTR;
if (pollfd[POLL_SIGNAL].revents & POLLIN) {
r = -EINTR;
goto finish;
}
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP)
return -ECONNRESET;
if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) {
r = -ECONNRESET;
goto finish;
}
if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) {
(void) flush_fd(inotify_fd);
if (req->keyring) {
r = ask_password_keyring(req, flags, ret);
if (r != -ENOKEY)
return r;
if (r >= 0) {
r = 0;
goto finish;
} else if (r != -ENOKEY)
goto finish;
}
}
if (pollfd[POLL_SOCKET].revents == 0)
continue;
if (pollfd[POLL_SOCKET].revents != POLLIN)
return -EIO;
char passphrase[LINE_MAX+1];
struct iovec iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
if (pollfd[POLL_SOCKET].revents != POLLIN) {
r = -EIO;
goto finish;
}
iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
@ -1014,7 +1039,7 @@ int ask_password_agent(
.msg_controllen = sizeof(control),
};
ssize_t n = recvmsg_safe(socket_fd, &msghdr, 0);
n = recvmsg_safe(socket_fd, &msghdr, 0);
if (ERRNO_IS_NEG_TRANSIENT(n))
continue;
if (n == -ECHRNG) {
@ -1025,30 +1050,30 @@ int ask_password_agent(
log_debug_errno(n, "Got message with truncated payload data, ignoring.");
continue;
}
if (n < 0)
return n;
if (n < 0) {
r = (int) n;
goto finish;
}
CLEANUP_ERASE(passphrase);
cmsg_close_all(&msghdr);
if (n == 0) {
log_debug("Got empty reply from ask-password agent, ignoring.");
log_debug("Message too short");
continue;
}
struct ucred *ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred) {
log_debug("Received message without credentials, ignoring.");
continue;
}
if (ucred->uid != getuid() && ucred->uid != 0) {
log_debug("Got password response from bad user, ignoring.");
log_debug("Received message without credentials. Ignoring.");
continue;
}
if (passphrase[0] == '-')
return -ECANCELED;
if (ucred->uid != getuid() && ucred->uid != 0) {
log_debug("Got response from bad user. Ignoring.");
continue;
}
if (passphrase[0] == '+') {
/* An empty message refers to the empty password */
@ -1056,23 +1081,45 @@ int ask_password_agent(
l = strv_new("");
else
l = strv_parse_nulstr(passphrase+1, n-1);
if (!l)
return -ENOMEM;
if (!strv_isempty(l))
break;
l = strv_free(l);
if (!l) {
r = -ENOMEM;
goto finish;
}
log_debug("Got invalid response from ask-password agent, ignoring.");
if (strv_isempty(l)) {
l = strv_free(l);
log_debug("Invalid packet");
continue;
}
break;
}
if (passphrase[0] == '-') {
r = -ECANCELED;
goto finish;
}
log_debug("Invalid packet");
}
if (req->keyring)
(void) add_to_keyring_and_log(req->keyring, flags, l);
*ret = TAKE_PTR(l);
return 0;
r = 0;
finish:
if (temp) {
assert(dfd >= 0);
(void) unlinkat(dfd, temp, 0);
} else if (final) {
assert(dfd >= 0);
(void) unlinkat(dfd, final, 0);
}
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
return r;
}
static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret) {

View File

@ -3,6 +3,7 @@
shared_sources = files(
'acl-util.c',
'acpi-fpdt.c',
'apparmor-util.c',
'ask-password-agent.c',
'ask-password-api.c',
'async.c',
@ -278,10 +279,6 @@ if conf.get('HAVE_LIBIDN2') == 1
shared_sources += files('idn-util.c')
endif
if conf.get('HAVE_APPARMOR') == 1
shared_sources += files('apparmor-util.c')
endif
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
ip_protocol_list_txt = custom_target(
input : [generate_ip_protocol_list, ipproto_sources],

View File

@ -11,7 +11,6 @@ int metrics_setup_varlink_server(
sd_varlink_server **server, /* in and out param */
sd_varlink_server_flags_t flags,
sd_event *event,
int64_t priority,
sd_varlink_method_t vl_method_list_cb,
sd_varlink_method_t vl_method_describe_cb,
void *userdata) {
@ -21,8 +20,6 @@ int metrics_setup_varlink_server(
assert(server);
assert(event);
assert(vl_method_list_cb);
assert(vl_method_describe_cb);
if (*server)
return 0;
@ -37,21 +34,24 @@ int metrics_setup_varlink_server(
r = sd_varlink_server_bind_method_many(
s,
"io.systemd.Metrics.List", vl_method_list_cb,
"io.systemd.Metrics.Describe", vl_method_describe_cb);
"io.systemd.Metrics.List",
vl_method_list_cb,
"io.systemd.Metrics.Describe",
vl_method_describe_cb);
if (r < 0)
return log_debug_errno(r, "Failed to register varlink metrics methods: %m");
r = sd_varlink_server_set_description(s, "varlink-metrics");
r = sd_varlink_server_set_description(s, "systemd varlink metrics server");
if (r < 0)
return log_debug_errno(r, "Failed to set varlink metrics server description: %m");
r = sd_varlink_server_attach_event(s, event, priority);
r = sd_varlink_server_attach_event(s, event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
return log_debug_errno(r, "Failed to attach varlink metrics server to event loop: %m");
*server = TAKE_PTR(s);
return 1;
return 0;
}
static const char * const metric_family_type_table[_METRIC_FAMILY_TYPE_MAX] = {
@ -84,12 +84,14 @@ int metrics_method_describe(
assert(metric_family_table);
assert(link);
assert(parameters);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
if (r < 0)
return r;
@ -121,12 +123,14 @@ int metrics_method_list(
assert(metric_family_table);
assert(link);
assert(parameters);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
if (r != 0)
return r;
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric");
if (r < 0)
return r;

View File

@ -31,7 +31,6 @@ int metrics_setup_varlink_server(
sd_varlink_server **server, /* in and out param */
sd_varlink_server_flags_t flags,
sd_event *event,
int64_t priority,
sd_varlink_method_t vl_method_list_cb,
sd_varlink_method_t vl_method_describe_cb,
void *userdata);

View File

@ -240,8 +240,6 @@ static int archive_unpack_regular(
if (fd < 0)
return log_error_errno(fd, "Failed to create regular file '%s': %m", path);
CLEANUP_TMPFILE_AT(parent_fd, tmp);
if ((fflags & CHATTR_EARLY_FL) != 0) {
r = chattr_full(fd,
/* path= */ NULL,
@ -252,29 +250,45 @@ static int archive_unpack_regular(
CHATTR_FALLBACK_BITWISE);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
log_warning_errno(r, "Failed to apply chattr of '%s', ignoring: %m", path);
else if (r < 0)
return log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
else if (r < 0) {
log_error_errno(r, "Failed to adjust chattr of '%s': %m", path);
goto fail;
}
}
r = sym_archive_read_data_into_fd(a, fd);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
if (r != ARCHIVE_OK) {
r = log_error_errno(
SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to unpack regular file '%s': %s", path, sym_archive_error_string(a));
goto fail;
}
/* If this is a sparse file, then libarchive's archive_read_data_into_fd() won't insert the final
* hole. We need to manually truncate. */
off_t l = lseek(fd, 0, SEEK_CUR);
if (l < 0)
return log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
if (ftruncate(fd, l) < 0)
return log_error_errno(errno, "Failed to truncate regular file '%s' to %" PRIu64 ": %m", path, (uint64_t) l);
if (l < 0) {
r = log_error_errno(errno, "Failed to determine current file position in '%s': %m", path);
goto fail;
}
if (ftruncate(fd, l) < 0) {
r = log_error_errno(errno, "Failed to truncate regular file '%s' to %" PRIu64 ": %m", path, (uint64_t) l);
goto fail;
}
r = link_tmpfile_at(fd, parent_fd, tmp, filename, LINK_TMPFILE_REPLACE);
if (r < 0)
return log_error_errno(r, "Failed to install regular file '%s': %m", path);
if (r < 0) {
log_error_errno(r, "Failed to install regular file '%s': %m", path);
goto fail;
}
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
return TAKE_FD(fd);
fail:
if (tmp)
(void) unlinkat(parent_fd, tmp, /* flags= */ 0);
return r;
}
static int archive_unpack_directory(

View File

@ -4,9 +4,8 @@
#include "varlink-io.systemd.MuteConsole.h"
static SD_VARLINK_DEFINE_METHOD_FULL(
static SD_VARLINK_DEFINE_METHOD(
Mute,
SD_VARLINK_REQUIRES_MORE,
SD_VARLINK_FIELD_COMMENT("Whether to mute the kernel's output to the console (defaults to true)."),
SD_VARLINK_DEFINE_INPUT(kernel, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Whether to mute PID1's output to the console (defaults to true)."),

View File

@ -1,10 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "bus-polkit.h"
#include "varlink-io.systemd.Network.h"
/* Helper macro to define address fields with both binary and string representation */
#define VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
#define SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \
SD_VARLINK_FIELD_COMMENT(comment), \
SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \
SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \
@ -43,10 +42,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
RoutingPolicyRule,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"),
SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Length of destination prefix in bits"),
SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"),
@ -98,14 +97,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
Route,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0),
SD_VARLINK_FIELD_COMMENT("Destination network prefix length"),
SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Source prefix length"),
SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field"),
SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"),
@ -140,7 +139,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration source for this route"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration state of this route"),
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Interface index for serialization"),
@ -163,7 +162,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"),
SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Human-readable flags string"),
@ -178,7 +177,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration source for this next hop"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration state of this next hop"),
SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
@ -209,7 +208,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
DNS,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0),
SD_VARLINK_FIELD_COMMENT("DNS server port number"),
SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"),
@ -218,29 +217,29 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
NTP,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("NTP server"),
SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
SIP,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("SIP server domain name"),
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
Domain,
@ -248,7 +247,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
DNSSECNegativeTrustAnchor,
@ -280,7 +279,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"),
SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
NDisc,
@ -291,14 +290,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
Address,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Network prefix length"),
SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("Configuration source for this address"),
SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"),
SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Human-readable scope string"),
@ -324,7 +323,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
Neighbor,
SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"),
SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0),
SD_VARLINK_FIELD_COMMENT("Link layer (MAC) address of the neighbor"),
SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"),
@ -387,7 +386,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
DHCPServerLease,
SD_VARLINK_FIELD_COMMENT("DHCP client identifier"),
SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Hostname provided by the DHCP client"),
SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"),
@ -448,7 +447,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Broadcast address for Ethernet interfaces"),
SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"),
SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),
@ -594,22 +593,6 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_FIELD_COMMENT("Whether persistent storage is ready and writable"),
SD_VARLINK_DEFINE_INPUT(Ready, SD_VARLINK_BOOL, 0));
static SD_VARLINK_DEFINE_METHOD(
LinkUp,
SD_VARLINK_FIELD_COMMENT("Index of the interface. If specified together with InterfaceName, both must reference the same link."),
SD_VARLINK_DEFINE_INPUT(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Name of the interface. If specified together with InterfaceIndex, both must reference the same link."),
SD_VARLINK_DEFINE_INPUT(InterfaceName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_POLKIT_INPUT);
static SD_VARLINK_DEFINE_METHOD(
LinkDown,
SD_VARLINK_FIELD_COMMENT("Index of the interface. If specified together with InterfaceName, both must reference the same link."),
SD_VARLINK_DEFINE_INPUT(InterfaceIndex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Name of the interface. If specified together with InterfaceIndex, both must reference the same link."),
SD_VARLINK_DEFINE_INPUT(InterfaceName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_POLKIT_INPUT);
static SD_VARLINK_DEFINE_ERROR(StorageReadOnly);
SD_VARLINK_DEFINE_INTERFACE(
@ -620,10 +603,6 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_method_GetNamespaceId,
&vl_method_GetLLDPNeighbors,
&vl_method_SetPersistentStorage,
SD_VARLINK_SYMBOL_COMMENT("Bring the specified link up."),
&vl_method_LinkUp,
SD_VARLINK_SYMBOL_COMMENT("Bring the specified link down."),
&vl_method_LinkDown,
&vl_type_Address,
&vl_type_DHCPLease,
&vl_type_DHCPServer,

View File

@ -59,9 +59,8 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a progress percentrage (specific to the work done for the specified phase+object is sent in progress updates."),
SD_VARLINK_DEFINE_OUTPUT(progress, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD_FULL(
static SD_VARLINK_DEFINE_METHOD(
ListCandidateDevices,
SD_VARLINK_REQUIRES_MORE,
SD_VARLINK_FIELD_COMMENT("Control whether to include the root disk of the currently booted OS in the list. Defaults to false, i.e. the root disk is included."),
SD_VARLINK_DEFINE_INPUT(ignoreRoot, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Control whether to include block devices with zero size in the list, i.e. typically block devices without any inserted medium. Defaults to false, i.e. empty block devices are included."),

View File

@ -300,7 +300,7 @@ static SD_VARLINK_DEFINE_METHOD(
static SD_VARLINK_DEFINE_METHOD_FULL(
BrowseServices,
SD_VARLINK_REQUIRES_MORE,
SD_VARLINK_SUPPORTS_MORE,
SD_VARLINK_FIELD_COMMENT("The domain to browse for services. If null, the default browsing domain local is used."),
SD_VARLINK_DEFINE_INPUT(domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."),

View File

@ -179,8 +179,6 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD_BY_TYPE(SocketBindDeny, CGroupSocketBind, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#RestrictNetworkInterfaces="),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(RestrictNetworkInterfaces, CGroupRestrictNetworkInterfaces, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#BindNetworkInterface="),
SD_VARLINK_DEFINE_FIELD(BindNetworkInterface, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#NFTSet=family:table:set"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(NFTSet, CGroupNFTSet, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),

View File

@ -1,73 +1,78 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-event.h"
#include "alloc-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fdset.h"
#include "log.h"
#include "serialize.h"
#include "parse-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "varlink-internal.h"
#include "varlink-serialize.h"
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) {
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
if (!s)
return 0;
const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server";
LIST_FOREACH(sockets, ss, s->sockets) {
int copy;
assert(ss->address);
assert(ss->fd >= 0);
fprintf(f, "varlink-server-socket-address=%s", ss->address);
/* If we fail to serialize the fd, it will be considered an error during deserialization */
int copy = fdset_put_dup(fds, ss->fd);
copy = fdset_put_dup(fds, ss->fd);
if (copy < 0)
return copy;
fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy);
fprintf(f, " varlink-server-socket-fd=%i", copy);
fputc('\n', f);
}
return 0;
}
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) {
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
_cleanup_free_ char *address = NULL;
_cleanup_close_ int fd = -EBADF;
const char *v;
int r;
/* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */
const char *v = ASSERT_PTR(value);
int r, fd = -EBADF;
char *buf;
size_t n;
assert(s);
assert(value);
assert(fds);
v = startswith(value, "socket-address=");
if (!v)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid varlink server serialization entry: %s", value);
n = strcspn(v, " ");
address = strndup(v, n);
if (!address)
return log_oom_debug();
r = extract_first_word(&v, &address, " ", /* flags = */ 0);
if (r <= 0)
return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA),
"Failed to extract socket address from varlink serialization: %s", value);
if (v)
v = startswith(v, "varlink-server-socket-fd=");
if (v[n] != ' ')
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
"Failed to deserialize sd_varlink_server_socket: %s", value);
v = startswith(v + n + 1, "varlink-server-socket-fd=");
if (!v)
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
"Got varlink serialization without socket fd, refusing.");
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
"Failed to deserialize VarlinkServerSocket fd: %s", value);
fd = deserialize_fd(fds, v);
n = strcspn(v, " ");
buf = strndupa_safe(v, n);
fd = parse_fd(buf);
if (fd < 0)
return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m");
return varlink_server_log_errno(s, fd, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf);
if (!fdset_contains(fds, fd))
return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
"VarlinkServerSocket varlink-server-socket-fd= has unknown fd: %d", fd);
/* NB: varlink_server_socket_free() does not close the fd! */
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
ss = new(VarlinkServerSocket, 1);
if (!ss)
return log_oom_debug();
@ -75,16 +80,14 @@ int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSe
*ss = (VarlinkServerSocket) {
.server = s,
.address = TAKE_PTR(address),
.fd = fd,
.fd = fdset_remove(fds, fd),
};
r = varlink_server_add_socket_event_source(s, ss);
r = varlink_server_add_socket_event_source(s, ss, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m");
LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
TAKE_FD(fd); /* ownership is now transferred to varlink server */
return 0;
}

View File

@ -3,7 +3,7 @@
#include "shared-forward.h"
int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds);
int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds);
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds);
bool varlink_server_contains_socket(sd_varlink_server *s, const char *address);

View File

@ -2749,7 +2749,6 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl
int r;
assert(link);
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
const char *class = NULL;
r = sd_varlink_dispatch(link, parameters, dispatch_table, &class);

View File

@ -149,7 +149,6 @@ simple_tests += files(
'test-mkdir.c',
'test-modhex.c',
'test-mountpoint-util.c',
'test-namespace-util.c',
'test-net-naming-scheme.c',
'test-notify-recv.c',
'test-nsresource.c',

View File

@ -1,48 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "capability-util.h"
#include "errno-util.h"
#include "pidref.h"
#include "process-util.h"
#include "fd-util.h"
#include "namespace-util.h"
#include "tests.h"
TEST(namespace_enter) {
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
r = pidref_safe_fork(
"test-ns-enter-1",
FORK_NEW_USERNS|FORK_NEW_MOUNTNS|FORK_LOG|FORK_FREEZE|FORK_DEATHSIG_SIGKILL,
&pidref);
if (ERRNO_IS_NEG_PRIVILEGE(r))
return (void) log_tests_skipped_errno(r, "Unable to unshare user namespace");
ASSERT_OK(r);
_cleanup_close_ int mntns_fd = -EBADF, userns_fd = -EBADF, root_fd = -EBADF;
ASSERT_OK(pidref_namespace_open(&pidref, NULL, &mntns_fd, NULL, &userns_fd, &root_fd));
r = ASSERT_OK(pidref_safe_fork(
"test-ns-enter-2",
FORK_LOG|FORK_WAIT|FORK_DEATHSIG_SIGKILL,
NULL));
if (r == 0) {
ASSERT_OK(namespace_enter(-EBADF, mntns_fd, -EBADF, userns_fd, root_fd));
_exit(EXIT_SUCCESS);
}
/* Make sure we can enter the namespaces as well if we don't have CAP_SYS_ADMIN. */
r = ASSERT_OK(pidref_safe_fork(
"test-ns-enter-3",
FORK_LOG|FORK_WAIT|FORK_DEATHSIG_SIGKILL,
NULL));
if (r == 0) {
ASSERT_OK(drop_capability(CAP_SYS_ADMIN));
ASSERT_OK(namespace_enter(-EBADF, mntns_fd, -EBADF, userns_fd, root_fd));
_exit(EXIT_SUCCESS);
}
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -15,9 +15,9 @@ TEST(manager_parse_string) {
assert_se(manager_new(&m) == 0);
assert_se(!m->fallback_set);
assert_se(!m->have_fallbacks);
assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0);
assert_se(m->fallback_set);
assert_se(m->have_fallbacks);
assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0);
assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);

View File

@ -20,7 +20,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers;
if (type == SERVER_FALLBACK)
m->fallback_set = true;
m->have_fallbacks = true;
for (;;) {
_cleanup_free_ char *word = NULL;
@ -59,7 +59,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
}
int manager_parse_fallback_string(Manager *m, const char *string) {
if (m->fallback_set)
if (m->have_fallbacks)
return 0;
return manager_parse_server_string(m, SERVER_FALLBACK, string);
@ -84,22 +84,16 @@ int config_parse_servers(
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
if (isempty(rvalue))
manager_flush_server_names(m, ltype);
/* FallbackNTP= with an empty string disables the built-in fallback servers. */
if (ltype == SERVER_FALLBACK)
m->fallback_set = true;
return 0;
}
else {
r = manager_parse_server_string(m, ltype, rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse NTP server string '%s', ignoring: %m", rvalue);
return 0;
}
}
return 0;
}

View File

@ -33,7 +33,7 @@ typedef struct Manager {
RateLimit ratelimit;
bool exhausted_servers;
bool fallback_set; /* Indicate if FallbackNTP= is explicitly configured. */
bool have_fallbacks;
/* network */
sd_event_source *network_event_source;

View File

@ -1452,7 +1452,6 @@ testcase_delegate() {
[Delegate]
DNS=192.168.77.78
Domains=exercise.test
FirewallMark=42
EOF
systemctl reload systemd-resolved
resolvectl status

View File

@ -573,4 +573,3 @@ loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="rebo
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"]
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]
varlinkctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--system"]
systemd.network.xml ./refsect1[title="[ModemManager] Section Options"]/variablelist/varlistentry[term="SimpleConnectProperties="]