1
0
mirror of https://github.com/systemd/systemd synced 2025-10-01 17:54:45 +02:00

Compare commits

..

34 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
10f4d47037 meson: bump version numbers 2021-02-23 01:56:21 +01:00
Zbigniew Jędrzejewski-Szmek
60d3137024 NEWS: add contributors 2021-02-23 01:55:11 +01:00
Lennart Poettering
048e043375 resolved: actually use the specified rrsig argument
The argument only exists to be used to override/fill in the RRSIG record
of the answer item. Hence actually use it instead of ignore it.

(Not sure how this got lost earlier.)

Fixes: #18714
2021-02-23 01:52:33 +01:00
Zbigniew Jędrzejewski-Szmek
67e700bad7
Merge pull request #18741 from poettering/stub-no-cname
resolved: don't follow CNAMEs in the stub anymore
2021-02-23 01:52:01 +01:00
Zbigniew Jędrzejewski-Szmek
8ebfd50aaf shared/condition: add ConditionControlGroupController=v1|v2
Before, we only allowed conditionalizing on controllers, not the hierarchy.
This commit extends this to allow a simple check for v1 (i.e. classic or hybrid),
and v2 (full unified).

An alternative approach would be to add a separate Condition for this, but I'm
not too keen on that, considering that v1 is already being deprecrecated
(c.f. 82f3063218).
2021-02-23 01:11:18 +01:00
Luca Boccassi
6c3f7ca036 MountImages: parse unit specifiers after permissive hyphen
The permissive bit it not something a specifier might synthetise
2021-02-23 01:11:05 +01:00
Zbigniew Jędrzejewski-Szmek
267294e08d
Merge pull request #18745 from keszybz/stop-using-fstrings
Stop using fstrings
2021-02-23 01:10:38 +01:00
Zbigniew Jędrzejewski-Szmek
d6191ed529 test-dns-packet: fix leak of DnsResourceRecord object 2021-02-23 01:06:08 +01:00
Zbigniew Jędrzejewski-Szmek
897a25617d NEWS: a few more entries for v248-rc1
I left the stuff related to [NextHop] out. There are still
patches outstanding, and we can add a comprehensive entry once
things reached the final form.
2021-02-23 00:47:55 +01:00
Zbigniew Jędrzejewski-Szmek
a5e5e102ba
Merge pull request #18704 from keszybz/fallback-hostame-override
Allow overriding of fallback hostname through envvar and os-release field
2021-02-23 00:41:27 +01:00
Lennart Poettering
5bd7ebb332 resolved: stick CNAME targets into main answer section in stub replies 2021-02-22 23:55:13 +01:00
Lennart Poettering
d1f8fbea9f resolved: add dns_resource_record_get_cname_target() helper
This determines the redirection target from a CNAME or DNAME RR given it
matches some given RR key.
2021-02-22 23:55:13 +01:00
Lennart Poettering
990e7e87ad resolved: remove duplicate comment
Practically the same comment is a few lines up covering both parts
anyway, let's remove one.
2021-02-22 23:55:13 +01:00
Lennart Poettering
c6ebf89b8f resolved: update comment in DNS stub code a bit
There's no "answer_auxiliary" object anymore, it's all one "answer"
object, and we have per-item flags that tell us which section things are
from, i.e. from the main answer section, or the additional or
authoritative ones.
2021-02-22 23:55:13 +01:00
Lennart Poettering
2f4d8e577c resolved: don't follow CNAMEs in the stub anymore
CNAME following was broken by 775ae35403f8f3c01b7ac13387fe8aac1759993f
where we'd not properly collect RRs along the CNAME path. Good thing
though is that we don't have to anymore: since we nowadays propagate all
sections of the upstream replies into the cache and back to stub clients
all the information should already be available anyway, and there's no
need for us to collect it.

Fixes: #18690
2021-02-22 23:55:13 +01:00
Zbigniew Jędrzejewski-Szmek
dda7d0a4d6
Merge pull request #18575 from bugaevc/aa
Set the AA bit in answers for synthetic records & mDNS
2021-02-22 23:08:13 +01:00
Zbigniew Jędrzejewski-Szmek
f2ec239c2b Revert "generate-dns_type-gperf: modernize python syntax"
This reverts commit b0a336a66929ed2a146888178157bf1af5c8598c.

Fixes #18708.
2021-02-22 22:43:14 +01:00
Zbigniew Jędrzejewski-Szmek
1f9441a72b Stop using f-strings in generate-sym-test.py
This partially reverts 7857b6e8383f5debab9544ef3abb15a27830fafa.
Debian 9 has python3.5 which does not have f-strings yet.

Partially fixes #18708.
2021-02-22 22:43:00 +01:00
Zbigniew Jędrzejewski-Szmek
85c8eac822 docs: align tables vertically to top
Fixes #18706.
2021-02-22 22:29:34 +01:00
Frantisek Sumsal
1a7c5ec4b2 Translated using Weblate (Slovak)
Currently translated at 24.8% (47 of 189 strings)

Co-authored-by: Frantisek Sumsal <frantisek@sumsal.cz>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/master/sk/
Translation: systemd/main
2021-02-22 21:26:57 +01:00
Zbigniew Jędrzejewski-Szmek
8770c8135b hostnamed: rename FallbackHostname to DefaultHostname
This follows the addition of DEFAULT_HOSTNAME= in os-release.
The distinction between the value from os-release or the env var and
the compile-time setting is not made in the api: HostnameSource is
"default" is all cases. I think that this level of detail is not needed,
because the users of this mostly care whether the hostname was set by
user configuration or not.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
e7637751c4 Use the DEFAULT_HOSTNAME field from os-release
This provides a fairly comprehensible fix for
https://bugzilla.redhat.com/show_bug.cgi?id=1893417.

This adds yet-another level of configuration:
- /etc/hostname
- transient hostname
- $SYSTEMD_DEFAULT_HOSTNAME
- DEFAULT_HOSTNAME is os-release
- -Dfallback-hostname=
- "linux"

It's a lot of layers, but each has it's own justification.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
05c6f341b1 Allow the fallback hostname to be overriden using an environment variable
See https://bugzilla.redhat.com/show_bug.cgi?id=1893417 for the back story:
the fallback hostname matters a lot in certain environments. Right now the only
way to configure the fallback hostname is by recompiling systemd, which is
obviously problematic in case when the fallback hostname shall differ between
different editions of the same distro that share a single compiled rpm.

By making this overridable through an envvar, we're providing an escape hatch
without making this a top-level api. Later on a way to set this through
os-release is added, but I think the approach with the variable is still
useful. It it very convenient for testing, or to override settings only in a
particular service, etc.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
209c14705d basic/os-util: make the sentinel implicit 2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
6ef06723b1 Move os-util.[ch] to basic/
parse_os_release() will be used basic/hostname-util.c later on.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
fd03a6a92b sysext: move extension_release_validate() out of os-util.c 2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
addddf565b os-release: add the DEFAULT_HOSTNAME= setting
The motivation is that variants of the same distro that share the same compiled
rpm want to customize various aspects of the system, in particular the
hostname. In some sense the default hostname is part of the identity of the
system, so setting it through os-release makes sense. In particular, instead of
setting a default value in /etc/hostname, the appropriate default can be baked
into the image, leaving /etc/hostname for local overrides only.

Why make this a separate field instead of e.g. using NAME from os-release?
NAME is already used for other purposes, and it seems likely that people want
to set those independently.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
aa96ef86a7 man: use ~/.config instead of XDG_CONFIG_HOME
e3820eeaf11f3b4614cbdfbc85675bc16a486e21 did that replacement XDG_CONFIG_HOME, in one
of two places. Let's use ~/.config everywhere.

Quoting https://github.com/systemd/systemd/pull/18704#discussion_r579465254:
> I'd really drop XDG_CONFIG_HOME from the docs. It's confusing enough as it
> is. Where we don't need the indirections we should not confuse people with
> it, in particular as people might then think it's actually a good idea to use
> that env var and redirect things. I'd just show the literal path everywhere,
> even if we internally use the env var.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
d55ed7de34 manager: add ManagerEnvironment configuration setting
This is useful for various variables that modify process behaviour. This makes
it easy to set it for pid1 without touching the kernel command line. Even for
the *user manager* this also can be convenient for the unprivileged user, who
cannot modify user@.service definition.

Variables that could be set like this include $SD_EVENT_PROFILE_DELAYS,
$SYSTEMD_FALLBACK_HOSTNAME, $SYSTEMD_MEMPOOL, $SYSTMED_RDRAND, etc.
2021-02-22 20:10:55 +01:00
Zbigniew Jędrzejewski-Szmek
fa256f43e7 basic/env-util: add putenv_dup() 2021-02-22 20:10:55 +01:00
Sergey Bugaev
bb4e030fcb resolved: set the AA bit for mDNS responses
This is required by RFC 6762.

Fixes https://github.com/systemd/systemd/issues/17972
2021-02-22 14:52:13 +03:00
Sergey Bugaev
4ad017cda5 resolved: set the AA bit for synthetic answers
The stub DNS server is authoritative for the RRs we synthesize, such as
localhost, _gateway, and entries from /etc/hosts, and also for trust anchors.

Partially fixes https://github.com/systemd/systemd/issues/17972
2021-02-22 14:51:29 +03:00
Zbigniew Jędrzejewski-Szmek
f70e6fb471 manager: read ~/.config/systemd/user.conf in user mode
This changes the paths we read user manager config from in two ways:

- split-usr-root paths are dropped. The user manager is a poster boy for
  non-early-boot, so reading dropins only from /usr is appropriate.

- we look at ~/.config/systemd/user.conf. Users should be allowed to override
  their own config.

As user managers become more and more used, it becomes more important for users
to customize their own daemon. By reading from ~/.config, this is possible
without privileges.
2021-02-22 10:03:07 +01:00
Zbigniew Jędrzejewski-Szmek
8b8024f1c2 shared/conf-parser: allow more than one location of the main config file
No functional change as long as only one path is passed.
2021-02-21 12:22:13 +01:00
57 changed files with 781 additions and 328 deletions

65
NEWS
View File

@ -167,6 +167,10 @@ CHANGES WITH 248:
i.e. whether the interface is always upped, always downed, or may be
upped/downed by the user using "ip dev".
* The default for the Broadcast= setting in .network files has slightly
changed: the broadcast address will not be configured for wireguard
devices.
* systemd.netdev files gained a [VLAN] Protocol=, IngressQOSMaps=,
EgressQOSMaps=, and [MACVLAN] BroadcastMulticastQueueLength=
configuration options for VLAN packet handling.
@ -229,17 +233,23 @@ CHANGES WITH 248:
* systemd-nspawn gained the ability to configure the firewall using the
nftables subsystem (in addition to the existing iptables
support). Similar, systemd-networkd's IPMasquerade= option now
support). Similarly, systemd-networkd's IPMasquerade= option now
supports nftables as back-end, too. In both cases NAT on IPv6 is now
supported too, in addition to IPv4 (the iptables back-end still is
IPv4-only).
"IPMasquerade=yes", which was the same as "IPMasquerade=ipv4" before,
retains its meaning, but has been deprecated. Please switch to either
"ivp4" or "both" (if covering IPv6 is desired).
* systemd-importd will now download .verity and .roothash.p7s files
along with the machine image (as exposed via machinectl pull-raw).
* systemd-oomd now gained a new DefaultMemoryPressureDurationSec=
setting to configure the time a unit's cgroup needs to exceed memory
pressure limits before action will be taken.
pressure limits before action will be taken, and a new
ManagedOOMPreference=none|avoid|omit setting to avoid killing certain
units.
systemd-oomd is now considered fully supported (the usual
backwards-compatiblity promises apply). Swap is not required for
@ -256,8 +266,8 @@ CHANGES WITH 248:
ignored. The goal is to honour configuration as specified by the
user.
* systemd-hostnamed now exports the fallback hostname and the source of
the configured hostname ("static", "transient", or "fallback") as
* systemd-hostnamed now exports the default hostname and the source of
the configured hostname ("static", "transient", or "default") as
D-Bus properties.
* systemd-hostnamed now exports the "HardwareVendor" and
@ -321,6 +331,10 @@ CHANGES WITH 248:
warning is emitted during build. Support is slated to be removed in
about a year (when the Debian Bookworm release development starts).
* Systems with the legacy cgroup v1 hierarchy are now marked as
"tainted", to make it clearer that using the legacy hierarchy is not
recommended.
* The main git development branch has been renamed to 'main'.
* mmcblk[0-9]boot[0-9] devices will no longer be probed automatically
@ -332,11 +346,12 @@ CHANGES WITH 248:
by programs for detecting whether they were forked off by the service
manager itself or are a process forked off further down the tree.
* The sd-device API gained three new calls sd_device_get_action() (for
determining the uevent add/remove/change/… action the device object
has been seen for), sd_device_get_seqno() (for determining the uevent
sequence number) and sd_device_new_from_stat_rdev() (for allocating a
new sd_device object from stat() data of a device node).
* The sd-device API gained four new calls: sd_device_get_action() to
determine the uevent add/remove/change/… action the device object has
been seen for, sd_device_get_seqno() to determine the uevent sequence
number, sd_device_new_from_stat_rdev() to allocate a new sd_device
object from stat(2) data of a device node, and sd_device_trigger() to
write to the 'uevent' attribute of a device.
* For most tools the --no-legend= switch has been replaced by
--legend=no and --legend=yes, to force whether tables are shown with
@ -371,6 +386,38 @@ CHANGES WITH 248:
* portablectl gained a new "reattach" verb for detaching/reattaching a
portable service image, useful for updating images on-the-fly.
Contributions from: Adam Nielsen, Adrian Vovk, AJ Jordan, Alan Perry,
Alexander Batischev, Ali Abdallah, Andrew Balmos, Anita Zhang, Ansgar
Burchardt, Antonius Frie, Ardy, Arian van Putten, Ariel Fermani, Arnaud
T, A S Alam, Bastien Nocera, Benjamin Berg, Benjamin Robin, Björn
Daase, chri2, Christian Ehrhardt, Christian Hesse, Christopher Obbard,
clayton craft, corvusnix, cprn, d032747, Daan De Meyer, Daniele Medri,
Dan Streetman, Darren Ng, David Edmundson, Deepak Rawat, Devon Pringle,
Dmitry Borodaenko, dropsignal, Einsler Lee, Endre Szabo, Evgeny
Vereshchagin, Fabian Affolter, Felipe Borges, feliperodriguesfr, Felix
Stupp, Florian Hülsmann, Florian Klink, Florian Westphal, Franck Bui,
Frantisek Sumsal, Gablegritule, Gaël PORTAY, Gaurav, Giedrius
Statkevičius, Greg Depoire--Ferrer, Hans de Goede, heretoenhance, Iago
López Galeiras, igo95862, Ilya Dmitrichenko, Jameer Pathan, Jan Tojnar,
Jiehong, Jinyuan Si, John Slade, Jonathan G. Underwood, Jonathan
McDowell, Josh Triplett, Joshua Watt, Julia Cartwright, Julien Humbert,
Kairui Song, Karel Zak, Kevin P. Fleming, Khem Raj, Konomi, krissgjeng,
l4gfcm, Lennart Poettering, Luca Boccassi, Luca BRUNO, Lucas
Werkmeister, Luka Kudra, Luna Jernberg, Marc-André Lureau, Matthias
Klumpp, Matt Turner, Michael Marley, Michal Fabik, Michał Kopeć, Michal
Sekletár, Mike Gilbert, milovlad, moson-mo, Nick, nihilix-melix, Oğuz
Ersen, Ondrej Mosnacek, pali, Pavel Hrdina, Pavel Sapezhko, Peter
Hutterer, Pierre Dubouilh, Piotr Drąg, Richard Laager, rnhmjoj,
RussianNeuroMancer, Sebastiaan van Stijn, Sergey Bugaev, shenyangyang4,
Simonas Kazlauskas, Stefan Agner, Steve Ramage, Susant Sahani, Sven
Mueller, Tad Fisher, Takashi Iwai, Thomas Haller, Topi Miettinen,
Torsten Hilbrich, Tyler Hicks, Ulrich Ölmann, Vinnie Magro, Vito
Caputo, Vlad, walbit-de, Weblate, Weblate (bot), Whired Planck, wouter
bolsterlee, Yuri Chornoivan, Yu Watanabe, Zach Smith, Zbigniew
Jędrzejewski-Szmek, Zmicer Turok, Дамјан Георгиевски
— Warsaw, 2021-02-23
CHANGES WITH 247:
* KERNEL API INCOMPATIBILITY: Linux 4.14 introduced two new uevents

View File

@ -56,6 +56,10 @@ All tools:
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
`SystemdOptions` EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
* `$SYSTEMD_DEFAULT_HOSTNAME` — override the compiled-in fallback hostname
(relevant in particular for the system manager and `systemd-hostnamed`).
Must be a valid hostname (either a single label or a FQDN).
* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
method. Defaults to `auto`. Behavior is defined as follows:
`auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted

View File

@ -116,6 +116,11 @@ footer {
margin-top: 4rem;
}
/* Make tables vertically aligned to the top */
tbody td {
vertical-align: top;
}
/* Github Code Highlighting */
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }

View File

@ -63,7 +63,7 @@ node /org/freedesktop/hostname1 {
readonly s StaticHostname = '...';
readonly s PrettyHostname = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s FallbackHostname = '...';
readonly s DefaultHostname = '...';
readonly s HostnameSource = '...';
readonly s IconName = '...';
readonly s Chassis = '...';
@ -124,7 +124,7 @@ node /org/freedesktop/hostname1 {
<variablelist class="dbus-property" generated="True" extra-ref="PrettyHostname"/>
<variablelist class="dbus-property" generated="True" extra-ref="FallbackHostname"/>
<variablelist class="dbus-property" generated="True" extra-ref="DefaultHostname"/>
<variablelist class="dbus-property" generated="True" extra-ref="HostnameSource"/>
@ -183,13 +183,15 @@ node /org/freedesktop/hostname1 {
set this setting will be the empty string. Applications should then find a suitable fallback, such as the
dynamic hostname.</para>
<para>The <varname>FallbackHostname</varname> property exposes the fallback hostname (configured at
compilation time).</para>
<para>The <varname>DefaultHostname</varname> property exposes the default hostname (configured through
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>, or a
fallback set at compilation time).</para>
<para>The <varname>HostnameSource</varname> property exposes the origin of the currently configured
hostname. One of <literal>static</literal> (set from <filename>/etc/hostname</filename>),
<literal>transient</literal> (a non-permanent hostname from an external source),
<literal>fallback</literal> (the compiled-in fallback value).</para>
<literal>default</literal> (the value from <filename>os-release</filename> or the the compiled-in
fallback).</para>
<para>The <varname>IconName</varname> property exposes the <emphasis>icon name</emphasis> following the
XDG icon naming spec. If not set, information such as the chassis type (see below) is used to find a
@ -332,8 +334,8 @@ node /org/freedesktop/hostname1 {
<listitem><para>Limit the hostname to 63 chars, which is the length of a DNS label.</para></listitem>
<listitem><para>If after stripping special chars the empty string is the result, you can pass this
as-is to <filename>systemd-hostnamed</filename> in which case it will automatically use
<literal>&FALLBACK_HOSTNAME;</literal>.</para></listitem>
as-is to <filename>systemd-hostnamed</filename> in which case it will automatically use a suitable
fallback.</para></listitem>
<listitem><para>Uppercase charaacters should be replaced with their lowercase equivalents.
</para></listitem>

View File

@ -317,6 +317,23 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>DEFAULT_HOSTNAME=</varname></term>
<listitem><para>A string specifying the hostname if
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry> is not
present and no other configuration source specifies the hostname. Must be either a single DNS label
(a string composed of 7-bit ASCII lower-case characters and no spaces or dots, limited to the format
allowed for DNS domain name labels), or a sequence of such labels separated by single dots that forms
a valid DNS FQDN. The total length must be at most 64 characters.</para>
<para>See
<citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for a description of how
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
determines the fallback hostname.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SYSEXT_LEVEL=</varname></term>

View File

@ -31,7 +31,9 @@
<filename>/etc/systemd/system.conf.d/*.conf</filename>,
<filename>/run/systemd/system.conf.d/*.conf</filename>,
<filename>/usr/lib/systemd/system.conf.d/*.conf</filename></para>
<para><filename>/etc/systemd/user.conf</filename>,
<para><filename>~/.config/systemd/user.conf</filename>,
<filename>/etc/systemd/user.conf</filename>,
<filename>/etc/systemd/user.conf.d/*.conf</filename>,
<filename>/run/systemd/user.conf.d/*.conf</filename>,
<filename>/usr/lib/systemd/user.conf.d/*.conf</filename></para>
@ -40,16 +42,16 @@
<refsect1>
<title>Description</title>
<para>When run as a system instance, systemd interprets the
configuration file <filename>system.conf</filename> and the files
in <filename>system.conf.d</filename> directories; when run as a
user instance, systemd interprets the configuration file
<filename>user.conf</filename> and the files in
<filename>user.conf.d</filename> directories. These configuration
files contain a few settings controlling basic manager
operations. See
<citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for a general description of the syntax.</para>
<para>When run as a system instance, <command>systemd</command> interprets the configuration file
<filename>system.conf</filename> and the files in <filename>system.conf.d</filename> directories; when
run as a user instance, it interprets the configuration file <filename>user.conf</filename> (either in
the home directory of the user, or if not found, under <filename>/etc/systemd/</filename>) and the files
in <filename>user.conf.d</filename> directories. These configuration files contain a few settings
controlling basic manager operations.</para>
<para>See
<citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry> for a
general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@ -321,11 +323,10 @@
<varlistentry>
<term><varname>DefaultEnvironment=</varname></term>
<listitem><para>Sets manager environment variables passed to
all executed processes. Takes a space-separated list of
variable assignments. See
<citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details about environment variables.</para>
<listitem><para>Configures environment variables passed to all executed processes. Takes a
space-separated list of variable assignments. See <citerefentry
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
details about environment variables.</para>
<para>Example:
@ -337,6 +338,20 @@
<literal>VAR3</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ManagerEnvironment=</varname></term>
<listitem><para>Takes the same arguments as <varname>DefaultEnvironment=</varname>, see above. Sets
environment variables just for the manager process itself. These variables are not inherited by
processes spawned by the service manager, use <varname>DefaultEnvironment=</varname> for that. Note
that these variables are merged into the existing environment block. In particular, in case of the
system manager, this includes variables set by the kernel based on the kernel command line.</para>
<para>Setting environment variables for the manager process may be useful to modify its behaviour.
See <ulink url="https://systemd.io/ENVIRONMENT">ENVIRONMENT</ulink> for a descriptions of some
variables understood by <command>systemd</command>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>DefaultCPUAccounting=</varname></term>
<term><varname>DefaultBlockIOAccounting=</varname></term>

View File

@ -60,7 +60,7 @@
<filename>$XDG_RUNTIME_DIR/systemd/user.control/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/transient/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/generator.early/*</filename>
<filename>$XDG_CONFIG_HOME/systemd/user/*</filename>
<filename>~/.config/systemd/user/*</filename>
<filename>$XDG_CONFIG_DIRS/systemd/user/*</filename>
<filename>/etc/systemd/user/*</filename>
<filename>$XDG_RUNTIME_DIR/systemd/user/*</filename>
@ -1456,14 +1456,25 @@
<varlistentry>
<term><varname>ConditionControlGroupController=</varname></term>
<listitem><para>Verify that the given cgroup controller (eg. <literal>cpu</literal>) is available
for use on the system. For example, a particular controller may not be available if it was disabled
on the kernel command line with <varname>cgroup_disable=controller</varname>. Multiple controllers
may be passed with a space separating them; in this case the condition will only pass if all listed
controllers are available for use. Controllers unknown to systemd are ignored. Valid controllers
are <literal>cpu</literal>, <literal>cpuacct</literal>, <literal>io</literal>,
<literal>blkio</literal>, <literal>memory</literal>, <literal>devices</literal>, and
<literal>pids</literal>.</para>
<listitem><para>Check whether given cgroup controllers (eg. <literal>cpu</literal>) are available
for use on the system or whether the legacy v1 cgroup or the modern v2 cgroup hierarchy is used.
</para>
<para>Multiple controllers may be passed with a space separating them; in this case the condition
will only pass if all listed controllers are available for use. Controllers unknown to systemd are
ignored. Valid controllers are <literal>cpu</literal>, <literal>cpuacct</literal>,
<literal>io</literal>, <literal>blkio</literal>, <literal>memory</literal>,
<literal>devices</literal>, and <literal>pids</literal>. Even if available in the kernel, a
particular controller may not be available if it was disabled on the kernel command line with
<varname>cgroup_disable=controller</varname>.</para>
<para>Alternatively, two special strings <literal>v1</literal> and <literal>v2</literal> may be
specified (without any controller names). <literal>v2</literal> will pass if the unified v2 cgroup
hierachy is used, and <literal>v1</literal> will pass if the legacy v1 hierarchy or the hybrid
hierarchy are used (see the discussion of <varname>systemd.unified_cgroup_hierarchy</varname> and
<varname>systemd.legacy_systemd_cgroup_controller</varname> in
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information).</para>
</listitem>
</varlistentry>

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
project('systemd', 'c',
version : '247',
version : '248',
license : 'LGPLv2+',
default_options: [
'c_std=gnu99',
@ -13,7 +13,7 @@ project('systemd', 'c',
meson_version : '>= 0.46',
)
libsystemd_version = '0.30.0'
libsystemd_version = '0.31.0'
libudev_version = '1.7.0'
# We need the same data in two different formats, ugh!

View File

@ -2,21 +2,22 @@
#
# Slovak translation for systemd.
# Dušan Kazik <prescott66@gmail.com>, 2017.
#
# Frantisek Sumsal <frantisek@sumsal.cz>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
"PO-Revision-Date: 2017-06-25 11:03+0200\n"
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"PO-Revision-Date: 2021-02-22 20:21+0000\n"
"Last-Translator: Frantisek Sumsal <frantisek@sumsal.cz>\n"
"Language-Team: Slovak <https://translate.fedoraproject.org/projects/systemd/"
"master/sk/>\n"
"Language: sk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
"X-Generator: Poedit 2.0.2\n"
"X-Generator: Weblate 4.4.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@ -235,11 +236,11 @@ msgstr ""
#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr ""
msgstr "Umožnenie aplikáciám odložiť spánok systému"
#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
msgstr "Vyžaduje sa overenie totožnosti na odloženie spánku systému aplikáciou."
#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"

View File

@ -768,6 +768,21 @@ int set_unset_env(const char *name, const char *value, bool overwrite) {
return 0;
}
int putenv_dup(const char *assignment, bool override) {
const char *e, *n;
e = strchr(assignment, '=');
if (!e)
return -EINVAL;
n = strndupa(assignment, e - assignment);
/* This is like putenv(), but uses setenv() so that our memory doesn't become part of environ[]. */
if (setenv(n, e + 1, override) < 0)
return -errno;
return 0;
}
int setenv_systemd_exec_pid(bool update_only) {
char str[DECIMAL_STR_MAX(pid_t)];
const char *e;

View File

@ -58,6 +58,9 @@ int getenv_bool_secure(const char *p);
/* Like setenv, but calls unsetenv if value == NULL. */
int set_unset_env(const char *name, const char *value, bool overwrite);
/* Like putenv, but duplicates the memory like setenv. */
int putenv_dup(const char *assignment, bool override);
int setenv_systemd_exec_pid(bool update_only);
/* Parses and does sanity checks on an environment variable containing

View File

@ -3,14 +3,39 @@
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "alloc-util.h"
#include "hostname-util.h"
#include "os-util.h"
#include "string-util.h"
#include "strv.h"
char* get_default_hostname(void) {
int r;
const char *e = secure_getenv("SYSTEMD_DEFAULT_HOSTNAME");
if (e) {
if (hostname_is_valid(e, 0))
return strdup(e);
log_debug("Invalid hostname in $SYSTEMD_DEFAULT_HOSTNAME, ignoring: %s", e);
}
_cleanup_free_ char *f = NULL;
r = parse_os_release(NULL, "DEFAULT_HOSTNAME", &f);
if (r < 0)
log_debug_errno(r, "Failed to parse os-release, ignoring: %m");
else if (f) {
if (hostname_is_valid(f, 0))
return TAKE_PTR(f);
log_debug("Invalid hostname in os-release, ignoring: %s", f);
}
return strdup(FALLBACK_HOSTNAME);
}
char* gethostname_malloc(void) {
struct utsname u;
const char *s;
@ -23,7 +48,7 @@ char* gethostname_malloc(void) {
s = u.nodename;
if (isempty(s) || streq(s, "(none)"))
s = FALLBACK_HOSTNAME;
return get_default_hostname();
return strdup(s);
}
@ -31,6 +56,7 @@ char* gethostname_malloc(void) {
char* gethostname_short_malloc(void) {
struct utsname u;
const char *s;
_cleanup_free_ char *f = NULL;
/* Like above, but kills the FQDN part if present. */
@ -38,7 +64,10 @@ char* gethostname_short_malloc(void) {
s = u.nodename;
if (isempty(s) || streq(s, "(none)") || s[0] == '.') {
s = FALLBACK_HOSTNAME;
s = f = get_default_hostname();
if (!s)
return NULL;
assert(s[0] != '.');
}

View File

@ -7,6 +7,7 @@
#include "macro.h"
#include "strv.h"
char* get_default_hostname(void);
char* gethostname_malloc(void);
char* gethostname_short_malloc(void);
int gethostname_strict(char **ret);

View File

@ -376,6 +376,7 @@ static inline int __coverity_check_and_return__(int condition) {
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
#define STRV_MAKE_CONST(...) ((const char* const*) ((const char*[]) { __VA_ARGS__, NULL }))
/* Pointers range from NULL to POINTER_MAX */
#define POINTER_MAX ((void*) UINTPTR_MAX)

View File

@ -170,6 +170,8 @@ basic_sources = files('''
nulstr-util.h
ordered-set.c
ordered-set.h
os-util.c
os-util.h
parse-util.c
parse-util.h
path-lookup.c

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "discover-image.h"
#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"
@ -9,8 +8,27 @@
#include "fs-util.h"
#include "macro.h"
#include "os-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
bool image_name_is_valid(const char *s) {
if (!filename_is_valid(s))
return false;
if (string_has_cc(s, NULL))
return false;
if (!utf8_is_valid(s))
return false;
/* Temporary files for atomically creating new files */
if (startswith(s, ".#"))
return false;
return true;
}
int path_is_extension_tree(const char *path, const char *extension) {
int r;
@ -118,7 +136,7 @@ static int parse_release_internal(const char *root, const char *extension, va_li
return parse_env_filev(f, p, ap);
}
int parse_extension_release(const char *root, const char *extension, ...) {
int _parse_extension_release(const char *root, const char *extension, ...) {
va_list ap;
int r;
@ -129,7 +147,7 @@ int parse_extension_release(const char *root, const char *extension, ...) {
return r;
}
int parse_os_release(const char *root, ...) {
int _parse_os_release(const char *root, ...) {
va_list ap;
int r;
@ -193,74 +211,3 @@ int load_extension_release_pairs(const char *root, const char *extension, char *
return load_env_file_pairs(f, p, ret);
}
int extension_release_validate(
const char *name,
const char *host_os_release_id,
const char *host_os_release_version_id,
const char *host_os_release_sysext_level,
char **extension_release) {
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
assert(name);
assert(!isempty(host_os_release_id));
/* Now that we can look into the extension image, let's see if the OS version is compatible */
if (strv_isempty(extension_release)) {
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
return 0;
}
extension_release_id = strv_env_pairs_get(extension_release, "ID");
if (isempty(extension_release_id)) {
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
name, strna(host_os_release_id));
return 0;
}
if (!streq_ptr(host_os_release_id, extension_release_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
name, strna(extension_release_id), strna(host_os_release_id));
return 0;
}
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
return 1;
}
/* If the extension has a sysext API level declared, then it must match the host API
* level. Otherwise, compare OS version as a whole */
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
return 0;
}
} else if (!isempty(host_os_release_version_id)) {
const char *extension_release_version_id;
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
if (isempty(extension_release_version_id)) {
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
name, strna(host_os_release_version_id));
return 0;
}
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
name, strna(extension_release_version_id), strna(host_os_release_version_id));
return 0;
}
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
return 1;
}
log_debug("Version info of extension '%s' matches host.", name);
return 1;
}

View File

@ -6,6 +6,8 @@
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
bool image_name_is_valid(const char *s) _pure_;
int path_is_extension_tree(const char *path, const char *extension);
static inline int path_is_os_tree(const char *path) {
return path_is_extension_tree(path, NULL);
@ -21,13 +23,11 @@ static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret
return fopen_extension_release(root, NULL, ret_path, ret_file);
}
int parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
int parse_os_release(const char *root, ...) _sentinel_;
int _parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
int _parse_os_release(const char *root, ...) _sentinel_;
#define parse_extension_release(root, extension, ...) _parse_extension_release(root, extension, __VA_ARGS__, NULL)
#define parse_os_release(root, ...) _parse_os_release(root, __VA_ARGS__, NULL)
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
/* Given an image name (for logging purposes), a set of os-release values from the host
* and a key-value pair vector of extension-release variables, check that the distro and
* (system extension level or distro version) match and return 1, and 0 otherwise. */
int extension_release_validate(const char *name, const char *host_os_release_id, const char *host_os_release_version_id, const char *host_os_release_sysext_level, char **extension_release);

View File

@ -5022,20 +5022,20 @@ int config_parse_mount_images(
if (r == 0)
continue;
r = unit_full_printf(u, first, &sresolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", first);
continue;
}
s = sresolved;
s = first;
if (s[0] == '-') {
permissive = true;
s++;
}
r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
r = unit_full_printf(u, s, &sresolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", s);
continue;
}
r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
if (r < 0)
continue;
@ -5113,7 +5113,7 @@ int config_parse_mount_images(
r = mount_image_add(&c->mount_images, &c->n_mount_images,
&(MountImage) {
.source = s,
.source = sresolved,
.destination = dresolved,
.mount_options = options,
.ignore_enoent = permissive,

View File

@ -134,6 +134,7 @@ static usec_t arg_kexec_watchdog;
static char *arg_early_core_pattern;
static char *arg_watchdog_device;
static char **arg_default_environment;
static char **arg_manager_environment;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX];
static uint64_t arg_capability_bounding_set;
static bool arg_no_new_privs;
@ -163,6 +164,36 @@ static char **saved_env = NULL;
static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
const struct rlimit *saved_rlimit_memlock);
static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) {
_cleanup_free_ char *base = NULL;
_cleanup_strv_free_ char **files = NULL, **dirs = NULL;
int r;
r = xdg_user_config_dir(&base, "/systemd");
if (r < 0)
return r;
r = strv_extendf(&files, "%s/user.conf", base);
if (r < 0)
return r;
r = strv_extend(&files, PKGSYSCONFDIR "/user.conf");
if (r < 0)
return r;
r = strv_consume(&dirs, TAKE_PTR(base));
if (r < 0)
return r;
r = strv_extend_strv(&dirs, CONF_PATHS_STRV("systemd"), false);
if (r < 0)
return r;
*ret_files = TAKE_PTR(files);
*ret_dirs = TAKE_PTR(dirs);
return 0;
}
_noreturn_ static void freeze_or_exit_or_reboot(void) {
/* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to
@ -640,6 +671,7 @@ static int parse_config_file(void) {
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
{ "Manager", "ManagerEnvironment", config_parse_environ, 0, &arg_manager_environment },
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
@ -668,26 +700,34 @@ static int parse_config_file(void) {
{}
};
const char *fn, *conf_dirs_nulstr;
_cleanup_strv_free_ char **_free_files = NULL, **_free_dirs = NULL;
fn = arg_system ?
PKGSYSCONFDIR "/system.conf" :
PKGSYSCONFDIR "/user.conf";
const char *const *files, *const *dirs, *suffix;
int r;
conf_dirs_nulstr = arg_system ?
CONF_PATHS_NULSTR("systemd/system.conf.d") :
CONF_PATHS_NULSTR("systemd/user.conf.d");
if (arg_system) {
files = STRV_MAKE_CONST(PKGSYSCONFDIR "/system.conf");
dirs = (const char* const*) CONF_PATHS_STRV("systemd");
suffix = "system.conf.d";
} else {
r = manager_find_user_config_paths(&_free_files, &_free_dirs);
if (r < 0)
return log_error_errno(r, "Failed to determine config file paths: %m");
files = (const char* const*) _free_files;
dirs = (const char* const*) _free_dirs;
suffix = "user.conf.d";
}
(void) config_parse_many_nulstr(
fn, conf_dirs_nulstr,
(void) config_parse_many(
files, dirs, suffix,
"Manager\0",
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
NULL,
NULL);
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY
* like everywhere else. */
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we use
* USEC_INFINITY like everywhere else. */
if (arg_default_timeout_start_usec <= 0)
arg_default_timeout_start_usec = USEC_INFINITY;
if (arg_default_timeout_stop_usec <= 0)
@ -1312,8 +1352,7 @@ static int status_welcome(void) {
r = parse_os_release(NULL,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
"ANSI_COLOR", &ansi_color);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
@ -2263,6 +2302,19 @@ static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) {
arg_default_rlimit[RLIMIT_MEMLOCK] = rl;
}
static void setenv_manager_environment(void) {
char **p;
int r;
STRV_FOREACH(p, arg_manager_environment) {
log_debug("Setting '%s' in our own environment.", *p);
r = putenv_dup(*p, true);
if (r < 0)
log_warning_errno(errno, "Failed to setenv \"%s\", ignoring: %m", *p);
}
}
static void reset_arguments(void) {
/* Frees/resets arg_* variables, with a few exceptions commented below. */
@ -2296,6 +2348,7 @@ static void reset_arguments(void) {
arg_watchdog_device = NULL;
arg_default_environment = strv_free(arg_default_environment);
arg_manager_environment = strv_free(arg_manager_environment);
rlimit_free_all(arg_default_rlimit);
arg_capability_bounding_set = CAP_ALL;
@ -2357,6 +2410,9 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
if (arg_show_status == _SHOW_STATUS_INVALID)
arg_show_status = SHOW_STATUS_YES;
/* Push variables into the manager environment block */
setenv_manager_environment();
return 0;
}

View File

@ -106,8 +106,7 @@ static void print_welcome(void) {
r = parse_os_release(
arg_root,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
"ANSI_COLOR", &ansi_color);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");

View File

@ -159,8 +159,7 @@ static void context_read_os_release(Context *c) {
r = parse_os_release(NULL,
"PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
"HOME_URL", &c->data[PROP_OS_HOME_URL],
NULL);
"HOME_URL", &c->data[PROP_OS_HOME_URL]);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
@ -323,6 +322,7 @@ static int context_update_kernel_hostname(
Context *c,
const char *transient_hn) {
_cleanup_free_ char *_hn_free = NULL;
const char *hn;
HostnameSource hns;
int r;
@ -341,8 +341,11 @@ static int context_update_kernel_hostname(
/* ... and the ultimate fallback */
} else {
hn = FALLBACK_HOSTNAME;
hns = HOSTNAME_FALLBACK;
hn = _hn_free = get_default_hostname();
if (!hn)
return log_oom();
hns = HOSTNAME_DEFAULT;
}
r = sethostname_idempotent(hn);
@ -503,16 +506,20 @@ static int property_get_hostname(
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *current = NULL;
_cleanup_free_ char *hn = NULL;
int r;
r = gethostname_strict(&current);
if (r == -ENXIO)
return sd_bus_message_append(reply, "s", FALLBACK_HOSTNAME);
if (r < 0)
r = gethostname_strict(&hn);
if (r < 0) {
if (r != -ENXIO)
return r;
return sd_bus_message_append(reply, "s", current);
hn = get_default_hostname();
if (!hn)
return -ENOMEM;
}
return sd_bus_message_append(reply, "s", hn);
}
static int property_get_static_hostname(
@ -532,7 +539,21 @@ static int property_get_static_hostname(
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
}
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME);
static int property_get_default_hostname(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *hn = get_default_hostname();
if (!hn)
return log_oom();
return sd_bus_message_append(reply, "s", hn);
}
static int property_get_hostname_source(
sd_bus *bus,
@ -560,16 +581,16 @@ static int property_get_hostname_source(
else {
/* If the hostname was not set by us, try to figure out where it came from. If we set
* it to the fallback hostname, the file will tell us. We compare the string because
* it to the default hostname, the file will tell us. We compare the string because
* it is possible that the hostname was set by an older version that had a different
* fallback, in the initramfs or before we reexecuted. */
r = read_one_line_file("/run/systemd/fallback-hostname", &fallback);
r = read_one_line_file("/run/systemd/default-hostname", &fallback);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read /run/systemd/fallback-hostname, ignoring: %m");
log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
if (streq_ptr(fallback, hostname))
c->hostname_source = HOSTNAME_FALLBACK;
c->hostname_source = HOSTNAME_DEFAULT;
else
c->hostname_source = HOSTNAME_TRANSIENT;
}
@ -967,7 +988,7 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PROPERTY("Hostname", "s", property_get_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("FallbackHostname", "s", property_get_fallback_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultHostname", "s", property_get_default_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),

View File

@ -755,7 +755,7 @@ static int request_handler_machine(
if (r < 0)
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
(void) parse_os_release(NULL, "PRETTY_NAME", &os_name, NULL);
(void) parse_os_release(NULL, "PRETTY_NAME", &os_name);
(void) get_virtualization(&v);
r = asprintf(&json,

View File

@ -18,6 +18,7 @@
#include "loop-util.h"
#include "missing_capability.h"
#include "mount-util.h"
#include "os-util.h"
#include "process-util.h"
#include "raw-clone.h"
#include "strv.h"

View File

@ -24,6 +24,7 @@
#include "machine-pool.h"
#include "machined.h"
#include "missing_capability.h"
#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "stdio-util.h"

View File

@ -686,7 +686,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
dropin_dirname = strjoina(basename(filename), ".d");
r = config_parse_many(
filename, NETWORK_DIRS, dropin_dirname,
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
@ -729,7 +729,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
NETDEV_VTABLE(netdev)->init(netdev);
r = config_parse_many(
filename, NETWORK_DIRS, dropin_dirname,
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
NETDEV_VTABLE(netdev)->sections,
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,

View File

@ -446,7 +446,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
};
r = config_parse_many(
filename, NETWORK_DIRS, dropin_dirname,
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
"Match\0"
"Link\0"
"SR-IOV\0"

View File

@ -12,7 +12,6 @@
#include "bus-wait-for-jobs.h"
#include "def.h"
#include "dirent-util.h"
#include "discover-image.h"
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
@ -20,6 +19,7 @@
#include "fs-util.h"
#include "locale-util.h"
#include "main-func.h"
#include "os-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"

View File

@ -17,6 +17,7 @@
#include "fileio.h"
#include "io-util.h"
#include "missing_capability.h"
#include "os-util.h"
#include "portable.h"
#include "portabled-bus.h"
#include "portabled-image-bus.h"

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
"Generate %-from-name.gperf from %-list.txt"
"""Generate %-from-name.gperf from %-list.txt
"""
import sys
@ -13,12 +14,12 @@ print("""\
_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"")
#endif
%}""")
print(f"""\
struct {name}_name {{ const char* name; int id; }};
print("""\
struct {}_name {{ const char* name; int id; }};
%null-strings
%%""")
%%""".format(name))
for line in open(input):
line = line.rstrip()
s = line.replace('_', '-')
print(f'{s}, {prefix}{line}')
print("{}, {}{}".format(s, prefix, line))

View File

@ -668,7 +668,7 @@ int dns_answer_copy_by_key(
if (r < 0)
return r;
r = dns_answer_add(*a, item->rr, item->ifindex, item->flags|or_flags, item->rrsig);
r = dns_answer_add(*a, item->rr, item->ifindex, item->flags|or_flags, rrsig ?: item->rrsig);
if (r < 0)
return r;
}

View File

@ -22,6 +22,10 @@ typedef enum DnsAnswerFlags {
DNS_ANSWER_SECTION_ANSWER = 1 << 5, /* When parsing: RR originates from answer section */
DNS_ANSWER_SECTION_AUTHORITY = 1 << 6, /* When parsing: RR originates from authority section */
DNS_ANSWER_SECTION_ADDITIONAL = 1 << 7, /* When parsing: RR originates from additional section */
DNS_ANSWER_MASK_SECTIONS = DNS_ANSWER_SECTION_ANSWER|
DNS_ANSWER_SECTION_AUTHORITY|
DNS_ANSWER_SECTION_ADDITIONAL,
} DnsAnswerFlags;
struct DnsAnswerItem {

View File

@ -1140,3 +1140,10 @@ bool dns_query_fully_confidential(DnsQuery *q) {
return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) && !q->previous_redirect_non_confidential;
}
bool dns_query_fully_synthetic(DnsQuery *q) {
assert(q);
return (q->answer_query_flags & (SD_RESOLVED_SYNTHETIC | SD_RESOLVED_FROM_TRUST_ANCHOR)) &&
!(q->answer_query_flags & SD_RESOLVED_FROM_MASK & ~SD_RESOLVED_FROM_TRUST_ANCHOR);
}

View File

@ -134,6 +134,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
bool dns_query_fully_authenticated(DnsQuery *q);
bool dns_query_fully_confidential(DnsQuery *q);
bool dns_query_fully_synthetic(DnsQuery *q);
static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
assert(q);

View File

@ -1722,6 +1722,7 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
}
bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
assert(rr);
if (rr->key->class != DNS_CLASS_IN)
return false;
@ -1735,6 +1736,47 @@ bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
return false;
}
int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret) {
_cleanup_free_ char *d = NULL;
int r;
assert(key);
assert(cname);
if (key->class != cname->key->class && key->class != DNS_CLASS_ANY)
return -EUNATCH;
if (cname->key->type == DNS_TYPE_CNAME) {
r = dns_name_equal(dns_resource_key_name(key),
dns_resource_key_name(cname->key));
if (r < 0)
return r;
if (r == 0)
return -EUNATCH; /* CNAME RR key doesn't actually match the original key */
d = strdup(cname->cname.name);
if (!d)
return -ENOMEM;
} else if (cname->key->type == DNS_TYPE_DNAME) {
r = dns_name_change_suffix(
dns_resource_key_name(key),
dns_resource_key_name(cname->key),
cname->dname.name,
&d);
if (r < 0)
return r;
if (r == 0)
return -EUNATCH; /* DNAME RR key doesn't actually match the original key */
} else
return -EUNATCH; /* Not a CNAME/DNAME RR, hence doesn't match the proposition either */
*ret = TAKE_PTR(d);
return 0;
}
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
DnsTxtItem *n;

View File

@ -326,6 +326,8 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl);
bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr);
int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret);
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i);

View File

@ -883,6 +883,7 @@ int dns_scope_make_reply_packet(
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
unsigned n_answer = 0, n_soa = 0;
int r;
bool c_or_aa;
assert(s);
assert(ret);
@ -896,11 +897,14 @@ int dns_scope_make_reply_packet(
if (r < 0)
return r;
/* mDNS answers must have the Authoritative Answer bit set, see RFC 6762, section 18.4. */
c_or_aa = s->protocol == DNS_PROTOCOL_MDNS;
DNS_PACKET_HEADER(p)->id = id;
DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
1 /* qr */,
0 /* opcode */,
0 /* c */,
c_or_aa,
0 /* tc */,
tentative,
0 /* (ra) */,

View File

@ -139,12 +139,38 @@ static int stub_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
DEFINE_HASH_OPS(stub_packet_hash_ops, DnsPacket, stub_packet_hash_func, stub_packet_compare_func);
static int reply_add_with_rrsig(
DnsAnswer **reply,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags flags,
DnsResourceRecord *rrsig,
bool with_rrsig) {
int r;
assert(reply);
assert(rr);
r = dns_answer_add_extend(reply, rr, ifindex, flags, rrsig);
if (r < 0)
return r;
if (with_rrsig && rrsig) {
r = dns_answer_add_extend(reply, rrsig, ifindex, flags, NULL);
if (r < 0)
return r;
}
return 0;
}
static int dns_stub_collect_answer_by_question(
DnsAnswer **reply,
DnsAnswer *answer,
DnsQuestion *question,
bool with_rrsig) { /* Add RRSIG RR matching each RR */
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *redirected_key = NULL;
DnsAnswerItem *item;
int r;
@ -153,36 +179,71 @@ static int dns_stub_collect_answer_by_question(
/* Copies all RRs from 'answer' into 'reply', if they match 'question'. */
DNS_ANSWER_FOREACH_ITEM(item, answer) {
if (question) {
bool match = false;
r = dns_question_matches_rr(question, item->rr, NULL);
if (r < 0)
return r;
else if (r > 0)
match = true;
else {
r = dns_question_matches_cname_or_dname(question, item->rr, NULL);
if (r == 0) {
_cleanup_free_ char *target = NULL;
/* OK, so the RR doesn't directly match. Let's see if the RR is a matching
* CNAME or DNAME */
r = dns_resource_record_get_cname_target(
question->keys[0],
item->rr,
&target);
if (r == -EUNATCH)
continue; /* Not a CNAME/DNAME or doesn't match */
if (r < 0)
return r;
if (r > 0)
match = true;
dns_resource_key_unref(redirected_key);
/* There can only be one CNAME per name, hence no point in storing more than one here */
redirected_key = dns_resource_key_new(question->keys[0]->class, question->keys[0]->type, target);
if (!redirected_key)
return -ENOMEM;
}
}
if (!match)
/* Mask the section info, we want the primary answers to always go without section info, so
* that it is added to the answer section when we synthesize a reply. */
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags & ~DNS_ANSWER_MASK_SECTIONS,
item->rrsig,
with_rrsig);
if (r < 0)
return r;
}
if (!redirected_key)
return 0;
/* This is a CNAME/DNAME answer. In this case also append where the redirections point to to the main
* answer section */
DNS_ANSWER_FOREACH_ITEM(item, answer) {
r = dns_resource_key_match_rr(redirected_key, item->rr, NULL);
if (r < 0)
return r;
if (r == 0)
continue;
}
r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags & ~DNS_ANSWER_MASK_SECTIONS,
item->rrsig,
with_rrsig);
if (r < 0)
return r;
if (with_rrsig && item->rrsig) {
r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
if (r < 0)
return r;
}
}
return 0;
@ -197,7 +258,6 @@ static int dns_stub_collect_answer_by_section(
bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
DnsAnswerItem *item;
unsigned c = 0;
int r;
assert(reply);
@ -218,22 +278,18 @@ static int dns_stub_collect_answer_by_section(
if (((item->flags ^ section) & (DNS_ANSWER_SECTION_ANSWER|DNS_ANSWER_SECTION_AUTHORITY|DNS_ANSWER_SECTION_ADDITIONAL)) != 0)
continue;
r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags,
item->rrsig,
with_dnssec);
if (r < 0)
return r;
c++;
if (with_dnssec && item->rrsig) {
r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
if (r < 0)
return r;
c++;
}
}
return (int) c;
return 0;
}
static int dns_stub_assign_sections(
@ -246,17 +302,17 @@ static int dns_stub_assign_sections(
assert(q);
assert(question);
/* Let's assign the 'answer' and 'answer_auxiliary' RRs we collected to their respective sections in
* the reply datagram. We try to reproduce a section assignment similar to what the upstream DNS
* server responded to us. We use the DNS_ANSWER_SECTION_xyz flags to match things up, which is where
* the original upstream's packet section assignment is stored in the DnsAnswer object. Not all RRs
* in the 'answer' and 'answer_auxiliary' objects come with section information though (for example,
* because they were synthesized locally, and not from a DNS packet). To deal with that we extend the
* assignment logic a bit: anything from the 'answer' object that directly matches the original
* question is always put in the ANSWER section, regardless if it carries section info, or what that
* section info says. Then, anything from the 'answer' and 'answer_auxiliary' objects that is from
* the ANSWER or AUTHORITY sections, and wasn't already added to the ANSWER section is placed in the
* AUTHORITY section. Everything else from either object is added to the ADDITIONAL section. */
/* Let's assign the 'answer' RRs we collected to their respective sections in the reply datagram. We
* try to reproduce a section assignment similar to what the upstream DNS server responded to us. We
* use the DNS_ANSWER_SECTION_xyz flags to match things up, which is where the original upstream's
* packet section assignment is stored in the DnsAnswer object. Not all RRs in the 'answer' objects
* come with section information though (for example, because they were synthesized locally, and not
* from a DNS packet). To deal with that we extend the assignment logic a bit: anything from the
* 'answer' object that directly matches the original question is always put in the ANSWER section,
* regardless if it carries section info, or what that section info says. Then, anything from the
* 'answer' objects that is from the ANSWER or AUTHORITY sections, and wasn't already added to the
* ANSWER section is placed in the AUTHORITY section. Everything else from either object is added to
* the ADDITIONAL section. */
/* Include all RRs that directly answer the question in the answer section */
r = dns_stub_collect_answer_by_question(
@ -277,9 +333,6 @@ static int dns_stub_assign_sections(
edns0_do);
if (r < 0)
return r;
/* Include all RRs that originate from the answer or authority sections, and aren't listed in the
* answer section, in the authority section */
r = dns_stub_collect_answer_by_section(
&q->reply_authoritative,
q->answer,
@ -428,6 +481,7 @@ static int dns_stub_finish_reply_packet(
uint16_t id,
int rcode,
bool tc, /* set the Truncated bit? */
bool aa, /* set the Authoritative Answer bit? */
bool add_opt, /* add an OPT RR to this packet? */
bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */
bool ad, /* set the DNSSEC authenticated data bit? */
@ -466,7 +520,7 @@ static int dns_stub_finish_reply_packet(
DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
1 /* qr */,
0 /* opcode */,
0 /* aa */,
aa /* aa */,
tc /* tc */,
1 /* rd */,
1 /* ra */,
@ -556,6 +610,7 @@ static int dns_stub_send_reply(
DNS_PACKET_ID(q->request_packet),
rcode,
truncated,
dns_query_fully_synthetic(q),
!!q->request_packet->opt,
edns0_do,
DNS_PACKET_AD(q->request_packet) && dns_query_fully_authenticated(q),
@ -596,6 +651,7 @@ static int dns_stub_send_failure(
DNS_PACKET_ID(p),
rcode,
truncated,
false,
!!p->opt,
DNS_PACKET_DO(p),
DNS_PACKET_AD(p) && authenticated,
@ -681,27 +737,13 @@ static void dns_stub_query_complete(DnsQuery *q) {
}
}
/* Note that we don't bother with following CNAMEs here. We propagate the authoritative/additional
* sections from the upstream answer however, hence if the upstream server collected that information
* already we don't have to collect it ourselves anymore. */
switch (q->state) {
case DNS_TRANSACTION_SUCCESS:
/* Follow CNAMEs, and accumulate answers. Except if DNSSEC is requested, then let the client do that. */
if (!DNS_PACKET_DO(q->request_packet)) {
r = dns_query_process_cname(q);
if (r == -ELOOP) { /* CNAME loop */
(void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
break;
}
if (r < 0) {
log_debug_errno(r, "Failed to process CNAME: %m");
break;
}
if (r == DNS_QUERY_RESTARTED)
return;
}
(void) dns_stub_send_reply(q, q->answer_rcode);
break;
case DNS_TRANSACTION_RCODE_FAILURE:
(void) dns_stub_send_reply(q, q->answer_rcode);
break;
@ -840,7 +882,8 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
r = dns_query_new(m, &q, p->question, p->question, NULL, 0,
SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_SEARCH|
(DNS_PACKET_DO(p) ? SD_RESOLVED_NO_CNAME|SD_RESOLVED_REQUIRE_PRIMARY : 0)|
SD_RESOLVED_NO_CNAME|
(DNS_PACKET_DO(p) ? SD_RESOLVED_REQUIRE_PRIMARY : 0)|
SD_RESOLVED_CLAMP_TTL);
if (r < 0) {
log_error_errno(r, "Failed to generate query object: %m");

View File

@ -88,7 +88,7 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
dropin_dirname = strjoina(service->name, ".dnssd.d");
r = config_parse_many(
filename, DNSSD_SERVICE_DIRS, dropin_dirname,
STRV_MAKE_CONST(filename), DNSSD_SERVICE_DIRS, dropin_dirname,
"Service\0",
config_item_perf_lookup, resolved_dnssd_gperf_lookup,
CONFIG_PARSE_WARN,

View File

@ -442,20 +442,25 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
return 0;
}
static const char *fallback_hostname(void) {
static char* fallback_hostname(void) {
/* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be
* "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */
/* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it
* to be "localhost" even if that's the default hostname. In this case, let's revert to "linux"
* instead. */
if (is_localhost(FALLBACK_HOSTNAME))
return "linux";
_cleanup_free_ char *n = get_default_hostname();
if (!n)
return NULL;
return FALLBACK_HOSTNAME;
if (is_localhost(n))
return strdup("linux");
return TAKE_PTR(n);
}
static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
_cleanup_free_ char *n = NULL, *m = NULL;
char label[DNS_LABEL_MAX], *h;
_cleanup_free_ char *h = NULL, *n = NULL, *m = NULL;
char label[DNS_LABEL_MAX];
const char *p;
int r;
@ -463,7 +468,10 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname,
assert(llmnr_hostname);
assert(mdns_hostname);
p = fallback_hostname();
p = h = fallback_hostname();
if (!h)
return log_oom();
r = dns_label_unescape(&p, label, sizeof label, 0);
if (r < 0)
return log_error_errno(r, "Failed to unescape fallback hostname: %m");
@ -478,14 +486,9 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname,
if (r < 0)
return log_error_errno(r, "Failed to concatenate mDNS hostname: %m");
h = strdup(fallback_hostname());
if (!h)
return log_oom();
*llmnr_hostname = TAKE_PTR(n);
*mdns_hostname = TAKE_PTR(m);
*full_hostname = h;
*full_hostname = TAKE_PTR(h);
return 0;
}

View File

@ -90,8 +90,41 @@ static void test_packet_from_file(const char* filename, bool canonical) {
}
}
static void test_dns_resource_record_get_cname_target(void) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *dname = NULL;
_cleanup_free_ char *target = NULL;
assert_se(cname = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_CNAME, "quux.foobar"));
assert_se(cname->cname.name = strdup("wuff.wuff"));
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "waldo"), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "foobar"), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux"), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, ""), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "."), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "nope.quux.foobar"), cname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux.foobar"), cname, &target) == 0);
assert_se(streq(target, "wuff.wuff"));
target = mfree(target);
assert_se(dname = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNAME, "quux.foobar"));
assert_se(dname->dname.name = strdup("wuff.wuff"));
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "waldo"), dname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "foobar"), dname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux"), dname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, ""), dname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "."), dname, &target) == -EUNATCH);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "yupp.quux.foobar"), dname, &target) == 0);
assert_se(streq(target, "yupp.wuff.wuff"));
target = mfree(target);
assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux.foobar"), cname, &target) == 0);
assert_se(streq(target, "wuff.wuff"));
}
int main(int argc, char **argv) {
int i, N;
int N;
_cleanup_globfree_ glob_t g = {};
char **fnames;
@ -108,7 +141,7 @@ int main(int argc, char **argv) {
fnames = g.gl_pathv;
}
for (i = 0; i < N; i++) {
for (int i = 0; i < N; i++) {
test_packet_from_file(fnames[i], false);
puts("");
test_packet_from_file(fnames[i], true);
@ -116,5 +149,7 @@ int main(int argc, char **argv) {
puts("");
}
test_dns_resource_record_get_cname_target();
return EXIT_SUCCESS;
}

View File

@ -354,6 +354,15 @@ static int condition_test_control_group_controller(Condition *c, char **env) {
assert(c->parameter);
assert(c->type == CONDITION_CONTROL_GROUP_CONTROLLER);
if (streq(c->parameter, "v2"))
return cg_all_unified();
if (streq(c->parameter, "v1")) {
r = cg_all_unified();
if (r < 0)
return r;
return !r;
}
r = cg_mask_supported(&system_mask);
if (r < 0)
return log_debug_errno(r, "Failed to determine supported controllers: %m");

View File

@ -420,11 +420,11 @@ int config_parse(
if (ret_mtime)
*ret_mtime = mtime;
return 0;
return 1;
}
static int config_parse_many_files(
const char *conf_file,
const char* const* conf_files,
char **files,
const char *sections,
ConfigItemLookup lookup,
@ -437,20 +437,23 @@ static int config_parse_many_files(
char **fn;
int r;
if (conf_file) {
r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata, &mtime);
/* First read the first found main config file. */
STRV_FOREACH(fn, (char**) conf_files) {
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &mtime);
if (r < 0)
return r;
if (r > 0)
break;
}
/* Then read all the drop-ins. */
STRV_FOREACH(fn, files) {
usec_t t;
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &t);
if (r < 0)
return r;
if (t > mtime) /* Find the newest */
mtime = t;
mtime = MAX(mtime, t); /* Find the newest */
}
if (ret_mtime)
@ -477,12 +480,14 @@ int config_parse_many_nulstr(
if (r < 0)
return r;
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
return config_parse_many_files(STRV_MAKE_CONST(conf_file),
files, sections, lookup, table, flags, userdata,
ret_mtime);
}
/* Parse each config file in the directories specified as strv. */
int config_parse_many(
const char *conf_file,
const char* const* conf_files,
const char* const* conf_file_dirs,
const char *dropin_dirname,
const char *sections,
@ -506,7 +511,7 @@ int config_parse_many(
if (r < 0)
return r;
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_mtime);
}
#define DEFINE_PARSER(type, vartype, conv_func) \

View File

@ -102,7 +102,7 @@ int config_parse_many_nulstr(
usec_t *ret_mtime); /* possibly NULL */
int config_parse_many(
const char *conf_file, /* possibly NULL */
const char* const* conf_files, /* possibly empty */
const char* const* conf_file_dirs,
const char *dropin_dirname,
const char *sections, /* nulstr */

View File

@ -1250,23 +1250,6 @@ int image_name_lock(const char *name, int operation, LockFile *ret) {
return make_lock_file(p, operation, ret);
}
bool image_name_is_valid(const char *s) {
if (!filename_is_valid(s))
return false;
if (string_has_cc(s, NULL))
return false;
if (!utf8_is_valid(s))
return false;
/* Temporary files for atomically creating new files */
if (startswith(s, ".#"))
return false;
return true;
}
bool image_in_search_path(
ImageClass class,
const char *root,

View File

@ -76,8 +76,6 @@ int image_read_only(Image *i, bool b);
const char* image_type_to_string(ImageType t) _const_;
ImageType image_type_from_string(const char *s) _pure_;
bool image_name_is_valid(const char *s) _pure_;
int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
int image_name_lock(const char *name, int operation, LockFile *ret);

View File

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "env-util.h"
#include "extension-release.h"
#include "log.h"
#include "os-util.h"
#include "strv.h"
int extension_release_validate(
const char *name,
const char *host_os_release_id,
const char *host_os_release_version_id,
const char *host_os_release_sysext_level,
char **extension_release) {
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
assert(name);
assert(!isempty(host_os_release_id));
/* Now that we can look into the extension image, let's see if the OS version is compatible */
if (strv_isempty(extension_release)) {
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
return 0;
}
extension_release_id = strv_env_pairs_get(extension_release, "ID");
if (isempty(extension_release_id)) {
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
name, strna(host_os_release_id));
return 0;
}
if (!streq_ptr(host_os_release_id, extension_release_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
name, strna(extension_release_id), strna(host_os_release_id));
return 0;
}
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
return 1;
}
/* If the extension has a sysext API level declared, then it must match the host API
* level. Otherwise, compare OS version as a whole */
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
return 0;
}
} else if (!isempty(host_os_release_version_id)) {
const char *extension_release_version_id;
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
if (isempty(extension_release_version_id)) {
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
name, strna(host_os_release_version_id));
return 0;
}
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
name, strna(extension_release_version_id), strna(host_os_release_version_id));
return 0;
}
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
return 1;
}
log_debug("Version info of extension '%s' matches host.", name);
return 1;
}

View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* Given an image name (for logging purposes), a set of os-release values from the host and a key-value pair
* vector of extension-release variables, check that the distro and (system extension level or distro
* version) match and return 1, and 0 otherwise. */
int extension_release_validate(
const char *name,
const char *host_os_release_id,
const char *host_os_release_version_id,
const char *host_os_release_sysext_level,
char **extension_release);

View File

@ -152,13 +152,13 @@ void hostname_update_source_hint(const char *hostname, HostnameSource source) {
* notice if somebody sets the hostname directly (not going through hostnamed).
*/
if (source == HOSTNAME_FALLBACK) {
r = write_string_file("/run/systemd/fallback-hostname", hostname,
if (source == HOSTNAME_DEFAULT) {
r = write_string_file("/run/systemd/default-hostname", hostname,
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
if (r < 0)
log_warning_errno(r, "Failed to create \"/run/systemd/fallback-hostname\": %m");
log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\": %m");
} else
unlink_or_warn("/run/systemd/fallback-hostname");
unlink_or_warn("/run/systemd/default-hostname");
}
int hostname_setup(bool really) {
@ -194,7 +194,7 @@ int hostname_setup(bool really) {
}
}
if (isempty(hn)) {
if (!hn) {
/* Don't override the hostname if it is already set and not explicitly configured */
char buf[HOST_NAME_MAX + 1] = {};
@ -204,10 +204,13 @@ int hostname_setup(bool really) {
}
if (enoent)
log_info("No hostname configured, using fallback hostname.");
log_info("No hostname configured, using default hostname.");
hn = FALLBACK_HOSTNAME;
source = HOSTNAME_FALLBACK;
hn = b = get_default_hostname();
if (!hn)
return log_oom();
source = HOSTNAME_DEFAULT;
}
@ -230,7 +233,7 @@ int hostname_setup(bool really) {
static const char* const hostname_source_table[] = {
[HOSTNAME_STATIC] = "static",
[HOSTNAME_TRANSIENT] = "transient",
[HOSTNAME_FALLBACK] = "fallback",
[HOSTNAME_DEFAULT] = "default",
};
DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);

View File

@ -7,7 +7,7 @@
typedef enum HostnameSource {
HOSTNAME_STATIC, /* from /etc/hostname */
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
HOSTNAME_DEFAULT, /* the os-release default or the compiled-in fallback were used */
_HOSTNAME_INVALID = -EINVAL,
} HostnameSource;

View File

@ -100,6 +100,8 @@ shared_sources = files('''
exec-util.h
exit-status.c
exit-status.h
extension-release.c
extension-release.h
fdset.c
fdset.h
fileio-label.c
@ -196,8 +198,6 @@ shared_sources = files('''
numa-util.h
openssl-util.c
openssl-util.h
os-util.c
os-util.h
output-mode.c
output-mode.h
pager.c

View File

@ -203,7 +203,7 @@ static int specifier_os_release_common(const char *field, char **ret) {
char *t = NULL;
int r;
r = parse_os_release(NULL, field, &t, NULL);
r = parse_os_release(NULL, field, &t);
if (r < 0)
return r;
if (!t) {

View File

@ -10,6 +10,7 @@
#include "dissect-image.h"
#include "env-util.h"
#include "escape.h"
#include "extension-release.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-table.h"
@ -472,8 +473,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
arg_root,
"ID", &host_os_release_id,
"VERSION_ID", &host_os_release_version_id,
"SYSEXT_LEVEL", &host_os_release_sysext_level,
NULL);
"SYSEXT_LEVEL", &host_os_release_sysext_level);
if (r < 0)
return log_error_errno(r, "Failed to acquire 'os-release' data of OS tree '%s': %m", empty_to_root(arg_root));

View File

@ -18,9 +18,9 @@ for line in open(sys.argv[1]):
if match:
s = match.group(1)
if s == 'sd_bus_object_vtable_format':
print(f' &{s},')
print(' &{},'.format(s))
else:
print(f' {s},')
print(' {},'.format(s))
print('''};

View File

@ -124,10 +124,26 @@ static void test_condition_test_path(void) {
condition_free(condition);
}
static void test_condition_test_control_group_hierarchy(void) {
Condition *condition;
int r;
r = cg_unified();
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "v1", false, false);
assert_se(condition);
assert_se(condition_test(condition, environ) == (r < CGROUP_UNIFIED_ALL));
condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "v2", false, false);
assert_se(condition);
assert_se(condition_test(condition, environ) == (r >= CGROUP_UNIFIED_ALL));
condition_free(condition);
}
static void test_condition_test_control_group_controller(void) {
Condition *condition;
CGroupMask system_mask;
CGroupController controller;
_cleanup_free_ char *controller_name = NULL;
int r;
@ -151,7 +167,7 @@ static void test_condition_test_control_group_controller(void) {
assert_se(cg_mask_supported(&system_mask) >= 0);
/* Individual valid controllers one by one */
for (controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) {
for (CGroupController controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) {
const char *local_controller_name = cgroup_controller_to_string(controller);
log_info("chosen controller is '%s'", local_controller_name);
if (system_mask & CGROUP_CONTROLLER_TO_MASK(controller)) {
@ -881,6 +897,7 @@ int main(int argc, char *argv[]) {
test_condition_test_virtualization();
test_condition_test_user();
test_condition_test_group();
test_condition_test_control_group_hierarchy();
test_condition_test_control_group_controller();
test_condition_test_cpus();
test_condition_test_memory();

View File

@ -349,27 +349,27 @@ static void test_config_parse(unsigned i, const char *s) {
switch (i) {
case 0 ... 4:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, "1"));
break;
case 5 ... 10:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, "1 2 3"));
break;
case 11:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, "1\\\\ \\\\2"));
break;
case 12:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, x1000("ABCD")));
break;
case 13 ... 14:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, x1000("ABCD") " foobar"));
break;
@ -379,7 +379,7 @@ static void test_config_parse(unsigned i, const char *s) {
break;
case 17:
assert_se(r == 0);
assert_se(r == 1);
assert_se(streq(setting1, "2"));
break;
}

View File

@ -361,6 +361,19 @@ static void test_env_assignment_is_valid(void) {
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
}
static void test_putenv_dup(void) {
log_info("/* %s */", __func__);
assert_se(putenv_dup("A=a1", true) == 0);
assert_se(streq(getenv("A"), "a1"));
assert_se(putenv_dup("A=a1", true) == 0);
assert_se(streq(getenv("A"), "a1"));
assert_se(putenv_dup("A=a2", false) == 0);
assert_se(streq(getenv("A"), "a1"));
assert_se(putenv_dup("A=a2", true) == 0);
assert_se(streq(getenv("A"), "a2"));
}
static void test_setenv_systemd_exec_pid(void) {
_cleanup_free_ char *saved = NULL;
const char *e;
@ -416,6 +429,7 @@ int main(int argc, char *argv[]) {
test_env_name_is_valid();
test_env_value_is_valid();
test_env_assignment_is_valid();
test_putenv_dup();
test_setenv_systemd_exec_pid();
return 0;

View File

@ -10,6 +10,8 @@
#include "tmpfile-util.h"
static void test_hostname_is_valid(void) {
log_info("/* %s */", __func__);
assert_se(hostname_is_valid("foobar", 0));
assert_se(hostname_is_valid("foobar.com", 0));
assert_se(!hostname_is_valid("foobar.com.", 0));
@ -49,6 +51,8 @@ static void test_hostname_is_valid(void) {
static void test_hostname_cleanup(void) {
char *s;
log_info("/* %s */", __func__);
s = strdupa("foobar");
assert_se(streq(hostname_cleanup(s), "foobar"));
s = strdupa("foobar.com");
@ -94,6 +98,8 @@ static void test_hostname_cleanup(void) {
static void test_hostname_malloc(void) {
_cleanup_free_ char *h = NULL, *l = NULL;
log_info("/* %s */", __func__);
assert_se(h = gethostname_malloc());
log_info("hostname_malloc: \"%s\"", h);
@ -101,21 +107,27 @@ static void test_hostname_malloc(void) {
log_info("hostname_short_malloc: \"%s\"", l);
}
static void test_fallback_hostname(void) {
static void test_default_hostname(void) {
log_info("/* %s */", __func__);
if (!hostname_is_valid(FALLBACK_HOSTNAME, 0)) {
log_error("Configured fallback hostname \"%s\" is not valid.", FALLBACK_HOSTNAME);
exit(EXIT_FAILURE);
}
_cleanup_free_ char *n = get_default_hostname();
assert_se(n);
log_info("get_default_hostname: \"%s\"", n);
assert_se(hostname_is_valid(n, 0));
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_setup_logging(LOG_DEBUG);
test_hostname_is_valid();
test_hostname_cleanup();
test_hostname_malloc();
test_fallback_hostname();
test_default_hostname();
return 0;
}