Compare commits

..

31 Commits

Author SHA1 Message Date
Susant Sahani 9efa8a3cff network: DHCPv6 Assign delegated prefix to LAN interface
In DHCPv6-PD environment, where WAN interface requests IPv6 via DHCPv6,
receives the address as well as delegated prefixes, with LAN interfaces
serving those delegated prefixes in their router advertisement messages.
The LAN interfaces on the router themselves do not have
the IPv6 addresses assigned by networkd from the prefix it
serves on that interface. Now this patch enables it.
2020-05-29 16:20:37 +09:00
Susant Sahani 5c95a9134a sd-network: Rectify Advertise Message Processing by a Client
We need to fix RCC 2215 behaviour with rfc7550 errata
and https://tools.ietf.org/html/rfc8415.

[RFC3315] specifies that a client must ignore an Advertise message if
   a server will not assign any addresses to a client, and [RFC3633]
   specifies that a client must ignore an Advertise message if a server
   returns the NoPrefixAvail status to a requesting router.  Thus, a
   client requesting both IA_NA and IA_PD, with a server that only
   offers either addresses or delegated prefixes, is not supported by
   the current protocol specifications.

   Solution: a client SHOULD accept Advertise messages, even when not
   all IA option types are being offered.  And, in this case, the client
   SHOULD include the not offered IA option types in its Request.  A
   client SHOULD only ignore an Advertise message when none of the
   requested IA options include offered addresses or delegated prefixes.
   Note that ignored messages MUST still be processed for SOL_MAX_RT and
   INF_MAX_RT options as specified in [RFC7083].

   Replace Section 17.1.3 of RFC 3315: (existing errata)

     The client MUST ignore any Advertise message that includes a Status
     Code option containing the value NoAddrsAvail, with the exception
     that the client MAY display the associated status message(s) to the
     user.

   With the following text (which addresses the existing erratum
   [Err2471] and includes the changes made by [RFC7083]):

     The client MUST ignore any Advertise message that contains no
     addresses (IAADDR options encapsulated in IA_NA or IA_TA options)
     and no delegated prefixes (IAPREFIX options encapsulated in IA_PD
     options; see RFC 3633) with the exception that the client:

       - MUST process an included SOL_MAX_RT option (RFC 7083) and
       - MUST process an included INF_MAX_RT option (RFC 7083).

     A client can display any associated status message(s) to the user
     or activity log.

     The client ignoring this Advertise message MUST NOT restart the
     Solicit retransmission timer.
2020-05-29 16:17:36 +09:00
Yu Watanabe fac729f811
Merge pull request #15911 from poettering/unit-name-tighten
pid1: improve logging when we encounter a path that is too long to be converted into a mount unit name
2020-05-29 15:55:38 +09:00
Lennart Poettering f6dbcebdc2 sd-device: check netlink netns matches host netns before using monitor
Tracking down #15931 confused the hell out of me, since running homed in
gdb from the command line worked fine, but doing so as a service failed.
Let's make this more debuggable and check if we live in the host netns
when allocating a new udev monitor.

This is just debug stuff, so that if things don't work, a quick debug
run will reveal what is going on.

That said, while we are at it, also fix unexpected closing of passed in
fd when failing.
2020-05-29 15:28:10 +09:00
Yu Watanabe 8abbd9a4d9
Merge pull request #15944 from poettering/sd-path-fixups
sd-path: some fixups
2020-05-29 15:23:37 +09:00
Yu Watanabe 27cd09442f
Merge pull request #15942 from poettering/pass-pktinfo
disable PassCredentials= on networkd netlink socket, enable NETLINK_PKTINFO instead
2020-05-29 15:23:15 +09:00
Yu Watanabe cfbee85ce2
Merge pull request #15956 from poettering/news-v246
start of a NEWS file for v246 and minor assorted fixes
2020-05-29 15:10:47 +09:00
Yu Watanabe 63ef9d31fd
Merge pull request #15930 from poettering/udev-no-lock-warn
udev: when the BSD lock on a block device is taken, don't complain
2020-05-29 10:39:14 +09:00
Yu Watanabe 63b00fa77d
Merge pull request #15619 from ddstreet/ignore_carrier_loss_default
Set IgnoreCarrierLoss= default to value of ConfigureWithoutCarrier=
2020-05-29 10:04:00 +09:00
Lennart Poettering bfafec253c update TODO 2020-05-28 23:54:35 +02:00
Lennart Poettering ccdf03b9c7 sd-path: drop "-dir" and "-path" suffixes from path enums
Clean up the naming of the sd-path enums. Previously, the more recently
added fields where named in the form SD_PATH_xyz_DIR and
SD_PATH_xyz_PATH, while the older fields where called just SD_PATH_xyz
and SD_PATH_SEARCH_xyz. Let's clean this up, to come to a more unified
way how we name this stuff.

I opted to stick to the old naming, i.e. dropthe suffixes. It's a bit of
a bike-shedding question of course, but I think there's a good reason to
avoid the additional DIR and PATH suffixes: the enum prefix contains
"PATH" anyway (i.e. "SD_PATH_"), so including PATH twice in each name is
redundant. Moreover, the key difference between the enums with the "dir"
and the "path" in the name is that the latter are *seach* paths, and I
think this is better emphasized by sticking to the "SEARCH" in the name.

Moreover dropping the suffixes makes the identifiers a lot shorter, in
particular in the "systemd-path" list output. And that's always good.

This means the naming pkgconfig file and in sd-path slightly deviate
(though the mapping is very simple), but I think that's OK, given that
this is developer facing and not user facing.
2020-05-28 23:54:35 +02:00
Lennart Poettering 4a56315a99 path: use ROOTPREFIX properly
ROOTPREFIX doesn't include the trailing /, hence add it in where needed.

Also, given that sysctl.d/, binfmt.d/, sysusers.d/ are generally
accessed before /var/ is up they should use ROOTPREFIX rather than
PREFIX. Fix that.
2020-05-28 23:52:34 +02:00
Lennart Poettering 6527b019fc xdg-autostart: fix two coverity found issues
Fixes: CID#1429003
Fixes: CID#1429004
2020-05-28 23:38:38 +02:00
Lennart Poettering 871dc8d644 homed: enable userdb too if homed is requested
Strictly speaking you can run homed without userdb. But it doesn't
really make much sense: they go hand in hand and implement the same
concepts, just for different sets of users. Let's hence disable both
automatically by default if homed is requested.

(We don't do the reverse: opting into userdbd shouldn't mean that you
are OK with homed.)

And of course, users can always deviate from our defaults easily, and
turn off userbd again right-away if they don't like it, and things will
generally work.
2020-05-28 23:38:29 +02:00
Lennart Poettering a745117dba udev: catch genuine_random_bytes() failures
Fixes: CID#1428926
2020-05-28 23:38:25 +02:00
Lennart Poettering 70d8586365 libsystemd: properly export new sd_notify_barrier() API call
Follow-up for: 4f07ddfa9b
2020-05-28 23:38:21 +02:00
Lennart Poettering 5a7cf2e9d8 hwdb: whitespace fix 2020-05-28 23:38:17 +02:00
Lennart Poettering b0d0e0ef98 start NEWS file for v246 2020-05-28 23:37:43 +02:00
Lennart Poettering 08ab18618e resolved: tweak cmsg calculation
We ask for the TTL, then have enough space for it.

We probably can drop the extra cmsg space now, but let's figure that out
another time, since the extra cmsg space is used elsewhere in resolved
as well.
2020-05-27 22:40:59 +02:00
Lennart Poettering 43007b302e networkd: clean up NETLINK_PKTINFO vs. SO_PASSCRED confusion
We actually care for NETLINK_PKTINFO, not for SO_PASSCRED, hence when
allocating the netlink socket, configure things accordingly.

Tracked down by Benjamin Robin, see:

https://github.com/systemd/systemd/pull/15571#issuecomment-633213747
2020-05-27 22:40:56 +02:00
Lennart Poettering a3d19f5d99 core: add new PassPacketInfo= socket unit property 2020-05-27 22:40:38 +02:00
Lennart Poettering 35a3eb9bdc socket-util: add generic socket_pass_pktinfo() helper
The helper turns on the protocol specific "packet info" structure cmsg
for three relevant protocols we know.
2020-05-27 22:39:34 +02:00
Lennart Poettering 5abee64ed4 udev: when the BSD lock on a block device is taken, don't complain
if someone implements https://systemd.io/BLOCK_DEVICE_LOCKING/ then we
shouldn't loudly complain about that.

This reverts back to the original behaviour from
3ebdb81ef088afd3b4c72b516beb5610f8c93a0d: when the lock is taken we
silently skip processing the device and sending out the messages for it.
2020-05-27 15:30:48 +02:00
Dan Streetman 0fc0d85fae test: add bridge configure-without-carrier test
Verify configure-without-carrier works, and retains configuration
across carrier losses/gains.
2020-05-26 09:52:55 -04:00
Dan Streetman 9bacf4313e test: expand configure-without-carrier test
The test currently doesn't actually test configure-without-carrier since
it does have carrier for the entire test.  It now forces carrier down
before starting the network portion of the test. Also, it tests to verify
the configuration is retained across future carrier losses/gains.
2020-05-26 09:52:55 -04:00
Dan Streetman 6b8a1aa6a3 network: return 1 on start and 0 if ipv4ll is already started
Instead of -EBUSY, return 0 from sd_ipv4ll_start() if it's already started,
and change successful start return value to 1.

This matches sd_ndisc_start() behavior; 1 indicates successful start, and
0 indicates already started.
2020-05-26 09:52:50 -04:00
Dan Streetman bd0d471c8f network: Change IgnoreCarrierLoss default to value of ConfigureWithoutCarrier
It doesn't make much sense to have ConfigureWithoutCarrier set, but not
IgnoreCarrierLoss; all the configuration added during initial interface
bring-up will be lost at the first carrier up/down.
2020-05-26 08:47:41 -04:00
Lennart Poettering 8dd7cbce42 journal: expand variables up to PATH_MAX in size in catalog output
It makes sense to be able to output every officially valid path, hence
bump the variable size limit in catalog entries to 4K (i.e. PATH_MAX).
2020-05-26 09:17:48 +02:00
Lennart Poettering 2c905207db core: improve log messages when we cannot process a mount point
Whenever we pick up a new line in /proc/self/mountinfo and want to
synthesize a new mount unit from it, let's say which one it is.
Moreover, downgrade the log message when we encounter a mount point with
an overly long name to LOG_WARNING, since it's generally fine to ignore
such mount points.

Also, attach a catalog entry to explain the situation further.

Prompted-By: #15221
2020-05-26 09:17:48 +02:00
Lennart Poettering 5aec5c751a unit-name: use TAKE_PTR() where appropriate 2020-05-26 09:17:48 +02:00
Lennart Poettering ab19db01ae unit-name: tighten checks for building valid unit names
Let's be more thorough that whenever we build a unit name based on
parameters, that the result is actually a valid user name. If it isn't
fail early.

This should allows us to catch various issues earlier, in particular
when we synthesize mount units from /proc/self/mountinfo: instead of
actually attempting to allocate a mount unit we will fail much earlier
when we build the name to synthesize the unit under. Failing early is a
good thing generally.
2020-05-26 09:17:47 +02:00
54 changed files with 974 additions and 246 deletions

324
NEWS
View File

@ -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
View File

@ -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.

View File

@ -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.

View File

@ -429,6 +429,7 @@ Most socket unit settings are available to transient units.
✓ Broadcast=
✓ PassCredentials=
✓ PassSecurity=
✓ PassPacketInfo=
✓ TCPCongestion=
✓ ReusePort=
✓ MessageQueueMaxMessages=

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -62,3 +62,8 @@ struct sockaddr_vm {
#ifndef IP_TRANSPARENT
#define IP_TRANSPARENT 19
#endif
/* linux/sockios.h */
#ifndef SIOCGSKNS
#define SIOCGSKNS 0x894C
#endif

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -715,4 +715,6 @@ global:
sd_path_lookup;
sd_path_lookup_strv;
sd_notify_barrier;
} LIBSYSTEMD_245;

View File

@ -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) {

View File

@ -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,

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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"))

View File

@ -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

View File

@ -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,
};

View File

@ -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;

View File

@ -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]);

View File

@ -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;
}

View File

@ -119,6 +119,7 @@ SendOption=
RequestOptions=
UserClass=
VendorClass=
AssignAcquiredDelegatedPrefixAddress=
[Route]
Destination=
Protocol=

View File

@ -164,6 +164,7 @@ PIDFile=
PartOf=
PassCredentials=
PassSecurity=
PassPacketInfo=
PathChanged=
PathExists=
PathExistsGlob=

View File

@ -4,4 +4,3 @@ Name=test1
[Network]
Address=192.168.0.15/24
Gateway=192.168.0.1
ConfigureWithoutCarrier=true

View File

@ -0,0 +1,2 @@
[Network]
ConfigureWithoutCarrier=true

View File

@ -0,0 +1,2 @@
[Network]
IgnoreCarrierLoss=false

View File

@ -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

View File

@ -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',

View File

@ -37,3 +37,4 @@ SystemCallFilter=@system-service @mount
[Install]
WantedBy=multi-user.target
Alias=dbus-org.freedesktop.home1.service
Also=systemd-userdbd.service

View File

@ -17,7 +17,7 @@ Before=sockets.target
[Socket]
ReceiveBuffer=128M
ListenNetlink=route 1361
PassCredentials=yes
PassPacketInfo=yes
[Install]
WantedBy=sockets.target