Compare commits
31 Commits
08b8f29a25
...
9efa8a3cff
Author | SHA1 | Date |
---|---|---|
Susant Sahani | 9efa8a3cff | |
Susant Sahani | 5c95a9134a | |
Yu Watanabe | fac729f811 | |
Lennart Poettering | f6dbcebdc2 | |
Yu Watanabe | 8abbd9a4d9 | |
Yu Watanabe | 27cd09442f | |
Yu Watanabe | cfbee85ce2 | |
Yu Watanabe | 63ef9d31fd | |
Yu Watanabe | 63b00fa77d | |
Lennart Poettering | bfafec253c | |
Lennart Poettering | ccdf03b9c7 | |
Lennart Poettering | 4a56315a99 | |
Lennart Poettering | 6527b019fc | |
Lennart Poettering | 871dc8d644 | |
Lennart Poettering | a745117dba | |
Lennart Poettering | 70d8586365 | |
Lennart Poettering | 5a7cf2e9d8 | |
Lennart Poettering | b0d0e0ef98 | |
Lennart Poettering | 08ab18618e | |
Lennart Poettering | 43007b302e | |
Lennart Poettering | a3d19f5d99 | |
Lennart Poettering | 35a3eb9bdc | |
Lennart Poettering | 5abee64ed4 | |
Dan Streetman | 0fc0d85fae | |
Dan Streetman | 9bacf4313e | |
Dan Streetman | 6b8a1aa6a3 | |
Dan Streetman | bd0d471c8f | |
Lennart Poettering | 8dd7cbce42 | |
Lennart Poettering | 2c905207db | |
Lennart Poettering | 5aec5c751a | |
Lennart Poettering | ab19db01ae |
324
NEWS
324
NEWS
|
@ -1,6 +1,92 @@
|
|||
systemd System and Service Manager
|
||||
|
||||
CHANGES WITH 246 in spe:
|
||||
|
||||
* The various programs included in systemd can now optionally output
|
||||
their log messages on stderr prefixed with a timestamp, controlled by
|
||||
the $SYSTEMD_LOG_TIME environment variable.
|
||||
|
||||
* A new boolean kernel command line option systemd.swap= has been
|
||||
added, which may be used to turn off automatic activation of swap
|
||||
devices, as listed in /etc/fstab.
|
||||
|
||||
* The CPUAffinity= setting in service unit files now supports a new
|
||||
special value "numa". If used, the NUMA mask is copied into the CPU
|
||||
affinity mask.
|
||||
|
||||
* The man pages for the sd-bus and sd-hwdb APIs have been completed.
|
||||
|
||||
* networkctl gained the new "forcerenew" command for forcing all DHCP
|
||||
server clients to renew their lease. The interface "status" output
|
||||
will now show numerous additional fields of information about an
|
||||
interface. There are new "up" and "down" commands to bring specific
|
||||
interfaces up or down.
|
||||
|
||||
* systemd-networkd's [IPv6Prefix] section in .network files gained a
|
||||
new boolean setting Assign=. If enabled an address from the prefix is
|
||||
automatically assigned to the interface.
|
||||
|
||||
* systemd-networkd's [Network] section gained a new setting
|
||||
IPv6PDSubnetId= that allows explicit configuration of the preferred
|
||||
subnet that networkd's Prefix Delegation logic assigns to an
|
||||
interfaces.
|
||||
|
||||
* systemd-networkd gained support for configuring the HTB queuing
|
||||
discipline in the [HierarchyTokenBucket] and
|
||||
[HierarchyTokenBucketClass] sections. Similar the "pfifo" qdisc may
|
||||
be configured in the [PFIFO] section, "GRED" in
|
||||
[GenericRandomEarlyDetection], "SFB" in [StochasticFairBlue], "cake"
|
||||
in [CAKE], "PIE" in [PIE], "DRR" in [DeficitRoundRobinScheduler] and
|
||||
[DeficitRoundRobinSchedulerClass], "BFIFO" in [BFIFO],
|
||||
"PFIFOHeadDrop" in [PFIFOHeadDrop], "PFIFOFast" in [PFIFOFast] and
|
||||
"HHF" in [HeavyHitterFilter].
|
||||
|
||||
* systemd-networkd gained support for a new Termination= setting in the
|
||||
[CAN] section for configuring the termination resistor. It also
|
||||
gained a new ListenOnly= setting for controlling whether to only
|
||||
listen on CAN interfaces, without interfering with traffic otherwise
|
||||
(which is useful for debugging/monitoring CAN network
|
||||
traffic). DataBitRate=, DataSamplePoint=, FDMode=, FDNonISO= have
|
||||
been added to configure various CAN-FD aspects.
|
||||
|
||||
* .link files managed by systemd-udevd gained options RxFlowControl=,
|
||||
TxFlowControl=, AutoNegotiationFlowControl= in the [Link] section, in
|
||||
order to configure various flow control parameters. They also gained
|
||||
RxMiniBufferSize= and RxJumboBufferSize= in order to configure jumbo
|
||||
frame ring buffer sizes.
|
||||
|
||||
* systemd-networkd's [DHCPv6] section gained a new WithoutRA= boolean
|
||||
setting. If enabled, DHCPv6 will be attempted right-away without
|
||||
requiring an Router Advertisement packet suggesting it
|
||||
first. Conversely, the [IPv6AcceptRA] gained a boolean option
|
||||
DHCPv6Client= that may be used to turn off the DHCPv6 client even if
|
||||
the RA packets suggest it.
|
||||
|
||||
* systemd-networkd's [DHCPv4] section gained a new setting UseGateway=
|
||||
which may be used to turn off use of the gateway information provided
|
||||
by the DHCP lease. A new FallbackLeaseLifetimeSec= setting may be
|
||||
used to configure how to process leases that lack a lifetime option.
|
||||
|
||||
* systemd-networkd's [DHCPv4] and [DHCPServer] sections gained a new
|
||||
setting SendVendorOption= allowing configuration of additional vendor
|
||||
options to send in the DHCP requests/responses. The [DHCPv6] section
|
||||
gained a new SendOption= setting for sending arbitrary DHCP
|
||||
options. RequestOptions= has been added to request arbitrary options
|
||||
from the server. UserClass= has been added to set the DHCP user class
|
||||
field.
|
||||
|
||||
* systemd-networkd's [DHCPServer] section gained a new set of options
|
||||
POP3Servers=, SMTPServers=, LPRServers= for including server
|
||||
information about these three protocols in the DHCP lease. It also
|
||||
gained support for including "MUD" URLs ("Manufacturer Usage
|
||||
Description"). Support for "MUD" URLs was also added to the LLDP
|
||||
stack, configurable in the [LLDP] section in .network files.
|
||||
|
||||
* systemd-resolved's DNS= configuration option now optionally accepts
|
||||
DNS server addresses suffixed by "#" followed by a host name. If
|
||||
used, the DNS-over-TLS certificate is validated to match the
|
||||
specified hostname.
|
||||
|
||||
* The fs.suid_dumpable sysctl is set to 2 / "suidsafe". This allows
|
||||
systemd-coredump to save core files for suid processes. When saving
|
||||
the core file, systemd-coredump will use the effective uid and gid of
|
||||
|
@ -14,6 +100,244 @@ CHANGES WITH 246 in spe:
|
|||
can now be suspended or resumed either using new systemctl verbs,
|
||||
freeze and thaw respectively, or via D-Bus.
|
||||
|
||||
* A new sd-path.h API has been added to libsystemd. It provides a
|
||||
simple API for retrieving various search paths and primary
|
||||
directories for various resources.
|
||||
|
||||
* The sd-bus API gained a number of convenience functions that take
|
||||
va_list arguments rather than "...". For example, there's now
|
||||
sd_bus_call_methodv() to match sd_bus_call_method(). Previously,
|
||||
these were missing since the calls are convenience calls only and
|
||||
could be put together from the more low-level functions they build
|
||||
on.
|
||||
|
||||
* sd-bus vtable entries learnt a new flag SD_BUS_VTABLE_ABSOLUTE_OFFSET
|
||||
which alters how the userdata pointer to pass to the callbacks is
|
||||
determined. If the flag is set the offset field is converted as-is
|
||||
into a pointer, without adding it to the object pointer the vtable is
|
||||
associated with.
|
||||
|
||||
* sd-bus now exposed four new functions:
|
||||
sd_bus_interface_name_is_valid() + sd_bus_service_name_is_valid() +
|
||||
sd_bus_member_name_is_valid() + sd_bus_object_path_is_valid() will
|
||||
validate strings to check if they qualify as various D-Bus concepts.
|
||||
|
||||
* systemctl gained a new "-P" switch that is a shortcut for "--value
|
||||
--property=…".
|
||||
|
||||
* The expectations on user/group name syntax are now documented in
|
||||
detail; documentation how classic home directories may be converted
|
||||
into home directories managed by homed has been added; documentation
|
||||
regarding integration of homed/userdb functionality in desktops has
|
||||
been added:
|
||||
|
||||
https://systemd.io/USER_NAMES
|
||||
https://systemd.io/CONVERTING_TO_HOMED
|
||||
https://systemd.io/USERDB_AND_DESKTOPS
|
||||
|
||||
* systemd-run gained a new switch --slice-inherit. If specified the
|
||||
unit it generates is placed in the same slice as the systemd-run
|
||||
process itself.
|
||||
|
||||
* service unit files now accept a new setting CoredumpFilter= which
|
||||
allows configuration of the memory sections coredumps of the
|
||||
service's processes shall include.
|
||||
|
||||
* coredumpctl gained a new --file= switch, matching the same one in
|
||||
journalctl: a specific journal file may be specified to read the
|
||||
coredump data from.
|
||||
|
||||
* Various D-Bus APIs of systemd daemons now have man pages that
|
||||
document the methods, signals and properties.
|
||||
|
||||
* journald.conf gained a new boolean setting Audit= that may be used to
|
||||
control whether systemd-journald will enable audit during
|
||||
initialization.
|
||||
|
||||
* A new default .network file is now shipped that matches TUN/TAP
|
||||
devices that begin with "vt-" in their name. Such interfaces will
|
||||
have IP routing onto the host links set up automatically. This is
|
||||
supposed to be used by VM managers to trivially acquire a network
|
||||
interface which is fully set up for host communication, simply by
|
||||
carefully picking an interface name to use.
|
||||
|
||||
* All D-Bus services shipped in systemd now implement the generic
|
||||
LogControl1 D-Bus API which allows clients to change log level +
|
||||
target of the service during runtime.
|
||||
|
||||
* systemd-nspawn's --resolv-conf= switch gained a number of new
|
||||
supported values. Specifically, options starting with "replace-" are
|
||||
like those prefixed "copy-" but replace any existing resolv.conf
|
||||
file. And options ending in "-uplink" and "-stub" can now be used to
|
||||
propagate other flavours of resolv.conf into the container (as
|
||||
defined by systemd-resolved).
|
||||
|
||||
* systemd-binfmt gained a new switch --unregister for unregistering all
|
||||
registered entries at once. This is now invoked automatically at
|
||||
shutdown, so that binary formats registered with the "F" flag will
|
||||
not block clean file system unmounting.
|
||||
|
||||
* Unit files, tmpfiles.d/ snippets, sysusers.d/ snippets and other
|
||||
configuration files that support specifier expansion learnt six new
|
||||
specifiers: %a resolves to the current architecture, %o/%w/%B/%W
|
||||
resolve to the various ID fields from /etc/os-release, %l resolves to
|
||||
the "short" hostname of the system, i.e. the kernel configured
|
||||
hostname, truncated at the first dot.
|
||||
|
||||
* systemd-notify's --pid= switch gained new values: "parent", "self",
|
||||
"auto" for controlling which PID to send to the service managing: the
|
||||
systemd-notify process' PID, or the one of the process invoking it.
|
||||
|
||||
* When sending a file descriptor (fd) to the service manager to keep
|
||||
track of, using the sd_notify() mechanism, a new parameter FDPOLL=0
|
||||
may be specified. If passed the service manager will refrain from
|
||||
poll()ing on the file descriptor. Traditionally (and when the
|
||||
parameter is not specified), the service manager will poll it for
|
||||
POLLHUP or POLLERR events, and immediately close the fds in that
|
||||
case.
|
||||
|
||||
* A new call sd_notify_barrier() has been added to the sd-daemon.h
|
||||
API. The call will block until all previously sent sd_notify()
|
||||
messages have been processed by the service manager. This is useful
|
||||
to remove races caused by a process already having disappeared at the
|
||||
time a notification message is processed by the service manager,
|
||||
making correct attribution impossible. The systemd-notify tool will
|
||||
now make use of this call implicitly, but this can be turned off again
|
||||
via the new --no-block switch.
|
||||
|
||||
* systemd-logind's Session bus object learnt a new method call
|
||||
SetType() for temporarily updating the session type of an already
|
||||
allocated session. This is useful for upgrading tty sessions to
|
||||
graphical ones once a compositor is invoked.
|
||||
|
||||
* .mount units gained a new ReadWriteOnly= boolean option. If set the
|
||||
it will not be attempted to mount a file system read-only if mounting
|
||||
it read-write mode doesn't succeed. An option x-systemd.rw-only is
|
||||
available in /etc/fstab to control the same.
|
||||
|
||||
* coredumps collected by systemd-coredump may now be compressed using
|
||||
the zstd algorithm.
|
||||
|
||||
* journalctl's "-o cat" output mode will now show one or more journal
|
||||
fields specified with --output-fields= instead of unconditionally
|
||||
MESSAGE=. This is useful to retrieve a very specific set of fields
|
||||
without any decoration.
|
||||
|
||||
* systemd-socket-proxy gained a new switch --exit-idle-time= for
|
||||
configuring an exit-on-idle time.
|
||||
|
||||
* systemd-homed's LUKS backend gained the ability to discard empty file
|
||||
system blocks automatically when the user logs out. This is enabled
|
||||
by default to ensure that home directories take minimal space when
|
||||
logged out but get full size guarantees when logged in. This may be
|
||||
controlled with the new --luks-offline-discard= switch to homectl.
|
||||
|
||||
* If systemd-homed detects that /home/ is encrypted as a whole it will
|
||||
now default to the directory or subvolume backends instead of the
|
||||
LUKS backend, in order to avoid double encryption. The default
|
||||
storage and file system may now be configured explicitly, too, via
|
||||
the new /etc/systemd/homed.conf configuration file.
|
||||
|
||||
* when systemd-journald's log stream is broken up into multiple lines
|
||||
because the PID of the sender changed this is indicated in the
|
||||
generated log records via the _LINE_BREAK=pid-change field.
|
||||
|
||||
* systemd-networkd's .netdev files now support a new setting
|
||||
VLANProtocol= in the [Bridge] section that allows configuration of
|
||||
the VLAN protocol to use.
|
||||
|
||||
* systemd-repart's --empty= setting gained a new value "create". If
|
||||
specified a new empty regular disk image file is created under the
|
||||
specified name. It's size may be specified with the new --size=
|
||||
option. The latter is also supported without the "create" mode, in
|
||||
order to grow existing disk image files to the specified size. These
|
||||
two new options make are useful when creating or manipulating
|
||||
disk images instead of operating on actual block devices.
|
||||
|
||||
* systemd-repart drop-ins now support a new UUID= setting to control
|
||||
the UUID to assign to a newly created partition.
|
||||
|
||||
* StandardError= and StandardOutput= in unit files no longer support
|
||||
the "syslog" and "syslog-console" switches. They were long removed
|
||||
from the documentation, but will now result in warnings when used,
|
||||
and be converted to "journal" and "journal+console" automatically.
|
||||
|
||||
* systemd-networkd supports a new Group= setting in the [Link] section
|
||||
of the .network files, to control the link group.
|
||||
|
||||
* Two new unit file settings
|
||||
ConditionPathIsEncrypted=/AssertPathIsEncrypted= have been
|
||||
added. They may be used to check whether a specific file system path
|
||||
resides on a block device that is encrypted on the block level
|
||||
(i.e. using dm-crypt/LUKS).
|
||||
|
||||
* Another pair of new settings ConditionEnvironment=/AssertEnvironment=
|
||||
has been added that may be used for simple environment checks. This
|
||||
is particularly useful when passing in environment variables from a
|
||||
container manager (or from PAM in case of the systemd --user
|
||||
instance).
|
||||
|
||||
* The /sys/module/kernel/parameters/crash_kexec_post_notifiers file is
|
||||
not automatically set to "Y" at boot, in order to enable pstore
|
||||
generation for collection with systemd-pstore.
|
||||
|
||||
* New kernel command line options systemd.condition-needs-update= and
|
||||
systemd.condition-first-boot= have been added, which override the
|
||||
result of the ConditionNeedsUpdate= and ConditionFirstBoot=
|
||||
conditions.
|
||||
|
||||
* A new kernel command line option systemd.clock-usec= has been added
|
||||
that allows setting the system clock to the specified time in µs
|
||||
since Jan 1st, 1970 early during boot. This is in particular useful
|
||||
in order to make test cases more reliable.
|
||||
|
||||
* A new kernel command line option systemd.hostname= has been added
|
||||
that allows controlling the hostname that is initialized early during
|
||||
boot.
|
||||
|
||||
* The /etc/crypttab tmp option now optionally takes an argument
|
||||
selecting the file system to use. Moreover, the default is now
|
||||
changed from ext2 to ext4.
|
||||
|
||||
* There's a new /etc/crypttab option "keyfile-erase". If specified the
|
||||
key file listed in the same line is removed after use, regardless if
|
||||
volume activation was successful or not. This is useful if the key
|
||||
file is only acquired transiently at runtime and shall be erased
|
||||
before the system continues to boot.
|
||||
|
||||
* There's also a new /etc/crypttab option "try-empty-password". If
|
||||
specified, before asking the user for a password it is attempted to
|
||||
unlock the volume with an empty password. This is useful for
|
||||
installing encrypted images whose password shall be set on first boot
|
||||
instead of at installation time.
|
||||
|
||||
* systemd-cryptsetup will now attempt to load the keys to unlock
|
||||
volumes with automatically from files in
|
||||
/etc/cryptsetup-keys.d/<volume>.key and
|
||||
/run/cryptsetup-keys.d/<volume>.key, if any of these files exist.
|
||||
|
||||
* logind.conf gained a new RuntimeDirectoryInodesMax= setting to
|
||||
control the inode limit for the per-user $XDG_RUNTIME_DIR tmpfs
|
||||
instance.
|
||||
|
||||
* systemd-firstboot gained a new --root-password-hashed= parameter for
|
||||
setting the root user's password as UNIX password hash. There's a new
|
||||
--delete-root-password switch which instead of setting a password for
|
||||
the root user, removes it so that log-in without a password is
|
||||
permitted. There's now --force which if specified means any existing
|
||||
configuration is overwritten by the specified settings. It also
|
||||
gained a new --kernel-command-line= parameter which may be used to
|
||||
set the /etc/kernel/cmdline file of an OS image.
|
||||
|
||||
* A new generator systemd-xdg-autostart-generator has been added. It
|
||||
automatically generates systemd unit files from XDG autostart
|
||||
.desktop files, and is useful for allowing systemd to manage services
|
||||
defined that way safely and automatically.
|
||||
|
||||
* systemd will now log about all left-over processes remaining in a
|
||||
unit when the unit is stopped. It will now warn about services using
|
||||
KillMode=none, as this is generally an unsafe thing to make use of.
|
||||
|
||||
CHANGES WITH 245:
|
||||
|
||||
* A new tool "systemd-repart" has been added, that operates as an
|
||||
|
|
3
TODO
3
TODO
|
@ -48,6 +48,9 @@ Features:
|
|||
* pid1: also remove PID files of a service when the service starts, not just
|
||||
when it exits
|
||||
|
||||
* systemd-path: add ESP and XBOOTLDR path. Add "private" runtime/state/cache dir enum,
|
||||
mapping to $RUNTIME_DIRECTORY, $STATE_DIRECTORY and such
|
||||
|
||||
* make "systemd-dissect" an official supported tool, i.e. move to /usr/bin/ and
|
||||
provide man page. Given that we now have a tool that can generate images like
|
||||
this, it's useful to have one that can dump contents of them, too.
|
||||
|
|
|
@ -435,3 +435,34 @@ hyphen and otherwise fully numeric.
|
|||
For further details on strict and relaxed user/group name rules, see:
|
||||
|
||||
https://systemd.io/USER_NAMES
|
||||
|
||||
-- 1b3bb94037f04bbf81028e135a12d293
|
||||
Subject: Failed to generate valid unit name from path '@MOUNT_POINT@'.
|
||||
Defined-By: systemd
|
||||
Support: %SUPPORT_URL%
|
||||
|
||||
The following mount point path could not be converted into a valid .mount
|
||||
unit name:
|
||||
|
||||
@MOUNT_POINT@
|
||||
|
||||
Typically this means that the path to the mount point is longer than allowed
|
||||
for valid unit names.
|
||||
|
||||
systemd dynamically synthesizes .mount units for all mount points appearing on
|
||||
the system. For that a simple escaping algorithm is applied: the absolute path
|
||||
name is used, with all "/" characters replaced by "-" (the leading one is
|
||||
removed). Moreover, any non-alphanumeric characters (as well as any of ":",
|
||||
"-", "_", ".", "\") are replaced by "\xNN" where "NN" is the hexadecimal code
|
||||
of the character. Finally, ".mount" is suffixed. The resulting string must be
|
||||
under 256 characters in length to be a valid unit name. This restriction is
|
||||
made in order for all unit names to also be suitable as file names. If a mount
|
||||
point appears that — after escaping — is longer than this limit it cannot be
|
||||
mapped to a unit. In this case systemd will refrain from synthesizing a unit
|
||||
and cannot be used to manage the mount point. It will not appear in the service
|
||||
manager's unit table and thus also not be torn down safely and automatically at
|
||||
system shutdown.
|
||||
|
||||
It is generally recommended to avoid such overly long mount point paths, or —
|
||||
if used anyway – manage them independently of systemd, i.e. establish them as
|
||||
well as tear them down automatically at system shutdown by other software.
|
||||
|
|
|
@ -429,6 +429,7 @@ Most socket unit settings are available to transient units.
|
|||
✓ Broadcast=
|
||||
✓ PassCredentials=
|
||||
✓ PassSecurity=
|
||||
✓ PassPacketInfo=
|
||||
✓ TCPCongestion=
|
||||
✓ ReusePort=
|
||||
✓ MessageQueueMaxMessages=
|
||||
|
|
|
@ -76,30 +76,30 @@
|
|||
<constant>SD_PATH_SEARCH_STATE_FACTORY</constant>,
|
||||
<constant>SD_PATH_SEARCH_CONFIGURATION</constant>,
|
||||
|
||||
<constant>SD_PATH_SYSTEMD_UTIL_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_UNIT_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_PRESET_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_UNIT_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_PRESET_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_CONF_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_CONF_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_UNIT_PATH</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_UNIT_PATH</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_GENERATOR_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_GENERATOR_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_GENERATOR_PATH</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_GENERATOR_PATH</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SLEEP_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SHUTDOWN_DIR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_UTIL</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_UNIT</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_PRESET</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_UNIT</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_PRESET</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_CONF</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_CONF</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SEARCH_USER_UNIT</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SYSTEM_GENERATOR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_USER_GENERATOR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SEARCH_USER_GENERATOR</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SLEEP</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SHUTDOWN</constant>,
|
||||
|
||||
<constant>SD_PATH_TMPFILES_DIR</constant>,
|
||||
<constant>SD_PATH_SYSUSERS_DIR</constant>,
|
||||
<constant>SD_PATH_SYSCTL_DIR</constant>,
|
||||
<constant>SD_PATH_BINFMT_DIR</constant>,
|
||||
<constant>SD_PATH_MODULES_LOAD_DIR</constant>,
|
||||
<constant>SD_PATH_CATALOG_DIR</constant>,
|
||||
<constant>SD_PATH_TMPFILES</constant>,
|
||||
<constant>SD_PATH_SYSUSERS</constant>,
|
||||
<constant>SD_PATH_SYSCTL</constant>,
|
||||
<constant>SD_PATH_BINFMT</constant>,
|
||||
<constant>SD_PATH_MODULES_LOAD</constant>,
|
||||
<constant>SD_PATH_CATALOG</constant>,
|
||||
|
||||
<constant>SD_PATH_SYSTEMD_NETWORK_PATH</constant>,
|
||||
<constant>SD_PATH_SYSTEMD_SEARCH_NETWORK</constant>,
|
||||
};</funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
|
|
|
@ -838,15 +838,17 @@
|
|||
<term><varname>ConfigureWithoutCarrier=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. Allows networkd to configure a specific link even if it has no carrier.
|
||||
Defaults to false.
|
||||
Defaults to false. If <option>IgnoreCarrierLoss=</option> is not explicitly set, it will
|
||||
default to this value.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>IgnoreCarrierLoss=</varname></term>
|
||||
<listitem>
|
||||
<para>A boolean. Allows networkd to retain both the static and dynamic configuration of the
|
||||
interface even if its carrier is lost. Defaults to false.
|
||||
<para>Takes a boolean. Allows networkd to retain both the static and dynamic configuration
|
||||
of the interface even if its carrier is lost. When unset, the value specified with
|
||||
<option>ConfigureWithoutCarrier=</option> is used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -1779,6 +1781,15 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>AssignAcquiredDelegatedPrefixAddress=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. Specifies whether to add an address from the delegated prefixes which are received
|
||||
from the WAN interface by the <varname>IPv6PrefixDelegation=</varname>. When true (on LAN interfce), the EUI-64
|
||||
algorithm will be used to form an interface identifier from the delegated prefixes. Defaults to true.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PrefixDelegationHint=</varname></term>
|
||||
<listitem>
|
||||
|
@ -3299,7 +3310,10 @@ DHCP=ipv6</programlisting>
|
|||
Name=enp2s0
|
||||
|
||||
[Network]
|
||||
IPv6PrefixDelegation=dhcpv6</programlisting>
|
||||
IPv6PrefixDelegation=dhcpv6
|
||||
|
||||
[DHCPv6]
|
||||
AssignAcquiredDelegatedPrefixAddress=yes</programlisting>
|
||||
|
||||
<para>This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the
|
||||
DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.</para>
|
||||
|
|
|
@ -709,6 +709,15 @@
|
|||
Defaults to <option>false</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PassPacketInfo=</varname></term>
|
||||
<listitem><para>Takes a boolean value. This controls the <constant>IP_PKTINFO</constant>,
|
||||
<constant>IPV6_RECVPKTINFO</constant> and <constant>NETLINK_PKTINFO</constant> socket options, which
|
||||
enable reception of additional per-packet metadata as ancillary message, on
|
||||
<constant>AF_INET</constant>, <constant>AF_INET6</constant> and <constant>AF_UNIX</constant> sockets.
|
||||
Defaults to <option>false</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>TCPCongestion=</varname></term>
|
||||
<listitem><para>Takes a string value. Controls the TCP
|
||||
|
|
|
@ -62,3 +62,8 @@ struct sockaddr_vm {
|
|||
#ifndef IP_TRANSPARENT
|
||||
#define IP_TRANSPARENT 19
|
||||
#endif
|
||||
|
||||
/* linux/sockios.h */
|
||||
#ifndef SIOCGSKNS
|
||||
#define SIOCGSKNS 0x894C
|
||||
#endif
|
||||
|
|
|
@ -1174,5 +1174,27 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
|
|||
}
|
||||
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
int socket_pass_pktinfo(int fd, bool b) {
|
||||
int af;
|
||||
socklen_t sl = sizeof(af);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
|
||||
return -errno;
|
||||
|
||||
switch (af) {
|
||||
|
||||
case AF_INET:
|
||||
return setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, b);
|
||||
|
||||
case AF_INET6:
|
||||
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, b);
|
||||
|
||||
case AF_NETLINK:
|
||||
return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b);
|
||||
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,3 +220,5 @@ int socket_bind_to_ifname(int fd, const char *ifname);
|
|||
int socket_bind_to_ifindex(int fd, int ifindex);
|
||||
|
||||
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
|
||||
|
||||
int socket_pass_pktinfo(int fd, bool b);
|
||||
|
|
|
@ -207,8 +207,9 @@ UnitType unit_name_to_type(const char *n) {
|
|||
}
|
||||
|
||||
int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
|
||||
char *e, *s;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t a, b;
|
||||
char *e;
|
||||
|
||||
assert(n);
|
||||
assert(suffix);
|
||||
|
@ -230,8 +231,12 @@ int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
|
|||
return -ENOMEM;
|
||||
|
||||
strcpy(mempcpy(s, n, a), suffix);
|
||||
*ret = s;
|
||||
|
||||
/* Make sure the name is still valid (i.e. didn't grow too large due to longer suffix) */
|
||||
if (!unit_name_is_valid(s, UNIT_NAME_ANY))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -253,8 +258,8 @@ int unit_name_build(const char *prefix, const char *instance, const char *suffix
|
|||
}
|
||||
|
||||
int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *ut;
|
||||
char *s;
|
||||
|
||||
assert(prefix);
|
||||
assert(type >= 0);
|
||||
|
@ -264,19 +269,23 @@ int unit_name_build_from_type(const char *prefix, const char *instance, UnitType
|
|||
if (!unit_prefix_is_valid(prefix))
|
||||
return -EINVAL;
|
||||
|
||||
if (instance && !unit_instance_is_valid(instance))
|
||||
return -EINVAL;
|
||||
|
||||
ut = unit_type_to_string(type);
|
||||
|
||||
if (!instance)
|
||||
s = strjoin(prefix, ".", ut);
|
||||
else
|
||||
if (instance) {
|
||||
if (!unit_instance_is_valid(instance))
|
||||
return -EINVAL;
|
||||
|
||||
s = strjoin(prefix, "@", instance, ".", ut);
|
||||
} else
|
||||
s = strjoin(prefix, ".", ut);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = s;
|
||||
/* Verify that this didn't grow too large (or otherwise is invalid) */
|
||||
if (!unit_name_is_valid(s, instance ? UNIT_NAME_INSTANCE : UNIT_NAME_PLAIN))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -441,8 +450,8 @@ int unit_name_path_unescape(const char *f, char **ret) {
|
|||
}
|
||||
|
||||
int unit_name_replace_instance(const char *f, const char *i, char **ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *p, *e;
|
||||
char *s;
|
||||
size_t a, b;
|
||||
|
||||
assert(f);
|
||||
|
@ -466,7 +475,11 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret) {
|
|||
|
||||
strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e);
|
||||
|
||||
*ret = s;
|
||||
/* Make sure the resulting name still is valid, i.e. didn't grow too large */
|
||||
if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -497,8 +510,7 @@ int unit_name_template(const char *f, char **ret) {
|
|||
}
|
||||
|
||||
int unit_name_from_path(const char *path, const char *suffix, char **ret) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
char *s = NULL;
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
@ -516,7 +528,11 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) {
|
|||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = s;
|
||||
/* Refuse this if this got too long or for some other reason didn't result in a valid name */
|
||||
if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -544,6 +560,10 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha
|
|||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Refuse this if this got too long or for some other reason didn't result in a valid name */
|
||||
if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
@ -597,9 +617,9 @@ static bool do_escape_mangle(const char *f, bool allow_globs, char *t) {
|
|||
* If @allow_globs, globs characters are preserved. Otherwise, they are escaped.
|
||||
*/
|
||||
int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNameMangle flags, const char *suffix, char **ret) {
|
||||
char *s;
|
||||
int r;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
bool mangled, suggest_escape = true;
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
assert(suffix);
|
||||
|
@ -657,7 +677,12 @@ int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNa
|
|||
if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0)
|
||||
strcat(s, suffix);
|
||||
|
||||
*ret = s;
|
||||
/* Make sure mangling didn't grow this too large (but don't do this check if globbing is allowed,
|
||||
* since globs generally do not qualify as valid unit names) */
|
||||
if (!FLAGS_SET(flags, UNIT_NAME_MANGLE_GLOB) && !unit_name_is_valid(s, UNIT_NAME_ANY))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 1;
|
||||
|
||||
good:
|
||||
|
@ -665,12 +690,13 @@ good:
|
|||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = s;
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int slice_build_parent_slice(const char *slice, char **ret) {
|
||||
char *s, *dash;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
char *dash;
|
||||
int r;
|
||||
|
||||
assert(slice);
|
||||
|
@ -693,13 +719,11 @@ int slice_build_parent_slice(const char *slice, char **ret) {
|
|||
strcpy(dash, ".slice");
|
||||
else {
|
||||
r = free_and_strdup(&s, SPECIAL_ROOT_SLICE);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
*ret = TAKE_PTR(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
|||
SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassPacketInfo", "b", bus_property_get_bool, offsetof(Socket, pass_pktinfo), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -202,6 +203,9 @@ static int bus_socket_set_transient_property(
|
|||
if (streq(name, "PassSecurity"))
|
||||
return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error);
|
||||
|
||||
if (streq(name, "PassPacketInfo"))
|
||||
return bus_set_transient_bool(u, name, &s->pass_pktinfo, message, flags, error);
|
||||
|
||||
if (streq(name, "ReusePort"))
|
||||
return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);
|
||||
|
||||
|
|
|
@ -396,6 +396,7 @@ Socket.Transparent, config_parse_bool, 0,
|
|||
Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast)
|
||||
Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
|
||||
Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
|
||||
Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo)
|
||||
Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
|
||||
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
|
||||
Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
|
||||
|
|
|
@ -1674,9 +1674,30 @@ static int mount_setup_unit(
|
|||
if (!is_path(where))
|
||||
return 0;
|
||||
|
||||
/* Mount unit names have to be (like all other unit names) short enough to fit into file names. This
|
||||
* means there's a good chance that overly long mount point paths after mangling them to look like a
|
||||
* unit name would result in unit names we don't actually consider valid. This should be OK however
|
||||
* as such long mount point paths should not happen on regular systems — and if they appear
|
||||
* nonetheless they are generally synthesized by software, and thus managed by that other
|
||||
* software. Having such long names just means you cannot use systemd to manage those specific mount
|
||||
* points, which should be an OK restriction to make. After all we don't have to be able to manage
|
||||
* all mount points in the world — as long as we don't choke on them when we encounter them. */
|
||||
r = unit_name_from_path(where, ".mount", &e);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where);
|
||||
if (r < 0) {
|
||||
static RateLimit rate_limit = { /* Let's log about this at warning level at most once every
|
||||
* 5s. Given that we generate this whenever we read the file
|
||||
* otherwise we probably shouldn't flood the logs with
|
||||
* this */
|
||||
.interval = 5 * USEC_PER_SEC,
|
||||
.burst = 1,
|
||||
};
|
||||
|
||||
return log_struct_errno(
|
||||
ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE_STR,
|
||||
"MOUNT_POINT=%s", where,
|
||||
LOG_MESSAGE("Failed to generate valid unit name from path '%s', ignoring mount point: %m", where));
|
||||
}
|
||||
|
||||
u = manager_get_unit(m, e);
|
||||
if (u)
|
||||
|
@ -1686,7 +1707,7 @@ static int mount_setup_unit(
|
|||
* by the sysadmin having called mount(8) directly. */
|
||||
r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to set up mount unit: %m");
|
||||
return log_warning_errno(r, "Failed to set up mount unit for '%s': %m", where);
|
||||
|
||||
/* If the mount changed properties or state, let's notify our clients */
|
||||
if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED))
|
||||
|
|
|
@ -635,6 +635,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
|||
"%sBroadcast: %s\n"
|
||||
"%sPassCredentials: %s\n"
|
||||
"%sPassSecurity: %s\n"
|
||||
"%sPassPacketInfo: %s\n"
|
||||
"%sTCPCongestion: %s\n"
|
||||
"%sRemoveOnStop: %s\n"
|
||||
"%sWritable: %s\n"
|
||||
|
@ -654,6 +655,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
|||
prefix, yes_no(s->broadcast),
|
||||
prefix, yes_no(s->pass_cred),
|
||||
prefix, yes_no(s->pass_sec),
|
||||
prefix, yes_no(s->pass_pktinfo),
|
||||
prefix, strna(s->tcp_congestion),
|
||||
prefix, yes_no(s->remove_on_stop),
|
||||
prefix, yes_no(s->writable),
|
||||
|
@ -1070,6 +1072,12 @@ static void socket_apply_socket_options(Socket *s, int fd) {
|
|||
log_unit_warning_errno(UNIT(s), r, "SO_PASSSEC failed: %m");
|
||||
}
|
||||
|
||||
if (s->pass_pktinfo) {
|
||||
r = socket_pass_pktinfo(fd, true);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m");
|
||||
}
|
||||
|
||||
if (s->priority >= 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority);
|
||||
if (r < 0)
|
||||
|
|
|
@ -121,6 +121,7 @@ struct Socket {
|
|||
bool broadcast;
|
||||
bool pass_cred;
|
||||
bool pass_sec;
|
||||
bool pass_pktinfo;
|
||||
|
||||
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
|
||||
SocketAddressBindIPv6Only bind_ipv6_only;
|
||||
|
|
|
@ -65,16 +65,16 @@ systemdshutdowndir=${systemd_shutdown_dir}
|
|||
tmpfiles_dir=${prefix}/lib/tmpfiles.d
|
||||
tmpfilesdir=${tmpfiles_dir}
|
||||
|
||||
sysusers_dir=${prefix}/lib/sysusers.d
|
||||
sysusers_dir=${rootprefix}/lib/sysusers.d
|
||||
sysusersdir=${sysusers_dir}
|
||||
|
||||
sysctl_dir=${prefix}/lib/sysctl.d
|
||||
sysctl_dir=${rootprefix}/lib/sysctl.d
|
||||
sysctldir=${sysctl_dir}
|
||||
|
||||
binfmt_dir=${prefix}/lib/binfmt.d
|
||||
binfmt_dir=${rootprefix}/lib/binfmt.d
|
||||
binfmtdir=${binfmt_dir}
|
||||
|
||||
modules_load_dir=${prefix}/lib/modules-load.d
|
||||
modules_load_dir=${rootprefix}/lib/modules-load.d
|
||||
modulesloaddir=${modules_load_dir}
|
||||
|
||||
catalog_dir=${prefix}/lib/systemd/catalog
|
||||
|
|
|
@ -30,7 +30,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||
|
||||
assert_se(service = xdg_autostart_service_parse_desktop(name));
|
||||
assert_se(service->name = strdup("fuzz-xdg-desktop.service"));
|
||||
if (service)
|
||||
(void) xdg_autostart_service_generate_unit(service, tmpdir);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -45,7 +45,9 @@
|
|||
|
||||
#define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
|
||||
|
||||
#define REPLACE_VAR_MAX 256
|
||||
/* The maximum size of variable values we'll expand in catalog entries. We bind this to PATH_MAX for now, as
|
||||
* we want to be able to show all officially valid paths at least */
|
||||
#define REPLACE_VAR_MAX PATH_MAX
|
||||
|
||||
#define DEFAULT_DATA_THRESHOLD (64*1024)
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_
|
|||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
|
||||
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia);
|
||||
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code);
|
||||
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
|
||||
struct in6_addr **addrs, size_t count,
|
||||
size_t *allocated);
|
||||
|
|
|
@ -417,13 +417,13 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
|
||||
uint16_t iatype, optlen;
|
||||
size_t i, len;
|
||||
int r = 0, status;
|
||||
uint16_t opt;
|
||||
size_t iaaddr_offset;
|
||||
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) {
|
||||
uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX;
|
||||
uint16_t iatype, optlen;
|
||||
size_t iaaddr_offset;
|
||||
int r = 0, status;
|
||||
size_t i, len;
|
||||
uint16_t opt;
|
||||
|
||||
assert_return(ia, -EINVAL);
|
||||
assert_return(!ia->addresses, -EINVAL);
|
||||
|
@ -533,11 +533,15 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
|
|||
status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data));
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (status > 0) {
|
||||
if (ret_status_code)
|
||||
*ret_status_code = status;
|
||||
|
||||
log_dhcp6_client(client, "IA status %s",
|
||||
dhcp6_message_status_to_string(status));
|
||||
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -581,7 +585,10 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
|
|||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (ret_status_code)
|
||||
*ret_status_code = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
|
||||
|
|
|
@ -998,10 +998,11 @@ static int client_parse_message(
|
|||
size_t len,
|
||||
sd_dhcp6_lease *lease) {
|
||||
|
||||
uint16_t ia_na_status = 0, ia_pd_status = 0;
|
||||
uint32_t lt_t1 = ~0, lt_t2 = ~0;
|
||||
usec_t irt = IRT_DEFAULT;
|
||||
bool clientid = false;
|
||||
size_t pos = 0;
|
||||
usec_t irt = IRT_DEFAULT;
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
|
@ -1015,8 +1016,8 @@ static int client_parse_message(
|
|||
DHCP6Option *option = (DHCP6Option *) &message->options[pos];
|
||||
uint16_t optcode, optlen;
|
||||
be32_t iaid_lease;
|
||||
uint8_t *optval;
|
||||
int status;
|
||||
uint8_t *optval;
|
||||
|
||||
if (len < pos + offsetof(DHCP6Option, data))
|
||||
return -ENOBUFS;
|
||||
|
@ -1093,10 +1094,15 @@ static int client_parse_message(
|
|||
break;
|
||||
}
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &lease->ia);
|
||||
r = dhcp6_option_parse_ia(option, &lease->ia, &ia_na_status);
|
||||
if (r < 0 && r != -ENOMSG)
|
||||
return r;
|
||||
|
||||
if (ia_na_status == DHCP6_STATUS_NO_ADDRS_AVAIL) {
|
||||
pos += offsetof(DHCP6Option, data) + optlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
r = dhcp6_lease_get_iaid(lease, &iaid_lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1121,10 +1127,15 @@ static int client_parse_message(
|
|||
break;
|
||||
}
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &lease->pd);
|
||||
r = dhcp6_option_parse_ia(option, &lease->pd, &ia_pd_status);
|
||||
if (r < 0 && r != -ENOMSG)
|
||||
return r;
|
||||
|
||||
if (ia_pd_status == DHCP6_STATUS_NO_PREFIX_AVAIL) {
|
||||
pos += offsetof(DHCP6Option, data) + optlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1188,6 +1199,11 @@ static int client_parse_message(
|
|||
pos += offsetof(DHCP6Option, data) + optlen;
|
||||
}
|
||||
|
||||
if (ia_na_status > 0 && ia_pd_status > 0) {
|
||||
log_dhcp6_client(client, "No IA_PD prefix or IA_NA address received. Ignoring.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!clientid) {
|
||||
log_dhcp6_client(client, "%s has incomplete options",
|
||||
dhcp6_message_type_to_string(message->type));
|
||||
|
|
|
@ -252,12 +252,14 @@ static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) {
|
|||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_ipv4ll_start(sd_ipv4ll *ll) {
|
||||
assert_return(ll, -EINVAL);
|
||||
assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
|
||||
|
||||
if (sd_ipv4ll_is_running(ll))
|
||||
return 0;
|
||||
|
||||
return ipv4ll_start_internal(ll, true);
|
||||
}
|
||||
|
|
|
@ -247,17 +247,17 @@ static int test_option_status(sd_event *e) {
|
|||
option = (DHCP6Option *)option1;
|
||||
assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &ia);
|
||||
assert_se(r == -EINVAL);
|
||||
r = dhcp6_option_parse_ia(option, &ia, NULL);
|
||||
assert_se(r == 0);
|
||||
assert_se(ia.addresses == NULL);
|
||||
|
||||
option->len = htobe16(17);
|
||||
r = dhcp6_option_parse_ia(option, &ia);
|
||||
r = dhcp6_option_parse_ia(option, &ia, NULL);
|
||||
assert_se(r == -ENOBUFS);
|
||||
assert_se(ia.addresses == NULL);
|
||||
|
||||
option->len = htobe16(sizeof(DHCP6Option));
|
||||
r = dhcp6_option_parse_ia(option, &ia);
|
||||
r = dhcp6_option_parse_ia(option, &ia, NULL);
|
||||
assert_se(r == -ENOBUFS);
|
||||
assert_se(ia.addresses == NULL);
|
||||
|
||||
|
@ -265,7 +265,7 @@ static int test_option_status(sd_event *e) {
|
|||
option = (DHCP6Option *)option2;
|
||||
assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len));
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &ia);
|
||||
r = dhcp6_option_parse_ia(option, &ia, NULL);
|
||||
assert_se(r >= 0);
|
||||
assert_se(ia.addresses == NULL);
|
||||
|
||||
|
@ -273,7 +273,7 @@ static int test_option_status(sd_event *e) {
|
|||
option = (DHCP6Option *)option3;
|
||||
assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len));
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &ia);
|
||||
r = dhcp6_option_parse_ia(option, &ia, NULL);
|
||||
assert_se(r >= 0);
|
||||
assert_se(ia.addresses != NULL);
|
||||
dhcp6_lease_free_ia(&ia);
|
||||
|
@ -282,8 +282,8 @@ static int test_option_status(sd_event *e) {
|
|||
option = (DHCP6Option *)option4;
|
||||
assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len));
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &pd);
|
||||
assert_se(r == 0);
|
||||
r = dhcp6_option_parse_ia(option, &pd, NULL);
|
||||
assert_se(r >= 0);
|
||||
assert_se(pd.addresses != NULL);
|
||||
assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0);
|
||||
assert_se(memcmp(&pd.ia_pd.lifetime_t1, &option4[8], 4) == 0);
|
||||
|
@ -294,8 +294,8 @@ static int test_option_status(sd_event *e) {
|
|||
option = (DHCP6Option *)option5;
|
||||
assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len));
|
||||
|
||||
r = dhcp6_option_parse_ia(option, &pd);
|
||||
assert_se(r == 0);
|
||||
r = dhcp6_option_parse_ia(option, &pd, NULL);
|
||||
assert_se(r >= 0);
|
||||
assert_se(pd.addresses != NULL);
|
||||
dhcp6_lease_free_ia(&pd);
|
||||
|
||||
|
@ -364,15 +364,15 @@ static int test_advertise_option(sd_event *e) {
|
|||
_cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
|
||||
DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
|
||||
size_t len = sizeof(msg_advertise) - sizeof(DHCP6Message), pos = 0;
|
||||
be32_t val;
|
||||
uint8_t preference = 255;
|
||||
struct in6_addr addr;
|
||||
uint32_t lt_pref, lt_valid;
|
||||
int r;
|
||||
uint8_t *opt;
|
||||
bool opt_clientid = false;
|
||||
const struct in6_addr *addrs;
|
||||
uint8_t preference = 255;
|
||||
struct in6_addr addr;
|
||||
char **domains;
|
||||
uint8_t *opt;
|
||||
int r;
|
||||
be32_t val;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
|
@ -410,7 +410,7 @@ static int test_advertise_option(sd_event *e) {
|
|||
val = htobe32(120);
|
||||
assert_se(!memcmp(optval + 8, &val, sizeof(val)));
|
||||
|
||||
assert_se(dhcp6_option_parse_ia(option, &lease->ia) >= 0);
|
||||
assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -563,12 +563,12 @@ static int test_client_send_reply(DHCP6Message *request) {
|
|||
|
||||
static int test_client_verify_request(DHCP6Message *request, size_t len) {
|
||||
_cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
|
||||
size_t pos = 0;
|
||||
bool found_clientid = false, found_iana = false, found_serverid = false,
|
||||
found_elapsed_time = false, found_fqdn = false;
|
||||
struct in6_addr addr;
|
||||
be32_t val;
|
||||
uint32_t lt_pref, lt_valid;
|
||||
struct in6_addr addr;
|
||||
size_t pos = 0;
|
||||
be32_t val;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
|
@ -606,7 +606,7 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
|
|||
val = htobe32(120);
|
||||
assert_se(!memcmp(optval + 8, &val, sizeof(val)));
|
||||
|
||||
assert_se(!dhcp6_option_parse_ia(option, &lease->ia));
|
||||
assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0);
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -159,10 +159,10 @@ static void test_basic_request(sd_event *e) {
|
|||
assert_se(sd_ipv4ll_start(ll) == -EINVAL);
|
||||
|
||||
assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0);
|
||||
assert_se(sd_ipv4ll_start(ll) == 0);
|
||||
assert_se(sd_ipv4ll_start(ll) == 1);
|
||||
|
||||
sd_event_run(e, (uint64_t) -1);
|
||||
assert_se(sd_ipv4ll_start(ll) == -EBUSY);
|
||||
assert_se(sd_ipv4ll_start(ll) == 0);
|
||||
|
||||
assert_se(sd_ipv4ll_is_running(ll));
|
||||
|
||||
|
|
|
@ -297,6 +297,7 @@ static void test_rs(void) {
|
|||
|
||||
assert_se(sd_ndisc_stop(nd) >= 0);
|
||||
assert_se(sd_ndisc_start(nd) >= 0);
|
||||
assert_se(sd_ndisc_start(nd) >= 0);
|
||||
assert_se(sd_ndisc_stop(nd) >= 0);
|
||||
|
||||
assert_se(sd_ndisc_start(nd) >= 0);
|
||||
|
|
|
@ -715,4 +715,6 @@ global:
|
|||
|
||||
sd_path_lookup;
|
||||
sd_path_lookup_strv;
|
||||
|
||||
sd_notify_barrier;
|
||||
} LIBSYSTEMD_245;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <errno.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
|
@ -13,10 +15,12 @@
|
|||
#include "device-monitor-private.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "io-util.h"
|
||||
#include "missing_socket.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
|
@ -163,12 +167,54 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
|
|||
|
||||
if (fd >= 0) {
|
||||
r = monitor_set_nl_address(m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "sd-device-monitor: Failed to set netlink address: %m");
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "sd-device-monitor: Failed to set netlink address: %m");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_close_ int netns = -1;
|
||||
|
||||
/* So here's the thing: only AF_NETLINK sockets from the main network namespace will get
|
||||
* hardware events. Let's check if ours is from there, and if not generate a debug message,
|
||||
* since we cannot possibly work correctly otherwise. This is just a safety check to make
|
||||
* things easier to debug. */
|
||||
|
||||
netns = ioctl(m->sock, SIOCGSKNS);
|
||||
if (netns < 0)
|
||||
log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns: %m");
|
||||
else {
|
||||
struct stat a, b;
|
||||
|
||||
if (fstat(netns, &a) < 0) {
|
||||
r = log_debug_errno(errno, "sd-device-monitor: Failed to stat netns of udev netlink socket: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (stat("/proc/1/ns/net", &b) < 0) {
|
||||
if (ERRNO_IS_PRIVILEGE(errno))
|
||||
/* If we can't access PID1's netns info due to permissions, it's fine, this is a
|
||||
* safety check only after all. */
|
||||
log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns: %m");
|
||||
else
|
||||
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns: %m");
|
||||
|
||||
} else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
|
||||
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/* Let's unset the socket fd in the monitor object before we destroy it so that the fd passed in is
|
||||
* not closed on failure. */
|
||||
if (fd >= 0)
|
||||
m->sock = -1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
_public_ int sd_device_monitor_new(sd_device_monitor **ret) {
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
||||
/* For some reason we need some extra cmsg space on some kernels. It's not clear why, and one of those days
|
||||
* we need to track this down. See: https://github.com/systemd/systemd/pull/15457 */
|
||||
#define EXTRA_CMSG_SPACE 1024
|
||||
|
||||
int socket_open(int family) {
|
||||
int fd;
|
||||
|
||||
|
@ -244,7 +240,7 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
|
|||
|
||||
static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_group, bool peek) {
|
||||
union sockaddr_union sender;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct nl_pktinfo)) + EXTRA_CMSG_SPACE) control;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct nl_pktinfo))) control;
|
||||
struct msghdr msg = {
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = 1,
|
||||
|
|
|
@ -320,73 +320,73 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
|
|||
case SD_PATH_USER_DESKTOP:
|
||||
return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
|
||||
|
||||
case SD_PATH_SYSTEMD_UTIL_DIR:
|
||||
*ret = ROOTPREFIX "lib/systemd";
|
||||
case SD_PATH_SYSTEMD_UTIL:
|
||||
*ret = ROOTPREFIX "/lib/systemd";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_UNIT_DIR:
|
||||
case SD_PATH_SYSTEMD_SYSTEM_UNIT:
|
||||
*ret = SYSTEM_DATA_UNIT_PATH;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_PRESET_DIR:
|
||||
*ret = ROOTPREFIX "lib/systemd/system-preset";
|
||||
case SD_PATH_SYSTEMD_SYSTEM_PRESET:
|
||||
*ret = ROOTPREFIX "/lib/systemd/system-preset";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_USER_UNIT_DIR:
|
||||
case SD_PATH_SYSTEMD_USER_UNIT:
|
||||
*ret = USER_DATA_UNIT_DIR;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_USER_PRESET_DIR:
|
||||
*ret = ROOTPREFIX "lib/systemd/user-preset";
|
||||
case SD_PATH_SYSTEMD_USER_PRESET:
|
||||
*ret = ROOTPREFIX "/lib/systemd/user-preset";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_CONF_DIR:
|
||||
case SD_PATH_SYSTEMD_SYSTEM_CONF:
|
||||
*ret = SYSTEM_CONFIG_UNIT_DIR;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_USER_CONF_DIR:
|
||||
case SD_PATH_SYSTEMD_USER_CONF:
|
||||
*ret = USER_CONFIG_UNIT_DIR;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_GENERATOR_DIR:
|
||||
case SD_PATH_SYSTEMD_SYSTEM_GENERATOR:
|
||||
*ret = SYSTEM_GENERATOR_DIR;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_USER_GENERATOR_DIR:
|
||||
case SD_PATH_SYSTEMD_USER_GENERATOR:
|
||||
*ret = USER_GENERATOR_DIR;
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SLEEP_DIR:
|
||||
*ret = ROOTPREFIX "lib/systemd/system-sleep";
|
||||
case SD_PATH_SYSTEMD_SLEEP:
|
||||
*ret = ROOTPREFIX "/lib/systemd/system-sleep";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSTEMD_SHUTDOWN_DIR:
|
||||
*ret = ROOTPREFIX "lib/systemd/system-shutdown";
|
||||
case SD_PATH_SYSTEMD_SHUTDOWN:
|
||||
*ret = ROOTPREFIX "/lib/systemd/system-shutdown";
|
||||
return 0;
|
||||
|
||||
/* FIXME: systemd.pc uses ${prefix}, but CONF_PATHS_NULSTR doesn't.
|
||||
* Should ${prefix} use in systemd.pc be removed? */
|
||||
case SD_PATH_TMPFILES_DIR:
|
||||
case SD_PATH_TMPFILES:
|
||||
*ret = "/usr/lib/tmpfiles.d";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSUSERS_DIR:
|
||||
*ret = "/usr/lib/sysusers.d";
|
||||
case SD_PATH_SYSUSERS:
|
||||
*ret = ROOTPREFIX "/lib/sysusers.d";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_SYSCTL_DIR:
|
||||
*ret = "/usr/lib/sysctl.d";
|
||||
case SD_PATH_SYSCTL:
|
||||
*ret = ROOTPREFIX "/lib/sysctl.d";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_BINFMT_DIR:
|
||||
*ret = "/usr/lib/binfmt.d";
|
||||
case SD_PATH_BINFMT:
|
||||
*ret = ROOTPREFIX "/lib/binfmt.d";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_MODULES_LOAD_DIR:
|
||||
*ret = "/usr/lib/modules-load.d";
|
||||
case SD_PATH_MODULES_LOAD:
|
||||
*ret = ROOTPREFIX "/lib/modules-load.d";
|
||||
return 0;
|
||||
|
||||
case SD_PATH_CATALOG_DIR:
|
||||
case SD_PATH_CATALOG:
|
||||
*ret = "/usr/lib/systemd/catalog";
|
||||
return 0;
|
||||
}
|
||||
|
@ -607,10 +607,10 @@ static int get_search(uint64_t type, char ***list) {
|
|||
case SD_PATH_SEARCH_BINARIES_DEFAULT:
|
||||
return strv_from_nulstr(list, DEFAULT_PATH_NULSTR);
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_UNIT_PATH:
|
||||
case SD_PATH_SYSTEMD_USER_UNIT_PATH: {
|
||||
case SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT:
|
||||
case SD_PATH_SYSTEMD_SEARCH_USER_UNIT: {
|
||||
_cleanup_(lookup_paths_free) LookupPaths lp = {};
|
||||
const UnitFileScope scope = type == SD_PATH_SYSTEMD_SYSTEM_UNIT_PATH ?
|
||||
const UnitFileScope scope = type == SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT ?
|
||||
UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||
|
||||
r = lookup_paths_init(&lp, scope, 0, NULL);
|
||||
|
@ -621,10 +621,10 @@ static int get_search(uint64_t type, char ***list) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
case SD_PATH_SYSTEMD_SYSTEM_GENERATOR_PATH:
|
||||
case SD_PATH_SYSTEMD_USER_GENERATOR_PATH: {
|
||||
case SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR:
|
||||
case SD_PATH_SYSTEMD_SEARCH_USER_GENERATOR: {
|
||||
char **t;
|
||||
const UnitFileScope scope = type == SD_PATH_SYSTEMD_SYSTEM_GENERATOR_PATH ?
|
||||
const UnitFileScope scope = type == SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR ?
|
||||
UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||
|
||||
t = generator_binary_paths(scope);
|
||||
|
@ -635,7 +635,7 @@ static int get_search(uint64_t type, char ***list) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
case SD_PATH_SYSTEMD_NETWORK_PATH:
|
||||
case SD_PATH_SYSTEMD_SEARCH_NETWORK:
|
||||
return strv_from_nulstr(list, NETWORK_DIRS_NULSTR);
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
|
|||
static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
|
||||
static int dhcp6_prefix_remove_all(Manager *m, Link *link);
|
||||
static bool dhcp6_link_has_dhcpv6_prefix(Link *link);
|
||||
static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *prefix,
|
||||
uint8_t prefix_len,
|
||||
uint32_t lifetime_preferred,
|
||||
uint32_t lifetime_valid);
|
||||
|
||||
static bool dhcp6_get_prefix_delegation(Link *link) {
|
||||
if (!link->network)
|
||||
|
@ -191,6 +195,12 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network->dhcp6_pd_assign_prefix) {
|
||||
r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_radv_start(radv);
|
||||
}
|
||||
|
||||
|
@ -1018,3 +1028,43 @@ static bool dhcp6_link_has_dhcpv6_prefix(Link *link) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int dhcp6_assign_delegated_prefix(Link *link,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t prefix_len,
|
||||
uint32_t lifetime_preferred,
|
||||
uint32_t lifetime_valid) {
|
||||
_cleanup_(address_freep) Address *address = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(prefix);
|
||||
|
||||
if (!link->network->dhcp6_pd_assign_prefix)
|
||||
return 0;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate address: %m");
|
||||
|
||||
address->in_addr.in6 = *prefix;
|
||||
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to generate EUI64 address for DHCPv6 acquired delegated prefix: %m");
|
||||
|
||||
address->prefixlen = prefix_len;
|
||||
address->family = AF_INET6;
|
||||
address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
address->cinfo.ifa_valid = lifetime_valid;
|
||||
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
|
||||
r = address_configure(address, link, address_handler, true);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set addresses: %m");
|
||||
if (r > 0)
|
||||
link->address_messages++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1173,7 +1173,7 @@ static int link_request_set_neighbors(Link *link) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
|
|
|
@ -228,6 +228,7 @@ int link_request_set_routes(Link *link);
|
|||
int link_request_set_nexthop(Link *link);
|
||||
|
||||
int link_reconfigure(Link *link, bool force);
|
||||
int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_link_ipv6_address_gen_mode);
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ Network.ProxyARP, config_parse_tristate,
|
|||
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
|
||||
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
|
||||
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
|
||||
Network.IgnoreCarrierLoss, config_parse_bool, 0, offsetof(Network, ignore_carrier_loss)
|
||||
Network.IgnoreCarrierLoss, config_parse_tristate, 0, offsetof(Network, ignore_carrier_loss)
|
||||
Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration)
|
||||
Address.Address, config_parse_address, 0, 0
|
||||
Address.Peer, config_parse_address, 0, 0
|
||||
|
@ -199,6 +199,7 @@ DHCPv6.RequestOptions, config_parse_dhcp_request_options,
|
|||
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
|
||||
DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class)
|
||||
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
||||
DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign_prefix)
|
||||
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
||||
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
|
||||
DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options)
|
||||
|
|
|
@ -271,6 +271,9 @@ int network_verify(Network *network) {
|
|||
if (network->dhcp_use_gateway < 0)
|
||||
network->dhcp_use_gateway = network->dhcp_use_routes;
|
||||
|
||||
if (network->ignore_carrier_loss < 0)
|
||||
network->ignore_carrier_loss = network->configure_without_carrier;
|
||||
|
||||
if (network->dhcp_critical >= 0) {
|
||||
if (network->keep_configuration >= 0)
|
||||
log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
|
||||
|
@ -409,6 +412,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||
.dhcp6_use_ntp = true,
|
||||
.dhcp6_use_dns = true,
|
||||
|
||||
.dhcp6_pd_assign_prefix = true,
|
||||
|
||||
.dhcp_server_emit_dns = true,
|
||||
.dhcp_server_emit_ntp = true,
|
||||
.dhcp_server_emit_sip = true,
|
||||
|
@ -461,6 +466,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||
.ipv6_accept_ra_route_table_set = false,
|
||||
.ipv6_accept_ra_start_dhcp6_client = true,
|
||||
|
||||
.configure_without_carrier = false,
|
||||
.ignore_carrier_loss = -1,
|
||||
.keep_configuration = _KEEP_CONFIGURATION_INVALID,
|
||||
.ipv6_address_gen_mode = _LINK_IPV6_ADDRESS_GEN_MODE_INVALID,
|
||||
.can_triple_sampling = -1,
|
||||
|
|
|
@ -192,6 +192,7 @@ struct Network {
|
|||
bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
|
||||
RA flag is set, see RFC 7084,
|
||||
WPD-4 */
|
||||
bool dhcp6_pd_assign_prefix;
|
||||
|
||||
/* Bridge Support */
|
||||
int use_bpdu;
|
||||
|
@ -258,7 +259,7 @@ struct Network {
|
|||
int allmulticast;
|
||||
bool unmanaged;
|
||||
bool configure_without_carrier;
|
||||
bool ignore_carrier_loss;
|
||||
int ignore_carrier_loss;
|
||||
KeepConfiguration keep_configuration;
|
||||
LinkIPv6AddressGenMode ipv6_address_gen_mode;
|
||||
uint32_t iaid;
|
||||
|
|
|
@ -59,30 +59,30 @@ static const char* const path_table[_SD_PATH_MAX] = {
|
|||
[SD_PATH_SEARCH_STATE_FACTORY] = "search-state-factory",
|
||||
[SD_PATH_SEARCH_CONFIGURATION] = "search-configuration",
|
||||
|
||||
[SD_PATH_SYSTEMD_UTIL_DIR] = "systemd-util-dir",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_UNIT_DIR] = "systemd-system-unit-dir",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_PRESET_DIR] = "systemd-system-preset-dir",
|
||||
[SD_PATH_SYSTEMD_USER_UNIT_DIR] = "systemd-user-unit-dir",
|
||||
[SD_PATH_SYSTEMD_USER_PRESET_DIR] = "systemd-user-preset-dir",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_CONF_DIR] = "systemd-system-conf-dir",
|
||||
[SD_PATH_SYSTEMD_USER_CONF_DIR] = "systemd-user-conf-dir",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_UNIT_PATH] = "systemd-system-unit-path",
|
||||
[SD_PATH_SYSTEMD_USER_UNIT_PATH] = "systemd-user-unit-path",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_GENERATOR_DIR] = "systemd-system-generator-dir",
|
||||
[SD_PATH_SYSTEMD_USER_GENERATOR_DIR] = "systemd-user-generator-dir",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_GENERATOR_PATH] = "systemd-system-generator-path",
|
||||
[SD_PATH_SYSTEMD_USER_GENERATOR_PATH] = "systemd-user-generator-path",
|
||||
[SD_PATH_SYSTEMD_SLEEP_DIR] = "systemd-sleep-dir",
|
||||
[SD_PATH_SYSTEMD_SHUTDOWN_DIR] = "systemd-shutdown-dir",
|
||||
[SD_PATH_SYSTEMD_UTIL] = "systemd-util",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_UNIT] = "systemd-system-unit",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_PRESET] = "systemd-system-preset",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_CONF] = "systemd-system-conf",
|
||||
[SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT] = "systemd-system-unit",
|
||||
[SD_PATH_SYSTEMD_SYSTEM_GENERATOR] = "systemd-system-generator",
|
||||
[SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR] = "systemd-system-generator",
|
||||
[SD_PATH_SYSTEMD_USER_UNIT] = "systemd-user-unit",
|
||||
[SD_PATH_SYSTEMD_USER_PRESET] = "systemd-user-preset",
|
||||
[SD_PATH_SYSTEMD_USER_CONF] = "systemd-user-conf",
|
||||
[SD_PATH_SYSTEMD_SEARCH_USER_UNIT] = "systemd-user-unit",
|
||||
[SD_PATH_SYSTEMD_SEARCH_USER_GENERATOR] = "systemd-user-generator",
|
||||
[SD_PATH_SYSTEMD_USER_GENERATOR] = "systemd-user-generator",
|
||||
[SD_PATH_SYSTEMD_SLEEP] = "systemd-sleep",
|
||||
[SD_PATH_SYSTEMD_SHUTDOWN] = "systemd-shutdown",
|
||||
|
||||
[SD_PATH_TMPFILES_DIR] = "tmpfiles-dir",
|
||||
[SD_PATH_SYSUSERS_DIR] = "sysusers-dir",
|
||||
[SD_PATH_SYSCTL_DIR] = "sysctl-dir",
|
||||
[SD_PATH_BINFMT_DIR] = "binfmt-dir",
|
||||
[SD_PATH_MODULES_LOAD_DIR] = "modules-load-dir",
|
||||
[SD_PATH_CATALOG_DIR] = "catalog-dir",
|
||||
[SD_PATH_TMPFILES] = "tmpfiles",
|
||||
[SD_PATH_SYSUSERS] = "sysusers",
|
||||
[SD_PATH_SYSCTL] = "sysctl",
|
||||
[SD_PATH_BINFMT] = "binfmt",
|
||||
[SD_PATH_MODULES_LOAD] = "modules-load",
|
||||
[SD_PATH_CATALOG] = "catalog",
|
||||
|
||||
[SD_PATH_SYSTEMD_NETWORK_PATH] = "systemd-network-path",
|
||||
[SD_PATH_SYSTEMD_SEARCH_NETWORK] = "systemd-search-network",
|
||||
};
|
||||
|
||||
static int list_homes(void) {
|
||||
|
|
|
@ -88,6 +88,7 @@ static int dns_stream_complete(DnsStream *s, int error) {
|
|||
|
||||
static int dns_stream_identify(DnsStream *s) {
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ CMSG_SPACE(int) + /* for the TTL */
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra space */) control;
|
||||
struct msghdr mh = {};
|
||||
struct cmsghdr *cmsg;
|
||||
|
|
|
@ -1632,6 +1632,7 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
|
|||
"Broadcast",
|
||||
"PassCredentials",
|
||||
"PassSecurity",
|
||||
"PassPacketInfo",
|
||||
"ReusePort",
|
||||
"RemoveOnStop",
|
||||
"SELinuxContextFromNet"))
|
||||
|
|
|
@ -161,6 +161,11 @@ _SD_BEGIN_DECLARATIONS;
|
|||
#define SD_MESSAGE_UNSAFE_USER_NAME SD_ID128_MAKE(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f)
|
||||
#define SD_MESSAGE_UNSAFE_USER_NAME_STR SD_ID128_MAKE_STR(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f)
|
||||
|
||||
#define SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE \
|
||||
SD_ID128_MAKE(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
||||
#define SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE_STR \
|
||||
SD_ID128_MAKE_STR(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,32 +78,37 @@ enum {
|
|||
SD_PATH_SEARCH_STATE_FACTORY,
|
||||
SD_PATH_SEARCH_CONFIGURATION,
|
||||
|
||||
/* Various systemd paths, generally mirroring systemd.pc */
|
||||
SD_PATH_SYSTEMD_UTIL_DIR,
|
||||
SD_PATH_SYSTEMD_SYSTEM_UNIT_DIR,
|
||||
SD_PATH_SYSTEMD_SYSTEM_PRESET_DIR,
|
||||
SD_PATH_SYSTEMD_USER_UNIT_DIR,
|
||||
SD_PATH_SYSTEMD_USER_PRESET_DIR,
|
||||
SD_PATH_SYSTEMD_SYSTEM_CONF_DIR,
|
||||
SD_PATH_SYSTEMD_USER_CONF_DIR,
|
||||
SD_PATH_SYSTEMD_SYSTEM_UNIT_PATH,
|
||||
SD_PATH_SYSTEMD_USER_UNIT_PATH,
|
||||
SD_PATH_SYSTEMD_SYSTEM_GENERATOR_DIR,
|
||||
SD_PATH_SYSTEMD_USER_GENERATOR_DIR,
|
||||
SD_PATH_SYSTEMD_SYSTEM_GENERATOR_PATH,
|
||||
SD_PATH_SYSTEMD_USER_GENERATOR_PATH,
|
||||
SD_PATH_SYSTEMD_SLEEP_DIR,
|
||||
SD_PATH_SYSTEMD_SHUTDOWN_DIR,
|
||||
/* Various systemd paths, generally mirroring systemd.pc — Except we drop the "dir" suffix (and
|
||||
* replaces "path" by "search"), since this API is about dirs/paths anyway, and contains "path"
|
||||
* already in the prefix */
|
||||
SD_PATH_SYSTEMD_UTIL,
|
||||
SD_PATH_SYSTEMD_SYSTEM_UNIT,
|
||||
SD_PATH_SYSTEMD_SYSTEM_PRESET,
|
||||
SD_PATH_SYSTEMD_SYSTEM_CONF,
|
||||
SD_PATH_SYSTEMD_USER_UNIT,
|
||||
SD_PATH_SYSTEMD_USER_PRESET,
|
||||
SD_PATH_SYSTEMD_USER_CONF,
|
||||
|
||||
SD_PATH_TMPFILES_DIR,
|
||||
SD_PATH_SYSUSERS_DIR,
|
||||
SD_PATH_SYSCTL_DIR,
|
||||
SD_PATH_BINFMT_DIR,
|
||||
SD_PATH_MODULES_LOAD_DIR,
|
||||
SD_PATH_CATALOG_DIR,
|
||||
SD_PATH_SYSTEMD_SEARCH_SYSTEM_UNIT,
|
||||
SD_PATH_SYSTEMD_SEARCH_USER_UNIT,
|
||||
|
||||
SD_PATH_SYSTEMD_SYSTEM_GENERATOR,
|
||||
SD_PATH_SYSTEMD_USER_GENERATOR,
|
||||
SD_PATH_SYSTEMD_SEARCH_SYSTEM_GENERATOR,
|
||||
SD_PATH_SYSTEMD_SEARCH_USER_GENERATOR,
|
||||
|
||||
SD_PATH_SYSTEMD_SLEEP,
|
||||
SD_PATH_SYSTEMD_SHUTDOWN,
|
||||
|
||||
SD_PATH_TMPFILES,
|
||||
SD_PATH_SYSUSERS,
|
||||
SD_PATH_SYSCTL,
|
||||
SD_PATH_BINFMT,
|
||||
SD_PATH_MODULES_LOAD,
|
||||
SD_PATH_CATALOG,
|
||||
|
||||
/* systemd-networkd search paths */
|
||||
SD_PATH_SYSTEMD_NETWORK_PATH,
|
||||
SD_PATH_SYSTEMD_SEARCH_NETWORK,
|
||||
|
||||
_SD_PATH_MAX,
|
||||
};
|
||||
|
|
|
@ -332,7 +332,9 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
|
|||
/* We require genuine randomness here, since we want to make sure we won't collide with other
|
||||
* systems booting up at the very same time. We do allow RDRAND however, since this is not
|
||||
* cryptographic key material. */
|
||||
genuine_random_bytes(mac->ether_addr_octet, ETH_ALEN, RANDOM_ALLOW_RDRAND);
|
||||
r = genuine_random_bytes(mac->ether_addr_octet, ETH_ALEN, RANDOM_ALLOW_RDRAND);
|
||||
if (r < 0)
|
||||
return log_device_error_errno(device, r, "Failed to acquire random data to generate MAC: %m");
|
||||
} else {
|
||||
uint64_t result;
|
||||
|
||||
|
|
|
@ -443,6 +443,10 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
|
|||
assert(manager);
|
||||
|
||||
r = worker_process_device(manager, dev);
|
||||
if (r == -EAGAIN)
|
||||
/* if we couldn't acquire the flock(), then proceed quietly */
|
||||
log_device_debug_errno(dev, r, "Device currently locked, not processing.");
|
||||
else {
|
||||
if (r < 0)
|
||||
log_device_warning_errno(dev, r, "Failed to process device, ignoring: %m");
|
||||
|
||||
|
@ -450,6 +454,7 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
|
|||
r = device_monitor_send_device(monitor, NULL, dev);
|
||||
if (r < 0)
|
||||
log_device_warning_errno(dev, r, "Failed to send device, ignoring: %m");
|
||||
}
|
||||
|
||||
/* send udevd the result of the event execution */
|
||||
r = worker_send_message(manager->worker_watch[WRITE_END]);
|
||||
|
|
|
@ -73,7 +73,6 @@ static int xdg_config_parse_bool(
|
|||
void *userdata) {
|
||||
|
||||
bool *b = data;
|
||||
const char *value;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
|
@ -85,7 +84,7 @@ static int xdg_config_parse_bool(
|
|||
else if (streq(rvalue, "false"))
|
||||
*b = false;
|
||||
else
|
||||
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Invalid value for boolean: %s", value);
|
||||
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Invalid value for boolean: %s", rvalue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ SendOption=
|
|||
RequestOptions=
|
||||
UserClass=
|
||||
VendorClass=
|
||||
AssignAcquiredDelegatedPrefixAddress=
|
||||
[Route]
|
||||
Destination=
|
||||
Protocol=
|
||||
|
|
|
@ -164,6 +164,7 @@ PIDFile=
|
|||
PartOf=
|
||||
PassCredentials=
|
||||
PassSecurity=
|
||||
PassPacketInfo=
|
||||
PathChanged=
|
||||
PathExists=
|
||||
PathExistsGlob=
|
||||
|
|
|
@ -4,4 +4,3 @@ Name=test1
|
|||
[Network]
|
||||
Address=192.168.0.15/24
|
||||
Gateway=192.168.0.1
|
||||
ConfigureWithoutCarrier=true
|
|
@ -0,0 +1,2 @@
|
|||
[Network]
|
||||
ConfigureWithoutCarrier=true
|
|
@ -0,0 +1,2 @@
|
|||
[Network]
|
||||
IgnoreCarrierLoss=false
|
|
@ -0,0 +1,9 @@
|
|||
[Match]
|
||||
Name=bridge99
|
||||
|
||||
[Network]
|
||||
LinkLocalAddressing=yes
|
||||
IPv6AcceptRA=no
|
||||
ConfigureWithoutCarrier=yes
|
||||
Address=10.1.2.3/24
|
||||
Gateway=10.1.2.1
|
|
@ -445,6 +445,9 @@ class Utilities():
|
|||
def check_link_exists(self, link):
|
||||
self.assertTrue(link_exists(link))
|
||||
|
||||
def check_link_attr(self, *args):
|
||||
self.assertEqual(read_link_attr(*args[:-1]), args[-1]);
|
||||
|
||||
def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
|
||||
"""Wait for the link to reach the specified operstate and/or setup state.
|
||||
|
||||
|
@ -1671,11 +1674,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||
'25-gateway-next-static.network',
|
||||
'25-sysctl-disable-ipv6.network',
|
||||
'25-sysctl.network',
|
||||
'25-test1.network',
|
||||
'25-veth-peer.network',
|
||||
'25-veth.netdev',
|
||||
'25-vrf.netdev',
|
||||
'26-link-local-addressing-ipv6.network',
|
||||
'configure-without-carrier.network',
|
||||
'routing-policy-rule-dummy98.network',
|
||||
'routing-policy-rule-test1.network']
|
||||
|
||||
|
@ -1762,15 +1765,56 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||
self.assertNotRegex(output, '192.168.100.10/24')
|
||||
|
||||
def test_configure_without_carrier(self):
|
||||
copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
|
||||
copy_unit_to_networkd_unit_path('11-dummy.netdev')
|
||||
start_networkd()
|
||||
self.wait_online(['test1:routable'])
|
||||
self.wait_operstate('test1', 'off', '')
|
||||
check_output('ip link set dev test1 up carrier off')
|
||||
|
||||
copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
|
||||
restart_networkd()
|
||||
self.wait_online(['test1:no-carrier'])
|
||||
|
||||
carrier_map = {'on': '1', 'off': '0'}
|
||||
routable_map = {'on': 'routable', 'off': 'no-carrier'}
|
||||
for carrier in ['off', 'on', 'off']:
|
||||
with self.subTest(carrier=carrier):
|
||||
if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
|
||||
check_output(f'ip link set dev test1 carrier {carrier}')
|
||||
self.wait_online([f'test1:{routable_map[carrier]}'])
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, '192.168.0.15')
|
||||
self.assertRegex(output, '192.168.0.1')
|
||||
self.assertRegex(output, 'routable')
|
||||
self.assertRegex(output, routable_map[carrier])
|
||||
|
||||
def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
|
||||
copy_unit_to_networkd_unit_path('11-dummy.netdev')
|
||||
start_networkd()
|
||||
self.wait_operstate('test1', 'off', '')
|
||||
check_output('ip link set dev test1 up carrier off')
|
||||
|
||||
copy_unit_to_networkd_unit_path('25-test1.network')
|
||||
restart_networkd()
|
||||
self.wait_online(['test1:no-carrier'])
|
||||
|
||||
carrier_map = {'on': '1', 'off': '0'}
|
||||
routable_map = {'on': 'routable', 'off': 'no-carrier'}
|
||||
for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
|
||||
with self.subTest(carrier=carrier, have_config=have_config):
|
||||
if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
|
||||
check_output(f'ip link set dev test1 carrier {carrier}')
|
||||
self.wait_online([f'test1:{routable_map[carrier]}'])
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
|
||||
print(output)
|
||||
if have_config:
|
||||
self.assertRegex(output, '192.168.0.15')
|
||||
self.assertRegex(output, '192.168.0.1')
|
||||
else:
|
||||
self.assertNotRegex(output, '192.168.0.15')
|
||||
self.assertNotRegex(output, '192.168.0.1')
|
||||
self.assertRegex(output, routable_map[carrier])
|
||||
|
||||
def test_routing_policy_rule(self):
|
||||
copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
|
||||
|
@ -2608,6 +2652,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
|
|||
'11-dummy.netdev',
|
||||
'12-dummy.netdev',
|
||||
'26-bridge.netdev',
|
||||
'26-bridge-configure-without-carrier.network',
|
||||
'26-bridge-slave-interface-1.network',
|
||||
'26-bridge-slave-interface-2.network',
|
||||
'26-bridge-vlan-master.network',
|
||||
|
@ -2722,6 +2767,55 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
|
|||
print(output)
|
||||
self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
|
||||
|
||||
def test_bridge_configure_without_carrier(self):
|
||||
copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
|
||||
'11-dummy.netdev')
|
||||
start_networkd()
|
||||
|
||||
# With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
|
||||
for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
|
||||
with self.subTest(test=test):
|
||||
if test == 'no-slave':
|
||||
# bridge has no slaves; it's up but *might* not have carrier
|
||||
self.wait_online(['bridge99:no-carrier'])
|
||||
# due to a bug in the kernel, newly-created bridges are brought up
|
||||
# *with* carrier, unless they have had any setting changed; e.g.
|
||||
# their mac set, priority set, etc. Then, they will lose carrier
|
||||
# as soon as a (down) slave interface is added, and regain carrier
|
||||
# again once the slave interface is brought up.
|
||||
#self.check_link_attr('bridge99', 'carrier', '0')
|
||||
elif test == 'add-slave':
|
||||
# add slave to bridge, but leave it down; bridge is definitely no-carrier
|
||||
self.check_link_attr('test1', 'operstate', 'down')
|
||||
check_output('ip link set dev test1 master bridge99')
|
||||
self.wait_online(['bridge99:no-carrier:no-carrier'])
|
||||
self.check_link_attr('bridge99', 'carrier', '0')
|
||||
elif test == 'slave-up':
|
||||
# bring up slave, which will have carrier; bridge gains carrier
|
||||
check_output('ip link set dev test1 up')
|
||||
self.wait_online(['bridge99:routable'])
|
||||
self.check_link_attr('bridge99', 'carrier', '1')
|
||||
elif test == 'slave-no-carrier':
|
||||
# drop slave carrier; bridge loses carrier
|
||||
check_output('ip link set dev test1 carrier off')
|
||||
self.wait_online(['bridge99:no-carrier:no-carrier'])
|
||||
self.check_link_attr('bridge99', 'carrier', '0')
|
||||
elif test == 'slave-carrier':
|
||||
# restore slave carrier; bridge gains carrier
|
||||
check_output('ip link set dev test1 carrier on')
|
||||
self.wait_online(['bridge99:routable'])
|
||||
self.check_link_attr('bridge99', 'carrier', '1')
|
||||
elif test == 'slave-down':
|
||||
# bring down slave; bridge loses carrier
|
||||
check_output('ip link set dev test1 down')
|
||||
self.wait_online(['bridge99:no-carrier:no-carrier'])
|
||||
self.check_link_attr('bridge99', 'carrier', '0')
|
||||
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, '10.1.2.3')
|
||||
self.assertRegex(output, '10.1.2.1')
|
||||
|
||||
def test_bridge_ignore_carrier_loss(self):
|
||||
copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
|
||||
'26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
|
||||
|
|
|
@ -37,3 +37,4 @@ SystemCallFilter=@system-service @mount
|
|||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=dbus-org.freedesktop.home1.service
|
||||
Also=systemd-userdbd.service
|
||||
|
|
|
@ -17,7 +17,7 @@ Before=sockets.target
|
|||
[Socket]
|
||||
ReceiveBuffer=128M
|
||||
ListenNetlink=route 1361
|
||||
PassCredentials=yes
|
||||
PassPacketInfo=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
|
|
Loading…
Reference in New Issue